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

Cache object: 59128c1386c729c71d739e1b32b51ce8


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