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


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

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

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

    1 /*-
    2  * Copyright (c) 1998 Kazutaka YOKOTA and Michael Smith
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer as
   10  *    the first lines of this file unmodified.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 #include "vga.h"
   30 #include "opt_vga.h"
   31 #include "opt_vesa.h"
   32 #include "opt_vm86.h"
   33 #include "opt_fb.h"
   34 
   35 #ifdef VGA_NO_MODE_CHANGE
   36 #undef VESA
   37 #endif
   38 
   39 #if (NVGA > 0 && defined(VESA) && defined(VM86)) || defined(KLD_MODULE)
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/module.h>
   45 #include <sys/malloc.h>
   46 #include <vm/vm.h>
   47 #include <vm/pmap.h>
   48 
   49 #include <machine/console.h>
   50 #include <machine/md_var.h>
   51 #include <machine/vm86.h>
   52 #include <machine/pc/bios.h>
   53 #include <machine/pc/vesa.h>
   54 
   55 #include <dev/fb/fbreg.h>
   56 #include <dev/fb/vgareg.h>
   57 
   58 #ifndef __i386__
   59 #include <isa/isareg.h>
   60 #else
   61 #include <i386/isa/isa.h>
   62 #endif
   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 #if 0
   80 static void *vesa_state_buf = NULL;
   81 #endif
   82 
   83 /* VESA functions */
   84 static int                      vesa_nop(void);
   85 static vi_probe_t               vesa_probe;
   86 static vi_init_t                vesa_init;
   87 static vi_get_info_t            vesa_get_info;
   88 static vi_query_mode_t          vesa_query_mode;
   89 static vi_set_mode_t            vesa_set_mode;
   90 static vi_save_font_t           vesa_save_font;
   91 static vi_load_font_t           vesa_load_font;
   92 static vi_show_font_t           vesa_show_font;
   93 static vi_save_palette_t        vesa_save_palette;
   94 static vi_load_palette_t        vesa_load_palette;
   95 static vi_set_border_t          vesa_set_border;
   96 static vi_save_state_t          vesa_save_state;
   97 static vi_load_state_t          vesa_load_state;
   98 static vi_set_win_org_t         vesa_set_origin;
   99 static vi_read_hw_cursor_t      vesa_read_hw_cursor;
  100 static vi_set_hw_cursor_t       vesa_set_hw_cursor;
  101 static vi_set_hw_cursor_shape_t vesa_set_hw_cursor_shape;
  102 static vi_mmap_t                vesa_mmap;
  103 static vi_diag_t                vesa_diag;
  104 static struct vm86context       vesa_vmcontext;
  105 
  106 static video_switch_t vesavidsw = {
  107         vesa_probe,
  108         vesa_init,
  109         vesa_get_info,
  110         vesa_query_mode,
  111         vesa_set_mode,
  112         vesa_save_font,
  113         vesa_load_font,
  114         vesa_show_font,
  115         vesa_save_palette,
  116         vesa_load_palette,
  117         vesa_set_border,
  118         vesa_save_state,
  119         vesa_load_state,
  120         vesa_set_origin,
  121         vesa_read_hw_cursor,
  122         vesa_set_hw_cursor,
  123         vesa_set_hw_cursor_shape,
  124         (vi_blank_display_t *)vesa_nop,
  125         vesa_mmap,
  126         vesa_diag,
  127 };
  128 
  129 static video_switch_t *prevvidsw;
  130 
  131 /* VESA BIOS video modes */
  132 #define VESA_MAXMODES   64
  133 #define EOT             (-1)
  134 #define NA              (-2)
  135 
  136 static video_info_t vesa_vmode[VESA_MAXMODES + 1] = {
  137         { EOT, },
  138 };
  139 
  140 static int vesa_init_done = FALSE;
  141 static int has_vesa_bios = FALSE;
  142 static struct vesa_info *vesa_adp_info = NULL;
  143 static u_int16_t *vesa_vmodetab = NULL;
  144 static char *vesa_oemstr = NULL;
  145 static char *vesa_venderstr = NULL;
  146 static char *vesa_prodstr = NULL;
  147 static char *vesa_revstr = NULL;
  148 
  149 /* local macros and functions */
  150 #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
  151 
  152 static int int10_set_mode(int mode);
  153 static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode);
  154 static int vesa_bios_set_mode(int mode);
  155 static int vesa_bios_get_dac(void);
  156 static int vesa_bios_set_dac(int bits);
  157 static int vesa_bios_save_palette(int start, int colors, u_char *palette,
  158                                   int bits);
  159 static int vesa_bios_load_palette(int start, int colors, u_char *palette,
  160                                   int bits);
  161 #define STATE_SIZE      0
  162 #define STATE_SAVE      1
  163 #define STATE_LOAD      2
  164 #define STATE_HW        (1<<0)
  165 #define STATE_DATA      (1<<1)
  166 #define STATE_DAC       (1<<2)
  167 #define STATE_REG       (1<<3)
  168 #define STATE_MOST      (STATE_HW | STATE_DATA | STATE_REG)
  169 #define STATE_ALL       (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
  170 static int vesa_bios_state_buf_size(void);
  171 static int vesa_bios_save_restore(int code, void *p, size_t size);
  172 static int vesa_bios_get_line_length(void);
  173 static int vesa_map_gen_mode_num(int type, int color, int mode);
  174 static int vesa_translate_flags(u_int16_t vflags);
  175 static void *vesa_fix_ptr(u_int32_t p, u_int16_t seg, u_int16_t off, 
  176                           u_char *buf);
  177 static int vesa_bios_init(void);
  178 static void vesa_clear_modes(video_info_t *info, int color);
  179 
  180 static void
  181 dump_buffer(u_char *buf, size_t len)
  182 {
  183     int i;
  184 
  185     for(i = 0; i < len;) {
  186         printf("%02x ", buf[i]);
  187         if ((++i % 16) == 0)
  188             printf("\n");
  189     }
  190 }
  191 
  192 /* INT 10 BIOS calls */
  193 static int
  194 int10_set_mode(int mode)
  195 {
  196         struct vm86frame vmf;
  197 
  198         bzero(&vmf, sizeof(vmf));
  199         vmf.vmf_eax = 0x0000 | mode;
  200         vm86_intcall(0x10, &vmf);
  201         return 0;
  202 }
  203 
  204 /* VESA BIOS calls */
  205 static int
  206 vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
  207 {
  208         struct vm86frame vmf;
  209         u_char *buf;
  210         int err;
  211 
  212         bzero(&vmf, sizeof(vmf));
  213         vmf.vmf_eax = 0x4f01; 
  214         vmf.vmf_ecx = mode;
  215         buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  216         vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_di);
  217 
  218         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  219         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  220                 return 1;
  221         bcopy(buf, vmode, sizeof(*vmode));
  222         return 0;
  223 }
  224 
  225 static int
  226 vesa_bios_set_mode(int mode)
  227 {
  228         struct vm86frame vmf;
  229         int err;
  230 
  231         bzero(&vmf, sizeof(vmf));
  232         vmf.vmf_eax = 0x4f02;
  233         vmf.vmf_ebx = mode;
  234         err = vm86_intcall(0x10, &vmf);
  235         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  236 }
  237 
  238 static int
  239 vesa_bios_get_dac(void)
  240 {
  241         struct vm86frame vmf;
  242         int err;
  243 
  244         bzero(&vmf, sizeof(vmf));
  245         vmf.vmf_eax = 0x4f08;
  246         vmf.vmf_ebx = 1;        /* get DAC width */
  247         err = vm86_intcall(0x10, &vmf);
  248         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  249                 return 6;       /* XXX */
  250         return ((vmf.vmf_ebx >> 8) & 0x00ff);
  251 }
  252 
  253 static int
  254 vesa_bios_set_dac(int bits)
  255 {
  256         struct vm86frame vmf;
  257         int err;
  258 
  259         bzero(&vmf, sizeof(vmf));
  260         vmf.vmf_eax = 0x4f08;
  261         vmf.vmf_ebx = (bits << 8);
  262         err = vm86_intcall(0x10, &vmf);
  263         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  264                 return 6;       /* XXX */
  265         return ((vmf.vmf_ebx >> 8) & 0x00ff);
  266 }
  267 
  268 static int
  269 vesa_bios_save_palette(int start, int colors, u_char *palette, int bits)
  270 {
  271         struct vm86frame vmf;
  272         u_char *p;
  273         int err;
  274         int i;
  275 
  276         bzero(&vmf, sizeof(vmf));
  277         vmf.vmf_eax = 0x4f09;
  278         vmf.vmf_ebx = 1;        /* get primary palette data */
  279         vmf.vmf_ecx = colors;
  280         vmf.vmf_edx = start;
  281         p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  282         vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);
  283 
  284         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  285         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  286                 return 1;
  287 
  288         bits = 8 - bits;
  289         for (i = 0; i < colors; ++i) {
  290                 palette[i*3]     = p[i*4 + 2] << bits;
  291                 palette[i*3 + 1] = p[i*4 + 1] << bits;
  292                 palette[i*3 + 2] = p[i*4] << bits;
  293         }
  294         return 0;
  295 }
  296 
  297 static int
  298 vesa_bios_load_palette(int start, int colors, u_char *palette, int bits)
  299 {
  300         struct vm86frame vmf;
  301         u_char *p;
  302         int err;
  303         int i;
  304 
  305         p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  306         bits = 8 - bits;
  307         for (i = 0; i < colors; ++i) {
  308                 p[i*4]     = palette[i*3 + 2] >> bits;
  309                 p[i*4 + 1] = palette[i*3 + 1] >> bits;
  310                 p[i*4 + 2] = palette[i*3] >> bits;
  311                 p[i*4 + 3] = 0;
  312         }
  313 
  314         bzero(&vmf, sizeof(vmf));
  315         vmf.vmf_eax = 0x4f09;
  316         vmf.vmf_ebx = 0;        /* set primary palette data */
  317         vmf.vmf_ecx = colors;
  318         vmf.vmf_edx = start;
  319         vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);
  320 
  321         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  322         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  323 }
  324 
  325 static int
  326 vesa_bios_state_buf_size(void)
  327 {
  328         struct vm86frame vmf;
  329         int err;
  330 
  331         bzero(&vmf, sizeof(vmf));
  332         vmf.vmf_eax = 0x4f04; 
  333         vmf.vmf_ecx = STATE_MOST;
  334         vmf.vmf_edx = STATE_SIZE;
  335         err = vm86_intcall(0x10, &vmf);
  336         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  337                 return 0;
  338         return vmf.vmf_bx*64;
  339 }
  340 
  341 static int
  342 vesa_bios_save_restore(int code, void *p, size_t size)
  343 {
  344         struct vm86frame vmf;
  345         u_char *buf;
  346         int err;
  347 
  348         bzero(&vmf, sizeof(vmf));
  349         vmf.vmf_eax = 0x4f04; 
  350         vmf.vmf_ecx = STATE_MOST;
  351         vmf.vmf_edx = code;     /* STATE_SAVE/STATE_LOAD */
  352         buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
  353         vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_di);
  354         bcopy(p, buf, size);
  355 
  356         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  357         return ((err != 0) || (vmf.vmf_ax != 0x4f));
  358 }
  359 
  360 static int
  361 vesa_bios_get_line_length(void)
  362 {
  363         struct vm86frame vmf;
  364         int err;
  365 
  366         bzero(&vmf, sizeof(vmf));
  367         vmf.vmf_eax = 0x4f06; 
  368         vmf.vmf_ebx = 1;        /* get scan line length */
  369         err = vm86_intcall(0x10, &vmf);
  370         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  371                 return -1;
  372         return vmf.vmf_bx;      /* line length in bytes */
  373 }
  374 
  375 /* map a generic video mode to a known mode */
  376 static int
  377 vesa_map_gen_mode_num(int type, int color, int mode)
  378 {
  379     static struct {
  380         int from;
  381         int to;
  382     } mode_map[] = {
  383         { M_TEXT_132x25, M_VESA_C132x25 },
  384         { M_TEXT_132x43, M_VESA_C132x43 },
  385         { M_TEXT_132x50, M_VESA_C132x50 },
  386         { M_TEXT_132x60, M_VESA_C132x60 },
  387     };
  388     int i;
  389 
  390     for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
  391         if (mode_map[i].from == mode)
  392             return mode_map[i].to;
  393     }
  394     return mode;
  395 }
  396 
  397 static int
  398 vesa_translate_flags(u_int16_t vflags)
  399 {
  400         static struct {
  401                 u_int16_t mask;
  402                 int set;
  403                 int reset;
  404         } ftable[] = {
  405                 { V_MODECOLOR, V_INFO_COLOR, 0 },
  406                 { V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 },
  407                 { V_MODELFB, V_INFO_LINEAR, 0 },
  408         };
  409         int flags;
  410         int i;
  411 
  412         for (flags = 0, i = 0; i < sizeof(ftable)/sizeof(ftable[0]); ++i) {
  413                 flags |= (vflags & ftable[i].mask) ? 
  414                          ftable[i].set : ftable[i].reset;
  415         }
  416         return flags;
  417 }
  418 
  419 static void
  420 *vesa_fix_ptr(u_int32_t p, u_int16_t seg, u_int16_t off, u_char *buf)
  421 {
  422         if (p == 0)
  423                 return NULL;
  424         if (((p >> 16) == seg) && ((p & 0xffff) >= off))
  425                 return (void *)(buf + ((p & 0xffff) - off));
  426         else {
  427                 p = BIOS_SADDRTOLADDR(p);
  428                 return (void *)BIOS_PADDRTOVADDR(p);
  429         }
  430 }
  431 
  432 static int
  433 vesa_bios_init(void)
  434 {
  435         static u_char buf[512];
  436         struct vm86frame vmf;
  437         struct vesa_mode vmode;
  438         u_char *vmbuf;
  439         int modes;
  440         int err;
  441         int i;
  442 
  443         if (vesa_init_done)
  444                 return 0;
  445 
  446         has_vesa_bios = FALSE;
  447         vesa_adp_info = NULL;
  448         vesa_vmode[0].vi_mode = EOT;
  449 
  450         vmbuf = (u_char *)vm86_addpage(&vesa_vmcontext, 1, 0);
  451         bzero(&vmf, sizeof(vmf));       /* paranoia */
  452         bcopy("VBE2", vmbuf, 4);        /* try for VBE2 data */
  453         vmf.vmf_eax = 0x4f00;
  454         vm86_getptr(&vesa_vmcontext, (vm_offset_t)vmbuf, &vmf.vmf_es, &vmf.vmf_di);
  455 
  456         err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
  457         if ((err != 0) || (vmf.vmf_ax != 0x4f) || bcmp("VESA", vmbuf, 4))
  458                 return 1;
  459         bcopy(vmbuf, buf, sizeof(buf));
  460         vesa_adp_info = (struct vesa_info *)buf;
  461         if (bootverbose) {
  462                 printf("VESA: information block\n");
  463                 dump_buffer(buf, 64);
  464         }
  465         if (vesa_adp_info->v_flags & V_NONVGA)
  466                 return 1;
  467 
  468         /* fix string ptrs */
  469         vesa_oemstr = (char *)vesa_fix_ptr(vesa_adp_info->v_oemstr,
  470                                            vmf.vmf_es, vmf.vmf_di, buf);
  471         if (vesa_adp_info->v_version >= 0x0200) {
  472                 vesa_venderstr = 
  473                     (char *)vesa_fix_ptr(vesa_adp_info->v_venderstr,
  474                                          vmf.vmf_es, vmf.vmf_di, buf);
  475                 vesa_prodstr = 
  476                     (char *)vesa_fix_ptr(vesa_adp_info->v_prodstr,
  477                                          vmf.vmf_es, vmf.vmf_di, buf);
  478                 vesa_revstr = 
  479                     (char *)vesa_fix_ptr(vesa_adp_info->v_revstr,
  480                                          vmf.vmf_es, vmf.vmf_di, buf);
  481         }
  482 
  483         /* obtain video mode information */
  484         vesa_vmode[0].vi_mode = EOT;
  485         vesa_vmodetab = (u_int16_t *)vesa_fix_ptr(vesa_adp_info->v_modetable,
  486                                                   vmf.vmf_es, vmf.vmf_di, buf);
  487         if (vesa_vmodetab == NULL)
  488                 return 1;
  489         for (i = 0, modes = 0; 
  490                 (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1))
  491                 && (vesa_vmodetab[i] != 0xffff); ++i) {
  492                 if (modes >= VESA_MAXMODES)
  493                         break;
  494                 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
  495                         continue;
  496 
  497                 /* reject unsupported modes */
  498 #if 0
  499                 if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO 
  500                                         | V_MODENONVGA))
  501                     != (V_MODESUPP | V_MODEOPTINFO))
  502                         continue;
  503 #else
  504                 if ((vmode.v_modeattr & (V_MODEOPTINFO | V_MODENONVGA))
  505                     != (V_MODEOPTINFO))
  506                         continue;
  507 #endif
  508 
  509                 /* copy some fields */
  510                 bzero(&vesa_vmode[modes], sizeof(vesa_vmode[modes]));
  511                 vesa_vmode[modes].vi_mode = vesa_vmodetab[i];
  512                 vesa_vmode[modes].vi_width = vmode.v_width;
  513                 vesa_vmode[modes].vi_height = vmode.v_height;
  514                 vesa_vmode[modes].vi_depth = vmode.v_bpp;
  515                 vesa_vmode[modes].vi_planes = vmode.v_planes;
  516                 vesa_vmode[modes].vi_cwidth = vmode.v_cwidth;
  517                 vesa_vmode[modes].vi_cheight = vmode.v_cheight;
  518                 vesa_vmode[modes].vi_window = (u_int)vmode.v_waseg << 4;
  519                 /* XXX window B */
  520                 vesa_vmode[modes].vi_window_size = vmode.v_wsize*1024;
  521                 vesa_vmode[modes].vi_window_gran = vmode.v_wgran*1024;
  522                 vesa_vmode[modes].vi_buffer = vmode.v_lfb;
  523                 /* XXX */
  524                 if (vmode.v_offscreen > vmode.v_lfb)
  525                         vesa_vmode[modes].vi_buffer_size
  526                                 = vmode.v_offscreen - vmode.v_lfb;
  527                 else
  528                         vesa_vmode[modes].vi_buffer_size = vmode.v_offscreen;
  529                 /* pixel format, memory model... */
  530 
  531                 vesa_vmode[modes].vi_flags 
  532                         = vesa_translate_flags(vmode.v_modeattr) | V_INFO_VESA;
  533                 ++modes;
  534         }
  535         vesa_vmode[modes].vi_mode = EOT;
  536         if (bootverbose)
  537                 printf("VESA: %d mode(s) found\n", modes);
  538 
  539         has_vesa_bios = (modes > 0);
  540         return (has_vesa_bios ? 0 : 1);
  541 }
  542 
  543 static void
  544 vesa_clear_modes(video_info_t *info, int color)
  545 {
  546         while (info->vi_mode != EOT) {
  547                 if ((info->vi_flags & V_INFO_COLOR) != color)
  548                         info->vi_mode = NA;
  549                 ++info;
  550         }
  551 }
  552 
  553 /* entry points */
  554 
  555 static int
  556 vesa_configure(int flags)
  557 {
  558         video_adapter_t *adp;
  559         int adapters;
  560         int error;
  561         int i;
  562 
  563         if (vesa_init_done)
  564                 return 0;
  565         if (flags & VIO_PROBE_ONLY)
  566                 return 0;               /* XXX */
  567 
  568         /*
  569          * If the VESA module has already been loaded, abort loading 
  570          * the module this time.
  571          */
  572         for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) {
  573                 if (adp->va_flags & V_ADP_VESA)
  574                         return ENXIO;
  575                 if (adp->va_type == KD_VGA)
  576                         break;
  577         }
  578         /*
  579          * The VGA adapter is not found.  This is because either 
  580          * 1) the VGA driver has not been initialized, or 2) the VGA card
  581          * is not present.  If 1) is the case, we shall defer
  582          * initialization for now and try again later.
  583          */
  584         if (adp == NULL) {
  585                 vga_sub_configure = vesa_configure;
  586                 return ENODEV;
  587         }
  588 
  589         /* count number of registered adapters */
  590         for (++i; vid_get_adapter(i) != NULL; ++i)
  591                 ;
  592         adapters = i;
  593 
  594         /* call VESA BIOS */
  595         vesa_adp = adp;
  596         if (vesa_bios_init()) {
  597                 vesa_adp = NULL;
  598                 return ENXIO;
  599         }
  600         vesa_adp->va_flags |= V_ADP_VESA;
  601 
  602         /* remove conflicting modes if we have more than one adapter */
  603         if (adapters > 1) {
  604                 vesa_clear_modes(vesa_vmode,
  605                                  (vesa_adp->va_flags & V_ADP_COLOR) ? 
  606                                      V_INFO_COLOR : 0);
  607         }
  608 
  609         if ((error = vesa_load_ioctl()) == 0) {
  610                 prevvidsw = vidsw[vesa_adp->va_index];
  611                 vidsw[vesa_adp->va_index] = &vesavidsw;
  612                 vesa_init_done = TRUE;
  613         } else {
  614                 vesa_adp = NULL;
  615                 return error;
  616         }
  617 
  618         return 0;
  619 }
  620 
  621 static int
  622 vesa_nop(void)
  623 {
  624         return 0;
  625 }
  626 
  627 static int
  628 vesa_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
  629 {
  630         return (*prevvidsw->probe)(unit, adpp, arg, flags);
  631 }
  632 
  633 static int
  634 vesa_init(int unit, video_adapter_t *adp, int flags)
  635 {
  636         return (*prevvidsw->init)(unit, adp, flags);
  637 }
  638 
  639 static int
  640 vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info)
  641 {
  642         int i;
  643 
  644         if ((*prevvidsw->get_info)(adp, mode, info) == 0)
  645                 return 0;
  646 
  647         if (adp != vesa_adp)
  648                 return 1;
  649 
  650         mode = vesa_map_gen_mode_num(vesa_adp->va_type, 
  651                                      vesa_adp->va_flags & V_ADP_COLOR, mode);
  652         for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
  653                 if (vesa_vmode[i].vi_mode == NA)
  654                         continue;
  655                 if (vesa_vmode[i].vi_mode == mode) {
  656                         *info = vesa_vmode[i];
  657                         return 0;
  658                 }
  659         }
  660         return 1;
  661 }
  662 
  663 static int
  664 vesa_query_mode(video_adapter_t *adp, video_info_t *info)
  665 {
  666         int i;
  667 
  668         if ((*prevvidsw->query_mode)(adp, info) == 0)
  669                 return 0;
  670         if (adp != vesa_adp)
  671                 return ENODEV;
  672 
  673         for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
  674                 if ((info->vi_width != 0)
  675                     && (info->vi_width != vesa_vmode[i].vi_width))
  676                         continue;
  677                 if ((info->vi_height != 0)
  678                     && (info->vi_height != vesa_vmode[i].vi_height))
  679                         continue;
  680                 if ((info->vi_cwidth != 0)
  681                     && (info->vi_cwidth != vesa_vmode[i].vi_cwidth))
  682                         continue;
  683                 if ((info->vi_cheight != 0)
  684                     && (info->vi_cheight != vesa_vmode[i].vi_cheight))
  685                         continue;
  686                 if ((info->vi_depth != 0)
  687                     && (info->vi_depth != vesa_vmode[i].vi_depth))
  688                         continue;
  689                 if ((info->vi_planes != 0)
  690                     && (info->vi_planes != vesa_vmode[i].vi_planes))
  691                         continue;
  692                 /* pixel format, memory model */
  693                 if ((info->vi_flags != 0)
  694                     && (info->vi_flags != vesa_vmode[i].vi_flags))
  695                         continue;
  696                 *info = vesa_vmode[i];
  697                 return 0;
  698         }
  699         return ENODEV;
  700 }
  701 
  702 static int
  703 vesa_set_mode(video_adapter_t *adp, int mode)
  704 {
  705         video_info_t info;
  706         size_t len;
  707 
  708         if (adp != vesa_adp)
  709                 return (*prevvidsw->set_mode)(adp, mode);
  710 
  711         mode = vesa_map_gen_mode_num(vesa_adp->va_type, 
  712                                      vesa_adp->va_flags & V_ADP_COLOR, mode);
  713 #if VESA_DEBUG > 0
  714         printf("VESA: set_mode(): %d(%x) -> %d(%x)\n",
  715                 vesa_adp->va_mode, vesa_adp->va_mode, mode, mode);
  716 #endif
  717         /* 
  718          * If the current mode is a VESA mode and the new mode is not,
  719          * restore the state of the adapter first, so that non-standard, 
  720          * extended SVGA registers are set to the state compatible with
  721          * the standard VGA modes. Otherwise (*prevvidsw->set_mode)() 
  722          * may not be able to set up the new mode correctly.
  723          */
  724         if (VESA_MODE(vesa_adp->va_mode)) {
  725                 if ((*prevvidsw->get_info)(adp, mode, &info) == 0) {
  726                         int10_set_mode(vesa_adp->va_initial_bios_mode);
  727 #if 0
  728                         /* assert(vesa_state_buf != NULL); */
  729                         if ((vesa_state_buf == NULL)
  730                             || vesa_load_state(adp, vesa_state_buf))
  731                                 return 1;
  732                         free(vesa_state_buf, M_DEVBUF);
  733                         vesa_state_buf = NULL;
  734 #if VESA_DEBUG > 0
  735                         printf("VESA: restored\n");
  736 #endif
  737 #endif /* 0 */
  738                 }
  739                 /* 
  740                  * once (*prevvidsw->get_info)() succeeded, 
  741                  * (*prevvidsw->set_mode)() below won't fail...
  742                  */
  743         }
  744 
  745         /* we may not need to handle this mode after all... */
  746         if ((*prevvidsw->set_mode)(adp, mode) == 0)
  747                 return 0;
  748 
  749         /* is the new mode supported? */
  750         if (vesa_get_info(adp, mode, &info))
  751                 return 1;
  752         /* assert(VESA_MODE(mode)); */
  753 
  754 #if VESA_DEBUG > 0
  755         printf("VESA: about to set a VESA mode...\n");
  756 #endif
  757         /* 
  758          * If the current mode is not a VESA mode, save the current state
  759          * so that the adapter state can be restored later when a non-VESA
  760          * mode is to be set up. See above.
  761          */
  762 #if 0
  763         if (!VESA_MODE(vesa_adp->va_mode) && (vesa_state_buf == NULL)) {
  764                 len = vesa_save_state(adp, NULL, 0);
  765                 vesa_state_buf = malloc(len, M_DEVBUF, M_WAITOK);
  766                 if (vesa_save_state(adp, vesa_state_buf, len)) {
  767 #if VESA_DEBUG > 0
  768                         printf("VESA: state save failed! (len=%d)\n", len);
  769 #endif
  770                         free(vesa_state_buf, M_DEVBUF);
  771                         vesa_state_buf = NULL;
  772                         return 1;
  773                 }
  774 #if VESA_DEBUG > 0
  775                 printf("VESA: saved (len=%d)\n", len);
  776                 dump_buffer(vesa_state_buf, len);
  777 #endif
  778         }
  779 #endif /* 0 */
  780 
  781         if (vesa_bios_set_mode(mode))
  782                 return 1;
  783 
  784 #if VESA_DEBUG > 0
  785         printf("VESA: mode set!\n");
  786 #endif
  787         vesa_adp->va_mode = mode;
  788         vesa_adp->va_flags &= ~V_ADP_COLOR;
  789         vesa_adp->va_flags |= 
  790                 (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
  791         vesa_adp->va_crtc_addr =
  792                 (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
  793         vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
  794         vesa_adp->va_window_size = info.vi_window_size;
  795         vesa_adp->va_window_gran = info.vi_window_gran;
  796         if (info.vi_buffer_size == 0) {
  797                 vesa_adp->va_buffer = 0;
  798                 vesa_adp->va_buffer_size = 0;
  799         } else {
  800                 vesa_adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
  801                 vesa_adp->va_buffer_size = info.vi_buffer_size;
  802         }
  803         len = vesa_bios_get_line_length();
  804         if (len > 0) {
  805                 vesa_adp->va_line_width = len;
  806         } else if (info.vi_flags & V_INFO_GRAPHICS) {
  807                 switch (info.vi_depth/info.vi_planes) {
  808                 case 1:
  809                         vesa_adp->va_line_width = info.vi_width/8;
  810                         break;
  811                 case 2:
  812                         vesa_adp->va_line_width = info.vi_width/4;
  813                         break;
  814                 case 4:
  815                         vesa_adp->va_line_width = info.vi_width/2;
  816                         break;
  817                 case 8:
  818                 default: /* shouldn't happen */
  819                         vesa_adp->va_line_width = info.vi_width;
  820                         break;
  821                 }
  822         } else {
  823                 vesa_adp->va_line_width = info.vi_width;
  824         }
  825 #if VESA_DEBUG > 0
  826         printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n",
  827                info.vi_width, len, vesa_adp->va_line_width);
  828 #endif
  829         bcopy(&info, &vesa_adp->va_info, sizeof(vesa_adp->va_info));
  830 
  831         /* move hardware cursor out of the way */
  832         (*vidsw[vesa_adp->va_index]->set_hw_cursor)(vesa_adp, -1, -1);
  833 
  834         return 0;
  835 }
  836 
  837 static int
  838 vesa_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
  839                int ch, int count)
  840 {
  841         return (*prevvidsw->save_font)(adp, page, fontsize, data, ch, count);
  842 }
  843 
  844 static int
  845 vesa_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
  846                int ch, int count)
  847 {
  848         return (*prevvidsw->load_font)(adp, page, fontsize, data, ch, count);
  849 }
  850 
  851 static int
  852 vesa_show_font(video_adapter_t *adp, int page)
  853 {
  854         return (*prevvidsw->show_font)(adp, page);
  855 }
  856 
  857 static int
  858 vesa_save_palette(video_adapter_t *adp, u_char *palette)
  859 {
  860         int bits;
  861         int error;
  862 
  863         if ((adp == vesa_adp) && (vesa_adp_info->v_flags & V_DAC8)
  864             && VESA_MODE(adp->va_mode)) {
  865                 bits = vesa_bios_get_dac();
  866                 error = vesa_bios_save_palette(0, 256, palette, bits);
  867                 if (error == 0)
  868                         return 0;
  869                 if (bits != 6)
  870                         return error;
  871         }
  872 
  873         return (*prevvidsw->save_palette)(adp, palette);
  874 }
  875 
  876 static int
  877 vesa_load_palette(video_adapter_t *adp, u_char *palette)
  878 {
  879 #if notyet
  880         int bits;
  881         int error;
  882 
  883         if ((adp == vesa_adp) && (vesa_adp_info->v_flags & V_DAC8) 
  884             && VESA_MODE(adp->va_mode) && ((bits = vesa_bios_set_dac(8)) > 6)) {
  885                 error = vesa_bios_load_palette(0, 256, palette, bits);
  886                 if (error == 0)
  887                         return 0;
  888                 if (vesa_bios_set_dac(6) != 6)
  889                         return 1;
  890         }
  891 #endif /* notyet */
  892 
  893         return (*prevvidsw->load_palette)(adp, palette);
  894 }
  895 
  896 static int
  897 vesa_set_border(video_adapter_t *adp, int color)
  898 {
  899         return (*prevvidsw->set_border)(adp, color);
  900 }
  901 
  902 static int
  903 vesa_save_state(video_adapter_t *adp, void *p, size_t size)
  904 {
  905         if (adp != vesa_adp)
  906                 return (*prevvidsw->save_state)(adp, p, size);
  907 
  908         if (vesa_state_buf_size == 0)
  909                 vesa_state_buf_size = vesa_bios_state_buf_size();
  910         if (size == 0)
  911                 return (sizeof(int) + vesa_state_buf_size);
  912         else if (size < (sizeof(int) + vesa_state_buf_size))
  913                 return 1;
  914 
  915         ((adp_state_t *)p)->sig = V_STATE_SIG;
  916         bzero(((adp_state_t *)p)->regs, vesa_state_buf_size);
  917         return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, 
  918                                       vesa_state_buf_size);
  919 }
  920 
  921 static int
  922 vesa_load_state(video_adapter_t *adp, void *p)
  923 {
  924         if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG))
  925                 return (*prevvidsw->load_state)(adp, p);
  926 
  927         return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, 
  928                                       vesa_state_buf_size);
  929 }
  930 
  931 static int
  932 vesa_set_origin(video_adapter_t *adp, off_t offset)
  933 {
  934         struct vm86frame vmf;
  935         int err;
  936 
  937         /*
  938          * This function should return as quickly as possible to 
  939          * maintain good performance of the system. For this reason,
  940          * error checking is kept minimal and let the VESA BIOS to 
  941          * detect error.
  942          */
  943         if (adp != vesa_adp) 
  944                 return (*prevvidsw->set_win_org)(adp, offset);
  945 
  946         if (vesa_adp->va_window_gran == 0)
  947                 return 1;
  948         bzero(&vmf, sizeof(vmf));
  949         vmf.vmf_eax = 0x4f05; 
  950         vmf.vmf_ebx = 0;                /* WINDOW_A, XXX */
  951         vmf.vmf_edx = offset/vesa_adp->va_window_gran;
  952         err = vm86_intcall(0x10, &vmf); 
  953         if ((err != 0) || (vmf.vmf_ax != 0x4f))
  954                 return 1;
  955         bzero(&vmf, sizeof(vmf));
  956         vmf.vmf_eax = 0x4f05; 
  957         vmf.vmf_ebx = 1;                /* WINDOW_B, XXX */
  958         vmf.vmf_edx = offset/vesa_adp->va_window_gran;
  959         err = vm86_intcall(0x10, &vmf); 
  960         return 0;                       /* XXX */
  961 }
  962 
  963 static int
  964 vesa_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
  965 {
  966         return (*prevvidsw->read_hw_cursor)(adp, col, row);
  967 }
  968 
  969 static int
  970 vesa_set_hw_cursor(video_adapter_t *adp, int col, int row)
  971 {
  972         return (*prevvidsw->set_hw_cursor)(adp, col, row);
  973 }
  974 
  975 static int
  976 vesa_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
  977                          int celsize, int blink)
  978 {
  979         return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize,
  980                                                  blink);
  981 }
  982 
  983 static int
  984 vesa_mmap(video_adapter_t *adp, vm_offset_t offset)
  985 {
  986         return (*prevvidsw->mmap)(adp, offset);
  987 }
  988 
  989 static int
  990 vesa_diag(video_adapter_t *adp, int level)
  991 {
  992 #if VESA_DEBUG > 1
  993         struct vesa_mode vmode;
  994         int i;
  995 #endif
  996 
  997         if (adp != vesa_adp)
  998                 return 1;
  999 
 1000 #ifndef KLD_MODULE
 1001         /* call the previous handler first */
 1002         (*prevvidsw->diag)(adp, level);
 1003 #endif
 1004 
 1005         /* general adapter information */
 1006         printf("VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n", 
 1007                ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 
 1008                    + ((vesa_adp_info->v_version & 0x0f00) >> 8),
 1009                ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 
 1010                    + (vesa_adp_info->v_version & 0x000f),
 1011                vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags,
 1012                vesa_vmodetab, vesa_adp_info->v_modetable);
 1013         /* OEM string */
 1014         if (vesa_oemstr != NULL)
 1015                 printf("VESA: %s\n", vesa_oemstr);
 1016 
 1017         if (level <= 0)
 1018                 return 0;
 1019 
 1020         if (vesa_adp_info->v_version >= 0x0200) {
 1021                 /* vendor name */
 1022                 if (vesa_venderstr != NULL)
 1023                         printf("VESA: %s\n", vesa_venderstr);
 1024                 /* product name */
 1025                 if (vesa_prodstr != NULL)
 1026                         printf("VESA: %s\n", vesa_prodstr);
 1027                 /* product revision */
 1028                 if (vesa_revstr != NULL)
 1029                         printf("VESA: %s\n", vesa_revstr);
 1030         }
 1031 
 1032 #if VESA_DEBUG > 1
 1033         /* mode information */
 1034         for (i = 0;
 1035                 (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1))
 1036                 && (vesa_vmodetab[i] != 0xffff); ++i) {
 1037                 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
 1038                         continue;
 1039 
 1040                 /* print something for diagnostic purpose */
 1041                 printf("VESA: mode:0x%03x, flags:0x%04x", 
 1042                        vesa_vmodetab[i], vmode.v_modeattr);
 1043                 if (vmode.v_modeattr & V_MODEOPTINFO) {
 1044                         if (vmode.v_modeattr & V_MODEGRAPHICS) {
 1045                                 printf(", G %dx%dx%d %d, ", 
 1046                                        vmode.v_width, vmode.v_height,
 1047                                        vmode.v_bpp, vmode.v_planes);
 1048                         } else {
 1049                                 printf(", T %dx%d, ", 
 1050                                        vmode.v_width, vmode.v_height);
 1051                         }
 1052                         printf("font:%dx%d", 
 1053                                vmode.v_cwidth, vmode.v_cheight);
 1054                 }
 1055                 if (vmode.v_modeattr & V_MODELFB) {
 1056                         printf(", mem:%d, LFB:0x%x, off:0x%x", 
 1057                                vmode.v_memmodel, vmode.v_lfb, 
 1058                                vmode.v_offscreen);
 1059                 }
 1060                 printf("\n");
 1061                 printf("VESA: window A:0x%x (%x), window B:0x%x (%x), ",
 1062                        vmode.v_waseg, vmode.v_waattr,
 1063                        vmode.v_wbseg, vmode.v_wbattr);
 1064                 printf("size:%dk, gran:%dk\n",
 1065                        vmode.v_wsize, vmode.v_wgran);
 1066         }
 1067 #endif
 1068 
 1069         return 0;
 1070 }
 1071 
 1072 /* module loading */
 1073 
 1074 static int
 1075 vesa_load(void)
 1076 {
 1077         int error;
 1078         int s;
 1079 
 1080         if (vesa_init_done)
 1081                 return 0;
 1082 
 1083         /* locate a VGA adapter */
 1084         s = spltty();
 1085         vesa_adp = NULL;
 1086         error = vesa_configure(0);
 1087         splx(s);
 1088 
 1089 #ifdef KLD_MODULE
 1090         if (error == 0)
 1091                 vesa_diag(vesa_adp, bootverbose);
 1092 #endif
 1093 
 1094         return error;
 1095 }
 1096 
 1097 #ifdef KLD_MODULE
 1098 
 1099 static int
 1100 vesa_unload(void)
 1101 {
 1102         u_char palette[256*3];
 1103         int error;
 1104         int bits;
 1105         int s;
 1106 
 1107         /* if the adapter is currently in a VESA mode, don't unload */
 1108         if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode))
 1109                 return EBUSY;
 1110         /* 
 1111          * FIXME: if there is at least one vty which is in a VESA mode,
 1112          * we shouldn't be unloading! XXX
 1113          */
 1114 
 1115         s = spltty();
 1116         if ((error = vesa_unload_ioctl()) == 0) {
 1117                 if (vesa_adp != NULL) {
 1118                         if (vesa_adp_info->v_flags & V_DAC8)  {
 1119                                 bits = vesa_bios_get_dac();
 1120                                 if (bits > 6) {
 1121                                         vesa_bios_save_palette(0, 256,
 1122                                                                palette, bits);
 1123                                         vesa_bios_set_dac(6);
 1124                                         vesa_bios_load_palette(0, 256,
 1125                                                                palette, 6);
 1126                                 }
 1127                         }
 1128                         vesa_adp->va_flags &= ~V_ADP_VESA;
 1129                         vidsw[vesa_adp->va_index] = prevvidsw;
 1130                 }
 1131         }
 1132         splx(s);
 1133 
 1134         return error;
 1135 }
 1136 
 1137 static int
 1138 vesa_mod_event(module_t mod, int type, void *data)
 1139 {
 1140         switch (type) {
 1141         case MOD_LOAD:
 1142                 return vesa_load();
 1143         case MOD_UNLOAD:
 1144                 return vesa_unload();
 1145         default:
 1146                 break;
 1147         }
 1148         return 0;
 1149 }
 1150 
 1151 static moduledata_t vesa_mod = {
 1152         "vesa",
 1153         vesa_mod_event,
 1154         NULL,
 1155 };
 1156 
 1157 DECLARE_MODULE(vesa, vesa_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
 1158 
 1159 #else /* KLD_MODULE */
 1160 
 1161 SYSINIT(vesa, SI_SUB_DRIVERS, SI_ORDER_MIDDLE,
 1162         (void (*)(void *))vesa_load, NULL);
 1163 
 1164 #endif /* KLD_MODULE */
 1165 
 1166 #endif /* (NVGA > 0 && VESA && VM86) || KLD_MODULE */

Cache object: 299c6d3d642736cf8f8ab864cac308d3


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