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