The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/vesa.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1998 Kazutaka YOKOTA and Michael Smith
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer as
   10  *    the first lines of this file unmodified.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/5.1/sys/i386/isa/vesa.c 113130 2003-04-05 18:08:22Z cognet $
   27  */
   28 
   29 #include "opt_vga.h"
   30 #include "opt_vesa.h"
   31 
   32 #ifndef VGA_NO_MODE_CHANGE
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/malloc.h>
   39 #include <sys/fbio.h>
   40 
   41 #include <vm/vm.h>
   42 #include <vm/vm_extern.h>
   43 #include <vm/vm_kern.h>
   44 #include <vm/pmap.h>
   45 
   46 #include <machine/md_var.h>
   47 #include <machine/vm86.h>
   48 #include <machine/pc/bios.h>
   49 #include <machine/pc/vesa.h>
   50 
   51 #include <dev/fb/fbreg.h>
   52 #include <dev/fb/vgareg.h>
   53 
   54 #ifndef __i386__
   55 #include <isa/isareg.h>
   56 #else
   57 #include <i386/isa/isa.h>
   58 #endif
   59 
   60 #ifndef VESA_DEBUG
   61 #define VESA_DEBUG      0
   62 #endif
   63 
   64 /* VESA video adapter state buffer stub */
   65 struct adp_state {
   66         int             sig;
   67 #define V_STATE_SIG     0x61736576
   68         u_char          regs[1];
   69 };
   70 typedef struct adp_state adp_state_t;
   71 
   72 /* VESA video adapter */
   73 static video_adapter_t *vesa_adp = NULL;
   74 static int vesa_state_buf_size = 0;
   75 
   76 /* VESA functions */
   77 #if 0
   78 static int                      vesa_nop(void);
   79 #endif
   80 static int                      vesa_error(void);
   81 static vi_probe_t               vesa_probe;
   82 static vi_init_t                vesa_init;
   83 static vi_get_info_t            vesa_get_info;
   84 static vi_query_mode_t          vesa_query_mode;
   85 static vi_set_mode_t            vesa_set_mode;
   86 static vi_save_font_t           vesa_save_font;
   87 static vi_load_font_t           vesa_load_font;
   88 static vi_show_font_t           vesa_show_font;
   89 static vi_save_palette_t        vesa_save_palette;
   90 static vi_load_palette_t        vesa_load_palette;
   91 static vi_set_border_t          vesa_set_border;
   92 static vi_save_state_t          vesa_save_state;
   93 static vi_load_state_t          vesa_load_state;
   94 static vi_set_win_org_t         vesa_set_origin;
   95 static vi_read_hw_cursor_t      vesa_read_hw_cursor;
   96 static vi_set_hw_cursor_t       vesa_set_hw_cursor;
   97 static vi_set_hw_cursor_shape_t vesa_set_hw_cursor_shape;
   98 static vi_blank_display_t       vesa_blank_display;
   99 static vi_mmap_t                vesa_mmap;
  100 static vi_ioctl_t               vesa_ioctl;
  101 static vi_clear_t               vesa_clear;
  102 static vi_fill_rect_t           vesa_fill_rect;
  103 static vi_bitblt_t              vesa_bitblt;
  104 static vi_diag_t                vesa_diag;
  105 static int                      vesa_bios_info(int level);
  106 static struct vm86context       vesa_vmcontext;
  107 
  108 static video_switch_t vesavidsw = {
  109         vesa_probe,
  110         vesa_init,
  111         vesa_get_info,
  112         vesa_query_mode,
  113         vesa_set_mode,
  114         vesa_save_font,
  115         vesa_load_font,
  116         vesa_show_font,
  117         vesa_save_palette,
  118         vesa_load_palette,
  119         vesa_set_border,
  120         vesa_save_state,
  121         vesa_load_state,
  122         vesa_set_origin,
  123         vesa_read_hw_cursor,
  124         vesa_set_hw_cursor,
  125         vesa_set_hw_cursor_shape,
  126         vesa_blank_display,
  127         vesa_mmap,
  128         vesa_ioctl,
  129         vesa_clear,
  130         vesa_fill_rect,
  131         vesa_bitblt,
  132         vesa_error,
  133         vesa_error,
  134         vesa_diag,
  135 };
  136 
  137 static video_switch_t *prevvidsw;
  138 
  139 /* VESA BIOS video modes */
  140 #define VESA_MAXMODES   64
  141 #define EOT             (-1)
  142 #define NA              (-2)
  143 
  144 #define MODE_TABLE_DELTA 8
  145 
  146 static int vesa_vmode_max = 0;
  147 static video_info_t vesa_vmode_empty = { EOT };
  148 static video_info_t *vesa_vmode = &vesa_vmode_empty;
  149 
  150 static int vesa_init_done = FALSE;
  151 static int has_vesa_bios = FALSE;
  152 static struct vesa_info *vesa_adp_info = NULL;
  153 static u_int16_t *vesa_vmodetab = NULL;
  154 static char *vesa_oemstr = NULL;
  155 static char *vesa_venderstr = NULL;
  156 static char *vesa_prodstr = NULL;
  157 static char *vesa_revstr = NULL;
  158 
  159 /* local macros and functions */
  160 #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
  161 
  162 static int int10_set_mode(int mode);
  163 static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode);
  164 static int vesa_bios_set_mode(int mode);
  165 static int vesa_bios_get_dac(void);
  166 static int vesa_bios_set_dac(int bits);
  167 static int vesa_bios_save_palette(int start, int colors, u_char *palette,
  168                                   int bits);
  169 static int vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g,
  170                                    u_char *b, int bits);
  171 static int vesa_bios_load_palette(int start, int colors, u_char *palette,
  172                                   int bits);
  173 #ifdef notyet
  174 static int vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g,
  175                                    u_char *b, int bits);
  176 #endif
  177 #define STATE_SIZE      0
  178 #define STATE_SAVE      1
  179 #define STATE_LOAD      2
  180 #define STATE_HW        (1<<0)
  181 #define STATE_DATA      (1<<1)
  182 #define STATE_DAC       (1<<2)
  183 #define STATE_REG       (1<<3)
  184 #define STATE_MOST      (STATE_HW | STATE_DATA | STATE_REG)
  185 #define STATE_ALL       (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
  186 static int vesa_bios_state_buf_size(void);
  187 static int vesa_bios_save_restore(int code, void *p, size_t size);
  188 static int vesa_bios_get_line_length(void);
  189 static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines);
  190 #if 0
  191 static int vesa_bios_get_start(int *x, int *y);
  192 #endif
  193 static int vesa_bios_set_start(int x, int y);
  194 static int vesa_map_gen_mode_num(int type, int color, int mode);
  195 static int vesa_translate_flags(u_int16_t vflags);
  196 static int vesa_translate_mmodel(u_int8_t vmodel);
  197 static void *vesa_fix_ptr(u_int32_t p, u_int16_t seg, u_int16_t off, 
  198                           u_char *buf);
  199 static int vesa_bios_init(void);
  200 static void vesa_clear_modes(video_info_t *info, int color);
  201 static vm_offset_t vesa_map_buffer(u_int paddr, size_t size);
  202 static void vesa_unmap_buffer(vm_offset_t vaddr, size_t size);
  203 
  204 #if 0
  205 static int vesa_get_origin(video_adapter_t *adp, off_t *offset);
  206 #endif
  207 
  208 static void
  209 dump_buffer(u_char *buf, size_t len)
  210 {
  211     int i;
  212 
  213     for(i = 0; i < len;) {
  214         printf("%02x ", buf[i]);
  215         if ((++i % 16) == 0)
  216             printf("\n");
  217     }
  218 }
  219 
  220 /* INT 10 BIOS calls */
  221 static int
  222 int10_set_mode(int mode)
  223 {
  224         struct vm86frame vmf;
  225 
  226         bzero(&vmf, sizeof(vmf));
  227         vmf.vmf_eax = 0x0000 | mode;
  228         vm86_intcall(0x10, &vmf);
  229         return 0;
  230 }
  231 
  232 /* VESA BIOS calls */
  233 static int
  234 vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
  235 {
  236         struct vm86frame vmf;
  237         u_char *buf;
  238         int err;
  239 
  240         bzero(&vmf, sizeof(vmf));
  241         vmf.vmf_eax = 0x4f01; 
  242         vmf.vmf_ecx = mode;
  243         buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  244         vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_di);
  245 
  246         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  247         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  248                 return 1;
  249         bcopy(buf, vmode, sizeof(*vmode));
  250         return 0;
  251 }
  252 
  253 static int
  254 vesa_bios_set_mode(int mode)
  255 {
  256         struct vm86frame vmf;
  257         int err;
  258 
  259         bzero(&vmf, sizeof(vmf));
  260         vmf.vmf_eax = 0x4f02;
  261         vmf.vmf_ebx = mode;
  262         err = vm86_intcall(0x10, &vmf);
  263         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  264 }
  265 
  266 static int
  267 vesa_bios_get_dac(void)
  268 {
  269         struct vm86frame vmf;
  270         int err;
  271 
  272         bzero(&vmf, sizeof(vmf));
  273         vmf.vmf_eax = 0x4f08;
  274         vmf.vmf_ebx = 1;        /* get DAC width */
  275         err = vm86_intcall(0x10, &vmf);
  276         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  277                 return 6;       /* XXX */
  278         return ((vmf.vmf_ebx >> 8) & 0x00ff);
  279 }
  280 
  281 static int
  282 vesa_bios_set_dac(int bits)
  283 {
  284         struct vm86frame vmf;
  285         int err;
  286 
  287         bzero(&vmf, sizeof(vmf));
  288         vmf.vmf_eax = 0x4f08;
  289         vmf.vmf_ebx = (bits << 8);
  290         err = vm86_intcall(0x10, &vmf);
  291         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  292                 return 6;       /* XXX */
  293         return ((vmf.vmf_ebx >> 8) & 0x00ff);
  294 }
  295 
  296 static int
  297 vesa_bios_save_palette(int start, int colors, u_char *palette, int bits)
  298 {
  299         struct vm86frame vmf;
  300         u_char *p;
  301         int err;
  302         int i;
  303 
  304         bzero(&vmf, sizeof(vmf));
  305         vmf.vmf_eax = 0x4f09;
  306         vmf.vmf_ebx = 1;        /* get primary palette data */
  307         vmf.vmf_ecx = colors;
  308         vmf.vmf_edx = start;
  309         p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  310         vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);
  311 
  312         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  313         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  314                 return 1;
  315 
  316         bits = 8 - bits;
  317         for (i = 0; i < colors; ++i) {
  318                 palette[i*3]     = p[i*4 + 2] << bits;
  319                 palette[i*3 + 1] = p[i*4 + 1] << bits;
  320                 palette[i*3 + 2] = p[i*4] << bits;
  321         }
  322         return 0;
  323 }
  324 
  325 static int
  326 vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b,
  327                         int bits)
  328 {
  329         struct vm86frame vmf;
  330         u_char *p;
  331         int err;
  332         int i;
  333 
  334         bzero(&vmf, sizeof(vmf));
  335         vmf.vmf_eax = 0x4f09;
  336         vmf.vmf_ebx = 1;        /* get primary palette data */
  337         vmf.vmf_ecx = colors;
  338         vmf.vmf_edx = start;
  339         p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  340         vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);
  341 
  342         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  343         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  344                 return 1;
  345 
  346         bits = 8 - bits;
  347         for (i = 0; i < colors; ++i) {
  348                 r[i] = p[i*4 + 2] << bits;
  349                 g[i] = p[i*4 + 1] << bits;
  350                 b[i] = p[i*4] << bits;
  351         }
  352         return 0;
  353 }
  354 
  355 static int
  356 vesa_bios_load_palette(int start, int colors, u_char *palette, int bits)
  357 {
  358         struct vm86frame vmf;
  359         u_char *p;
  360         int err;
  361         int i;
  362 
  363         p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  364         bits = 8 - bits;
  365         for (i = 0; i < colors; ++i) {
  366                 p[i*4]     = palette[i*3 + 2] >> bits;
  367                 p[i*4 + 1] = palette[i*3 + 1] >> bits;
  368                 p[i*4 + 2] = palette[i*3] >> bits;
  369                 p[i*4 + 3] = 0;
  370         }
  371 
  372         bzero(&vmf, sizeof(vmf));
  373         vmf.vmf_eax = 0x4f09;
  374         vmf.vmf_ebx = 0;        /* set primary palette data */
  375         vmf.vmf_ecx = colors;
  376         vmf.vmf_edx = start;
  377         vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);
  378 
  379         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  380         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  381 }
  382 
  383 #ifdef notyet
  384 static int
  385 vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b,
  386                         int bits)
  387 {
  388         struct vm86frame vmf;
  389         u_char *p;
  390         int err;
  391         int i;
  392 
  393         p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  394         bits = 8 - bits;
  395         for (i = 0; i < colors; ++i) {
  396                 p[i*4]     = b[i] >> bits;
  397                 p[i*4 + 1] = g[i] >> bits;
  398                 p[i*4 + 2] = r[i] >> bits;
  399                 p[i*4 + 3] = 0;
  400         }
  401 
  402         bzero(&vmf, sizeof(vmf));
  403         vmf.vmf_eax = 0x4f09;
  404         vmf.vmf_ebx = 0;        /* set primary palette data */
  405         vmf.vmf_ecx = colors;
  406         vmf.vmf_edx = start;
  407         vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);
  408 
  409         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  410         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  411 }
  412 #endif
  413 
  414 static int
  415 vesa_bios_state_buf_size(void)
  416 {
  417         struct vm86frame vmf;
  418         int err;
  419 
  420         bzero(&vmf, sizeof(vmf));
  421         vmf.vmf_eax = 0x4f04; 
  422         vmf.vmf_ecx = STATE_MOST;
  423         vmf.vmf_edx = STATE_SIZE;
  424         err = vm86_intcall(0x10, &vmf);
  425         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  426                 return 0;
  427         return vmf.vmf_bx*64;
  428 }
  429 
  430 static int
  431 vesa_bios_save_restore(int code, void *p, size_t size)
  432 {
  433         struct vm86frame vmf;
  434         u_char *buf;
  435         int err;
  436 
  437         bzero(&vmf, sizeof(vmf));
  438         vmf.vmf_eax = 0x4f04; 
  439         vmf.vmf_ecx = STATE_MOST;
  440         vmf.vmf_edx = code;     /* STATE_SAVE/STATE_LOAD */
  441         buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  442         vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_bx);
  443         bcopy(p, buf, size);
  444 
  445         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  446         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  447 }
  448 
  449 static int
  450 vesa_bios_get_line_length(void)
  451 {
  452         struct vm86frame vmf;
  453         int err;
  454 
  455         bzero(&vmf, sizeof(vmf));
  456         vmf.vmf_eax = 0x4f06; 
  457         vmf.vmf_ebx = 1;        /* get scan line length */
  458         err = vm86_intcall(0x10, &vmf);
  459         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  460                 return -1;
  461         return vmf.vmf_bx;      /* line length in bytes */
  462 }
  463 
  464 static int
  465 vesa_bios_set_line_length(int pixel, int *bytes, int *lines)
  466 {
  467         struct vm86frame vmf;
  468         int err;
  469 
  470         bzero(&vmf, sizeof(vmf));
  471         vmf.vmf_eax = 0x4f06; 
  472         vmf.vmf_ebx = 0;        /* set scan line length in pixel */
  473         vmf.vmf_ecx = pixel;
  474         err = vm86_intcall(0x10, &vmf);
  475 #if VESA_DEBUG > 1
  476         printf("bx:%d, cx:%d, dx:%d\n", vmf.vmf_bx, vmf.vmf_cx, vmf.vmf_dx); 
  477 #endif
  478         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  479                 return 1;
  480         if (bytes)
  481                 *bytes = vmf.vmf_bx;
  482         if (lines)
  483                 *lines = vmf.vmf_dx;
  484         return 0;
  485 }
  486 
  487 #if 0
  488 static int
  489 vesa_bios_get_start(int *x, int *y)
  490 {
  491         struct vm86frame vmf;
  492         int err;
  493 
  494         bzero(&vmf, sizeof(vmf));
  495         vmf.vmf_eax = 0x4f07; 
  496         vmf.vmf_ebx = 1;        /* get display start */
  497         err = vm86_intcall(0x10, &vmf);
  498         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  499                 return 1;
  500         *x = vmf.vmf_cx;
  501         *y = vmf.vmf_dx;
  502         return 0;
  503 }
  504 #endif
  505 
  506 static int
  507 vesa_bios_set_start(int x, int y)
  508 {
  509         struct vm86frame vmf;
  510         int err;
  511 
  512         bzero(&vmf, sizeof(vmf));
  513         vmf.vmf_eax = 0x4f07; 
  514         vmf.vmf_ebx = 0x80;     /* set display start */
  515         vmf.vmf_edx = y;
  516         vmf.vmf_ecx = x;
  517         err = vm86_intcall(0x10, &vmf);
  518         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  519 }
  520 
  521 /* map a generic video mode to a known mode */
  522 static int
  523 vesa_map_gen_mode_num(int type, int color, int mode)
  524 {
  525     static struct {
  526         int from;
  527         int to;
  528     } mode_map[] = {
  529         { M_TEXT_132x25, M_VESA_C132x25 },
  530         { M_TEXT_132x43, M_VESA_C132x43 },
  531         { M_TEXT_132x50, M_VESA_C132x50 },
  532         { M_TEXT_132x60, M_VESA_C132x60 },
  533     };
  534     int i;
  535 
  536     for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
  537         if (mode_map[i].from == mode)
  538             return mode_map[i].to;
  539     }
  540     return mode;
  541 }
  542 
  543 static int
  544 vesa_translate_flags(u_int16_t vflags)
  545 {
  546         static struct {
  547                 u_int16_t mask;
  548                 int set;
  549                 int reset;
  550         } ftable[] = {
  551                 { V_MODECOLOR, V_INFO_COLOR, 0 },
  552                 { V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 },
  553                 { V_MODELFB, V_INFO_LINEAR, 0 },
  554         };
  555         int flags;
  556         int i;
  557 
  558         for (flags = 0, i = 0; i < sizeof(ftable)/sizeof(ftable[0]); ++i) {
  559                 flags |= (vflags & ftable[i].mask) ? 
  560                          ftable[i].set : ftable[i].reset;
  561         }
  562         return flags;
  563 }
  564 
  565 static int
  566 vesa_translate_mmodel(u_int8_t vmodel)
  567 {
  568         static struct {
  569                 u_int8_t vmodel;
  570                 int mmodel;
  571         } mtable[] = {
  572                 { V_MMTEXT,     V_INFO_MM_TEXT },
  573                 { V_MMCGA,      V_INFO_MM_CGA },
  574                 { V_MMHGC,      V_INFO_MM_HGC },
  575                 { V_MMEGA,      V_INFO_MM_PLANAR },
  576                 { V_MMPACKED,   V_INFO_MM_PACKED },
  577                 { V_MMDIRCOLOR, V_INFO_MM_DIRECT },
  578         };
  579         int i;
  580 
  581         for (i = 0; mtable[i].mmodel >= 0; ++i) {
  582                 if (mtable[i].vmodel == vmodel)
  583                         return mtable[i].mmodel;
  584         }
  585         return V_INFO_MM_OTHER;
  586 }
  587 
  588 static void
  589 *vesa_fix_ptr(u_int32_t p, u_int16_t seg, u_int16_t off, u_char *buf)
  590 {
  591         if (p == 0)
  592                 return NULL;
  593         if (((p >> 16) == seg) && ((p & 0xffff) >= off))
  594                 return (void *)(buf + ((p & 0xffff) - off));
  595         else {
  596                 p = BIOS_SADDRTOLADDR(p);
  597                 return (void *)BIOS_PADDRTOVADDR(p);
  598         }
  599 }
  600 
  601 static int
  602 vesa_bios_init(void)
  603 {
  604         static u_char buf[512];
  605         struct vm86frame vmf;
  606         struct vesa_mode vmode;
  607         video_info_t *p;
  608         u_char *vmbuf;
  609         int modes;
  610         int err;
  611         int i;
  612 
  613         if (vesa_init_done)
  614                 return 0;
  615 
  616         has_vesa_bios = FALSE;
  617         vesa_adp_info = NULL;
  618         vesa_vmode_max = 0;
  619         vesa_vmode[0].vi_mode = EOT;
  620 
  621         vmbuf = (u_char *)vm86_addpage(&vesa_vmcontext, 1, 0);
  622         bzero(&vmf, sizeof(vmf));       /* paranoia */
  623         bcopy("VBE2", vmbuf, 4);        /* try for VBE2 data */
  624         vmf.vmf_eax = 0x4f00;
  625         vm86_getptr(&vesa_vmcontext, (vm_offset_t)vmbuf, &vmf.vmf_es, &vmf.vmf_di);
  626 
  627         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  628         if ((err != 0) || (vmf.vmf_ax != 0x4f) || bcmp("VESA", vmbuf, 4))
  629                 return 1;
  630         bcopy(vmbuf, buf, sizeof(buf));
  631         vesa_adp_info = (struct vesa_info *)buf;
  632         if (bootverbose) {
  633                 printf("VESA: information block\n");
  634                 dump_buffer(buf, 64);
  635         }
  636         if (vesa_adp_info->v_flags & V_NONVGA)
  637                 return 1;
  638         if (vesa_adp_info->v_version < 0x0102) {
  639                 printf("VESA: VBE version %d.%d is not supported; "
  640                        "version 1.2 or later is required.\n",
  641                        ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 
  642                            + ((vesa_adp_info->v_version & 0x0f00) >> 8),
  643                        ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 
  644                            + (vesa_adp_info->v_version & 0x000f));
  645                 return 1;
  646         }
  647 
  648         /* fix string ptrs */
  649         vesa_oemstr = (char *)vesa_fix_ptr(vesa_adp_info->v_oemstr,
  650                                            vmf.vmf_es, vmf.vmf_di, buf);
  651         if (vesa_adp_info->v_version >= 0x0200) {
  652                 vesa_venderstr = 
  653                     (char *)vesa_fix_ptr(vesa_adp_info->v_venderstr,
  654                                          vmf.vmf_es, vmf.vmf_di, buf);
  655                 vesa_prodstr = 
  656                     (char *)vesa_fix_ptr(vesa_adp_info->v_prodstr,
  657                                          vmf.vmf_es, vmf.vmf_di, buf);
  658                 vesa_revstr = 
  659                     (char *)vesa_fix_ptr(vesa_adp_info->v_revstr,
  660                                          vmf.vmf_es, vmf.vmf_di, buf);
  661         }
  662 
  663         /* obtain video mode information */
  664         vesa_vmodetab = (u_int16_t *)vesa_fix_ptr(vesa_adp_info->v_modetable,
  665                                                   vmf.vmf_es, vmf.vmf_di, buf);
  666         if (vesa_vmodetab == NULL)
  667                 return 1;
  668         for (i = 0, modes = 0; 
  669                 (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1))
  670                 && (vesa_vmodetab[i] != 0xffff); ++i) {
  671                 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
  672                         continue;
  673 
  674                 /* reject unsupported modes */
  675 #if 0
  676                 if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO 
  677                                         | V_MODENONVGA))
  678                     != (V_MODESUPP | V_MODEOPTINFO))
  679                         continue;
  680 #else
  681                 if ((vmode.v_modeattr & V_MODEOPTINFO) == 0) {
  682 #if VESA_DEBUG > 1
  683                         printf(
  684                 "Rejecting VESA %s mode: %d x %d x %d bpp  attr = %x\n",
  685                             vmode.v_modeattr & V_MODEGRAPHICS ? "graphics" : "text",
  686                             vmode.v_width, vmode.v_height, vmode.v_bpp,
  687                             vmode.v_modeattr);
  688 #endif
  689                         continue;
  690                 }
  691 #endif
  692 
  693                 /* expand the array if necessary */
  694                 if (modes >= vesa_vmode_max) {
  695                         vesa_vmode_max += MODE_TABLE_DELTA;
  696                         p = malloc(sizeof(*vesa_vmode)*(vesa_vmode_max + 1),
  697                                    M_DEVBUF, M_WAITOK);
  698 #if VESA_DEBUG > 1
  699                         printf("vesa_bios_init(): modes:%d, vesa_mode_max:%d\n",
  700                                modes, vesa_vmode_max);
  701 #endif
  702                         if (modes > 0) {
  703                                 bcopy(vesa_vmode, p, sizeof(*vesa_vmode)*modes);
  704                                 free(vesa_vmode, M_DEVBUF);
  705                         }
  706                         vesa_vmode = p;
  707                 }
  708 
  709 #if VESA_DEBUG > 1
  710                 printf("Found VESA %s mode: %d x %d x %d bpp\n",
  711                     vmode.v_modeattr & V_MODEGRAPHICS ? "graphics" : "text",
  712                     vmode.v_width, vmode.v_height, vmode.v_bpp);
  713 #endif
  714                 /* copy some fields */
  715                 bzero(&vesa_vmode[modes], sizeof(vesa_vmode[modes]));
  716                 vesa_vmode[modes].vi_mode = vesa_vmodetab[i];
  717                 vesa_vmode[modes].vi_width = vmode.v_width;
  718                 vesa_vmode[modes].vi_height = vmode.v_height;
  719                 vesa_vmode[modes].vi_depth = vmode.v_bpp;
  720                 vesa_vmode[modes].vi_planes = vmode.v_planes;
  721                 vesa_vmode[modes].vi_cwidth = vmode.v_cwidth;
  722                 vesa_vmode[modes].vi_cheight = vmode.v_cheight;
  723                 vesa_vmode[modes].vi_window = (u_int)vmode.v_waseg << 4;
  724                 /* XXX window B */
  725                 vesa_vmode[modes].vi_window_size = vmode.v_wsize*1024;
  726                 vesa_vmode[modes].vi_window_gran = vmode.v_wgran*1024;
  727                 if (vmode.v_modeattr & V_MODELFB)
  728                         vesa_vmode[modes].vi_buffer = vmode.v_lfb;
  729                 else
  730                         vesa_vmode[modes].vi_buffer = 0;
  731                 /* XXX */
  732                 vesa_vmode[modes].vi_buffer_size
  733                         = vesa_adp_info->v_memsize*64*1024;
  734 #if 0
  735                 if (vmode.v_offscreen > vmode.v_lfb)
  736                         vesa_vmode[modes].vi_buffer_size
  737                                 = vmode.v_offscreen + vmode.v_offscreensize*1024
  738                                       - vmode.v_lfb;
  739                 else
  740                         vesa_vmode[modes].vi_buffer_size
  741                                 = vmode.v_offscreen + vmode.v_offscreensize*1024
  742 #endif
  743                 vesa_vmode[modes].vi_mem_model 
  744                         = vesa_translate_mmodel(vmode.v_memmodel);
  745                 vesa_vmode[modes].vi_pixel_fields[0] = 0;
  746                 vesa_vmode[modes].vi_pixel_fields[1] = 0;
  747                 vesa_vmode[modes].vi_pixel_fields[2] = 0;
  748                 vesa_vmode[modes].vi_pixel_fields[3] = 0;
  749                 vesa_vmode[modes].vi_pixel_fsizes[0] = 0;
  750                 vesa_vmode[modes].vi_pixel_fsizes[1] = 0;
  751                 vesa_vmode[modes].vi_pixel_fsizes[2] = 0;
  752                 vesa_vmode[modes].vi_pixel_fsizes[3] = 0;
  753                 if (vesa_vmode[modes].vi_mem_model == V_INFO_MM_PACKED) {
  754                         vesa_vmode[modes].vi_pixel_size = (vmode.v_bpp + 7)/8;
  755                 } else if (vesa_vmode[modes].vi_mem_model == V_INFO_MM_DIRECT) {
  756                         vesa_vmode[modes].vi_pixel_size = (vmode.v_bpp + 7)/8;
  757                         vesa_vmode[modes].vi_pixel_fields[0]
  758                             = vmode.v_redfieldpos;
  759                         vesa_vmode[modes].vi_pixel_fields[1]
  760                             = vmode.v_greenfieldpos;
  761                         vesa_vmode[modes].vi_pixel_fields[2]
  762                             = vmode.v_bluefieldpos;
  763                         vesa_vmode[modes].vi_pixel_fields[3]
  764                             = vmode.v_resfieldpos;
  765                         vesa_vmode[modes].vi_pixel_fsizes[0]
  766                             = vmode.v_redmasksize;
  767                         vesa_vmode[modes].vi_pixel_fsizes[1]
  768                             = vmode.v_greenmasksize;
  769                         vesa_vmode[modes].vi_pixel_fsizes[2]
  770                             = vmode.v_bluemasksize;
  771                         vesa_vmode[modes].vi_pixel_fsizes[3]
  772                             = vmode.v_resmasksize;
  773                 } else {
  774                         vesa_vmode[modes].vi_pixel_size = 0;
  775                 }
  776                 
  777                 vesa_vmode[modes].vi_flags 
  778                         = vesa_translate_flags(vmode.v_modeattr) | V_INFO_VESA;
  779                 ++modes;
  780         }
  781         vesa_vmode[modes].vi_mode = EOT;
  782         if (bootverbose)
  783                 printf("VESA: %d mode(s) found\n", modes);
  784 
  785         has_vesa_bios = (modes > 0);
  786         return (has_vesa_bios ? 0 : 1);
  787 }
  788 
  789 static void
  790 vesa_clear_modes(video_info_t *info, int color)
  791 {
  792         while (info->vi_mode != EOT) {
  793                 if ((info->vi_flags & V_INFO_COLOR) != color)
  794                         info->vi_mode = NA;
  795                 ++info;
  796         }
  797 }
  798 
  799 static vm_offset_t
  800 vesa_map_buffer(u_int paddr, size_t size)
  801 {
  802         vm_offset_t vaddr;
  803         u_int off;
  804 
  805         off = paddr - trunc_page(paddr);
  806         vaddr = (vm_offset_t)pmap_mapdev(paddr - off, size + off);
  807 #if VESA_DEBUG > 1
  808         printf("vesa_map_buffer: paddr:%x vaddr:%x size:%x off:%x\n",
  809                paddr, vaddr, size, off);
  810 #endif
  811         return (vaddr + off);
  812 }
  813 
  814 static void
  815 vesa_unmap_buffer(vm_offset_t vaddr, size_t size)
  816 {
  817 #if VESA_DEBUG > 1
  818         printf("vesa_unmap_buffer: vaddr:%x size:%x\n", vaddr, size);
  819 #endif
  820         kmem_free(kernel_map, vaddr, size);
  821 }
  822 
  823 /* entry points */
  824 
  825 static int
  826 vesa_configure(int flags)
  827 {
  828         video_adapter_t *adp;
  829         int adapters;
  830         int error;
  831         int i;
  832 
  833         if (vesa_init_done)
  834                 return 0;
  835         if (flags & VIO_PROBE_ONLY)
  836                 return 0;               /* XXX */
  837 
  838         /*
  839          * If the VESA module has already been loaded, abort loading 
  840          * the module this time.
  841          */
  842         for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) {
  843                 if (adp->va_flags & V_ADP_VESA)
  844                         return ENXIO;
  845                 if (adp->va_type == KD_VGA)
  846                         break;
  847         }
  848         /*
  849          * The VGA adapter is not found.  This is because either 
  850          * 1) the VGA driver has not been initialized, or 2) the VGA card
  851          * is not present.  If 1) is the case, we shall defer
  852          * initialization for now and try again later.
  853          */
  854         if (adp == NULL) {
  855                 vga_sub_configure = vesa_configure;
  856                 return ENODEV;
  857         }
  858 
  859         /* count number of registered adapters */
  860         for (++i; vid_get_adapter(i) != NULL; ++i)
  861                 ;
  862         adapters = i;
  863 
  864         /* call VESA BIOS */
  865         vesa_adp = adp;
  866         if (vesa_bios_init()) {
  867                 vesa_adp = NULL;
  868                 return ENXIO;
  869         }
  870         vesa_adp->va_flags |= V_ADP_VESA;
  871 
  872         /* remove conflicting modes if we have more than one adapter */
  873         if (adapters > 1) {
  874                 vesa_clear_modes(vesa_vmode,
  875                                  (vesa_adp->va_flags & V_ADP_COLOR) ? 
  876                                      V_INFO_COLOR : 0);
  877         }
  878 
  879         if ((error = vesa_load_ioctl()) == 0) {
  880                 prevvidsw = vidsw[vesa_adp->va_index];
  881                 vidsw[vesa_adp->va_index] = &vesavidsw;
  882                 vesa_init_done = TRUE;
  883         } else {
  884                 vesa_adp = NULL;
  885                 return error;
  886         }
  887 
  888         return 0;
  889 }
  890 
  891 #if 0
  892 static int
  893 vesa_nop(void)
  894 {
  895         return 0;
  896 }
  897 #endif
  898 
  899 static int
  900 vesa_error(void)
  901 {
  902         return 1;
  903 }
  904 
  905 static int
  906 vesa_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
  907 {
  908         return (*prevvidsw->probe)(unit, adpp, arg, flags);
  909 }
  910 
  911 static int
  912 vesa_init(int unit, video_adapter_t *adp, int flags)
  913 {
  914         return (*prevvidsw->init)(unit, adp, flags);
  915 }
  916 
  917 static int
  918 vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info)
  919 {
  920         int i;
  921 
  922         if ((*prevvidsw->get_info)(adp, mode, info) == 0)
  923                 return 0;
  924 
  925         if (adp != vesa_adp)
  926                 return 1;
  927 
  928         mode = vesa_map_gen_mode_num(vesa_adp->va_type, 
  929                                      vesa_adp->va_flags & V_ADP_COLOR, mode);
  930         for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
  931                 if (vesa_vmode[i].vi_mode == NA)
  932                         continue;
  933                 if (vesa_vmode[i].vi_mode == mode) {
  934                         *info = vesa_vmode[i];
  935                         return 0;
  936                 }
  937         }
  938         return 1;
  939 }
  940 
  941 static int
  942 vesa_query_mode(video_adapter_t *adp, video_info_t *info)
  943 {
  944         int i;
  945 
  946         if ((*prevvidsw->query_mode)(adp, info) == 0)
  947                 return 0;
  948         if (adp != vesa_adp)
  949                 return ENODEV;
  950 
  951         for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
  952                 if ((info->vi_width != 0)
  953                     && (info->vi_width != vesa_vmode[i].vi_width))
  954                         continue;
  955                 if ((info->vi_height != 0)
  956                     && (info->vi_height != vesa_vmode[i].vi_height))
  957                         continue;
  958                 if ((info->vi_cwidth != 0)
  959                     && (info->vi_cwidth != vesa_vmode[i].vi_cwidth))
  960                         continue;
  961                 if ((info->vi_cheight != 0)
  962                     && (info->vi_cheight != vesa_vmode[i].vi_cheight))
  963                         continue;
  964                 if ((info->vi_depth != 0)
  965                     && (info->vi_depth != vesa_vmode[i].vi_depth))
  966                         continue;
  967                 if ((info->vi_planes != 0)
  968                     && (info->vi_planes != vesa_vmode[i].vi_planes))
  969                         continue;
  970                 /* pixel format, memory model */
  971                 if ((info->vi_flags != 0)
  972                     && (info->vi_flags != vesa_vmode[i].vi_flags))
  973                         continue;
  974                 *info = vesa_vmode[i];
  975                 return 0;
  976         }
  977         return ENODEV;
  978 }
  979 
  980 static int
  981 vesa_set_mode(video_adapter_t *adp, int mode)
  982 {
  983         video_info_t info;
  984         int len;
  985 
  986         if (adp != vesa_adp)
  987                 return (*prevvidsw->set_mode)(adp, mode);
  988 
  989         mode = vesa_map_gen_mode_num(adp->va_type, 
  990                                      adp->va_flags & V_ADP_COLOR, mode);
  991 #if VESA_DEBUG > 0
  992         printf("VESA: set_mode(): %d(%x) -> %d(%x)\n",
  993                 adp->va_mode, adp->va_mode, mode, mode);
  994 #endif
  995         /* 
  996          * If the current mode is a VESA mode and the new mode is not,
  997          * restore the state of the adapter first by setting one of the
  998          * standard VGA mode, so that non-standard, extended SVGA registers 
  999          * are set to the state compatible with the standard VGA modes. 
 1000          * Otherwise (*prevvidsw->set_mode)() may not be able to set up 
 1001          * the new mode correctly.
 1002          */
 1003         if (VESA_MODE(adp->va_mode)) {
 1004                 if ((*prevvidsw->get_info)(adp, mode, &info) == 0) {
 1005                         int10_set_mode(adp->va_initial_bios_mode);
 1006                         if (adp->va_info.vi_flags & V_INFO_LINEAR)
 1007                                 vesa_unmap_buffer(adp->va_buffer,
 1008                                                   vesa_adp_info->v_memsize*64*1024);
 1009                         /* 
 1010                          * Once (*prevvidsw->get_info)() succeeded, 
 1011                          * (*prevvidsw->set_mode)() below won't fail...
 1012                          */
 1013                 }
 1014         }
 1015 
 1016         /* we may not need to handle this mode after all... */
 1017         if ((*prevvidsw->set_mode)(adp, mode) == 0)
 1018                 return 0;
 1019 
 1020         /* is the new mode supported? */
 1021         if (vesa_get_info(adp, mode, &info))
 1022                 return 1;
 1023         /* assert(VESA_MODE(mode)); */
 1024 
 1025 #if VESA_DEBUG > 0
 1026         printf("VESA: about to set a VESA mode...\n");
 1027 #endif
 1028         /* don't use the linear frame buffer for text modes. XXX */
 1029         if (!(info.vi_flags & V_INFO_GRAPHICS))
 1030                 info.vi_flags &= ~V_INFO_LINEAR;
 1031 
 1032         if (vesa_bios_set_mode(mode | ((info.vi_flags & V_INFO_LINEAR) ? 0x4000 : 0)))
 1033                 return 1;
 1034 
 1035         if (adp->va_info.vi_flags & V_INFO_LINEAR)
 1036                 vesa_unmap_buffer(adp->va_buffer,
 1037                                   vesa_adp_info->v_memsize*64*1024);
 1038 
 1039 #if VESA_DEBUG > 0
 1040         printf("VESA: mode set!\n");
 1041 #endif
 1042         vesa_adp->va_mode = mode;
 1043         vesa_adp->va_flags &= ~V_ADP_COLOR;
 1044         vesa_adp->va_flags |= 
 1045                 (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
 1046         vesa_adp->va_crtc_addr =
 1047                 (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
 1048         if (info.vi_flags & V_INFO_LINEAR) {
 1049 #if VESA_DEBUG > 1
 1050                 printf("VESA: setting up LFB\n");
 1051 #endif
 1052                 vesa_adp->va_buffer =
 1053                         vesa_map_buffer(info.vi_buffer,
 1054                                         vesa_adp_info->v_memsize*64*1024);
 1055                 vesa_adp->va_buffer_size = info.vi_buffer_size;
 1056                 vesa_adp->va_window = vesa_adp->va_buffer;
 1057                 vesa_adp->va_window_size = info.vi_buffer_size/info.vi_planes;
 1058                 vesa_adp->va_window_gran = info.vi_buffer_size/info.vi_planes;
 1059         } else {
 1060                 vesa_adp->va_buffer = 0;
 1061                 vesa_adp->va_buffer_size = info.vi_buffer_size;
 1062                 vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
 1063                 vesa_adp->va_window_size = info.vi_window_size;
 1064                 vesa_adp->va_window_gran = info.vi_window_gran;
 1065         }
 1066         vesa_adp->va_window_orig = 0;
 1067         len = vesa_bios_get_line_length();
 1068         if (len > 0) {
 1069                 vesa_adp->va_line_width = len;
 1070         } else if (info.vi_flags & V_INFO_GRAPHICS) {
 1071                 switch (info.vi_depth/info.vi_planes) {
 1072                 case 1:
 1073                         vesa_adp->va_line_width = info.vi_width/8;
 1074                         break;
 1075                 case 2:
 1076                         vesa_adp->va_line_width = info.vi_width/4;
 1077                         break;
 1078                 case 4:
 1079                         vesa_adp->va_line_width = info.vi_width/2;
 1080                         break;
 1081                 case 8:
 1082                 default: /* shouldn't happen */
 1083                         vesa_adp->va_line_width = info.vi_width;
 1084                         break;
 1085                 }
 1086         } else {
 1087                 vesa_adp->va_line_width = info.vi_width;
 1088         }
 1089         vesa_adp->va_disp_start.x = 0;
 1090         vesa_adp->va_disp_start.y = 0;
 1091 #if VESA_DEBUG > 0
 1092         printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n",
 1093                info.vi_width, len, vesa_adp->va_line_width);
 1094 #endif
 1095         bcopy(&info, &vesa_adp->va_info, sizeof(vesa_adp->va_info));
 1096 
 1097         /* move hardware cursor out of the way */
 1098         (*vidsw[vesa_adp->va_index]->set_hw_cursor)(vesa_adp, -1, -1);
 1099 
 1100         return 0;
 1101 }
 1102 
 1103 static int
 1104 vesa_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
 1105                int ch, int count)
 1106 {
 1107         return (*prevvidsw->save_font)(adp, page, fontsize, data, ch, count);
 1108 }
 1109 
 1110 static int
 1111 vesa_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
 1112                int ch, int count)
 1113 {
 1114         return (*prevvidsw->load_font)(adp, page, fontsize, data, ch, count);
 1115 }
 1116 
 1117 static int
 1118 vesa_show_font(video_adapter_t *adp, int page)
 1119 {
 1120         return (*prevvidsw->show_font)(adp, page);
 1121 }
 1122 
 1123 static int
 1124 vesa_save_palette(video_adapter_t *adp, u_char *palette)
 1125 {
 1126         int bits;
 1127         int error;
 1128 
 1129         if ((adp == vesa_adp) && (vesa_adp_info->v_flags & V_DAC8)
 1130             && VESA_MODE(adp->va_mode)) {
 1131                 bits = vesa_bios_get_dac();
 1132                 error = vesa_bios_save_palette(0, 256, palette, bits);
 1133                 if (error == 0)
 1134                         return 0;
 1135                 if (bits != 6)
 1136                         return error;
 1137         }
 1138 
 1139         return (*prevvidsw->save_palette)(adp, palette);
 1140 }
 1141 
 1142 static int
 1143 vesa_load_palette(video_adapter_t *adp, u_char *palette)
 1144 {
 1145 #if notyet
 1146         int bits;
 1147         int error;
 1148 
 1149         if ((adp == vesa_adp) && (vesa_adp_info->v_flags & V_DAC8) 
 1150             && VESA_MODE(adp->va_mode) && ((bits = vesa_bios_set_dac(8)) > 6)) {
 1151                 error = vesa_bios_load_palette(0, 256, palette, bits);
 1152                 if (error == 0)
 1153                         return 0;
 1154                 if (vesa_bios_set_dac(6) != 6)
 1155                         return 1;
 1156         }
 1157 #endif /* notyet */
 1158 
 1159         return (*prevvidsw->load_palette)(adp, palette);
 1160 }
 1161 
 1162 static int
 1163 vesa_set_border(video_adapter_t *adp, int color)
 1164 {
 1165         return (*prevvidsw->set_border)(adp, color);
 1166 }
 1167 
 1168 static int
 1169 vesa_save_state(video_adapter_t *adp, void *p, size_t size)
 1170 {
 1171         if (adp != vesa_adp)
 1172                 return (*prevvidsw->save_state)(adp, p, size);
 1173 
 1174         if (vesa_state_buf_size == 0)
 1175                 vesa_state_buf_size = vesa_bios_state_buf_size();
 1176         if (size == 0)
 1177                 return (sizeof(int) + vesa_state_buf_size);
 1178         else if (size < (sizeof(int) + vesa_state_buf_size))
 1179                 return 1;
 1180 
 1181         ((adp_state_t *)p)->sig = V_STATE_SIG;
 1182         bzero(((adp_state_t *)p)->regs, vesa_state_buf_size);
 1183         return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, 
 1184                                       vesa_state_buf_size);
 1185 }
 1186 
 1187 static int
 1188 vesa_load_state(video_adapter_t *adp, void *p)
 1189 {
 1190         if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG))
 1191                 return (*prevvidsw->load_state)(adp, p);
 1192 
 1193         return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, 
 1194                                       vesa_state_buf_size);
 1195 }
 1196 
 1197 #if 0
 1198 static int
 1199 vesa_get_origin(video_adapter_t *adp, off_t *offset)
 1200 {
 1201         struct vm86frame vmf;
 1202         int err;
 1203 
 1204         bzero(&vmf, sizeof(vmf));
 1205         vmf.vmf_eax = 0x4f05; 
 1206         vmf.vmf_ebx = 0x10;             /* WINDOW_A, XXX */
 1207         err = vm86_intcall(0x10, &vmf); 
 1208         if ((err != 0) || (vmf.vmf_ax != 0x4f))
 1209                 return 1;
 1210         *offset = vmf.vmf_dx*adp->va_window_gran;
 1211         return 0;
 1212 }
 1213 #endif
 1214 
 1215 static int
 1216 vesa_set_origin(video_adapter_t *adp, off_t offset)
 1217 {
 1218         struct vm86frame vmf;
 1219         int err;
 1220 
 1221         /*
 1222          * This function should return as quickly as possible to 
 1223          * maintain good performance of the system. For this reason,
 1224          * error checking is kept minimal and let the VESA BIOS to 
 1225          * detect error.
 1226          */
 1227         if (adp != vesa_adp) 
 1228                 return (*prevvidsw->set_win_org)(adp, offset);
 1229 
 1230         /* if this is a linear frame buffer, do nothing */
 1231         if (adp->va_info.vi_flags & V_INFO_LINEAR)
 1232                 return 0;
 1233         /* XXX */
 1234         if (adp->va_window_gran == 0)
 1235                 return 1;
 1236 
 1237         bzero(&vmf, sizeof(vmf));
 1238         vmf.vmf_eax = 0x4f05; 
 1239         vmf.vmf_ebx = 0;                /* WINDOW_A, XXX */
 1240         vmf.vmf_edx = offset/adp->va_window_gran;
 1241         err = vm86_intcall(0x10, &vmf); 
 1242         if ((err != 0) || (vmf.vmf_ax != 0x4f))
 1243                 return 1;
 1244         bzero(&vmf, sizeof(vmf));
 1245         vmf.vmf_eax = 0x4f05; 
 1246         vmf.vmf_ebx = 1;                /* WINDOW_B, XXX */
 1247         vmf.vmf_edx = offset/adp->va_window_gran;
 1248         err = vm86_intcall(0x10, &vmf); 
 1249         adp->va_window_orig = (offset/adp->va_window_gran)*adp->va_window_gran;
 1250         return 0;                       /* XXX */
 1251 }
 1252 
 1253 static int
 1254 vesa_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
 1255 {
 1256         return (*prevvidsw->read_hw_cursor)(adp, col, row);
 1257 }
 1258 
 1259 static int
 1260 vesa_set_hw_cursor(video_adapter_t *adp, int col, int row)
 1261 {
 1262         return (*prevvidsw->set_hw_cursor)(adp, col, row);
 1263 }
 1264 
 1265 static int
 1266 vesa_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
 1267                          int celsize, int blink)
 1268 {
 1269         return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize,
 1270                                                  blink);
 1271 }
 1272 
 1273 static int
 1274 vesa_blank_display(video_adapter_t *adp, int mode) 
 1275 {
 1276         /* XXX: use VESA DPMS */
 1277         return (*prevvidsw->blank_display)(adp, mode);
 1278 }
 1279 
 1280 static int
 1281 vesa_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr,
 1282           int prot)
 1283 {
 1284 #if VESA_DEBUG > 0
 1285         printf("vesa_mmap(): window:0x%x, buffer:0x%x, offset:0x%x\n", 
 1286                adp->va_info.vi_window, adp->va_info.vi_buffer, offset);
 1287 #endif
 1288 
 1289         if ((adp == vesa_adp) && (adp->va_info.vi_flags & V_INFO_LINEAR)) {
 1290                 /* va_window_size == va_buffer_size/vi_planes */
 1291                 /* XXX: is this correct? */
 1292                 if (offset > adp->va_window_size - PAGE_SIZE)
 1293                         return -1;
 1294                 *paddr = adp->va_info.vi_buffer + offset;
 1295                 return 0;
 1296         } else {
 1297                 return (*prevvidsw->mmap)(adp, offset, paddr, prot);
 1298         }
 1299 }
 1300 
 1301 static int
 1302 vesa_clear(video_adapter_t *adp)
 1303 {
 1304         return (*prevvidsw->clear)(adp);
 1305 }
 1306 
 1307 static int
 1308 vesa_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
 1309 {
 1310         return (*prevvidsw->fill_rect)(adp, val, x, y, cx, cy);
 1311 }
 1312 
 1313 static int
 1314 vesa_bitblt(video_adapter_t *adp,...)
 1315 {
 1316         /* FIXME */
 1317         return 1;
 1318 }
 1319 
 1320 static int
 1321 get_palette(video_adapter_t *adp, int base, int count,
 1322             u_char *red, u_char *green, u_char *blue, u_char *trans)
 1323 {
 1324         u_char *r;
 1325         u_char *g;
 1326         u_char *b;
 1327         int bits;
 1328         int error;
 1329 
 1330         if ((base < 0) || (base >= 256) || (count < 0) || (count > 256))
 1331                 return 1;
 1332         if ((base + count) > 256)
 1333                 return 1;
 1334         if (!(vesa_adp_info->v_flags & V_DAC8) || !VESA_MODE(adp->va_mode))
 1335                 return 1;
 1336 
 1337         bits = vesa_bios_get_dac();
 1338         if (bits <= 6)
 1339                 return 1;
 1340 
 1341         r = malloc(count*3, M_DEVBUF, M_WAITOK);
 1342         g = r + count;
 1343         b = g + count;
 1344         error = vesa_bios_save_palette2(base, count, r, g, b, bits);
 1345         if (error == 0) {
 1346                 copyout(r, red, count);
 1347                 copyout(g, green, count);
 1348                 copyout(b, blue, count);
 1349                 if (trans != NULL) {
 1350                         bzero(r, count);
 1351                         copyout(r, trans, count);
 1352                 }
 1353         }
 1354         free(r, M_DEVBUF);
 1355 
 1356         /* if error && bits != 6 at this point, we are in in trouble... XXX */
 1357         return error;
 1358 }
 1359 
 1360 static int
 1361 set_palette(video_adapter_t *adp, int base, int count,
 1362             u_char *red, u_char *green, u_char *blue, u_char *trans)
 1363 {
 1364         return 1;
 1365 #if notyet
 1366         u_char *r;
 1367         u_char *g;
 1368         u_char *b;
 1369         int bits;
 1370         int error;
 1371 
 1372         if ((base < 0) || (base >= 256) || (base + count > 256))
 1373                 return 1;
 1374         if (!(vesa_adp_info->v_flags & V_DAC8) || !VESA_MODE(adp->va_mode)
 1375                 || ((bits = vesa_bios_set_dac(8)) <= 6))
 1376                 return 1;
 1377 
 1378         r = malloc(count*3, M_DEVBUF, M_WAITOK);
 1379         g = r + count;
 1380         b = g + count;
 1381         copyin(red, r, count);
 1382         copyin(green, g, count);
 1383         copyin(blue, b, count);
 1384 
 1385         error = vesa_bios_load_palette2(base, count, r, g, b, bits);
 1386         free(r, M_DEVBUF);
 1387         if (error == 0)
 1388                 return 0;
 1389 
 1390         /* if the following call fails, we are in trouble... XXX */
 1391         vesa_bios_set_dac(6);
 1392         return 1;
 1393 #endif /* notyet */
 1394 }
 1395 
 1396 static int
 1397 vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
 1398 {
 1399         int bytes;
 1400 
 1401         if (adp != vesa_adp)
 1402                 return (*prevvidsw->ioctl)(adp, cmd, arg);
 1403 
 1404         switch (cmd) {
 1405         case FBIO_SETWINORG:    /* set frame buffer window origin */
 1406                 if (!VESA_MODE(adp->va_mode))
 1407                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1408                 return (vesa_set_origin(adp, *(off_t *)arg) ? ENODEV : 0);
 1409 
 1410         case FBIO_SETDISPSTART: /* set display start address */
 1411                 if (!VESA_MODE(adp->va_mode))
 1412                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1413                 if (vesa_bios_set_start(((video_display_start_t *)arg)->x,
 1414                                         ((video_display_start_t *)arg)->y))
 1415                         return ENODEV;
 1416                 adp->va_disp_start.x = ((video_display_start_t *)arg)->x;
 1417                 adp->va_disp_start.y = ((video_display_start_t *)arg)->y;
 1418                 return 0;
 1419 
 1420         case FBIO_SETLINEWIDTH: /* set line length in pixel */
 1421                 if (!VESA_MODE(adp->va_mode))
 1422                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1423                 if (vesa_bios_set_line_length(*(u_int *)arg, &bytes, NULL))
 1424                         return ENODEV;
 1425                 adp->va_line_width = bytes;
 1426 #if VESA_DEBUG > 1
 1427                 printf("new line width:%d\n", adp->va_line_width);
 1428 #endif
 1429                 return 0;
 1430 
 1431         case FBIO_GETPALETTE:   /* get color palette */
 1432                 if (get_palette(adp, ((video_color_palette_t *)arg)->index,
 1433                                 ((video_color_palette_t *)arg)->count,
 1434                                 ((video_color_palette_t *)arg)->red,
 1435                                 ((video_color_palette_t *)arg)->green,
 1436                                 ((video_color_palette_t *)arg)->blue,
 1437                                 ((video_color_palette_t *)arg)->transparent))
 1438                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1439                 return 0;
 1440 
 1441 
 1442         case FBIO_SETPALETTE:   /* set color palette */
 1443                 if (set_palette(adp, ((video_color_palette_t *)arg)->index,
 1444                                 ((video_color_palette_t *)arg)->count,
 1445                                 ((video_color_palette_t *)arg)->red,
 1446                                 ((video_color_palette_t *)arg)->green,
 1447                                 ((video_color_palette_t *)arg)->blue,
 1448                                 ((video_color_palette_t *)arg)->transparent))
 1449                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1450                 return 0;
 1451 
 1452         case FBIOGETCMAP:       /* get color palette */
 1453                 if (get_palette(adp, ((struct fbcmap *)arg)->index,
 1454                                 ((struct fbcmap *)arg)->count,
 1455                                 ((struct fbcmap *)arg)->red,
 1456                                 ((struct fbcmap *)arg)->green,
 1457                                 ((struct fbcmap *)arg)->blue, NULL))
 1458                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1459                 return 0;
 1460 
 1461         case FBIOPUTCMAP:       /* set color palette */
 1462                 if (set_palette(adp, ((struct fbcmap *)arg)->index,
 1463                                 ((struct fbcmap *)arg)->count,
 1464                                 ((struct fbcmap *)arg)->red,
 1465                                 ((struct fbcmap *)arg)->green,
 1466                                 ((struct fbcmap *)arg)->blue, NULL))
 1467                         return (*prevvidsw->ioctl)(adp, cmd, arg);
 1468                 return 0;
 1469 
 1470         default:
 1471                 return (*prevvidsw->ioctl)(adp, cmd, arg);
 1472         }
 1473 }
 1474 
 1475 static int
 1476 vesa_diag(video_adapter_t *adp, int level)
 1477 {
 1478         int error;
 1479 
 1480         /* call the previous handler first */
 1481         error = (*prevvidsw->diag)(adp, level);
 1482         if (error)
 1483                 return error;
 1484 
 1485         if (adp != vesa_adp)
 1486                 return 1;
 1487 
 1488         if (level <= 0)
 1489                 return 0;
 1490 
 1491         return 0;
 1492 }
 1493 
 1494 static int
 1495 vesa_bios_info(int level)
 1496 {
 1497 #if VESA_DEBUG > 1
 1498         struct vesa_mode vmode;
 1499         int i;
 1500 #endif
 1501 
 1502         /* general adapter information */
 1503         printf("VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n", 
 1504                ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 
 1505                    + ((vesa_adp_info->v_version & 0x0f00) >> 8),
 1506                ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 
 1507                    + (vesa_adp_info->v_version & 0x000f),
 1508                vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags,
 1509                vesa_vmodetab, vesa_adp_info->v_modetable);
 1510         /* OEM string */
 1511         if (vesa_oemstr != NULL)
 1512                 printf("VESA: %s\n", vesa_oemstr);
 1513 
 1514         if (level <= 0)
 1515                 return 0;
 1516 
 1517         if (vesa_adp_info->v_version >= 0x0200) {
 1518                 /* vender name, product name, product revision */
 1519                 printf("VESA: %s %s %s\n",
 1520                         (vesa_venderstr != NULL) ? vesa_venderstr : "unknown",
 1521                         (vesa_prodstr != NULL) ? vesa_prodstr : "unknown",
 1522                         (vesa_revstr != NULL) ? vesa_revstr : "?");
 1523         }
 1524 
 1525 #if VESA_DEBUG > 1
 1526         /* mode information */
 1527         for (i = 0;
 1528                 (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1))
 1529                 && (vesa_vmodetab[i] != 0xffff); ++i) {
 1530                 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
 1531                         continue;
 1532 
 1533                 /* print something for diagnostic purpose */
 1534                 printf("VESA: mode:0x%03x, flags:0x%04x", 
 1535                        vesa_vmodetab[i], vmode.v_modeattr);
 1536                 if (vmode.v_modeattr & V_MODEOPTINFO) {
 1537                         if (vmode.v_modeattr & V_MODEGRAPHICS) {
 1538                                 printf(", G %dx%dx%d %d, ", 
 1539                                        vmode.v_width, vmode.v_height,
 1540                                        vmode.v_bpp, vmode.v_planes);
 1541                         } else {
 1542                                 printf(", T %dx%d, ", 
 1543                                        vmode.v_width, vmode.v_height);
 1544                         }
 1545                         printf("font:%dx%d, ", 
 1546                                vmode.v_cwidth, vmode.v_cheight);
 1547                         printf("pages:%d, mem:%d",
 1548                                vmode.v_ipages + 1, vmode.v_memmodel);
 1549                 }
 1550                 if (vmode.v_modeattr & V_MODELFB) {
 1551                         printf("\nVESA: LFB:0x%x, off:0x%x, off_size:0x%x", 
 1552                                vmode.v_lfb, vmode.v_offscreen,
 1553                                vmode.v_offscreensize*1024);
 1554                 }
 1555                 printf("\n");
 1556                 printf("VESA: window A:0x%x (%x), window B:0x%x (%x), ",
 1557                        vmode.v_waseg, vmode.v_waattr,
 1558                        vmode.v_wbseg, vmode.v_wbattr);
 1559                 printf("size:%dk, gran:%dk\n",
 1560                        vmode.v_wsize, vmode.v_wgran);
 1561         }
 1562 #endif /* VESA_DEBUG > 1 */
 1563 
 1564         return 0;
 1565 }
 1566 
 1567 /* module loading */
 1568 
 1569 static int
 1570 vesa_load(void)
 1571 {
 1572         int error;
 1573         int s;
 1574 
 1575         if (vesa_init_done)
 1576                 return 0;
 1577 
 1578         /* locate a VGA adapter */
 1579         s = spltty();
 1580         vesa_adp = NULL;
 1581         error = vesa_configure(0);
 1582         splx(s);
 1583 
 1584         if (error == 0)
 1585                 vesa_bios_info(bootverbose);
 1586 
 1587         return error;
 1588 }
 1589 
 1590 static int
 1591 vesa_unload(void)
 1592 {
 1593         u_char palette[256*3];
 1594         int error;
 1595         int bits;
 1596         int s;
 1597 
 1598         /* if the adapter is currently in a VESA mode, don't unload */
 1599         if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode))
 1600                 return EBUSY;
 1601         /* 
 1602          * FIXME: if there is at least one vty which is in a VESA mode,
 1603          * we shouldn't be unloading! XXX
 1604          */
 1605 
 1606         s = spltty();
 1607         if ((error = vesa_unload_ioctl()) == 0) {
 1608                 if (vesa_adp != NULL) {
 1609                         if (vesa_adp_info->v_flags & V_DAC8)  {
 1610                                 bits = vesa_bios_get_dac();
 1611                                 if (bits > 6) {
 1612                                         vesa_bios_save_palette(0, 256,
 1613                                                                palette, bits);
 1614                                         vesa_bios_set_dac(6);
 1615                                         vesa_bios_load_palette(0, 256,
 1616                                                                palette, 6);
 1617                                 }
 1618                         }
 1619                         vesa_adp->va_flags &= ~V_ADP_VESA;
 1620                         vidsw[vesa_adp->va_index] = prevvidsw;
 1621                 }
 1622         }
 1623         splx(s);
 1624 
 1625         return error;
 1626 }
 1627 
 1628 static int
 1629 vesa_mod_event(module_t mod, int type, void *data)
 1630 {
 1631         switch (type) {
 1632         case MOD_LOAD:
 1633                 return vesa_load();
 1634         case MOD_UNLOAD:
 1635                 return vesa_unload();
 1636         default:
 1637                 break;
 1638         }
 1639         return 0;
 1640 }
 1641 
 1642 static moduledata_t vesa_mod = {
 1643         "vesa",
 1644         vesa_mod_event,
 1645         NULL,
 1646 };
 1647 
 1648 DECLARE_MODULE(vesa, vesa_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
 1649 
 1650 #endif  /* VGA_NO_MODE_CHANGE */

Cache object: fe1e68ae9bf9197ed7d2c4eaa0d1d2f3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.