[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

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