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 /* $OpenBSD: vga.c,v 1.74 2021/05/27 23:24:40 cheloha Exp $ */
    2 /* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */
    3 
    4 /*-
    5   * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    6   * Copyright (c) 1992-1998 Søren Schmidt
    7   * All rights reserved.
    8   *
    9   * Redistribution and use in source and binary forms, with or without
   10   * modification, are permitted provided that the following conditions
   11   * are met:
   12   * 1. Redistributions of source code must retain the above copyright
   13   *    notice, this list of conditions and the following disclaimer as
   14   *    the first lines of this file unmodified.
   15   * 2. Redistributions in binary form must reproduce the above copyright
   16   *    notice, this list of conditions and the following disclaimer in the
   17   *    documentation and/or other materials provided with the distribution.
   18   * 3. The name of the author may not be used to endorse or promote products
   19   *    derived from this software without specific prior written permission.
   20   *
   21   * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   22   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   25   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31   *
   32   */
   33 /*
   34  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
   35  * All rights reserved.
   36  *
   37  * Author: Chris G. Demetriou
   38  * 
   39  * Permission to use, copy, modify and distribute this software and
   40  * its documentation is hereby granted, provided that both the copyright
   41  * notice and this permission notice appear in all copies of the
   42  * software, derivative works or modified versions, and any portions
   43  * thereof, and that both notices appear in supporting documentation.
   44  * 
   45  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
   46  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
   47  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   48  * 
   49  * Carnegie Mellon requests users of this software to return to
   50  *
   51  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   52  *  School of Computer Science
   53  *  Carnegie Mellon University
   54  *  Pittsburgh PA 15213-3890
   55  *
   56  * any improvements or extensions that they make and grant Carnegie the
   57  * rights to redistribute these changes.
   58  */
   59 
   60 #include "vga.h"
   61 
   62 #include <sys/param.h>
   63 #include <sys/systm.h>
   64 #include <sys/kernel.h>
   65 #include <sys/device.h>
   66 #include <sys/malloc.h>
   67 #include <sys/queue.h>
   68 #include <machine/bus.h>
   69 
   70 #include <dev/ic/mc6845reg.h>
   71 #include <dev/ic/pcdisplayvar.h>
   72 #include <dev/ic/vgareg.h>
   73 
   74 #include <dev/wscons/wsdisplayvar.h>
   75 #include <dev/wscons/wsconsio.h>
   76 #include <dev/wscons/unicode.h>
   77 
   78 #include <dev/ic/vgavar.h>
   79 #include <dev/ic/pcdisplay.h>
   80 
   81 static struct vgafont {
   82         char name[WSFONT_NAME_SIZE];
   83         int height;
   84         int encoding;
   85 #ifdef notyet
   86         int firstchar, numchars;
   87 #endif
   88         int slot;
   89         void *fontdata;
   90 } vga_builtinfont = {
   91         .name = "builtin",
   92         .height = 16,
   93         .encoding = WSDISPLAY_FONTENC_IBM,
   94 #ifdef notyet
   95         .firstchar = 0,
   96         .numchars = 256,
   97 #endif
   98         .slot = 0,
   99         .fontdata = NULL
  100 };
  101 
  102 int vgaconsole, vga_console_type, vga_console_attached;
  103 struct vgascreen vga_console_screen;
  104 struct vga_config vga_console_vc;
  105 
  106 int     vga_selectfont(struct vga_config *, struct vgascreen *,
  107     const char *, const char *);
  108 void    vga_init_screen(struct vga_config *, struct vgascreen *,
  109     const struct wsscreen_descr *, int, uint32_t *);
  110 void    vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t);
  111 void    vga_setfont(struct vga_config *, struct vgascreen *);
  112 void    vga_pick_monitor_type(struct vga_config *);
  113 
  114 int     vga_mapchar(void *, int, unsigned int *);
  115 int     vga_putchar(void *, int, int, u_int, uint32_t);
  116 int     vga_pack_attr(void *, int, int, int, uint32_t *);
  117 int     vga_copyrows(void *, int, int, int);
  118 void    vga_unpack_attr(void *, uint32_t, int *, int *, int *);
  119 
  120 static const struct wsdisplay_emulops vga_emulops = {
  121         pcdisplay_cursor,
  122         vga_mapchar,
  123         vga_putchar,
  124         pcdisplay_copycols,
  125         pcdisplay_erasecols,
  126         vga_copyrows,
  127         pcdisplay_eraserows,
  128         vga_pack_attr,
  129         vga_unpack_attr
  130 };
  131 
  132 /*
  133  * translate WS(=ANSI) color codes to standard pc ones
  134  */
  135 static const unsigned char fgansitopc[] = {
  136 #ifdef __alpha__
  137         /*
  138          * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
  139          * XXX We should probably not bother with this
  140          * XXX (reinitialize the palette registers).
  141          */
  142         FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
  143         FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
  144 #else
  145         FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
  146         FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
  147 #endif
  148 }, bgansitopc[] = {
  149 #ifdef __alpha__
  150         BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
  151         BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
  152 #else
  153         BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
  154         BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
  155 #endif
  156 };
  157 
  158 /*
  159  * translate standard pc color codes to WS(=ANSI) ones
  160  */
  161 static const u_int8_t pctoansi[] = {
  162 #ifdef __alpha__
  163         WSCOL_BLACK, WSCOL_RED, WSCOL_GREEN, WSCOL_BROWN,
  164         WSCOL_BLUE, WSCOL_MAGENTA, WSCOL_CYAN, WSCOL_WHITE
  165 #else
  166         WSCOL_BLACK, WSCOL_BLUE, WSCOL_GREEN, WSCOL_CYAN,
  167         WSCOL_RED, WSCOL_MAGENTA, WSCOL_BROWN, WSCOL_WHITE
  168 #endif
  169 };
  170 
  171 
  172 const struct wsscreen_descr vga_stdscreen = {
  173         "80x25", 80, 25,
  174         &vga_emulops,
  175         8, 16,
  176         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  177 }, vga_stdscreen_mono = {
  178         "80x25", 80, 25,
  179         &vga_emulops,
  180         8, 16,
  181         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  182 }, vga_stdscreen_bf = {
  183         "80x25bf", 80, 25,
  184         &vga_emulops,
  185         8, 16,
  186         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  187 }, vga_40lscreen = {
  188         "80x40", 80, 40,
  189         &vga_emulops,
  190         8, 10,
  191         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  192 }, vga_40lscreen_mono = {
  193         "80x40", 80, 40,
  194         &vga_emulops,
  195         8, 10,
  196         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  197 }, vga_40lscreen_bf = {
  198         "80x40bf", 80, 40,
  199         &vga_emulops,
  200         8, 10,
  201         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  202 }, vga_50lscreen = {
  203         "80x50", 80, 50,
  204         &vga_emulops,
  205         8, 8,
  206         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  207 }, vga_50lscreen_mono = {
  208         "80x50", 80, 50,
  209         &vga_emulops,
  210         8, 8,
  211         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  212 }, vga_50lscreen_bf = {
  213         "80x50bf", 80, 50,
  214         &vga_emulops,
  215         8, 8,
  216         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  217 };
  218 
  219 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
  220 
  221 const struct wsscreen_descr *_vga_scrlist[] = {
  222         &vga_stdscreen,
  223         &vga_stdscreen_bf,
  224         &vga_40lscreen,
  225         &vga_40lscreen_bf,
  226         &vga_50lscreen,
  227         &vga_50lscreen_bf,
  228         /* XXX other formats, graphics screen? */
  229 }, *_vga_scrlist_mono[] = {
  230         &vga_stdscreen_mono,
  231         &vga_40lscreen_mono,
  232         &vga_50lscreen_mono,
  233         /* XXX other formats, graphics screen? */
  234 };
  235 
  236 const struct wsscreen_list vga_screenlist = {
  237         sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
  238         _vga_scrlist
  239 }, vga_screenlist_mono = {
  240         sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
  241         _vga_scrlist_mono
  242 };
  243 
  244 int     vga_ioctl(void *, u_long, caddr_t, int, struct proc *);
  245 paddr_t vga_mmap(void *, off_t, int);
  246 int     vga_alloc_screen(void *, const struct wsscreen_descr *,
  247                          void **, int *, int *, uint32_t *);
  248 void    vga_free_screen(void *, void *);
  249 int     vga_show_screen(void *, void *, int,
  250                         void (*) (void *, int, int), void *);
  251 int     vga_load_font(void *, void *, struct wsdisplay_font *);
  252 int     vga_list_font(void *, struct wsdisplay_font *);
  253 void    vga_scrollback(void *, void *, int);
  254 void    vga_burner(void *v, u_int on, u_int flags);
  255 int     vga_getchar(void *, int, int, struct wsdisplay_charcell *);
  256 
  257 void vga_doswitch(void *);
  258 
  259 const struct wsdisplay_accessops vga_accessops = {
  260         .ioctl = vga_ioctl,
  261         .mmap = vga_mmap,
  262         .alloc_screen = vga_alloc_screen,
  263         .free_screen = vga_free_screen,
  264         .show_screen = vga_show_screen,
  265         .load_font = vga_load_font,
  266         .list_font = vga_list_font,
  267         .scrollback = vga_scrollback,
  268         .getchar = vga_getchar,
  269         .burn_screen = vga_burner
  270 };
  271 
  272 /*
  273  * The following functions implement back-end configuration grabbing
  274  * and attachment.
  275  */
  276 int
  277 vga_common_probe(bus_space_tag_t iot, bus_space_tag_t memt)
  278 {
  279         bus_space_handle_t ioh_vga, ioh_6845, memh;
  280         u_int8_t regval;
  281         u_int16_t vgadata;
  282         int gotio_vga, gotio_6845, gotmem, mono, rv;
  283         int dispoffset;
  284 
  285         gotio_vga = gotio_6845 = gotmem = rv = 0;
  286 
  287         if (bus_space_map(iot, 0x3c0, 0x10, 0, &ioh_vga))
  288                 goto bad;
  289         gotio_vga = 1;
  290 
  291         /* read "misc output register" */
  292         regval = bus_space_read_1(iot, ioh_vga, 0xc);
  293         mono = !(regval & 1);
  294 
  295         if (bus_space_map(iot, (mono ? 0x3b0 : 0x3d0), 0x10, 0, &ioh_6845))
  296                 goto bad;
  297         gotio_6845 = 1;
  298 
  299         if (bus_space_map(memt, 0xa0000, 0x20000, 0, &memh))
  300                 goto bad;
  301         gotmem = 1;
  302 
  303         dispoffset = (mono ? 0x10000 : 0x18000);
  304 
  305         vgadata = bus_space_read_2(memt, memh, dispoffset);
  306         bus_space_write_2(memt, memh, dispoffset, 0xa55a);
  307         if (bus_space_read_2(memt, memh, dispoffset) != 0xa55a)
  308                 goto bad;
  309         bus_space_write_2(memt, memh, dispoffset, vgadata);
  310 
  311         /*
  312          * check if this is really a VGA
  313          * (try to write "Color Select" register as XFree86 does)
  314          * XXX check before if at least EGA?
  315          */
  316         /* reset state */
  317         (void) bus_space_read_1(iot, ioh_6845, 10);
  318         bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,
  319                           20 | 0x20); /* colselect | enable */
  320         regval = bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR);
  321         /* toggle the implemented bits */
  322         bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval ^ 0x0f);
  323         bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,
  324                           20 | 0x20);
  325         /* read back */
  326         if (bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR) != (regval ^ 0x0f))
  327                 goto bad;
  328         /* restore contents */
  329         bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval);
  330 
  331         rv = 1;
  332 bad:
  333         if (gotio_vga)
  334                 bus_space_unmap(iot, ioh_vga, 0x10);
  335         if (gotio_6845)
  336                 bus_space_unmap(iot, ioh_6845, 0x10);
  337         if (gotmem)
  338                 bus_space_unmap(memt, memh, 0x20000);
  339 
  340         return (rv);
  341 }
  342 
  343 /*
  344  * We want at least ASCII 32..127 be present in the
  345  * first font slot.
  346  */
  347 int
  348 vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1,
  349     const char *name2) /* NULL: take first found */
  350 {
  351         const struct wsscreen_descr *type = scr->pcs.type;
  352         struct vgafont *f1, *f2;
  353         int i;
  354 
  355         f1 = f2 = 0;
  356 
  357         for (i = 0; i < VGA_MAXFONT; i++) {
  358                 struct vgafont *f = vc->vc_fonts[i];
  359                 if (!f || f->height != type->fontheight)
  360                         continue;
  361                 if (!f1 && (!name1 || !*name1 ||
  362                      !strncmp(name1, f->name, WSFONT_NAME_SIZE))) {
  363                         f1 = f;
  364                         continue;
  365                 }
  366                 if (!f2 &&
  367                     VGA_SCREEN_CANTWOFONTS(type) &&
  368                     (!name2 || !*name2 ||
  369                      !strncmp(name2, f->name, WSFONT_NAME_SIZE))) {
  370                         f2 = f;
  371                         continue;
  372                 }
  373         }
  374 
  375         /*
  376          * The request fails if no primary font was found,
  377          * or if a second font was requested but not found.
  378          */
  379         if (f1 && (!name2 || !*name2 || f2)) {
  380 #ifdef VGAFONTDEBUG
  381                 if (scr != &vga_console_screen || vga_console_attached) {
  382                         printf("vga (%s): font1=%s (slot %d)", type->name,
  383                                f1->name, f1->slot);
  384                         if (f2)
  385                                 printf(", font2=%s (slot %d)",
  386                                        f2->name, f2->slot);
  387                         printf("\n");
  388                 }
  389 #endif
  390                 scr->fontset1 = f1;
  391                 scr->fontset2 = f2;
  392                 return (0);
  393         }
  394         return (ENXIO);
  395 }
  396 
  397 void
  398 vga_init_screen(struct vga_config *vc, struct vgascreen *scr,
  399     const struct wsscreen_descr *type, int existing, uint32_t *attrp)
  400 {
  401         int cpos;
  402         int res;
  403 
  404         scr->cfg = vc;
  405         scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
  406         scr->pcs.type = type;
  407         scr->pcs.active = 0;
  408         scr->mindispoffset = 0;
  409         scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
  410 
  411         if (existing) {
  412                 cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
  413                 cpos |= vga_6845_read(&vc->hdl, cursorl);
  414 
  415                 /* make sure we have a valid cursor position */
  416                 if (cpos < 0 || cpos >= type->nrows * type->ncols)
  417                         cpos = 0;
  418 
  419                 scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
  420                 scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
  421 
  422                 /* make sure we have a valid memory offset */
  423                 if (scr->pcs.dispoffset < scr->mindispoffset ||
  424                     scr->pcs.dispoffset > scr->maxdispoffset)
  425                         scr->pcs.dispoffset = scr->mindispoffset;
  426         } else {
  427                 cpos = 0;
  428                 scr->pcs.dispoffset = scr->mindispoffset;
  429         }
  430         scr->pcs.visibleoffset = scr->pcs.dispoffset;
  431         scr->vga_rollover = 0;
  432 
  433         scr->pcs.vc_crow = cpos / type->ncols;
  434         scr->pcs.vc_ccol = cpos % type->ncols;
  435         pcdisplay_cursor_init(&scr->pcs, existing);
  436 
  437 #ifdef __alpha__
  438         if (!vc->hdl.vh_mono)
  439                 /*
  440                  * DEC firmware uses a blue background.
  441                  */
  442                 res = vga_pack_attr(scr, WSCOL_WHITE, WSCOL_BLUE,
  443                                      WSATTR_WSCOLORS, attrp);
  444         else
  445 #endif
  446         res = vga_pack_attr(scr, 0, 0, 0, attrp);
  447 #ifdef DIAGNOSTIC
  448         if (res)
  449                 panic("vga_init_screen: attribute botch");
  450 #endif
  451 
  452         scr->pcs.mem = NULL;
  453 
  454         scr->fontset1 = scr->fontset2 = 0;
  455         if (vga_selectfont(vc, scr, 0, 0)) {
  456                 if (scr == &vga_console_screen)
  457                         panic("vga_init_screen: no font");
  458                 else
  459                         printf("vga_init_screen: no font\n");
  460         }
  461 
  462         vc->nscreens++;
  463         LIST_INSERT_HEAD(&vc->screens, scr, next);
  464 }
  465 
  466 void
  467 vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt)
  468 {
  469         struct vga_handle *vh = &vc->hdl;
  470         u_int8_t mor;
  471         int i;
  472 
  473         vh->vh_iot = iot;
  474         vh->vh_memt = memt;
  475 
  476         if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
  477                 panic("vga_common_setup: can't map vga i/o");
  478 
  479         /* read "misc output register" */
  480         mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc);
  481         vh->vh_mono = !(mor & 1);
  482 
  483         if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
  484                           &vh->vh_ioh_6845))
  485                 panic("vga_common_setup: can't map 6845 i/o");
  486 
  487         if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
  488                 panic("vga_common_setup: can't map mem space");
  489 
  490         if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
  491                                 (vh->vh_mono ? 0x10000 : 0x18000), 0x8000,
  492                                 &vh->vh_memh))
  493                 panic("vga_common_setup: mem subrange failed");
  494 
  495 #ifdef __alpha__
  496         vga_pick_monitor_type(vc);
  497 #endif
  498 
  499         vc->nscreens = 0;
  500         LIST_INIT(&vc->screens);
  501         vc->active = NULL;
  502 #ifdef __alpha__
  503         if (vc->custom_list.screens != NULL)
  504                 vc->currenttype = vc->custom_list.screens[0];
  505         else
  506 #endif
  507                 vc->currenttype =
  508                     vh->vh_mono ? &vga_stdscreen_mono : &vga_stdscreen;
  509 
  510         vc->vc_fonts[0] = &vga_builtinfont;
  511         for (i = 1; i < VGA_MAXFONT; i++)
  512                 vc->vc_fonts[i] = NULL;
  513 
  514         vc->currentfontset1 = vc->currentfontset2 = 0;
  515 
  516         vga_save_palette(vc);
  517 }
  518 
  519 struct vga_config *
  520 vga_common_attach(struct device *self, bus_space_tag_t iot,
  521     bus_space_tag_t memt, int type)
  522 {
  523         return vga_extended_attach(self, iot, memt, type, NULL);
  524 }
  525 
  526 struct vga_config *
  527 vga_extended_attach(struct device *self, bus_space_tag_t iot,
  528     bus_space_tag_t memt, int type, paddr_t (*map)(void *, off_t, int))
  529 {
  530         int console;
  531         struct vga_config *vc;
  532         struct wsemuldisplaydev_attach_args aa;
  533 
  534         console = vga_is_console(iot, type);
  535         if (console)
  536                 vga_console_attached = 1;
  537 
  538         if (type == -1)
  539                 return NULL;
  540 
  541         if (console) {
  542                 vc = &vga_console_vc;
  543         } else {
  544                 vc = malloc(sizeof(*vc), M_DEVBUF, M_NOWAIT | M_ZERO);
  545                 if (vc == NULL)
  546                         return NULL;
  547                 vga_init(vc, iot, memt);
  548         }
  549 
  550         vc->vc_softc = self;
  551         vc->vc_type = type;
  552         vc->vc_mmap = map;
  553 
  554         aa.console = console;
  555 #ifdef __alpha__
  556         if (vc->custom_list.screens != NULL)
  557                 aa.scrdata = &vc->custom_list;
  558         else
  559 #endif
  560                 aa.scrdata =
  561                     vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist;
  562 
  563         aa.accessops = &vga_accessops;
  564         aa.accesscookie = vc;
  565         aa.defaultscreens = 0;
  566 
  567         config_found_sm(self, &aa, wsemuldisplaydevprint,
  568             wsemuldisplaydevsubmatch);
  569 
  570         return vc;
  571 }
  572 
  573 int
  574 vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
  575 {
  576         uint32_t defattr;
  577         const struct wsscreen_descr *scr;
  578 
  579         if (check && !vga_common_probe(iot, memt))
  580                 return (ENXIO);
  581 
  582         /* set up bus-independent VGA configuration */
  583         vga_init(&vga_console_vc, iot, memt);
  584         scr = vga_console_vc.currenttype;
  585         vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
  586 
  587         vga_console_screen.pcs.active = 1;
  588         vga_console_vc.active = &vga_console_screen;
  589 
  590         wsdisplay_cnattach(scr, &vga_console_screen,
  591                            vga_console_screen.pcs.vc_ccol,
  592                            vga_console_screen.pcs.vc_crow,
  593                            defattr);
  594 
  595         vgaconsole = 1;
  596         vga_console_type = type;
  597         return (0);
  598 }
  599 
  600 int
  601 vga_is_console(bus_space_tag_t iot, int type)
  602 {
  603         if (vgaconsole &&
  604             !vga_console_attached &&
  605             iot == vga_console_vc.hdl.vh_iot &&
  606             (vga_console_type == -1 || (type == vga_console_type)))
  607                 return (1);
  608         return (0);
  609 }
  610 
  611 int
  612 vga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  613 {
  614         struct vga_config *vc = v;
  615         int mode;
  616 #if NVGA_PCI > 0
  617         int error;
  618 
  619         if (vc->vc_type == WSDISPLAY_TYPE_PCIVGA &&
  620             (error = vga_pci_ioctl(v, cmd, data, flag, p)) != ENOTTY)
  621                 return (error);
  622 #endif
  623 
  624         switch (cmd) {
  625         case WSDISPLAYIO_GTYPE:
  626                 *(int *)data = vc->vc_type;
  627                 /* XXX should get detailed hardware information here */
  628                 break;
  629 
  630         case WSDISPLAYIO_SMODE:
  631                 mode = *(u_int *)data;
  632                 if (mode == WSDISPLAYIO_MODE_EMUL) {
  633                         vga_restore_fonts(vc);
  634                         vga_restore_palette(vc);
  635                 }
  636                 break;
  637 
  638         case WSDISPLAYIO_GVIDEO:
  639         case WSDISPLAYIO_SVIDEO:
  640                 break;
  641 
  642         case WSDISPLAYIO_GINFO:
  643         case WSDISPLAYIO_GETCMAP:
  644         case WSDISPLAYIO_PUTCMAP:
  645         case WSDISPLAYIO_GCURPOS:
  646         case WSDISPLAYIO_SCURPOS:
  647         case WSDISPLAYIO_GCURMAX:
  648         case WSDISPLAYIO_GCURSOR:
  649         case WSDISPLAYIO_SCURSOR:
  650         default:
  651                 /* NONE of these operations are by the generic VGA driver. */
  652                 return ENOTTY;
  653         }
  654 
  655         return (0);
  656 }
  657 
  658 paddr_t
  659 vga_mmap(void *v, off_t offset, int prot)
  660 {
  661         struct vga_config *vc = v;
  662 
  663         if (vc->vc_mmap != NULL)
  664                 return (*vc->vc_mmap)(v, offset, prot);
  665 
  666         return (paddr_t)-1;
  667 }
  668 
  669 int
  670 vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  671     int *curxp, int *curyp, uint32_t *defattrp)
  672 {
  673         struct vga_config *vc = v;
  674         struct vgascreen *scr;
  675 
  676         if (vc->nscreens == 1) {
  677                 /*
  678                  * When allocating the second screen, get backing store
  679                  * for the first one too.
  680                  * XXX We could be more clever and use video RAM.
  681                  */
  682                 scr = LIST_FIRST(&vc->screens);
  683                 scr->pcs.mem = mallocarray(scr->pcs.type->ncols,
  684                     scr->pcs.type->nrows * 2, M_DEVBUF, M_WAITOK);
  685         }
  686 
  687         scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
  688         vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
  689 
  690         if (vc->nscreens == 1) {
  691                 scr->pcs.active = 1;
  692                 vc->active = scr;
  693                 vc->currenttype = type;
  694         } else {
  695                 scr->pcs.mem = mallocarray(type->ncols,
  696                     type->nrows * 2, M_DEVBUF, M_WAITOK);
  697                 pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
  698         }
  699 
  700         *cookiep = scr;
  701         *curxp = scr->pcs.vc_ccol;
  702         *curyp = scr->pcs.vc_crow;
  703 
  704         return (0);
  705 }
  706 
  707 void
  708 vga_free_screen(void *v, void *cookie)
  709 {
  710         struct vgascreen *vs = cookie;
  711         struct vga_config *vc = vs->cfg;
  712 
  713         LIST_REMOVE(vs, next);
  714         vc->nscreens--;
  715         if (vs != &vga_console_screen) {
  716                 /*
  717                  * deallocating the one but last screen
  718                  * removes backing store for the last one
  719                  */
  720                 if (vc->nscreens == 1)
  721                         free(LIST_FIRST(&vc->screens)->pcs.mem, M_DEVBUF, 0);
  722 
  723                 /* Last screen has no backing store */
  724                 if (vc->nscreens != 0)
  725                         free(vs->pcs.mem, M_DEVBUF, 0);
  726 
  727                 free(vs, M_DEVBUF, sizeof *vs);
  728         } else
  729                 panic("vga_free_screen: console");
  730 
  731         if (vc->active == vs)
  732                 vc->active = NULL;
  733 }
  734 
  735 void
  736 vga_setfont(struct vga_config *vc, struct vgascreen *scr)
  737 {
  738         int fontslot1, fontslot2;
  739 
  740         fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
  741         fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
  742         if (vc->currentfontset1 != fontslot1 ||
  743             vc->currentfontset2 != fontslot2) {
  744                 vga_setfontset(&vc->hdl, fontslot1, fontslot2);
  745                 vc->currentfontset1 = fontslot1;
  746                 vc->currentfontset2 = fontslot2;
  747         }
  748 }
  749 
  750 int
  751 vga_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
  752     void *cbarg)
  753 {
  754         struct vgascreen *scr = cookie, *oldscr;
  755         struct vga_config *vc = scr->cfg;
  756 
  757         oldscr = vc->active; /* can be NULL! */
  758         if (scr == oldscr) {
  759                 return (0);
  760         }
  761 
  762         vc->wantedscreen = cookie;
  763         vc->switchcb = cb;
  764         vc->switchcbarg = cbarg;
  765         if (cb) {
  766                 timeout_set(&vc->vc_switch_timeout, vga_doswitch, vc);
  767                 timeout_add(&vc->vc_switch_timeout, 0);
  768                 return (EAGAIN);
  769         }
  770 
  771         vga_doswitch(vc);
  772         return (0);
  773 }
  774 
  775 void
  776 vga_doswitch(void *arg)
  777 {
  778         struct vga_config *vc = arg;
  779         struct vgascreen *scr, *oldscr;
  780         struct vga_handle *vh = &vc->hdl;
  781         const struct wsscreen_descr *type;
  782         int s;
  783 
  784         scr = vc->wantedscreen;
  785         if (!scr) {
  786                 printf("vga_doswitch: disappeared\n");
  787                 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
  788                 return;
  789         }
  790 
  791         type = scr->pcs.type;
  792         oldscr = vc->active; /* can be NULL! */
  793         if (scr == oldscr)
  794                 return;
  795         s = spltty();
  796 #ifdef DIAGNOSTIC
  797         if (oldscr) {
  798                 if (!oldscr->pcs.active)
  799                         panic("vga_show_screen: not active");
  800                 if (oldscr->pcs.type != vc->currenttype)
  801                         panic("vga_show_screen: bad type");
  802         }
  803         if (scr->pcs.active)
  804                 panic("vga_show_screen: active");
  805 #endif
  806 
  807         scr->vga_rollover = 0;
  808 
  809         if (oldscr) {
  810                 const struct wsscreen_descr *oldtype = oldscr->pcs.type;
  811 
  812                 oldscr->pcs.active = 0;
  813                 bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
  814                                         oldscr->pcs.dispoffset, oldscr->pcs.mem,
  815                                         oldtype->ncols * oldtype->nrows);
  816         }
  817 
  818         if (vc->currenttype != type) {
  819                 vga_setscreentype(vh, type);
  820                 vc->currenttype = type;
  821         }
  822 
  823         vga_restore_fonts(vc);
  824         vga_setfont(vc, scr);
  825         vga_restore_palette(vc);
  826 
  827         scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
  828         if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
  829                 vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
  830                 vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
  831         }
  832 
  833         bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
  834                                 scr->pcs.dispoffset, scr->pcs.mem,
  835                                 type->ncols * type->nrows);
  836         scr->pcs.active = 1;
  837         splx(s);
  838 
  839         vc->active = scr;
  840 
  841         pcdisplay_cursor_reset(&scr->pcs);
  842         pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
  843                          scr->pcs.vc_crow, scr->pcs.vc_ccol);
  844 
  845         vc->wantedscreen = 0;
  846         if (vc->switchcb)
  847                 (*vc->switchcb)(vc->switchcbarg, 0, 0);
  848 }
  849 
  850 int
  851 vga_load_font(void *v, void *cookie, struct wsdisplay_font *data)
  852 {
  853         struct vga_config *vc = v;
  854         struct vgascreen *scr = cookie;
  855         char *name2;
  856         int res, slot;
  857         struct vgafont *f;
  858 
  859         if (data->data == NULL) {
  860                 if (scr == NULL)
  861                         return EINVAL;
  862 
  863                 if ((name2 = data->name) != NULL) {
  864                         while (*name2 && *name2 != ',')
  865                                 name2++;
  866                         if (*name2)
  867                                 *name2++ = '\0';
  868                 }
  869                 res = vga_selectfont(vc, scr, data->name, name2);
  870                 if (res == 0)
  871                         vga_setfont(vc, scr);
  872                 return (res);
  873         }
  874 
  875         if (data->fontwidth != 8 || data->stride != 1)
  876                 return (EINVAL); /* XXX 1 byte per line */
  877         if (data->firstchar != 0 || data->numchars != 256)
  878                 return (EINVAL);
  879 
  880         if (data->index < 0) {
  881                 for (slot = 0; slot < VGA_MAXFONT; slot++)
  882                         if (!vc->vc_fonts[slot])
  883                                 break;
  884         } else
  885                 slot = data->index;
  886 
  887         if (slot >= VGA_MAXFONT)
  888                 return (ENOSPC);
  889 
  890         if (vc->vc_fonts[slot] != NULL)
  891                 return (EEXIST);
  892         f = malloc(sizeof(struct vgafont), M_DEVBUF, M_WAITOK | M_CANFAIL);
  893         if (f == NULL)
  894                 return (ENOMEM);
  895         strlcpy(f->name, data->name, sizeof(f->name));
  896         f->height = data->fontheight;
  897         f->encoding = data->encoding;
  898 #ifdef notyet
  899         f->firstchar = data->firstchar;
  900         f->numchars = data->numchars;
  901 #endif
  902 #ifdef VGAFONTDEBUG
  903         printf("vga: load %s (8x%d, enc %d) font to slot %d\n", f->name,
  904                f->height, f->encoding, slot);
  905 #endif
  906         vga_loadchars(&vc->hdl, slot, 0, 256, f->height, data->data);
  907         f->slot = slot;
  908         f->fontdata = data->data;
  909         vc->vc_fonts[slot] = f;
  910         data->cookie = f;
  911         data->index = slot;
  912 
  913         return (0);
  914 }
  915 
  916 int
  917 vga_list_font(void *v, struct wsdisplay_font *data)
  918 {
  919         struct vga_config *vc = v;
  920         struct vgafont *f;
  921 
  922         if (data->index < 0 || data->index >= VGA_MAXFONT)
  923                 return EINVAL;
  924 
  925         if ((f = vc->vc_fonts[data->index]) == NULL)
  926                 return EINVAL;
  927 
  928         strlcpy(data->name, f->name, sizeof data->name);
  929 #ifdef notyet
  930         data->firstchar = f->firstchar;
  931         data->numchars = f->numchars;
  932 #else
  933         data->firstchar = 0;
  934         data->numchars = 256;
  935 #endif
  936         data->encoding = f->encoding;
  937         data->fontwidth = 8;
  938         data->fontheight = f->height;
  939         data->stride = 1;
  940         data->bitorder = data->byteorder = WSDISPLAY_FONTORDER_L2R;
  941 
  942         return (0);
  943 }
  944 
  945 void
  946 vga_scrollback(void *v, void *cookie, int lines)
  947 {
  948         struct vga_config *vc = v;
  949         struct vgascreen *scr = cookie;
  950         struct vga_handle *vh = &vc->hdl;
  951 
  952         if (lines == 0) {
  953                 if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
  954                         return;
  955 
  956                 scr->pcs.visibleoffset = scr->pcs.dispoffset;   /* reset */
  957         }
  958         else {
  959                 int vga_scr_end;
  960                 int margin = scr->pcs.type->ncols * 2;
  961                 int ul, we, p, st;
  962 
  963                 vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
  964                     scr->pcs.type->nrows * 2);
  965                 if (scr->vga_rollover > vga_scr_end + margin) {
  966                         ul = vga_scr_end;
  967                         we = scr->vga_rollover + scr->pcs.type->ncols * 2;
  968                 } else {
  969                         ul = 0;
  970                         we = 0x8000;
  971                 }
  972                 p = (scr->pcs.visibleoffset - ul + we) % we + lines *
  973                     (scr->pcs.type->ncols * 2);
  974                 st = (scr->pcs.dispoffset - ul + we) % we;
  975                 if (p < margin)
  976                         p = 0;
  977                 if (p > st - margin)
  978                         p = st;
  979                 scr->pcs.visibleoffset = (p + ul) % we;
  980         }
  981         
  982         /* update visible position */
  983         vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
  984         vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
  985 }
  986 
  987 int
  988 vga_pack_attr(void *id, int fg, int bg, int flags, uint32_t *attrp)
  989 {
  990         struct vgascreen *scr = id;
  991         struct vga_config *vc = scr->cfg;
  992 
  993         if (vc->hdl.vh_mono) {
  994                 if (flags & WSATTR_WSCOLORS)
  995                         return (EINVAL);
  996                 if (flags & WSATTR_REVERSE)
  997                         *attrp = 0x70;
  998                 else
  999                         *attrp = 0x07;
 1000                 if (flags & WSATTR_UNDERLINE)
 1001                         *attrp |= FG_UNDERLINE;
 1002                 if (flags & WSATTR_HILIT)
 1003                         *attrp |= FG_INTENSE;
 1004         } else {
 1005                 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
 1006                         return (EINVAL);
 1007                 if (flags & WSATTR_WSCOLORS)
 1008                         *attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7];
 1009                 else
 1010                         *attrp = 7;
 1011                 if ((flags & WSATTR_HILIT) || (fg & 8) || (bg & 8))
 1012                         *attrp += 8;
 1013         }
 1014         if (flags & WSATTR_BLINK)
 1015                 *attrp |= FG_BLINK;
 1016         return (0);
 1017 }
 1018 
 1019 void
 1020 vga_unpack_attr(void *id, uint32_t attr, int *fg, int *bg, int *ul)
 1021 {
 1022         struct vgascreen *scr = id;
 1023         struct vga_config *vc = scr->cfg;
 1024 
 1025         if (vc->hdl.vh_mono) {
 1026                 *fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE : WSCOL_BLACK;
 1027                 *bg = attr & 0x70 ? WSCOL_WHITE : WSCOL_BLACK;
 1028                 if (ul != NULL)
 1029                         *ul = *fg != WSCOL_WHITE && (attr & 0x01) ? 1 : 0;
 1030         } else {
 1031                 *fg = pctoansi[attr & 0x07];
 1032                 *bg = pctoansi[(attr & 0x70) >> 4];
 1033                 if (ul != NULL)
 1034                         *ul = 0;
 1035         }
 1036         if (attr & FG_INTENSE)
 1037                 *fg += 8;
 1038 }
 1039 
 1040 int
 1041 vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
 1042 {
 1043         struct vgascreen *scr = id;
 1044         bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
 1045         bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
 1046         int ncols = scr->pcs.type->ncols;
 1047         bus_size_t srcoff, dstoff;
 1048         int s;
 1049 
 1050         srcoff = srcrow * ncols + 0;
 1051         dstoff = dstrow * ncols + 0;
 1052 
 1053         s = spltty();
 1054         if (scr->pcs.active) {
 1055                 if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
 1056 #ifdef PCDISPLAY_SOFTCURSOR
 1057                         int cursoron = scr->pcs.cursoron;
 1058 
 1059                         /* NOTE this assumes pcdisplay_cursor() never fails */
 1060                         if (cursoron)
 1061                                 pcdisplay_cursor(&scr->pcs, 0,
 1062                                     scr->pcs.vc_crow, scr->pcs.vc_ccol);
 1063 #endif
 1064                         /* scroll up whole screen */
 1065                         if ((scr->pcs.dispoffset + srcrow * ncols * 2)
 1066                             <= scr->maxdispoffset) {
 1067                                 scr->pcs.dispoffset += srcrow * ncols * 2;
 1068                         } else {
 1069                                 bus_space_copy_2(memt, memh,
 1070                                         scr->pcs.dispoffset + srcoff * 2,
 1071                                         memh, scr->mindispoffset,
 1072                                         nrows * ncols);
 1073                                 scr->vga_rollover = scr->pcs.dispoffset;
 1074                                 scr->pcs.dispoffset = scr->mindispoffset;
 1075                         }
 1076                         scr->pcs.visibleoffset = scr->pcs.dispoffset;
 1077                         vga_6845_write(&scr->cfg->hdl, startadrh,
 1078                                        scr->pcs.dispoffset >> 9);
 1079                         vga_6845_write(&scr->cfg->hdl, startadrl,
 1080                                        scr->pcs.dispoffset >> 1);
 1081 #ifdef PCDISPLAY_SOFTCURSOR
 1082                         /* NOTE this assumes pcdisplay_cursor() never fails */
 1083                         if (cursoron)
 1084                                 pcdisplay_cursor(&scr->pcs, 1,
 1085                                     scr->pcs.vc_crow, scr->pcs.vc_ccol);
 1086 #endif
 1087                 } else {
 1088                         bus_space_copy_2(memt, memh,
 1089                                         scr->pcs.dispoffset + srcoff * 2,
 1090                                         memh, scr->pcs.dispoffset + dstoff * 2,
 1091                                         nrows * ncols);
 1092                 }
 1093         } else
 1094                 bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff],
 1095                       nrows * ncols * 2);
 1096         splx(s);
 1097 
 1098         return 0;
 1099 }
 1100 
 1101 int _vga_mapchar(void *, struct vgafont *, int, unsigned int *);
 1102 
 1103 int
 1104 _vga_mapchar(void *id, struct vgafont *font, int uni, unsigned int *index)
 1105 {
 1106 
 1107         switch (font->encoding) {
 1108         case WSDISPLAY_FONTENC_ISO:
 1109                 if (uni < 256) {
 1110                         *index = uni;
 1111                         return (5);
 1112                 } else {
 1113                         *index = '?';
 1114                         return (0);
 1115                 }
 1116                 break;
 1117         case WSDISPLAY_FONTENC_IBM:
 1118                 return (pcdisplay_mapchar(id, uni, index));
 1119         default:
 1120 #ifdef VGAFONTDEBUG
 1121                 printf("_vga_mapchar: encoding=%d\n", font->encoding);
 1122 #endif
 1123                 *index = '?';
 1124                 return (0);
 1125         }
 1126 }
 1127 
 1128 int
 1129 vga_mapchar(void *id, int uni, unsigned int *index)
 1130 {
 1131         struct vgascreen *scr = id;
 1132         unsigned int idx1, idx2;
 1133         int res1, res2;
 1134 
 1135         res1 = 0;
 1136         idx1 = ' '; /* space */
 1137         if (scr->fontset1)
 1138                 res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
 1139         res2 = -1;
 1140         if (scr->fontset2) {
 1141                 KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
 1142                 res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
 1143         }
 1144         if (res2 >= res1) {
 1145                 *index = idx2 | 0x0800; /* attribute bit 3 */
 1146                 return (res2);
 1147         }
 1148         *index = idx1;
 1149         return (res1);
 1150 }
 1151 
 1152 int
 1153 vga_putchar(void *c, int row, int col, u_int uc, uint32_t attr)
 1154 {
 1155         struct vgascreen *scr = c;
 1156         int rc;
 1157         int s;
 1158         
 1159         s = spltty();
 1160         if (scr->pcs.active && scr->pcs.visibleoffset != scr->pcs.dispoffset)
 1161                 vga_scrollback(scr->cfg, scr, 0);
 1162         rc = pcdisplay_putchar(c, row, col, uc, attr);
 1163         splx(s);
 1164 
 1165         return rc;
 1166 }
 1167 
 1168 void
 1169 vga_burner(void *v, u_int on, u_int flags)
 1170 {
 1171         struct vga_config *vc = v;
 1172         struct vga_handle *vh = &vc->hdl;
 1173         u_int8_t r;
 1174         int s;
 1175 
 1176         s = splhigh();
 1177         vga_ts_write(vh, syncreset, 0x01);
 1178         if (on) {
 1179                 vga_ts_write(vh, mode, (vga_ts_read(vh, mode) & ~0x20));
 1180                 r = vga_6845_read(vh, mode) | 0x80;
 1181                 DELAY(10000);
 1182                 vga_6845_write(vh, mode, r);
 1183         } else {
 1184                 vga_ts_write(vh, mode, (vga_ts_read(vh, mode) | 0x20));
 1185                 if (flags & WSDISPLAY_BURN_VBLANK) {
 1186                         r = vga_6845_read(vh, mode) & ~0x80;
 1187                         DELAY(10000);
 1188                         vga_6845_write(vh, mode, r);
 1189                 }
 1190         }
 1191         vga_ts_write(vh, syncreset, 0x03);
 1192         splx(s);
 1193 }
 1194 
 1195 int
 1196 vga_getchar(void *c, int row, int col, struct wsdisplay_charcell *cell)
 1197 {
 1198         struct vga_config *vc = c;
 1199         
 1200         return (pcdisplay_getchar(vc->active, row, col, cell));
 1201 }       
 1202 
 1203 void
 1204 vga_save_palette(struct vga_config *vc)
 1205 {
 1206         struct vga_handle *vh = &vc->hdl;
 1207         uint i;
 1208         uint8_t *palette = vc->vc_palette;
 1209 
 1210         if (vh->vh_mono)
 1211                 return;
 1212 
 1213         vga_raw_write(vh, VGA_DAC_MASK, 0xff);
 1214         vga_raw_write(vh, VGA_DAC_READ, 0x00);
 1215         for (i = 0; i < 3 * 256; i++)
 1216                 *palette++ = vga_raw_read(vh, VGA_DAC_DATA);
 1217 }
 1218 
 1219 void
 1220 vga_restore_palette(struct vga_config *vc)
 1221 {
 1222         struct vga_handle *vh = &vc->hdl;
 1223         uint i;
 1224         uint8_t *palette = vc->vc_palette;
 1225 
 1226         if (vh->vh_mono)
 1227                 return;
 1228 
 1229         vga_raw_write(vh, VGA_DAC_MASK, 0xff);
 1230         vga_raw_write(vh, VGA_DAC_WRITE, 0x00);
 1231         for (i = 0; i < 3 * 256; i++)
 1232                 vga_raw_write(vh, VGA_DAC_DATA, *palette++);
 1233 }
 1234 
 1235 void
 1236 vga_restore_fonts(struct vga_config *vc)
 1237 {
 1238         int slot;
 1239         struct vgafont *f;
 1240 
 1241         for (slot = 0; slot < VGA_MAXFONT; slot++) {
 1242                 f = vc->vc_fonts[slot];
 1243                 if (f == NULL || f->fontdata == NULL)
 1244                         continue;
 1245 
 1246                 vga_loadchars(&vc->hdl, slot, 0, 256, f->height, f->fontdata);
 1247         }
 1248 }
 1249 
 1250 #ifdef __alpha__
 1251 void
 1252 vga_pick_monitor_type(struct vga_config *vc)
 1253 {
 1254         struct vga_handle *vh = &vc->hdl;
 1255 
 1256         /*
 1257          * The Tadpole Alphabook1 uses a 800x600 flat panel in text mode,
 1258          * causing the display console to really be 100x37 instead of the
 1259          * usual 80x25.
 1260          * We attempt to detect this here by checking the CRTC registers.
 1261          */
 1262         unsigned int hend, oflow, vend;
 1263         unsigned int width, height;
 1264 
 1265         hend = vga_6845_read(vh, hdisple);
 1266         oflow = vga_6845_read(vh, overfll);
 1267         vend = vga_6845_read(vh, vde);
 1268         if (oflow & 0x02)
 1269                 vend |= 0x100;
 1270         if (oflow & 0x40)
 1271                 vend |= 0x200;
 1272 
 1273         width = hend + 1;
 1274         height = (vend + 1) / 16;
 1275 
 1276         /* check that the values sound plausible */
 1277         if ((width > 80 && width <= 128) && (height > 25 && height <= 50)) {
 1278                 snprintf(vc->custom_scr.name, sizeof(vc->custom_scr.name),
 1279                     "%ux%u", width, height);
 1280                 vc->custom_scr.ncols = width;
 1281                 vc->custom_scr.nrows = height;
 1282                 vc->custom_scr.textops = &vga_emulops;
 1283                 vc->custom_scr.fontwidth = 8;
 1284                 vc->custom_scr.fontheight = 16;
 1285                 vc->custom_scr.capabilities =
 1286                     WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK;
 1287                 vc->custom_scrlist[0] = &vc->custom_scr;
 1288                 vc->custom_list.nscreens = 1;
 1289                 vc->custom_list.screens =
 1290                     (const struct wsscreen_descr **)vc->custom_scrlist;
 1291         }
 1292 }
 1293 #endif
 1294 
 1295 struct cfdriver vga_cd = {
 1296         NULL, "vga", DV_DULL
 1297 };

Cache object: 0f14d8f5ab89e82f9c69841274e4e82f


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