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