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

Cache object: dd90cf5a47ad5b94c0144cbd38b6be3c


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