[BACK]Return to diofb.c CVS log [TXT][DIR] Up to [local] / sys / arch / hp300 / dev

Annotation of sys/arch/hp300/dev/diofb.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: diofb.c,v 1.16 2006/11/29 19:08:19 miod Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005, Miodrag Vallat
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            18:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            19:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            20:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            23:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            24:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            25:  * POSSIBILITY OF SUCH DAMAGE.
        !            26:  */
        !            27: /*
        !            28:  * Copyright (c) 1988 University of Utah.
        !            29:  * Copyright (c) 1990, 1993
        !            30:  *     The Regents of the University of California.  All rights reserved.
        !            31:  *
        !            32:  * This code is derived from software contributed to Berkeley by
        !            33:  * the Systems Programming Group of the University of Utah Computer
        !            34:  * Science Department.
        !            35:  *
        !            36:  * Redistribution and use in source and binary forms, with or without
        !            37:  * modification, are permitted provided that the following conditions
        !            38:  * are met:
        !            39:  * 1. Redistributions of source code must retain the above copyright
        !            40:  *    notice, this list of conditions and the following disclaimer.
        !            41:  * 2. Redistributions in binary form must reproduce the above copyright
        !            42:  *    notice, this list of conditions and the following disclaimer in the
        !            43:  *    documentation and/or other materials provided with the distribution.
        !            44:  * 3. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  */
        !            60:
        !            61: #include <sys/param.h>
        !            62: #include <sys/conf.h>
        !            63: #include <sys/proc.h>
        !            64: #include <sys/ioctl.h>
        !            65: #include <sys/tty.h>
        !            66: #include <sys/systm.h>
        !            67: #include <sys/device.h>
        !            68:
        !            69: #include <machine/autoconf.h>
        !            70: #include <machine/cpu.h>
        !            71:
        !            72: #include <hp300/dev/dioreg.h>
        !            73: #include <hp300/dev/diovar.h>
        !            74:
        !            75: #include <dev/wscons/wsconsio.h>
        !            76: #include <dev/wscons/wsdisplayvar.h>
        !            77: #include <dev/rasops/rasops.h>
        !            78:
        !            79: #include <hp300/dev/diofbreg.h>
        !            80: #include <hp300/dev/diofbvar.h>
        !            81:
        !            82: extern int rasops_alloc_cattr(void *, int, int, int, long *);
        !            83:
        !            84: int    diofb_alloc_attr(void *, int, int, int, long *);
        !            85: void   diofb_copycols(void *, int, int, int, int);
        !            86: void   diofb_erasecols(void *, int, int, int, long);
        !            87: void   diofb_copyrows(void *, int, int, int);
        !            88: void   diofb_eraserows(void *, int, int, long);
        !            89: void   diofb_do_cursor(struct rasops_info *);
        !            90:
        !            91: /*
        !            92:  * Frame buffer geometry initialization
        !            93:  */
        !            94:
        !            95: int
        !            96: diofb_fbinquire(struct diofb *fb, int scode, struct diofbreg *fbr)
        !            97: {
        !            98:        int fboff, regsize;
        !            99:
        !           100:        if (ISIIOVA(fbr))
        !           101:                fb->regaddr = (caddr_t)IIOP(fbr);
        !           102:        else
        !           103:                fb->regaddr = dio_scodetopa(scode);
        !           104:
        !           105:        if (fb->fbwidth == 0 || fb->fbheight == 0) {
        !           106:                fb->fbwidth = (fbr->fbwmsb << 8) | fbr->fbwlsb;
        !           107:                fb->fbheight = (fbr->fbhmsb << 8) | fbr->fbhlsb;
        !           108:        }
        !           109:        fb->fbsize = fb->fbwidth * fb->fbheight;
        !           110:
        !           111:        fb->regkva = (caddr_t)fbr;
        !           112:        fboff = (fbr->fbomsb << 8) | fbr->fbolsb;
        !           113:        fb->fbaddr = (caddr_t) (*((u_char *)fbr + fboff) << 16);
        !           114:
        !           115:        if (fb->regaddr >= (caddr_t)DIOII_BASE) {
        !           116:                /*
        !           117:                 * For DIO-II space the fbaddr just computed is
        !           118:                 * the offset from the select code base (regaddr)
        !           119:                 * of the framebuffer.  Hence it is also implicitly
        !           120:                 * the size of the set.
        !           121:                 */
        !           122:                regsize = (int)fb->fbaddr;
        !           123:                fb->fbaddr += (int)fb->regaddr;
        !           124:                fb->fbkva = (caddr_t)fbr + regsize;
        !           125:        } else {
        !           126:                /*
        !           127:                 * For internal or DIO-I space we need to map the separate
        !           128:                 * framebuffer.
        !           129:                 */
        !           130:                fb->fbkva = iomap(fb->fbaddr, fb->fbsize);
        !           131:                if (fb->fbkva == NULL)
        !           132:                        return (ENOMEM);
        !           133:        }
        !           134:        if (fb->dwidth == 0 || fb->dheight == 0) {
        !           135:                fb->dwidth = (fbr->dwmsb << 8) | fbr->dwlsb;
        !           136:                fb->dheight = (fbr->dhmsb << 8) | fbr->dhlsb;
        !           137:        }
        !           138:
        !           139:        /*
        !           140:         * Some displays, such as the DaVinci, appear to return a display
        !           141:         * height larger than the frame buffer height.
        !           142:         */
        !           143:        if (fb->dwidth > fb->fbwidth)
        !           144:                fb->dwidth = fb->fbwidth;
        !           145:        if (fb->dheight > fb->fbheight)
        !           146:                fb->dheight = fb->fbheight;
        !           147:
        !           148:        fb->planes = fbr->num_planes;
        !           149:        if (fb->planes > 8)
        !           150:                fb->planes = 8;
        !           151:        fb->planemask = (1 << fb->planes) - 1;
        !           152:
        !           153:        fb->mapmode = WSDISPLAYIO_MODE_DUMBFB;
        !           154:
        !           155:        return (0);
        !           156: }
        !           157:
        !           158: /*
        !           159:  * Frame buffer rasops and colormap setup
        !           160:  */
        !           161:
        !           162: void
        !           163: diofb_fbsetup(struct diofb *fb)
        !           164: {
        !           165:        struct rasops_info *ri = &fb->ri;
        !           166:
        !           167:        /*
        !           168:         * Pretend we are an 8bpp frame buffer, unless ri_depth is already
        !           169:         * initialized, since this is how it is supposed to be addressed.
        !           170:         * (Hyperion forces 1bpp because it is really 1bpp addressed).
        !           171:         */
        !           172:        if (ri->ri_depth == 0)
        !           173:                ri->ri_depth = 8;
        !           174:        ri->ri_stride = (fb->fbwidth * ri->ri_depth) / 8;
        !           175:
        !           176:        ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
        !           177:        /* We don't really support colors on less than 4bpp frame buffers */
        !           178:        if (fb->planes < 4)
        !           179:                ri->ri_flg |= RI_FORCEMONO;
        !           180:        ri->ri_bits = fb->fbkva;
        !           181:        ri->ri_width = fb->dwidth;
        !           182:        ri->ri_height = fb->dheight;
        !           183:        ri->ri_hw = fb;
        !           184:
        !           185:        /*
        !           186:         * Ask for an unholy big display, rasops will trim this to more
        !           187:         * reasonable values.
        !           188:         */
        !           189:        rasops_init(ri, 160, 160);
        !           190:
        !           191:        diofb_resetcmap(fb);
        !           192:
        !           193:        /*
        !           194:         * For low depth frame buffers, since we have faked a 8bpp frame buffer
        !           195:         * to rasops, we actually have to remove capabilities.
        !           196:         */
        !           197:        if (fb->planes == 4) {
        !           198:                ri->ri_ops.alloc_attr = diofb_alloc_attr;
        !           199:                ri->ri_caps &= ~WSSCREEN_HILIT;
        !           200:        }
        !           201:
        !           202:        ri->ri_ops.copycols = diofb_copycols;
        !           203:        ri->ri_ops.erasecols = diofb_erasecols;
        !           204:        if (ri->ri_depth != 1) {
        !           205:                ri->ri_ops.copyrows = diofb_copyrows;
        !           206:                ri->ri_ops.eraserows = diofb_eraserows;
        !           207:                ri->ri_do_cursor = diofb_do_cursor;
        !           208:        }
        !           209:
        !           210:        /* Clear entire display, including non visible areas */
        !           211:        (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, fb->fbheight, RR_CLEAR, 0xff);
        !           212:
        !           213:        strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name));
        !           214:        fb->wsd.ncols = ri->ri_cols;
        !           215:        fb->wsd.nrows = ri->ri_rows;
        !           216:        fb->wsd.textops = &ri->ri_ops;
        !           217:        fb->wsd.fontwidth = ri->ri_font->fontwidth;
        !           218:        fb->wsd.fontheight = ri->ri_font->fontheight;
        !           219:        fb->wsd.capabilities = ri->ri_caps;
        !           220: }
        !           221:
        !           222: /*
        !           223:  * Setup default emulation mode colormap
        !           224:  */
        !           225: void
        !           226: diofb_resetcmap(struct diofb *fb)
        !           227: {
        !           228:        const u_char *color;
        !           229:        u_int i;
        !           230:
        !           231:        /* start with the rasops colormap */
        !           232:        color = (const u_char *)rasops_cmap;
        !           233:        for (i = 0; i < 256; i++) {
        !           234:                fb->cmap.r[i] = *color++;
        !           235:                fb->cmap.g[i] = *color++;
        !           236:                fb->cmap.b[i] = *color++;
        !           237:        }
        !           238:
        !           239:        /*
        !           240:         * Tweak colormap
        !           241:         *
        !           242:         * Due to the way rasops cursor work, we need to provide
        !           243:         * copies of the 8 or 16 basic colors at extra locations
        !           244:         * in 4bpp and 6bpp mode. This is because missing planes
        !           245:         * accept writes but read back as zero.
        !           246:         *
        !           247:         * So, in 6bpp mode:
        !           248:         *   00 gets inverted to ff, read back as 3f
        !           249:         *   3f gets inverted to c0, read back as 00
        !           250:         * and in 4bpp mode:
        !           251:         *   00 gets inverted to ff, read back as 0f
        !           252:         *   0f gets inverted to f0, read back as 00
        !           253:         */
        !           254:
        !           255:        switch (fb->planes) {
        !           256:        case 6:
        !           257:                /*
        !           258:                 * 00-0f normal colors
        !           259:                 * 30-3f inverted colors
        !           260:                 * c0-cf normal colors
        !           261:                 * f0-ff inverted colors
        !           262:                 */
        !           263:                bcopy(fb->cmap.r + 0x00, fb->cmap.r + 0xc0, 0x10);
        !           264:                bcopy(fb->cmap.g + 0x00, fb->cmap.g + 0xc0, 0x10);
        !           265:                bcopy(fb->cmap.b + 0x00, fb->cmap.b + 0xc0, 0x10);
        !           266:                bcopy(fb->cmap.r + 0xf0, fb->cmap.r + 0x30, 0x10);
        !           267:                bcopy(fb->cmap.g + 0xf0, fb->cmap.g + 0x30, 0x10);
        !           268:                bcopy(fb->cmap.b + 0xf0, fb->cmap.b + 0x30, 0x10);
        !           269:                break;
        !           270:        case 4:
        !           271:                /*
        !           272:                 * 00-07 normal colors
        !           273:                 * 08-0f inverted colors
        !           274:                 * highlighted colors are not available.
        !           275:                 */
        !           276:                bcopy(fb->cmap.r + 0xf8, fb->cmap.r + 0x08, 0x08);
        !           277:                bcopy(fb->cmap.g + 0xf8, fb->cmap.g + 0x08, 0x08);
        !           278:                bcopy(fb->cmap.b + 0xf8, fb->cmap.b + 0x08, 0x08);
        !           279:                break;
        !           280:        }
        !           281: }
        !           282:
        !           283: /*
        !           284:  * Attachment helpers
        !           285:  */
        !           286:
        !           287: void
        !           288: diofb_cnattach(struct diofb *fb)
        !           289: {
        !           290:        long defattr;
        !           291:        struct rasops_info *ri;
        !           292:
        !           293:        ri = &fb->ri;
        !           294:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
        !           295:        wsdisplay_cnattach(&fb->wsd, ri, 0, 0, defattr);
        !           296: }
        !           297:
        !           298: void
        !           299: diofb_end_attach(void *sc, struct wsdisplay_accessops *accessops,
        !           300:     struct diofb *fb, int console, const char *descr)
        !           301: {
        !           302:        struct wsemuldisplaydev_attach_args waa;
        !           303:
        !           304:        printf(": %dx%d", fb->dwidth, fb->dheight);
        !           305:
        !           306:        if (fb->planes == 1)
        !           307:                printf(" monochrome");
        !           308:        else
        !           309:                printf("x%d", fb->planes);
        !           310:
        !           311:        if (descr != NULL)
        !           312:                printf(" %s", descr);
        !           313:        printf(" frame buffer\n");
        !           314:
        !           315:        fb->scrlist[0] = &fb->wsd;
        !           316:        fb->wsl.nscreens = 1;
        !           317:        fb->wsl.screens = (const struct wsscreen_descr **)fb->scrlist;
        !           318:
        !           319:        waa.console = console;
        !           320:        waa.scrdata = &fb->wsl;
        !           321:        waa.accessops = accessops;
        !           322:        waa.accesscookie = fb;
        !           323:        waa.defaultscreens = 0;
        !           324:
        !           325:        config_found((struct device *)sc, &waa, wsemuldisplaydevprint);
        !           326: }
        !           327:
        !           328: /*
        !           329:  * Common wsdisplay emulops for DIO frame buffers
        !           330:  */
        !           331:
        !           332: int
        !           333: diofb_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
        !           334: {
        !           335:        if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
        !           336:                return (EINVAL);
        !           337:
        !           338:        return (rasops_alloc_cattr(cookie, fg, bg, flg, attr));
        !           339: }
        !           340:
        !           341: void
        !           342: diofb_copycols(void *cookie, int row, int src, int dst, int n)
        !           343: {
        !           344:        struct rasops_info *ri = cookie;
        !           345:        struct diofb *fb = ri->ri_hw;
        !           346:
        !           347:        n *= ri->ri_font->fontwidth;
        !           348:        src *= ri->ri_font->fontwidth;
        !           349:        dst *= ri->ri_font->fontwidth;
        !           350:        row *= ri->ri_font->fontheight;
        !           351:
        !           352:        (*fb->bmv)(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
        !           353:            ri->ri_xorigin + dst, ri->ri_yorigin + row,
        !           354:            n, ri->ri_font->fontheight, RR_COPY, 0xff);
        !           355: }
        !           356:
        !           357: void
        !           358: diofb_copyrows(void *cookie, int src, int dst, int n)
        !           359: {
        !           360:        struct rasops_info *ri = cookie;
        !           361:        struct diofb *fb = ri->ri_hw;
        !           362:
        !           363:        n *= ri->ri_font->fontheight;
        !           364:        src *= ri->ri_font->fontheight;
        !           365:        dst *= ri->ri_font->fontheight;
        !           366:
        !           367:        (*fb->bmv)(fb, ri->ri_xorigin, ri->ri_yorigin + src,
        !           368:            ri->ri_xorigin, ri->ri_yorigin + dst,
        !           369:            ri->ri_emuwidth, n, RR_COPY, 0xff);
        !           370: }
        !           371:
        !           372: void
        !           373: diofb_erasecols(void *cookie, int row, int col, int num, long attr)
        !           374: {
        !           375:        struct rasops_info *ri = cookie;
        !           376:        struct diofb *fb = ri->ri_hw;
        !           377:        int fg, bg;
        !           378:        int snum, scol, srow;
        !           379:
        !           380:        ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
        !           381:
        !           382:        snum = num * ri->ri_font->fontwidth;
        !           383:        scol = col * ri->ri_font->fontwidth + ri->ri_xorigin;
        !           384:        srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
        !           385:
        !           386:        /*
        !           387:         * If this is too tricky for the simple raster ops engine,
        !           388:         * pass the fun to rasops.
        !           389:         */
        !           390:        if ((*fb->bmv)(fb, scol, srow, scol, srow, snum,
        !           391:            ri->ri_font->fontheight, RR_CLEAR, 0xff ^ bg) != 0)
        !           392:                rasops_erasecols(cookie, row, col, num, attr);
        !           393: }
        !           394:
        !           395: void
        !           396: diofb_eraserows(void *cookie, int row, int num, long attr)
        !           397: {
        !           398:        struct rasops_info *ri = cookie;
        !           399:        struct diofb *fb = ri->ri_hw;
        !           400:        int fg, bg;
        !           401:        int srow, snum;
        !           402:        int rc;
        !           403:
        !           404:        ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
        !           405:        bg ^= 0xff;
        !           406:
        !           407:        if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
        !           408:                rc = (*fb->bmv)(fb, 0, 0, 0, 0, ri->ri_width, ri->ri_height,
        !           409:                    RR_CLEAR, bg);
        !           410:        } else {
        !           411:                srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
        !           412:                snum = num * ri->ri_font->fontheight;
        !           413:                rc = (*fb->bmv)(fb, ri->ri_xorigin, srow, ri->ri_xorigin,
        !           414:                    srow, ri->ri_emuwidth, snum, RR_CLEAR, bg);
        !           415:        }
        !           416:        if (rc != 0)
        !           417:                rasops_eraserows(cookie, row, num, attr);
        !           418: }
        !           419:
        !           420: void
        !           421: diofb_do_cursor(struct rasops_info *ri)
        !           422: {
        !           423:        struct diofb *fb = ri->ri_hw;
        !           424:        int x, y;
        !           425:
        !           426:        x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
        !           427:        y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
        !           428:        (*fb->bmv)(fb, x, y, x, y, ri->ri_font->fontwidth,
        !           429:            ri->ri_font->fontheight, RR_INVERT, 0xff);
        !           430: }
        !           431:
        !           432: /*
        !           433:  * Common wsdisplay accessops for DIO frame buffers
        !           434:  */
        !           435:
        !           436: int
        !           437: diofb_alloc_screen(void *v, const struct wsscreen_descr *type,
        !           438:     void **cookiep, int *curxp, int *curyp, long *attrp)
        !           439: {
        !           440:        struct diofb *fb = v;
        !           441:        struct rasops_info *ri = &fb->ri;
        !           442:
        !           443:        if (fb->nscreens > 0)
        !           444:                return (ENOMEM);
        !           445:
        !           446:        *cookiep = ri;
        !           447:        *curxp = *curyp = 0;
        !           448:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
        !           449:        fb->nscreens++;
        !           450:
        !           451:        return (0);
        !           452: }
        !           453:
        !           454: void
        !           455: diofb_free_screen(void *v, void *cookie)
        !           456: {
        !           457:        struct diofb *fb = v;
        !           458:
        !           459:        fb->nscreens--;
        !           460: }
        !           461:
        !           462: int
        !           463: diofb_show_screen(void *v, void *cookie, int waitok,
        !           464:     void (*cb)(void *, int, int), void *cbarg)
        !           465: {
        !           466:        return (0);
        !           467: }
        !           468:
        !           469: paddr_t
        !           470: diofb_mmap(void * v, off_t offset, int prot)
        !           471: {
        !           472:        struct diofb *fb = v;
        !           473:
        !           474:        if ((offset & PAGE_MASK) != 0)
        !           475:                return (-1);
        !           476:
        !           477:        switch (fb->mapmode) {
        !           478:        case WSDISPLAYIO_MODE_MAPPED:
        !           479:                if (offset >= 0 && offset < DIOFB_REGSPACE)
        !           480:                        return (((paddr_t)fb->regaddr + offset) >> PGSHIFT);
        !           481:                offset -= DIOFB_REGSPACE;
        !           482:                /* FALLTHROUGH */
        !           483:        case WSDISPLAYIO_MODE_DUMBFB:
        !           484:                if (offset >= 0 && offset < fb->fbsize)
        !           485:                        return (((paddr_t)fb->fbaddr + offset) >> PGSHIFT);
        !           486:                break;
        !           487:        }
        !           488:
        !           489:        return (-1);
        !           490: }
        !           491:
        !           492: int
        !           493: diofb_getcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
        !           494: {
        !           495:        u_int index = cm->index, count = cm->count;
        !           496:        u_int colcount = 1 << fb->planes;
        !           497:        int error;
        !           498:
        !           499:        if (index >= colcount || count > colcount - index)
        !           500:                return (EINVAL);
        !           501:
        !           502:        if ((error = copyout(fb->cmap.r + index, cm->red, count)) != 0)
        !           503:                return (error);
        !           504:        if ((error = copyout(fb->cmap.g + index, cm->green, count)) != 0)
        !           505:                return (error);
        !           506:        if ((error = copyout(fb->cmap.b + index, cm->blue, count)) != 0)
        !           507:                return (error);
        !           508:
        !           509:        return (0);
        !           510: }

CVSweb