root/dev/isa/ega.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ega_probe_col
  2. ega_probe_mono
  3. ega_selectfont
  4. ega_init_screen
  5. ega_init
  6. ega_match
  7. ega_attach
  8. ega_cnattach
  9. ega_is_console
  10. ega_ioctl
  11. ega_mmap
  12. ega_alloc_screen
  13. ega_free_screen
  14. ega_setfont
  15. ega_show_screen
  16. ega_doswitch
  17. ega_load_font
  18. ega_alloc_attr
  19. ega_unpack_attr
  20. ega_copyrows

    1 /* $OpenBSD: ega.c,v 1.12 2007/02/06 22:03:24 miod Exp $ */
    2 /* $NetBSD: ega.c,v 1.4.4.1 2000/06/30 16:27:47 simonb Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1999
    6  *      Matthias Drochner.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/device.h>
   34 #include <sys/malloc.h>
   35 #include <sys/timeout.h>
   36 #include <machine/bus.h>
   37 
   38 #include <dev/isa/isavar.h>
   39 
   40 #include <dev/ic/mc6845reg.h>
   41 #include <dev/ic/pcdisplayvar.h>
   42 #include <dev/ic/vgareg.h>
   43 #include <dev/ic/vgavar.h>
   44 #include <dev/isa/egavar.h>
   45 
   46 #include <dev/ic/pcdisplay.h>
   47 
   48 #include <dev/wscons/wsconsio.h>
   49 #include <dev/wscons/wsdisplayvar.h>
   50 
   51 static struct egafont {
   52         char name[WSFONT_NAME_SIZE];
   53         int height;
   54         int encoding;
   55         int slot;
   56 } ega_builtinfont = {
   57         "builtin",
   58         14,
   59         WSDISPLAY_FONTENC_IBM,
   60         0
   61 };
   62 
   63 struct egascreen {
   64         struct pcdisplayscreen pcs;
   65         LIST_ENTRY(egascreen) next;
   66         struct ega_config *cfg;
   67         struct egafont *fontset1, *fontset2;
   68 
   69         int mindispoffset, maxdispoffset;
   70 };
   71 
   72 struct ega_config {
   73         struct vga_handle hdl;
   74 
   75         int nscreens;
   76         LIST_HEAD(, egascreen) screens;
   77         struct egascreen *active; /* current display */
   78         const struct wsscreen_descr *currenttype;
   79         int currentfontset1, currentfontset2;
   80 
   81         struct egafont *vc_fonts[4];
   82 
   83         struct egascreen *wantedscreen;
   84         void (*switchcb)(void *, int, int);
   85         void *switchcbarg;
   86 
   87         struct timeout switch_timeout;
   88 };
   89 
   90 struct ega_softc {
   91         struct device sc_dev;
   92         struct ega_config *sc_dc;
   93         int nscreens;
   94 };
   95 
   96 static int egaconsole, ega_console_attached;
   97 static struct egascreen ega_console_screen;
   98 static struct ega_config ega_console_dc;
   99 
  100 int     ega_match(struct device *, void *, void *);
  101 void    ega_attach(struct device *, struct device *, void *);
  102 
  103 static int ega_is_console(bus_space_tag_t);
  104 static int ega_probe_col(bus_space_tag_t, bus_space_tag_t);
  105 static int ega_probe_mono(bus_space_tag_t, bus_space_tag_t);
  106 int ega_selectfont(struct ega_config *, struct egascreen *,
  107                         char *, char *);
  108 void ega_init_screen(struct ega_config *, struct egascreen *,
  109                           const struct wsscreen_descr *,
  110                           int, long *);
  111 static void ega_init(struct ega_config *,
  112                           bus_space_tag_t, bus_space_tag_t, int);
  113 static void ega_setfont(struct ega_config *, struct egascreen *);
  114 static int ega_alloc_attr(void *, int, int, int, long *);
  115 static void ega_unpack_attr(void *, long, int *, int *, int *);
  116 void ega_copyrows(void *, int, int, int);
  117 
  118 struct cfattach ega_ca = {
  119         sizeof(struct ega_softc), ega_match, ega_attach,
  120 };
  121 
  122 struct cfdriver ega_cd = {
  123         NULL, "ega", DV_DULL,
  124 };
  125 
  126 const struct wsdisplay_emulops ega_emulops = {
  127         pcdisplay_cursor,
  128         pcdisplay_mapchar,
  129         pcdisplay_putchar,
  130         pcdisplay_copycols,
  131         pcdisplay_erasecols,
  132         ega_copyrows,
  133         pcdisplay_eraserows,
  134         ega_alloc_attr,
  135         ega_unpack_attr
  136 };
  137 
  138 /*
  139  * translate WS(=ANSI) color codes to standard pc ones
  140  */
  141 static const unsigned char fgansitopc[] = {
  142         FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
  143         FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
  144 }, bgansitopc[] = {
  145         BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
  146         BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
  147 };
  148 
  149 /*
  150  * translate standard pc color codes to WS(=ANSI) ones
  151  */
  152 static const u_int8_t pctoansi[] = {
  153 #ifdef __alpha__
  154         WSCOL_BLACK, WSCOL_RED, WSCOL_GREEN, WSCOL_BROWN,
  155         WSCOL_BLUE, WSCOL_MAGENTA, WSCOL_CYAN, WSCOL_WHITE
  156 #else
  157         WSCOL_BLACK, WSCOL_BLUE, WSCOL_GREEN, WSCOL_CYAN,
  158         WSCOL_RED, WSCOL_MAGENTA, WSCOL_BROWN, WSCOL_WHITE
  159 #endif
  160 };
  161 const struct wsscreen_descr ega_stdscreen = {
  162         "80x25", 80, 25,
  163         &ega_emulops,
  164         8, 14,
  165         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  166 }, ega_stdscreen_mono = {
  167         "80x25", 80, 25,
  168         &ega_emulops,
  169         8, 14,
  170         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  171 }, ega_stdscreen_bf = {
  172         "80x25bf", 80, 25,
  173         &ega_emulops,
  174         8, 14,
  175         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  176 }, ega_35lscreen = {
  177         "80x35", 80, 35,
  178         &ega_emulops,
  179         8, 10,
  180         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  181 }, ega_35lscreen_mono = {
  182         "80x35", 80, 35,
  183         &ega_emulops,
  184         8, 10,
  185         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  186 }, ega_35lscreen_bf = {
  187         "80x35bf", 80, 35,
  188         &ega_emulops,
  189         8, 10,
  190         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  191 }, ega_43lscreen = {
  192         "80x43", 80, 43,
  193         &ega_emulops,
  194         8, 8,
  195         WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
  196 }, ega_43lscreen_mono = {
  197         "80x43", 80, 43,
  198         &ega_emulops,
  199         8, 8,
  200         WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
  201 }, ega_43lscreen_bf = {
  202         "80x43bf", 80, 43,
  203         &ega_emulops,
  204         8, 8,
  205         WSSCREEN_WSCOLORS | WSSCREEN_BLINK
  206 };
  207 
  208 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
  209 
  210 const struct wsscreen_descr *_ega_scrlist[] = {
  211         &ega_stdscreen,
  212         &ega_stdscreen_bf,
  213         &ega_35lscreen,
  214         &ega_35lscreen_bf,
  215         &ega_43lscreen,
  216         &ega_43lscreen_bf,
  217 }, *_ega_scrlist_mono[] = {
  218         &ega_stdscreen_mono,
  219         &ega_35lscreen_mono,
  220         &ega_43lscreen_mono,
  221 };
  222 
  223 
  224 const struct wsscreen_list ega_screenlist = {
  225         sizeof(_ega_scrlist) / sizeof(struct wsscreen_descr *),
  226         _ega_scrlist
  227 }, ega_screenlist_mono = {
  228         sizeof(_ega_scrlist_mono) / sizeof(struct wsscreen_descr *),
  229         _ega_scrlist_mono
  230 };
  231 
  232 static int ega_ioctl(void *, u_long, caddr_t, int, struct proc *);
  233 static paddr_t ega_mmap(void *, off_t, int);
  234 static int ega_alloc_screen(void *, const struct wsscreen_descr *,
  235                             void **, int *, int *, long *);
  236 static void ega_free_screen(void *, void *);
  237 static int ega_show_screen(void *, void *, int,
  238                            void (*) (void *, int, int), void *);
  239 static int ega_load_font(void *, void *, struct wsdisplay_font *);
  240 
  241 void ega_doswitch(struct ega_config *);
  242 
  243 const struct wsdisplay_accessops ega_accessops = {
  244         ega_ioctl,
  245         ega_mmap,
  246         ega_alloc_screen,
  247         ega_free_screen,
  248         ega_show_screen,
  249         ega_load_font
  250 };
  251 
  252 static int
  253 ega_probe_col(iot, memt)
  254         bus_space_tag_t iot, memt;
  255 {
  256         bus_space_handle_t memh, ioh_6845;
  257         u_int16_t oldval, val;
  258 
  259         if (bus_space_map(memt, 0xb8000, 0x8000, 0, &memh))
  260                 return (0);
  261         oldval = bus_space_read_2(memt, memh, 0);
  262         bus_space_write_2(memt, memh, 0, 0xa55a);
  263         val = bus_space_read_2(memt, memh, 0);
  264         bus_space_write_2(memt, memh, 0, oldval);
  265         bus_space_unmap(memt, memh, 0x8000);
  266         if (val != 0xa55a)
  267                 return (0);
  268 
  269         if (bus_space_map(iot, 0x3d0, 0x10, 0, &ioh_6845))
  270                 return (0);
  271         bus_space_unmap(iot, ioh_6845, 0x10);
  272 
  273         return (1);
  274 }
  275 
  276 static int
  277 ega_probe_mono(iot, memt)
  278         bus_space_tag_t iot, memt;
  279 {
  280         bus_space_handle_t memh, ioh_6845;
  281         u_int16_t oldval, val;
  282 
  283         if (bus_space_map(memt, 0xb0000, 0x8000, 0, &memh))
  284                 return (0);
  285         oldval = bus_space_read_2(memt, memh, 0);
  286         bus_space_write_2(memt, memh, 0, 0xa55a);
  287         val = bus_space_read_2(memt, memh, 0);
  288         bus_space_write_2(memt, memh, 0, oldval);
  289         bus_space_unmap(memt, memh, 0x8000);
  290         if (val != 0xa55a)
  291                 return (0);
  292 
  293         if (bus_space_map(iot, 0x3b0, 0x10, 0, &ioh_6845))
  294                 return (0);
  295         bus_space_unmap(iot, ioh_6845, 0x10);
  296 
  297         return (1);
  298 }
  299 /*
  300  * We want at least ASCII 32..127 be present in the
  301  * first font slot.
  302  */
  303 #define vga_valid_primary_font(f) \
  304         (f->encoding == WSDISPLAY_FONTENC_IBM || \
  305         f->encoding == WSDISPLAY_FONTENC_ISO)
  306 
  307 int
  308 ega_selectfont(vc, scr, name1, name2)
  309         struct ega_config *vc;
  310         struct egascreen *scr;
  311         char *name1, *name2; /* NULL: take first found */
  312 {
  313         const struct wsscreen_descr *type = scr->pcs.type;
  314         struct egafont *f1, *f2;
  315         int i;
  316 
  317         f1 = f2 = 0;
  318 
  319         for (i = 0; i < 4; i++) {
  320                 struct egafont *f = vc->vc_fonts[i];
  321                 if (!f || f->height != type->fontheight)
  322                         continue;
  323                 if (!f1 &&
  324                     vga_valid_primary_font(f) &&
  325                     (!name1 || !strcmp(name1, f->name))) {
  326                         f1 = f;
  327                         continue;
  328                 }
  329                 if (!f2 &&
  330                     VGA_SCREEN_CANTWOFONTS(type) &&
  331                     (!name2 || !strcmp(name2, f->name))) {
  332                         f2 = f;
  333                         continue;
  334                 }
  335         }
  336 
  337         /*
  338          * The request fails if no primary font was found,
  339          * or if a second font was requested but not found.
  340          */
  341         if (f1 && (!name2 || f2)) {
  342 #ifdef EGAFONTDEBUG
  343                 if (scr != &ega_console_screen || ega_console_attached) {
  344                         printf("ega (%s): font1=%s (slot %d)", type->name,
  345                                f1->name, f1->slot);
  346                         if (f2)
  347                                 printf(", font2=%s (slot %d)",
  348                                        f2->name, f2->slot);
  349                         printf("\n");
  350                 }
  351 #endif
  352                 scr->fontset1 = f1;
  353                 scr->fontset2 = f2;
  354                 return (0);
  355         }
  356         return (ENXIO);
  357 }
  358 
  359 void
  360 ega_init_screen(vc, scr, type, existing, attrp)
  361         struct ega_config *vc;
  362         struct egascreen *scr;
  363         const struct wsscreen_descr *type;
  364         int existing;
  365         long *attrp;
  366 {
  367         int cpos;
  368         int res;
  369 
  370         scr->cfg = vc;
  371         scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
  372         scr->pcs.type = type;
  373         scr->pcs.active = 0;
  374         scr->mindispoffset = 0;
  375         scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
  376 
  377         if (existing) {
  378                 cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
  379                 cpos |= vga_6845_read(&vc->hdl, cursorl);
  380 
  381                 /* make sure we have a valid cursor position */
  382                 if (cpos < 0 || cpos >= type->nrows * type->ncols)
  383                         cpos = 0;
  384 
  385                 scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
  386                 scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
  387 
  388                 /* make sure we have a valid memory offset */
  389                 if (scr->pcs.dispoffset < scr->mindispoffset ||
  390                     scr->pcs.dispoffset > scr->maxdispoffset)
  391                         scr->pcs.dispoffset = scr->mindispoffset;
  392         } else {
  393                 cpos = 0;
  394                 scr->pcs.dispoffset = scr->mindispoffset;
  395         }
  396 
  397         scr->pcs.vc_crow = cpos / type->ncols;
  398         scr->pcs.vc_ccol = cpos % type->ncols;
  399         pcdisplay_cursor_init(&scr->pcs, existing);
  400 
  401         res = ega_alloc_attr(scr, 0, 0, 0, attrp);
  402 #ifdef DIAGNOSTIC
  403         if (res)
  404                 panic("ega_init_screen: attribute botch");
  405 #endif
  406 
  407         scr->pcs.mem = NULL;
  408 
  409         scr->fontset1 = scr->fontset2 = 0;
  410         if (ega_selectfont(vc, scr, 0, 0)) {
  411                 if (scr == &ega_console_screen)
  412                         panic("ega_init_screen: no font");
  413                 else
  414                         printf("ega_init_screen: no font\n");
  415         }
  416 
  417         vc->nscreens++;
  418         LIST_INSERT_HEAD(&vc->screens, scr, next);
  419 }
  420 
  421 static void
  422 ega_init(vc, iot, memt, mono)
  423         struct ega_config *vc;
  424         bus_space_tag_t iot, memt;
  425         int mono;
  426 {
  427         struct vga_handle *vh = &vc->hdl;
  428         int i;
  429 
  430         vh->vh_iot = iot;
  431         vh->vh_memt = memt;
  432         vh->vh_mono = mono;
  433 
  434         if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
  435                 panic("ega_common_setup: couldn't map ega io");
  436 
  437         if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
  438                           &vh->vh_ioh_6845))
  439                 panic("ega_common_setup: couldn't map 6845 io");
  440 
  441         if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
  442                 panic("ega_common_setup: couldn't map memory");
  443 
  444         if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
  445                                 (vh->vh_mono ? 0x10000 : 0x18000), 0x8000,
  446                                 &vh->vh_memh))
  447                 panic("ega_common_setup: mem subrange failed");
  448 
  449         vc->nscreens = 0;
  450         LIST_INIT(&vc->screens);
  451         vc->active = NULL;
  452         vc->currenttype = vh->vh_mono ? &ega_stdscreen_mono : &ega_stdscreen;
  453 
  454         vc->vc_fonts[0] = &ega_builtinfont;
  455         for (i = 1; i < 4; i++)
  456                 vc->vc_fonts[i] = 0;
  457 
  458         vc->currentfontset1 = vc->currentfontset2 = 0;
  459 }
  460 
  461 int
  462 ega_match(parent, match, aux)
  463         struct device *parent;
  464         void *match;
  465         void *aux;
  466 {
  467         struct isa_attach_args *ia = aux;
  468         int mono;
  469 
  470         /* If values are hardwired to something that they can't be, punt. */
  471         if ((ia->ia_iobase != IOBASEUNK &&
  472              ia->ia_iobase != 0x3d0 &&
  473              ia->ia_iobase != 0x3b0) ||
  474             /* ia->ia_iosize != 0 || XXX isa.c */
  475             (ia->ia_maddr != MADDRUNK &&
  476              ia->ia_maddr != 0xb8000 &&
  477              ia->ia_maddr != 0xb0000) ||
  478             (ia->ia_msize != 0 && ia->ia_msize != 0x8000) ||
  479             ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK)
  480                 return (0);
  481 
  482         if (ega_is_console(ia->ia_iot))
  483                 mono = ega_console_dc.hdl.vh_mono;
  484         else if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 &&
  485                  ega_probe_col(ia->ia_iot, ia->ia_memt))
  486                 mono = 0;
  487         else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 &&
  488                 ega_probe_mono(ia->ia_iot, ia->ia_memt))
  489                 mono = 1;
  490         else
  491                 return (0);
  492 
  493         ia->ia_iobase = mono ? 0x3b0 : 0x3d0;
  494         ia->ia_iosize = 0x10;
  495         ia->ia_maddr = mono ? 0xb0000 : 0xb8000;
  496         ia->ia_msize = 0x8000;
  497         return (2); /* beat pcdisplay */
  498 }
  499 
  500 void
  501 ega_attach(parent, self, aux)
  502         struct device *parent, *self;
  503         void *aux;
  504 {
  505         struct isa_attach_args *ia = aux;
  506         struct ega_softc *sc = (struct ega_softc *)self;
  507         int console;
  508         struct ega_config *dc;
  509         struct wsemuldisplaydev_attach_args aa;
  510 
  511         printf("\n");
  512 
  513         console = ega_is_console(ia->ia_iot);
  514 
  515         if (console) {
  516                 dc = &ega_console_dc;
  517                 sc->nscreens = 1;
  518                 ega_console_attached = 1;
  519         } else {
  520                 dc = malloc(sizeof(struct ega_config),
  521                             M_DEVBUF, M_WAITOK);
  522                 if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 &&
  523                     ega_probe_col(ia->ia_iot, ia->ia_memt))
  524                         ega_init(dc, ia->ia_iot, ia->ia_memt, 0);
  525                 else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 &&
  526                          ega_probe_mono(ia->ia_iot, ia->ia_memt))
  527                         ega_init(dc, ia->ia_iot, ia->ia_memt, 1);
  528                 else
  529                         panic("ega_attach: display disappeared");
  530         }
  531         sc->sc_dc = dc;
  532 
  533         aa.console = console;
  534         aa.scrdata = &ega_screenlist;
  535         aa.accessops = &ega_accessops;
  536         aa.accesscookie = dc;
  537         aa.defaultscreens = 0;
  538 
  539         config_found(self, &aa, wsemuldisplaydevprint);
  540 }
  541 
  542 
  543 int
  544 ega_cnattach(iot, memt)
  545         bus_space_tag_t iot, memt;
  546 {
  547         int mono;
  548         long defattr;
  549         const struct wsscreen_descr *scr;
  550 
  551         if (ega_probe_col(iot, memt))
  552                 mono = 0;
  553         else if (ega_probe_mono(iot, memt))
  554                 mono = 1;
  555         else
  556                 return (ENXIO);
  557 
  558         ega_init(&ega_console_dc, iot, memt, mono);
  559         scr = ega_console_dc.currenttype;
  560         ega_init_screen(&ega_console_dc, &ega_console_screen, scr, 1, &defattr);
  561 
  562         ega_console_screen.pcs.active = 1;
  563         ega_console_dc.active = &ega_console_screen;
  564 
  565         wsdisplay_cnattach(scr, &ega_console_screen,
  566                            ega_console_screen.pcs.vc_ccol,
  567                            ega_console_screen.pcs.vc_crow,
  568                            defattr);
  569 
  570         egaconsole = 1;
  571         return (0);
  572 }
  573 
  574 static int
  575 ega_is_console(iot)
  576         bus_space_tag_t iot;
  577 {
  578         if (egaconsole &&
  579             !ega_console_attached &&
  580             iot == ega_console_dc.hdl.vh_iot)
  581                 return (1);
  582         return (0);
  583 }
  584 
  585 static int
  586 ega_ioctl(v, cmd, data, flag, p)
  587         void *v;
  588         u_long cmd;
  589         caddr_t data;
  590         int flag;
  591         struct proc *p;
  592 {
  593         /*
  594          * XXX "do something!"
  595          */
  596         return (-1);
  597 }
  598 
  599 static paddr_t
  600 ega_mmap(v, offset, prot)
  601         void *v;
  602         off_t offset;
  603         int prot;
  604 {
  605         return (-1);
  606 }
  607 
  608 static int
  609 ega_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
  610         void *v;
  611         const struct wsscreen_descr *type;
  612         void **cookiep;
  613         int *curxp, *curyp;
  614         long *defattrp;
  615 {
  616         struct ega_config *vc = v;
  617         struct egascreen *scr;
  618 
  619         if (vc->nscreens == 1) {
  620                 /*
  621                  * When allocating the second screen, get backing store
  622                  * for the first one too.
  623                  * XXX We could be more clever and use video RAM.
  624                  */
  625                 LIST_FIRST(&vc->screens)->pcs.mem =
  626                   malloc(type->ncols * type->nrows * 2, M_DEVBUF, M_WAITOK);
  627         }
  628 
  629         scr = malloc(sizeof(struct egascreen), M_DEVBUF, M_WAITOK);
  630         ega_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
  631 
  632         if (vc->nscreens == 1) {
  633                 scr->pcs.active = 1;
  634                 vc->active = scr;
  635                 vc->currenttype = type;
  636         } else {
  637                 scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
  638                                       M_DEVBUF, M_WAITOK);
  639                 pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
  640         }
  641 
  642         *cookiep = scr;
  643         *curxp = scr->pcs.vc_ccol;
  644         *curyp = scr->pcs.vc_crow;
  645         return (0);
  646 }
  647 
  648 static void
  649 ega_free_screen(v, cookie)
  650         void *v;
  651         void *cookie;
  652 {
  653         struct egascreen *vs = cookie;
  654         struct ega_config *vc = vs->cfg;
  655 
  656         LIST_REMOVE(vs, next);
  657         if (vs != &ega_console_screen) {
  658                 /*
  659                  * deallocating the one but last screen
  660                  * removes backing store for the last one
  661                  */
  662                 if (vc->nscreens == 1)
  663                         free(LIST_FIRST(&vc->screens)->pcs.mem, M_DEVBUF);
  664 
  665                 /* Last screen has no backing store */
  666                 if (vc->nscreens != 0)
  667                         free(vs->pcs.mem, M_DEVBUF);
  668 
  669                 free(vs, M_DEVBUF);
  670         } else
  671                 panic("ega_free_screen: console");
  672 
  673         if (vc->active == vs)
  674                 vc->active = NULL;
  675 }
  676 
  677 static void
  678 ega_setfont(vc, scr)
  679         struct ega_config *vc;
  680         struct egascreen *scr;
  681 {
  682         int fontslot1, fontslot2;
  683 
  684         fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
  685         fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
  686         if (vc->currentfontset1 != fontslot1 ||
  687             vc->currentfontset2 != fontslot2) {
  688                 vga_setfontset(&vc->hdl, 2 * fontslot1, 2 * fontslot2);
  689                 vc->currentfontset1 = fontslot1;
  690                 vc->currentfontset2 = fontslot2;
  691         }
  692 }
  693 
  694 static int
  695 ega_show_screen(v, cookie, waitok, cb, cbarg)
  696         void *v;
  697         void *cookie;
  698         int waitok;
  699         void (*cb)(void *, int, int);
  700         void *cbarg;
  701 {
  702         struct egascreen *scr = cookie, *oldscr;
  703         struct ega_config *vc = scr->cfg;
  704 
  705         oldscr = vc->active; /* can be NULL! */
  706         if (scr == oldscr) {
  707                 return (0);
  708         }
  709 
  710         vc->wantedscreen = cookie;
  711         vc->switchcb = cb;
  712         vc->switchcbarg = cbarg;
  713         if (cb) {
  714                 timeout_set(&vc->switch_timeout,
  715                     (void(*)(void *))ega_doswitch, vc);
  716                 timeout_add(&vc->switch_timeout, 0);
  717                 return (EAGAIN);
  718         }
  719 
  720         ega_doswitch(vc);
  721         return (0);
  722 }
  723 
  724 void
  725 ega_doswitch(vc)
  726         struct ega_config *vc;
  727 {
  728         struct egascreen *scr, *oldscr;
  729         struct vga_handle *vh = &vc->hdl;
  730         const struct wsscreen_descr *type;
  731 
  732         scr = vc->wantedscreen;
  733         if (!scr) {
  734                 printf("ega_doswitch: disappeared\n");
  735                 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
  736                 return;
  737         }
  738         type = scr->pcs.type;
  739         oldscr = vc->active; /* can be NULL! */
  740 #ifdef DIAGNOSTIC
  741         if (oldscr) {
  742                 if (!oldscr->pcs.active)
  743                         panic("ega_show_screen: not active");
  744                 if (oldscr->pcs.type != vc->currenttype)
  745                         panic("ega_show_screen: bad type");
  746         }
  747 #endif
  748         if (scr == oldscr) {
  749                 return;
  750         }
  751 #ifdef DIAGNOSTIC
  752         if (scr->pcs.active)
  753                 panic("ega_show_screen: active");
  754 #endif
  755 
  756         if (oldscr) {
  757                 const struct wsscreen_descr *oldtype = oldscr->pcs.type;
  758 
  759                 oldscr->pcs.active = 0;
  760                 bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
  761                                         oldscr->pcs.dispoffset, oldscr->pcs.mem,
  762                                         oldtype->ncols * oldtype->nrows);
  763         }
  764 
  765         if (vc->currenttype != type) {
  766                 vga_setscreentype(vh, type);
  767                 vc->currenttype = type;
  768         }
  769 
  770         ega_setfont(vc, scr);
  771         /* XXX swich colours! */
  772 
  773         scr->pcs.dispoffset = scr->mindispoffset;
  774         if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
  775                 vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
  776                 vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
  777         }
  778 
  779         bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
  780                                 scr->pcs.dispoffset, scr->pcs.mem,
  781                                 type->ncols * type->nrows);
  782         scr->pcs.active = 1;
  783 
  784         vc->active = scr;
  785 
  786         pcdisplay_cursor_reset(&scr->pcs);
  787         pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
  788                          scr->pcs.vc_crow, scr->pcs.vc_ccol);
  789 
  790         vc->wantedscreen = 0;
  791         if (vc->switchcb)
  792                 (*vc->switchcb)(vc->switchcbarg, 0, 0);
  793 }
  794 
  795 static int
  796 ega_load_font(v, cookie, data)
  797         void *v;
  798         void *cookie;
  799         struct wsdisplay_font *data;
  800 {
  801         struct ega_config *vc = v;
  802         struct egascreen *scr = cookie;
  803         char *name2;
  804         int res, slot;
  805         struct egafont *f;
  806 
  807         if (scr) {
  808                 if ((name2 = data->name) != NULL) {
  809                         while (*name2 && *name2 != ',')
  810                                 name2++;
  811                         if (name2)
  812                                 *name2++ = '\0';
  813                 }
  814                 res = ega_selectfont(vc, scr, data->name, name2);
  815                 if (!res)
  816                         ega_setfont(vc, scr);
  817                 return (res);
  818         }
  819 
  820         if (data->fontwidth != 8 || data->stride != 1)
  821                 return (EINVAL); /* XXX 1 byte per line */
  822         if (data->firstchar != 0 || data->numchars != 256)
  823                 return (EINVAL);
  824 #ifndef WSCONS_SUPPORT_PCVTFONTS
  825         if (data->encoding == WSDISPLAY_FONTENC_PCVT) {
  826                 printf("vga: pcvt font support not built in, see vga(4)\n");
  827                 return (EINVAL);
  828         }
  829 #endif
  830 
  831         if (data->index < 0) {
  832                 for (slot = 0; slot < 4; slot++)
  833                         if (!vc->vc_fonts[slot])
  834                                 break;
  835         } else
  836                 slot = data->index;
  837 
  838         if (slot >= 4)
  839                 return (ENOSPC);
  840 
  841         if (vc->vc_fonts[slot] != NULL)
  842                 return (EEXIST);
  843         f = malloc(sizeof(struct egafont), M_DEVBUF, M_WAITOK);
  844         if (f == NULL)
  845                 return (ENOMEM);
  846         strlcpy(f->name, data->name, sizeof(f->name));
  847         f->height = data->fontheight;
  848         f->encoding = data->encoding;
  849 #ifdef notyet
  850         f->firstchar = data->firstchar;
  851         f->numchars = data->numchars;
  852 #endif
  853 #ifdef EGAFONTDEBUG
  854         printf("ega: load %s (8x%d, enc %d) font to slot %d\n", f->name,
  855                f->height, f->encoding, slot);
  856 #endif
  857         vga_loadchars(&vc->hdl, 2 * slot, 0, 256, f->height, data->data);
  858         f->slot = slot;
  859         vc->vc_fonts[slot] = f;
  860         data->cookie = f;
  861         data->index = slot;
  862 
  863         return (0);
  864 }
  865 
  866 static int
  867 ega_alloc_attr(id, fg, bg, flags, attrp)
  868         void *id;
  869         int fg, bg;
  870         int flags;
  871         long *attrp;
  872 {
  873         struct egascreen *scr = id;
  874         struct ega_config *vc = scr->cfg;
  875 
  876         if (vc->hdl.vh_mono) {
  877                 if (flags & WSATTR_WSCOLORS)
  878                         return (EINVAL);
  879                 if (flags & WSATTR_REVERSE)
  880                         *attrp = 0x70;
  881                 else
  882                         *attrp = 0x07;
  883                 if (flags & WSATTR_UNDERLINE)
  884                         *attrp |= FG_UNDERLINE;
  885                 if (flags & WSATTR_HILIT)
  886                         *attrp |= FG_INTENSE;
  887         } else {
  888                 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
  889                         return (EINVAL);
  890                 if (flags & WSATTR_WSCOLORS)
  891                         *attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7];
  892                 else
  893                         *attrp = 7;
  894                 if ((flags & WSATTR_HILIT) || (fg & 8) || (bg & 8))
  895                         *attrp += 8;
  896         }
  897         if (flags & WSATTR_BLINK)
  898                 *attrp |= FG_BLINK;
  899         return (0);
  900 }
  901 
  902 void
  903 ega_unpack_attr(id, attr, fg, bg, ul)
  904         void *id;
  905         long attr;
  906         int *fg, *bg, *ul;
  907 {
  908         struct egascreen *scr = id;
  909         struct ega_config *vc = scr->cfg;
  910 
  911         if (vc->hdl.vh_mono) {
  912                 *fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE : WSCOL_BLACK;
  913                 *bg = attr & 0x70 ? WSCOL_WHITE : WSCOL_BLACK;
  914                 if (ul != NULL)
  915                         *ul = *fg != WSCOL_WHITE && (attr & 0x01) ? 1 : 0;
  916         } else {
  917                 *fg = pctoansi[attr & 0x07];
  918                 *bg = pctoansi[(attr & 0x70) >> 4];
  919                 if (ul != NULL)
  920                         *ul = 0;
  921         }
  922         if (attr & FG_INTENSE)
  923                 *fg += 8;
  924 }
  925 
  926 void
  927 ega_copyrows(id, srcrow, dstrow, nrows)
  928         void *id;
  929         int srcrow, dstrow, nrows;
  930 {
  931         struct egascreen *scr = id;
  932         bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
  933         bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
  934         int ncols = scr->pcs.type->ncols;
  935         bus_size_t srcoff, dstoff;
  936 
  937         srcoff = srcrow * ncols + 0;
  938         dstoff = dstrow * ncols + 0;
  939 
  940         if (scr->pcs.active) {
  941                 if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
  942 #ifdef PCDISPLAY_SOFTCURSOR
  943                         int cursoron = scr->pcs.cursoron;
  944 
  945                         if (cursoron)
  946                                 pcdisplay_cursor(&scr->pcs, 0,
  947                                     scr->pcs.vc_crow, scr->pcs.vc_ccol);
  948 #endif
  949                         /* scroll up whole screen */
  950                         if ((scr->pcs.dispoffset + srcrow * ncols * 2)
  951                             <= scr->maxdispoffset) {
  952                                 scr->pcs.dispoffset += srcrow * ncols * 2;
  953                         } else {
  954                                 bus_space_copy_2(memt, memh,
  955                                         scr->pcs.dispoffset + srcoff * 2,
  956                                         memh, scr->mindispoffset,
  957                                         nrows * ncols);
  958                                 scr->pcs.dispoffset = scr->mindispoffset;
  959                         }
  960                         vga_6845_write(&scr->cfg->hdl, startadrh,
  961                                        scr->pcs.dispoffset >> 9);
  962                         vga_6845_write(&scr->cfg->hdl, startadrl,
  963                                        scr->pcs.dispoffset >> 1);
  964 #ifdef PCDISPLAY_SOFTCURSOR
  965                         if (cursoron)
  966                                 pcdisplay_cursor(&scr->pcs, 1,
  967                                     scr->pcs.vc_crow, scr->pcs.vc_ccol);
  968 #endif
  969                 } else {
  970                         bus_space_copy_2(memt, memh,
  971                                         scr->pcs.dispoffset + srcoff * 2,
  972                                         memh, scr->pcs.dispoffset + dstoff * 2,
  973                                         nrows * ncols);
  974                 }
  975         } else
  976                 bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff],
  977                       nrows * ncols * 2);
  978 }

/* [<][>][^][v][top][bottom][index][help] */