Annotation of sys/arch/sparc/dev/zx.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: zx.c,v 1.19 2007/03/13 19:40:48 miod Exp $ */
2: /* $NetBSD: zx.c,v 1.5 2002/10/02 16:52:46 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 2003, Miodrag Vallat.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27: * POSSIBILITY OF SUCH DAMAGE.
28: *
29: * Derived from NetBSD syssrc/sys/dev/sbus/zx.c under the following licence
30: * terms:
31: *
32: * Copyright (c) 2002 The NetBSD Foundation, Inc.
33: * All rights reserved.
34: *
35: * This code is derived from software contributed to The NetBSD Foundation
36: * by Andrew Doran.
37: *
38: * Redistribution and use in source and binary forms, with or without
39: * modification, are permitted provided that the following conditions
40: * are met:
41: * 1. Redistributions of source code must retain the above copyright
42: * notice, this list of conditions and the following disclaimer.
43: * 2. Redistributions in binary form must reproduce the above copyright
44: * notice, this list of conditions and the following disclaimer in the
45: * documentation and/or other materials provided with the distribution.
46: * 3. All advertising materials mentioning features or use of this software
47: * must display the following acknowledgement:
48: * This product includes software developed by the NetBSD
49: * Foundation, Inc. and its contributors.
50: * 4. Neither the name of The NetBSD Foundation nor the names of its
51: * contributors may be used to endorse or promote products derived
52: * from this software without specific prior written permission.
53: *
54: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64: * POSSIBILITY OF SUCH DAMAGE.
65: */
66:
67: /*
68: * Driver for the Sun ZX display adapter. This would be called 'leo', but
69: * NetBSD/amiga already has a driver by that name. The XFree86 and Linux
70: * drivers were used as "living documentation" when writing this; thanks
71: * to the authors.
72: */
73:
74: #include <sys/param.h>
75: #include <sys/systm.h>
76: #include <sys/device.h>
77: #include <sys/ioctl.h>
78: #include <sys/malloc.h>
79: #include <sys/mman.h>
80: #include <sys/tty.h>
81: #include <sys/conf.h>
82:
83: #include <uvm/uvm_extern.h>
84:
85: #include <machine/autoconf.h>
86: #include <machine/cpu.h>
87: #include <machine/conf.h>
88:
89: #include <dev/wscons/wsconsio.h>
90: #include <dev/wscons/wsdisplayvar.h>
91: #include <dev/rasops/rasops.h>
92: #include <machine/fbvar.h>
93:
94: #include <dev/sbus/zxreg.h>
95: #include <sparc/dev/sbusvar.h>
96:
97: #include <dev/cons.h> /* for prom console hook */
98:
99: #define ZX_WID_SHARED_8 0
100: #define ZX_WID_SHARED_24 1
101: #define ZX_WID_DBL_8 2
102: #define ZX_WID_DBL_24 3
103:
104: /*
105: * Per-instance data.
106: */
107:
108: struct zx_cmap {
109: u_int8_t cm_red[256];
110: u_int8_t cm_green[256];
111: u_int8_t cm_blue[256];
112: };
113:
114: struct zx_softc {
115: struct sunfb sc_sunfb;
116: struct rom_reg sc_phys;
117:
118: struct zx_cmap sc_cmap; /* shadow color map for overlay plane */
119:
120: volatile struct zx_command *sc_zc;
121: volatile struct zx_cross *sc_zx;
122: volatile struct zx_draw *sc_zd_ss0;
123: volatile struct zx_draw_ss1 *sc_zd_ss1;
124: volatile struct zx_cursor *sc_zcu;
125:
126: int sc_mode;
127: };
128:
129: void zx_burner(void *, u_int, u_int);
130: int zx_ioctl(void *, u_long, caddr_t, int, struct proc *);
131: paddr_t zx_mmap(void *v, off_t offset, int prot);
132: void zx_prom(void *);
133: void zx_reset(struct zx_softc *, u_int);
134: void zx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
135:
136: struct wsdisplay_accessops zx_accessops = {
137: zx_ioctl,
138: zx_mmap,
139: NULL, /* alloc_screen */
140: NULL, /* free_screen */
141: NULL, /* show_screen */
142: NULL, /* load_font */
143: NULL, /* scrollback */
144: NULL, /* getchar */
145: zx_burner,
146: NULL /* pollc */
147: };
148:
149: /* Force 32-bit writes. */
150: #define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v))
151:
152: #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
153: ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
154:
155: #define ZX_BWIDTH 13
156: #define ZX_WWIDTH 11 /* word width */
157:
158: #define ZX_COORDS(x, y) ((x) | ((y) << ZX_WWIDTH))
159:
160: void zx_attach(struct device *, struct device *, void *);
161: int zx_match(struct device *, void *, void *);
162:
163: void zx_copyrect(struct rasops_info *, int, int, int, int, int, int);
164: int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int);
165: int zx_cross_wait(struct zx_softc *);
166: void zx_fillrect(struct rasops_info *, int, int, int, int, long, int);
167: int zx_intr(void *);
168: int zx_putcmap(struct zx_softc *);
169:
170: void zx_copycols(void *, int, int, int, int);
171: void zx_copyrows(void *, int, int, int);
172: void zx_do_cursor(struct rasops_info *);
173: void zx_erasecols(void *, int, int, int, long);
174: void zx_eraserows(void *, int, int, long);
175: void zx_putchar(void *, int, int, u_int, long);
176:
177: struct cfattach zx_ca = {
178: sizeof(struct zx_softc), zx_match, zx_attach
179: };
180:
181: struct cfdriver zx_cd = {
182: NULL, "zx", DV_DULL
183: };
184:
185: int
186: zx_match(struct device *parent, void *vcf, void *aux)
187: {
188: struct confargs *ca = aux;
189: struct romaux *ra = &ca->ca_ra;
190:
191: if (strcmp(ra->ra_name, "SUNW,leo") == 0)
192: return (1);
193:
194: return (0);
195: }
196:
197: void
198: zx_attach(struct device *parent, struct device *self, void *args)
199: {
200: struct zx_softc *sc = (struct zx_softc *)self;
201: struct confargs *ca = args;
202: struct rasops_info *ri;
203: int node, isconsole = 0;
204: const char *nam;
205:
206: ri = &sc->sc_sunfb.sf_ro;
207: node = ca->ca_ra.ra_node;
208:
209: /*
210: * Map the various parts of the card.
211: */
212: sc->sc_phys = ca->ca_ra.ra_reg[0];
213:
214: sc->sc_zc = (struct zx_command *)
215: mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LC_SS0_USR,
216: sizeof(struct zx_command));
217: sc->sc_zd_ss0 = (struct zx_draw *)
218: mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LD_SS0,
219: sizeof(struct zx_draw));
220: sc->sc_zd_ss1 = (struct zx_draw_ss1 *)
221: mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LD_SS1,
222: sizeof(struct zx_draw_ss1));
223: sc->sc_zx = (struct zx_cross *)
224: mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LX_CROSS,
225: sizeof(struct zx_cross));
226: sc->sc_zcu = (struct zx_cursor *)
227: mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LX_CURSOR,
228: sizeof(struct zx_cursor));
229:
230: nam = getpropstring(node, "model");
231: if (*nam == '\0')
232: nam = ca->ca_ra.ra_name;
233: printf(": %s", nam);
234:
235: isconsole = node == fbnode;
236:
237: /*
238: * The console is using the 8-bit overlay plane, while the prom
239: * will correctly report 32 bit depth.
240: * The following is an equivalent for
241: * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
242: * forcing the depth value not to be overwritten.
243: * Furthermore, the linebytes value is in fact 8192 bytes.
244: */
245: sc->sc_sunfb.sf_depth = 8;
246: sc->sc_sunfb.sf_width = getpropint(node, "width", 1152);
247: sc->sc_sunfb.sf_height = getpropint(node, "height", 900);
248: sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH;
249: sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH;
250:
251: printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
252:
253: ri->ri_bits = mapiodev(ca->ca_ra.ra_reg,
254: ZX_OFF_SS0, round_page(sc->sc_sunfb.sf_fbsize));
255: ri->ri_hw = sc;
256:
257: fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
258:
259: /*
260: * Watch out! rasops_init() invoked via fbwscons_init() did not
261: * compute ri_bits correctly when centering the display, because
262: * it has been tricked with the low depth value.
263: * Recompute now.
264: */
265: ri->ri_emustride = ri->ri_emuwidth * 4;
266: ri->ri_delta = ri->ri_stride - ri->ri_emustride;
267: ri->ri_pelbytes = 4;
268: ri->ri_xscale = ri->ri_font->fontwidth * 4;
269: ri->ri_bits = ri->ri_origbits;
270: ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3;
271: ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
272: ri->ri_stride;
273: ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
274: / ri->ri_stride;
275: ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
276: % ri->ri_stride) / 4);
277:
278: ri->ri_ops.copyrows = zx_copyrows;
279: ri->ri_ops.copycols = zx_copycols;
280: ri->ri_ops.eraserows = zx_eraserows;
281: ri->ri_ops.erasecols = zx_erasecols;
282: ri->ri_ops.putchar = zx_putchar;
283: ri->ri_do_cursor = zx_do_cursor;
284:
285: if (isconsole) {
286: /* zx_reset() below will clear screen, so restart at 1st row */
287: fbwscons_console_init(&sc->sc_sunfb, 0);
288: shutdownhook_establish(zx_prom, sc);
289: }
290:
291: /* reset cursor & frame buffer controls */
292: sc->sc_mode = ~WSDISPLAYIO_MODE_EMUL; /* force action */
293: zx_reset(sc, WSDISPLAYIO_MODE_EMUL);
294:
295: /* enable video */
296: zx_burner(sc, 1, 0);
297:
298: fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole);
299: }
300:
301: int
302: zx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
303: {
304: struct zx_softc *sc = dev;
305: struct wsdisplay_fbinfo *wdf;
306:
307: /*
308: * Note that, although the emulation (text) mode is running in
309: * a 8-bit plane, we advertize the frame buffer as the full-blown
310: * 32-bit beast it is.
311: */
312: switch (cmd) {
313: case WSDISPLAYIO_GTYPE:
314: *(u_int *)data = WSDISPLAY_TYPE_SUN24;
315: break;
316: case WSDISPLAYIO_GINFO:
317: wdf = (struct wsdisplay_fbinfo *)data;
318: wdf->height = sc->sc_sunfb.sf_height;
319: wdf->width = sc->sc_sunfb.sf_width;
320: wdf->depth = 32;
321: wdf->cmsize = 0;
322: break;
323: case WSDISPLAYIO_GETSUPPORTEDDEPTH:
324: *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
325: break;
326: case WSDISPLAYIO_LINEBYTES:
327: *(u_int *)data = sc->sc_sunfb.sf_linebytes;
328: break;
329:
330: case WSDISPLAYIO_GETCMAP:
331: case WSDISPLAYIO_PUTCMAP:
332: break;
333:
334: case WSDISPLAYIO_SMODE:
335: zx_reset(sc, *(u_int *)data);
336: break;
337:
338: case WSDISPLAYIO_SVIDEO:
339: case WSDISPLAYIO_GVIDEO:
340: break;
341:
342: default:
343: return (-1);
344: }
345:
346: return (0);
347: }
348:
349: /*
350: * Return the address that would map the given device at the given
351: * offset, allowing for the given protection, or return -1 for error.
352: */
353: paddr_t
354: zx_mmap(void *v, off_t offset, int prot)
355: {
356: struct zx_softc *sc = v;
357:
358: if (offset & PGOFSET)
359: return (-1);
360:
361: /* Allow mapping as a dumb framebuffer from offset 0 */
362: if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
363: return (REG2PHYS(&sc->sc_phys, ZX_OFF_SS0 + offset) | PMAP_NC);
364: }
365:
366: return (-1);
367: }
368:
369: void
370: zx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
371: {
372: struct zx_softc *sc = v;
373:
374: sc->sc_cmap.cm_red[index] = r;
375: sc->sc_cmap.cm_green[index] = g;
376: sc->sc_cmap.cm_blue[index] = b;
377: }
378:
379: void
380: zx_reset(struct zx_softc *sc, u_int mode)
381: {
382: volatile struct zx_draw *zd;
383: volatile struct zx_command *zc;
384: u_int32_t i;
385: const u_char *color;
386: u_int8_t *r, *g, *b;
387:
388: if (mode == sc->sc_mode)
389: return;
390:
391: zd = sc->sc_zd_ss0;
392: zc = sc->sc_zc;
393:
394: if (mode == WSDISPLAYIO_MODE_EMUL) {
395: /* Back from X11 to emulation mode, or first reset */
396: zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0);
397: zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30);
398: zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20);
399: zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30);
400:
401: i = sc->sc_zd_ss1->zd_misc;
402: i |= ZX_SS1_MISC_ENABLE;
403: SETREG(sc->sc_zd_ss1->zd_misc, i);
404:
405: /*
406: * XXX
407: * If zc_fill is not set to that value, there will be black
408: * bars left in the margins. But then with this value, the
409: * screen gets cleared. Go figure.
410: */
411: SETREG(zd->zd_wid, 0xffffffff);
412: SETREG(zd->zd_wmask, 0xffff);
413: SETREG(zd->zd_vclipmin, 0);
414: SETREG(zd->zd_vclipmax, (sc->sc_sunfb.sf_width - 1) |
415: ((sc->sc_sunfb.sf_height - 1) << 16));
416: SETREG(zd->zd_fg, 0);
417: SETREG(zd->zd_planemask, 0xff000000);
418: SETREG(zd->zd_rop, ZX_STD_ROP);
419: SETREG(zd->zd_widclip, 0);
420:
421: SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1,
422: sc->sc_sunfb.sf_height - 1));
423: SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR);
424: SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS);
425: SETREG(zc->zc_fontt, 0);
426:
427: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
428: ;
429:
430: /*
431: * Initialize the 8-bit colormap
432: */
433: r = sc->sc_cmap.cm_red;
434: g = sc->sc_cmap.cm_green;
435: b = sc->sc_cmap.cm_blue;
436: color = rasops_cmap;
437: for (i = 0; i < 256; i++) {
438: *r++ = *color++;
439: *g++ = *color++;
440: *b++ = *color++;
441: }
442: fbwscons_setcolormap(&sc->sc_sunfb, zx_setcolor);
443: zx_putcmap(sc);
444: } else {
445: /* Starting X11 - switch to 24bit WID */
446: SETREG(zd->zd_wid, 1);
447: SETREG(zd->zd_widclip, 0);
448: SETREG(zd->zd_wmask, 0xffff);
449: SETREG(zd->zd_planemask, 0x00ffffff);
450: SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1,
451: sc->sc_sunfb.sf_height - 1));
452: SETREG(zc->zc_fill, 0);
453: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
454: ;
455:
456: SETREG(zc->zc_addrspace, ZX_ADDRSPC_OBGR);
457: SETREG(zd->zd_rop, ZX_ATTR_RGBE_ENABLE |
458: ZX_ROP_NEW /* | ZX_ATTR_FORCE_WID */);
459: }
460:
461: sc->sc_mode = mode;
462: }
463:
464: int
465: zx_cross_wait(struct zx_softc *sc)
466: {
467: volatile struct zx_cross *zx;
468: int i;
469:
470: zx = sc->sc_zx;
471:
472: for (i = 300000; i != 0; i--) {
473: if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0)
474: break;
475: DELAY(1);
476: }
477:
478: if (i == 0)
479: printf("%s: zx_cross_wait: timed out\n",
480: sc->sc_sunfb.sf_dev.dv_xname);
481:
482: return (i);
483: }
484:
485: int
486: zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value)
487: {
488: volatile struct zx_cross *zx;
489: u_int tmp;
490:
491: zx = sc->sc_zx;
492: SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
493:
494: if (!zx_cross_wait(sc))
495: return (1);
496:
497: if (type == ZX_WID_DBL_8)
498: tmp = (index & 0x0f) + 0x40;
499: else if (type == ZX_WID_DBL_24)
500: tmp = index & 0x3f;
501:
502: SETREG(zx->zx_type, 0x5800 + tmp);
503: SETREG(zx->zx_value, value);
504: SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
505: SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2);
506:
507: return (0);
508: }
509:
510: int
511: zx_putcmap(struct zx_softc *sc)
512: {
513: volatile struct zx_cross *zx;
514: u_int32_t i;
515: u_int8_t *r, *g, *b;
516:
517: zx = sc->sc_zx;
518:
519: SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
520: if (!zx_cross_wait(sc))
521: return (1);
522:
523: SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA);
524:
525: r = sc->sc_cmap.cm_red;
526: g = sc->sc_cmap.cm_green;
527: b = sc->sc_cmap.cm_blue;
528: for (i = 0; i < 256; i++) {
529: SETREG(zx->zx_value, *r++ | (*g++ << 8) | (*b++ << 16));
530: }
531:
532: SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
533: i = zx->zx_csr;
534: i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2;
535: SETREG(zx->zx_csr, i);
536: return (0);
537: }
538:
539: void
540: zx_burner(void *v, u_int on, u_int flags)
541: {
542: struct zx_softc *sc = v;
543: volatile struct zx_cross *zx;
544: u_int32_t i;
545:
546: zx = sc->sc_zx;
547:
548: SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO);
549: i = zx->zx_csr;
550: if (on) {
551: i |= ZX_CROSS_CSR_ENABLE;
552: } else {
553: i &= ~ZX_CROSS_CSR_ENABLE;
554: }
555: SETREG(zx->zx_csr, i);
556: }
557:
558: void
559: zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, long attr,
560: int rop)
561: {
562: struct zx_softc *sc;
563: volatile struct zx_command *zc;
564: volatile struct zx_draw *zd;
565: int fg, bg;
566:
567: sc = ri->ri_hw;
568: zc = sc->sc_zc;
569: zd = sc->sc_zd_ss0;
570:
571: ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, NULL);
572: x = x * ri->ri_font->fontwidth + ri->ri_xorigin;
573: y = y * ri->ri_font->fontheight + ri->ri_yorigin;
574: w = ri->ri_font->fontwidth * w - 1;
575: h = ri->ri_font->fontheight * h - 1;
576:
577: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
578: ;
579:
580: SETREG(zd->zd_rop, rop);
581: SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24);
582: SETREG(zc->zc_extent, ZX_COORDS(w, h));
583: SETREG(zc->zc_fill, ZX_COORDS(x, y) | ZX_EXTENT_DIR_BACKWARDS);
584: }
585:
586: void
587: zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w,
588: int h)
589: {
590: struct zx_softc *sc;
591: volatile struct zx_command *zc;
592: volatile struct zx_draw *zd;
593: int dir;
594:
595: sc = ri->ri_hw;
596: zc = sc->sc_zc;
597: zd = sc->sc_zd_ss0;
598:
599: sx = sx * ri->ri_font->fontwidth + ri->ri_xorigin;
600: sy = sy * ri->ri_font->fontheight + ri->ri_yorigin;
601: dx = dx * ri->ri_font->fontwidth + ri->ri_xorigin;
602: dy = dy * ri->ri_font->fontheight + ri->ri_yorigin;
603: w = w * ri->ri_font->fontwidth - 1;
604: h = h * ri->ri_font->fontheight - 1;
605:
606: if (sy < dy || sx < dx) {
607: dir = ZX_EXTENT_DIR_BACKWARDS;
608: sx += w;
609: sy += h;
610: dx += w;
611: dy += h;
612: } else
613: dir = ZX_EXTENT_DIR_FORWARDS;
614:
615: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
616: ;
617:
618: SETREG(zd->zd_rop, ZX_STD_ROP);
619: SETREG(zc->zc_extent, ZX_COORDS(w, h) | dir);
620: SETREG(zc->zc_src, ZX_COORDS(sx, sy));
621: SETREG(zc->zc_copy, ZX_COORDS(dx, dy));
622: }
623:
624: void
625: zx_do_cursor(struct rasops_info *ri)
626: {
627:
628: zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, WSCOL_BLACK << 16,
629: ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
630: ZX_ATTR_FORCE_WID);
631: }
632:
633: void
634: zx_erasecols(void *cookie, int row, int col, int num, long attr)
635: {
636: struct rasops_info *ri;
637:
638: ri = (struct rasops_info *)cookie;
639:
640: zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP);
641: }
642:
643: void
644: zx_eraserows(void *cookie, int row, int num, long attr)
645: {
646: struct rasops_info *ri;
647: struct zx_softc *sc;
648: volatile struct zx_command *zc;
649: volatile struct zx_draw *zd;
650: int fg, bg;
651:
652: ri = (struct rasops_info *)cookie;
653:
654: if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
655: sc = ri->ri_hw;
656: zc = sc->sc_zc;
657: zd = sc->sc_zd_ss0;
658:
659: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
660:
661: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
662: ;
663:
664: SETREG(zd->zd_rop, ZX_STD_ROP);
665: SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24);
666: SETREG(zc->zc_extent,
667: ZX_COORDS(ri->ri_width - 1, ri->ri_height - 1));
668: SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS);
669: } else
670: zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP);
671: }
672:
673: void
674: zx_copyrows(void *cookie, int src, int dst, int num)
675: {
676: struct rasops_info *ri;
677:
678: ri = (struct rasops_info *)cookie;
679:
680: zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num);
681: }
682:
683: void
684: zx_copycols(void *cookie, int row, int src, int dst, int num)
685: {
686: struct rasops_info *ri;
687:
688: ri = (struct rasops_info *)cookie;
689:
690: zx_copyrect(ri, src, row, dst, row, num, 1);
691: }
692:
693: void
694: zx_putchar(void *cookie, int row, int col, u_int uc, long attr)
695: {
696: struct rasops_info *ri;
697: struct zx_softc *sc;
698: struct wsdisplay_font *font;
699: volatile struct zx_command *zc;
700: volatile struct zx_draw *zd;
701: volatile u_int32_t *dp;
702: u_int8_t *fb;
703: int fs, i, fg, bg, ul;
704:
705: ri = (struct rasops_info *)cookie;
706: font = ri->ri_font;
707: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, &ul);
708: fg = ri->ri_devcmap[fg];
709: bg = ri->ri_devcmap[bg];
710:
711: dp = (volatile u_int32_t *)ri->ri_bits +
712: ZX_COORDS(col * font->fontwidth, row * font->fontheight);
713:
714: if (uc == ' ') {
715: zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP);
716: if (ul == 0)
717: return;
718:
719: dp += font->fontheight << ZX_WWIDTH;
720:
721: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
722: ;
723:
724: SETREG(zd->zd_rop, ZX_STD_ROP);
725: SETREG(zd->zd_fg, fg << 24);
726: SETREG(zd->zd_bg, bg << 24);
727: SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
728: } else {
729: sc = ri->ri_hw;
730: zc = sc->sc_zc;
731: zd = sc->sc_zd_ss0;
732:
733: fb = (u_int8_t *)font->data + (uc - font->firstchar) *
734: ri->ri_fontscale;
735: fs = font->stride;
736:
737: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
738: ;
739:
740: SETREG(zd->zd_rop, ZX_STD_ROP);
741: SETREG(zd->zd_fg, fg << 24);
742: SETREG(zd->zd_bg, bg << 24);
743: SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
744:
745: if (font->fontwidth <= 8) {
746: for (i = font->fontheight; i != 0;
747: i--, dp += 1 << ZX_WWIDTH) {
748: *dp = *fb << 24;
749: fb += fs;
750: }
751: } else {
752: for (i = font->fontheight; i != 0;
753: i--, dp += 1 << ZX_WWIDTH) {
754: *dp = *((u_int16_t *)fb) << 16;
755: fb += fs;
756: }
757: }
758: }
759:
760: /* underline */
761: if (ul) {
762: dp -= 2 << ZX_WWIDTH;
763: *dp = 0xffffffff;
764: }
765: }
766:
767: void
768: zx_prom(void *v)
769: {
770: struct zx_softc *sc = v;
771: extern struct consdev consdev_prom;
772:
773: if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) {
774: /*
775: * Select 8-bit mode.
776: */
777: zx_reset(sc, WSDISPLAYIO_MODE_EMUL);
778:
779: /*
780: * Go back to prom output for the last few messages, so they
781: * will be displayed correctly.
782: */
783: cn_tab = &consdev_prom;
784: }
785: }
CVSweb