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