Annotation of sys/dev/sbus/zx.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: zx.c,v 1.13 2007/03/13 19:40:49 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/bus.h>
87: #include <machine/cpu.h>
88: #include <machine/conf.h>
89:
90: #include <dev/wscons/wsconsio.h>
91: #include <dev/wscons/wsdisplayvar.h>
92: #include <dev/rasops/rasops.h>
93: #include <machine/fbvar.h>
94:
95: #include <dev/sbus/zxreg.h>
96: #include <dev/sbus/sbusvar.h>
97:
98: #define ZX_WID_SHARED_8 0
99: #define ZX_WID_SHARED_24 1
100: #define ZX_WID_DBL_8 2
101: #define ZX_WID_DBL_24 3
102:
103: /*
104: * Per-instance data.
105: */
106:
107: struct zx_cmap {
108: u_int8_t cm_red[256];
109: u_int8_t cm_green[256];
110: u_int8_t cm_blue[256];
111: };
112:
113: struct zx_softc {
114: struct sunfb sc_sunfb;
115:
116: bus_space_tag_t sc_bustag;
117: bus_addr_t sc_paddr;
118:
119: struct zx_cmap sc_cmap; /* shadow color map for overlay plane */
120:
121: volatile struct zx_command *sc_zc;
122: volatile struct zx_cross *sc_zx;
123: volatile struct zx_draw *sc_zd_ss0;
124: volatile struct zx_draw_ss1 *sc_zd_ss1;
125: volatile struct zx_cursor *sc_zcu;
126:
127: int sc_nscreens;
128: };
129:
130: int zx_ioctl(void *, u_long, caddr_t, int, struct proc *);
131: int zx_alloc_screen(void *, const struct wsscreen_descr *, void **,
132: int *, int *, long *);
133: void zx_free_screen(void *, void *);
134: int zx_show_screen(void *, void *, int, void (*)(void *, int, int), void *);
135: paddr_t zx_mmap(void *, off_t, int);
136: void zx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
137: void zx_reset(struct zx_softc *, u_int);
138: void zx_burner(void *, u_int, u_int);
139:
140: struct wsdisplay_accessops zx_accessops = {
141: zx_ioctl,
142: zx_mmap,
143: zx_alloc_screen,
144: zx_free_screen,
145: zx_show_screen,
146: NULL, /* load_font */
147: NULL, /* scrollback */
148: NULL, /* getchar */
149: zx_burner
150: };
151:
152: /* Force 32-bit writes. */
153: #define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v))
154:
155: #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
156: ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
157:
158: #define ZX_BWIDTH 13
159: #define ZX_WWIDTH 11 /* word width */
160:
161: #define ZX_COORDS(x, y) ((x) | ((y) << ZX_WWIDTH))
162:
163: void zx_attach(struct device *, struct device *, void *);
164: int zx_match(struct device *, void *, void *);
165:
166: int zx_putcmap(struct zx_softc *);
167: void zx_copyrect(struct rasops_info *, int, int, int, int, int, int);
168: int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int);
169: int zx_cross_wait(struct zx_softc *);
170: void zx_fillrect(struct rasops_info *, int, int, int, int, long, int);
171: int zx_intr(void *);
172: void zx_prom(void *);
173:
174: void zx_putchar(void *, int, int, u_int, long);
175: void zx_copycols(void *, int, int, int, int);
176: void zx_erasecols(void *, int, int, int, long);
177: void zx_copyrows(void *, int, int, int);
178: void zx_eraserows(void *, int, int, long);
179: void zx_do_cursor(struct rasops_info *);
180:
181: struct cfattach zx_ca = {
182: sizeof(struct zx_softc), zx_match, zx_attach
183: };
184:
185: struct cfdriver zx_cd = {
186: NULL, "zx", DV_DULL
187: };
188:
189: int
190: zx_match(struct device *parent, void *vcf, void *aux)
191: {
192: struct sbus_attach_args *sa = aux;
193:
194: if (strcmp(sa->sa_name, "SUNW,leo") == 0)
195: return (1);
196:
197: return (0);
198: }
199:
200: void
201: zx_attach(struct device *parent, struct device *self, void *args)
202: {
203: struct zx_softc *sc = (struct zx_softc *)self;
204: struct sbus_attach_args *sa = args;
205: struct rasops_info *ri;
206: bus_space_tag_t bt;
207: bus_space_handle_t bh;
208: int node, isconsole = 0;
209: const char *nam;
210:
211: bt = sa->sa_bustag;
212: ri = &sc->sc_sunfb.sf_ro;
213: node = sa->sa_node;
214:
215: /*
216: * Map the various parts of the card.
217: */
218: sc->sc_bustag = bt;
219: sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);
220:
221: if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
222: sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
223: printf(": couldn't map command registers\n");
224: return;
225: }
226: sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh);
227:
228: if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
229: sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
230: printf(": couldn't map ss0 drawing registers\n");
231: return;
232: }
233: sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh);
234:
235: if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
236: sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
237: printf(": couldn't map ss1 drawing registers\n");
238: return;
239: }
240: sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh);
241:
242: if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
243: sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
244: printf(": couldn't map cross registers\n");
245: return;
246: }
247: sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh);
248:
249: if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
250: sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
251: printf(": couldn't map cursor registers\n");
252: return;
253: }
254: sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh);
255:
256: nam = getpropstring(node, "model");
257: if (*nam == '\0')
258: nam = sa->sa_name;
259: printf(": %s", nam);
260:
261: isconsole = node == fbnode;
262:
263: /*
264: * The console is using the 8-bit overlay plane, while the prom
265: * will correctly report 32 bit depth.
266: * The following is an equivalent for
267: * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
268: * forcing the depth value not to be overwritten.
269: * Furthermore, the linebytes value is in fact 8192 bytes.
270: */
271: sc->sc_sunfb.sf_depth = 8;
272: sc->sc_sunfb.sf_width = getpropint(node, "width", 1152);
273: sc->sc_sunfb.sf_height = getpropint(node, "height", 900);
274: sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH;
275: sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH;
276:
277: printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
278:
279: if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
280: round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR,
281: 0, &bh) != 0) {
282: printf("%s: couldn't map video memory\n", self->dv_xname);
283: return;
284: }
285: ri->ri_bits = bus_space_vaddr(bt, bh);
286: ri->ri_hw = sc;
287:
288: fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
289:
290: /*
291: * Watch out! rasops_init() invoked via fbwscons_init() did not
292: * compute ri_bits correctly when centering the display, because
293: * it has been tricked with the low depth value.
294: * Recompute now.
295: */
296: ri->ri_emustride = ri->ri_emuwidth * 4;
297: ri->ri_delta = ri->ri_stride - ri->ri_emustride;
298: ri->ri_pelbytes = 4;
299: ri->ri_xscale = ri->ri_font->fontwidth * 4;
300: ri->ri_bits = ri->ri_origbits;
301: ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3;
302: ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
303: ri->ri_stride;
304: ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
305: / ri->ri_stride;
306: ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
307: % ri->ri_stride) / 4);
308:
309: ri->ri_ops.copyrows = zx_copyrows;
310: ri->ri_ops.copycols = zx_copycols;
311: ri->ri_ops.eraserows = zx_eraserows;
312: ri->ri_ops.erasecols = zx_erasecols;
313: ri->ri_ops.putchar = zx_putchar;
314: ri->ri_do_cursor = zx_do_cursor;
315:
316: if (isconsole) {
317: /* zx_reset() below will clear screen, so restart at 1st row */
318: fbwscons_console_init(&sc->sc_sunfb, 0);
319: }
320:
321: /* reset cursor & frame buffer controls */
322: zx_reset(sc, WSDISPLAYIO_MODE_EMUL);
323:
324: /* enable video */
325: zx_burner(sc, 1, 0);
326:
327: fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole);
328: }
329:
330: int
331: zx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
332: {
333: struct zx_softc *sc = dev;
334: struct wsdisplay_fbinfo *wdf;
335:
336: /*
337: * Note that, although the emulation (text) mode is running in
338: * a 8-bit plane, we advertize the frame buffer as the full-blown
339: * 32-bit beast it is.
340: */
341: switch (cmd) {
342: case WSDISPLAYIO_GTYPE:
343: *(u_int *)data = WSDISPLAY_TYPE_SUN24;
344: break;
345: case WSDISPLAYIO_GINFO:
346: wdf = (struct wsdisplay_fbinfo *)data;
347: wdf->height = sc->sc_sunfb.sf_height;
348: wdf->width = sc->sc_sunfb.sf_width;
349: wdf->depth = 32;
350: wdf->cmsize = 0;
351: break;
352: case WSDISPLAYIO_GETSUPPORTEDDEPTH:
353: *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
354: break;
355: case WSDISPLAYIO_LINEBYTES:
356: *(u_int *)data = sc->sc_sunfb.sf_linebytes;
357: break;
358:
359: case WSDISPLAYIO_GETCMAP:
360: case WSDISPLAYIO_PUTCMAP:
361: break;
362:
363: case WSDISPLAYIO_SMODE:
364: zx_reset(sc, *(u_int *)data);
365: break;
366:
367: case WSDISPLAYIO_SVIDEO:
368: case WSDISPLAYIO_GVIDEO:
369: break;
370:
371: default:
372: return (-1);
373: }
374:
375: return (0);
376: }
377:
378: int
379: zx_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
380: int *curxp, int *curyp, long *attrp)
381: {
382: struct zx_softc *sc = v;
383:
384: if (sc->sc_nscreens > 0)
385: return (ENOMEM);
386:
387: *cookiep = &sc->sc_sunfb.sf_ro;
388: *curyp = 0;
389: *curxp = 0;
390: sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
391: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
392: sc->sc_nscreens++;
393: return (0);
394: }
395:
396: void
397: zx_free_screen(void *v, void *cookie)
398: {
399: struct zx_softc *sc = v;
400:
401: sc->sc_nscreens--;
402: }
403:
404: int
405: zx_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
406: void *cbarg)
407: {
408: return (0);
409: }
410:
411: /*
412: * Return the address that would map the given device at the given
413: * offset, allowing for the given protection, or return -1 for error.
414: */
415: paddr_t
416: zx_mmap(void *v, off_t offset, int prot)
417: {
418: struct zx_softc *sc = v;
419:
420: if (offset & PGOFSET)
421: return (-1);
422:
423: /* Allow mapping as a dumb framebuffer from offset 0 */
424: if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
425: return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
426: ZX_OFF_SS0 + offset, prot, BUS_SPACE_MAP_LINEAR));
427: }
428:
429: return (-1);
430: }
431:
432: void
433: zx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
434: {
435: struct zx_softc *sc = v;
436:
437: sc->sc_cmap.cm_red[index] = r;
438: sc->sc_cmap.cm_green[index] = g;
439: sc->sc_cmap.cm_blue[index] = b;
440: }
441:
442: void
443: zx_reset(struct zx_softc *sc, u_int mode)
444: {
445: volatile struct zx_draw *zd;
446: volatile struct zx_command *zc;
447: u_int32_t i;
448: const u_char *color;
449: u_int8_t *r, *g, *b;
450:
451: zd = sc->sc_zd_ss0;
452: zc = sc->sc_zc;
453:
454: if (mode == WSDISPLAYIO_MODE_EMUL) {
455: /* Back from X11 to emulation mode, or first reset */
456: zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0);
457: zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30);
458: zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20);
459: zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30);
460:
461: i = sc->sc_zd_ss1->zd_misc;
462: i |= ZX_SS1_MISC_ENABLE;
463: SETREG(sc->sc_zd_ss1->zd_misc, i);
464:
465: /*
466: * XXX
467: * If zc_fill is not set to that value, there will be black
468: * bars left in the margins. But then with this value, the
469: * screen gets cleared. Go figure.
470: */
471: SETREG(zd->zd_wid, 0xffffffff);
472: SETREG(zd->zd_wmask, 0xffff);
473: SETREG(zd->zd_vclipmin, 0);
474: SETREG(zd->zd_vclipmax, (sc->sc_sunfb.sf_width - 1) |
475: ((sc->sc_sunfb.sf_height - 1) << 16));
476: SETREG(zd->zd_fg, 0);
477: SETREG(zd->zd_planemask, 0xff000000);
478: SETREG(zd->zd_rop, ZX_STD_ROP);
479: SETREG(zd->zd_widclip, 0);
480:
481: SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1,
482: sc->sc_sunfb.sf_height - 1));
483: SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR);
484: SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS);
485: SETREG(zc->zc_fontt, 0);
486:
487: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
488: ;
489:
490: /*
491: * Initialize the 8-bit colormap
492: */
493: r = sc->sc_cmap.cm_red;
494: g = sc->sc_cmap.cm_green;
495: b = sc->sc_cmap.cm_blue;
496: color = rasops_cmap;
497: for (i = 0; i < 256; i++) {
498: *r++ = *color++;
499: *g++ = *color++;
500: *b++ = *color++;
501: }
502: fbwscons_setcolormap(&sc->sc_sunfb, zx_setcolor);
503: zx_putcmap(sc);
504: } else {
505: /* Starting X11 - switch to 24bit WID */
506: SETREG(zd->zd_wid, 1);
507: SETREG(zd->zd_widclip, 0);
508: SETREG(zd->zd_wmask, 0xffff);
509: SETREG(zd->zd_planemask, 0x00ffffff);
510: SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1,
511: sc->sc_sunfb.sf_height - 1));
512: SETREG(zc->zc_fill, 0);
513: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
514: ;
515:
516: SETREG(zc->zc_addrspace, ZX_ADDRSPC_OBGR);
517: SETREG(zd->zd_rop, ZX_ATTR_RGBE_ENABLE |
518: ZX_ROP_NEW /* | ZX_ATTR_FORCE_WID */);
519: }
520: }
521:
522: int
523: zx_cross_wait(struct zx_softc *sc)
524: {
525: volatile struct zx_cross *zx;
526: int i;
527:
528: zx = sc->sc_zx;
529:
530: for (i = 300000; i != 0; i--) {
531: if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0)
532: break;
533: DELAY(1);
534: }
535:
536: if (i == 0)
537: printf("%s: zx_cross_wait: timed out\n",
538: sc->sc_sunfb.sf_dev.dv_xname);
539:
540: return (i);
541: }
542:
543: int
544: zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value)
545: {
546: volatile struct zx_cross *zx;
547: u_int tmp;
548:
549: zx = sc->sc_zx;
550: SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
551:
552: if (!zx_cross_wait(sc))
553: return (1);
554:
555: if (type == ZX_WID_DBL_8)
556: tmp = (index & 0x0f) + 0x40;
557: else if (type == ZX_WID_DBL_24)
558: tmp = index & 0x3f;
559:
560: SETREG(zx->zx_type, 0x5800 + tmp);
561: SETREG(zx->zx_value, value);
562: SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
563: SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2);
564:
565: return (0);
566: }
567:
568: int
569: zx_putcmap(struct zx_softc *sc)
570: {
571: volatile struct zx_cross *zx;
572: u_int32_t i;
573: u_int8_t *r, *g, *b;
574:
575: zx = sc->sc_zx;
576:
577: SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
578: if (!zx_cross_wait(sc))
579: return (1);
580:
581: SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA);
582:
583: r = sc->sc_cmap.cm_red;
584: g = sc->sc_cmap.cm_green;
585: b = sc->sc_cmap.cm_blue;
586: for (i = 0; i < 256; i++) {
587: SETREG(zx->zx_value, *r++ | (*g++ << 8) | (*b++ << 16));
588: }
589:
590: SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
591: i = zx->zx_csr;
592: i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2;
593: SETREG(zx->zx_csr, i);
594: return (0);
595: }
596:
597: void
598: zx_burner(void *v, u_int on, u_int flags)
599: {
600: struct zx_softc *sc = v;
601: volatile struct zx_cross *zx;
602: u_int32_t i;
603:
604: zx = sc->sc_zx;
605:
606: SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO);
607: i = zx->zx_csr;
608: if (on) {
609: i |= ZX_CROSS_CSR_ENABLE;
610: } else {
611: i &= ~ZX_CROSS_CSR_ENABLE;
612: }
613: SETREG(zx->zx_csr, i);
614: }
615:
616: void
617: zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, long attr,
618: int rop)
619: {
620: struct zx_softc *sc;
621: volatile struct zx_command *zc;
622: volatile struct zx_draw *zd;
623: int fg, bg;
624:
625: sc = ri->ri_hw;
626: zc = sc->sc_zc;
627: zd = sc->sc_zd_ss0;
628:
629: ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, NULL);
630: x = x * ri->ri_font->fontwidth + ri->ri_xorigin;
631: y = y * ri->ri_font->fontheight + ri->ri_yorigin;
632: w = ri->ri_font->fontwidth * w - 1;
633: h = ri->ri_font->fontheight * h - 1;
634:
635: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
636: ;
637:
638: SETREG(zd->zd_rop, rop);
639: SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24);
640: SETREG(zc->zc_extent, ZX_COORDS(w, h));
641: SETREG(zc->zc_fill, ZX_COORDS(x, y) | ZX_EXTENT_DIR_BACKWARDS);
642: }
643:
644: void
645: zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w,
646: int h)
647: {
648: struct zx_softc *sc;
649: volatile struct zx_command *zc;
650: volatile struct zx_draw *zd;
651: int dir;
652:
653: sc = ri->ri_hw;
654: zc = sc->sc_zc;
655: zd = sc->sc_zd_ss0;
656:
657: sx = sx * ri->ri_font->fontwidth + ri->ri_xorigin;
658: sy = sy * ri->ri_font->fontheight + ri->ri_yorigin;
659: dx = dx * ri->ri_font->fontwidth + ri->ri_xorigin;
660: dy = dy * ri->ri_font->fontheight + ri->ri_yorigin;
661: w = w * ri->ri_font->fontwidth - 1;
662: h = h * ri->ri_font->fontheight - 1;
663:
664: if (sy < dy || sx < dx) {
665: dir = ZX_EXTENT_DIR_BACKWARDS;
666: sx += w;
667: sy += h;
668: dx += w;
669: dy += h;
670: } else
671: dir = ZX_EXTENT_DIR_FORWARDS;
672:
673: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
674: ;
675:
676: SETREG(zd->zd_rop, ZX_STD_ROP);
677: SETREG(zc->zc_extent, ZX_COORDS(w, h) | dir);
678: SETREG(zc->zc_src, ZX_COORDS(sx, sy));
679: SETREG(zc->zc_copy, ZX_COORDS(dx, dy));
680: }
681:
682: void
683: zx_do_cursor(struct rasops_info *ri)
684: {
685:
686: zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, WSCOL_BLACK << 16,
687: ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
688: ZX_ATTR_FORCE_WID);
689: }
690:
691: void
692: zx_erasecols(void *cookie, int row, int col, int num, long attr)
693: {
694: struct rasops_info *ri;
695:
696: ri = (struct rasops_info *)cookie;
697:
698: zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP);
699: }
700:
701: void
702: zx_eraserows(void *cookie, int row, int num, long attr)
703: {
704: struct rasops_info *ri;
705: struct zx_softc *sc;
706: volatile struct zx_command *zc;
707: volatile struct zx_draw *zd;
708: int fg, bg;
709:
710: ri = (struct rasops_info *)cookie;
711:
712: if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
713: sc = ri->ri_hw;
714: zc = sc->sc_zc;
715: zd = sc->sc_zd_ss0;
716:
717: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
718:
719: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
720: ;
721:
722: SETREG(zd->zd_rop, ZX_STD_ROP);
723: SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24);
724: SETREG(zc->zc_extent,
725: ZX_COORDS(ri->ri_width - 1, ri->ri_height - 1));
726: SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS);
727: } else
728: zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP);
729: }
730:
731: void
732: zx_copyrows(void *cookie, int src, int dst, int num)
733: {
734: struct rasops_info *ri;
735:
736: ri = (struct rasops_info *)cookie;
737:
738: zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num);
739: }
740:
741: void
742: zx_copycols(void *cookie, int row, int src, int dst, int num)
743: {
744: struct rasops_info *ri;
745:
746: ri = (struct rasops_info *)cookie;
747:
748: zx_copyrect(ri, src, row, dst, row, num, 1);
749: }
750:
751: void
752: zx_putchar(void *cookie, int row, int col, u_int uc, long attr)
753: {
754: struct rasops_info *ri;
755: struct zx_softc *sc;
756: struct wsdisplay_font *font;
757: volatile struct zx_command *zc;
758: volatile struct zx_draw *zd;
759: volatile u_int32_t *dp;
760: u_int8_t *fb;
761: int fs, i, fg, bg, ul;
762:
763: ri = (struct rasops_info *)cookie;
764: font = ri->ri_font;
765: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, &ul);
766: fg = ri->ri_devcmap[fg];
767: bg = ri->ri_devcmap[bg];
768:
769: dp = (volatile u_int32_t *)ri->ri_bits +
770: ZX_COORDS(col * font->fontwidth, row * font->fontheight);
771:
772: if (uc == ' ') {
773: zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP);
774: if (ul == 0)
775: return;
776:
777: dp += font->fontheight << ZX_WWIDTH;
778:
779: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
780: ;
781:
782: SETREG(zd->zd_rop, ZX_STD_ROP);
783: SETREG(zd->zd_fg, fg << 24);
784: SETREG(zd->zd_bg, bg << 24);
785: SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
786: } else {
787: sc = ri->ri_hw;
788: zc = sc->sc_zc;
789: zd = sc->sc_zd_ss0;
790:
791: fb = (u_int8_t *)font->data + (uc - font->firstchar) *
792: ri->ri_fontscale;
793: fs = font->stride;
794:
795: while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
796: ;
797:
798: SETREG(zd->zd_rop, ZX_STD_ROP);
799: SETREG(zd->zd_fg, fg << 24);
800: SETREG(zd->zd_bg, bg << 24);
801: SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
802:
803: if (font->fontwidth <= 8) {
804: for (i = font->fontheight; i != 0;
805: i--, dp += 1 << ZX_WWIDTH) {
806: *dp = *fb << 24;
807: fb += fs;
808: }
809: } else {
810: for (i = font->fontheight; i != 0;
811: i--, dp += 1 << ZX_WWIDTH) {
812: *dp = *((u_int16_t *)fb) << 16;
813: fb += fs;
814: }
815: }
816: }
817:
818: /* underline */
819: if (ul) {
820: dp -= 2 << ZX_WWIDTH;
821: *dp = 0xffffffff;
822: }
823: }
CVSweb