[BACK]Return to lcg.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / vsa

Annotation of sys/arch/vax/vsa/lcg.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: lcg.c,v 1.10 2006/11/29 12:13:54 miod Exp $   */
                      2: /*
                      3:  * Copyright (c) 2006 Miodrag Vallat.
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice, this permission notice, and the disclaimer below
                      8:  * appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18: /*
                     19:  * Copyright (c) 2003, 2004 Blaz Antonic
                     20:  * All rights reserved.
                     21:  *
                     22:  * Redistribution and use in source and binary forms, with or without
                     23:  * modification, are permitted provided that the following conditions
                     24:  * are met:
                     25:  * 1. Redistributions of source code must retain the above copyright
                     26:  *    notice, this list of conditions and the following disclaimer.
                     27:  * 2. Redistributions in binary form must reproduce the above copyright
                     28:  *    notice, this list of conditions and the following disclaimer in the
                     29:  *    documentation and/or other materials provided with the distribution.
                     30:  * 3. All advertising materials mentioning features or use of this software
                     31:  *    must display the abovementioned copyrights
                     32:  * 4. The name of the author may not be used to endorse or promote products
                     33:  *    derived from this software without specific prior written permission
                     34:  *
                     35:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     36:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     37:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     38:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     39:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     40:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     41:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     42:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     43:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     44:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     45:  */
                     46:
                     47: #include <sys/param.h>
                     48: #include <sys/device.h>
                     49: #include <sys/systm.h>
                     50: #include <sys/malloc.h>
                     51: #include <sys/conf.h>
                     52: #include <sys/kernel.h>
                     53:
                     54: #include <machine/vsbus.h>
                     55: #include <machine/scb.h>
                     56: #include <machine/sid.h>
                     57: #include <machine/cpu.h>
                     58:
                     59: #include <uvm/uvm_extern.h>
                     60:
                     61: #include <dev/cons.h>
                     62:
                     63: #include <dev/wscons/wsconsio.h>
                     64: #include <dev/wscons/wsdisplayvar.h>
                     65: #include <dev/rasops/rasops.h>
                     66:
                     67: #include <vax/vsa/lcgreg.h>
                     68:
                     69: #define        LCG_CONFIG_ADDR 0x200f0010      /* configuration register */
                     70: #define        LCG_REG_ADDR    0x20100000      /* registers */
                     71: #define        LCG_REG_SIZE    0x4000
                     72: #define        LCG_LUT_ADDR    0x21800000      /* colormap */
                     73: #define        LCG_LUT_OFFSET  0x0800
                     74: #define        LCG_LUT_SIZE    0x0800
                     75: #define        LCG_FB_ADDR     0x21801000      /* frame buffer */
                     76:
                     77: int    lcg_match(struct device *, void *, void *);
                     78: void   lcg_attach(struct device *, struct device *, void *);
                     79:
                     80: struct lcg_screen {
                     81:        struct rasops_info ss_ri;
                     82:        u_int32_t       ss_cfg;
                     83:        u_int           ss_width, ss_height, ss_depth;
                     84:        u_int           ss_fbsize;              /* visible part only */
                     85:        caddr_t         ss_addr;                /* frame buffer address */
                     86:        vaddr_t         ss_reg;
                     87:        volatile u_int8_t *ss_lut;
                     88:        u_int8_t        ss_cmap[256 * 3];
                     89: };
                     90:
                     91: /* for console */
                     92: struct lcg_screen lcg_consscr;
                     93:
                     94: struct lcg_softc {
                     95:        struct device sc_dev;
                     96:        struct lcg_screen *sc_scr;
                     97:        int     sc_nscreens;
                     98: };
                     99:
                    100: struct cfattach lcg_ca = {
                    101:        sizeof(struct lcg_softc), lcg_match, lcg_attach,
                    102: };
                    103:
                    104: struct cfdriver lcg_cd = {
                    105:        NULL, "lcg", DV_DULL
                    106: };
                    107:
                    108: struct wsscreen_descr lcg_stdscreen = {
                    109:        "std",
                    110: };
                    111:
                    112: const struct wsscreen_descr *_lcg_scrlist[] = {
                    113:        &lcg_stdscreen,
                    114: };
                    115:
                    116: const struct wsscreen_list lcg_screenlist = {
                    117:        sizeof(_lcg_scrlist) / sizeof(struct wsscreen_descr *),
                    118:        _lcg_scrlist,
                    119: };
                    120:
                    121: int    lcg_ioctl(void *, u_long, caddr_t, int, struct proc *);
                    122: paddr_t        lcg_mmap(void *, off_t, int);
                    123: int    lcg_alloc_screen(void *, const struct wsscreen_descr *,
                    124:            void **, int *, int *, long *);
                    125: void   lcg_free_screen(void *, void *);
                    126: int    lcg_show_screen(void *, void *, int,
                    127:            void (*) (void *, int, int), void *);
                    128: void   lcg_burner(void *, u_int, u_int);
                    129:
                    130: const struct wsdisplay_accessops lcg_accessops = {
                    131:        lcg_ioctl,
                    132:        lcg_mmap,
                    133:        lcg_alloc_screen,
                    134:        lcg_free_screen,
                    135:        lcg_show_screen,
                    136:        NULL,   /* load_font */
                    137:        NULL,   /* scrollback */
                    138:        NULL,   /* getchar */
                    139:        lcg_burner
                    140: };
                    141:
                    142: int    lcg_alloc_attr(void *, int, int, int, long *);
                    143: int    lcg_getcmap(struct lcg_screen *, struct wsdisplay_cmap *);
                    144: void   lcg_loadcmap(struct lcg_screen *, int, int);
                    145: int    lcg_probe_screen(u_int32_t, u_int *, u_int *);
                    146: int    lcg_putcmap(struct lcg_screen *, struct wsdisplay_cmap *);
                    147: void   lcg_resetcmap(struct lcg_screen *);
                    148: int    lcg_setup_screen(struct lcg_screen *);
                    149:
                    150: #define        lcg_read_reg(ss, regno) \
                    151:        *(volatile u_int32_t *)((ss)->ss_reg + (regno))
                    152: #define        lcg_write_reg(ss, regno, val) \
                    153:        *(volatile u_int32_t *)((ss)->ss_reg + (regno)) = (val)
                    154:
                    155: int
                    156: lcg_match(struct device *parent, void *vcf, void *aux)
                    157: {
                    158:        struct vsbus_softc *sc = (void *)parent;
                    159:        struct vsbus_attach_args *va = aux;
                    160:        vaddr_t cfgreg;
                    161:        int depth, missing;
                    162:        volatile u_int8_t *ch;
                    163:
                    164:        switch (vax_boardtype) {
                    165:        default:
                    166:                return (0);
                    167:
                    168:        case VAX_BTYP_46:
                    169:        case VAX_BTYP_48:
                    170:                if (va->va_paddr != LCG_REG_ADDR)
                    171:                        return (0);
                    172:
                    173:                break;
                    174:        }
                    175:
                    176:        /*
                    177:         * Check the configuration register.
                    178:         * This is done to sort out empty frame buffer slots, since the video
                    179:         * memory test sometimes passes!
                    180:         */
                    181:        cfgreg = vax_map_physmem(LCG_CONFIG_ADDR, 1);
                    182:        depth = lcg_probe_screen(*(volatile u_int32_t *)cfgreg, NULL, NULL);
                    183:        vax_unmap_physmem(cfgreg, 1);
                    184:        if (depth < 0)  /* no frame buffer */
                    185:                return (0);
                    186:
                    187:        /*
                    188:         * Check for video memory.
                    189:         * We can not use badaddr() on these models.
                    190:         */
                    191:        missing = 0;
                    192:        ch = (volatile u_int8_t *)vax_map_physmem(LCG_FB_ADDR, 1);
                    193:        *ch = 0x01;
                    194:        if ((*ch & 0x01) == 0)
                    195:                missing = 1;
                    196:        else {
                    197:                *ch = 0x00;
                    198:                if ((*ch & 0x01) != 0)
                    199:                        missing = 1;
                    200:        }
                    201:        vax_unmap_physmem((vaddr_t)ch, 1);
                    202:        if (missing != 0)
                    203:                return (0);
                    204:
                    205:        sc->sc_mask = 0x04;     /* XXX - should be generated */
                    206:        scb_fake(0x120, 0x15);
                    207:        return (20);
                    208: }
                    209:
                    210: void
                    211: lcg_attach(struct device *parent, struct device *self, void *aux)
                    212: {
                    213:        struct lcg_softc *sc = (struct lcg_softc *)self;
                    214:        struct lcg_screen *ss;
                    215:        struct wsemuldisplaydev_attach_args aa;
                    216:        vaddr_t tmp;
                    217:        u_int32_t cfg;
                    218:        int console;
                    219:        extern struct consdev wsdisplay_cons;
                    220:
                    221:        console = (vax_confdata & 0x100) == 0 && cn_tab == &wsdisplay_cons;
                    222:
                    223:        /*
                    224:         * Check for a recognized configuration register.
                    225:         * If we do not recognize it, print it and do not attach - so that
                    226:         * this gets noticed...
                    227:         */
                    228:        if (!console) {
                    229:                tmp = vax_map_physmem(LCG_CONFIG_ADDR, 1);
                    230:                if (tmp == NULL) {
                    231:                        printf("\n%s: can not map configuration register\n",
                    232:                            self->dv_xname);
                    233:                        return;
                    234:                }
                    235:                cfg = *(volatile u_int32_t *)tmp;
                    236:                vax_unmap_physmem(tmp, 1);
                    237:
                    238:                if (lcg_probe_screen(cfg, NULL, NULL) <= 0) {
                    239:                        printf("\n%s:"
                    240:                            " unrecognized configuration register %08x\n",
                    241:                            self->dv_xname, cfg);
                    242:                        return;
                    243:                }
                    244:        }
                    245:
                    246:        if (console) {
                    247:                ss = &lcg_consscr;
                    248:                sc->sc_nscreens = 1;
                    249:        } else {
                    250:                ss = malloc(sizeof(struct lcg_screen), M_DEVBUF, M_NOWAIT);
                    251:                if (ss == NULL) {
                    252:                        printf(": can not allocate memory\n");
                    253:                        return;
                    254:                }
                    255:                bzero(ss, sizeof(struct lcg_screen));
                    256:
                    257:                ss->ss_cfg = cfg;
                    258:                ss->ss_depth = lcg_probe_screen(ss->ss_cfg,
                    259:                    &ss->ss_width, &ss->ss_height);
                    260:                ss->ss_fbsize =
                    261:                    roundup(ss->ss_width * ss->ss_height, PAGE_SIZE);
                    262:
                    263:                ss->ss_addr = (caddr_t)vax_map_physmem(LCG_FB_ADDR,
                    264:                    ss->ss_fbsize / VAX_NBPG);
                    265:                if (ss->ss_addr == NULL) {
                    266:                        printf(": can not map frame buffer\n");
                    267:                        goto fail1;
                    268:                }
                    269:
                    270:                ss->ss_reg = vax_map_physmem(LCG_REG_ADDR,
                    271:                    LCG_REG_SIZE / VAX_NBPG);
                    272:                if (ss->ss_reg == 0L) {
                    273:                        printf(": can not map registers\n");
                    274:                        goto fail2;
                    275:                }
                    276:
                    277:                ss->ss_lut = (volatile u_int8_t *)vax_map_physmem(LCG_LUT_ADDR +
                    278:                    LCG_LUT_OFFSET, LCG_LUT_SIZE / VAX_NBPG);
                    279:                if (ss->ss_lut == NULL) {
                    280:                        printf(": can not map color LUT\n");
                    281:                        goto fail3;
                    282:                }
                    283:
                    284:                if (lcg_setup_screen(ss) != 0) {
                    285:                        printf(": initialization failed\n");
                    286:                        goto fail4;
                    287:                }
                    288:        }
                    289:        sc->sc_scr = ss;
                    290:
                    291:        printf(": %dx%dx%d frame buffer\n",
                    292:            ss->ss_width, ss->ss_height, ss->ss_depth);
                    293:
                    294:        aa.console = console;
                    295:        aa.scrdata = &lcg_screenlist;
                    296:        aa.accessops = &lcg_accessops;
                    297:        aa.accesscookie = sc;
                    298:        aa.defaultscreens = 0;
                    299:
                    300:        config_found(self, &aa, wsemuldisplaydevprint);
                    301:        return;
                    302:
                    303: fail4:
                    304:        vax_unmap_physmem((vaddr_t)ss->ss_lut, LCG_LUT_SIZE / VAX_NBPG);
                    305: fail3:
                    306:        vax_unmap_physmem(ss->ss_reg, LCG_REG_SIZE / VAX_NBPG);
                    307: fail2:
                    308:        vax_unmap_physmem((vaddr_t)ss->ss_addr, ss->ss_fbsize / VAX_NBPG);
                    309: fail1:
                    310:        free(ss, M_DEVBUF);
                    311: }
                    312:
                    313: /*
                    314:  * Determine if we have a recognized frame buffer, its resolution and
                    315:  * color depth.
                    316:  */
                    317: int
                    318: lcg_probe_screen(u_int32_t cfg, u_int *width, u_int *height)
                    319: {
                    320:        u_int w, h, d = 8;
                    321:
                    322:        switch (vax_boardtype) {
                    323:        case VAX_BTYP_46:
                    324:                switch (cfg & 0xf0) {
                    325:                case 0x00:
                    326:                        return (-1);    /* no hardware */
                    327:                case 0x20:
                    328:                case 0x60:
                    329:                        w = 1024; h = 864;
                    330:                        break;
                    331:                case 0x40:
                    332:                        w = 1024; h = 768;
                    333:                        break;
                    334:                case 0x80:
                    335:                        d = 4;
                    336:                        /* FALLTHROUGH */
                    337:                case 0x90:
                    338:                case 0xb0:
                    339:                        w = 1280; h = 1024;
                    340:                        break;
                    341:                default:
                    342:                        return (0);     /* unknown configuration, please help */
                    343:                }
                    344:                break;
                    345:        case VAX_BTYP_48:
                    346:                switch (cfg & 0x07) {
                    347:                case 0x00:
                    348:                        return (-1);    /* no hardware */
                    349:                case 0x05:
                    350:                        w = 1280; h = 1024;
                    351:                        break;
                    352:                case 0x06:
                    353:                        if (vax_confdata & 0x80) {
                    354:                                w = 1024; h = 768;
                    355:                        } else {
                    356:                                w = 640; h = 480;
                    357:                        }
                    358:                        break;
                    359:                case 0x07:
                    360:                        if (vax_confdata & 0x80) {
                    361:                                w = 1024; h = 864;
                    362:                        } else {
                    363:                                w = 1024; h = 768;
                    364:                        }
                    365:                        break;
                    366:                default:
                    367:                        return (0);     /* unknown configuration, please help */
                    368:                }
                    369:                break;
                    370:        }
                    371:
                    372:        if (width != NULL)
                    373:                *width = w;
                    374:        if (height != NULL)
                    375:                *height = h;
                    376:
                    377:        return (d);
                    378: }
                    379:
                    380: /*
                    381:  * Initialize anything necessary for an emulating wsdisplay to work (i.e.
                    382:  * pick a font, initialize a rasops structure, setup the accessops callbacks.)
                    383:  */
                    384: int
                    385: lcg_setup_screen(struct lcg_screen *ss)
                    386: {
                    387:        struct rasops_info *ri = &ss->ss_ri;
                    388:
                    389:        bzero(ri, sizeof(*ri));
                    390:        /*
                    391:         * Since the frame buffer memory is byte addressed, even in low-bpp
                    392:         * mode, initialize a 8bpp rasops engine. We will report a shorter
                    393:         * colormap if necessary, which will allow X to do TRT.
                    394:         */
                    395:        ri->ri_depth = 8;
                    396:        ri->ri_width = ss->ss_width;
                    397:        ri->ri_height = ss->ss_height;
                    398:        ri->ri_stride = ss->ss_width;
                    399:        ri->ri_flg = RI_CLEAR | RI_CENTER;
                    400:        ri->ri_bits = (void *)ss->ss_addr;
                    401:        ri->ri_hw = ss;
                    402:
                    403:        /*
                    404:         * Ask for an unholy big display, rasops will trim this to more
                    405:         * reasonable values.
                    406:         */
                    407:        if (rasops_init(ri, 160, 160) != 0)
                    408:                return (-1);
                    409:
                    410:        if (ss->ss_depth < 8) {
                    411:                ri->ri_ops.alloc_attr = lcg_alloc_attr;
                    412:                ri->ri_caps &= ~WSSCREEN_HILIT;
                    413:        }
                    414:
                    415:        lcg_stdscreen.ncols = ri->ri_cols;
                    416:        lcg_stdscreen.nrows = ri->ri_rows;
                    417:        lcg_stdscreen.textops = &ri->ri_ops;
                    418:        lcg_stdscreen.fontwidth = ri->ri_font->fontwidth;
                    419:        lcg_stdscreen.fontheight = ri->ri_font->fontheight;
                    420:        lcg_stdscreen.capabilities = ri->ri_caps;
                    421:
                    422:        lcg_resetcmap(ss);
                    423:
                    424:        return (0);
                    425: }
                    426:
                    427: int
                    428: lcg_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
                    429: {
                    430:        struct lcg_softc *sc = v;
                    431:        struct lcg_screen *ss = sc->sc_scr;
                    432:        struct wsdisplay_fbinfo *wdf;
                    433:        struct wsdisplay_cmap *cm;
                    434:        int error;
                    435:
                    436:        switch (cmd) {
                    437:        case WSDISPLAYIO_GTYPE:
                    438:                *(u_int *)data = WSDISPLAY_TYPE_LCG;
                    439:                break;
                    440:
                    441:        case WSDISPLAYIO_GINFO:
                    442:                wdf = (struct wsdisplay_fbinfo *)data;
                    443:                wdf->height = ss->ss_height;
                    444:                wdf->width = ss->ss_width;
                    445:                wdf->depth = 8;
                    446:                wdf->cmsize = 1 << ss->ss_depth;
                    447:                break;
                    448:
                    449:        case WSDISPLAYIO_LINEBYTES:
                    450:                *(u_int *)data = ss->ss_ri.ri_stride;
                    451:                break;
                    452:
                    453:        case WSDISPLAYIO_GETCMAP:
                    454:                cm = (struct wsdisplay_cmap *)data;
                    455:                error = lcg_getcmap(ss, cm);
                    456:                if (error != 0)
                    457:                        return (error);
                    458:                break;
                    459:        case WSDISPLAYIO_PUTCMAP:
                    460:                cm = (struct wsdisplay_cmap *)data;
                    461:                error = lcg_putcmap(ss, cm);
                    462:                if (error != 0)
                    463:                        return (error);
                    464:                lcg_loadcmap(ss, cm->index, cm->count);
                    465:                break;
                    466:
                    467:        case WSDISPLAYIO_GVIDEO:
                    468:        case WSDISPLAYIO_SVIDEO:
                    469:                break;
                    470:
                    471:        default:
                    472:                return (-1);
                    473:        }
                    474:
                    475:        return (0);
                    476: }
                    477:
                    478: paddr_t
                    479: lcg_mmap(void *v, off_t offset, int prot)
                    480: {
                    481:        struct lcg_softc *sc = v;
                    482:        struct lcg_screen *ss = sc->sc_scr;
                    483:
                    484:        if (offset >= ss->ss_fbsize || offset < 0)
                    485:                return (-1);
                    486:
                    487:        return (LCG_FB_ADDR + offset) >> PGSHIFT;
                    488: }
                    489:
                    490: int
                    491: lcg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
                    492:     int *curxp, int *curyp, long *defattrp)
                    493: {
                    494:        struct lcg_softc *sc = v;
                    495:        struct lcg_screen *ss = sc->sc_scr;
                    496:        struct rasops_info *ri = &ss->ss_ri;
                    497:
                    498:        if (sc->sc_nscreens > 0)
                    499:                return (ENOMEM);
                    500:
                    501:        *cookiep = ri;
                    502:        *curxp = *curyp = 0;
                    503:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, defattrp);
                    504:        sc->sc_nscreens++;
                    505:
                    506:        return (0);
                    507: }
                    508:
                    509: void
                    510: lcg_free_screen(void *v, void *cookie)
                    511: {
                    512:        struct lcg_softc *sc = v;
                    513:
                    514:        sc->sc_nscreens--;
                    515: }
                    516:
                    517: int
                    518: lcg_show_screen(void *v, void *cookie, int waitok,
                    519:     void (*cb)(void *, int, int), void *cbarg)
                    520: {
                    521:        return (0);
                    522: }
                    523:
                    524: void
                    525: lcg_burner(void *v, u_int on, u_int flags)
                    526: {
                    527:        struct lcg_softc *sc = v;
                    528:        struct lcg_screen *ss = sc->sc_scr;
                    529:        u_int32_t vidcfg;
                    530:
                    531:        vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG);
                    532:        if (on)
                    533:                vidcfg |= VIDEO_ENABLE_VIDEO | VIDEO_SYNC_ENABLE;
                    534:        else {
                    535:                vidcfg &= ~VIDEO_ENABLE_VIDEO;
                    536:                if (flags & WSDISPLAY_BURN_VBLANK)
                    537:                        vidcfg &= ~VIDEO_SYNC_ENABLE;
                    538:        }
                    539:        lcg_write_reg(ss, LCG_REG_VIDEO_CONFIG, vidcfg);
                    540: }
                    541:
                    542: /*
                    543:  * Attribute allocator for 4bpp frame buffers.
                    544:  * In such modes, highlighting is not available.
                    545:  */
                    546: int
                    547: lcg_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
                    548: {
                    549:        extern int rasops_alloc_cattr(void *, int, int, int, long *);
                    550:
                    551:        if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
                    552:                return (EINVAL);
                    553:
                    554:        return (rasops_alloc_cattr(cookie, fg, bg, flg, attr));
                    555: }
                    556:
                    557: /*
                    558:  * Colormap handling routines
                    559:  */
                    560:
                    561: int
                    562: lcg_getcmap(struct lcg_screen *ss, struct wsdisplay_cmap *cm)
                    563: {
                    564:        u_int index = cm->index, count = cm->count, i;
                    565:        u_int colcount = 1 << ss->ss_depth;
                    566:        int error;
                    567:        u_int8_t ramp[256], *c, *r;
                    568:
                    569:        if (index >= colcount || count > colcount - index)
                    570:                return (EINVAL);
                    571:
                    572:        /* extract reds */
                    573:        c = ss->ss_cmap + 0 + index * 3;
                    574:        for (i = count, r = ramp; i != 0; i--)
                    575:                *r++ = *c, c += 3;
                    576:        if ((error = copyout(ramp, cm->red, count)) != 0)
                    577:                return (error);
                    578:
                    579:        /* extract greens */
                    580:        c = ss->ss_cmap + 1 + index * 3;
                    581:        for (i = count, r = ramp; i != 0; i--)
                    582:                *r++ = *c, c += 3;
                    583:        if ((error = copyout(ramp, cm->green, count)) != 0)
                    584:                return (error);
                    585:
                    586:        /* extract blues */
                    587:        c = ss->ss_cmap + 2 + index * 3;
                    588:        for (i = count, r = ramp; i != 0; i--)
                    589:                *r++ = *c, c += 3;
                    590:        if ((error = copyout(ramp, cm->blue, count)) != 0)
                    591:                return (error);
                    592:
                    593:        return (0);
                    594: }
                    595:
                    596: int
                    597: lcg_putcmap(struct lcg_screen *ss, struct wsdisplay_cmap *cm)
                    598: {
                    599:        u_int index = cm->index, count = cm->count;
                    600:        u_int colcount = 1 << ss->ss_depth;
                    601:        int i, error;
                    602:        u_int8_t r[256], g[256], b[256], *nr, *ng, *nb, *c;
                    603:
                    604:        if (index >= colcount || count > colcount - index)
                    605:                return (EINVAL);
                    606:
                    607:        if ((error = copyin(cm->red, r, count)) != 0)
                    608:                return (error);
                    609:        if ((error = copyin(cm->green, g, count)) != 0)
                    610:                return (error);
                    611:        if ((error = copyin(cm->blue, b, count)) != 0)
                    612:                return (error);
                    613:
                    614:        nr = r, ng = g, nb = b;
                    615:        c = ss->ss_cmap + index * 3;
                    616:        for (i = count; i != 0; i--) {
                    617:                *c++ = *nr++;
                    618:                *c++ = *ng++;
                    619:                *c++ = *nb++;
                    620:        }
                    621:
                    622:        return (0);
                    623: }
                    624:
                    625: /* Fill the given colormap (LUT) entry.  */
                    626: #define lcg_set_lut_entry(lutptr, cmap, idx, shift)                    \
                    627: do {                                                                   \
                    628:        *(lutptr)++ = LUT_ADRS_REG;                                     \
                    629:        *(lutptr)++ = (idx);                                            \
                    630:        *(lutptr)++ = LUT_COLOR_AUTOINC;                                \
                    631:        *(lutptr)++ = (*(cmap)++) >> (shift);                           \
                    632:        *(lutptr)++ = LUT_COLOR_AUTOINC;                                \
                    633:        *(lutptr)++ = (*(cmap)++) >> (shift);                           \
                    634:        *(lutptr)++ = LUT_COLOR_AUTOINC;                                \
                    635:        *(lutptr)++ = (*(cmap)++) >> (shift);                           \
                    636: } while (0)
                    637:
                    638: void
                    639: lcg_loadcmap(struct lcg_screen *ss, int from, int count)
                    640: {
                    641:        const u_int8_t *cmap;
                    642:        u_int i;
                    643:        volatile u_int8_t *lutptr;
                    644:        u_int32_t vidcfg;
                    645:
                    646:        /* partial updates ignored for now */
                    647:        cmap = ss->ss_cmap;
                    648:        lutptr = ss->ss_lut;
                    649:        if (ss->ss_depth == 8) {
                    650:                for (i = 0; i < 256; i++) {
                    651:                        lcg_set_lut_entry(lutptr, cmap, i, 0);
                    652:                }
                    653:        } else {
                    654:                for (i = 0; i < 16; i++) {
                    655:                        lcg_set_lut_entry(lutptr, cmap, i, 4);
                    656:                }
                    657:        }
                    658:
                    659:        /*
                    660:         * Wait for retrace
                    661:         */
                    662:        while (((vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG)) &
                    663:            VIDEO_VSTATE) != VIDEO_VSYNC)
                    664:                DELAY(1);
                    665:
                    666:        vidcfg &= ~(VIDEO_SHIFT_SEL | VIDEO_MEM_REFRESH_SEL_MASK |
                    667:            VIDEO_LUT_SHIFT_SEL);
                    668:        /* Do full loads if width is 1024 or 2048, split loads otherwise. */
                    669:        if (ss->ss_width == 1024 || ss->ss_width == 2048)
                    670:                vidcfg |= VIDEO_SHIFT_SEL | (1 << VIDEO_MEM_REFRESH_SEL_SHIFT) |
                    671:                    VIDEO_LUT_SHIFT_SEL;
                    672:        else
                    673:                vidcfg |= (2 << VIDEO_MEM_REFRESH_SEL_SHIFT);
                    674:        vidcfg |= VIDEO_LUT_LOAD_SIZE;  /* 2KB lut */
                    675:        lcg_write_reg(ss, LCG_REG_VIDEO_CONFIG, vidcfg);
                    676:        lcg_write_reg(ss, LCG_REG_LUT_CONSOLE_SEL, LUT_SEL_COLOR);
                    677:        lcg_write_reg(ss, LCG_REG_LUT_COLOR_BASE_W, LCG_LUT_OFFSET);
                    678:        /* Wait for end of retrace */
                    679:        while (((vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG)) &
                    680:            VIDEO_VSTATE) == VIDEO_VSYNC)
                    681:                DELAY(1);
                    682:        lcg_write_reg(ss, LCG_REG_LUT_CONSOLE_SEL, LUT_SEL_CONSOLE);
                    683: }
                    684:
                    685: void
                    686: lcg_resetcmap(struct lcg_screen *ss)
                    687: {
                    688:        if (ss->ss_depth == 8)
                    689:                bcopy(rasops_cmap, ss->ss_cmap, sizeof(ss->ss_cmap));
                    690:        else {
                    691:                bcopy(rasops_cmap, ss->ss_cmap, 8 * 3);
                    692:                bcopy(rasops_cmap + 0xf8 * 3, ss->ss_cmap + 8 * 3, 8 * 3);
                    693:        }
                    694:        lcg_loadcmap(ss, 0, 1 << ss->ss_depth);
                    695: }
                    696:
                    697: /*
                    698:  * Console support code
                    699:  */
                    700:
                    701: int    lcgcnprobe(void);
                    702: void   lcgcninit(void);
                    703:
                    704: int
                    705: lcgcnprobe()
                    706: {
                    707:        extern vaddr_t virtual_avail;
                    708:        u_int32_t cfg;
                    709:        vaddr_t tmp;
                    710:        volatile u_int8_t *ch;
                    711:
                    712:        switch (vax_boardtype) {
                    713:        case VAX_BTYP_46:
                    714:        case VAX_BTYP_48:
                    715:                if ((vax_confdata & 0x100) != 0)
                    716:                        break; /* doesn't use graphics console */
                    717:
                    718:                tmp = virtual_avail;
                    719:                ioaccess(tmp, vax_trunc_page(LCG_CONFIG_ADDR), 1);
                    720:                cfg = *(volatile u_int32_t *)
                    721:                    (tmp + (LCG_CONFIG_ADDR & VAX_PGOFSET));
                    722:
                    723:                if (lcg_probe_screen(cfg, NULL, NULL) <= 0)
                    724:                        break;  /* unsupported configuration */
                    725:
                    726:                /*
                    727:                 * Check for video memory.
                    728:                 * We can not use badaddr() on these models.
                    729:                 */
                    730:                ioaccess(tmp, LCG_FB_ADDR, 1);
                    731:                ch = (volatile u_int8_t *)tmp;
                    732:                *ch = 0x01;
                    733:                if ((*ch & 0x01) == 0)
                    734:                        break;
                    735:                *ch = 0x00;
                    736:                if ((*ch & 0x01) != 0)
                    737:                        break;
                    738:
                    739:                return (1);
                    740:
                    741:        default:
                    742:                break;
                    743:        }
                    744:
                    745:        return (0);
                    746: }
                    747:
                    748: /*
                    749:  * Called very early to setup the glass tty as console.
                    750:  * Because it's called before the VM system is initialized, virtual memory
                    751:  * for the framebuffer can be stolen directly without disturbing anything.
                    752:  */
                    753: void
                    754: lcgcninit()
                    755: {
                    756:        struct lcg_screen *ss = &lcg_consscr;
                    757:        extern vaddr_t virtual_avail;
                    758:        vaddr_t tmp;
                    759:        long defattr;
                    760:        struct rasops_info *ri;
                    761:
                    762:        tmp = virtual_avail;
                    763:        ioaccess(tmp, vax_trunc_page(LCG_CONFIG_ADDR), 1);
                    764:        ss->ss_cfg = *(volatile u_int32_t *)
                    765:            (tmp + (LCG_CONFIG_ADDR & VAX_PGOFSET));
                    766:
                    767:        ss->ss_depth = lcg_probe_screen(ss->ss_cfg,
                    768:            &ss->ss_width, &ss->ss_height);
                    769:
                    770:        ss->ss_fbsize = roundup(ss->ss_width * ss->ss_height, PAGE_SIZE);
                    771:
                    772:        ss->ss_addr = (caddr_t)virtual_avail;
                    773:        virtual_avail += ss->ss_fbsize;
                    774:        ioaccess((vaddr_t)ss->ss_addr, LCG_FB_ADDR, ss->ss_fbsize / VAX_NBPG);
                    775:
                    776:        ss->ss_reg = virtual_avail;
                    777:        virtual_avail += LCG_REG_SIZE;
                    778:        ioaccess(ss->ss_reg, LCG_REG_ADDR, LCG_REG_SIZE / VAX_NBPG);
                    779:
                    780:        ss->ss_lut = (volatile u_int8_t *)virtual_avail;
                    781:        virtual_avail += LCG_LUT_SIZE;
                    782:        ioaccess((vaddr_t)ss->ss_lut, LCG_LUT_ADDR + LCG_LUT_OFFSET,
                    783:            LCG_LUT_SIZE / VAX_NBPG);
                    784:
                    785:        virtual_avail = round_page(virtual_avail);
                    786:
                    787:        /* this had better not fail as we can't recover there */
                    788:        if (lcg_setup_screen(ss) != 0)
                    789:                panic(__func__);
                    790:
                    791:        ri = &ss->ss_ri;
                    792:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
                    793:        wsdisplay_cnattach(&lcg_stdscreen, ri, 0, 0, defattr);
                    794: }

CVSweb