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/ic/vga.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 /* $NetBSD: vga.c,v 1.120 2021/08/07 16:19:12 thorpej Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
    5  * All rights reserved.
    6  *
    7  * Author: Chris G. Demetriou
    8  *
    9  * Permission to use, copy, modify and distribute this software and
   10  * its documentation is hereby granted, provided that both the copyright
   11  * notice and this permission notice appear in all copies of the
   12  * software, derivative works or modified versions, and any portions
   13  * thereof, and that both notices appear in supporting documentation.
   14  *
   15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   17  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   18  *
   19  * Carnegie Mellon requests users of this software to return to
   20  *
   21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   22  *  School of Computer Science
   23  *  Carnegie Mellon University
   24  *  Pittsburgh PA 15213-3890
   25  *
   26  * any improvements or extensions that they make and grant Carnegie the
   27  * rights to redistribute these changes.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __KERNEL_RCSID(0, "$NetBSD: vga.c,v 1.120 2021/08/07 16:19:12 thorpej Exp $");
   32 
   33 #include "opt_vga.h"
   34 /* for WSCONS_SUPPORT_PCVTFONTS */
   35 #include "opt_wsdisplay_compat.h"
   36 /* for WSDISPLAY_CUSTOM_BORDER */
   37 #include "opt_wsdisplay_border.h"
   38 /* for WSDISPLAY_CUSTOM_OUTPUT */
   39 #include "opt_wsmsgattrs.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/callout.h>
   44 #include <sys/kernel.h>
   45 #include <sys/device.h>
   46 #include <sys/malloc.h>
   47 #include <sys/queue.h>
   48 #include <sys/bus.h>
   49 
   50 #include <dev/ic/mc6845reg.h>
   51 #include <dev/ic/pcdisplayvar.h>
   52 #include <dev/ic/vgareg.h>
   53 #include <dev/ic/vgavar.h>
   54 
   55 #include <dev/wscons/wsdisplayvar.h>
   56 #include <dev/wscons/wsconsio.h>
   57 #include <dev/wscons/unicode.h>
   58 #include <dev/wsfont/wsfont.h>
   59 
   60 #include <dev/ic/pcdisplay.h>
   61 
   62 int vga_no_builtinfont = 0;
   63 
   64 static struct wsdisplay_font _vga_builtinfont = {
   65         "builtin",                      /* typeface name */
   66         0,                              /* firstchar */
   67         256,                            /* numbers */
   68         WSDISPLAY_FONTENC_IBM,          /* encoding */
   69         8,                              /* width */
   70         16,                             /* height */
   71         1,                              /* stride */
   72         WSDISPLAY_FONTORDER_L2R,        /* bit order */
   73         0,                              /* byte order */
   74         NULL                            /* data */
   75 };
   76 
   77 struct egavga_font {
   78         struct wsdisplay_font *wsfont;
   79         int cookie; /* wsfont handle, -1 invalid */
   80         int slot; /* in adapter RAM */
   81         int usecount;
   82         TAILQ_ENTRY(egavga_font) next; /* LRU queue */
   83 };
   84 
   85 static struct egavga_font vga_builtinfont = {
   86         .wsfont = &_vga_builtinfont,
   87         .cookie = -1,
   88         .slot = 0,
   89 };
   90 
   91 #ifdef VGA_CONSOLE_SCREENTYPE
   92 static struct egavga_font vga_consolefont;
   93 #endif
   94 
   95 struct vgascreen {
   96         struct pcdisplayscreen pcs;
   97 
   98         LIST_ENTRY(vgascreen) next;
   99 
  100         struct vga_config *cfg;
  101 
  102         /* videostate */
  103         struct egavga_font *fontset1, *fontset2;
  104         /* font data */
  105 
  106         int mindispoffset, maxdispoffset;
  107         int vga_rollover;
  108         int visibleoffset;
  109 };
  110 
  111 static int vgaconsole, vga_console_type, vga_console_attached;
  112 static struct vgascreen vga_console_screen;
  113 static struct vga_config vga_console_vc;
  114 
  115 static struct egavga_font *egavga_getfont(struct vga_config *, struct vgascreen *,
  116                                    const char *, int);
  117 static void egavga_unreffont(struct vga_config *, struct egavga_font *);
  118 
  119 static int vga_selectfont(struct vga_config *, struct vgascreen *, const char *,
  120                                    const char *);
  121 static void vga_init_screen(struct vga_config *, struct vgascreen *,
  122                      const struct wsscreen_descr *, int, long *);
  123 static void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t);
  124 static void vga_setfont(struct vga_config *, struct vgascreen *);
  125 
  126 static int vga_mapchar(void *, int, unsigned int *);
  127 static void vga_putchar(void *, int, int, u_int, long);
  128 static int vga_allocattr(void *, int, int, int, long *);
  129 static void vga_copyrows(void *, int, int, int);
  130 #ifdef WSDISPLAY_SCROLLSUPPORT
  131 static void vga_scroll (void *, void *, int);
  132 #endif
  133 
  134 const struct wsdisplay_emulops vga_emulops = {
  135         pcdisplay_cursor,
  136         vga_mapchar,
  137         vga_putchar,
  138         pcdisplay_copycols,
  139         pcdisplay_erasecols,
  140         vga_copyrows,
  141         pcdisplay_eraserows,
  142         vga_allocattr,
  143 #ifdef WSDISPLAY_CUSTOM_OUTPUT
  144         pcdisplay_replaceattr,
  145 #else
  146         NULL,
  147 #endif
  148 };
  149 
  150 /*
  151  * translate WS(=ANSI) color codes to standard pc ones
  152  */
  153 static const unsigned char fgansitopc[] = {
  154 #ifdef __alpha__
  155         /*
  156          * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
  157          * XXX We should probably not bother with this
  158          * XXX (reinitialize the palette registers).
  159          */
  160         FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
  161         FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
  162 #else
  163         FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
  164         FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
  165 #endif
  166 }, bgansitopc[] = {
  167 #ifdef __alpha__
  168         BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
  169         BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
  170 #else
  171         BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
  172         BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
  173 #endif
  174 };
  175 
  176 const struct wsscreen_descr vga_25lscreen = {
  177         "80x25", 80, 25,
  178         &vga_emulops,
  179         8, 16,
  180         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
  181         NULL,
  182 }, vga_25lscreen_mono = {
  183         "80x25", 80, 25,
  184         &vga_emulops,
  185         8, 16,
  186         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
  187         NULL,
  188 }, vga_25lscreen_bf = {
  189         "80x25bf", 80, 25,
  190         &vga_emulops,
  191         8, 16,
  192         WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
  193         NULL,
  194 }, vga_40lscreen = {
  195         "80x40", 80, 40,
  196         &vga_emulops,
  197         8, 10,
  198         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
  199         NULL,
  200 }, vga_40lscreen_mono = {
  201         "80x40", 80, 40,
  202         &vga_emulops,
  203         8, 10,
  204         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
  205         NULL,
  206 }, vga_40lscreen_bf = {
  207         "80x40bf", 80, 40,
  208         &vga_emulops,
  209         8, 10,
  210         WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
  211         NULL,
  212 }, vga_50lscreen = {
  213         "80x50", 80, 50,
  214         &vga_emulops,
  215         8, 8,
  216         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
  217         NULL,
  218 }, vga_50lscreen_mono = {
  219         "80x50", 80, 50,
  220         &vga_emulops,
  221         8, 8,
  222         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
  223         NULL,
  224 }, vga_50lscreen_bf = {
  225         "80x50bf", 80, 50,
  226         &vga_emulops,
  227         8, 8,
  228         WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
  229         NULL,
  230 }, vga_24lscreen = {
  231         "80x24", 80, 24,
  232         &vga_emulops,
  233         8, 16,
  234         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
  235         NULL,
  236 }, vga_24lscreen_mono = {
  237         "80x24", 80, 24,
  238         &vga_emulops,
  239         8, 16,
  240         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
  241         NULL,
  242 }, vga_24lscreen_bf = {
  243         "80x24bf", 80, 24,
  244         &vga_emulops,
  245         8, 16,
  246         WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
  247         NULL,
  248 };
  249 
  250 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
  251 
  252 const struct wsscreen_descr *_vga_scrlist[] = {
  253         &vga_25lscreen,
  254         &vga_25lscreen_bf,
  255         &vga_40lscreen,
  256         &vga_40lscreen_bf,
  257         &vga_50lscreen,
  258         &vga_50lscreen_bf,
  259         &vga_24lscreen,
  260         &vga_24lscreen_bf,
  261         /* XXX other formats, graphics screen? */
  262 }, *_vga_scrlist_mono[] = {
  263         &vga_25lscreen_mono,
  264         &vga_40lscreen_mono,
  265         &vga_50lscreen_mono,
  266         &vga_24lscreen_mono,
  267         /* XXX other formats, graphics screen? */
  268 };
  269 
  270 const struct wsscreen_list vga_screenlist = {
  271         sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
  272         _vga_scrlist
  273 }, vga_screenlist_mono = {
  274         sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
  275         _vga_scrlist_mono
  276 };
  277 
  278 static int      vga_ioctl(void *, void *, u_long, void *, int, struct lwp *);
  279 static paddr_t  vga_mmap(void *, void *, off_t, int);
  280 static int      vga_alloc_screen(void *, const struct wsscreen_descr *,
  281                                  void **, int *, int *, long *);
  282 static void     vga_free_screen(void *, void *);
  283 static int      vga_show_screen(void *, void *, int,
  284                                 void (*)(void *, int, int), void *);
  285 static int      vga_load_font(void *, void *, struct wsdisplay_font *);
  286 #ifdef WSDISPLAY_CUSTOM_BORDER
  287 static int      vga_getborder(struct vga_config *, u_int *);
  288 static int      vga_setborder(struct vga_config *, u_int);
  289 #endif /* WSDISPLAY_CUSTOM_BORDER */
  290 
  291 static void vga_doswitch(struct vga_config *);
  292 static void    vga_save_palette(struct vga_config *);
  293 static void    vga_restore_palette(struct vga_config *);
  294 
  295 
  296 const struct wsdisplay_accessops vga_accessops = {
  297         vga_ioctl,
  298         vga_mmap,
  299         vga_alloc_screen,
  300         vga_free_screen,
  301         vga_show_screen,
  302         vga_load_font,
  303         NULL,
  304 #ifdef WSDISPLAY_SCROLLSUPPORT
  305         vga_scroll,
  306 #else
  307         NULL,
  308 #endif
  309 };
  310 
  311 /*
  312  * We want at least ASCII 32..127 be present in the
  313  * first font slot.
  314  */
  315 #define vga_valid_primary_font(f) \
  316         (f->wsfont->encoding == WSDISPLAY_FONTENC_IBM || \
  317         f->wsfont->encoding == WSDISPLAY_FONTENC_ISO || \
  318         f->wsfont->encoding == WSDISPLAY_FONTENC_ISO2 || \
  319         f->wsfont->encoding == WSDISPLAY_FONTENC_ISO7 || \
  320         f->wsfont->encoding == WSDISPLAY_FONTENC_KOI8_R)
  321 
  322 static struct egavga_font *
  323 egavga_getfont(struct vga_config *vc, struct vgascreen *scr, const char *name,
  324                int primary)
  325 {
  326         struct egavga_font *f;
  327         int cookie;
  328         struct wsdisplay_font *wf;
  329 
  330         TAILQ_FOREACH(f, &vc->vc_fontlist, next) {
  331                 if (wsfont_matches(f->wsfont, name,
  332                     8, scr->pcs.type->fontheight, 0, WSFONT_FIND_BITMAP) &&
  333                     (!primary || vga_valid_primary_font(f))) {
  334 #ifdef VGAFONTDEBUG
  335                         if (scr != &vga_console_screen || vga_console_attached)
  336                                 printf("vga_getfont: %s already present\n",
  337                                     name ? name : "<default>");
  338 #endif
  339                         goto found;
  340                 }
  341         }
  342 
  343         cookie = wsfont_find(name, 8, scr->pcs.type->fontheight, 0,
  344             WSDISPLAY_FONTORDER_L2R, 0, WSFONT_FIND_BITMAP);
  345         /* XXX obey "primary" */
  346         if (cookie == -1) {
  347 #ifdef VGAFONTDEBUG
  348                 if (scr != &vga_console_screen || vga_console_attached)
  349                         printf("vga_getfont: %s not found\n",
  350                             name ? name : "<default>");
  351 #endif
  352                 return (0);
  353         }
  354 
  355         if (wsfont_lock(cookie, &wf))
  356                 return (0);
  357 
  358 #ifdef VGA_CONSOLE_SCREENTYPE
  359         if (scr == &vga_console_screen)
  360                 f = &vga_consolefont;
  361         else
  362 #endif
  363         f = malloc(sizeof(struct egavga_font), M_DEVBUF, M_WAITOK);
  364         f->wsfont = wf;
  365         f->cookie = cookie;
  366         f->slot = -1; /* not yet loaded */
  367         f->usecount = 0; /* incremented below */
  368         TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
  369 
  370 found:
  371         f->usecount++;
  372 #ifdef VGAFONTDEBUG
  373         if (scr != &vga_console_screen || vga_console_attached)
  374                 printf("vga_getfont: usecount=%d\n", f->usecount);
  375 #endif
  376         return (f);
  377 }
  378 
  379 static void
  380 egavga_unreffont(struct vga_config *vc, struct egavga_font *f)
  381 {
  382 
  383         f->usecount--;
  384 #ifdef VGAFONTDEBUG
  385         printf("vga_unreffont: usecount=%d\n", f->usecount);
  386 #endif
  387         if (f->usecount == 0 && f->cookie != -1) {
  388                 TAILQ_REMOVE(&vc->vc_fontlist, f, next);
  389                 if (f->slot != -1) {
  390                         KASSERT(vc->vc_fonts[f->slot] == f);
  391                         vc->vc_fonts[f->slot] = 0;
  392                 }
  393                 wsfont_unlock(f->cookie);
  394 #ifdef VGA_CONSOLE_SCREENTYPE
  395                 if (f != &vga_consolefont)
  396 #endif
  397                 free(f, M_DEVBUF);
  398         }
  399 }
  400 
  401 static int
  402 vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1,
  403                const char *name2)
  404 {
  405         const struct wsscreen_descr *type = scr->pcs.type;
  406         struct egavga_font *f1, *f2;
  407 
  408         f1 = egavga_getfont(vc, scr, name1, 1);
  409         if (!f1)
  410                 return (ENXIO);
  411 
  412         if (VGA_SCREEN_CANTWOFONTS(type) && name2) {
  413                 f2 = egavga_getfont(vc, scr, name2, 0);
  414                 if (!f2) {
  415                         egavga_unreffont(vc, f1);
  416                         return (ENXIO);
  417                 }
  418         } else
  419                 f2 = 0;
  420 
  421 #ifdef VGAFONTDEBUG
  422         if (scr != &vga_console_screen || vga_console_attached) {
  423                 printf("vga (%s): font1=%s (slot %d)", type->name,
  424                     f1->wsfont->name, f1->slot);
  425                 if (f2)
  426                         printf(", font2=%s (slot %d)",
  427                             f2->wsfont->name, f2->slot);
  428                 printf("\n");
  429         }
  430 #endif
  431         if (scr->fontset1)
  432                 egavga_unreffont(vc, scr->fontset1);
  433         scr->fontset1 = f1;
  434         if (scr->fontset2)
  435                 egavga_unreffont(vc, scr->fontset2);
  436         scr->fontset2 = f2;
  437         return (0);
  438 }
  439 
  440 static void
  441 vga_init_screen(struct vga_config *vc, struct vgascreen *scr,
  442                 const struct wsscreen_descr *type, int existing, long *attrp)
  443 {
  444         int cpos;
  445         int res __diagused;
  446 
  447         scr->cfg = vc;
  448         scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
  449         scr->pcs.type = type;
  450         scr->pcs.active = existing;
  451         scr->mindispoffset = 0;
  452         if (vc->vc_quirks & VGA_QUIRK_NOFASTSCROLL)
  453                 scr->maxdispoffset = 0;
  454         else
  455                 scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
  456 
  457         if (existing) {
  458                 vc->active = scr;
  459 
  460                 cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
  461                 cpos |= vga_6845_read(&vc->hdl, cursorl);
  462 
  463                 /* make sure we have a valid cursor position */
  464                 if (cpos < 0 || cpos >= type->nrows * type->ncols)
  465                         cpos = 0;
  466 
  467                 scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
  468                 scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
  469 
  470                 /* make sure we have a valid memory offset */
  471                 if (scr->pcs.dispoffset < scr->mindispoffset ||
  472                     scr->pcs.dispoffset > scr->maxdispoffset)
  473                         scr->pcs.dispoffset = scr->mindispoffset;
  474 
  475                 if (type != vc->currenttype) {
  476                         vga_setscreentype(&vc->hdl, type);
  477                         vc->currenttype = type;
  478                 }
  479         } else {
  480                 cpos = 0;
  481                 scr->pcs.dispoffset = scr->mindispoffset;
  482         }
  483 
  484         scr->pcs.visibleoffset = scr->pcs.dispoffset;
  485         scr->vga_rollover = 0;
  486 
  487         scr->pcs.cursorrow = cpos / type->ncols;
  488         scr->pcs.cursorcol = cpos % type->ncols;
  489         pcdisplay_cursor_init(&scr->pcs, existing);
  490 
  491 #ifdef __alpha__
  492         if (!vc->hdl.vh_mono)
  493                 /*
  494                  * DEC firmware uses a blue background.
  495                  * XXX These should be specified as kernel options for
  496                  * XXX alpha only, not hardcoded here (which is wrong
  497                  * XXX anyway because the emulation layer will assume
  498                  * XXX the default attribute is white on black).
  499                  */
  500                 res = vga_allocattr(scr, WSCOL_WHITE, WSCOL_BLUE,
  501                     WSATTR_WSCOLORS, attrp);
  502         else
  503 #endif
  504         res = vga_allocattr(scr, 0, 0, 0, attrp);
  505 #ifdef DIAGNOSTIC
  506         if (res)
  507                 panic("vga_init_screen: attribute botch");
  508 #endif
  509 
  510         scr->pcs.mem = NULL;
  511 
  512         scr->fontset1 = scr->fontset2 = 0;
  513         if (vga_selectfont(vc, scr, 0, 0)) {
  514                 if (scr == &vga_console_screen)
  515                         panic("vga_init_screen: no font");
  516                 else
  517                         printf("vga_init_screen: no font\n");
  518         }
  519         if (existing)
  520                 vga_setfont(vc, scr);
  521 
  522         vc->nscreens++;
  523         LIST_INSERT_HEAD(&vc->screens, scr, next);
  524 }
  525 
  526 static void
  527 vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt)
  528 {
  529         struct vga_handle *vh = &vc->hdl;
  530         uint8_t mor;
  531         int i;
  532 
  533         vh->vh_iot = iot;
  534         vh->vh_memt = memt;
  535 
  536         if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
  537                 panic("vga_init: couldn't map vga io");
  538 
  539         /* read "misc output register" */
  540         mor = vga_raw_read(vh, VGA_MISC_DATAR);
  541         vh->vh_mono = !(mor & 1);
  542 
  543         if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
  544             &vh->vh_ioh_6845))
  545                 panic("vga_init: couldn't map 6845 io");
  546 
  547         if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 
  548             BUS_SPACE_MAP_CACHEABLE, &vh->vh_allmemh))
  549                 panic("vga_init: couldn't map memory");
  550 
  551         if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
  552             (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, &vh->vh_memh))
  553                 panic("vga_init: mem subrange failed");
  554 
  555         vc->nscreens = 0;
  556         LIST_INIT(&vc->screens);
  557         vc->active = NULL;
  558         vc->currenttype = vh->vh_mono ? &vga_25lscreen_mono : &vga_25lscreen;
  559         callout_init(&vc->vc_switch_callout, 0);
  560 
  561         wsfont_init();
  562         if (vga_no_builtinfont) {
  563                 struct wsdisplay_font *wf;
  564                 int cookie;
  565 
  566                 cookie = wsfont_find(NULL, 8, 16, 0,
  567                      WSDISPLAY_FONTORDER_L2R, 0, WSFONT_FIND_BITMAP);
  568                 if (cookie == -1 || wsfont_lock(cookie, &wf))
  569                         panic("vga_init: can't load console font");
  570                 vga_loadchars(&vc->hdl, 0, wf->firstchar, wf->numchars,
  571                     wf->fontheight, wf->data);
  572                 vga_builtinfont.wsfont = wf;
  573                 vga_builtinfont.cookie = cookie;
  574                 vga_builtinfont.slot = 0;
  575         }
  576         vc->vc_fonts[0] = &vga_builtinfont;
  577         for (i = 1; i < 8; i++)
  578                 vc->vc_fonts[i] = 0;
  579         TAILQ_INIT(&vc->vc_fontlist);
  580         TAILQ_INSERT_HEAD(&vc->vc_fontlist, &vga_builtinfont, next);
  581 
  582         vc->currentfontset1 = vc->currentfontset2 = 0;
  583 
  584         if (!vh->vh_mono && (u_int)WSDISPLAY_BORDER_COLOR < sizeof(fgansitopc))
  585                 _vga_attr_write(vh, VGA_ATC_OVERSCAN,
  586                                 fgansitopc[WSDISPLAY_BORDER_COLOR]);
  587         vga_save_palette(vc);
  588 }
  589 
  590 void
  591 vga_common_attach(struct vga_softc *sc, bus_space_tag_t iot,
  592                   bus_space_tag_t memt, int type, int quirks,
  593                   const struct vga_funcs *vf)
  594 {
  595         int console;
  596         struct vga_config *vc;
  597         struct wsemuldisplaydev_attach_args aa;
  598 
  599         console = vga_is_console(iot, type);
  600 
  601         if (console) {
  602                 vc = &vga_console_vc;
  603                 vga_console_attached = 1;
  604         } else {
  605                 vc = malloc(sizeof(struct vga_config), M_DEVBUF, M_WAITOK);
  606                 vga_init(vc, iot, memt);
  607         }
  608 
  609         if (quirks & VGA_QUIRK_ONEFONT) {
  610                 vc->vc_nfontslots = 1;
  611 #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  612                 /*
  613                  * XXX maybe invalidate font in slot > 0, but this can
  614                  * only be happen with VGA_CONSOLE_SCREENTYPE, and then
  615                  * we require VGA_CONSOLE_ATI_BROKEN_FONTSEL anyway.
  616                  */
  617 #endif
  618         } else {
  619                 vc->vc_nfontslots = 8;
  620 #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  621                 /*
  622                  * XXX maybe validate builtin font shifted to slot 1 if
  623                  * slot 0 got overwritten because of VGA_CONSOLE_SCREENTYPE,
  624                  * but it will be reloaded anyway if needed.
  625                  */
  626 #endif
  627         }
  628 
  629         /*
  630          * Save the builtin font to memory. In case it got overwritten
  631          * in console initialization, use the copy in slot 1.
  632          */
  633 #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  634 #define BUILTINFONTLOC (vga_builtinfont.slot == -1 ? 1 : 0)
  635 #else
  636         KASSERT(vga_builtinfont.slot == 0);
  637 #define BUILTINFONTLOC (0)
  638 #endif
  639         if (!vga_no_builtinfont) {
  640                 char *data =
  641                     malloc(256 * vga_builtinfont.wsfont->fontheight,
  642                     M_DEVBUF, M_WAITOK);
  643                 vga_readoutchars(&vc->hdl, BUILTINFONTLOC, 0, 256,
  644                     vga_builtinfont.wsfont->fontheight, data);
  645                 vga_builtinfont.wsfont->data = data;
  646         }
  647 
  648         vc->vc_type = type;
  649         vc->vc_funcs = vf;
  650         vc->vc_quirks = quirks;
  651 
  652         sc->sc_vc = vc;
  653         vc->softc = sc;
  654 
  655         aa.console = console;
  656         aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
  657         aa.accessops = &vga_accessops;
  658         aa.accesscookie = vc;
  659 
  660         config_found(sc->sc_dev, &aa, wsemuldisplaydevprint,
  661             CFARGS(.iattr = "wsemuldisplaydev"));
  662 }
  663 
  664 int
  665 vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
  666 {
  667         long defattr;
  668         const struct wsscreen_descr *scr;
  669 
  670         if (check && !vga_common_probe(iot, memt))
  671                 return (ENXIO);
  672 
  673         /* set up bus-independent VGA configuration */
  674         vga_init(&vga_console_vc, iot, memt);
  675 #ifdef VGA_CONSOLE_SCREENTYPE
  676         scr = wsdisplay_screentype_pick(vga_console_vc.hdl.vh_mono ?
  677             &vga_screenlist_mono : &vga_screenlist, VGA_CONSOLE_SCREENTYPE);
  678         if (!scr)
  679                 panic("vga_cnattach: invalid screen type");
  680 #else
  681         scr = vga_console_vc.currenttype;
  682 #endif
  683 #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  684         /*
  685          * On some (most/all?) ATI cards, only font slot 0 is usable.
  686          * vga_init_screen() might need font slot 0 for a non-default
  687          * console font, so save the builtin VGA font to another font slot.
  688          * The attach() code will take care later.
  689          */
  690         vga_console_vc.vc_quirks |= VGA_QUIRK_ONEFONT; /* redundant */
  691         vga_copyfont01(&vga_console_vc.hdl);
  692         vga_console_vc.vc_nfontslots = 1;
  693 #else
  694         vga_console_vc.vc_nfontslots = 8;
  695 #endif
  696 #ifdef notdef
  697         /* until we know better, assume "fast scrolling" does not work */
  698         vga_console_vc.vc_quirks |= VGA_QUIRK_NOFASTSCROLL;
  699 #endif
  700 
  701         vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
  702 
  703         wsdisplay_cnattach(scr, &vga_console_screen,
  704             vga_console_screen.pcs.cursorcol,
  705             vga_console_screen.pcs.cursorrow, defattr);
  706 
  707         vgaconsole = 1;
  708         vga_console_type = type;
  709         return (0);
  710 }
  711 
  712 int
  713 vga_cndetach(void)
  714 {
  715         struct vga_config *vc;
  716         struct vga_handle *vh;
  717 
  718         vc = &vga_console_vc;
  719         vh = &vc->hdl;
  720 
  721         if (vgaconsole) {
  722                 wsdisplay_cndetach();
  723 
  724                 bus_space_unmap(vh->vh_iot, vh->vh_ioh_vga, 0x10);
  725                 bus_space_unmap(vh->vh_iot, vh->vh_ioh_6845, 0x10);
  726                 bus_space_unmap(vh->vh_memt, vh->vh_allmemh, 0x20000);
  727 
  728                 vga_console_attached = 0;
  729                 vgaconsole = 0;
  730 
  731                 return 1;
  732         }
  733 
  734         return 0;
  735 }
  736 
  737 int
  738 vga_is_console(bus_space_tag_t iot, int type)
  739 {
  740         if (vgaconsole &&
  741             !vga_console_attached &&
  742             bus_space_is_equal(iot, vga_console_vc.hdl.vh_iot) &&
  743             (vga_console_type == -1 || (type == vga_console_type)))
  744                 return (1);
  745         return (0);
  746 }
  747 
  748 static int
  749 vga_get_video(struct vga_config *vc)
  750 {
  751 
  752         return (vga_ts_read(&vc->hdl, mode) & VGA_TS_MODE_BLANK) == 0;
  753 }
  754 
  755 static void
  756 vga_set_video(struct vga_config *vc, int state)
  757 {
  758         int val;
  759 
  760         vga_ts_write(&vc->hdl, syncreset, 0x01);
  761         if (state) {                                    /* unblank screen */
  762                 val = vga_ts_read(&vc->hdl, mode);
  763                 vga_ts_write(&vc->hdl, mode, val & ~VGA_TS_MODE_BLANK);
  764 #ifndef VGA_NO_VBLANK
  765                 val = vga_6845_read(&vc->hdl, mode);
  766                 vga_6845_write(&vc->hdl, mode, val | 0x80);
  767 #endif
  768         } else {                                        /* blank screen */
  769                 val = vga_ts_read(&vc->hdl, mode);
  770                 vga_ts_write(&vc->hdl, mode, val | VGA_TS_MODE_BLANK);
  771 #ifndef VGA_NO_VBLANK
  772                 val = vga_6845_read(&vc->hdl, mode);
  773                 vga_6845_write(&vc->hdl, mode, val & ~0x80);
  774 #endif
  775         }
  776         vga_ts_write(&vc->hdl, syncreset, 0x03);
  777 }
  778 
  779 static int
  780 vga_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
  781 {
  782         struct vga_config *vc = v;
  783         struct vgascreen *scr = vs;
  784         const struct vga_funcs *vf = vc->vc_funcs;
  785 
  786         switch (cmd) {
  787         case WSDISPLAYIO_SMODE:
  788                 if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL)
  789                         vga_restore_palette(vc);
  790                 return 0;
  791 
  792         case WSDISPLAYIO_GTYPE:
  793                 *(int *)data = vc->vc_type;
  794                 return 0;
  795 
  796         case WSDISPLAYIO_GINFO:
  797                 /* XXX should get detailed hardware information here */
  798                 return EPASSTHROUGH;
  799 
  800         case WSDISPLAYIO_GVIDEO:
  801                 *(int *)data = (vga_get_video(vc) ?
  802                     WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF);
  803                 return 0;
  804 
  805         case WSDISPLAYIO_SVIDEO:
  806                 vga_set_video(vc, *(int *)data == WSDISPLAYIO_VIDEO_ON);
  807                 return 0;
  808 
  809         case WSDISPLAYIO_GETWSCHAR:
  810                 KASSERT(scr != NULL);
  811                 return pcdisplay_getwschar(&scr->pcs,
  812                     (struct wsdisplay_char *)data);
  813 
  814         case WSDISPLAYIO_PUTWSCHAR:
  815                 KASSERT(scr != NULL);
  816                 return pcdisplay_putwschar(&scr->pcs,
  817                     (struct wsdisplay_char *)data);
  818 
  819 #ifdef WSDISPLAY_CUSTOM_BORDER
  820         case WSDISPLAYIO_GBORDER:
  821                 return (vga_getborder(vc, (u_int *)data));
  822 
  823         case WSDISPLAYIO_SBORDER:
  824                 return (vga_setborder(vc, *(u_int *)data));
  825 #endif
  826 
  827         case WSDISPLAYIO_GETCMAP:
  828         case WSDISPLAYIO_PUTCMAP:
  829         case WSDISPLAYIO_GCURPOS:
  830         case WSDISPLAYIO_SCURPOS:
  831         case WSDISPLAYIO_GCURMAX:
  832         case WSDISPLAYIO_GCURSOR:
  833         case WSDISPLAYIO_SCURSOR:
  834                 /* NONE of these operations are by the generic VGA driver. */
  835                 return EPASSTHROUGH;
  836         }
  837 
  838         if (vc->vc_funcs == NULL)
  839                 return (EPASSTHROUGH);
  840 
  841         if (vf->vf_ioctl == NULL)
  842                 return (EPASSTHROUGH);
  843 
  844         return ((*vf->vf_ioctl)(v, cmd, data, flag, l));
  845 }
  846 
  847 static paddr_t
  848 vga_mmap(void *v, void *vs, off_t offset, int prot)
  849 {
  850         struct vga_config *vc = v;
  851         const struct vga_funcs *vf = vc->vc_funcs;
  852 
  853         if (vc->vc_funcs == NULL)
  854                 return (-1);
  855 
  856         if (vf->vf_mmap == NULL)
  857                 return (-1);
  858 
  859         return ((*vf->vf_mmap)(v, offset, prot));
  860 }
  861 
  862 static int
  863 vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  864                  int *curxp, int *curyp, long *defattrp)
  865 {
  866         struct vga_config *vc = v;
  867         struct vgascreen *scr;
  868 
  869         if (vc->nscreens == 1) {
  870                 struct vgascreen *scr1 = vc->screens.lh_first;
  871                 /*
  872                  * When allocating the second screen, get backing store
  873                  * for the first one too.
  874                  * XXX We could be more clever and use video RAM.
  875                  */
  876                 scr1->pcs.mem =
  877                     malloc(scr1->pcs.type->ncols * scr1->pcs.type->nrows * 2,
  878                     M_DEVBUF, M_WAITOK);
  879         }
  880 
  881         scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
  882         vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
  883 
  884         if (vc->nscreens > 1) {
  885                 scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
  886                     M_DEVBUF, M_WAITOK);
  887                 pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
  888         }
  889 
  890         *cookiep = scr;
  891         *curxp = scr->pcs.cursorcol;
  892         *curyp = scr->pcs.cursorrow;
  893 
  894         return (0);
  895 }
  896 
  897 static void
  898 vga_free_screen(void *v, void *cookie)
  899 {
  900         struct vgascreen *vs = cookie;
  901         struct vga_config *vc = vs->cfg;
  902 
  903         LIST_REMOVE(vs, next);
  904         vc->nscreens--;
  905         if (vs->fontset1)
  906                 egavga_unreffont(vc, vs->fontset1);
  907         if (vs->fontset2)
  908                 egavga_unreffont(vc, vs->fontset2);
  909 
  910         if (vs != &vga_console_screen)
  911                 free(vs, M_DEVBUF);
  912         else
  913                 panic("vga_free_screen: console");
  914 
  915         if (vc->active == vs)
  916                 vc->active = 0;
  917 }
  918 
  919 static void vga_usefont(struct vga_config *, struct egavga_font *);
  920 
  921 static void
  922 vga_usefont(struct vga_config *vc, struct egavga_font *f)
  923 {
  924         int slot;
  925         struct egavga_font *of;
  926 
  927         if (f->slot != -1)
  928                 goto toend;
  929 
  930         for (slot = 0; slot < vc->vc_nfontslots; slot++) {
  931                 if (!vc->vc_fonts[slot])
  932                         goto loadit;
  933         }
  934 
  935         /* have to kick out another one */
  936         TAILQ_FOREACH(of, &vc->vc_fontlist, next) {
  937                 if (of->slot != -1) {
  938                         KASSERT(vc->vc_fonts[of->slot] == of);
  939                         slot = of->slot;
  940                         of->slot = -1;
  941                         goto loadit;
  942                 }
  943         }
  944         panic("vga_usefont");
  945 
  946 loadit:
  947         vga_loadchars(&vc->hdl, slot, f->wsfont->firstchar,
  948             f->wsfont->numchars, f->wsfont->fontheight, f->wsfont->data);
  949         f->slot = slot;
  950         vc->vc_fonts[slot] = f;
  951 
  952 toend:
  953         TAILQ_REMOVE(&vc->vc_fontlist, f, next);
  954         TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
  955 }
  956 
  957 static void
  958 vga_setfont(struct vga_config *vc, struct vgascreen *scr)
  959 {
  960         int fontslot1, fontslot2;
  961 
  962         if (scr->fontset1)
  963                 vga_usefont(vc, scr->fontset1);
  964         if (scr->fontset2)
  965                 vga_usefont(vc, scr->fontset2);
  966 
  967         fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
  968         fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
  969         if (vc->currentfontset1 != fontslot1 ||
  970             vc->currentfontset2 != fontslot2) {
  971                 vga_setfontset(&vc->hdl, fontslot1, fontslot2);
  972                 vc->currentfontset1 = fontslot1;
  973                 vc->currentfontset2 = fontslot2;
  974         }
  975 }
  976 
  977 static int
  978 vga_show_screen(void *v, void *cookie, int waitok,
  979                 void (*cb)(void *, int, int), void *cbarg)
  980 {
  981         struct vgascreen *scr = cookie, *oldscr;
  982         struct vga_config *vc = scr->cfg;
  983 
  984         oldscr = vc->active; /* can be NULL! */
  985         if (scr == oldscr) {
  986                 return (0);
  987         }
  988 
  989         vc->wantedscreen = cookie;
  990         vc->switchcb = cb;
  991         vc->switchcbarg = cbarg;
  992         if (cb) {
  993                 callout_reset(&vc->vc_switch_callout, 0,
  994                     (void(*)(void *))vga_doswitch, vc);
  995                 return (EAGAIN);
  996         }
  997 
  998         vga_doswitch(vc);
  999         return (0);
 1000 }
 1001 
 1002 static void
 1003 vga_doswitch(struct vga_config *vc)
 1004 {
 1005         struct vgascreen *scr, *oldscr;
 1006         struct vga_handle *vh = &vc->hdl;
 1007         const struct wsscreen_descr *type;
 1008 
 1009         scr = vc->wantedscreen;
 1010         if (!scr) {
 1011                 printf("vga_doswitch: disappeared\n");
 1012                 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
 1013                 return;
 1014         }
 1015         type = scr->pcs.type;
 1016         oldscr = vc->active; /* can be NULL! */
 1017 #ifdef DIAGNOSTIC
 1018         if (oldscr) {
 1019                 if (!oldscr->pcs.active)
 1020                         panic("vga_show_screen: not active");
 1021                 if (oldscr->pcs.type != vc->currenttype)
 1022                         panic("vga_show_screen: bad type");
 1023         }
 1024 #endif
 1025         if (scr == oldscr) {
 1026                 return;
 1027         }
 1028 #ifdef DIAGNOSTIC
 1029         if (scr->pcs.active)
 1030                 panic("vga_show_screen: active");
 1031 #endif
 1032 
 1033         if (oldscr) {
 1034                 const struct wsscreen_descr *oldtype = oldscr->pcs.type;
 1035 
 1036                 oldscr->pcs.active = 0;
 1037                 bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
 1038                     oldscr->pcs.dispoffset, oldscr->pcs.mem,
 1039                     oldtype->ncols * oldtype->nrows);
 1040         }
 1041 
 1042         if (vc->currenttype != type) {
 1043                 vga_setscreentype(vh, type);
 1044                 vc->currenttype = type;
 1045         }
 1046 
 1047         vga_setfont(vc, scr);
 1048         vga_restore_palette(vc);
 1049 
 1050         scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
 1051         if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
 1052                 vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
 1053                 vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
 1054         }
 1055 
 1056         bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
 1057             scr->pcs.dispoffset, scr->pcs.mem, type->ncols * type->nrows);
 1058         scr->pcs.active = 1;
 1059 
 1060         vc->active = scr;
 1061 
 1062         pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
 1063             scr->pcs.cursorrow, scr->pcs.cursorcol);
 1064 
 1065         vc->wantedscreen = 0;
 1066         if (vc->switchcb)
 1067                 (*vc->switchcb)(vc->switchcbarg, 0, 0);
 1068 }
 1069 
 1070 static int
 1071 vga_load_font(void *v, void *cookie, struct wsdisplay_font *data)
 1072 {
 1073         struct vga_config *vc = v;
 1074         struct vgascreen *scr = cookie;
 1075         char *name2;
 1076         int res;
 1077 
 1078         if (scr) {
 1079                 name2 = NULL;
 1080                 if (data->name) {
 1081                         name2 = strchr(data->name, ',');
 1082                         if (name2)
 1083                                 *name2++ = '\0';
 1084                 }
 1085                 res = vga_selectfont(vc, scr, data->name, name2);
 1086                 if (!res && scr->pcs.active)
 1087                         vga_setfont(vc, scr);
 1088                 return (res);
 1089         }
 1090 
 1091         return (0);
 1092 }
 1093 
 1094 static int
 1095 vga_allocattr(void *id, int fg, int bg, int flags, long *attrp)
 1096 {
 1097         struct vgascreen *scr = id;
 1098         struct vga_config *vc = scr->cfg;
 1099 
 1100         if (__predict_false((unsigned int)fg >= sizeof(fgansitopc) || 
 1101             (unsigned int)bg >= sizeof(bgansitopc)))
 1102                 return (EINVAL);
 1103 
 1104         if (vc->hdl.vh_mono) {
 1105                 if (flags & WSATTR_WSCOLORS)
 1106                         return (EINVAL);
 1107                 if (flags & WSATTR_REVERSE)
 1108                         *attrp = 0x70;
 1109                 else
 1110                         *attrp = 0x07;
 1111                 if (flags & WSATTR_UNDERLINE)
 1112                         *attrp |= FG_UNDERLINE;
 1113                 if (flags & WSATTR_HILIT)
 1114                         *attrp |= FG_INTENSE;
 1115         } else {
 1116                 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
 1117                         return (EINVAL);
 1118                 if (flags & WSATTR_WSCOLORS)
 1119                         *attrp = fgansitopc[fg] | bgansitopc[bg];
 1120                 else
 1121                         *attrp = 7;
 1122                 if (flags & WSATTR_HILIT)
 1123                         *attrp += 8;
 1124         }
 1125         if (flags & WSATTR_BLINK)
 1126                 *attrp |= FG_BLINK;
 1127         return (0);
 1128 }
 1129 
 1130 static void
 1131 vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
 1132 {
 1133         struct vgascreen *scr = id;
 1134         bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
 1135         bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
 1136         int ncols = scr->pcs.type->ncols;
 1137         bus_size_t srcoff, dstoff;
 1138 
 1139         srcoff = srcrow * ncols + 0;
 1140         dstoff = dstrow * ncols + 0;
 1141 
 1142         if (scr->pcs.active) {
 1143                 if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
 1144 #ifdef PCDISPLAY_SOFTCURSOR
 1145                         int cursoron = scr->pcs.cursoron;
 1146 
 1147                         if (cursoron)
 1148                                 pcdisplay_cursor(&scr->pcs, 0,
 1149                                     scr->pcs.cursorrow, scr->pcs.cursorcol);
 1150 #endif
 1151                         /* scroll up whole screen */
 1152                         if ((scr->pcs.dispoffset + srcrow * ncols * 2)
 1153                             <= scr->maxdispoffset) {
 1154                                 scr->pcs.dispoffset += srcrow * ncols * 2;
 1155                         } else {
 1156                                 bus_space_copy_region_2(memt, memh,
 1157                                     scr->pcs.dispoffset + srcoff * 2,
 1158                                     memh, scr->mindispoffset, nrows * ncols);
 1159                                 scr->pcs.dispoffset = scr->mindispoffset;
 1160                         }
 1161                         vga_6845_write(&scr->cfg->hdl, startadrh,
 1162                             scr->pcs.dispoffset >> 9);
 1163                         vga_6845_write(&scr->cfg->hdl, startadrl,
 1164                             scr->pcs.dispoffset >> 1);
 1165 #ifdef PCDISPLAY_SOFTCURSOR
 1166                         if (cursoron)
 1167                                 pcdisplay_cursor(&scr->pcs, 1,
 1168                                     scr->pcs.cursorrow, scr->pcs.cursorcol);
 1169 #endif
 1170                 } else {
 1171                         bus_space_copy_region_2(memt, memh,
 1172                             scr->pcs.dispoffset + srcoff * 2,
 1173                             memh, scr->pcs.dispoffset + dstoff * 2,
 1174                             nrows * ncols);
 1175                 }
 1176         } else
 1177                 memcpy(&scr->pcs.mem[dstoff], &scr->pcs.mem[srcoff],
 1178                     nrows * ncols * 2);
 1179 }
 1180 
 1181 #ifdef WSCONS_SUPPORT_PCVTFONTS
 1182 
 1183 #define NOTYET 0xffff
 1184 static const uint16_t pcvt_unichars[0xa0] = {
 1185 /* 0 */ _e006U, /* N/L control */
 1186         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1187         NOTYET,
 1188         0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */
 1189         0x240a, /* SYMBOL FOR LINE FEED */
 1190         0x240b, /* SYMBOL FOR VERTICAL TABULATION */
 1191         0x240c, /* SYMBOL FOR FORM FEED */
 1192         0x240d, /* SYMBOL FOR CARRIAGE RETURN */
 1193         NOTYET, NOTYET,
 1194 /* 1 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1195         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1196 /* 2 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1197         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1198 /* 3 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1199         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1200 /* 4 */ 0x03c1, /* GREEK SMALL LETTER RHO */
 1201         0x03c8, /* GREEK SMALL LETTER PSI */
 1202         0x2202, /* PARTIAL DIFFERENTIAL */
 1203         0x03bb, /* GREEK SMALL LETTER LAMDA */
 1204         0x03b9, /* GREEK SMALL LETTER IOTA */
 1205         0x03b7, /* GREEK SMALL LETTER ETA */
 1206         0x03b5, /* GREEK SMALL LETTER EPSILON */
 1207         0x03c7, /* GREEK SMALL LETTER CHI */
 1208         0x2228, /* LOGICAL OR */
 1209         0x2227, /* LOGICAL AND */
 1210         0x222a, /* UNION */
 1211         0x2283, /* SUPERSET OF */
 1212         0x2282, /* SUBSET OF */
 1213         0x03a5, /* GREEK CAPITAL LETTER UPSILON */
 1214         0x039e, /* GREEK CAPITAL LETTER XI */
 1215         0x03a8, /* GREEK CAPITAL LETTER PSI */
 1216 /* 5 */ 0x03a0, /* GREEK CAPITAL LETTER PI */
 1217         0x21d2, /* RIGHTWARDS DOUBLE ARROW */
 1218         0x21d4, /* LEFT RIGHT DOUBLE ARROW */
 1219         0x039b, /* GREEK CAPITAL LETTER LAMDA */
 1220         0x0398, /* GREEK CAPITAL LETTER THETA */
 1221         0x2243, /* ASYMPTOTICALLY EQUAL TO */
 1222         0x2207, /* NABLA */
 1223         0x2206, /* INCREMENT */
 1224         0x221d, /* PROPORTIONAL TO */
 1225         0x2234, /* THEREFORE */
 1226         0x222b, /* INTEGRAL */
 1227         0x2215, /* DIVISION SLASH */
 1228         0x2216, /* SET MINUS */
 1229         _e00eU, /* angle? */
 1230         _e00dU, /* inverted angle? */
 1231         _e00bU, /* braceleftmid */
 1232 /* 6 */ _e00cU, /* bracerightmid */
 1233         _e007U, /* bracelefttp */
 1234         _e008U, /* braceleftbt */
 1235         _e009U, /* bracerighttp */
 1236         _e00aU, /* bracerightbt */
 1237         0x221a, /* SQUARE ROOT */
 1238         0x03c9, /* GREEK SMALL LETTER OMEGA */
 1239         0x00a5, /* YEN SIGN */
 1240         0x03be, /* GREEK SMALL LETTER XI */
 1241         0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */
 1242         0x00fe, /* LATIN SMALL LETTER THORN */
 1243         0x00f0, /* LATIN SMALL LETTER ETH */
 1244         0x00de, /* LATIN CAPITAL LETTER THORN */
 1245         0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */
 1246         0x00d7, /* MULTIPLICATION SIGN */
 1247         0x00d0, /* LATIN CAPITAL LETTER ETH */
 1248 /* 7 */ 0x00be, /* VULGAR FRACTION THREE QUARTERS */
 1249         0x00b8, /* CEDILLA */
 1250         0x00b4, /* ACUTE ACCENT */
 1251         0x00af, /* MACRON */
 1252         0x00ae, /* REGISTERED SIGN */
 1253         0x00ad, /* SOFT HYPHEN */
 1254         0x00ac, /* NOT SIGN */
 1255         0x00a8, /* DIAERESIS */
 1256         0x2260, /* NOT EQUAL TO */
 1257         0x23bd, /* scan 9 */
 1258         0x23bc, /* scan 7 */
 1259         0x2500, /* scan 5 */
 1260         0x23bb, /* scan 3 */
 1261         0x23ba, /* scan 1 */
 1262         0x03c5, /* GREEK SMALL LETTER UPSILON */
 1263         0x00f8, /* LATIN SMALL LETTER O WITH STROKE */
 1264 /* 8 */ 0x0153, /* LATIN SMALL LIGATURE OE */
 1265         0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */
 1266         0x00e3, /* LATIN SMALL LETTER A WITH TILDE */
 1267         0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
 1268         0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
 1269         0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */
 1270         0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */
 1271         0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */
 1272         0x0152, /* LATIN CAPITAL LIGATURE OE */
 1273         0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */
 1274         0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
 1275         0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */
 1276         0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */
 1277         0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
 1278         0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
 1279         0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */
 1280 /* 9 */ 0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */
 1281         0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
 1282         0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
 1283         0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */
 1284         0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */
 1285         0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
 1286         0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */
 1287         0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */
 1288         0x00b9, /* SUPERSCRIPT ONE */
 1289         0x00b7, /* MIDDLE DOT */
 1290         0x03b6, /* GREEK SMALL LETTER ZETA */
 1291         0x00b3, /* SUPERSCRIPT THREE */
 1292         0x00a9, /* COPYRIGHT SIGN */
 1293         0x00a4, /* CURRENCY SIGN */
 1294         0x03ba, /* GREEK SMALL LETTER KAPPA */
 1295         _e000U  /* mirrored question mark? */
 1296 };
 1297 
 1298 static int vga_pcvt_mapchar(int, u_int *);
 1299 
 1300 static int
 1301 vga_pcvt_mapchar(int uni, u_int *index)
 1302 {
 1303         int i;
 1304 
 1305         for (i = 0; i < 0xa0; i++) /* 0xa0..0xff are reserved */
 1306                 if (uni == pcvt_unichars[i]) {
 1307                         *index = i;
 1308                         return (5);
 1309                 }
 1310         *index = 0x99; /* middle dot */
 1311         return (0);
 1312 }
 1313 
 1314 #endif /* WSCONS_SUPPORT_PCVTFONTS */
 1315 
 1316 #ifdef WSCONS_SUPPORT_ISO7FONTS
 1317 
 1318 static int
 1319 vga_iso7_mapchar(int uni, u_int *index)
 1320 {
 1321 
 1322         /*
 1323          * U+0384 (GREEK TONOS) to
 1324          * U+03ce (GREEK SMALL LETTER OMEGA WITH TONOS)
 1325          * map directly to the iso-9 font
 1326          */
 1327         if (uni >= 0x0384 && uni <= 0x03ce) {
 1328                 /* U+0384 is at offset 0xb4 in the font */
 1329                 *index = uni - 0x0384 + 0xb4;
 1330                 return (5);
 1331         }
 1332 
 1333         /* XXX more chars in the iso-9 font */
 1334 
 1335         *index = 0xa4; /* shaded rectangle */
 1336         return (0);
 1337 }
 1338 
 1339 #endif /* WSCONS_SUPPORT_ISO7FONTS */
 1340 
 1341 static const uint16_t iso2_unichars[0x60] = {
 1342         0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
 1343         0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
 1344         0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
 1345         0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
 1346         0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
 1347         0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
 1348         0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
 1349         0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
 1350         0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
 1351         0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
 1352         0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
 1353         0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
 1354 };
 1355 
 1356 static const uint16_t koi8_unichars[0x40] = {
 1357         0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
 1358         0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
 1359         0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
 1360         0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
 1361         0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
 1362         0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
 1363         0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
 1364         0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
 1365 };
 1366 
 1367 static int _vga_mapchar(void *, const struct egavga_font *, int, u_int *);
 1368 
 1369 static int
 1370 _vga_mapchar(void *id, const struct egavga_font *font, int uni, u_int *index)
 1371 {
 1372 
 1373         switch (font->wsfont->encoding) {
 1374         case WSDISPLAY_FONTENC_ISO:
 1375                 if (uni < 256) {
 1376                         *index = uni;
 1377                         return (5);
 1378                 } else {
 1379                         *index = ' ';
 1380                         return (0);
 1381                 }
 1382         case WSDISPLAY_FONTENC_ISO2:
 1383                 if (uni < 0xa0) {
 1384                         *index = uni;
 1385                         return (5);
 1386                 } else {
 1387                         int i;
 1388                         for (i = 0; i < 0x60; i++) {
 1389                                 if (uni == iso2_unichars[i]) {
 1390                                         *index = i + 0xa0;
 1391                                         return (5);
 1392                                 }
 1393                         }
 1394                         *index = 0xa4; /* currency sign */
 1395                         return (0);
 1396                 }
 1397         case WSDISPLAY_FONTENC_KOI8_R:
 1398                 if (uni < 0x80) {
 1399                         *index = uni;
 1400                         return (5);
 1401                 } else {
 1402                         int i;
 1403                         for (i = 0; i < 0x40; i++) {
 1404                                 if (uni == koi8_unichars[i]) {
 1405                                         *index = i + 0xc0;
 1406                                         return (5);
 1407                                 }
 1408                         }
 1409                         *index = 0x94; /* box */
 1410                         return (0);
 1411                 }
 1412         case WSDISPLAY_FONTENC_IBM:
 1413                 return (pcdisplay_mapchar(id, uni, index));
 1414 #ifdef WSCONS_SUPPORT_PCVTFONTS
 1415         case WSDISPLAY_FONTENC_PCVT:
 1416                 return (vga_pcvt_mapchar(uni, index));
 1417 #endif
 1418 #ifdef WSCONS_SUPPORT_ISO7FONTS
 1419         case WSDISPLAY_FONTENC_ISO7:
 1420                 return (vga_iso7_mapchar(uni, index));
 1421 #endif
 1422         default:
 1423 #ifdef VGAFONTDEBUG
 1424                 printf("_vga_mapchar: encoding=%d\n", font->wsfont->encoding);
 1425 #endif
 1426                 *index = ' ';
 1427                 return (0);
 1428         }
 1429 }
 1430 
 1431 static int
 1432 vga_mapchar(void *id, int uni, u_int *index)
 1433 {
 1434         struct vgascreen *scr = id;
 1435         u_int idx1, idx2;
 1436         int res1, res2;
 1437 
 1438         res1 = 0;
 1439         idx1 = ' '; /* space */
 1440         if (scr->fontset1)
 1441                 res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
 1442         res2 = -1;
 1443         if (scr->fontset2) {
 1444                 KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
 1445                 res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
 1446         }
 1447         if (res2 > res1) {
 1448                 *index = idx2 | 0x0800; /* attribute bit 3 */
 1449                 return (res2);
 1450         }
 1451         *index = idx1;
 1452         return (res1);
 1453 }
 1454 
 1455 #ifdef WSDISPLAY_SCROLLSUPPORT
 1456 static void
 1457 vga_scroll(void *v, void *cookie, int lines)
 1458 {
 1459         struct vga_config *vc = v;
 1460         struct vgascreen *scr = cookie;
 1461         struct vga_handle *vh = &vc->hdl;
 1462 
 1463         if (lines == 0) {
 1464                 if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
 1465                         return;
 1466 
 1467                 scr->pcs.visibleoffset = scr->pcs.dispoffset;
 1468         }
 1469         else {
 1470                 int vga_scr_end;
 1471                 int margin = scr->pcs.type->ncols * 2;
 1472                 int ul, we, p, st;
 1473 
 1474                 vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
 1475                     scr->pcs.type->nrows * 2);
 1476                 if (scr->vga_rollover > vga_scr_end + margin) {
 1477                         ul = vga_scr_end;
 1478                         we = scr->vga_rollover + scr->pcs.type->ncols * 2;
 1479                 } else {
 1480                         ul = 0;
 1481                         we = 0x8000;
 1482                 }
 1483                 p = (scr->pcs.visibleoffset - ul + we) % we + lines *
 1484                     (scr->pcs.type->ncols * 2);
 1485                 st = (scr->pcs.dispoffset - ul + we) % we;
 1486                 if (p < margin)
 1487                         p = 0;
 1488                 if (p > st - margin)
 1489                         p = st;
 1490                 scr->pcs.visibleoffset = (p + ul) % we;
 1491         }
 1492 
 1493         vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
 1494         vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
 1495 }
 1496 #endif
 1497 
 1498 static void
 1499 vga_putchar(void *c, int row, int col, u_int uc, long attr)
 1500 {
 1501 
 1502         pcdisplay_putchar(c, row, col, uc, attr);
 1503 }
 1504 
 1505 #ifdef WSDISPLAY_CUSTOM_BORDER
 1506 static int
 1507 vga_getborder(struct vga_config *vc, u_int *valuep)
 1508 {
 1509         struct vga_handle *vh = &vc->hdl;
 1510         u_int idx;
 1511         uint8_t value;
 1512 
 1513         if (vh->vh_mono)
 1514                 return ENODEV;
 1515 
 1516         value = _vga_attr_read(vh, VGA_ATC_OVERSCAN);
 1517         for (idx = 0; idx < sizeof(fgansitopc); idx++) {
 1518                 if (fgansitopc[idx] == value) {
 1519                         *valuep = idx;
 1520                         return (0);
 1521                 }
 1522         }
 1523         return (EIO);
 1524 }
 1525 
 1526 static int
 1527 vga_setborder(struct vga_config *vc, u_int value)
 1528 {
 1529         struct vga_handle *vh = &vc->hdl;
 1530 
 1531         if (vh->vh_mono)
 1532                 return ENODEV;
 1533         if (value >= sizeof(fgansitopc))
 1534                 return EINVAL;
 1535 
 1536         _vga_attr_write(vh, VGA_ATC_OVERSCAN, fgansitopc[value]);
 1537         return (0);
 1538 }
 1539 #endif /* WSDISPLAY_CUSTOM_BORDER */
 1540 
 1541 void
 1542 vga_resume(struct vga_softc *sc)
 1543 {
 1544 #ifdef VGA_RESET_ON_RESUME
 1545         vga_initregs(&sc->sc_vc->hdl);
 1546 #endif
 1547 #ifdef PCDISPLAY_SOFTCURSOR
 1548         /* Disable the hardware cursor */
 1549         vga_6845_write(&sc->sc_vc->hdl, curstart, 0x20);
 1550         vga_6845_write(&sc->sc_vc->hdl, curend, 0x00);
 1551 #endif
 1552 }
 1553 
 1554 static void
 1555 vga_save_palette(struct vga_config *vc)
 1556 {
 1557         struct vga_handle *vh = &vc->hdl;
 1558         size_t i;
 1559         uint8_t *palette = vc->palette;
 1560 
 1561         if (vh->vh_mono)
 1562                 return;
 1563 
 1564         vga_raw_write(vh, VGA_DAC_PELMASK, 0xff);
 1565         vga_raw_write(vh, VGA_DAC_ADDRR, 0x00);
 1566         for (i = 0; i < sizeof(vc->palette); i++)
 1567                 *palette++ = vga_raw_read(vh, VGA_DAC_PALETTE);
 1568 
 1569         vga_reset_state(vh);                    /* reset flip/flop */
 1570 }
 1571 
 1572 static void
 1573 vga_restore_palette(struct vga_config *vc)
 1574 {
 1575         struct vga_handle *vh = &vc->hdl;
 1576         size_t i;
 1577         uint8_t *palette = vc->palette;
 1578 
 1579         if (vh->vh_mono)
 1580                 return;
 1581 
 1582         vga_raw_write(vh, VGA_DAC_PELMASK, 0xff);
 1583         vga_raw_write(vh, VGA_DAC_ADDRW, 0x00);
 1584         for (i = 0; i < sizeof(vc->palette); i++)
 1585                 vga_raw_write(vh, VGA_DAC_PALETTE, *palette++);
 1586 
 1587         vga_reset_state(vh);                    /* reset flip/flop */
 1588         vga_enable(vh);
 1589 }

Cache object: 8ab75eff235ec56cdc1f20a8c0dc79f9


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