[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

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