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.71.4.6 2007/08/12 19:52:27 bouyer 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.71.4.6 2007/08/12 19:52:27 bouyer Exp $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/callout.h>
   36 #include <sys/kernel.h>
   37 #include <sys/device.h>
   38 #include <sys/malloc.h>
   39 #include <sys/queue.h>
   40 #include <machine/bus.h>
   41 
   42 #include <dev/ic/mc6845reg.h>
   43 #include <dev/ic/pcdisplayvar.h>
   44 #include <dev/ic/vgareg.h>
   45 #include <dev/ic/vgavar.h>
   46 
   47 #include <dev/wscons/wsdisplayvar.h>
   48 #include <dev/wscons/wsconsio.h>
   49 #include <dev/wscons/unicode.h>
   50 #include <dev/wsfont/wsfont.h>
   51 
   52 #include <dev/ic/pcdisplay.h>
   53 
   54 /* for WSCONS_SUPPORT_PCVTFONTS and WSDISPLAY_CHARFUNCS */
   55 #include "opt_wsdisplay_compat.h"
   56 
   57 int vga_no_builtinfont = 0;
   58 
   59 static struct wsdisplay_font _vga_builtinfont = {
   60         "builtin",                      /* typeface name */
   61         0,                              /* firstchar */
   62         256,                            /* numbers */
   63         WSDISPLAY_FONTENC_IBM,          /* encoding */
   64         8,                              /* width */
   65         16,                             /* height */
   66         1,                              /* stride */
   67         WSDISPLAY_FONTORDER_L2R,        /* bit order */
   68         0,                              /* byte order */
   69         NULL                            /* data */
   70 };
   71 
   72 struct egavga_font {
   73         struct wsdisplay_font *wsfont;
   74         int cookie; /* wsfont handle, -1 invalid */
   75         int slot; /* in adapter RAM */
   76         int usecount;
   77         TAILQ_ENTRY(egavga_font) next; /* LRU queue */
   78 };
   79 
   80 static struct egavga_font vga_builtinfont = {
   81         &_vga_builtinfont,
   82         -1, 0
   83 };
   84 
   85 #ifdef VGA_CONSOLE_SCREENTYPE
   86 static struct egavga_font vga_consolefont;
   87 #endif
   88 
   89 struct vgascreen {
   90         struct pcdisplayscreen pcs;
   91 
   92         LIST_ENTRY(vgascreen) next;
   93 
   94         struct vga_config *cfg;
   95 
   96         /* videostate */
   97         struct egavga_font *fontset1, *fontset2;
   98         /* font data */
   99         /* palette */
  100 
  101         int mindispoffset, maxdispoffset;
  102         int vga_rollover;
  103         int visibleoffset;
  104 };
  105 
  106 static int vgaconsole, vga_console_type, vga_console_attached;
  107 static struct vgascreen vga_console_screen;
  108 static struct vga_config vga_console_vc;
  109 
  110 struct egavga_font *egavga_getfont(struct vga_config *, struct vgascreen *,
  111                                    const char *, int);
  112 void egavga_unreffont(struct vga_config *, struct egavga_font *);
  113 
  114 int vga_selectfont(struct vga_config *, struct vgascreen *, const char *,
  115                                    const char *);
  116 void vga_init_screen(struct vga_config *, struct vgascreen *,
  117                      const struct wsscreen_descr *, int, long *);
  118 void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t);
  119 static void vga_setfont(struct vga_config *, struct vgascreen *);
  120 
  121 static int vga_mapchar(void *, int, unsigned int *);
  122 void vga_putchar(void *, int, int, u_int, long);
  123 static int vga_allocattr(void *, int, int, int, long *);
  124 static void vga_copyrows(void *, int, int, int);
  125 #ifdef WSDISPLAY_SCROLLSUPPORT
  126 void vga_scroll (void *, void *, int);
  127 #endif
  128 
  129 const struct wsdisplay_emulops vga_emulops = {
  130         pcdisplay_cursor,
  131         vga_mapchar,
  132         vga_putchar,
  133         pcdisplay_copycols,
  134         pcdisplay_erasecols,
  135         vga_copyrows,
  136         pcdisplay_eraserows,
  137         vga_allocattr
  138 };
  139 
  140 /*
  141  * translate WS(=ANSI) color codes to standard pc ones
  142  */
  143 static const unsigned char fgansitopc[] = {
  144 #ifdef __alpha__
  145         /*
  146          * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
  147          * XXX We should probably not bother with this
  148          * XXX (reinitialize the palette registers).
  149          */
  150         FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
  151         FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
  152 #else
  153         FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
  154         FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
  155 #endif
  156 }, bgansitopc[] = {
  157 #ifdef __alpha__
  158         BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
  159         BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
  160 #else
  161         BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
  162         BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
  163 #endif
  164 };
  165 
  166 const struct wsscreen_descr vga_25lscreen = {
  167         "80x25", 80, 25,
  168         &vga_emulops,
  169         8, 16,
  170         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  171 }, vga_25lscreen_mono = {
  172         "80x25", 80, 25,
  173         &vga_emulops,
  174         8, 16,
  175         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  176 }, vga_25lscreen_bf = {
  177         "80x25bf", 80, 25,
  178         &vga_emulops,
  179         8, 16,
  180         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  181 }, vga_40lscreen = {
  182         "80x40", 80, 40,
  183         &vga_emulops,
  184         8, 10,
  185         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  186 }, vga_40lscreen_mono = {
  187         "80x40", 80, 40,
  188         &vga_emulops,
  189         8, 10,
  190         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  191 }, vga_40lscreen_bf = {
  192         "80x40bf", 80, 40,
  193         &vga_emulops,
  194         8, 10,
  195         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  196 }, vga_50lscreen = {
  197         "80x50", 80, 50,
  198         &vga_emulops,
  199         8, 8,
  200         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  201 }, vga_50lscreen_mono = {
  202         "80x50", 80, 50,
  203         &vga_emulops,
  204         8, 8,
  205         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  206 }, vga_50lscreen_bf = {
  207         "80x50bf", 80, 50,
  208         &vga_emulops,
  209         8, 8,
  210         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  211 }, vga_24lscreen = {
  212         "80x24", 80, 24,
  213         &vga_emulops,
  214         8, 16,
  215         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  216 }, vga_24lscreen_mono = {
  217         "80x24", 80, 24,
  218         &vga_emulops,
  219         8, 16,
  220         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  221 }, vga_24lscreen_bf = {
  222         "80x24bf", 80, 24,
  223         &vga_emulops,
  224         8, 16,
  225         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  226 };
  227 
  228 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
  229 
  230 const struct wsscreen_descr *_vga_scrlist[] = {
  231         &vga_25lscreen,
  232         &vga_25lscreen_bf,
  233         &vga_40lscreen,
  234         &vga_40lscreen_bf,
  235         &vga_50lscreen,
  236         &vga_50lscreen_bf,
  237         &vga_24lscreen,
  238         &vga_24lscreen_bf,
  239         /* XXX other formats, graphics screen? */
  240 }, *_vga_scrlist_mono[] = {
  241         &vga_25lscreen_mono,
  242         &vga_40lscreen_mono,
  243         &vga_50lscreen_mono,
  244         &vga_24lscreen_mono,
  245         /* XXX other formats, graphics screen? */
  246 };
  247 
  248 const struct wsscreen_list vga_screenlist = {
  249         sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
  250         _vga_scrlist
  251 }, vga_screenlist_mono = {
  252         sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
  253         _vga_scrlist_mono
  254 };
  255 
  256 static int      vga_ioctl(void *, u_long, caddr_t, int, struct proc *);
  257 static paddr_t  vga_mmap(void *, off_t, int);
  258 static int      vga_alloc_screen(void *, const struct wsscreen_descr *,
  259                                  void **, int *, int *, long *);
  260 static void     vga_free_screen(void *, void *);
  261 static int      vga_show_screen(void *, void *, int,
  262                                 void (*)(void *, int, int), void *);
  263 static int      vga_load_font(void *, void *, struct wsdisplay_font *);
  264 #ifdef WSDISPLAY_CHARFUNCS
  265 static int      vga_getwschar(void *, struct wsdisplay_char *);
  266 static int      vga_putwschar(void *, struct wsdisplay_char *);
  267 #endif /* WSDISPLAY_CHARFUNCS */
  268 
  269 void vga_doswitch(struct vga_config *);
  270 
  271 const struct wsdisplay_accessops vga_accessops = {
  272         vga_ioctl,
  273         vga_mmap,
  274         vga_alloc_screen,
  275         vga_free_screen,
  276         vga_show_screen,
  277         vga_load_font,
  278         NULL,
  279 #ifdef WSDISPLAY_CHARFUNCS
  280         vga_getwschar,
  281         vga_putwschar,
  282 #else /* WSDISPLAY_CHARFUNCS */
  283         NULL,
  284         NULL,
  285 #endif /* WSDISPLAY_CHARFUNCS */
  286 #ifdef WSDISPLAY_SCROLLSUPPORT
  287         vga_scroll,
  288 #else
  289         NULL,
  290 #endif
  291 };
  292 
  293 /*
  294  * We want at least ASCII 32..127 be present in the
  295  * first font slot.
  296  */
  297 #define vga_valid_primary_font(f) \
  298         (f->wsfont->encoding == WSDISPLAY_FONTENC_IBM || \
  299         f->wsfont->encoding == WSDISPLAY_FONTENC_ISO || \
  300         f->wsfont->encoding == WSDISPLAY_FONTENC_ISO7)
  301 
  302 struct egavga_font *
  303 egavga_getfont(struct vga_config *vc, struct vgascreen *scr, const char *name,
  304                int primary)
  305 {
  306         struct egavga_font *f;
  307         int cookie;
  308         struct wsdisplay_font *wf;
  309 
  310         TAILQ_FOREACH(f, &vc->vc_fontlist, next) {
  311                 if (wsfont_matches(f->wsfont, name,
  312                     8, scr->pcs.type->fontheight, 0) &&
  313                     (!primary || vga_valid_primary_font(f))) {
  314 #ifdef VGAFONTDEBUG
  315                         if (scr != &vga_console_screen || vga_console_attached)
  316                                 printf("vga_getfont: %s already present\n",
  317                                     name ? name : "<default>");
  318 #endif
  319                         goto found;
  320                 }
  321         }
  322 
  323         cookie = wsfont_find(name, 8, scr->pcs.type->fontheight, 0,
  324             WSDISPLAY_FONTORDER_L2R, 0);
  325         /* XXX obey "primary" */
  326         if (cookie == -1) {
  327 #ifdef VGAFONTDEBUG
  328                 if (scr != &vga_console_screen || vga_console_attached)
  329                         printf("vga_getfont: %s not found\n",
  330                             name ? name : "<default>");
  331 #endif
  332                 return (0);
  333         }
  334 
  335         if (wsfont_lock(cookie, &wf))
  336                 return (0);
  337 
  338 #ifdef VGA_CONSOLE_SCREENTYPE
  339         if (scr == &vga_console_screen)
  340                 f = &vga_consolefont;
  341         else
  342 #endif
  343         f = malloc(sizeof(struct egavga_font), M_DEVBUF, M_NOWAIT);
  344         if (!f) {
  345                 wsfont_unlock(cookie);
  346                 return (0);
  347         }
  348         f->wsfont = wf;
  349         f->cookie = cookie;
  350         f->slot = -1; /* not yet loaded */
  351         f->usecount = 0; /* incremented below */
  352         TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
  353 
  354 found:
  355         f->usecount++;
  356 #ifdef VGAFONTDEBUG
  357         if (scr != &vga_console_screen || vga_console_attached)
  358                 printf("vga_getfont: usecount=%d\n", f->usecount);
  359 #endif
  360         return (f);
  361 }
  362 
  363 void
  364 egavga_unreffont(struct vga_config *vc, struct egavga_font *f)
  365 {
  366 
  367         f->usecount--;
  368 #ifdef VGAFONTDEBUG
  369         printf("vga_unreffont: usecount=%d\n", f->usecount);
  370 #endif
  371         if (f->usecount == 0 && f->cookie != -1) {
  372                 TAILQ_REMOVE(&vc->vc_fontlist, f, next);
  373                 if (f->slot != -1) {
  374                         KASSERT(vc->vc_fonts[f->slot] == f);
  375                         vc->vc_fonts[f->slot] = 0;
  376                 }
  377                 wsfont_unlock(f->cookie);
  378 #ifdef VGA_CONSOLE_SCREENTYPE
  379                 if (f != &vga_consolefont)
  380 #endif
  381                 free(f, M_DEVBUF);
  382         }
  383 }
  384 
  385 int
  386 vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1,
  387                const char *name2)
  388 {
  389         const struct wsscreen_descr *type = scr->pcs.type;
  390         struct egavga_font *f1, *f2;
  391 
  392         f1 = egavga_getfont(vc, scr, name1, 1);
  393         if (!f1)
  394                 return (ENXIO);
  395 
  396         if (VGA_SCREEN_CANTWOFONTS(type) && name2) {
  397                 f2 = egavga_getfont(vc, scr, name2, 0);
  398                 if (!f2) {
  399                         egavga_unreffont(vc, f1);
  400                         return (ENXIO);
  401                 }
  402         } else
  403                 f2 = 0;
  404 
  405 #ifdef VGAFONTDEBUG
  406         if (scr != &vga_console_screen || vga_console_attached) {
  407                 printf("vga (%s): font1=%s (slot %d)", type->name,
  408                     f1->wsfont->name, f1->slot);
  409                 if (f2)
  410                         printf(", font2=%s (slot %d)",
  411                             f2->wsfont->name, f2->slot);
  412                 printf("\n");
  413         }
  414 #endif
  415         if (scr->fontset1)
  416                 egavga_unreffont(vc, scr->fontset1);
  417         scr->fontset1 = f1;
  418         if (scr->fontset2)
  419                 egavga_unreffont(vc, scr->fontset2);
  420         scr->fontset2 = f2;
  421         return (0);
  422 }
  423 
  424 void
  425 vga_init_screen(struct vga_config *vc, struct vgascreen *scr,
  426                 const struct wsscreen_descr *type, int existing, long *attrp)
  427 {
  428         int cpos;
  429         int res;
  430 
  431         scr->cfg = vc;
  432         scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
  433         scr->pcs.type = type;
  434         scr->pcs.active = existing;
  435         scr->mindispoffset = 0;
  436         if (vc->vc_quirks & VGA_QUIRK_NOFASTSCROLL)
  437                 scr->maxdispoffset = 0;
  438         else
  439                 scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
  440 
  441         if (existing) {
  442                 vc->active = scr;
  443 
  444                 cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
  445                 cpos |= vga_6845_read(&vc->hdl, cursorl);
  446 
  447                 /* make sure we have a valid cursor position */
  448                 if (cpos < 0 || cpos >= type->nrows * type->ncols)
  449                         cpos = 0;
  450 
  451                 scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
  452                 scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
  453 
  454                 /* make sure we have a valid memory offset */
  455                 if (scr->pcs.dispoffset < scr->mindispoffset ||
  456                     scr->pcs.dispoffset > scr->maxdispoffset)
  457                         scr->pcs.dispoffset = scr->mindispoffset;
  458 
  459                 if (type != vc->currenttype) {
  460                         vga_setscreentype(&vc->hdl, type);
  461                         vc->currenttype = type;
  462                 }
  463         } else {
  464                 cpos = 0;
  465                 scr->pcs.dispoffset = scr->mindispoffset;
  466         }
  467 
  468         scr->pcs.visibleoffset = scr->pcs.dispoffset;
  469         scr->vga_rollover = 0;
  470 
  471         scr->pcs.cursorrow = cpos / type->ncols;
  472         scr->pcs.cursorcol = cpos % type->ncols;
  473         pcdisplay_cursor_init(&scr->pcs, existing);
  474 
  475 #ifdef __alpha__
  476         if (!vc->hdl.vh_mono)
  477                 /*
  478                  * DEC firmware uses a blue background.
  479                  */
  480                 res = vga_allocattr(scr, WSCOL_WHITE, WSCOL_BLUE,
  481                     WSATTR_WSCOLORS, attrp);
  482         else
  483 #endif
  484         res = vga_allocattr(scr, 0, 0, 0, attrp);
  485 #ifdef DIAGNOSTIC
  486         if (res)
  487                 panic("vga_init_screen: attribute botch");
  488 #endif
  489 
  490         scr->pcs.mem = NULL;
  491 
  492         scr->fontset1 = scr->fontset2 = 0;
  493         if (vga_selectfont(vc, scr, 0, 0)) {
  494                 if (scr == &vga_console_screen)
  495                         panic("vga_init_screen: no font");
  496                 else
  497                         printf("vga_init_screen: no font\n");
  498         }
  499         if (existing)
  500                 vga_setfont(vc, scr);
  501 
  502         vc->nscreens++;
  503         LIST_INSERT_HEAD(&vc->screens, scr, next);
  504 }
  505 
  506 void
  507 vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt)
  508 {
  509         struct vga_handle *vh = &vc->hdl;
  510         u_int8_t mor;
  511         int i;
  512 
  513         vh->vh_iot = iot;
  514         vh->vh_memt = memt;
  515 
  516         if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
  517                 panic("vga_init: couldn't map vga io");
  518 
  519         /* read "misc output register" */
  520         mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, VGA_MISC_DATAR);
  521         vh->vh_mono = !(mor & 1);
  522 
  523         if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
  524             &vh->vh_ioh_6845))
  525                 panic("vga_init: couldn't map 6845 io");
  526 
  527         if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
  528                 panic("vga_init: couldn't map memory");
  529 
  530         if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
  531             (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, &vh->vh_memh))
  532                 panic("vga_init: mem subrange failed");
  533 
  534         /* should only reserve the space (no need to map - save KVM) */
  535         vc->vc_biostag = memt;
  536         if (bus_space_map(vc->vc_biostag, 0xc0000, 0x8000, 0, &vc->vc_bioshdl))
  537                 vc->vc_biosmapped = 0;
  538         else
  539                 vc->vc_biosmapped = 1;
  540 
  541         vc->nscreens = 0;
  542         LIST_INIT(&vc->screens);
  543         vc->active = NULL;
  544         vc->currenttype = vh->vh_mono ? &vga_25lscreen_mono : &vga_25lscreen;
  545         callout_init(&vc->vc_switch_callout);
  546 
  547         wsfont_init();
  548         if (vga_no_builtinfont) {
  549                 struct wsdisplay_font *wf;
  550                 int cookie;
  551 
  552                 cookie = wsfont_find(NULL, 8, 16, 0,
  553                      WSDISPLAY_FONTORDER_L2R, 0);
  554                 if (cookie == -1 || wsfont_lock(cookie, &wf))
  555                         panic("vga_init: can't load console font");
  556                 vga_loadchars(&vc->hdl, 0, wf->firstchar, wf->numchars,
  557                     wf->fontheight, wf->data);
  558                 vga_builtinfont.wsfont = wf;
  559                 vga_builtinfont.cookie = cookie;
  560                 vga_builtinfont.slot = 0;
  561         }
  562         vc->vc_fonts[0] = &vga_builtinfont;
  563         for (i = 1; i < 8; i++)
  564                 vc->vc_fonts[i] = 0;
  565         TAILQ_INIT(&vc->vc_fontlist);
  566         TAILQ_INSERT_HEAD(&vc->vc_fontlist, &vga_builtinfont, next);
  567 
  568         vc->currentfontset1 = vc->currentfontset2 = 0;
  569 }
  570 
  571 void
  572 vga_common_attach(struct vga_softc *sc, bus_space_tag_t iot,
  573                   bus_space_tag_t memt, int type, int quirks,
  574                   const struct vga_funcs *vf)
  575 {
  576         int console;
  577         struct vga_config *vc;
  578         struct wsemuldisplaydev_attach_args aa;
  579 
  580         console = vga_is_console(iot, type);
  581 
  582         if (console) {
  583                 vc = &vga_console_vc;
  584                 vga_console_attached = 1;
  585         } else {
  586                 vc = malloc(sizeof(struct vga_config), M_DEVBUF, M_WAITOK);
  587                 vga_init(vc, iot, memt);
  588         }
  589 
  590         if (quirks & VGA_QUIRK_ONEFONT) {
  591                 vc->vc_nfontslots = 1;
  592 #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  593                 /*
  594                  * XXX maybe invalidate font in slot > 0, but this can
  595                  * only be happen with VGA_CONSOLE_SCREENTYPE, and then
  596                  * we require VGA_CONSOLE_ATI_BROKEN_FONTSEL anyway.
  597                  */
  598 #endif
  599         } else {
  600                 vc->vc_nfontslots = 8;
  601 #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  602                 /*
  603                  * XXX maybe validate builtin font shifted to slot 1 if
  604                  * slot 0 got overwritten because of VGA_CONSOLE_SCREENTYPE,
  605                  * but it will be reloaded anyway if needed.
  606                  */
  607 #endif
  608         }
  609 
  610         /*
  611          * Save the builtin font to memory. In case it got overwritten
  612          * in console initialization, use the copy in slot 1.
  613          */
  614 #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  615 #define BUILTINFONTLOC (vga_builtinfont.slot == -1 ? 1 : 0)
  616 #else
  617         KASSERT(vga_builtinfont.slot == 0);
  618 #define BUILTINFONTLOC (0)
  619 #endif
  620         if (!vga_no_builtinfont) {
  621                 char *data =
  622                     malloc(256 * vga_builtinfont.wsfont->fontheight,
  623                     M_DEVBUF, M_WAITOK);
  624                 vga_readoutchars(&vc->hdl, BUILTINFONTLOC, 0, 256,
  625                     vga_builtinfont.wsfont->fontheight, data);
  626                 vga_builtinfont.wsfont->data = data;
  627         }
  628 
  629         vc->vc_type = type;
  630         vc->vc_funcs = vf;
  631         vc->vc_quirks = quirks;
  632 
  633         sc->sc_vc = vc;
  634         vc->softc = sc;
  635 
  636         aa.console = console;
  637         aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
  638         aa.accessops = &vga_accessops;
  639         aa.accesscookie = vc;
  640 
  641         config_found(&sc->sc_dev, &aa, wsemuldisplaydevprint);
  642 }
  643 
  644 int
  645 vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
  646 {
  647         long defattr;
  648         const struct wsscreen_descr *scr;
  649 
  650         if (check && !vga_common_probe(iot, memt))
  651                 return (ENXIO);
  652 
  653         /* set up bus-independent VGA configuration */
  654         vga_init(&vga_console_vc, iot, memt);
  655 #ifdef VGA_CONSOLE_SCREENTYPE
  656         scr = wsdisplay_screentype_pick(vga_console_vc.hdl.vh_mono ?
  657             &vga_screenlist_mono : &vga_screenlist, VGA_CONSOLE_SCREENTYPE);
  658         if (!scr)
  659                 panic("vga_cnattach: invalid screen type");
  660 #else
  661         scr = vga_console_vc.currenttype;
  662 #endif
  663 #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
  664         /*
  665          * On some (most/all?) ATI cards, only font slot 0 is usable.
  666          * vga_init_screen() might need font slot 0 for a non-default
  667          * console font, so save the builtin VGA font to another font slot.
  668          * The attach() code will take care later.
  669          */
  670         vga_console_vc.vc_quirks |= VGA_QUIRK_ONEFONT; /* redundant */
  671         vga_copyfont01(&vga_console_vc.hdl);
  672         vga_console_vc.vc_nfontslots = 1;
  673 #else
  674         vga_console_vc.vc_nfontslots = 8;
  675 #endif
  676 #ifdef notdef
  677         /* until we know better, assume "fast scrolling" does not work */
  678         vga_console_vc.vc_quirks |= VGA_QUIRK_NOFASTSCROLL;
  679 #endif
  680 
  681         vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
  682 
  683         wsdisplay_cnattach(scr, &vga_console_screen,
  684             vga_console_screen.pcs.cursorcol,
  685             vga_console_screen.pcs.cursorrow, defattr);
  686 
  687         vgaconsole = 1;
  688         vga_console_type = type;
  689         return (0);
  690 }
  691 
  692 int
  693 vga_is_console(bus_space_tag_t iot, int type)
  694 {
  695         if (vgaconsole &&
  696             !vga_console_attached &&
  697             iot == vga_console_vc.hdl.vh_iot &&
  698             (vga_console_type == -1 || (type == vga_console_type)))
  699                 return (1);
  700         return (0);
  701 }
  702 
  703 static int
  704 vga_get_video(struct vga_config *vc)
  705 {
  706 
  707         return (vga_ts_read(&vc->hdl, mode) & VGA_TS_MODE_BLANK) == 0;
  708 }
  709 
  710 static void
  711 vga_set_video(struct vga_config *vc, int state)
  712 {
  713         int val;
  714 
  715         vga_ts_write(&vc->hdl, syncreset, 0x01);
  716         if (state) {                                    /* unblank screen */
  717                 val = vga_ts_read(&vc->hdl, mode);
  718                 vga_ts_write(&vc->hdl, mode, val & ~VGA_TS_MODE_BLANK);
  719 #ifndef VGA_NO_VBLANK
  720                 val = vga_6845_read(&vc->hdl, mode);
  721                 vga_6845_write(&vc->hdl, mode, val | 0x80);
  722 #endif
  723         } else {                                        /* blank screen */
  724                 val = vga_ts_read(&vc->hdl, mode);
  725                 vga_ts_write(&vc->hdl, mode, val | VGA_TS_MODE_BLANK);
  726 #ifndef VGA_NO_VBLANK
  727                 val = vga_6845_read(&vc->hdl, mode);
  728                 vga_6845_write(&vc->hdl, mode, val & ~0x80);
  729 #endif
  730         }
  731         vga_ts_write(&vc->hdl, syncreset, 0x03);
  732 }
  733 
  734 int
  735 vga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  736 {
  737         struct vga_config *vc = v;
  738         const struct vga_funcs *vf = vc->vc_funcs;
  739 
  740         switch (cmd) {
  741         case WSDISPLAYIO_GTYPE:
  742                 *(int *)data = vc->vc_type;
  743                 return 0;
  744 
  745         case WSDISPLAYIO_GINFO:
  746                 /* XXX should get detailed hardware information here */
  747                 return EPASSTHROUGH;
  748 
  749         case WSDISPLAYIO_GVIDEO:
  750                 *(int *)data = (vga_get_video(vc) ?
  751                     WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF);
  752                 return 0;
  753 
  754         case WSDISPLAYIO_SVIDEO:
  755                 vga_set_video(vc, *(int *)data == WSDISPLAYIO_VIDEO_ON);
  756                 return 0;
  757 
  758         case WSDISPLAYIO_GETCMAP:
  759         case WSDISPLAYIO_PUTCMAP:
  760         case WSDISPLAYIO_GCURPOS:
  761         case WSDISPLAYIO_SCURPOS:
  762         case WSDISPLAYIO_GCURMAX:
  763         case WSDISPLAYIO_GCURSOR:
  764         case WSDISPLAYIO_SCURSOR:
  765                 /* NONE of these operations are by the generic VGA driver. */
  766                 return EPASSTHROUGH;
  767         }
  768 
  769         if (vc->vc_funcs == NULL)
  770                 return (EPASSTHROUGH);
  771 
  772         if (vf->vf_ioctl == NULL)
  773                 return (EPASSTHROUGH);
  774 
  775         return ((*vf->vf_ioctl)(v, cmd, data, flag, p));
  776 }
  777 
  778 static paddr_t
  779 vga_mmap(void *v, off_t offset, int prot)
  780 {
  781         struct vga_config *vc = v;
  782         const struct vga_funcs *vf = vc->vc_funcs;
  783 
  784         if (vc->vc_funcs == NULL)
  785                 return (-1);
  786 
  787         if (vf->vf_mmap == NULL)
  788                 return (-1);
  789 
  790         return ((*vf->vf_mmap)(v, offset, prot));
  791 }
  792 
  793 int
  794 vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  795                  int *curxp, int *curyp, long *defattrp)
  796 {
  797         struct vga_config *vc = v;
  798         struct vgascreen *scr;
  799 
  800         if (vc->nscreens == 1) {
  801                 struct vgascreen *scr1 = vc->screens.lh_first;
  802                 /*
  803                  * When allocating the second screen, get backing store
  804                  * for the first one too.
  805                  * XXX We could be more clever and use video RAM.
  806                  */
  807                 scr1->pcs.mem =
  808                     malloc(scr1->pcs.type->ncols * scr1->pcs.type->nrows * 2,
  809                     M_DEVBUF, M_WAITOK);
  810         }
  811 
  812         scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
  813         vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
  814 
  815         if (vc->nscreens > 1) {
  816                 scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
  817                     M_DEVBUF, M_WAITOK);
  818                 pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
  819         }
  820 
  821         *cookiep = scr;
  822         *curxp = scr->pcs.cursorcol;
  823         *curyp = scr->pcs.cursorrow;
  824 
  825         return (0);
  826 }
  827 
  828 void
  829 vga_free_screen(void *v, void *cookie)
  830 {
  831         struct vgascreen *vs = cookie;
  832         struct vga_config *vc = vs->cfg;
  833 
  834         LIST_REMOVE(vs, next);
  835         if (vs->fontset1)
  836                 egavga_unreffont(vc, vs->fontset1);
  837         if (vs->fontset2)
  838                 egavga_unreffont(vc, vs->fontset2);
  839 
  840         if (vs != &vga_console_screen)
  841                 free(vs, M_DEVBUF);
  842         else
  843                 panic("vga_free_screen: console");
  844 
  845         if (vc->active == vs)
  846                 vc->active = 0;
  847 }
  848 
  849 static void vga_usefont(struct vga_config *, struct egavga_font *);
  850 
  851 static void
  852 vga_usefont(struct vga_config *vc, struct egavga_font *f)
  853 {
  854         int slot;
  855         struct egavga_font *of;
  856 
  857         if (f->slot != -1)
  858                 goto toend;
  859 
  860         for (slot = 0; slot < vc->vc_nfontslots; slot++) {
  861                 if (!vc->vc_fonts[slot])
  862                         goto loadit;
  863         }
  864 
  865         /* have to kick out another one */
  866         TAILQ_FOREACH(of, &vc->vc_fontlist, next) {
  867                 if (of->slot != -1) {
  868                         KASSERT(vc->vc_fonts[of->slot] == of);
  869                         slot = of->slot;
  870                         of->slot = -1;
  871                         goto loadit;
  872                 }
  873         }
  874         panic("vga_usefont");
  875 
  876 loadit:
  877         vga_loadchars(&vc->hdl, slot, f->wsfont->firstchar,
  878             f->wsfont->numchars, f->wsfont->fontheight, f->wsfont->data);
  879         f->slot = slot;
  880         vc->vc_fonts[slot] = f;
  881 
  882 toend:
  883         TAILQ_REMOVE(&vc->vc_fontlist, f, next);
  884         TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
  885 }
  886 
  887 static void
  888 vga_setfont(struct vga_config *vc, struct vgascreen *scr)
  889 {
  890         int fontslot1, fontslot2;
  891 
  892         if (scr->fontset1)
  893                 vga_usefont(vc, scr->fontset1);
  894         if (scr->fontset2)
  895                 vga_usefont(vc, scr->fontset2);
  896 
  897         fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
  898         fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
  899         if (vc->currentfontset1 != fontslot1 ||
  900             vc->currentfontset2 != fontslot2) {
  901                 vga_setfontset(&vc->hdl, fontslot1, fontslot2);
  902                 vc->currentfontset1 = fontslot1;
  903                 vc->currentfontset2 = fontslot2;
  904         }
  905 }
  906 
  907 int
  908 vga_show_screen(void *v, void *cookie, int waitok,
  909                 void (*cb)(void *, int, int), void *cbarg)
  910 {
  911         struct vgascreen *scr = cookie, *oldscr;
  912         struct vga_config *vc = scr->cfg;
  913 
  914         oldscr = vc->active; /* can be NULL! */
  915         if (scr == oldscr) {
  916                 return (0);
  917         }
  918 
  919         vc->wantedscreen = cookie;
  920         vc->switchcb = cb;
  921         vc->switchcbarg = cbarg;
  922         if (cb) {
  923                 callout_reset(&vc->vc_switch_callout, 0,
  924                     (void(*)(void *))vga_doswitch, vc);
  925                 return (EAGAIN);
  926         }
  927 
  928         vga_doswitch(vc);
  929         return (0);
  930 }
  931 
  932 void
  933 vga_doswitch(struct vga_config *vc)
  934 {
  935         struct vgascreen *scr, *oldscr;
  936         struct vga_handle *vh = &vc->hdl;
  937         const struct wsscreen_descr *type;
  938 
  939         scr = vc->wantedscreen;
  940         if (!scr) {
  941                 printf("vga_doswitch: disappeared\n");
  942                 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
  943                 return;
  944         }
  945         type = scr->pcs.type;
  946         oldscr = vc->active; /* can be NULL! */
  947 #ifdef DIAGNOSTIC
  948         if (oldscr) {
  949                 if (!oldscr->pcs.active)
  950                         panic("vga_show_screen: not active");
  951                 if (oldscr->pcs.type != vc->currenttype)
  952                         panic("vga_show_screen: bad type");
  953         }
  954 #endif
  955         if (scr == oldscr) {
  956                 return;
  957         }
  958 #ifdef DIAGNOSTIC
  959         if (scr->pcs.active)
  960                 panic("vga_show_screen: active");
  961 #endif
  962 
  963         if (oldscr) {
  964                 const struct wsscreen_descr *oldtype = oldscr->pcs.type;
  965 
  966                 oldscr->pcs.active = 0;
  967                 bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
  968                     oldscr->pcs.dispoffset, oldscr->pcs.mem,
  969                     oldtype->ncols * oldtype->nrows);
  970         }
  971 
  972         if (vc->currenttype != type) {
  973                 vga_setscreentype(vh, type);
  974                 vc->currenttype = type;
  975         }
  976 
  977         vga_setfont(vc, scr);
  978         /* XXX swich colours! */
  979 
  980         scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
  981         if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
  982                 vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
  983                 vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
  984         }
  985 
  986         bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
  987             scr->pcs.dispoffset, scr->pcs.mem, type->ncols * type->nrows);
  988         scr->pcs.active = 1;
  989 
  990         vc->active = scr;
  991 
  992         pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
  993             scr->pcs.cursorrow, scr->pcs.cursorcol);
  994 
  995         vc->wantedscreen = 0;
  996         if (vc->switchcb)
  997                 (*vc->switchcb)(vc->switchcbarg, 0, 0);
  998 }
  999 
 1000 static int
 1001 vga_load_font(void *v, void *cookie, struct wsdisplay_font *data)
 1002 {
 1003         struct vga_config *vc = v;
 1004         struct vgascreen *scr = cookie;
 1005         char *name2;
 1006         int res;
 1007 
 1008         if (scr) {
 1009                 name2 = NULL;
 1010                 if (data->name) {
 1011                         name2 = strchr(data->name, ',');
 1012                         if (name2)
 1013                                 *name2++ = '\0';
 1014                 }
 1015                 res = vga_selectfont(vc, scr, data->name, name2);
 1016                 if (!res && scr->pcs.active)
 1017                         vga_setfont(vc, scr);
 1018                 return (res);
 1019         }
 1020 
 1021         return (0);
 1022 }
 1023 
 1024 static int
 1025 vga_allocattr(void *id, int fg, int bg, int flags, long *attrp)
 1026 {
 1027         struct vgascreen *scr = id;
 1028         struct vga_config *vc = scr->cfg;
 1029 
 1030         if (__predict_false((unsigned int)fg >= sizeof(fgansitopc) || 
 1031             (unsigned int)bg >= sizeof(bgansitopc)))
 1032                 return (EINVAL);
 1033 
 1034         if (vc->hdl.vh_mono) {
 1035                 if (flags & WSATTR_WSCOLORS)
 1036                         return (EINVAL);
 1037                 if (flags & WSATTR_REVERSE)
 1038                         *attrp = 0x70;
 1039                 else
 1040                         *attrp = 0x07;
 1041                 if (flags & WSATTR_UNDERLINE)
 1042                         *attrp |= FG_UNDERLINE;
 1043                 if (flags & WSATTR_HILIT)
 1044                         *attrp |= FG_INTENSE;
 1045         } else {
 1046                 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
 1047                         return (EINVAL);
 1048                 if (flags & WSATTR_WSCOLORS)
 1049                         *attrp = fgansitopc[fg] | bgansitopc[bg];
 1050                 else
 1051                         *attrp = 7;
 1052                 if (flags & WSATTR_HILIT)
 1053                         *attrp += 8;
 1054         }
 1055         if (flags & WSATTR_BLINK)
 1056                 *attrp |= FG_BLINK;
 1057         return (0);
 1058 }
 1059 
 1060 static void
 1061 vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
 1062 {
 1063         struct vgascreen *scr = id;
 1064         bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
 1065         bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
 1066         int ncols = scr->pcs.type->ncols;
 1067         bus_size_t srcoff, dstoff;
 1068 
 1069         srcoff = srcrow * ncols + 0;
 1070         dstoff = dstrow * ncols + 0;
 1071 
 1072         if (scr->pcs.active) {
 1073                 if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
 1074 #ifdef PCDISPLAY_SOFTCURSOR
 1075                         int cursoron = scr->pcs.cursoron;
 1076 
 1077                         if (cursoron)
 1078                                 pcdisplay_cursor(&scr->pcs, 0,
 1079                                     scr->pcs.cursorrow, scr->pcs.cursorcol);
 1080 #endif
 1081                         /* scroll up whole screen */
 1082                         if ((scr->pcs.dispoffset + srcrow * ncols * 2)
 1083                             <= scr->maxdispoffset) {
 1084                                 scr->pcs.dispoffset += srcrow * ncols * 2;
 1085                         } else {
 1086                                 bus_space_copy_region_2(memt, memh,
 1087                                     scr->pcs.dispoffset + srcoff * 2,
 1088                                     memh, scr->mindispoffset, nrows * ncols);
 1089                                 scr->pcs.dispoffset = scr->mindispoffset;
 1090                         }
 1091                         vga_6845_write(&scr->cfg->hdl, startadrh,
 1092                             scr->pcs.dispoffset >> 9);
 1093                         vga_6845_write(&scr->cfg->hdl, startadrl,
 1094                             scr->pcs.dispoffset >> 1);
 1095 #ifdef PCDISPLAY_SOFTCURSOR
 1096                         if (cursoron)
 1097                                 pcdisplay_cursor(&scr->pcs, 1,
 1098                                     scr->pcs.cursorrow, scr->pcs.cursorcol);
 1099 #endif
 1100                 } else {
 1101                         bus_space_copy_region_2(memt, memh,
 1102                             scr->pcs.dispoffset + srcoff * 2,
 1103                             memh, scr->pcs.dispoffset + dstoff * 2,
 1104                             nrows * ncols);
 1105                 }
 1106         } else
 1107                 memcpy(&scr->pcs.mem[dstoff], &scr->pcs.mem[srcoff],
 1108                     nrows * ncols * 2);
 1109 }
 1110 
 1111 #ifdef WSCONS_SUPPORT_PCVTFONTS
 1112 
 1113 #define NOTYET 0xffff
 1114 static const u_int16_t pcvt_unichars[0xa0] = {
 1115 /* 0 */ _e006U, /* N/L control */
 1116         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1117         NOTYET,
 1118         0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */
 1119         0x240a, /* SYMBOL FOR LINE FEED */
 1120         0x240b, /* SYMBOL FOR VERTICAL TABULATION */
 1121         0x240c, /* SYMBOL FOR FORM FEED */
 1122         0x240d, /* SYMBOL FOR CARRIAGE RETURN */
 1123         NOTYET, NOTYET,
 1124 /* 1 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1125         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1126 /* 2 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1127         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1128 /* 3 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1129         NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
 1130 /* 4 */ 0x03c1, /* GREEK SMALL LETTER RHO */
 1131         0x03c8, /* GREEK SMALL LETTER PSI */
 1132         0x2202, /* PARTIAL DIFFERENTIAL */
 1133         0x03bb, /* GREEK SMALL LETTER LAMDA */
 1134         0x03b9, /* GREEK SMALL LETTER IOTA */
 1135         0x03b7, /* GREEK SMALL LETTER ETA */
 1136         0x03b5, /* GREEK SMALL LETTER EPSILON */
 1137         0x03c7, /* GREEK SMALL LETTER CHI */
 1138         0x2228, /* LOGICAL OR */
 1139         0x2227, /* LOGICAL AND */
 1140         0x222a, /* UNION */
 1141         0x2283, /* SUPERSET OF */
 1142         0x2282, /* SUBSET OF */
 1143         0x03a5, /* GREEK CAPITAL LETTER UPSILON */
 1144         0x039e, /* GREEK CAPITAL LETTER XI */
 1145         0x03a8, /* GREEK CAPITAL LETTER PSI */
 1146 /* 5 */ 0x03a0, /* GREEK CAPITAL LETTER PI */
 1147         0x21d2, /* RIGHTWARDS DOUBLE ARROW */
 1148         0x21d4, /* LEFT RIGHT DOUBLE ARROW */
 1149         0x039b, /* GREEK CAPITAL LETTER LAMDA */
 1150         0x0398, /* GREEK CAPITAL LETTER THETA */
 1151         0x2243, /* ASYMPTOTICALLY EQUAL TO */
 1152         0x2207, /* NABLA */
 1153         0x2206, /* INCREMENT */
 1154         0x221d, /* PROPORTIONAL TO */
 1155         0x2234, /* THEREFORE */
 1156         0x222b, /* INTEGRAL */
 1157         0x2215, /* DIVISION SLASH */
 1158         0x2216, /* SET MINUS */
 1159         _e00eU, /* angle? */
 1160         _e00dU, /* inverted angle? */
 1161         _e00bU, /* braceleftmid */
 1162 /* 6 */ _e00cU, /* bracerightmid */
 1163         _e007U, /* bracelefttp */
 1164         _e008U, /* braceleftbt */
 1165         _e009U, /* bracerighttp */
 1166         _e00aU, /* bracerightbt */
 1167         0x221a, /* SQUARE ROOT */
 1168         0x03c9, /* GREEK SMALL LETTER OMEGA */
 1169         0x00a5, /* YEN SIGN */
 1170         0x03be, /* GREEK SMALL LETTER XI */
 1171         0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */
 1172         0x00fe, /* LATIN SMALL LETTER THORN */
 1173         0x00f0, /* LATIN SMALL LETTER ETH */
 1174         0x00de, /* LATIN CAPITAL LETTER THORN */
 1175         0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */
 1176         0x00d7, /* MULTIPLICATION SIGN */
 1177         0x00d0, /* LATIN CAPITAL LETTER ETH */
 1178 /* 7 */ 0x00be, /* VULGAR FRACTION THREE QUARTERS */
 1179         0x00b8, /* CEDILLA */
 1180         0x00b4, /* ACUTE ACCENT */
 1181         0x00af, /* MACRON */
 1182         0x00ae, /* REGISTERED SIGN */
 1183         0x00ad, /* SOFT HYPHEN */
 1184         0x00ac, /* NOT SIGN */
 1185         0x00a8, /* DIAERESIS */
 1186         0x2260, /* NOT EQUAL TO */
 1187         _e005U, /* scan 9 */
 1188         _e004U, /* scan 7 */
 1189         _e003U, /* scan 5 */
 1190         _e002U, /* scan 3 */
 1191         _e001U, /* scan 1 */
 1192         0x03c5, /* GREEK SMALL LETTER UPSILON */
 1193         0x00f8, /* LATIN SMALL LETTER O WITH STROKE */
 1194 /* 8 */ 0x0153, /* LATIN SMALL LIGATURE OE */
 1195         0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */
 1196         0x00e3, /* LATIN SMALL LETTER A WITH TILDE */
 1197         0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
 1198         0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
 1199         0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */
 1200         0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */
 1201         0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */
 1202         0x0152, /* LATIN CAPITAL LIGATURE OE */
 1203         0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */
 1204         0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
 1205         0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */
 1206         0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */
 1207         0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
 1208         0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
 1209         0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */
 1210 /* 9 */ 0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */
 1211         0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
 1212         0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
 1213         0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */
 1214         0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */
 1215         0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
 1216         0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */
 1217         0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */
 1218         0x00b9, /* SUPERSCRIPT ONE */
 1219         0x00b7, /* MIDDLE DOT */
 1220         0x03b6, /* GREEK SMALL LETTER ZETA */
 1221         0x00b3, /* SUPERSCRIPT THREE */
 1222         0x00a9, /* COPYRIGHT SIGN */
 1223         0x00a4, /* CURRENCY SIGN */
 1224         0x03ba, /* GREEK SMALL LETTER KAPPA */
 1225         _e000U  /* mirrored question mark? */
 1226 };
 1227 
 1228 static int vga_pcvt_mapchar(int, u_int *);
 1229 
 1230 static int
 1231 vga_pcvt_mapchar(int uni, u_int *index)
 1232 {
 1233         int i;
 1234 
 1235         for (i = 0; i < 0xa0; i++) /* 0xa0..0xff are reserved */
 1236                 if (uni == pcvt_unichars[i]) {
 1237                         *index = i;
 1238                         return (5);
 1239                 }
 1240         *index = 0x99; /* middle dot */
 1241         return (0);
 1242 }
 1243 
 1244 #endif /* WSCONS_SUPPORT_PCVTFONTS */
 1245 
 1246 #ifdef WSCONS_SUPPORT_ISO7FONTS
 1247 
 1248 static int
 1249 vga_iso7_mapchar(int uni, u_int *index)
 1250 {
 1251 
 1252         /*
 1253          * U+0384 (GREEK TONOS) to
 1254          * U+03ce (GREEK SMALL LETTER OMEGA WITH TONOS)
 1255          * map directly to the iso-9 font
 1256          */
 1257         if (uni >= 0x0384 && uni <= 0x03ce) {
 1258                 /* U+0384 is at offset 0xb4 in the font */
 1259                 *index = uni - 0x0384 + 0xb4;
 1260                 return (5);
 1261         }
 1262 
 1263         /* XXX more chars in the iso-9 font */
 1264 
 1265         *index = 0xa4; /* shaded rectangle */
 1266         return (0);
 1267 }
 1268 
 1269 #endif /* WSCONS_SUPPORT_ISO7FONTS */
 1270 
 1271 static int _vga_mapchar(void *, const struct egavga_font *, int, u_int *);
 1272 
 1273 static int
 1274 _vga_mapchar(void *id, const struct egavga_font *font, int uni, u_int *index)
 1275 {
 1276 
 1277         switch (font->wsfont->encoding) {
 1278         case WSDISPLAY_FONTENC_ISO:
 1279                 if (uni < 256) {
 1280                         *index = uni;
 1281                         return (5);
 1282                 } else {
 1283                         *index = ' ';
 1284                         return (0);
 1285                 }
 1286         case WSDISPLAY_FONTENC_IBM:
 1287                 return (pcdisplay_mapchar(id, uni, index));
 1288 #ifdef WSCONS_SUPPORT_PCVTFONTS
 1289         case WSDISPLAY_FONTENC_PCVT:
 1290                 return (vga_pcvt_mapchar(uni, index));
 1291 #endif
 1292 #ifdef WSCONS_SUPPORT_ISO7FONTS
 1293         case WSDISPLAY_FONTENC_ISO7:
 1294                 return (vga_iso7_mapchar(uni, index));
 1295 #endif
 1296         default:
 1297 #ifdef VGAFONTDEBUG
 1298                 printf("_vga_mapchar: encoding=%d\n", font->wsfont->encoding);
 1299 #endif
 1300                 *index = ' ';
 1301                 return (0);
 1302         }
 1303 }
 1304 
 1305 static int
 1306 vga_mapchar(void *id, int uni, u_int *index)
 1307 {
 1308         struct vgascreen *scr = id;
 1309         u_int idx1, idx2;
 1310         int res1, res2;
 1311 
 1312         res1 = 0;
 1313         idx1 = ' '; /* space */
 1314         if (scr->fontset1)
 1315                 res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
 1316         res2 = -1;
 1317         if (scr->fontset2) {
 1318                 KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
 1319                 res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
 1320         }
 1321         if (res2 > res1) {
 1322                 *index = idx2 | 0x0800; /* attribute bit 3 */
 1323                 return (res2);
 1324         }
 1325         *index = idx1;
 1326         return (res1);
 1327 }
 1328 
 1329 #ifdef WSDISPLAY_SCROLLSUPPORT
 1330 void
 1331 vga_scroll(void *v, void *cookie, int lines)
 1332 {
 1333         struct vga_config *vc = v;
 1334         struct vgascreen *scr = cookie;
 1335         struct vga_handle *vh = &vc->hdl;
 1336 
 1337         if (lines == 0) {
 1338                 if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
 1339                         return;
 1340 
 1341                 scr->pcs.visibleoffset = scr->pcs.dispoffset;
 1342         }
 1343         else {
 1344                 int vga_scr_end;
 1345                 int margin = scr->pcs.type->ncols * 2;
 1346                 int ul, we, p, st;
 1347 
 1348                 vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
 1349                     scr->pcs.type->nrows * 2);
 1350                 if (scr->vga_rollover > vga_scr_end + margin) {
 1351                         ul = vga_scr_end;
 1352                         we = scr->vga_rollover + scr->pcs.type->ncols * 2;
 1353                 } else {
 1354                         ul = 0;
 1355                         we = 0x8000;
 1356                 }
 1357                 p = (scr->pcs.visibleoffset - ul + we) % we + lines *
 1358                     (scr->pcs.type->ncols * 2);
 1359                 st = (scr->pcs.dispoffset - ul + we) % we;
 1360                 if (p < margin)
 1361                         p = 0;
 1362                 if (p > st - margin)
 1363                         p = st;
 1364                 scr->pcs.visibleoffset = (p + ul) % we;
 1365         }
 1366         
 1367         vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
 1368         vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
 1369 }
 1370 #endif
 1371 
 1372 void
 1373 vga_putchar(void *c, int row, int col, u_int uc, long attr)
 1374 {
 1375 
 1376         pcdisplay_putchar(c, row, col, uc, attr);
 1377 }
 1378 
 1379 
 1380 #ifdef WSDISPLAY_CHARFUNCS
 1381 int
 1382 vga_getwschar(void *cookie, struct wsdisplay_char *wschar)
 1383 {
 1384         struct vgascreen *scr = cookie;
 1385 
 1386         if (scr == NULL) return 0;
 1387         return (pcdisplay_getwschar(&scr->pcs, wschar));
 1388 }
 1389 
 1390 int
 1391 vga_putwschar(void *cookie, struct wsdisplay_char *wschar)
 1392 {
 1393         struct vgascreen *scr = cookie;
 1394 
 1395         if (scr == NULL) return 0;
 1396         return (pcdisplay_putwschar(&scr->pcs, wschar));
 1397 }
 1398 #endif /* WSDISPLAY_CHARFUNCS */

Cache object: 6f5d67f610890aed518bd8b0eb9f76ce


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