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

Annotation of sys/arch/vax/vsa/gpx.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: gpx.c,v 1.16 2006/11/29 19:08:22 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) 1988 Regents of the University of California.
        !            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. Neither the name of the University nor the names of its contributors
        !            31:  *    may be used to endorse or promote products derived from this software
        !            32:  *    without specific prior written permission.
        !            33:  *
        !            34:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            35:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            36:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            37:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            38:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            39:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            40:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            41:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            42:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            43:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            44:  * SUCH DAMAGE.
        !            45:  *
        !            46:  *     @(#)qd.c        7.1 (Berkeley) 6/28/91
        !            47:  */
        !            48:
        !            49: /************************************************************************
        !            50: *                                                                      *
        !            51: *                      Copyright (c) 1985-1988 by                      *
        !            52: *              Digital Equipment Corporation, Maynard, MA              *
        !            53: *                      All rights reserved.                            *
        !            54: *                                                                      *
        !            55: *   This software is furnished under a license and may be used and     *
        !            56: *   copied  only  in accordance with the terms of such license and     *
        !            57: *   with the  inclusion  of  the  above  copyright  notice.   This     *
        !            58: *   software  or  any  other copies thereof may not be provided or     *
        !            59: *   otherwise made available to any other person.  No title to and     *
        !            60: *   ownership of the software is hereby transferred.                   *
        !            61: *                                                                      *
        !            62: *   The information in this software is subject to change  without     *
        !            63: *   notice  and should not be construed as a commitment by Digital     *
        !            64: *   Equipment Corporation.                                             *
        !            65: *                                                                      *
        !            66: *   Digital assumes no responsibility for the use  or  reliability     *
        !            67: *   of its software on equipment which is not supplied by Digital.     *
        !            68: *                                                                      *
        !            69: *************************************************************************/
        !            70:
        !            71: /*
        !            72:  * Driver for the GPX color option on VAXstation 3100, based on the
        !            73:  * MicroVAX II qdss driver.
        !            74:  *
        !            75:  * The frame buffer memory itself is not directly accessible (unlike
        !            76:  * the on-board monochrome smg frame buffer), and writes through the
        !            77:  * Dragon chip can only happen in multiples of 16 pixels, horizontally.
        !            78:  *
        !            79:  * Because of this limitation, the font image is copied to offscreen
        !            80:  * memory (which there is plenty of), and screen to screen blt operations
        !            81:  * are done for everything.
        !            82:  */
        !            83:
        !            84: #include <sys/param.h>
        !            85: #include <sys/device.h>
        !            86: #include <sys/systm.h>
        !            87: #include <sys/malloc.h>
        !            88: #include <sys/conf.h>
        !            89: #include <sys/kernel.h>
        !            90:
        !            91: #include <machine/sid.h>
        !            92: #include <machine/cpu.h>
        !            93: #include <machine/ka420.h>
        !            94: #include <machine/scb.h>
        !            95: #include <machine/vsbus.h>
        !            96:
        !            97: #include <uvm/uvm_extern.h>
        !            98:
        !            99: #include <dev/cons.h>
        !           100:
        !           101: #include <dev/wscons/wsconsio.h>
        !           102: #include <dev/wscons/wsdisplayvar.h>
        !           103: #include <dev/rasops/rasops.h>
        !           104: #include <dev/wsfont/wsfont.h>
        !           105:
        !           106: #include <dev/ic/bt458reg.h>
        !           107: #if 0
        !           108: #include <dev/ic/dc503reg.h>
        !           109: #endif
        !           110: #include <vax/qbus/qdreg.h>
        !           111:
        !           112: #define        GPXADDR         0x3c000000      /* base address on VAXstation 3100 */
        !           113:
        !           114: #define        GPX_ADDER_OFFSET        0x0000
        !           115: #define        GPX_VDAC_OFFSET         0x0300
        !           116: #define        GPX_CURSOR_OFFSET       0x0400  /* DC503 */
        !           117: #define        GPX_READBACK_OFFSET     0x0500
        !           118:
        !           119: #define        GPX_WIDTH       1024
        !           120: #define        GPX_VISHEIGHT   864
        !           121: #define        GPX_HEIGHT      2048
        !           122:
        !           123: /* 4 plane option RAMDAC */
        !           124: struct ramdac4 {
        !           125:        u_int16_t       colormap[16];
        !           126:        u_int8_t        unknown[0x20];
        !           127:        u_int16_t       cursormap[4];
        !           128:        u_int8_t        unknown2[0x18];
        !           129:        u_int16_t       control;
        !           130: #define        RAMDAC4_INIT    0x0047
        !           131: #define        RAMDAC4_ENABLE  0x0002
        !           132: };
        !           133:
        !           134: /* 8 plane option RAMDAC - Bt458 or compatible */
        !           135: struct ramdac8 {
        !           136:        u_int16_t       address;
        !           137:        u_int16_t       cmapdata;
        !           138:        u_int16_t       control;
        !           139:        u_int16_t       omapdata;
        !           140: };
        !           141:
        !           142: int    gpx_match(struct device *, void *, void *);
        !           143: void   gpx_attach(struct device *, struct device *, void *);
        !           144:
        !           145: struct gpx_screen {
        !           146:        struct rasops_info ss_ri;
        !           147:        int             ss_console;
        !           148:        u_int           ss_depth;
        !           149:        u_int           ss_gpr;         /* font glyphs per row */
        !           150:        struct adder    *ss_adder;
        !           151:        void            *ss_vdac;
        !           152:        u_int8_t        ss_cmap[256 * 3];
        !           153: #if 0
        !           154:        struct dc503reg *ss_cursor;
        !           155:        u_int16_t       ss_curcmd;
        !           156: #endif
        !           157: };
        !           158:
        !           159: /* for console */
        !           160: struct gpx_screen gpx_consscr;
        !           161:
        !           162: struct gpx_softc {
        !           163:        struct device sc_dev;
        !           164:        struct gpx_screen *sc_scr;
        !           165:        int     sc_nscreens;
        !           166: };
        !           167:
        !           168: struct cfattach gpx_ca = {
        !           169:        sizeof(struct gpx_softc), gpx_match, gpx_attach,
        !           170: };
        !           171:
        !           172: struct cfdriver gpx_cd = {
        !           173:        NULL, "gpx", DV_DULL
        !           174: };
        !           175:
        !           176: struct wsscreen_descr gpx_stdscreen = {
        !           177:        "std",
        !           178: };
        !           179:
        !           180: const struct wsscreen_descr *_gpx_scrlist[] = {
        !           181:        &gpx_stdscreen,
        !           182: };
        !           183:
        !           184: const struct wsscreen_list gpx_screenlist = {
        !           185:        sizeof(_gpx_scrlist) / sizeof(struct wsscreen_descr *),
        !           186:        _gpx_scrlist,
        !           187: };
        !           188:
        !           189: int    gpx_ioctl(void *, u_long, caddr_t, int, struct proc *);
        !           190: paddr_t        gpx_mmap(void *, off_t, int);
        !           191: int    gpx_alloc_screen(void *, const struct wsscreen_descr *,
        !           192:            void **, int *, int *, long *);
        !           193: void   gpx_free_screen(void *, void *);
        !           194: int    gpx_show_screen(void *, void *, int,
        !           195:            void (*) (void *, int, int), void *);
        !           196: void   gpx_burner(void *, u_int, u_int);
        !           197:
        !           198: const struct wsdisplay_accessops gpx_accessops = {
        !           199:        gpx_ioctl,
        !           200:        gpx_mmap,
        !           201:        gpx_alloc_screen,
        !           202:        gpx_free_screen,
        !           203:        gpx_show_screen,
        !           204:        NULL,   /* load_font */
        !           205:        NULL,   /* scrollback */
        !           206:        NULL,   /* getchar */
        !           207:        gpx_burner
        !           208: };
        !           209:
        !           210: void   gpx_clear_screen(struct gpx_screen *);
        !           211: void   gpx_copyrect(struct gpx_screen *, int, int, int, int, int, int);
        !           212: void   gpx_fillrect(struct gpx_screen *, int, int, int, int, long, u_int);
        !           213: int    gpx_getcmap(struct gpx_screen *, struct wsdisplay_cmap *);
        !           214: void   gpx_loadcmap(struct gpx_screen *, int, int);
        !           215: int    gpx_putcmap(struct gpx_screen *, struct wsdisplay_cmap *);
        !           216: void   gpx_resetcmap(struct gpx_screen *);
        !           217: void   gpx_reset_viper(struct gpx_screen *);
        !           218: int    gpx_setup_screen(struct gpx_screen *);
        !           219: void   gpx_upload_font(struct gpx_screen *);
        !           220: int    gpx_viper_write(struct gpx_screen *, u_int, u_int16_t);
        !           221: int    gpx_wait(struct gpx_screen *, int);
        !           222:
        !           223: void   gpx_copycols(void *, int, int, int, int);
        !           224: void   gpx_copyrows(void *, int, int, int);
        !           225: void   gpx_do_cursor(struct rasops_info *);
        !           226: void   gpx_erasecols(void *, int, int, int, long);
        !           227: void   gpx_eraserows(void *, int, int, long);
        !           228: void   gpx_putchar(void *, int, int, u_int, long);
        !           229:
        !           230: /*
        !           231:  * Autoconf glue
        !           232:  */
        !           233:
        !           234: int
        !           235: gpx_match(struct device *parent, void *vcf, void *aux)
        !           236: {
        !           237:        struct vsbus_attach_args *va = aux;
        !           238:        struct adder *adder;
        !           239:        vaddr_t tmp;
        !           240:        u_int depth;
        !           241:        extern struct consdev wsdisplay_cons;
        !           242:        extern int oldvsbus;
        !           243:
        !           244:        switch (vax_boardtype) {
        !           245:        default:
        !           246:                return (0);
        !           247:
        !           248:        case VAX_BTYP_410:
        !           249:        case VAX_BTYP_420:
        !           250:        case VAX_BTYP_43:
        !           251:                if (va->va_paddr != GPXADDR)
        !           252:                        return (0);
        !           253:
        !           254:                /* not present on microvaxes */
        !           255:                if ((vax_confdata & KA420_CFG_MULTU) != 0)
        !           256:                        return (0);
        !           257:
        !           258:                if ((vax_confdata & KA420_CFG_VIDOPT) == 0)
        !           259:                        return (0);
        !           260:                break;
        !           261:        }
        !           262:
        !           263:        /* Check for a recognized color depth */
        !           264:        tmp = vax_map_physmem(va->va_paddr + GPX_READBACK_OFFSET, 1);
        !           265:        if (tmp == 0L)
        !           266:                return (0);
        !           267:        depth = (*(u_int16_t *)tmp) & 0x00f0;
        !           268:        vax_unmap_physmem(tmp, 1);
        !           269:        if (depth != 0x00f0 && depth != 0x0080)
        !           270:                return (0);
        !           271:
        !           272:        /* when already running as console, always fake things */
        !           273:        if ((vax_confdata & KA420_CFG_L3CON) == 0 &&
        !           274:            cn_tab == &wsdisplay_cons) {
        !           275:                struct vsbus_softc *sc = (void *)parent;
        !           276:                sc->sc_mask = 0x08;
        !           277:                scb_fake(0x44, oldvsbus ? 0x14 : 0x15);
        !           278:        } else {
        !           279:                adder = (struct adder *)vax_map_physmem(va->va_paddr +
        !           280:                    GPX_ADDER_OFFSET, 1);
        !           281:                if (adder == NULL)
        !           282:                        return (0);
        !           283:                adder->interrupt_enable = FRAME_SYNC;
        !           284:                DELAY(100000);  /* enough to get a retrace interrupt */
        !           285:                adder->interrupt_enable = 0;
        !           286:                vax_unmap_physmem((vaddr_t)adder, 1);
        !           287:        }
        !           288:        return (20);
        !           289: }
        !           290:
        !           291: void
        !           292: gpx_attach(struct device *parent, struct device *self, void *aux)
        !           293: {
        !           294:        struct gpx_softc *sc = (struct gpx_softc *)self;
        !           295:        struct vsbus_attach_args *va = aux;
        !           296:        struct gpx_screen *scr;
        !           297:        struct wsemuldisplaydev_attach_args aa;
        !           298:        int console;
        !           299:        vaddr_t tmp;
        !           300:        extern struct consdev wsdisplay_cons;
        !           301:
        !           302:        console = (vax_confdata & KA420_CFG_L3CON) == 0 &&
        !           303:            cn_tab == &wsdisplay_cons;
        !           304:        if (console) {
        !           305:                scr = &gpx_consscr;
        !           306:                sc->sc_nscreens = 1;
        !           307:        } else {
        !           308:                scr = malloc(sizeof(struct gpx_screen), M_DEVBUF, M_NOWAIT);
        !           309:                if (scr == NULL) {
        !           310:                        printf(": can not allocate memory\n");
        !           311:                        return;
        !           312:                }
        !           313:
        !           314:                tmp = vax_map_physmem(va->va_paddr + GPX_READBACK_OFFSET, 1);
        !           315:                if (tmp == 0L) {
        !           316:                        printf(": can not probe depth\n");
        !           317:                        goto bad1;
        !           318:                }
        !           319:                scr->ss_depth = (*(u_int16_t *)tmp & 0x00f0) == 0x00f0 ? 4 : 8;
        !           320:                vax_unmap_physmem(tmp, 1);
        !           321:
        !           322:                scr->ss_adder = (struct adder *)vax_map_physmem(va->va_paddr +
        !           323:                    GPX_ADDER_OFFSET, 1);
        !           324:                if (scr->ss_adder == NULL) {
        !           325:                        printf(": can not map frame buffer registers\n");
        !           326:                        goto bad1;
        !           327:                }
        !           328:
        !           329:                scr->ss_vdac = (void *)vax_map_physmem(va->va_paddr +
        !           330:                    GPX_VDAC_OFFSET, 1);
        !           331:                if (scr->ss_vdac == NULL) {
        !           332:                        printf(": can not map RAMDAC\n");
        !           333:                        goto bad2;
        !           334:                }
        !           335:
        !           336: #if 0
        !           337:                scr->ss_cursor =
        !           338:                    (struct dc503reg *)vax_map_physmem(va->va_paddr +
        !           339:                    GPX_CURSOR_OFFSET, 1);
        !           340:                if (scr->ss_cursor == NULL) {
        !           341:                        printf(": can not map cursor chip\n");
        !           342:                        goto bad3;
        !           343:                }
        !           344: #endif
        !           345:
        !           346:                if (gpx_setup_screen(scr) != 0) {
        !           347:                        printf(": initialization failed\n");
        !           348:                        goto bad4;
        !           349:                }
        !           350:        }
        !           351:        sc->sc_scr = scr;
        !           352:
        !           353:        printf("\n%s: %dx%d %d plane color framebuffer\n",
        !           354:            self->dv_xname, GPX_WIDTH, GPX_VISHEIGHT, scr->ss_depth);
        !           355:
        !           356:        aa.console = console;
        !           357:        aa.scrdata = &gpx_screenlist;
        !           358:        aa.accessops = &gpx_accessops;
        !           359:        aa.accesscookie = sc;
        !           360:        aa.defaultscreens = 0;
        !           361:
        !           362:        config_found(self, &aa, wsemuldisplaydevprint);
        !           363:
        !           364:        return;
        !           365:
        !           366: bad4:
        !           367: #if 0
        !           368:        vax_unmap_physmem((vaddr_t)scr->ss_cursor, 1);
        !           369: bad3:
        !           370: #endif
        !           371:        vax_unmap_physmem((vaddr_t)scr->ss_vdac, 1);
        !           372: bad2:
        !           373:        vax_unmap_physmem((vaddr_t)scr->ss_adder, 1);
        !           374: bad1:
        !           375:        free(scr, M_DEVBUF);
        !           376: }
        !           377:
        !           378: /*
        !           379:  * wsdisplay accessops
        !           380:  */
        !           381:
        !           382: int
        !           383: gpx_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           384: {
        !           385:        struct gpx_softc *sc = v;
        !           386:        struct gpx_screen *ss = sc->sc_scr;
        !           387:        struct wsdisplay_fbinfo *wdf;
        !           388:        struct wsdisplay_cmap *cm;
        !           389:        int error;
        !           390:
        !           391:        switch (cmd) {
        !           392:        case WSDISPLAYIO_GTYPE:
        !           393:                *(u_int *)data = WSDISPLAY_TYPE_GPX;
        !           394:                break;
        !           395:
        !           396:        case WSDISPLAYIO_GINFO:
        !           397:                wdf = (struct wsdisplay_fbinfo *)data;
        !           398:                wdf->height = ss->ss_ri.ri_height;
        !           399:                wdf->width = ss->ss_ri.ri_width;
        !           400:                wdf->depth = ss->ss_depth;
        !           401:                wdf->cmsize = 1 << ss->ss_depth;
        !           402:                break;
        !           403:
        !           404:        case WSDISPLAYIO_GETCMAP:
        !           405:                cm = (struct wsdisplay_cmap *)data;
        !           406:                error = gpx_getcmap(ss, cm);
        !           407:                if (error != 0)
        !           408:                        return (error);
        !           409:                break;
        !           410:        case WSDISPLAYIO_PUTCMAP:
        !           411:                cm = (struct wsdisplay_cmap *)data;
        !           412:                error = gpx_putcmap(ss, cm);
        !           413:                if (error != 0)
        !           414:                        return (error);
        !           415:                gpx_loadcmap(ss, cm->index, cm->count);
        !           416:                break;
        !           417:
        !           418:        case WSDISPLAYIO_GVIDEO:
        !           419:        case WSDISPLAYIO_SVIDEO:
        !           420:                break;
        !           421:
        !           422:        case WSDISPLAYIO_LINEBYTES:     /* no linear mapping */
        !           423:        default:
        !           424:                return (-1);
        !           425:        }
        !           426:
        !           427:        return (0);
        !           428: }
        !           429:
        !           430: paddr_t
        !           431: gpx_mmap(void *v, off_t offset, int prot)
        !           432: {
        !           433:        return (-1);
        !           434: }
        !           435:
        !           436: int
        !           437: gpx_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
        !           438:     int *curxp, int *curyp, long *defattrp)
        !           439: {
        !           440:        struct gpx_softc *sc = v;
        !           441:        struct gpx_screen *ss = sc->sc_scr;
        !           442:        struct rasops_info *ri = &ss->ss_ri;
        !           443:
        !           444:        if (sc->sc_nscreens > 0)
        !           445:                return (ENOMEM);
        !           446:
        !           447:        *cookiep = ri;
        !           448:        *curxp = *curyp = 0;
        !           449:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, defattrp);
        !           450:        sc->sc_nscreens++;
        !           451:
        !           452:        return (0);
        !           453: }
        !           454:
        !           455: void
        !           456: gpx_free_screen(void *v, void *cookie)
        !           457: {
        !           458:        struct gpx_softc *sc = v;
        !           459:
        !           460:        sc->sc_nscreens--;
        !           461: }
        !           462:
        !           463: int
        !           464: gpx_show_screen(void *v, void *cookie, int waitok,
        !           465:     void (*cb)(void *, int, int), void *cbarg)
        !           466: {
        !           467:        return (0);
        !           468: }
        !           469:
        !           470: void
        !           471: gpx_burner(void *v, u_int on, u_int flags)
        !           472: {
        !           473:        struct gpx_softc *sc = v;
        !           474:        struct gpx_screen *ss = sc->sc_scr;
        !           475:
        !           476:        if (ss->ss_depth == 8) {
        !           477:                struct ramdac8 *rd = ss->ss_vdac;
        !           478:                rd->address = BT_CR;
        !           479:                if (on)
        !           480:                        rd->control = BTCR_RAMENA | BTCR_BLINK_1648 |
        !           481:                            BTCR_MPLX_4;
        !           482:                else
        !           483:                        /* fade colormap to black as well? */
        !           484:                        rd->control = BTCR_BLINK_1648 | BTCR_MPLX_4;
        !           485:        } else {
        !           486:                struct ramdac4 *rd = ss->ss_vdac;
        !           487:                if (on)
        !           488:                        rd->control = RAMDAC4_INIT;
        !           489:                else
        !           490:                        rd->control = RAMDAC4_INIT & ~RAMDAC4_ENABLE;
        !           491:        }
        !           492: }
        !           493:
        !           494: /*
        !           495:  * wsdisplay emulops
        !           496:  */
        !           497:
        !           498: void
        !           499: gpx_putchar(void *v, int row, int col, u_int uc, long attr)
        !           500: {
        !           501:        struct rasops_info *ri = v;
        !           502:        struct gpx_screen *ss = ri->ri_hw;
        !           503:        struct wsdisplay_font *font = ri->ri_font;
        !           504:        int dx, dy, sx, sy, fg, bg, ul;
        !           505:
        !           506:        ri->ri_ops.unpack_attr(v, attr, &fg, &bg, &ul);
        !           507:
        !           508:        /* find where to output the glyph... */
        !           509:        dx = col * font->fontwidth + ri->ri_xorigin;
        !           510:        dy = row * font->fontheight + ri->ri_yorigin;
        !           511:        /* ... and where to pick it from */
        !           512:        uc -= font->firstchar;
        !           513:        sx = (uc % ss->ss_gpr) * font->stride * NBBY;
        !           514:        sy = GPX_HEIGHT - (1 + uc / ss->ss_gpr) * font->fontheight;
        !           515:
        !           516:        /* setup VIPER operand control registers */
        !           517:        while (gpx_viper_write(ss, CS_UPDATE_MASK, 0x00ff));
        !           518:        gpx_viper_write(ss, SRC1_OCR_B,
        !           519:            EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
        !           520:        gpx_viper_write(ss, DST_OCR_B,
        !           521:            EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
        !           522:        gpx_viper_write(ss, MASK_1, 0xffff);
        !           523:        gpx_viper_write(ss, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, fg);
        !           524:        gpx_viper_write(ss, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, bg);
        !           525:        ss->ss_adder->x_clip_min = 0;
        !           526:        ss->ss_adder->x_clip_max = GPX_WIDTH;
        !           527:        ss->ss_adder->y_clip_min = 0;
        !           528:        ss->ss_adder->y_clip_max = GPX_VISHEIGHT;
        !           529:        /* load DESTINATION origin and vectors */
        !           530:        ss->ss_adder->fast_dest_dy = 0;
        !           531:        ss->ss_adder->slow_dest_dx = 0;
        !           532:        ss->ss_adder->error_1 = 0;
        !           533:        ss->ss_adder->error_2 = 0;
        !           534:        ss->ss_adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
        !           535:        gpx_wait(ss, RASTEROP_COMPLETE);
        !           536:        ss->ss_adder->destination_x = dx;
        !           537:        ss->ss_adder->fast_dest_dx = font->fontwidth;
        !           538:        ss->ss_adder->destination_y = dy;
        !           539:        ss->ss_adder->slow_dest_dy = font->fontheight;
        !           540:        /* load SOURCE origin and vectors */
        !           541:        ss->ss_adder->source_1_x = sx;
        !           542:        ss->ss_adder->source_1_y = sy;
        !           543:        ss->ss_adder->source_1_dx = font->fontwidth;
        !           544:        ss->ss_adder->source_1_dy = font->fontheight;
        !           545:        ss->ss_adder->cmd = RASTEROP | OCRB | S1E | DTE | LF_R1;
        !           546:
        !           547:        if (ul != 0) {
        !           548:                gpx_fillrect(ss, dx, dy + font->fontheight - 2, font->fontwidth,
        !           549:                    1, attr, LF_R3);    /* fg fill */
        !           550:        }
        !           551: }
        !           552:
        !           553: void
        !           554: gpx_copycols(void *v, int row, int src, int dst, int cnt)
        !           555: {
        !           556:        struct rasops_info *ri = v;
        !           557:        struct gpx_screen *ss = ri->ri_hw;
        !           558:        struct wsdisplay_font *font = ri->ri_font;
        !           559:        int sx, y, dx, w, h;
        !           560:
        !           561:        sx = ri->ri_xorigin + src * font->fontwidth;
        !           562:        dx = ri->ri_xorigin + dst * font->fontwidth;
        !           563:        w = cnt * font->fontwidth;
        !           564:        y = ri->ri_yorigin + row * font->fontheight;
        !           565:        h = font->fontheight;
        !           566:
        !           567:        gpx_copyrect(ss, sx, y, dx, y, w, h);
        !           568: }
        !           569:
        !           570: void
        !           571: gpx_erasecols(void *v, int row, int col, int cnt, long attr)
        !           572: {
        !           573:        struct rasops_info *ri = v;
        !           574:        struct gpx_screen *ss = ri->ri_hw;
        !           575:        struct wsdisplay_font *font = ri->ri_font;
        !           576:        int x, y, dx, dy;
        !           577:
        !           578:        x = ri->ri_xorigin + col * font->fontwidth;
        !           579:        dx = cnt * font->fontwidth;
        !           580:        y = ri->ri_yorigin + row * font->fontheight;
        !           581:        dy = font->fontheight;
        !           582:
        !           583:        gpx_fillrect(ss, x, y, dx, dy, attr, LF_R2); /* bg fill */
        !           584: }
        !           585:
        !           586: void
        !           587: gpx_copyrows(void *v, int src, int dst, int cnt)
        !           588: {
        !           589:        struct rasops_info *ri = v;
        !           590:        struct gpx_screen *ss = ri->ri_hw;
        !           591:        struct wsdisplay_font *font = ri->ri_font;
        !           592:        int x, sy, dy, w, h;
        !           593:
        !           594:        x = ri->ri_xorigin;
        !           595:        w = ri->ri_emustride;
        !           596:        sy = ri->ri_yorigin + src * font->fontheight;
        !           597:        dy = ri->ri_yorigin + dst * font->fontheight;
        !           598:        h = cnt * font->fontheight;
        !           599:
        !           600:        gpx_copyrect(ss, x, sy, x, dy, w, h);
        !           601: }
        !           602:
        !           603: void
        !           604: gpx_eraserows(void *v, int row, int cnt, long attr)
        !           605: {
        !           606:        struct rasops_info *ri = v;
        !           607:        struct gpx_screen *ss = ri->ri_hw;
        !           608:        struct wsdisplay_font *font = ri->ri_font;
        !           609:        int x, y, dx, dy;
        !           610:
        !           611:        x = ri->ri_xorigin;
        !           612:        dx = ri->ri_emustride;
        !           613:        y = ri->ri_yorigin + row * font->fontheight;
        !           614:        dy = cnt * font->fontheight;
        !           615:
        !           616:        gpx_fillrect(ss, x, y, dx, dy, attr, LF_R2); /* bg fill */
        !           617: }
        !           618:
        !           619: void
        !           620: gpx_do_cursor(struct rasops_info *ri)
        !           621: {
        !           622:        struct gpx_screen *ss = ri->ri_hw;
        !           623:        int x, y, w, h;
        !           624:
        !           625:        x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
        !           626:        y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
        !           627:        w = ri->ri_font->fontwidth;
        !           628:        h = ri->ri_font->fontheight;
        !           629:
        !           630:        gpx_fillrect(ss, x, y, w, h, WSCOL_WHITE << 24, LF_R4); /* invert */
        !           631: }
        !           632:
        !           633: /*
        !           634:  * low-level programming routines
        !           635:  */
        !           636:
        !           637: int
        !           638: gpx_wait(struct gpx_screen *ss, int bits)
        !           639: {
        !           640:        int i;
        !           641:
        !           642:        ss->ss_adder->status = 0;
        !           643:        for (i = 100000; i != 0; i--) {
        !           644:                if ((ss->ss_adder->status & bits) == bits)
        !           645:                        break;
        !           646:                DELAY(1);
        !           647:        }
        !           648:
        !           649:        return (i == 0);
        !           650: }
        !           651:
        !           652: int
        !           653: gpx_viper_write(struct gpx_screen *ss, u_int reg, u_int16_t val)
        !           654: {
        !           655:        if (gpx_wait(ss, ADDRESS_COMPLETE) == 0 &&
        !           656:            gpx_wait(ss, TX_READY) == 0) {
        !           657:                ss->ss_adder->id_data = val;
        !           658:                ss->ss_adder->command = ID_LOAD | reg;
        !           659:                return (0);
        !           660:        }
        !           661: #ifdef DEBUG
        !           662:        if (ss->ss_console == 0)        /* don't make things worse! */
        !           663:                printf("gpx_viper_write failure, reg %x val %x\n", reg, val);
        !           664: #endif
        !           665:        return (1);
        !           666: }
        !           667:
        !           668: /* Initialize the damned beast. Straight from qdss. */
        !           669: void
        !           670: gpx_reset_viper(struct gpx_screen *ss)
        !           671: {
        !           672:        int i;
        !           673:
        !           674:        ss->ss_adder->interrupt_enable = 0;
        !           675:        ss->ss_adder->command = CANCEL;
        !           676:        /* set monitor timing */
        !           677:        ss->ss_adder->x_scan_count_0 = 0x2800;
        !           678:        ss->ss_adder->x_scan_count_1 = 0x1020;
        !           679:        ss->ss_adder->x_scan_count_2 = 0x003a;
        !           680:        ss->ss_adder->x_scan_count_3 = 0x38f0;
        !           681:        ss->ss_adder->x_scan_count_4 = 0x6128;
        !           682:        ss->ss_adder->x_scan_count_5 = 0x093a;
        !           683:        ss->ss_adder->x_scan_count_6 = 0x313c;
        !           684:        ss->ss_adder->sync_phase_adj = 0x0100;
        !           685:        ss->ss_adder->x_scan_conf = 0x00c8;
        !           686:        /*
        !           687:         * got a bug in secound pass ADDER! lets take care of it...
        !           688:         *
        !           689:         * normally, just use the code in the following bug fix code, but to
        !           690:         * make repeated demos look pretty, load the registers as if there was
        !           691:         * no bug and then test to see if we are getting sync
        !           692:         */
        !           693:        ss->ss_adder->y_scan_count_0 = 0x135f;
        !           694:        ss->ss_adder->y_scan_count_1 = 0x3363;
        !           695:        ss->ss_adder->y_scan_count_2 = 0x2366;
        !           696:        ss->ss_adder->y_scan_count_3 = 0x0388;
        !           697:        /*
        !           698:         * if no sync, do the bug fix code
        !           699:         */
        !           700:        if (gpx_wait(ss, FRAME_SYNC) != 0) {
        !           701:                /*
        !           702:                 * First load all Y scan registers with very short frame and
        !           703:                 * wait for scroll service.  This guarantees at least one SYNC
        !           704:                 * to fix the pass 2 Adder initialization bug (synchronizes
        !           705:                 * XCINCH with DMSEEDH)
        !           706:                 */
        !           707:                ss->ss_adder->y_scan_count_0 = 0x01;
        !           708:                ss->ss_adder->y_scan_count_1 = 0x01;
        !           709:                ss->ss_adder->y_scan_count_2 = 0x01;
        !           710:                ss->ss_adder->y_scan_count_3 = 0x01;
        !           711:                /* delay at least 1 full frame time */
        !           712:                gpx_wait(ss, FRAME_SYNC);
        !           713:                gpx_wait(ss, FRAME_SYNC);
        !           714:                /*
        !           715:                 * now load the REAL sync values (in reverse order just to
        !           716:                 * be safe).
        !           717:                 */
        !           718:                ss->ss_adder->y_scan_count_3 = 0x0388;
        !           719:                ss->ss_adder->y_scan_count_2 = 0x2366;
        !           720:                ss->ss_adder->y_scan_count_1 = 0x3363;
        !           721:                ss->ss_adder->y_scan_count_0 = 0x135f;
        !           722:        }
        !           723:        /* zero the index registers */
        !           724:        ss->ss_adder->x_index_pending = 0;
        !           725:        ss->ss_adder->y_index_pending = 0;
        !           726:        ss->ss_adder->x_index_new = 0;
        !           727:        ss->ss_adder->y_index_new = 0;
        !           728:        ss->ss_adder->x_index_old = 0;
        !           729:        ss->ss_adder->y_index_old = 0;
        !           730:        ss->ss_adder->pause = 0;
        !           731:        /* set rasterop mode to normal pen down */
        !           732:        ss->ss_adder->rasterop_mode =
        !           733:            DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
        !           734:        /* set the rasterop registers to default values */
        !           735:        ss->ss_adder->source_1_dx = 1;
        !           736:        ss->ss_adder->source_1_dy = 1;
        !           737:        ss->ss_adder->source_1_x = 0;
        !           738:        ss->ss_adder->source_1_y = 0;
        !           739:        ss->ss_adder->destination_x = 0;
        !           740:        ss->ss_adder->destination_y = 0;
        !           741:        ss->ss_adder->fast_dest_dx = 1;
        !           742:        ss->ss_adder->fast_dest_dy = 0;
        !           743:        ss->ss_adder->slow_dest_dx = 0;
        !           744:        ss->ss_adder->slow_dest_dy = 1;
        !           745:        ss->ss_adder->error_1 = 0;
        !           746:        ss->ss_adder->error_2 = 0;
        !           747:        /* scale factor = UNITY */
        !           748:        ss->ss_adder->fast_scale = UNITY;
        !           749:        ss->ss_adder->slow_scale = UNITY;
        !           750:        /* set the source 2 parameters */
        !           751:        ss->ss_adder->source_2_x = 0;
        !           752:        ss->ss_adder->source_2_y = 0;
        !           753:        ss->ss_adder->source_2_size = 0x0022;
        !           754:        /* initialize plane addresses for eight vipers */
        !           755:        for (i = 0; i < 8; i++) {
        !           756:                gpx_viper_write(ss, CS_UPDATE_MASK, 1 << i);
        !           757:                gpx_viper_write(ss, PLANE_ADDRESS, i);
        !           758:        }
        !           759:        /* initialize the external registers. */
        !           760:        gpx_viper_write(ss, CS_UPDATE_MASK, 0x00ff);
        !           761:        gpx_viper_write(ss, CS_SCROLL_MASK, 0x00ff);
        !           762:        /* initialize resolution mode */
        !           763:        gpx_viper_write(ss, MEMORY_BUS_WIDTH, 0x000c);  /* bus width = 16 */
        !           764:        gpx_viper_write(ss, RESOLUTION_MODE, 0x0000);   /* one bit/pixel */
        !           765:        /* initialize viper registers */
        !           766:        gpx_viper_write(ss, SCROLL_CONSTANT,
        !           767:            SCROLL_ENABLE | VIPER_LEFT | VIPER_UP);
        !           768:        gpx_viper_write(ss, SCROLL_FILL, 0x0000);
        !           769:        /* set clipping and scrolling limits to full screen */
        !           770:        gpx_wait(ss, ADDRESS_COMPLETE);
        !           771:        ss->ss_adder->x_clip_min = 0;
        !           772:        ss->ss_adder->x_clip_max = GPX_WIDTH;
        !           773:        ss->ss_adder->y_clip_min = 0;
        !           774:        ss->ss_adder->y_clip_max = GPX_HEIGHT;
        !           775:        ss->ss_adder->scroll_x_min = 0;
        !           776:        ss->ss_adder->scroll_x_max = GPX_WIDTH;
        !           777:        ss->ss_adder->scroll_y_min = 0;
        !           778:        ss->ss_adder->scroll_y_max = GPX_HEIGHT;
        !           779:        gpx_wait(ss, FRAME_SYNC);       /* wait at LEAST 1 full frame */
        !           780:        gpx_wait(ss, FRAME_SYNC);
        !           781:        ss->ss_adder->x_index_pending = 0;
        !           782:        ss->ss_adder->y_index_pending = 0;
        !           783:        ss->ss_adder->x_index_new = 0;
        !           784:        ss->ss_adder->y_index_new = 0;
        !           785:        ss->ss_adder->x_index_old = 0;
        !           786:        ss->ss_adder->y_index_old = 0;
        !           787:        gpx_wait(ss, ADDRESS_COMPLETE);
        !           788:        gpx_viper_write(ss, LEFT_SCROLL_MASK, 0x0000);
        !           789:        gpx_viper_write(ss, RIGHT_SCROLL_MASK, 0x0000);
        !           790:        /* set source and the mask register to all ones */
        !           791:        gpx_viper_write(ss, SOURCE, 0xffff);
        !           792:        gpx_viper_write(ss, MASK_1, 0xffff);
        !           793:        gpx_viper_write(ss, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
        !           794:        gpx_viper_write(ss, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
        !           795:        /* initialize Operand Control Register banks for fill command */
        !           796:        gpx_viper_write(ss, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
        !           797:        gpx_viper_write(ss, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
        !           798:        gpx_viper_write(ss, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
        !           799:        gpx_viper_write(ss, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
        !           800:        gpx_viper_write(ss, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
        !           801:        gpx_viper_write(ss, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
        !           802:
        !           803:        /*
        !           804:         * Init Logic Unit Function registers.
        !           805:         */
        !           806:        /* putchar */
        !           807:        gpx_viper_write(ss, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
        !           808:        /* erase{cols,rows} */
        !           809:        gpx_viper_write(ss, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_ZEROS);
        !           810:        /* underline */
        !           811:        gpx_viper_write(ss, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_ONES);
        !           812:        /* cursor */
        !           813:        gpx_viper_write(ss, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_NOT_D);
        !           814: }
        !           815:
        !           816: /* Clear the whole screen. Straight from qdss. */
        !           817: void
        !           818: gpx_clear_screen(struct gpx_screen *ss)
        !           819: {
        !           820:        ss->ss_adder->x_limit = GPX_WIDTH;
        !           821:        ss->ss_adder->y_limit = GPX_HEIGHT;
        !           822:        ss->ss_adder->y_offset_pending = 0;
        !           823:        gpx_wait(ss, FRAME_SYNC);       /* wait at LEAST 1 full frame */
        !           824:        gpx_wait(ss, FRAME_SYNC);
        !           825:        ss->ss_adder->y_scroll_constant = SCROLL_ERASE;
        !           826:        gpx_wait(ss, FRAME_SYNC);
        !           827:        gpx_wait(ss, FRAME_SYNC);
        !           828:        ss->ss_adder->y_offset_pending = GPX_VISHEIGHT;
        !           829:        gpx_wait(ss, FRAME_SYNC);
        !           830:        gpx_wait(ss, FRAME_SYNC);
        !           831:        ss->ss_adder->y_scroll_constant = SCROLL_ERASE;
        !           832:        gpx_wait(ss, FRAME_SYNC);
        !           833:        gpx_wait(ss, FRAME_SYNC);
        !           834:        ss->ss_adder->y_offset_pending = 2 * GPX_VISHEIGHT;
        !           835:        gpx_wait(ss, FRAME_SYNC);
        !           836:        gpx_wait(ss, FRAME_SYNC);
        !           837:        ss->ss_adder->y_scroll_constant = SCROLL_ERASE;
        !           838:        gpx_wait(ss, FRAME_SYNC);
        !           839:        gpx_wait(ss, FRAME_SYNC);
        !           840:        ss->ss_adder->y_offset_pending = 0;      /* back to normal */
        !           841:        gpx_wait(ss, FRAME_SYNC);
        !           842:        gpx_wait(ss, FRAME_SYNC);
        !           843:        ss->ss_adder->x_limit = GPX_WIDTH;
        !           844:        ss->ss_adder->y_limit = GPX_VISHEIGHT;
        !           845: }
        !           846:
        !           847: int
        !           848: gpx_setup_screen(struct gpx_screen *ss)
        !           849: {
        !           850:        struct rasops_info *ri = &ss->ss_ri;
        !           851:        int cookie;
        !           852:
        !           853:        bzero(ri, sizeof(*ri));
        !           854:        ri->ri_depth = 8;       /* masquerade as a 8 bit device for rasops */
        !           855:        ri->ri_width = GPX_WIDTH;
        !           856:        ri->ri_height = GPX_VISHEIGHT;
        !           857:        ri->ri_stride = GPX_WIDTH;
        !           858:        ri->ri_flg = RI_CENTER;         /* no RI_CLEAR as ri_bits is NULL! */
        !           859:        ri->ri_hw = ss;
        !           860:
        !           861:        /*
        !           862:         * We can not let rasops select our font, because we need to use
        !           863:         * a font with right-to-left bit order on this frame buffer.
        !           864:         */
        !           865:        wsfont_init();
        !           866:        cookie = wsfont_find(NULL, 12, 0, 0);
        !           867:        if (cookie <= 0)
        !           868:                cookie = wsfont_find(NULL, 8, 0, 0);
        !           869:        if (cookie <= 0)
        !           870:                cookie = wsfont_find(NULL, 0, 0, 0);
        !           871:        if (cookie <= 0)
        !           872:                return (-1);
        !           873:        if (wsfont_lock(cookie, &ri->ri_font,
        !           874:            WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0)
        !           875:                return (-1);
        !           876:        ri->ri_wsfcookie = cookie;
        !           877:
        !           878:        /*
        !           879:         * Ask for an unholy big display, rasops will trim this to more
        !           880:         * reasonable values.
        !           881:         */
        !           882:        if (rasops_init(ri, 160, 160) != 0)
        !           883:                return (-1);
        !           884:
        !           885:        /*
        !           886:         * Override the rasops emulops.
        !           887:         */
        !           888:        ri->ri_ops.copyrows = gpx_copyrows;
        !           889:        ri->ri_ops.copycols = gpx_copycols;
        !           890:        ri->ri_ops.eraserows = gpx_eraserows;
        !           891:        ri->ri_ops.erasecols = gpx_erasecols;
        !           892:        ri->ri_ops.putchar = gpx_putchar;
        !           893:        ri->ri_do_cursor = gpx_do_cursor;
        !           894:
        !           895:        gpx_stdscreen.ncols = ri->ri_cols;
        !           896:        gpx_stdscreen.nrows = ri->ri_rows;
        !           897:        gpx_stdscreen.textops = &ri->ri_ops;
        !           898:        gpx_stdscreen.fontwidth = ri->ri_font->fontwidth;
        !           899:        gpx_stdscreen.fontheight = ri->ri_font->fontheight;
        !           900:        gpx_stdscreen.capabilities = ri->ri_caps;
        !           901:
        !           902:        /*
        !           903:         * Initialize RAMDAC.
        !           904:         */
        !           905:        if (ss->ss_depth == 8) {
        !           906:                struct ramdac8 *rd = ss->ss_vdac;
        !           907:                rd->address = BT_CR;
        !           908:                rd->control = BTCR_RAMENA | BTCR_BLINK_1648 | BTCR_MPLX_4;
        !           909:        } else {
        !           910:                struct ramdac4 *rd = ss->ss_vdac;
        !           911:                rd->control = RAMDAC4_INIT;
        !           912:        }
        !           913:
        !           914:        /*
        !           915:         * Put the ADDER and VIPER in a good state.
        !           916:         */
        !           917:        gpx_reset_viper(ss);
        !           918:
        !           919:        /*
        !           920:         * Initialize colormap.
        !           921:         */
        !           922:        gpx_resetcmap(ss);
        !           923:
        !           924:        /*
        !           925:         * Clear display (including non-visible area), in 864 lines chunks.
        !           926:         */
        !           927:        gpx_clear_screen(ss);
        !           928:
        !           929:        /*
        !           930:         * Copy our font to the offscreen area.
        !           931:         */
        !           932:        gpx_upload_font(ss);
        !           933:
        !           934: #if 0
        !           935:        ss->ss_cursor->cmdr = ss->ss_curcmd = PCCCMD_HSHI;
        !           936: #endif
        !           937:
        !           938:        return (0);
        !           939: }
        !           940:
        !           941: /*
        !           942:  * Copy the selected wsfont to non-visible frame buffer area.
        !           943:  * This is necessary since the only way to send data to the frame buffer
        !           944:  * is through the ID interface, which is slow and needs 16 bit wide data.
        !           945:  * Adapted from qdss.
        !           946:  */
        !           947: void
        !           948: gpx_upload_font(struct gpx_screen *ss)
        !           949: {
        !           950:        struct rasops_info *ri = &ss->ss_ri;
        !           951:        struct wsdisplay_font *font = ri->ri_font;
        !           952:        u_int8_t *fontbits, *fb;
        !           953:        u_int remaining, nchars, row;
        !           954:        u_int i, j;
        !           955:        u_int16_t data;
        !           956:
        !           957:        /* setup VIPER operand control registers */
        !           958:
        !           959:        gpx_viper_write(ss, MASK_1, 0xffff);
        !           960:        gpx_viper_write(ss, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
        !           961:        gpx_viper_write(ss, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
        !           962:
        !           963:        gpx_viper_write(ss, SRC1_OCR_B,
        !           964:            EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
        !           965:        gpx_viper_write(ss, SRC2_OCR_B,
        !           966:            EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
        !           967:        gpx_viper_write(ss, DST_OCR_B,
        !           968:            EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
        !           969:
        !           970:        ss->ss_adder->rasterop_mode =
        !           971:            DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
        !           972:        gpx_wait(ss, RASTEROP_COMPLETE);
        !           973:
        !           974:        /*
        !           975:         * Load font data. The font is uploaded in 8 or 16 bit wide cells, on
        !           976:         * as many ``lines'' as necessary at the end of the display.
        !           977:         */
        !           978:        ss->ss_gpr = MIN(GPX_WIDTH / (NBBY * font->stride), font->numchars);
        !           979:        if (ss->ss_gpr & 1)
        !           980:                ss->ss_gpr--;
        !           981:        fontbits = font->data;
        !           982:        for (row = 1, remaining = font->numchars; remaining != 0;
        !           983:            row++, remaining -= nchars) {
        !           984:                nchars = MIN(ss->ss_gpr, remaining);
        !           985:
        !           986:                ss->ss_adder->destination_x = 0;
        !           987:                ss->ss_adder->destination_y =
        !           988:                    GPX_HEIGHT - row * font->fontheight;
        !           989:                ss->ss_adder->fast_dest_dx = nchars * 16;
        !           990:                ss->ss_adder->slow_dest_dy = font->fontheight;
        !           991:
        !           992:                /* setup for processor to bitmap xfer */
        !           993:                gpx_viper_write(ss, CS_UPDATE_MASK, 0x00ff);
        !           994:                ss->ss_adder->cmd = PBT | OCRB | DTE | LF_R1 | 2; /*XXX why 2?*/
        !           995:
        !           996:                /* iteratively do the processor to bitmap xfer */
        !           997:                for (i = font->fontheight; i != 0; i--) {
        !           998:                        fb = fontbits;
        !           999:                        fontbits += font->stride;
        !          1000:                        /* PTOB a scan line */
        !          1001:                        for (j = nchars; j != 0; j--) {
        !          1002:                                /* PTOB one scan of a char cell */
        !          1003:                                if (font->stride == 1) {
        !          1004:                                        data = *fb;
        !          1005:                                        fb += font->fontheight;
        !          1006:                                        /*
        !          1007:                                         * Do not access past font memory if
        !          1008:                                         * it has an odd number of characters
        !          1009:                                         * and this is the last pair.
        !          1010:                                         */
        !          1011:                                        if (j != 1 || (nchars & 1) == 0 ||
        !          1012:                                            remaining != nchars) {
        !          1013:                                                data |= ((u_int16_t)*fb) << 8;
        !          1014:                                                fb += font->fontheight;
        !          1015:                                        }
        !          1016:                                } else {
        !          1017:                                        data =
        !          1018:                                            fb[0] | (((u_int16_t)fb[1]) << 8);
        !          1019:                                        fb += font->fontheight * font->stride;
        !          1020:                                }
        !          1021:
        !          1022:                                gpx_wait(ss, TX_READY);
        !          1023:                                ss->ss_adder->id_data = data;
        !          1024:                        }
        !          1025:                }
        !          1026:                fontbits += (nchars - 1) * font->stride * font->fontheight;
        !          1027:        }
        !          1028: }
        !          1029:
        !          1030: void
        !          1031: gpx_copyrect(struct gpx_screen *ss,
        !          1032:     int sx, int sy, int dx, int dy, int w, int h)
        !          1033: {
        !          1034:        while (gpx_viper_write(ss, CS_UPDATE_MASK, 0x00ff));
        !          1035:        gpx_viper_write(ss, MASK_1, 0xffff);
        !          1036:        gpx_viper_write(ss, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
        !          1037:        gpx_viper_write(ss, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
        !          1038:        gpx_viper_write(ss, SRC1_OCR_B,
        !          1039:            EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
        !          1040:        gpx_viper_write(ss, DST_OCR_B,
        !          1041:            EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
        !          1042:        ss->ss_adder->fast_dest_dy = 0;
        !          1043:        ss->ss_adder->slow_dest_dx = 0;
        !          1044:        ss->ss_adder->error_1 = 0;
        !          1045:        ss->ss_adder->error_2 = 0;
        !          1046:        ss->ss_adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
        !          1047:        gpx_wait(ss, RASTEROP_COMPLETE);
        !          1048:        ss->ss_adder->destination_x = dx;
        !          1049:        ss->ss_adder->fast_dest_dx = w;
        !          1050:        ss->ss_adder->destination_y = dy;
        !          1051:        ss->ss_adder->slow_dest_dy = h;
        !          1052:        ss->ss_adder->source_1_x = sx;
        !          1053:        ss->ss_adder->source_1_dx = w;
        !          1054:        ss->ss_adder->source_1_y = sy;
        !          1055:        ss->ss_adder->source_1_dy = h;
        !          1056:        ss->ss_adder->cmd = RASTEROP | OCRB | S1E | DTE | LF_R1;
        !          1057: }
        !          1058:
        !          1059: /*
        !          1060:  * Fill a rectangle with the given attribute and function (i.e. rop).
        !          1061:  */
        !          1062: void
        !          1063: gpx_fillrect(struct gpx_screen *ss, int x, int y, int dx, int dy, long attr,
        !          1064:     u_int function)
        !          1065: {
        !          1066:        struct rasops_info *ri = &ss->ss_ri;
        !          1067:        int fg, bg;
        !          1068:
        !          1069:        ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, NULL);
        !          1070:
        !          1071:        while (gpx_viper_write(ss, CS_UPDATE_MASK, 0x00ff));
        !          1072:        gpx_viper_write(ss, MASK_1, 0xffff);
        !          1073:        gpx_viper_write(ss, SOURCE, 0xffff);
        !          1074:        gpx_viper_write(ss, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, fg);
        !          1075:        gpx_viper_write(ss, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, bg);
        !          1076:        gpx_viper_write(ss, SRC1_OCR_B,
        !          1077:            EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
        !          1078:        gpx_viper_write(ss, DST_OCR_B,
        !          1079:            EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
        !          1080:        ss->ss_adder->fast_dest_dx = 0;
        !          1081:        ss->ss_adder->fast_dest_dy = 0;
        !          1082:        ss->ss_adder->slow_dest_dx = 0;
        !          1083:        ss->ss_adder->error_1 = 0;
        !          1084:        ss->ss_adder->error_2 = 0;
        !          1085:        ss->ss_adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
        !          1086:        gpx_wait(ss, RASTEROP_COMPLETE);
        !          1087:        ss->ss_adder->destination_x = x;
        !          1088:        ss->ss_adder->fast_dest_dx = dx;
        !          1089:        ss->ss_adder->destination_y = y;
        !          1090:        ss->ss_adder->slow_dest_dy = dy;
        !          1091:        ss->ss_adder->source_1_x = x;
        !          1092:        ss->ss_adder->source_1_dx = dx;
        !          1093:        ss->ss_adder->source_1_y = y;
        !          1094:        ss->ss_adder->source_1_dy = dy;
        !          1095:        ss->ss_adder->cmd = RASTEROP | OCRB | S1E | DTE | function;
        !          1096: }
        !          1097:
        !          1098: /*
        !          1099:  * Colormap handling routines
        !          1100:  */
        !          1101:
        !          1102: int
        !          1103: gpx_getcmap(struct gpx_screen *ss, struct wsdisplay_cmap *cm)
        !          1104: {
        !          1105:        u_int index = cm->index, count = cm->count, i;
        !          1106:        u_int colcount = 1 << ss->ss_depth;
        !          1107:        int error;
        !          1108:        u_int8_t ramp[256], *c, *r;
        !          1109:
        !          1110:        if (index >= colcount || count > colcount - index)
        !          1111:                return (EINVAL);
        !          1112:
        !          1113:        /* extract reds */
        !          1114:        c = ss->ss_cmap + 0 + index * 3;
        !          1115:        for (i = count, r = ramp; i != 0; i--)
        !          1116:                *r++ = *c << (8 - ss->ss_depth), c += 3;
        !          1117:        if ((error = copyout(ramp, cm->red, count)) != 0)
        !          1118:                return (error);
        !          1119:
        !          1120:        /* extract greens */
        !          1121:        c = ss->ss_cmap + 1 + index * 3;
        !          1122:        for (i = count, r = ramp; i != 0; i--)
        !          1123:                *r++ = *c << (8 - ss->ss_depth), c += 3;
        !          1124:        if ((error = copyout(ramp, cm->green, count)) != 0)
        !          1125:                return (error);
        !          1126:
        !          1127:        /* extract blues */
        !          1128:        c = ss->ss_cmap + 2 + index * 3;
        !          1129:        for (i = count, r = ramp; i != 0; i--)
        !          1130:                *r++ = *c << (8 - ss->ss_depth), c += 3;
        !          1131:        if ((error = copyout(ramp, cm->blue, count)) != 0)
        !          1132:                return (error);
        !          1133:
        !          1134:        return (0);
        !          1135: }
        !          1136:
        !          1137: int
        !          1138: gpx_putcmap(struct gpx_screen *ss, struct wsdisplay_cmap *cm)
        !          1139: {
        !          1140:        u_int index = cm->index, count = cm->count;
        !          1141:        u_int colcount = 1 << ss->ss_depth;
        !          1142:        int i, error;
        !          1143:        u_int8_t r[256], g[256], b[256], *nr, *ng, *nb, *c;
        !          1144:
        !          1145:        if (index >= colcount || count > colcount - index)
        !          1146:                return (EINVAL);
        !          1147:
        !          1148:        if ((error = copyin(cm->red, r, count)) != 0)
        !          1149:                return (error);
        !          1150:        if ((error = copyin(cm->green, g, count)) != 0)
        !          1151:                return (error);
        !          1152:        if ((error = copyin(cm->blue, b, count)) != 0)
        !          1153:                return (error);
        !          1154:
        !          1155:        nr = r, ng = g, nb = b;
        !          1156:        c = ss->ss_cmap + index * 3;
        !          1157:        for (i = count; i != 0; i--) {
        !          1158:                *c++ = *nr++ >> (8 - ss->ss_depth);
        !          1159:                *c++ = *ng++ >> (8 - ss->ss_depth);
        !          1160:                *c++ = *nb++ >> (8 - ss->ss_depth);
        !          1161:        }
        !          1162:
        !          1163:        return (0);
        !          1164: }
        !          1165:
        !          1166: void
        !          1167: gpx_loadcmap(struct gpx_screen *ss, int from, int count)
        !          1168: {
        !          1169:        u_int8_t *cmap = ss->ss_cmap;
        !          1170:        int i, color12;
        !          1171:
        !          1172:        gpx_wait(ss, FRAME_SYNC);
        !          1173:        if (ss->ss_depth == 8) {
        !          1174:                struct ramdac8 *rd = ss->ss_vdac;
        !          1175:
        !          1176:                cmap += from * 3;
        !          1177:                rd->address = from;
        !          1178:                for (i = 0; i < count * 3; i++)
        !          1179:                        rd->cmapdata = *cmap++;
        !          1180:        } else {
        !          1181:                struct ramdac4 *rd = ss->ss_vdac;
        !          1182:
        !          1183:                cmap = ss->ss_cmap + from;
        !          1184:                for (i = from; i < from + count; i++) {
        !          1185:                        color12  = (*cmap++ >> 4) << 0;
        !          1186:                        color12 |= (*cmap++ >> 4) << 8;
        !          1187:                        color12 |= (*cmap++ >> 4) << 4;
        !          1188:                        rd->colormap[i] = color12;
        !          1189:                }
        !          1190:        }
        !          1191: }
        !          1192:
        !          1193: void
        !          1194: gpx_resetcmap(struct gpx_screen *ss)
        !          1195: {
        !          1196:        if (ss->ss_depth == 8)
        !          1197:                bcopy(rasops_cmap, ss->ss_cmap, sizeof(ss->ss_cmap));
        !          1198:        else {
        !          1199:                bcopy(rasops_cmap, ss->ss_cmap, 8 * 3);
        !          1200:                bcopy(rasops_cmap + 0xf8 * 3, ss->ss_cmap + 8 * 3, 8 * 3);
        !          1201:        }
        !          1202:        gpx_loadcmap(ss, 0, 1 << ss->ss_depth);
        !          1203:
        !          1204:        /*
        !          1205:         * On the 4bit RAMDAC, make the hardware cursor black on black
        !          1206:         */
        !          1207:        if (ss->ss_depth != 8) {
        !          1208:                struct ramdac4 *rd = ss->ss_vdac;
        !          1209:
        !          1210:                rd->cursormap[0] = rd->cursormap[1] =
        !          1211:                    rd->cursormap[2] = rd->cursormap[3] = 0x0000;
        !          1212:        }
        !          1213: }
        !          1214:
        !          1215: /*
        !          1216:  * Console support code
        !          1217:  */
        !          1218:
        !          1219: int    gpxcnprobe(void);
        !          1220: void   gpxcninit(void);
        !          1221:
        !          1222: int
        !          1223: gpxcnprobe()
        !          1224: {
        !          1225:        extern vaddr_t virtual_avail;
        !          1226:        vaddr_t tmp;
        !          1227:        int depth;
        !          1228:
        !          1229:        switch (vax_boardtype) {
        !          1230:        case VAX_BTYP_410:
        !          1231:        case VAX_BTYP_420:
        !          1232:        case VAX_BTYP_43:
        !          1233:                if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_MULTU)) != 0)
        !          1234:                        break; /* doesn't use graphics console */
        !          1235:
        !          1236:                if ((vax_confdata & KA420_CFG_VIDOPT) == 0)
        !          1237:                        break; /* no color option */
        !          1238:
        !          1239:                /* Check for a recognized color depth */
        !          1240:                tmp = virtual_avail;
        !          1241:                ioaccess(tmp, vax_trunc_page(GPXADDR + GPX_READBACK_OFFSET), 1);
        !          1242:                depth = *(u_int16_t *)
        !          1243:                    (tmp + (GPX_READBACK_OFFSET & VAX_PGOFSET)) & 0x00f0;
        !          1244:                if (depth == 0x00f0 || depth == 0x0080)
        !          1245:                        return (1);
        !          1246:
        !          1247:                break;
        !          1248:
        !          1249:        default:
        !          1250:                break;
        !          1251:        }
        !          1252:
        !          1253:        return (0);
        !          1254: }
        !          1255:
        !          1256: /*
        !          1257:  * Called very early to setup the glass tty as console.
        !          1258:  * Because it's called before the VM system is initialized, virtual memory
        !          1259:  * for the framebuffer can be stolen directly without disturbing anything.
        !          1260:  */
        !          1261: void
        !          1262: gpxcninit()
        !          1263: {
        !          1264:        struct gpx_screen *ss = &gpx_consscr;
        !          1265:        extern vaddr_t virtual_avail;
        !          1266:        vaddr_t tmp;
        !          1267:        long defattr;
        !          1268:        struct rasops_info *ri;
        !          1269:
        !          1270:        tmp = virtual_avail;
        !          1271:        ioaccess(tmp, vax_trunc_page(GPXADDR + GPX_READBACK_OFFSET), 1);
        !          1272:        ss->ss_depth = (0x00f0 & *(u_int16_t *)
        !          1273:            (tmp + (GPX_READBACK_OFFSET & VAX_PGOFSET))) == 0x00f0 ? 4 : 8;
        !          1274:
        !          1275:        ioaccess(virtual_avail, GPXADDR + GPX_ADDER_OFFSET, 1);
        !          1276:        ss->ss_adder = (struct adder *)virtual_avail;
        !          1277:        virtual_avail += VAX_NBPG;
        !          1278:
        !          1279:        ioaccess(virtual_avail, vax_trunc_page(GPXADDR + GPX_VDAC_OFFSET), 1);
        !          1280:        ss->ss_vdac = (void *)(virtual_avail + (GPX_VDAC_OFFSET & VAX_PGOFSET));
        !          1281:        virtual_avail += VAX_NBPG;
        !          1282:
        !          1283: #if 0
        !          1284:        ioaccess(virtual_avail, GPXADDR + GPX_CURSOR_OFFSET, 1);
        !          1285:        ss->ss_cursor = (struct dc503reg *)virtual_avail;
        !          1286:        virtual_avail += VAX_NBPG;
        !          1287: #endif
        !          1288:
        !          1289:        virtual_avail = round_page(virtual_avail);
        !          1290:
        !          1291:        /* this had better not fail as we can't recover there */
        !          1292:        if (gpx_setup_screen(ss) != 0)
        !          1293:                panic(__func__);
        !          1294:
        !          1295:        ri = &ss->ss_ri;
        !          1296:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
        !          1297:        wsdisplay_cnattach(&gpx_stdscreen, ri, 0, 0, defattr);
        !          1298: }

CVSweb