[BACK]Return to ega.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/ega.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb