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

Annotation of sys/dev/sbus/vigra.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: vigra.c,v 1.10 2006/12/17 22:18:16 miod Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002, 2003, Miodrag Vallat.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  *
                     28:  */
                     29:
                     30: /*
                     31:  * Driver for the Vigra VS series of SBus framebuffers.
                     32:  *
                     33:  * The VS10, VS11 and VS12 models are supported. VS10-EK is handled by the
                     34:  * regular cgthree driver.
                     35:  *
                     36:  * The monochrome VS14, 16 grays VS15, and color VS18 are not supported.
                     37:  */
                     38:
                     39: #include <sys/param.h>
                     40: #include <sys/systm.h>
                     41: #include <sys/buf.h>
                     42: #include <sys/device.h>
                     43: #include <sys/ioctl.h>
                     44: #include <sys/malloc.h>
                     45: #include <sys/mman.h>
                     46: #include <sys/tty.h>
                     47: #include <sys/conf.h>
                     48:
                     49: #include <uvm/uvm_extern.h>
                     50:
                     51: #include <machine/autoconf.h>
                     52: #include <machine/bus.h>
                     53: #include <machine/pmap.h>
                     54: #include <machine/cpu.h>
                     55: #include <machine/conf.h>
                     56:
                     57: #include <dev/wscons/wsconsio.h>
                     58: #include <dev/wscons/wsdisplayvar.h>
                     59: #include <dev/rasops/rasops.h>
                     60: #include <machine/fbvar.h>
                     61:
                     62: #include <dev/sbus/sbusvar.h>
                     63:
                     64: /*
                     65:  * The hardware information below has been gathered through experiments, as
                     66:  * well as the debug information of the SunOS 4.x vigfb driver.
                     67:  */
                     68:
                     69: /*
                     70:  * Control and status registers
                     71:  */
                     72:
                     73: struct csregs {
                     74:        u_int32_t       sosr;
                     75:        u_int32_t       g3rr;
                     76:        u_int32_t       bcr;    /* board control register */
                     77:        u_int32_t       spr;
                     78:        u_int32_t       g3sr;   /* ramdac status register */
                     79: #define        STATUS_INTR     0x0001
                     80:        u_int32_t       imr;    /* interrupt mode register */
                     81:        u_int32_t       ewcr;
                     82:        u_int32_t       ssr;
                     83: };
                     84:
                     85: /*
                     86:  * G300 layout
                     87:  */
                     88:
                     89: struct g300dac {
                     90:        u_int32_t       cmap[256];
                     91:        u_int32_t       g3null;
                     92:        u_int32_t       unused1[32];
                     93:        u_int32_t       half_sync;
                     94:        u_int32_t       back_porch;
                     95:        u_int32_t       display;
                     96:        u_int32_t       short_display;
                     97:        u_int32_t       broad_pulse;
                     98:        u_int32_t       vsync;
                     99:        u_int32_t       vblank;
                    100:        u_int32_t       vdisplay;
                    101:        u_int32_t       line_time;
                    102:        u_int32_t       tos1;
                    103:        u_int32_t       mem_init;
                    104:        u_int32_t       transfer_delay;
                    105:        u_int32_t       unused2[19];
                    106:        u_int32_t       mask;
                    107:        u_int32_t       unused3[31];
                    108:        u_int32_t       cr;
                    109:        u_int32_t       unused4[31];
                    110:        u_int32_t       tos2;
                    111:        u_int32_t       unused5[31];
                    112:        u_int32_t       boot_location;
                    113: };
                    114:
                    115: /*
                    116:  * G335 layout
                    117:  */
                    118:
                    119: struct g335dac {
                    120:        u_int32_t       boot_location;
                    121:        u_int32_t       unused1[32];
                    122:        u_int32_t       half_sync;
                    123:        u_int32_t       back_porch;
                    124:        u_int32_t       display;
                    125:        u_int32_t       short_display;
                    126:        u_int32_t       broad_pulse;
                    127:        u_int32_t       vsync;
                    128:        u_int32_t       vpre_equalize;
                    129:        u_int32_t       vpost_equalize;
                    130:        u_int32_t       vblank;
                    131:        u_int32_t       vdisplay;
                    132:        u_int32_t       line_time;
                    133:        u_int32_t       tos1;
                    134:        u_int32_t       mem_init;
                    135:        u_int32_t       transfer_delay;
                    136:        u_int32_t       unused2[17];
                    137:        u_int32_t       mask;
                    138:        u_int32_t       unused3[31];
                    139:        u_int32_t       cra;
                    140:        u_int32_t       unused4[15];
                    141:        u_int32_t       crb;
                    142:        u_int32_t       unused5[15];
                    143:        u_int32_t       tos2;
                    144:        u_int32_t       unused6[32];
                    145:        u_int32_t       cursor_palette[3];
                    146:        u_int32_t       unused7[28];
                    147:        u_int32_t       checksum[3];
                    148:        u_int32_t       unused8[4];
                    149:        u_int32_t       cursor_position;
                    150:        u_int32_t       unused9[56];
                    151:        u_int32_t       cmap[256];
                    152:        u_int32_t       cursor_store[512];
                    153: };
                    154:
                    155: union dac {
                    156:        struct g300dac  g300;
                    157:        struct g335dac  g335;
                    158: };
                    159:
                    160: /*
                    161:  * SBUS register mappings
                    162:  */
                    163: #define        VIGRA_REG_RAMDAC        1       /* either G300 or G335 */
                    164: #define        VIGRA_REG_CSR           2
                    165: #define        VIGRA_REG_VRAM          3
                    166:
                    167: #define        VIGRA_NREG              4
                    168:
                    169: union vigracmap {
                    170:        u_char          cm_map[256][4]; /* 256 R/G/B entries plus pad */
                    171:        u_int32_t       cm_chip[256];   /* the way the chip gets loaded */
                    172: };
                    173:
                    174: /* per-display variables */
                    175: struct vigra_softc {
                    176:        struct  sunfb sc_sunfb;         /* common base part */
                    177:        bus_space_tag_t sc_bustag;
                    178:        bus_addr_t      sc_paddr;
                    179:        volatile struct csregs *sc_regs;/* control registers */
                    180:        volatile union dac *sc_ramdac;  /* ramdac registers */
                    181:        union   vigracmap sc_cmap;      /* current colormap */
                    182:        int     sc_g300;
                    183:        void    *sc_ih;
                    184:        int     sc_nscreens;
                    185: };
                    186:
                    187: int vigra_ioctl(void *, u_long, caddr_t, int, struct proc *);
                    188: int vigra_alloc_screen(void *, const struct wsscreen_descr *, void **,
                    189:     int *, int *, long *);
                    190: void vigra_free_screen(void *, void *);
                    191: int vigra_show_screen(void *, void *, int, void (*cb)(void *, int, int),
                    192:     void *);
                    193: paddr_t vigra_mmap(void *, off_t, int);
                    194: void vigra_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
                    195: int vigra_getcmap(union vigracmap *, struct wsdisplay_cmap *, int);
                    196: int vigra_putcmap(union vigracmap *, struct wsdisplay_cmap *, int);
                    197: void vigra_loadcmap_immediate(struct vigra_softc *, int, int);
                    198: static __inline__ void vigra_loadcmap_deferred(struct vigra_softc *,
                    199:     u_int, u_int);
                    200: void vigra_burner(void *, u_int, u_int);
                    201: int vigra_intr(void *);
                    202:
                    203: struct wsdisplay_accessops vigra_accessops = {
                    204:        vigra_ioctl,
                    205:        vigra_mmap,
                    206:        vigra_alloc_screen,
                    207:        vigra_free_screen,
                    208:        vigra_show_screen,
                    209:        NULL,   /* load_font */
                    210:        NULL,   /* scrollback */
                    211:        NULL,   /* getchar */
                    212:        vigra_burner,
                    213: };
                    214:
                    215: int    vigramatch(struct device *, void *, void *);
                    216: void   vigraattach(struct device *, struct device *, void *);
                    217:
                    218: struct cfattach vigra_ca = {
                    219:        sizeof (struct vigra_softc), vigramatch, vigraattach
                    220: };
                    221:
                    222: struct cfdriver vigra_cd = {
                    223:        NULL, "vigra", DV_DULL
                    224: };
                    225:
                    226: /*
                    227:  * Match a supported vigra card.
                    228:  */
                    229: int
                    230: vigramatch(struct device *parent, void *vcf, void *aux)
                    231: {
                    232:        struct sbus_attach_args *sa = aux;
                    233:
                    234:        if (strcmp("vs10", sa->sa_name) != 0 &&
                    235:            strcmp("vs11", sa->sa_name) != 0 &&
                    236:            strcmp("vs12", sa->sa_name) != 0)
                    237:                return (0);
                    238:
                    239:        return (1);
                    240: }
                    241:
                    242: /*
                    243:  * Attach and initialize a vigra display, as well as a child wsdisplay.
                    244:  */
                    245: void
                    246: vigraattach(struct device *parent, struct device *self, void *args)
                    247: {
                    248:        struct vigra_softc *sc = (struct vigra_softc *)self;
                    249:        struct sbus_attach_args *sa = args;
                    250:        bus_space_tag_t bt;
                    251:        bus_space_handle_t bh;
                    252:        int node, row, isconsole = 0;
                    253:        char *nam;
                    254:
                    255:        bt = sa->sa_bustag;
                    256:        node = sa->sa_node;
                    257:        nam = getpropstring(node, "model");
                    258:        if (*nam == '\0')
                    259:                nam = (char *)sa->sa_name;
                    260:        printf(": %s", nam);
                    261:
                    262:        isconsole = node == fbnode;
                    263:
                    264:        if (sa->sa_nreg < VIGRA_NREG) {
                    265:                printf("\n%s: expected %d registers, got %d",
                    266:                    self->dv_xname, VIGRA_NREG, sa->sa_nreg);
                    267:                return;
                    268:        }
                    269:
                    270:        /*
                    271:         * Check whether we are using an G300 or an G335 chip.
                    272:         * The VS10 and VS12 use the G300, while the VS11 uses a G335.
                    273:         */
                    274:        sc->sc_g300 = strncmp(nam, "VIGRA,vs11", strlen("VIGRA,vs11"));
                    275:
                    276:        sc->sc_bustag = bt;
                    277:        if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_CSR].sbr_slot,
                    278:            sa->sa_reg[VIGRA_REG_CSR].sbr_offset,
                    279:            sa->sa_reg[VIGRA_REG_CSR].sbr_size, BUS_SPACE_MAP_LINEAR, 0,
                    280:            &bh) != 0) {
                    281:                printf("\n%s: can't map control registers\n", self->dv_xname);
                    282:                return;
                    283:        }
                    284:        sc->sc_regs = bus_space_vaddr(bt, bh);
                    285:        if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_RAMDAC].sbr_slot,
                    286:            sa->sa_reg[VIGRA_REG_RAMDAC].sbr_offset,
                    287:            sa->sa_reg[VIGRA_REG_RAMDAC].sbr_size, BUS_SPACE_MAP_LINEAR, 0,
                    288:            &bh) != 0) {
                    289:                printf("\n%s: can't map ramdac registers\n", self->dv_xname);
                    290:                return;
                    291:        }
                    292:        sc->sc_ramdac = bus_space_vaddr(bt, bh);
                    293:
                    294:        /* enable video */
                    295:        vigra_burner(sc, 1, 0);
                    296:
                    297:        fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
                    298:        if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot,
                    299:            sa->sa_reg[VIGRA_REG_VRAM].sbr_offset,
                    300:            round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0,
                    301:            &bh) != 0) {
                    302:                printf("\n%s: can't map video memory\n", self->dv_xname);
                    303:                return;
                    304:        }
                    305:        sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
                    306:        sc->sc_sunfb.sf_ro.ri_hw = sc;
                    307:        sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot,
                    308:            sa->sa_reg[VIGRA_REG_VRAM].sbr_offset);
                    309:
                    310:        printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
                    311:
                    312:        if ((sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri,
                    313:            IPL_TTY, 0, vigra_intr, sc, self->dv_xname)) == NULL) {
                    314:                printf("%s: couldn't establish interrupt, pri %d\n",
                    315:                    self->dv_xname, INTLEV(sa->sa_pri));
                    316:        }
                    317:
                    318:        /*
                    319:         * If the framebuffer width is under 1024x768, we will switch from the
                    320:         * PROM font to the more adequate 8x16 font here.
                    321:         * However, we need to adjust two things in this case:
                    322:         * - the display row should be overrided from the current PROM metrics,
                    323:         *   to prevent us from overwriting the last few lines of text.
                    324:         * - if the 80x34 screen would make a large margin appear around it,
                    325:         *   choose to clear the screen rather than keeping old prom output in
                    326:         *   the margins.
                    327:         * XXX there should be a rasops "clear margins" feature
                    328:         *
                    329:         * Also, in 1280x1024 resolution, the PROM display is not centered
                    330:         * vertically (why? no other frame buffer does this in such a mode!),
                    331:         * so be lazy and clear the screen here too anyways...
                    332:         */
                    333:        fbwscons_init(&sc->sc_sunfb, isconsole && (sc->sc_sunfb.sf_width != 800
                    334:            && sc->sc_sunfb.sf_width != 1280) ? 0 : RI_CLEAR);
                    335:        fbwscons_setcolormap(&sc->sc_sunfb, vigra_setcolor);
                    336:
                    337:        if (isconsole) {
                    338:                switch (sc->sc_sunfb.sf_width) {
                    339:                case 640:
                    340:                        row = sc->sc_sunfb.sf_ro.ri_rows - 1;
                    341:                        break;
                    342:                case 800:
                    343:                case 1280:
                    344:                        row = 0;        /* screen has been cleared above */
                    345:                        break;
                    346:                default:
                    347:                        row = -1;
                    348:                        break;
                    349:                }
                    350:
                    351:                fbwscons_console_init(&sc->sc_sunfb, row);
                    352:        }
                    353:
                    354:        fbwscons_attach(&sc->sc_sunfb, &vigra_accessops, isconsole);
                    355: }
                    356:
                    357: int
                    358: vigra_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
                    359: {
                    360:        struct vigra_softc *sc = v;
                    361:        struct wsdisplay_cmap *cm;
                    362:        struct wsdisplay_fbinfo *wdf;
                    363:        int error;
                    364:
                    365:        switch (cmd) {
                    366:        case WSDISPLAYIO_GTYPE:
                    367:                *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN;
                    368:                break;
                    369:        case WSDISPLAYIO_GINFO:
                    370:                wdf = (struct wsdisplay_fbinfo *)data;
                    371:                wdf->height = sc->sc_sunfb.sf_height;
                    372:                wdf->width  = sc->sc_sunfb.sf_width;
                    373:                wdf->depth  = sc->sc_sunfb.sf_depth;
                    374:                wdf->cmsize = 256;
                    375:                break;
                    376:        case WSDISPLAYIO_LINEBYTES:
                    377:                *(u_int *)data = sc->sc_sunfb.sf_linebytes;
                    378:                break;
                    379:
                    380:        case WSDISPLAYIO_GETCMAP:
                    381:                cm = (struct wsdisplay_cmap *)data;
                    382:                error = vigra_getcmap(&sc->sc_cmap, cm, sc->sc_g300);
                    383:                if (error)
                    384:                        return (error);
                    385:                break;
                    386:        case WSDISPLAYIO_PUTCMAP:
                    387:                cm = (struct wsdisplay_cmap *)data;
                    388:                error = vigra_putcmap(&sc->sc_cmap, cm, sc->sc_g300);
                    389:                if (error)
                    390:                        return (error);
                    391:                /* if we can handle interrupts, defer the update */
                    392:                if (sc->sc_ih != NULL)
                    393:                        vigra_loadcmap_deferred(sc, cm->index, cm->count);
                    394:                else
                    395:                        vigra_loadcmap_immediate(sc, cm->index, cm->count);
                    396:                break;
                    397:
                    398:        case WSDISPLAYIO_SVIDEO:
                    399:        case WSDISPLAYIO_GVIDEO:
                    400:                break;
                    401:
                    402:        case WSDISPLAYIO_GCURPOS:
                    403:        case WSDISPLAYIO_SCURPOS:
                    404:        case WSDISPLAYIO_GCURMAX:
                    405:        case WSDISPLAYIO_GCURSOR:
                    406:        case WSDISPLAYIO_SCURSOR:
                    407:        default:
                    408:                return (-1);    /* not supported yet */
                    409:         }
                    410:
                    411:        return (0);
                    412: }
                    413:
                    414: int
                    415: vigra_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
                    416:     int *curxp, int *curyp, long *attrp)
                    417: {
                    418:        struct vigra_softc *sc = v;
                    419:
                    420:        if (sc->sc_nscreens > 0)
                    421:                return (ENOMEM);
                    422:
                    423:        *cookiep = &sc->sc_sunfb.sf_ro;
                    424:        *curyp = 0;
                    425:        *curxp = 0;
                    426:        sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
                    427:            WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
                    428:        sc->sc_nscreens++;
                    429:        return (0);
                    430: }
                    431:
                    432: void
                    433: vigra_free_screen(void *v, void *cookie)
                    434: {
                    435:        struct vigra_softc *sc = v;
                    436:
                    437:        sc->sc_nscreens--;
                    438: }
                    439:
                    440: int
                    441: vigra_show_screen(void *v, void *cookie, int waitok,
                    442:     void (*cb)(void *, int, int), void *cbarg)
                    443: {
                    444:        return (0);
                    445: }
                    446:
                    447: /*
                    448:  * Return the address that would map the given device at the given
                    449:  * offset, allowing for the given protection, or return -1 for error.
                    450:  */
                    451: paddr_t
                    452: vigra_mmap(void *v, off_t offset, int prot)
                    453: {
                    454:        struct vigra_softc *sc = v;
                    455:
                    456:        if (offset & PGOFSET)
                    457:                return (-1);
                    458:
                    459:        if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
                    460:                return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
                    461:                    offset, prot, BUS_SPACE_MAP_LINEAR));
                    462:        }
                    463:
                    464:        return (-1);
                    465: }
                    466:
                    467: void
                    468: vigra_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
                    469: {
                    470:        struct vigra_softc *sc = v;
                    471:
                    472:        if (sc->sc_g300) {
                    473:                sc->sc_cmap.cm_map[index][3] = r;
                    474:                sc->sc_cmap.cm_map[index][2] = g;
                    475:                sc->sc_cmap.cm_map[index][1] = b;
                    476:        } else {
                    477:                sc->sc_cmap.cm_map[index][3] = b;
                    478:                sc->sc_cmap.cm_map[index][2] = g;
                    479:                sc->sc_cmap.cm_map[index][1] = r;
                    480:        }
                    481:        sc->sc_cmap.cm_map[index][0] = 0;       /* no alpha channel */
                    482:
                    483:        vigra_loadcmap_immediate(sc, index, 1);
                    484: }
                    485:
                    486: int
                    487: vigra_getcmap(union vigracmap *cm, struct wsdisplay_cmap *rcm, int g300)
                    488: {
                    489:        u_int index = rcm->index, count = rcm->count, i;
                    490:        int error;
                    491:
                    492:        if (index >= 256 || count > 256 - index)
                    493:                return (EINVAL);
                    494:
                    495:        if (g300) {
                    496:                for (i = 0; i < count; i++) {
                    497:                        if ((error = copyout(&cm->cm_map[index + i][3],
                    498:                            &rcm->red[i], 1)) != 0)
                    499:                                return (error);
                    500:                        if ((error = copyout(&cm->cm_map[index + i][1],
                    501:                            &rcm->blue[i], 1)) != 0)
                    502:                                return (error);
                    503:                }
                    504:        } else {
                    505:                for (i = 0; i < count; i++) {
                    506:                        if ((error = copyout(&cm->cm_map[index + i][1],
                    507:                            &rcm->red[i], 1)) != 0)
                    508:                                return (error);
                    509:                        if ((error = copyout(&cm->cm_map[index + i][3],
                    510:                            &rcm->blue[i], 1)) != 0)
                    511:                                return (error);
                    512:                }
                    513:        }
                    514:
                    515:        for (i = 0; i < count; i++) {
                    516:                if ((error = copyout(&cm->cm_map[index + i][2],
                    517:                    &rcm->green[i], 1)) != 0)
                    518:                        return (error);
                    519:        }
                    520:        return (0);
                    521: }
                    522:
                    523: int
                    524: vigra_putcmap(union vigracmap *cm, struct wsdisplay_cmap *rcm, int g300)
                    525: {
                    526:        u_int index = rcm->index, count = rcm->count, i;
                    527:        int error;
                    528:
                    529:        if (index >= 256 || count > 256 - index)
                    530:                return (EINVAL);
                    531:
                    532:        if (g300) {
                    533:                for (i = 0; i < count; i++) {
                    534:                        if ((error = copyin(&rcm->red[i],
                    535:                            &cm->cm_map[index + i][3], 1)) != 0)
                    536:                                return (error);
                    537:                        if ((error = copyin(&rcm->blue[i],
                    538:                            &cm->cm_map[index + i][1], 1)) != 0)
                    539:                                return (error);
                    540:                }
                    541:        } else {
                    542:                for (i = 0; i < count; i++) {
                    543:                        if ((error = copyin(&rcm->red[i],
                    544:                            &cm->cm_map[index + i][1], 1)) != 0)
                    545:                                return (error);
                    546:                        if ((error = copyin(&rcm->blue[i],
                    547:                            &cm->cm_map[index + i][3], 1)) != 0)
                    548:                                return (error);
                    549:                }
                    550:        }
                    551:
                    552:        for (i = 0; i < count; i++) {
                    553:                if ((error = copyin(&rcm->green[i],
                    554:                    &cm->cm_map[index + i][2], 1)) != 0)
                    555:                        return (error);
                    556:                cm->cm_map[index + i][0] = 0;   /* no alpha channel */
                    557:        }
                    558:        return (0);
                    559: }
                    560:
                    561: void
                    562: vigra_loadcmap_immediate(struct vigra_softc *sc, int start, int ncolors)
                    563: {
                    564:        u_int32_t *colp = &sc->sc_cmap.cm_chip[start];
                    565:        volatile u_int32_t *lutp;
                    566:
                    567:        if (sc->sc_g300)
                    568:                lutp = &(sc->sc_ramdac->g300.cmap[start]);
                    569:        else
                    570:                lutp = &(sc->sc_ramdac->g335.cmap[start]);
                    571:
                    572:        while (--ncolors >= 0)
                    573:                *lutp++ = *colp++;
                    574: }
                    575:
                    576: static __inline__ void
                    577: vigra_loadcmap_deferred(struct vigra_softc *sc, u_int start, u_int ncolors)
                    578: {
                    579:
                    580:        sc->sc_regs->imr = 1;
                    581: }
                    582:
                    583: void
                    584: vigra_burner(void *v, u_int on, u_int flags)
                    585: {
                    586:        struct vigra_softc *sc = v;
                    587:
                    588:        if (on) {
                    589:                sc->sc_regs->bcr = 0;
                    590:        } else {
                    591:                sc->sc_regs->bcr = 1;
                    592:        }
                    593: }
                    594:
                    595: int
                    596: vigra_intr(void *v)
                    597: {
                    598:        struct vigra_softc *sc = v;
                    599:
                    600:        if (sc->sc_regs->imr == 0 ||
                    601:            !ISSET(sc->sc_regs->g3sr, STATUS_INTR)) {
                    602:                /* Not expecting an interrupt, it's not for us. */
                    603:                return (0);
                    604:        }
                    605:
                    606:        /* Acknowledge the interrupt and disable it. */
                    607:        sc->sc_regs->imr = 0;
                    608:
                    609:        vigra_loadcmap_immediate(sc, 0, 256);
                    610:
                    611:        return (1);
                    612: }

CVSweb