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

Cache object: b3deb7009638d982bdac74cb914927b7


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