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

Cache object: 9e5eb3ccac7050f4ffe762a60c982417


[ 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.