[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     ! 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