This source file includes following definitions.
- zx_match
- zx_attach
- zx_ioctl
- zx_alloc_screen
- zx_free_screen
- zx_show_screen
- zx_mmap
- zx_setcolor
- zx_reset
- zx_cross_wait
- zx_cross_loadwid
- zx_putcmap
- zx_burner
- zx_fillrect
- zx_copyrect
- zx_do_cursor
- zx_erasecols
- zx_eraserows
- zx_copyrows
- zx_copycols
- zx_putchar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
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;
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,
147 NULL,
148 NULL,
149 zx_burner
150 };
151
152
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
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
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
265
266
267
268
269
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
292
293
294
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
318 fbwscons_console_init(&sc->sc_sunfb, 0);
319 }
320
321
322 zx_reset(sc, WSDISPLAYIO_MODE_EMUL);
323
324
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
338
339
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
413
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
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
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
467
468
469
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
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
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 );
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
819 if (ul) {
820 dp -= 2 << ZX_WWIDTH;
821 *dp = 0xffffffff;
822 }
823 }