[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

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