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