zx.c revision 1.23 1 /* $NetBSD: zx.c,v 1.23 2008/06/11 18:50:59 cegger Exp $ */
2
3 /*
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Driver for the Sun ZX display adapter. This would be called 'leo', but
34 * NetBSD/amiga already has a driver by that name. The XFree86 and Linux
35 * drivers were used as "living documentation" when writing this; thanks
36 * to the authors.
37 *
38 * Issues (which can be solved with wscons, happily enough):
39 *
40 * o There is lots of unnecessary mucking about rasops in here, primarily
41 * to appease the sparc fb code.
42 *
43 * o RASTERCONSOLE is required. X needs the board set up correctly, and
44 * that's difficult to reconcile with using the PROM for output.
45 */
46
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: zx.c,v 1.23 2008/06/11 18:50:59 cegger Exp $");
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/device.h>
53 #include <sys/ioctl.h>
54 #include <sys/malloc.h>
55 #include <sys/mman.h>
56 #include <sys/tty.h>
57 #include <sys/conf.h>
58 #include <sys/syslog.h>
59 #include <sys/buf.h>
60
61 #include <sys/bus.h>
62 #include <machine/autoconf.h>
63
64 #include <uvm/uvm_extern.h>
65
66 #include <dev/sun/fbio.h>
67 #include <dev/sun/fbvar.h>
68
69 #include <dev/sbus/zxreg.h>
70 #include <dev/sbus/zxvar.h>
71 #include <dev/sbus/sbusvar.h>
72
73 #include <dev/wscons/wsconsio.h>
74
75 #ifndef RASTERCONSOLE
76 #error Sorry, this driver needs the RASTERCONSOLE option
77 #endif
78
79 /* Force 32-bit writes. */
80 #define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v))
81
82 #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
83 ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
84
85 void zx_attach(struct device *, struct device *, void *);
86 int zx_match(struct device *, struct cfdata *, void *);
87
88 void zx_blank(struct device *);
89 int zx_cmap_put(struct zx_softc *);
90 void zx_copyrect(struct rasops_info *, int, int, int, int, int, int);
91 int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int);
92 int zx_cross_wait(struct zx_softc *);
93 void zx_fillrect(struct rasops_info *, int, int, int, int, long, int);
94 int zx_intr(void *);
95 void zx_reset(struct zx_softc *);
96 void zx_unblank(struct device *);
97
98 void zx_cursor_blank(struct zx_softc *);
99 void zx_cursor_color(struct zx_softc *);
100 void zx_cursor_move(struct zx_softc *);
101 void zx_cursor_set(struct zx_softc *);
102 void zx_cursor_unblank(struct zx_softc *);
103
104 void zx_copycols(void *, int, int, int, int);
105 void zx_copyrows(void *, int, int, int);
106 void zx_cursor(void *, int, int, int);
107 void zx_do_cursor(struct rasops_info *);
108 void zx_erasecols(void *, int, int, int, long);
109 void zx_eraserows(void *, int, int, long);
110 void zx_putchar(void *, int, int, u_int, long);
111
112 struct zx_mmo {
113 off_t mo_va;
114 off_t mo_pa;
115 off_t mo_size;
116 } static const zx_mmo[] = {
117 { ZX_FB0_VOFF, ZX_OFF_SS0, 0x00800000 },
118 { ZX_LC0_VOFF, ZX_OFF_LC_SS0_USR, 0x00001000 },
119 { ZX_LD0_VOFF, ZX_OFF_LD_SS0, 0x00001000 },
120 { ZX_LX0_CURSOR_VOFF, ZX_OFF_LX_CURSOR, 0x00001000 },
121 { ZX_FB1_VOFF, ZX_OFF_SS1, 0x00800000 },
122 { ZX_LC1_VOFF, ZX_OFF_LC_SS1_USR, 0x00001000 },
123 { ZX_LD1_VOFF, ZX_OFF_LD_SS1, 0x00001000 },
124 { ZX_LX_KRN_VOFF, ZX_OFF_LX_CROSS, 0x00001000 },
125 { ZX_LC0_KRN_VOFF, ZX_OFF_LC_SS0_KRN, 0x00001000 },
126 { ZX_LC1_KRN_VOFF, ZX_OFF_LC_SS1_KRN, 0x00001000 },
127 { ZX_LD_GBL_VOFF, ZX_OFF_LD_GBL, 0x00001000 },
128 };
129
130 CFATTACH_DECL(zx, sizeof(struct zx_softc),
131 zx_match, zx_attach, NULL, NULL);
132
133 extern struct cfdriver zx_cd;
134
135 dev_type_open(zxopen);
136 dev_type_close(zxclose);
137 dev_type_ioctl(zxioctl);
138 dev_type_mmap(zxmmap);
139
140 static struct fbdriver zx_fbdriver = {
141 zx_unblank, zxopen, zxclose, zxioctl, nopoll, zxmmap
142 };
143
144 int
145 zx_match(struct device *parent, struct cfdata *cf, void *aux)
146 {
147 struct sbus_attach_args *sa;
148
149 sa = (struct sbus_attach_args *)aux;
150
151 return (strcmp(sa->sa_name, "SUNW,leo") == 0);
152 }
153
154 void
155 zx_attach(struct device *parent, struct device *self, void *args)
156 {
157 struct zx_softc *sc;
158 struct sbus_attach_args *sa;
159 bus_space_handle_t bh;
160 bus_space_tag_t bt;
161 struct fbdevice *fb;
162 struct rasops_info *ri;
163 volatile struct zx_command *zc;
164 int isconsole;
165
166 sc = (struct zx_softc *)self;
167 sa = args;
168 fb = &sc->sc_fb;
169 ri = &fb->fb_rinfo;
170 bt = sa->sa_bustag;
171 sc->sc_bt = bt;
172
173 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);
174
175 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
176 0x800000, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
177 aprint_error_dev(self, "can't map bits\n");
178 return;
179 }
180 fb->fb_pixels = (void *)bus_space_vaddr(bt, bh);
181 sc->sc_pixels = (u_int32_t *)fb->fb_pixels;
182
183 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
184 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
185 aprint_error_dev(self, "can't map zc\n");
186 return;
187 }
188 sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh);
189
190 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
191 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
192 aprint_error_dev(self, "can't map ld/ss0\n");
193 return;
194 }
195 sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh);
196
197 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
198 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
199 aprint_error_dev(self, "can't map ld/ss1\n");
200 return;
201 }
202 sc->sc_zd_ss1 =
203 (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh);
204
205 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
206 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
207 aprint_error_dev(self, "can't map zx\n");
208 return;
209 }
210 sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh);
211
212 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
213 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
214 aprint_error_dev(self, "can't map zcu\n");
215 return;
216 }
217 sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh);
218
219 fb->fb_driver = &zx_fbdriver;
220 fb->fb_device = &sc->sc_dv;
221 fb->fb_flags = device_cfdata(&sc->sc_dv)->cf_flags & FB_USERMASK;
222 fb->fb_pfour = NULL;
223 fb->fb_linebytes = 8192;
224
225 fb_setsize_obp(fb, 32, 1280, 1024, sa->sa_node);
226
227 fb->fb_type.fb_cmsize = 256;
228 fb->fb_type.fb_depth = 32;
229 fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
230 fb->fb_type.fb_type = FBTYPE_SUNLEO;
231
232 printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height);
233 isconsole = fb_is_console(sa->sa_node);
234 if (isconsole)
235 printf(" (console)");
236 printf("\n");
237
238 sbus_establish(&sc->sc_sd, &sc->sc_dv);
239 if (sa->sa_nintr != 0)
240 bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc);
241
242 sc->sc_cmap = malloc(768, M_DEVBUF, M_NOWAIT);
243 fb_attach(&sc->sc_fb, isconsole);
244 zx_reset(sc);
245
246 /*
247 * Attach to rcons. XXX At this point, rasops_do_cursor() will be
248 * called before we get our hooks in place. So, we mask off access
249 * to the framebuffer until it's done.
250 */
251 zc = sc->sc_zc;
252 SETREG(zc->zc_fontt, 1);
253 SETREG(zc->zc_fontmsk, 0);
254
255 fbrcons_init(&sc->sc_fb);
256
257 SETREG(zc->zc_fontt, 0);
258 SETREG(zc->zc_fontmsk, 0xffffffff);
259
260 ri->ri_hw = sc;
261 ri->ri_do_cursor = zx_do_cursor;
262 ri->ri_ops.copycols = zx_copycols;
263 ri->ri_ops.copyrows = zx_copyrows;
264 ri->ri_ops.erasecols = zx_erasecols;
265 ri->ri_ops.eraserows = zx_eraserows;
266 ri->ri_ops.putchar = zx_putchar;
267
268 sc->sc_fontw = ri->ri_font->fontwidth;
269 sc->sc_fonth = ri->ri_font->fontheight;
270 }
271
272 int
273 zxopen(dev_t dev, int flags, int mode, struct lwp *l)
274 {
275
276 if (device_lookup(&zx_cd, minor(dev)) == NULL)
277 return (ENXIO);
278 return (0);
279 }
280
281 int
282 zxclose(dev_t dev, int flags, int mode, struct lwp *l)
283 {
284 struct zx_softc *sc;
285
286 sc = device_lookup_private(&zx_cd, minor(dev));
287
288 zx_reset(sc);
289 zx_cursor_blank(sc);
290 return (0);
291 }
292
293 int
294 zxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
295 {
296 struct zx_softc *sc;
297 struct fbcmap *cm;
298 struct fbcursor *cu;
299 uint32_t curbits[2][32];
300 int rv, v, count, i;
301
302 sc = device_lookup_private(&zx_cd, minor(dev));
303
304 switch (cmd) {
305 case FBIOGTYPE:
306 *(struct fbtype *)data = sc->sc_fb.fb_type;
307 break;
308
309 case FBIOGATTR:
310 #define fba ((struct fbgattr *)data)
311 fba->real_type = sc->sc_fb.fb_type.fb_type;
312 fba->owner = 0; /* XXX ??? */
313 fba->fbtype = sc->sc_fb.fb_type;
314 fba->sattr.flags = 0;
315 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
316 fba->sattr.dev_specific[0] = -1;
317 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
318 fba->emu_types[1] = -1;
319 fba->emu_types[2] = -1;
320 #undef fba
321 break;
322
323 case FBIOGVIDEO:
324 *(int *)data = ((sc->sc_flags & ZX_BLANKED) != 0);
325 break;
326
327 case FBIOSVIDEO:
328 if (*(int *)data)
329 zx_unblank(&sc->sc_dv);
330 else
331 zx_blank(&sc->sc_dv);
332 break;
333
334 case FBIOGETCMAP:
335 cm = (struct fbcmap *)data;
336 if (cm->index > 256 || cm->count > 256 - cm->index)
337 return (EINVAL);
338 rv = copyout(sc->sc_cmap + cm->index, cm->red, cm->count);
339 if (rv == 0)
340 rv = copyout(sc->sc_cmap + 256 + cm->index, cm->green,
341 cm->count);
342 if (rv == 0)
343 rv = copyout(sc->sc_cmap + 512 + cm->index, cm->blue,
344 cm->count);
345 return (rv);
346
347 case FBIOPUTCMAP:
348 cm = (struct fbcmap *)data;
349 if (cm->index > 256 || cm->count > 256 - cm->index)
350 return (EINVAL);
351 rv = copyin(cm->red, sc->sc_cmap + cm->index, cm->count);
352 if (rv == 0)
353 rv = copyin(cm->green, sc->sc_cmap + 256 + cm->index,
354 cm->count);
355 if (rv == 0)
356 rv = copyin(cm->blue, sc->sc_cmap + 512 + cm->index,
357 cm->count);
358 zx_cmap_put(sc);
359 return (rv);
360
361 case FBIOGCURPOS:
362 *(struct fbcurpos *)data = sc->sc_curpos;
363 break;
364
365 case FBIOSCURPOS:
366 sc->sc_curpos = *(struct fbcurpos *)data;
367 zx_cursor_move(sc);
368 break;
369
370 case FBIOGCURMAX:
371 ((struct fbcurpos *)data)->x = 32;
372 ((struct fbcurpos *)data)->y = 32;
373 break;
374
375 case FBIOSCURSOR:
376 cu = (struct fbcursor *)data;
377 v = cu->set;
378
379 if ((v & FB_CUR_SETSHAPE) != 0) {
380 if ((u_int)cu->size.x > 32 || (u_int)cu->size.y > 32)
381 return (EINVAL);
382 count = cu->size.y * 4;
383 rv = copyin(cu->mask, curbits[0], count);
384 if (rv)
385 return rv;
386 rv = copyin(cu->image, curbits[1], count);
387 if (rv)
388 return rv;
389 }
390 if ((v & FB_CUR_SETCUR) != 0) {
391 if (cu->enable)
392 zx_cursor_unblank(sc);
393 else
394 zx_cursor_blank(sc);
395 }
396 if ((v & (FB_CUR_SETPOS | FB_CUR_SETHOT)) != 0) {
397 if ((v & FB_CUR_SETPOS) != 0)
398 sc->sc_curpos = cu->pos;
399 if ((v & FB_CUR_SETHOT) != 0)
400 sc->sc_curhot = cu->hot;
401 zx_cursor_move(sc);
402 }
403 if ((v & FB_CUR_SETCMAP) != 0) {
404 if (cu->cmap.index > 2 ||
405 cu->cmap.count > 2 - cu->cmap.index)
406 return (EINVAL);
407 for (i = 0; i < cu->cmap.count; i++) {
408 if ((v = fubyte(&cu->cmap.red[i])) < 0)
409 return (EFAULT);
410 sc->sc_curcmap[i + cu->cmap.index + 0] = v;
411 if ((v = fubyte(&cu->cmap.green[i])) < 0)
412 return (EFAULT);
413 sc->sc_curcmap[i + cu->cmap.index + 2] = v;
414 if ((v = fubyte(&cu->cmap.blue[i])) < 0)
415 return (EFAULT);
416 sc->sc_curcmap[i + cu->cmap.index + 4] = v;
417 }
418 zx_cursor_color(sc);
419 }
420 if ((v & FB_CUR_SETSHAPE) != 0) {
421 sc->sc_cursize = cu->size;
422 count = cu->size.y * 4;
423 memset(sc->sc_curbits, 0, sizeof(sc->sc_curbits));
424 memcpy(sc->sc_curbits[0], curbits[0], count);
425 memcpy(sc->sc_curbits[1], curbits[1], count);
426 zx_cursor_set(sc);
427 }
428 break;
429
430 case FBIOGCURSOR:
431 cu = (struct fbcursor *)data;
432
433 cu->set = FB_CUR_SETALL;
434 cu->enable = ((sc->sc_flags & ZX_CURSOR) != 0);
435 cu->pos = sc->sc_curpos;
436 cu->hot = sc->sc_curhot;
437 cu->size = sc->sc_cursize;
438
439 if (cu->image != NULL) {
440 count = sc->sc_cursize.y * 4;
441 rv = copyout(sc->sc_curbits[1], cu->image, count);
442 if (rv)
443 return (rv);
444 rv = copyout(sc->sc_curbits[0], cu->mask, count);
445 if (rv)
446 return (rv);
447 }
448 if (cu->cmap.red != NULL) {
449 if (cu->cmap.index > 2 ||
450 cu->cmap.count > 2 - cu->cmap.index)
451 return (EINVAL);
452 for (i = 0; i < cu->cmap.count; i++) {
453 v = sc->sc_curcmap[i + cu->cmap.index + 0];
454 if (subyte(&cu->cmap.red[i], v))
455 return (EFAULT);
456 v = sc->sc_curcmap[i + cu->cmap.index + 2];
457 if (subyte(&cu->cmap.green[i], v))
458 return (EFAULT);
459 v = sc->sc_curcmap[i + cu->cmap.index + 4];
460 if (subyte(&cu->cmap.blue[i], v))
461 return (EFAULT);
462 }
463 } else {
464 cu->cmap.index = 0;
465 cu->cmap.count = 2;
466 }
467 break;
468
469 default:
470 #ifdef DEBUG
471 log(LOG_NOTICE, "zxioctl(0x%lx) (%s[%d])\n", cmd,
472 l->l_proc->p_comm, l->l_proc->p_pid);
473 #endif
474 return (ENOTTY);
475 }
476
477 return (0);
478 }
479
480 int
481 zx_intr(void *cookie)
482 {
483
484 return (1);
485 }
486
487 void
488 zx_reset(struct zx_softc *sc)
489 {
490 volatile struct zx_draw *zd;
491 volatile struct zx_command *zc;
492 struct fbtype *fbt;
493 u_int i;
494
495 zd = sc->sc_zd_ss0;
496 zc = sc->sc_zc;
497 fbt = &sc->sc_fb.fb_type;
498
499 zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0);
500 zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30);
501 zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20);
502 zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30);
503
504 i = sc->sc_zd_ss1->zd_misc;
505 i |= ZX_SS1_MISC_ENABLE;
506 SETREG(sc->sc_zd_ss1->zd_misc, i);
507
508 SETREG(zd->zd_wid, 0xffffffff);
509 SETREG(zd->zd_widclip, 0);
510 SETREG(zd->zd_wmask, 0xffff);
511 SETREG(zd->zd_vclipmin, 0);
512 SETREG(zd->zd_vclipmax,
513 (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 16));
514 SETREG(zd->zd_fg, 0);
515 SETREG(zd->zd_planemask, 0xff000000);
516 SETREG(zd->zd_rop, ZX_STD_ROP);
517
518 SETREG(zc->zc_extent,
519 (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 11));
520 SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR);
521 SETREG(zc->zc_fontt, 0);
522
523 for (i = 0; i < 256; i++) {
524 sc->sc_cmap[i] = rasops_cmap[i * 3];
525 sc->sc_cmap[i + 256] = rasops_cmap[i * 3 + 1];
526 sc->sc_cmap[i + 512] = rasops_cmap[i * 3 + 2];
527 }
528
529 zx_cmap_put(sc);
530 }
531
532 int
533 zx_cross_wait(struct zx_softc *sc)
534 {
535 volatile struct zx_cross *zx;
536 int i;
537
538 zx = sc->sc_zx;
539
540 for (i = 300000; i != 0; i--) {
541 if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0)
542 break;
543 DELAY(1);
544 }
545
546 if (i == 0)
547 printf("zx_cross_wait: timed out\n");
548
549 return (i);
550 }
551
552 int
553 zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value)
554 {
555 volatile struct zx_cross *zx;
556 u_int tmp = 0;
557
558 zx = sc->sc_zx;
559 SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
560
561 if (zx_cross_wait(sc))
562 return (1);
563
564 if (type == ZX_WID_DBL_8)
565 tmp = (index & 0x0f) + 0x40;
566 else if (type == ZX_WID_DBL_24)
567 tmp = index & 0x3f;
568
569 SETREG(zx->zx_type, 0x5800 + tmp);
570 SETREG(zx->zx_value, value);
571 SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
572 SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2);
573
574 return (0);
575 }
576
577 int
578 zx_cmap_put(struct zx_softc *sc)
579 {
580 volatile struct zx_cross *zx;
581 const u_char *b;
582 u_int i, t;
583
584 zx = sc->sc_zx;
585
586 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
587 if (zx_cross_wait(sc))
588 return (1);
589
590 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA);
591
592 for (i = 0, b = sc->sc_cmap; i < 256; i++) {
593 t = b[i];
594 t |= b[i + 256] << 8;
595 t |= b[i + 512] << 16;
596 SETREG(zx->zx_value, t);
597 }
598
599 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
600 i = zx->zx_csr;
601 i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2;
602 SETREG(zx->zx_csr, i);
603 return (0);
604 }
605
606 void
607 zx_cursor_move(struct zx_softc *sc)
608 {
609 volatile struct zx_cursor *zcu;
610 int sx, sy, x, y;
611
612 x = sc->sc_curpos.x - sc->sc_curhot.x;
613 y = sc->sc_curpos.y - sc->sc_curhot.y;
614 zcu = sc->sc_zcu;
615
616 if (x < 0) {
617 sx = min(-x, 32);
618 x = 0;
619 } else
620 sx = 0;
621
622 if (y < 0) {
623 sy = min(-y, 32);
624 y = 0;
625 } else
626 sy = 0;
627
628 if (sx != sc->sc_shiftx || sy != sc->sc_shifty) {
629 sc->sc_shiftx = sx;
630 sc->sc_shifty = sy;
631 zx_cursor_set(sc);
632 }
633
634 SETREG(zcu->zcu_sxy, ((y & 0x7ff) << 11) | (x & 0x7ff));
635 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x30);
636
637 /* XXX Necessary? */
638 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x80);
639 }
640
641 void
642 zx_cursor_set(struct zx_softc *sc)
643 {
644 volatile struct zx_cursor *zcu;
645 int i, j, data;
646
647 zcu = sc->sc_zcu;
648
649 if ((sc->sc_flags & ZX_CURSOR) != 0)
650 SETREG(zcu->zcu_misc, zcu->zcu_misc & ~0x80);
651
652 for (j = 0; j < 2; j++) {
653 SETREG(zcu->zcu_type, 0x20 << j);
654
655 for (i = sc->sc_shifty; i < 32; i++) {
656 data = sc->sc_curbits[j][i];
657 SETREG(zcu->zcu_data, data >> sc->sc_shiftx);
658 }
659 for (i = sc->sc_shifty; i != 0; i--)
660 SETREG(zcu->zcu_data, 0);
661 }
662
663 if ((sc->sc_flags & ZX_CURSOR) != 0)
664 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x80);
665 }
666
667 void
668 zx_cursor_blank(struct zx_softc *sc)
669 {
670 volatile struct zx_cursor *zcu;
671
672 sc->sc_flags &= ~ZX_CURSOR;
673 zcu = sc->sc_zcu;
674 SETREG(zcu->zcu_misc, zcu->zcu_misc & ~0x80);
675 }
676
677 void
678 zx_cursor_unblank(struct zx_softc *sc)
679 {
680 volatile struct zx_cursor *zcu;
681
682 sc->sc_flags |= ZX_CURSOR;
683 zcu = sc->sc_zcu;
684 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x80);
685 }
686
687 void
688 zx_cursor_color(struct zx_softc *sc)
689 {
690 volatile struct zx_cursor *zcu;
691 u_int8_t tmp;
692
693 zcu = sc->sc_zcu;
694
695 SETREG(zcu->zcu_type, 0x50);
696
697 tmp = sc->sc_curcmap[0] | (sc->sc_curcmap[2] << 8) |
698 (sc->sc_curcmap[4] << 16);
699 SETREG(zcu->zcu_data, tmp);
700
701 tmp = sc->sc_curcmap[1] | (sc->sc_curcmap[3] << 8) |
702 (sc->sc_curcmap[5] << 16);
703 SETREG(zcu->zcu_data, sc->sc_curcmap[1]);
704
705 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x03);
706 }
707
708 void
709 zx_blank(struct device *dv)
710 {
711 struct zx_softc *sc;
712 volatile struct zx_cross *zx;
713
714 sc = (struct zx_softc *)dv;
715
716 if ((sc->sc_flags & ZX_BLANKED) != 0)
717 return;
718 sc->sc_flags |= ZX_BLANKED;
719
720 zx = sc->sc_zx;
721 SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO);
722 SETREG(zx->zx_csr, zx->zx_csr & ~ZX_CROSS_CSR_ENABLE);
723 }
724
725 void
726 zx_unblank(struct device *dv)
727 {
728 struct zx_softc *sc;
729 volatile struct zx_cross *zx;
730
731 sc = (struct zx_softc *)dv;
732
733 if ((sc->sc_flags & ZX_BLANKED) == 0)
734 return;
735 sc->sc_flags &= ~ZX_BLANKED;
736
737 zx = sc->sc_zx;
738 SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO);
739 SETREG(zx->zx_csr, zx->zx_csr | ZX_CROSS_CSR_ENABLE);
740 }
741
742 paddr_t
743 zxmmap(dev_t dev, off_t off, int prot)
744 {
745 struct zx_softc *sc;
746 const struct zx_mmo *mm, *mmmax;
747
748 sc = device_lookup_private(&zx_cd, minor(dev));
749 off = trunc_page(off);
750 mm = zx_mmo;
751 mmmax = mm + sizeof(zx_mmo) / sizeof(zx_mmo[0]);
752
753 for (; mm < mmmax; mm++)
754 if (off >= mm->mo_va && off < mm->mo_va + mm->mo_size) {
755 off = off - mm->mo_va + mm->mo_pa;
756 return (bus_space_mmap(sc->sc_bt, sc->sc_paddr,
757 off, prot, BUS_SPACE_MAP_LINEAR));
758 }
759
760 return (-1);
761 }
762
763 void
764 zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, long attr,
765 int rop)
766 {
767 struct zx_softc *sc;
768 volatile struct zx_command *zc;
769 volatile struct zx_draw *zd;
770 int fg, bg;
771
772 sc = ri->ri_hw;
773 zc = sc->sc_zc;
774 zd = sc->sc_zd_ss0;
775
776 rasops_unpack_attr(attr, &fg, &bg, NULL);
777 x = x * sc->sc_fontw + ri->ri_xorigin;
778 y = y * sc->sc_fonth + ri->ri_yorigin;
779 w = sc->sc_fontw * w - 1;
780 h = sc->sc_fonth * h - 1;
781
782 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
783 ;
784
785 SETREG(zd->zd_rop, rop);
786 SETREG(zd->zd_fg, (bg & 7) ? 0x00000000 : 0xff000000);
787 SETREG(zc->zc_extent, w | (h << 11));
788 SETREG(zc->zc_fill, x | (y << 11) | 0x80000000);
789 }
790
791 void
792 zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w,
793 int h)
794 {
795 struct zx_softc *sc;
796 volatile struct zx_command *zc;
797 volatile struct zx_draw *zd;
798 int dir;
799
800 sc = ri->ri_hw;
801 zc = sc->sc_zc;
802 zd = sc->sc_zd_ss0;
803
804 sx = sx * sc->sc_fontw + ri->ri_xorigin;
805 sy = sy * sc->sc_fonth + ri->ri_yorigin;
806 dx = dx * sc->sc_fontw + ri->ri_xorigin;
807 dy = dy * sc->sc_fonth + ri->ri_yorigin;
808 w = w * sc->sc_fontw - 1;
809 h = h * sc->sc_fonth - 1;
810
811 if (sy < dy || sx < dx) {
812 dir = 0x80000000;
813 sx += w;
814 sy += h;
815 dx += w;
816 dy += h;
817 } else
818 dir = 0;
819
820 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
821 ;
822
823 SETREG(zd->zd_rop, ZX_STD_ROP);
824 SETREG(zc->zc_extent, w | (h << 11) | dir);
825 SETREG(zc->zc_src, sx | (sy << 11));
826 SETREG(zc->zc_copy, dx | (dy << 11));
827 }
828
829 void
830 zx_do_cursor(struct rasops_info *ri)
831 {
832
833 zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, 0,
834 ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
835 ZX_ATTR_FORCE_WID);
836 }
837
838 void
839 zx_erasecols(void *cookie, int row, int col, int num, long attr)
840 {
841 struct rasops_info *ri;
842
843 ri = (struct rasops_info *)cookie;
844
845 zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP);
846 }
847
848 void
849 zx_eraserows(void *cookie, int row, int num, long attr)
850 {
851 struct rasops_info *ri;
852
853 ri = (struct rasops_info *)cookie;
854
855 zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP);
856 }
857
858 void
859 zx_copyrows(void *cookie, int src, int dst, int num)
860 {
861 struct rasops_info *ri;
862
863 ri = (struct rasops_info *)cookie;
864
865 zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num);
866 }
867
868 void
869 zx_copycols(void *cookie, int row, int src, int dst, int num)
870 {
871 struct rasops_info *ri;
872
873 ri = (struct rasops_info *)cookie;
874
875 zx_copyrect(ri, src, row, dst, row, num, 1);
876 }
877
878 void
879 zx_putchar(void *cookie, int row, int col, u_int uc, long attr)
880 {
881 struct rasops_info *ri;
882 struct zx_softc *sc;
883 struct wsdisplay_font *font;
884 volatile struct zx_command *zc;
885 volatile struct zx_draw *zd;
886 volatile u_int32_t *dp;
887 u_int8_t *fb;
888 int fs, i, fg, bg, ul;
889
890 ri = (struct rasops_info *)cookie;
891
892 if (uc == ' ') {
893 zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP);
894 return;
895 }
896
897 sc = (struct zx_softc *)ri->ri_hw;
898 font = ri->ri_font;
899 zc = sc->sc_zc;
900 zd = sc->sc_zd_ss0;
901
902 dp = (volatile u_int32_t *)sc->sc_pixels +
903 ((row * sc->sc_fonth + ri->ri_yorigin) << 11) +
904 (col * sc->sc_fontw + ri->ri_xorigin);
905 fb = (u_int8_t *)font->data + (uc - font->firstchar) *
906 ri->ri_fontscale;
907 fs = font->stride;
908 rasops_unpack_attr(attr, &fg, &bg, &ul);
909
910 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
911 ;
912
913 SETREG(zd->zd_rop, ZX_STD_ROP);
914 SETREG(zd->zd_fg, (fg & 7) ? 0x00000000 : 0xff000000);
915 SETREG(zd->zd_bg, (bg & 7) ? 0x00000000 : 0xff000000);
916 SETREG(zc->zc_fontmsk, 0xffffffff << (32 - sc->sc_fontw));
917
918 if (sc->sc_fontw <= 8) {
919 for (i = sc->sc_fonth; i != 0; i--, dp += 2048) {
920 *dp = *fb << 24;
921 fb += fs;
922 }
923 } else {
924 for (i = sc->sc_fonth; i != 0; i--, dp += 2048) {
925 *dp = *((u_int16_t *)fb) << 16;
926 fb += fs;
927 }
928 }
929
930 if (ul) {
931 dp -= 4096;
932 *dp = 0xffffffff;
933 }
934 }
935