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

Annotation of sys/dev/pcmcia/cfxga.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cfxga.c,v 1.14 2006/11/29 19:11:17 miod Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005, 2006, Matthieu Herrb and Miodrag Vallat
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * Display driver for the Colorgraphic CompactFlash ``VoyagerVGA'' card.
        !            21:  * based upon the Epson S1D13806 graphics chip.
        !            22:  *
        !            23:  * Our goals are:
        !            24:  * - to provide a somewhat usable emulation mode for extra text display.
        !            25:  * - to let an application (such as an X server) map the controller registers
        !            26:  *   in order to do its own display game.
        !            27:  *
        !            28:  * Driving this card is somewhat a challenge since:
        !            29:  * - its video memory is not directly accessible.
        !            30:  * - no operation can make use of DMA.
        !            31:  */
        !            32:
        !            33: #include <sys/param.h>
        !            34: #include <sys/kernel.h>
        !            35: #include <sys/device.h>
        !            36: #include <sys/systm.h>
        !            37: #include <sys/malloc.h>
        !            38: #include <sys/conf.h>
        !            39:
        !            40: #include <dev/pcmcia/pcmciavar.h>
        !            41: #include <dev/pcmcia/pcmciareg.h>
        !            42:
        !            43: #include <dev/wscons/wsconsio.h>
        !            44: #include <dev/wscons/wsdisplayvar.h>
        !            45: #include <dev/rasops/rasops.h>
        !            46:
        !            47: #include <dev/pcmcia/cfxgareg.h>
        !            48:
        !            49: /*
        !            50: #define CFXGADEBUG
        !            51: #define ENABLE_8BIT_MODES
        !            52: */
        !            53:
        !            54: #ifdef CFXGADEBUG
        !            55: #define        DPRINTF(arg) printf arg
        !            56: #else
        !            57: #define        DPRINTF(arg)
        !            58: #endif
        !            59:
        !            60: struct cfxga_screen;
        !            61:
        !            62: #define        CFXGA_MODE_640x480x16   0
        !            63: #define        CFXGA_MODE_800x600x16   1
        !            64: #ifdef ENABLE_8BIT_MODES
        !            65: #define        CFXGA_MODE_640x480x8    2
        !            66: #define        CFXGA_MODE_800x600x8    3
        !            67: #define        CFXGA_NMODES            4
        !            68: #else
        !            69: #define        CFXGA_NMODES            2
        !            70: #endif
        !            71:
        !            72: struct cfxga_softc {
        !            73:        struct device sc_dev;
        !            74:        struct pcmcia_function *sc_pf;
        !            75:        int     sc_state;
        !            76: #define        CS_MAPPED       0x0001
        !            77: #define        CS_RESET        0x0002
        !            78:
        !            79:        struct pcmcia_mem_handle sc_pmemh;
        !            80:        int sc_memwin;
        !            81:        bus_addr_t sc_offset;
        !            82:
        !            83:        int sc_mode;
        !            84:
        !            85:        int sc_nscreens;
        !            86:        LIST_HEAD(, cfxga_screen) sc_scr;
        !            87:        struct cfxga_screen *sc_active;
        !            88:
        !            89:        /* wsdisplay glue */
        !            90:        struct wsscreen_descr sc_wsd[CFXGA_NMODES];
        !            91:        struct wsscreen_list sc_wsl;
        !            92:        struct wsscreen_descr *sc_scrlist[CFXGA_NMODES];
        !            93:        struct wsdisplay_emulops sc_ops;
        !            94:        struct device *sc_wsdisplay;
        !            95: };
        !            96:
        !            97: int    cfxga_match(struct device *, void *,  void *);
        !            98: void   cfxga_attach(struct device *, struct device *, void *);
        !            99: int    cfxga_detach(struct device *, int);
        !           100: int    cfxga_activate(struct device *, enum devact);
        !           101:
        !           102: struct cfattach cfxga_ca = {
        !           103:        sizeof(struct cfxga_softc), cfxga_match, cfxga_attach,
        !           104:        cfxga_detach, cfxga_activate
        !           105: };
        !           106:
        !           107: struct cfdriver cfxga_cd = {
        !           108:        NULL, "cfxga", DV_DULL
        !           109: };
        !           110:
        !           111: int    cfxga_alloc_screen(void *, const struct wsscreen_descr *, void **,
        !           112:            int *, int *, long *);
        !           113: void   cfxga_burner(void *, u_int, u_int);
        !           114: void   cfxga_free_screen(void *, void *);
        !           115: int    cfxga_ioctl(void *, u_long, caddr_t, int, struct proc *);
        !           116: paddr_t        cfxga_mmap(void *, off_t, int);
        !           117: int    cfxga_show_screen(void *, void *, int, void (*)(void *, int, int),
        !           118:            void *);
        !           119:
        !           120: struct wsdisplay_accessops cfxga_accessops = {
        !           121:        cfxga_ioctl,
        !           122:        cfxga_mmap,
        !           123:        cfxga_alloc_screen,
        !           124:        cfxga_free_screen,
        !           125:        cfxga_show_screen,
        !           126:        NULL,
        !           127:        NULL,
        !           128:        NULL,
        !           129:        cfxga_burner
        !           130: };
        !           131:
        !           132: /*
        !           133:  * Per-screen structure
        !           134:  */
        !           135:
        !           136: struct cfxga_screen {
        !           137:        LIST_ENTRY(cfxga_screen) scr_link;
        !           138:        struct cfxga_softc *scr_sc;     /* parent reference */
        !           139:        struct rasops_info scr_ri;      /* raster op glue */
        !           140:        struct wsdisplay_charcell *scr_mem;     /* backing memory */
        !           141: };
        !           142:
        !           143: void   cfxga_copycols(void *, int, int, int, int);
        !           144: void   cfxga_copyrows(void *, int, int, int);
        !           145: void   cfxga_do_cursor(struct rasops_info *);
        !           146: void   cfxga_erasecols(void *, int, int, int, long);
        !           147: void   cfxga_eraserows(void *, int, int, long);
        !           148: void   cfxga_putchar(void *, int, int, u_int, long);
        !           149:
        !           150: int    cfxga_install_function(struct pcmcia_function *);
        !           151: void   cfxga_remove_function(struct pcmcia_function *);
        !           152:
        !           153: int    cfxga_expand_char(struct cfxga_screen *, u_int, int, int, long);
        !           154: int    cfxga_repaint_screen(struct cfxga_screen *);
        !           155: void   cfxga_reset_video(struct cfxga_softc *);
        !           156: void   cfxga_reset_and_repaint(struct cfxga_softc *);
        !           157: int    cfxga_solid_fill(struct cfxga_screen *, int, int, int, int, int32_t);
        !           158: int    cfxga_standalone_rop(struct cfxga_screen *, u_int,
        !           159:            int, int, int, int, int, int);
        !           160: int    cfxga_synchronize(struct cfxga_softc *);
        !           161: u_int  cfxga_wait(struct cfxga_softc *, u_int, u_int);
        !           162:
        !           163: #define        cfxga_clear_screen(scr) \
        !           164:        cfxga_solid_fill(scr, 0, 0, scr->scr_ri.ri_width, \
        !           165:            scr->scr_ri.ri_height, scr->scr_ri.ri_devcmap[WSCOL_BLACK])
        !           166:
        !           167: #define        cfxga_read_1(sc, addr) \
        !           168:        bus_space_read_1((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
        !           169:            (sc)->sc_offset + (addr))
        !           170: #define        cfxga_read_2(sc, addr) \
        !           171:        bus_space_read_2((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
        !           172:            (sc)->sc_offset + (addr))
        !           173: #define        cfxga_write_1(sc, addr, val) \
        !           174:        bus_space_write_1((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
        !           175:            (sc)->sc_offset + (addr), (val))
        !           176: #define        cfxga_write_2(sc, addr, val) \
        !           177:        bus_space_write_2((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
        !           178:            (sc)->sc_offset + (addr), (val))
        !           179:
        !           180: #define        cfxga_stop_memory_blt(sc) \
        !           181:        (void)cfxga_read_2(sc, CFREG_BITBLT_DATA)
        !           182:
        !           183: const char *cfxga_modenames[CFXGA_NMODES] = {
        !           184:        "640x480x16",
        !           185:        "800x600x16",
        !           186: #ifdef ENABLE_8BIT_MODES
        !           187:        "640x480x8",
        !           188:        "800x600x8"
        !           189: #endif
        !           190: };
        !           191:
        !           192: /*
        !           193:  * This card is very poorly engineered, specificationwise. It does not
        !           194:  * provide any CIS information, and has no vendor/product numbers as
        !           195:  * well: as such, there is no easy way to differentiate it from any
        !           196:  * other cheapo PCMCIA card.
        !           197:  *
        !           198:  * The best we can do is probe for a chip ID. This is not perfect but better
        !           199:  * than matching blindly. Of course this requires us to play some nasty games
        !           200:  * behind the PCMCIA framework to be able to do this probe, and correctly fail
        !           201:  * if this is not the card we are looking for.
        !           202:  *
        !           203:  * In shorter words: some card designers ought to be shot, as a service
        !           204:  * to the community.
        !           205:  */
        !           206:
        !           207: /*
        !           208:  * Create the necessary pcmcia function structures to alleviate the lack
        !           209:  * of any CIS information on this device.
        !           210:  * Actually, we hijack the fake function created by the pcmcia framework.
        !           211:  */
        !           212: int
        !           213: cfxga_install_function(struct pcmcia_function *pf)
        !           214: {
        !           215:        struct pcmcia_config_entry *cfe;
        !           216:
        !           217:        /* Get real. */
        !           218:        pf->pf_flags &= ~PFF_FAKE;
        !           219:
        !           220:        /* Tell the pcmcia framework where the CCR is. */
        !           221:        pf->ccr_base = 0x800;
        !           222:        pf->ccr_mask = 0x67;
        !           223:
        !           224:        /* Create a simple cfe. */
        !           225:        cfe = (struct pcmcia_config_entry *)malloc(sizeof *cfe,
        !           226:            M_DEVBUF, M_NOWAIT);
        !           227:        if (cfe == NULL) {
        !           228:                DPRINTF(("%s: cfe allocation failed\n", __func__));
        !           229:                return (ENOMEM);
        !           230:        }
        !           231:
        !           232:        bzero(cfe, sizeof *cfe);
        !           233:        cfe->number = 42;       /* have to put some value... */
        !           234:        cfe->flags = PCMCIA_CFE_IO16;
        !           235:        cfe->iftype = PCMCIA_IFTYPE_MEMORY;
        !           236:
        !           237:        SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
        !           238:
        !           239:        pcmcia_function_init(pf, cfe);
        !           240:        return (0);
        !           241: }
        !           242:
        !           243: /*
        !           244:  * Undo the changes done above.
        !           245:  * Such a function is necessary since we need a full-blown pcmcia world
        !           246:  * set up in order to do the device probe, but if we don't match the card,
        !           247:  * leaving this state will cause trouble during other probes.
        !           248:  */
        !           249: void
        !           250: cfxga_remove_function(struct pcmcia_function *pf)
        !           251: {
        !           252:        struct pcmcia_config_entry *cfe;
        !           253:
        !           254:        /* we are the first and only entry... */
        !           255:        cfe = SIMPLEQ_FIRST(&pf->cfe_head);
        !           256:        SIMPLEQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
        !           257:        free(cfe, M_DEVBUF);
        !           258:
        !           259:        /* And we're a figment of the kernel's imagination again. */
        !           260:        pf->pf_flags |= PFF_FAKE;
        !           261: }
        !           262:
        !           263: int
        !           264: cfxga_match(struct device *parent, void *match, void *aux)
        !           265: {
        !           266:        struct pcmcia_attach_args *pa = aux;
        !           267:        struct pcmcia_function *pf = pa->pf;
        !           268:        struct pcmcia_mem_handle h;
        !           269:        int rc;
        !           270:        int win;
        !           271:        bus_addr_t ptr;
        !           272:        u_int8_t id = 0;
        !           273:
        !           274:        if (pa->product != PCMCIA_PRODUCT_INVALID ||
        !           275:            pa->manufacturer != PCMCIA_VENDOR_INVALID)
        !           276:                return (0);
        !           277:
        !           278:        /* Only a card with no CIS will have a fake function... */
        !           279:        if ((pf->pf_flags & PFF_FAKE) == 0)
        !           280:                return (0);
        !           281:
        !           282:        if (cfxga_install_function(pf) != 0)
        !           283:                return (0);
        !           284:
        !           285:        if (pcmcia_function_enable(pf) != 0) {
        !           286:                DPRINTF(("%s: function enable failed\n"));
        !           287:                return (0);
        !           288:        }
        !           289:
        !           290:        rc = pcmcia_mem_alloc(pf, CFXGA_MEM_RANGE, &h);
        !           291:        if (rc != 0)
        !           292:                goto out;
        !           293:
        !           294:        rc = pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0, CFXGA_MEM_RANGE,
        !           295:            &h, &ptr, &win);
        !           296:        if (rc != 0)
        !           297:                goto out2;
        !           298:
        !           299:        id = (bus_space_read_1(h.memt, h.memh, ptr + CFREG_REV) &
        !           300:            CR_PRODUCT_MASK) >> CR_PRODUCT_SHIFT;
        !           301:
        !           302:        pcmcia_mem_unmap(pa->pf, win);
        !           303: out2:
        !           304:        pcmcia_mem_free(pa->pf, &h);
        !           305: out:
        !           306:        pcmcia_function_disable(pf);
        !           307:        cfxga_remove_function(pf);
        !           308:
        !           309:        /*
        !           310:         * Be sure to return a value greater than pccom's if we match,
        !           311:         * otherwise it can win due to the way config(8) will order devices...
        !           312:         */
        !           313:        return (id == PRODUCT_S1D13806 ? 10 : 0);
        !           314: }
        !           315:
        !           316: int
        !           317: cfxga_activate(struct device *dev, enum devact act)
        !           318: {
        !           319:        struct cfxga_softc *sc = (void *)dev;
        !           320:
        !           321:        switch (act) {
        !           322:        case DVACT_ACTIVATE:
        !           323:                if (pcmcia_function_enable(sc->sc_pf) != 0) {
        !           324:                        printf("%s: function enable failed\n",
        !           325:                            sc->sc_dev.dv_xname);
        !           326:                } else {
        !           327:                        cfxga_reset_and_repaint(sc);
        !           328:                }
        !           329:                break;
        !           330:        case DVACT_DEACTIVATE:
        !           331:                pcmcia_function_disable(sc->sc_pf);
        !           332:                break;
        !           333:        }
        !           334:        return (0);
        !           335: }
        !           336:
        !           337: void
        !           338: cfxga_attach(struct device *parent, struct device *self, void *aux)
        !           339: {
        !           340:        struct cfxga_softc *sc = (void *)self;
        !           341:        struct pcmcia_attach_args *pa = aux;
        !           342:        struct pcmcia_function *pf = pa->pf;
        !           343:        struct wsemuldisplaydev_attach_args waa;
        !           344:        struct wsscreen_descr *wsd;
        !           345:        u_int i;
        !           346:
        !           347:        LIST_INIT(&sc->sc_scr);
        !           348:        sc->sc_nscreens = 0;
        !           349:        sc->sc_pf = pf;
        !           350:
        !           351:        if (cfxga_install_function(pf) != 0) {
        !           352:                printf(": pcmcia function setup failed\n");
        !           353:                return;
        !           354:        }
        !           355:
        !           356:        if (pcmcia_function_enable(pf)) {
        !           357:                printf(": function enable failed\n");
        !           358:                return;
        !           359:        }
        !           360:
        !           361:        if (pcmcia_mem_alloc(pf, CFXGA_MEM_RANGE, &sc->sc_pmemh) != 0) {
        !           362:                printf(": can't allocate memory space\n");
        !           363:                return;
        !           364:        }
        !           365:
        !           366:        if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0, CFXGA_MEM_RANGE,
        !           367:            &sc->sc_pmemh, &sc->sc_offset, &sc->sc_memwin) != 0) {
        !           368:                printf(": can't map frame buffer registers\n");
        !           369:                pcmcia_mem_free(pf, &sc->sc_pmemh);
        !           370:                return;
        !           371:        }
        !           372:
        !           373:        SET(sc->sc_state, CS_MAPPED);
        !           374:
        !           375:        printf("\n");
        !           376:
        !           377:        sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
        !           378:
        !           379:        /*
        !           380:         * We actually defer real initialization to the creation of the
        !           381:         * first wsdisplay screen, since we do not know which mode to pick
        !           382:         * yet.
        !           383:         */
        !           384:
        !           385:        for (wsd = sc->sc_wsd, i = 0; i < CFXGA_NMODES; wsd++, i++) {
        !           386:                strlcpy(wsd->name, cfxga_modenames[i], sizeof(wsd->name));
        !           387:                wsd->textops = &sc->sc_ops;
        !           388:                sc->sc_scrlist[i] = wsd;
        !           389:        }
        !           390:        sc->sc_wsl.nscreens = CFXGA_NMODES;
        !           391:        sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
        !           392:
        !           393:        waa.console = 0;
        !           394:        waa.scrdata = &sc->sc_wsl;
        !           395:        waa.accessops = &cfxga_accessops;
        !           396:        waa.accesscookie = sc;
        !           397:        waa.defaultscreens = 1;
        !           398:
        !           399:        if ((sc->sc_wsdisplay =
        !           400:            config_found(self, &waa, wsemuldisplaydevprint)) == NULL) {
        !           401:                /* otherwise wscons will do this */
        !           402:                if (sc->sc_active != NULL)
        !           403:                        cfxga_clear_screen(sc->sc_active);
        !           404:                else
        !           405:                        cfxga_burner(sc, 0, 0);
        !           406:        }
        !           407: }
        !           408:
        !           409: int
        !           410: cfxga_detach(struct device *dev, int flags)
        !           411: {
        !           412:        struct cfxga_softc *sc = (void *)dev;
        !           413:
        !           414:        /*
        !           415:         * Detach all children, and hope wsdisplay detach code is correct...
        !           416:         */
        !           417:        if (sc->sc_wsdisplay != NULL) {
        !           418:                config_detach(sc->sc_wsdisplay, DETACH_FORCE);
        !           419:                /* sc->sc_wsdisplay = NULL; */
        !           420:        }
        !           421:
        !           422:        if (ISSET(sc->sc_state, CS_MAPPED)) {
        !           423:                pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
        !           424:                pcmcia_mem_free(sc->sc_pf, &sc->sc_pmemh);
        !           425:                /* CLR(sc->sc_state, CS_MAPPED); */
        !           426:        }
        !           427:
        !           428:        return (0);
        !           429: }
        !           430:
        !           431: /*
        !           432:  * Wscons operations
        !           433:  */
        !           434:
        !           435: int
        !           436: cfxga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
        !           437:     int *curxp, int *curyp, long *attrp)
        !           438: {
        !           439:        struct cfxga_softc *sc = v;
        !           440:        struct cfxga_screen *scr;
        !           441:        struct rasops_info *ri;
        !           442:        u_int mode, width, height, depth, scrsize;
        !           443:
        !           444:        scr = malloc(sizeof *scr, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
        !           445:        if (scr == NULL)
        !           446:                return (ENOMEM);
        !           447:        bzero(scr, sizeof *scr);
        !           448:
        !           449:        mode = type - sc->sc_wsd;
        !           450: #ifdef DIAGNOSTIC
        !           451:        if (mode >= CFXGA_NMODES)
        !           452:                mode = CFXGA_MODE_640x480x16;
        !           453: #endif
        !           454:        switch (mode) {
        !           455:        default:
        !           456:        case CFXGA_MODE_640x480x16:
        !           457:                width = 640;
        !           458:                height = 480;
        !           459:                depth = 16;
        !           460:                break;
        !           461:        case CFXGA_MODE_800x600x16:
        !           462:                width = 800;
        !           463:                height = 600;
        !           464:                depth = 16;
        !           465:                break;
        !           466: #ifdef ENABLE_8BIT_MODES
        !           467:        case CFXGA_MODE_640x480x8:
        !           468:                width = 640;
        !           469:                height = 480;
        !           470:                depth = 8;
        !           471:                break;
        !           472:        case CFXGA_MODE_800x600x8:
        !           473:                width = 800;
        !           474:                height = 600;
        !           475:                depth = 8;
        !           476:                break;
        !           477: #endif
        !           478:        }
        !           479:
        !           480:        ri = &scr->scr_ri;
        !           481:        ri->ri_hw = (void *)scr;
        !           482:        ri->ri_bits = NULL;
        !           483:        ri->ri_depth = depth;
        !           484:        ri->ri_width = width;
        !           485:        ri->ri_height = height;
        !           486:        ri->ri_stride = width * depth / 8;
        !           487:        ri->ri_flg = 0;
        !           488:
        !           489:        /* swap B and R at 16 bpp */
        !           490:        if (depth == 16) {
        !           491:                ri->ri_rnum = 5;
        !           492:                ri->ri_rpos = 11;
        !           493:                ri->ri_gnum = 6;
        !           494:                ri->ri_gpos = 5;
        !           495:                ri->ri_bnum = 5;
        !           496:                ri->ri_bpos = 0;
        !           497:        }
        !           498:
        !           499:        if (type->nrows == 0)   /* first screen creation */
        !           500:                rasops_init(ri, 100, 100);
        !           501:        else
        !           502:                rasops_init(ri, type->nrows, type->ncols);
        !           503:
        !           504:        /*
        !           505:         * Allocate backing store to remember non-visible screen contents in
        !           506:         * emulation mode.
        !           507:         */
        !           508:        scrsize = ri->ri_rows * ri->ri_cols * sizeof(struct wsdisplay_charcell);
        !           509:        scr->scr_mem = malloc(scrsize, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
        !           510:        if (scr->scr_mem == NULL) {
        !           511:                free(scr, M_DEVBUF);
        !           512:                return (ENOMEM);
        !           513:        }
        !           514:        bzero(scr->scr_mem, scrsize);
        !           515:
        !           516:        ri->ri_ops.copycols = cfxga_copycols;
        !           517:        ri->ri_ops.copyrows = cfxga_copyrows;
        !           518:        ri->ri_ops.erasecols = cfxga_erasecols;
        !           519:        ri->ri_ops.eraserows = cfxga_eraserows;
        !           520:        ri->ri_ops.putchar = cfxga_putchar;
        !           521:        ri->ri_do_cursor = cfxga_do_cursor;
        !           522:
        !           523:        /*
        !           524:         * Finish initializing our screen descriptions, now that we know
        !           525:         * the actual console emulation parameters.
        !           526:         */
        !           527:        if (type->nrows == 0) {
        !           528:                struct wsscreen_descr *wsd = (struct wsscreen_descr *)type;
        !           529:
        !           530:                wsd->nrows = ri->ri_rows;
        !           531:                wsd->ncols = ri->ri_cols;
        !           532:                bcopy(&ri->ri_ops, &sc->sc_ops, sizeof(sc->sc_ops));
        !           533:                wsd->fontwidth = ri->ri_font->fontwidth;
        !           534:                wsd->fontheight = ri->ri_font->fontheight;
        !           535:                wsd->capabilities = ri->ri_caps;
        !           536:        }
        !           537:
        !           538:        scr->scr_sc = sc;
        !           539:        LIST_INSERT_HEAD(&sc->sc_scr, scr, scr_link);
        !           540:        sc->sc_nscreens++;
        !           541:
        !           542:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
        !           543:
        !           544:        *cookiep = ri;
        !           545:        *curxp = *curyp = 0;
        !           546:
        !           547:        return (0);
        !           548: }
        !           549:
        !           550: void
        !           551: cfxga_burner(void *v, u_int on, u_int flags)
        !           552: {
        !           553:        struct cfxga_softc *sc = (void *)v;
        !           554:        u_int8_t mode;
        !           555:
        !           556:        mode = cfxga_read_1(sc, CFREG_MODE) & LCD_MODE_SWIVEL_BIT_0;
        !           557:
        !           558:        if (on)
        !           559:                cfxga_write_1(sc, CFREG_MODE, mode | MODE_CRT);
        !           560:        else
        !           561:                cfxga_write_1(sc, CFREG_MODE, mode | MODE_NO_DISPLAY);
        !           562: }
        !           563:
        !           564: void
        !           565: cfxga_free_screen(void *v, void *cookie)
        !           566: {
        !           567:        struct cfxga_softc *sc = v;
        !           568:        struct rasops_info *ri = cookie;
        !           569:        struct cfxga_screen *scr = ri->ri_hw;
        !           570:
        !           571:        LIST_REMOVE(scr, scr_link);
        !           572:        sc->sc_nscreens--;
        !           573:
        !           574:        if (scr == sc->sc_active) {
        !           575:                sc->sc_active = NULL;
        !           576:                cfxga_burner(sc, 0, 0);
        !           577:        }
        !           578:
        !           579:        free(scr->scr_mem, M_DEVBUF);
        !           580:        free(scr, M_DEVBUF);
        !           581: }
        !           582:
        !           583: int
        !           584: cfxga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           585: {
        !           586:        struct cfxga_softc *sc = v;
        !           587:        struct cfxga_screen *scr;
        !           588:        struct wsdisplay_fbinfo *wdf;
        !           589:        int mode;
        !           590:
        !           591:        switch (cmd) {
        !           592:        case WSDISPLAYIO_GTYPE:
        !           593:                *(u_int *)data = WSDISPLAY_TYPE_CFXGA;
        !           594:                break;
        !           595:
        !           596:        case WSDISPLAYIO_GINFO:
        !           597:                wdf = (struct wsdisplay_fbinfo *)data;
        !           598:                scr = sc->sc_active;
        !           599:                if (scr == NULL) {
        !           600:                        /* try later...after running wsconscfg to add screens */
        !           601:                        wdf->height = wdf->width = wdf->depth = wdf->cmsize = 0;
        !           602:                } else {
        !           603:                        wdf->height = scr->scr_ri.ri_height;
        !           604:                        wdf->width = scr->scr_ri.ri_width;
        !           605:                        wdf->depth = scr->scr_ri.ri_depth;
        !           606:                        wdf->cmsize = scr->scr_ri.ri_depth <= 8 ?
        !           607:                            (1 << scr->scr_ri.ri_depth) : 0;
        !           608:                }
        !           609:                break;
        !           610:
        !           611:        case WSDISPLAYIO_SMODE:
        !           612:                mode = *(u_int *)data;
        !           613:                if (mode == sc->sc_mode)
        !           614:                        break;
        !           615:                switch (mode) {
        !           616:                case WSDISPLAYIO_MODE_EMUL:
        !           617:                        cfxga_reset_and_repaint(sc);
        !           618:                        break;
        !           619:                case WSDISPLAYIO_MODE_MAPPED:
        !           620:                        break;
        !           621:                default:
        !           622:                        return (EINVAL);
        !           623:                }
        !           624:                sc->sc_mode = mode;
        !           625:                break;
        !           626:
        !           627:        /* these operations are handled by the wscons code... */
        !           628:        case WSDISPLAYIO_GVIDEO:
        !           629:        case WSDISPLAYIO_SVIDEO:
        !           630:                break;
        !           631:
        !           632:        /* these operations are not supported... */
        !           633:        case WSDISPLAYIO_GETCMAP:
        !           634:        case WSDISPLAYIO_PUTCMAP:
        !           635:        case WSDISPLAYIO_LINEBYTES:
        !           636:        case WSDISPLAYIO_GCURPOS:
        !           637:        case WSDISPLAYIO_SCURPOS:
        !           638:        case WSDISPLAYIO_GCURMAX:
        !           639:        case WSDISPLAYIO_GCURSOR:
        !           640:        case WSDISPLAYIO_SCURSOR:
        !           641:        default:
        !           642:                return (-1);
        !           643:        }
        !           644:
        !           645:        return (0);
        !           646: }
        !           647:
        !           648: paddr_t
        !           649: cfxga_mmap(void *v, off_t off, int prot)
        !           650: {
        !           651:        return (-1);
        !           652: }
        !           653:
        !           654: int
        !           655: cfxga_show_screen(void *v, void *cookie, int waitok,
        !           656:     void (*cb)(void *, int, int), void *cbarg)
        !           657: {
        !           658:        struct cfxga_softc *sc = v;
        !           659:        struct rasops_info *ri = cookie;
        !           660:        struct cfxga_screen *scr = ri->ri_hw, *old;
        !           661:
        !           662:        old = sc->sc_active;
        !           663:        if (old == scr)
        !           664:                return (0);
        !           665:
        !           666:        sc->sc_active = scr;
        !           667:        cfxga_reset_and_repaint(sc);    /* will turn video on if scr != NULL */
        !           668:
        !           669:        return (0);
        !           670: }
        !           671:
        !           672: /*
        !           673:  * Real frame buffer operations
        !           674:  */
        !           675:
        !           676: void
        !           677: cfxga_reset_video(struct cfxga_softc *sc)
        !           678: {
        !           679:        struct cfxga_screen *scr = sc->sc_active;
        !           680:        struct rasops_info *ri;
        !           681: #ifdef ENABLE_8BIT_MODES
        !           682:        const u_int8_t *cmap;
        !           683:        u_int i;
        !           684: #endif
        !           685:
        !           686:        /*
        !           687:         * Reset controller
        !           688:         */
        !           689:
        !           690:        /* need to write to both REV and MISC at the same time */
        !           691:        cfxga_write_2(sc, CFREG_REV, 0x80 | (CM_REGSEL << 8));
        !           692:        delay(25000);   /* maintain reset for a short while */
        !           693:        /* need to write to both REV and MISC at the same time */
        !           694:        cfxga_write_2(sc, CFREG_REV, 0 | (CM_MEMSEL << 8));
        !           695:        delay(25000);
        !           696:        /* stop any pending blt operation */
        !           697:        cfxga_write_2(sc, CFREG_BITBLT_CONTROL, 0);
        !           698:        cfxga_stop_memory_blt(sc);
        !           699:        cfxga_write_1(sc, CFREG_MODE, 0);       /* disable all displays */
        !           700:
        !           701:        /*
        !           702:         * Setup common video mode parameters.
        !           703:         */
        !           704:
        !           705:        cfxga_write_2(sc, CFREG_MEMCLK, MEMCLK_SRC_CLK3);
        !           706: #if 0
        !           707:        cfxga_write_1(sc, CFREG_LCD_PCLK, LCD_PCLK_SRC_CLKI | LCD_PCLK_DIV_1);
        !           708:        cfxga_write_1(sc, CFREG_MPLUG_CLK,
        !           709:            MPLUG_PCLK_SRC_CLKI2 | MPLUG_PCLK_DIV_1);
        !           710: #endif
        !           711:        cfxga_write_2(sc, CFREG_CRTTV_PCLK, CRT_PCLK_SRC_CLKI | CRT_PCLK_DIV_1);
        !           712:        cfxga_write_2(sc, CFREG_WSTATE, WSTATE_MCLK);
        !           713:
        !           714:        /* MEMCNF and DRAM_RFRSH need to be programmed at the same time */
        !           715:        cfxga_write_2(sc, CFREG_MEMCNF,
        !           716:            MEMCNF_SDRAM_INIT | (DRAM_RFRSH_50MHZ << 8));
        !           717:        delay(250);
        !           718:        cfxga_write_2(sc, CFREG_DRAM_TIMING, DRAM_TIMING_50MHZ);
        !           719:
        !           720:        /*
        !           721:         * Setup mode-dependent parameters.
        !           722:         */
        !           723:        if (scr == NULL)
        !           724:                return;
        !           725:
        !           726:        ri = &scr->scr_ri;
        !           727:        switch (scr->scr_ri.ri_width) {
        !           728:        default:
        !           729:        case 640:
        !           730:                cfxga_write_1(sc, CFREG_CRT_HWIDTH, (640 / 8) - 1);
        !           731:                /* HNDISP and HSTART need to be programmed at the same time */
        !           732:                cfxga_write_2(sc, CFREG_CRT_HNDISP, 23 | (2 << 8));
        !           733:                cfxga_write_1(sc, CFREG_CRT_HPULSE, 4);
        !           734:                cfxga_write_2(sc, CFREG_CRT_VHEIGHT, 480 - 1);
        !           735:                /* VNDISP and VSTART need to be programmed at the same time */
        !           736:                cfxga_write_2(sc, CFREG_CRT_VNDISP, 39 | (8 << 8));
        !           737:                cfxga_write_1(sc, CFREG_CRT_VPULSE, 2);
        !           738:                break;
        !           739:        case 800:
        !           740:                cfxga_write_1(sc, CFREG_CRT_HWIDTH, (800 / 8) - 1);
        !           741:                /* HNDISP and HSTART need to be programmed at the same time */
        !           742:                cfxga_write_2(sc, CFREG_CRT_HNDISP, 27 | (2 << 8));
        !           743:                cfxga_write_1(sc, CFREG_CRT_HPULSE, 4);
        !           744:                cfxga_write_2(sc, CFREG_CRT_VHEIGHT, 600 - 1);
        !           745:                /* VNDISP and VSTART need to be programmed at the same time */
        !           746:                cfxga_write_2(sc, CFREG_CRT_VNDISP, 25 | (8 << 8));
        !           747:                cfxga_write_1(sc, CFREG_CRT_VPULSE, 2);
        !           748:                break;
        !           749:        }
        !           750:        cfxga_write_1(sc, CFREG_CRT_MODE,
        !           751:            ri->ri_depth == 16 ? CRT_MODE_16BPP : CRT_MODE_8BPP);
        !           752:        cfxga_write_2(sc, CFREG_CRT_START_LOW, 0);
        !           753:        cfxga_write_1(sc, CFREG_CRT_START_HIGH, 0);
        !           754:        cfxga_write_2(sc, CFREG_CRT_MEMORY, ri->ri_width * ri->ri_depth / 16);
        !           755:        cfxga_write_1(sc, CFREG_CRT_PANNING, 0);
        !           756:        cfxga_write_1(sc, CFREG_CRT_FIFO_THRESHOLD_HIGH, 0);
        !           757:        cfxga_write_1(sc, CFREG_CRT_FIFO_THRESHOLD_LOW, 0);
        !           758:        cfxga_write_1(sc, CFREG_CRT_CURSOR_CONTROL, CURSOR_INACTIVE);
        !           759:
        !           760: #ifdef ENABLE_8BIT_MODES
        !           761:        /*
        !           762:         * On 8bpp video modes, program the LUT
        !           763:         */
        !           764:        if (ri->ri_depth == 8) {
        !           765: #if 0
        !           766:                /* Wait for retrace */
        !           767:                while ((cfxga_read_1(sc, CFREG_CRT_VNDISP) &
        !           768:                    CRT_VNDISP_STATUS) == 0)
        !           769:                        delay(1);
        !           770: #endif
        !           771:                cfxga_write_1(sc, CFREG_LUT_MODE, LUT_CRT);
        !           772:                cfxga_write_1(sc, CFREG_LUT_ADDRESS, 0); /* autoincrements */
        !           773:                cmap = rasops_cmap;
        !           774:                for (i = 256 * 3; i != 0; i--)
        !           775:                        cfxga_write_1(sc, CFREG_LUT_DATA, *cmap++ & 0xf0);
        !           776:        }
        !           777: #endif
        !           778:
        !           779:        cfxga_write_1(sc, CFREG_TV_CONTROL,
        !           780:            TV_LUMINANCE_FILTER | TV_SVIDEO_OUTPUT | TV_NTSC_OUTPUT);
        !           781:
        !           782:        cfxga_write_1(sc, CFREG_POWER_CONF, POWERSAVE_MBO);
        !           783:        cfxga_write_1(sc, CFREG_WATCHDOG, 0);
        !           784:
        !           785:        cfxga_write_1(sc, CFREG_MODE, MODE_CRT);
        !           786:        delay(25000);
        !           787: }
        !           788:
        !           789: void
        !           790: cfxga_reset_and_repaint(struct cfxga_softc *sc)
        !           791: {
        !           792:        cfxga_reset_video(sc);
        !           793:
        !           794:        if (sc->sc_active != NULL)
        !           795:                cfxga_repaint_screen(sc->sc_active);
        !           796:        else
        !           797:                cfxga_burner(sc, 0, 0);
        !           798: }
        !           799:
        !           800: /*
        !           801:  * Wait for the blitter to be in a given state.
        !           802:  */
        !           803: u_int
        !           804: cfxga_wait(struct cfxga_softc *sc, u_int mask, u_int result)
        !           805: {
        !           806:        u_int tries;
        !           807:
        !           808:        for (tries = 10000; tries != 0; tries--) {
        !           809:                if ((cfxga_read_1(sc, CFREG_BITBLT_CONTROL) & mask) == result)
        !           810:                        break;
        !           811:                delay(10);
        !           812:        }
        !           813:
        !           814:        return (tries);
        !           815: }
        !           816:
        !           817: /*
        !           818:  * Wait for all pending blitter operations to be complete.
        !           819:  * Returns non-zero if the blitter got stuck.
        !           820:  */
        !           821: int
        !           822: cfxga_synchronize(struct cfxga_softc *sc)
        !           823: {
        !           824:        /* Wait for previous operations to complete */
        !           825:        if (cfxga_wait(sc, BITBLT_ACTIVE, 0) == 0) {
        !           826:                DPRINTF(("%s: not ready\n", __func__));
        !           827:                if (ISSET(sc->sc_state, CS_RESET))
        !           828:                        return (EAGAIN);
        !           829:                else {
        !           830:                        DPRINTF(("%s: resetting...\n", sc->sc_dev.dv_xname));
        !           831:                        SET(sc->sc_state, CS_RESET);
        !           832:                        cfxga_reset_and_repaint(sc);
        !           833:                        CLR(sc->sc_state, CS_RESET);
        !           834:                }
        !           835:        }
        !           836:        cfxga_stop_memory_blt(sc);
        !           837:        return (0);
        !           838: }
        !           839:
        !           840: /*
        !           841:  * Display a character.
        !           842:  */
        !           843: int
        !           844: cfxga_expand_char(struct cfxga_screen *scr, u_int uc, int x, int y, long attr)
        !           845: {
        !           846:        struct cfxga_softc *sc = scr->scr_sc;
        !           847:        struct rasops_info *ri = &scr->scr_ri;
        !           848:        struct wsdisplay_font *font = ri->ri_font;
        !           849:        u_int pos, sts, fifo_avail, chunk;
        !           850:        u_int8_t *fontbits;
        !           851:        int bg, fg, ul;
        !           852:        u_int i;
        !           853:        int rc;
        !           854:
        !           855:        pos = (y * ri->ri_width + x) * ri->ri_depth / 8;
        !           856:        fontbits = (u_int8_t *)(font->data + (uc - font->firstchar) *
        !           857:            ri->ri_fontscale);
        !           858:        ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul);
        !           859:
        !           860:        /* Wait for previous operations to complete */
        !           861:        if ((rc = cfxga_synchronize(sc)) != 0)
        !           862:                return (rc);
        !           863:
        !           864:        cfxga_write_2(sc, CFREG_COLOR_EXPANSION,
        !           865:            ((font->fontwidth - 1) & 7) | (OP_COLOR_EXPANSION << 8));
        !           866:        cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, font->fontwidth <= 8 ? 0 : 1);
        !           867:        cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, 0);
        !           868:        cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, pos);
        !           869:        cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, pos >> 16);
        !           870:        cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
        !           871:            ri->ri_width * ri->ri_depth / 16);
        !           872:        cfxga_write_2(sc, CFREG_BITBLT_WIDTH, font->fontwidth - 1);
        !           873:        cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, font->fontheight - 1);
        !           874:        cfxga_write_2(sc, CFREG_BITBLT_FG, ri->ri_devcmap[fg]);
        !           875:        cfxga_write_2(sc, CFREG_BITBLT_BG, ri->ri_devcmap[bg]);
        !           876:        cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
        !           877:            (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
        !           878:
        !           879:        if (cfxga_wait(sc, BITBLT_ACTIVE, BITBLT_ACTIVE) == 0)
        !           880:                goto fail;      /* unlikely */
        !           881:        fifo_avail = 0;
        !           882:
        !           883:        for (i = font->fontheight; i != 0; i--) {
        !           884:                /*
        !           885:                 * Find out how much words we can feed before
        !           886:                 * a FIFO check is needed.
        !           887:                 */
        !           888:                if (fifo_avail == 0) {
        !           889:                        sts = cfxga_read_1(sc, CFREG_BITBLT_CONTROL);
        !           890:                        if ((sts & BITBLT_FIFO_NOT_EMPTY) == 0)
        !           891:                                fifo_avail = font->fontwidth <= 8 ? 2 : 1;
        !           892:                        else if ((sts & BITBLT_FIFO_HALF_FULL) == 0)
        !           893:                                fifo_avail = font->fontwidth <= 8 ? 1 : 0;
        !           894:                        else {
        !           895:                                /*
        !           896:                                 * Let the cheap breathe for a short while.
        !           897:                                 * If this is not enough to free some FIFO
        !           898:                                 * entries, abort the operation.
        !           899:                                 */
        !           900:                                if (cfxga_wait(sc, BITBLT_FIFO_FULL, 0) == 0)
        !           901:                                        goto fail;
        !           902:                        }
        !           903:                }
        !           904:
        !           905:                if (font->fontwidth <= 8) {
        !           906:                        chunk = *fontbits;
        !           907:                        if (ul && i == 1)
        !           908:                                chunk = 0xff;
        !           909:                } else {
        !           910:                        chunk = *(u_int16_t *)fontbits;
        !           911:                        if (ul && i == 1)
        !           912:                                chunk = 0xffff;
        !           913:                }
        !           914:                cfxga_write_2(sc, CFREG_BITBLT_DATA, chunk);
        !           915:                fontbits += font->stride;
        !           916:                fifo_avail--;
        !           917:        }
        !           918:
        !           919:        return (0);
        !           920:
        !           921: fail:
        !           922:        DPRINTF(("%s: abort\n", __func__));
        !           923:        cfxga_write_2(sc, CFREG_BITBLT_CONTROL, 0);
        !           924:        cfxga_stop_memory_blt(sc);
        !           925:        return (EINTR);
        !           926: }
        !           927:
        !           928: /*
        !           929:  * Copy a memory bitmap to the frame buffer.
        !           930:  *
        !           931:  * This is slow - we only use this to repaint the whole frame buffer on
        !           932:  * screen switches.
        !           933:  */
        !           934: int
        !           935: cfxga_repaint_screen(struct cfxga_screen *scr)
        !           936: {
        !           937:        struct wsdisplay_charcell *cell = scr->scr_mem;
        !           938:        struct rasops_info *ri = &scr->scr_ri;
        !           939:        int x, y, cx, cy, lx, ly;
        !           940:        int fg, bg;
        !           941:        int rc;
        !           942:
        !           943:        cfxga_clear_screen(scr);
        !           944:
        !           945:        cx = ri->ri_font->fontwidth;
        !           946:        cy = ri->ri_font->fontheight;
        !           947:
        !           948:        for (ly = 0, y = ri->ri_yorigin; ly < ri->ri_rows; ly++, y += cy) {
        !           949:                for (lx = 0, x = ri->ri_xorigin; lx < ri->ri_cols;
        !           950:                    lx++, x += cx) {
        !           951:                        if (cell->uc == 0 || cell->uc == ' ') {
        !           952:                                ri->ri_ops.unpack_attr(ri, cell->attr,
        !           953:                                    &fg, &bg, NULL);
        !           954:                                rc = cfxga_solid_fill(scr, x, y, cx, cy,
        !           955:                                    ri->ri_devcmap[bg]);
        !           956:                        } else {
        !           957:                                rc = cfxga_expand_char(scr, cell->uc,
        !           958:                                    x, y, cell->attr);
        !           959:                        }
        !           960:                        cell++;
        !           961:                        if (rc != 0)
        !           962:                                return (rc);
        !           963:                }
        !           964:        }
        !           965:
        !           966:        return (0);
        !           967: }
        !           968:
        !           969: /*
        !           970:  * Perform a solid fill operation.
        !           971:  */
        !           972: int
        !           973: cfxga_solid_fill(struct cfxga_screen *scr, int x, int y, int cx, int cy,
        !           974:     int32_t srccolor)
        !           975: {
        !           976:        struct cfxga_softc *sc = scr->scr_sc;
        !           977:        struct rasops_info *ri = &scr->scr_ri;
        !           978:        u_int pos;
        !           979:        int rc;
        !           980:
        !           981:        pos = (y * ri->ri_width + x) * ri->ri_depth / 8;
        !           982:
        !           983:        /* Wait for previous operations to complete */
        !           984:        if ((rc = cfxga_synchronize(sc)) != 0)
        !           985:                return (rc);
        !           986:
        !           987:        cfxga_write_2(sc, CFREG_BITBLT_ROP, 0 | (OP_SOLID_FILL << 8));
        !           988:        cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, pos);
        !           989:        cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, pos >> 16);
        !           990:        cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, pos);
        !           991:        cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, pos >> 16);
        !           992:        cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
        !           993:            ri->ri_width * ri->ri_depth / 16);
        !           994:        cfxga_write_2(sc, CFREG_BITBLT_WIDTH, cx - 1);
        !           995:        cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, cy - 1);
        !           996:        cfxga_write_2(sc, CFREG_BITBLT_FG, (u_int16_t)srccolor);
        !           997:        cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
        !           998:            (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
        !           999:
        !          1000:        return (0);
        !          1001: }
        !          1002:
        !          1003: /*
        !          1004:  * Perform an internal frame buffer operation.
        !          1005:  */
        !          1006: int
        !          1007: cfxga_standalone_rop(struct cfxga_screen *scr, u_int rop, int sx, int sy,
        !          1008:     int dx, int dy, int cx, int cy)
        !          1009: {
        !          1010:        struct cfxga_softc *sc = scr->scr_sc;
        !          1011:        struct rasops_info *ri = &scr->scr_ri;
        !          1012:        u_int srcpos, dstpos;
        !          1013:        u_int opcode;
        !          1014:        int rc;
        !          1015:
        !          1016:        srcpos = (sy * ri->ri_width + sx) * ri->ri_depth / 8;
        !          1017:        dstpos = (dy * ri->ri_width + dx) * ri->ri_depth / 8;
        !          1018:
        !          1019:        if (dstpos <= srcpos)
        !          1020:                opcode = (OP_MOVE_POSITIVE_ROP << 8) | rop;
        !          1021:        else
        !          1022:                opcode = (OP_MOVE_NEGATIVE_ROP << 8) | rop;
        !          1023:
        !          1024:        /* Wait for previous operations to complete */
        !          1025:        if ((rc = cfxga_synchronize(sc)) != 0)
        !          1026:                return (rc);
        !          1027:
        !          1028:        cfxga_write_2(sc, CFREG_BITBLT_ROP, opcode);
        !          1029:        cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, srcpos);
        !          1030:        cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, srcpos >> 16);
        !          1031:        cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, dstpos);
        !          1032:        cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, dstpos >> 16);
        !          1033:        cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
        !          1034:            ri->ri_width * ri->ri_depth / 16);
        !          1035:        cfxga_write_2(sc, CFREG_BITBLT_WIDTH, cx - 1);
        !          1036:        cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, cy - 1);
        !          1037:        cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
        !          1038:            (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
        !          1039:
        !          1040:        return (0);
        !          1041: }
        !          1042:
        !          1043: /*
        !          1044:  * Text console raster operations.
        !          1045:  *
        !          1046:  * We shadow all these operations on a memory copy of the frame buffer.
        !          1047:  * Since we are running in emulation mode only, this could be optimized
        !          1048:  * by only storing actual character cell values (a la mda).
        !          1049:  */
        !          1050:
        !          1051: void
        !          1052: cfxga_copycols(void *cookie, int row, int src, int dst, int num)
        !          1053: {
        !          1054:        struct rasops_info *ri = cookie;
        !          1055:        struct cfxga_screen *scr = ri->ri_hw;
        !          1056:        int sx, dx, y, cx, cy;
        !          1057:
        !          1058:        /* Copy columns in backing store. */
        !          1059:        ovbcopy(scr->scr_mem + row * ri->ri_cols + src,
        !          1060:            scr->scr_mem + row * ri->ri_cols + dst,
        !          1061:            num * sizeof(struct wsdisplay_charcell));
        !          1062:
        !          1063:        if (scr != scr->scr_sc->sc_active)
        !          1064:                return;
        !          1065:
        !          1066:        sx = src * ri->ri_font->fontwidth + ri->ri_xorigin;
        !          1067:        dx = dst * ri->ri_font->fontwidth + ri->ri_xorigin;
        !          1068:        y = row * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1069:        cx = num * ri->ri_font->fontwidth;
        !          1070:        cy = ri->ri_font->fontheight;
        !          1071:        cfxga_standalone_rop(scr, ROP_SRC, sx, y, dx, y, cx, cy);
        !          1072: }
        !          1073:
        !          1074: void
        !          1075: cfxga_copyrows(void *cookie, int src, int dst, int num)
        !          1076: {
        !          1077:        struct rasops_info *ri = cookie;
        !          1078:        struct cfxga_screen *scr = ri->ri_hw;
        !          1079:        int x, sy, dy, cx, cy;
        !          1080:
        !          1081:        /* Copy rows in backing store. */
        !          1082:        ovbcopy(scr->scr_mem + src * ri->ri_cols,
        !          1083:            scr->scr_mem + dst * ri->ri_cols,
        !          1084:            num * ri->ri_cols * sizeof(struct wsdisplay_charcell));
        !          1085:
        !          1086:        if (scr != scr->scr_sc->sc_active)
        !          1087:                return;
        !          1088:
        !          1089:        x = ri->ri_xorigin;
        !          1090:        sy = src * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1091:        dy = dst * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1092:        cx = ri->ri_emuwidth;
        !          1093:        cy = num * ri->ri_font->fontheight;
        !          1094:        cfxga_standalone_rop(scr, ROP_SRC, x, sy, x, dy, cx, cy);
        !          1095: }
        !          1096:
        !          1097: void
        !          1098: cfxga_do_cursor(struct rasops_info *ri)
        !          1099: {
        !          1100:        struct cfxga_screen *scr = ri->ri_hw;
        !          1101:        int x, y, cx, cy;
        !          1102:
        !          1103:        if (scr != scr->scr_sc->sc_active)
        !          1104:                return;
        !          1105:
        !          1106:        x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
        !          1107:        y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1108:        cx = ri->ri_font->fontwidth;
        !          1109:        cy = ri->ri_font->fontheight;
        !          1110:        cfxga_standalone_rop(scr, ROP_ONES ^ ROP_SRC /* i.e. not SRC */,
        !          1111:            x, y, x, y, cx, cy);
        !          1112: }
        !          1113:
        !          1114: void
        !          1115: cfxga_erasecols(void *cookie, int row, int col, int num, long attr)
        !          1116: {
        !          1117:        struct rasops_info *ri = cookie;
        !          1118:        struct cfxga_screen *scr = ri->ri_hw;
        !          1119:        int fg, bg;
        !          1120:        int x, y, cx, cy;
        !          1121:
        !          1122:        /* Erase columns in backing store. */
        !          1123:        for (x = col; x < col + num; x++) {
        !          1124:                scr->scr_mem[row * ri->ri_cols + x].uc = 0;
        !          1125:                scr->scr_mem[row * ri->ri_cols + x].attr = attr;
        !          1126:        }
        !          1127:
        !          1128:        if (scr != scr->scr_sc->sc_active)
        !          1129:                return;
        !          1130:
        !          1131:        ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
        !          1132:        x = col * ri->ri_font->fontwidth + ri->ri_xorigin;
        !          1133:        y = row * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1134:        cx = num * ri->ri_font->fontwidth;
        !          1135:        cy = ri->ri_font->fontheight;
        !          1136:        cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
        !          1137: }
        !          1138:
        !          1139: void
        !          1140: cfxga_eraserows(void *cookie, int row, int num, long attr)
        !          1141: {
        !          1142:        struct rasops_info *ri = cookie;
        !          1143:        struct cfxga_screen *scr = ri->ri_hw;
        !          1144:        int fg, bg;
        !          1145:        int x, y, cx, cy;
        !          1146:
        !          1147:        /* Erase rows in backing store. */
        !          1148:        for (x = 0; x < ri->ri_cols; x++) {
        !          1149:                scr->scr_mem[row * ri->ri_cols + x].uc = 0;
        !          1150:                scr->scr_mem[row * ri->ri_cols + x].attr = attr;
        !          1151:        }
        !          1152:        for (y = 1; y < num; y++)
        !          1153:                ovbcopy(scr->scr_mem + row * ri->ri_cols,
        !          1154:                    scr->scr_mem + (row + y) * ri->ri_cols,
        !          1155:                    ri->ri_cols * sizeof(struct wsdisplay_charcell));
        !          1156:
        !          1157:        if (scr != scr->scr_sc->sc_active)
        !          1158:                return;
        !          1159:
        !          1160:        ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
        !          1161:        x = ri->ri_xorigin;
        !          1162:        y = row * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1163:        cx = ri->ri_emuwidth;
        !          1164:        cy = num * ri->ri_font->fontheight;
        !          1165:        cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
        !          1166: }
        !          1167:
        !          1168: void
        !          1169: cfxga_putchar(void *cookie, int row, int col, u_int uc, long attr)
        !          1170: {
        !          1171:        struct rasops_info *ri = cookie;
        !          1172:        struct cfxga_screen *scr = ri->ri_hw;
        !          1173:        int x, y;
        !          1174:
        !          1175:        scr->scr_mem[row * ri->ri_cols + col].uc = uc;
        !          1176:        scr->scr_mem[row * ri->ri_cols + col].attr = attr;
        !          1177:
        !          1178:        if (scr != scr->scr_sc->sc_active)
        !          1179:                return;
        !          1180:
        !          1181:        x = col * ri->ri_font->fontwidth + ri->ri_xorigin;
        !          1182:        y = row * ri->ri_font->fontheight + ri->ri_yorigin;
        !          1183:
        !          1184:        if (uc == ' ') {
        !          1185:                int cx, cy, fg, bg;
        !          1186:
        !          1187:                ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
        !          1188:                cx = ri->ri_font->fontwidth;
        !          1189:                cy = ri->ri_font->fontheight;
        !          1190:                cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
        !          1191:        } else {
        !          1192:                cfxga_expand_char(scr, uc, x, y, attr);
        !          1193:        }
        !          1194: }

CVSweb