1 /* $NetBSD: zx.c,v 1.34 2010/01/05 04:17:49 macallan Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
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
38 * Issues (which can be solved with wscons, happily enough):
40 * o There is lots of unnecessary mucking about rasops in here, primarily
41 * to appease the sparc fb code.
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.
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: zx.c,v 1.34 2010/01/05 04:17:49 macallan Exp $");
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>
58 #include <sys/syslog.h>
62 #include <machine/autoconf.h>
64 #include <uvm/uvm_extern.h>
66 #include <dev/sun/fbio.h>
67 #include <dev/sun/fbvar.h>
69 #include "wsdisplay.h"
71 #include <dev/wscons/wsconsio.h>
72 #include <dev/wsfont/wsfont.h>
73 #include <dev/rasops/rasops.h>
74 #include <dev/wscons/wsdisplay_vconsvar.h>
76 #include "opt_wsemul.h"
79 #include <dev/sbus/zxreg.h>
80 #include <dev/sbus/zxvar.h>
81 #include <dev/sbus/sbusvar.h>
83 #include <dev/wscons/wsconsio.h>
87 #if (NWSDISPLAY == 0) && !defined(RASTERCONSOLE)
88 #error Sorry, this driver needs WSCONS or RASTERCONSOLE
91 #if (NWSDISPLAY > 0) && defined(RASTERCONSOLE)
92 #error Sorry, RASTERCONSOLE and WSCONS are mutually exclusive
95 #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
96 ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
98 static void zx_attach(device_t
, device_t
, void *);
99 static int zx_match(device_t
, cfdata_t
, void *);
101 static void zx_blank(device_t
);
102 static int zx_cmap_put(struct zx_softc
*);
103 static void zx_copyrect(struct zx_softc
*, int, int, int, int, int, int);
104 static int zx_cross_loadwid(struct zx_softc
*, u_int
, u_int
, u_int
);
105 static int zx_cross_wait(struct zx_softc
*);
106 static void zx_fillrect(struct zx_softc
*, int, int, int, int, uint32_t, int);
107 static int zx_intr(void *);
108 static void zx_reset(struct zx_softc
*);
109 static void zx_unblank(device_t
);
111 static void zx_cursor_blank(struct zx_softc
*);
112 static void zx_cursor_color(struct zx_softc
*);
113 static void zx_cursor_move(struct zx_softc
*);
114 static void zx_cursor_set(struct zx_softc
*);
115 static void zx_cursor_unblank(struct zx_softc
*);
117 static void zx_copycols(void *, int, int, int, int);
118 static void zx_copyrows(void *, int, int, int);
119 static void zx_do_cursor(void *, int, int, int);
120 static void zx_erasecols(void *, int, int, int, long);
121 static void zx_eraserows(void *, int, int, long);
122 static void zx_putchar(void *, int, int, u_int
, long);
128 } static const zx_mmo
[] = {
129 { ZX_FB0_VOFF
, ZX_OFF_SS0
, 0x00800000 },
130 { ZX_LC0_VOFF
, ZX_OFF_LC_SS0_USR
, 0x00001000 },
131 { ZX_LD0_VOFF
, ZX_OFF_LD_SS0
, 0x00001000 },
132 { ZX_LX0_CURSOR_VOFF
, ZX_OFF_LX_CURSOR
, 0x00001000 },
133 { ZX_FB1_VOFF
, ZX_OFF_SS1
, 0x00800000 },
134 { ZX_LC1_VOFF
, ZX_OFF_LC_SS1_USR
, 0x00001000 },
135 { ZX_LD1_VOFF
, ZX_OFF_LD_SS1
, 0x00001000 },
136 { ZX_LX_KRN_VOFF
, ZX_OFF_LX_CROSS
, 0x00001000 },
137 { ZX_LC0_KRN_VOFF
, ZX_OFF_LC_SS0_KRN
, 0x00001000 },
138 { ZX_LC1_KRN_VOFF
, ZX_OFF_LC_SS1_KRN
, 0x00001000 },
139 { ZX_LD_GBL_VOFF
, ZX_OFF_LD_GBL
, 0x00001000 },
142 CFATTACH_DECL_NEW(zx
, sizeof(struct zx_softc
),
143 zx_match
, zx_attach
, NULL
, NULL
);
145 static dev_type_open(zxopen
);
146 static dev_type_close(zxclose
);
147 static dev_type_ioctl(zxioctl
);
148 static dev_type_mmap(zxmmap
);
150 static struct fbdriver zx_fbdriver
= {
151 zx_unblank
, zxopen
, zxclose
, zxioctl
, nopoll
, zxmmap
155 struct wsscreen_descr zx_defaultscreen
= {
157 0, 0, /* will be filled in -- XXX shouldn't, it's global */
158 /* doesn't matter - you can't really have more than one leo */
160 8, 16, /* font width/height */
161 WSSCREEN_WSCOLORS
, /* capabilities */
162 NULL
/* modecookie */
165 static int zx_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
166 static paddr_t
zx_mmap(void *, void *, off_t
, int);
167 static void zx_init_screen(void *, struct vcons_screen
*, int, long *);
169 static int zx_putcmap(struct zx_softc
*, struct wsdisplay_cmap
*);
170 static int zx_getcmap(struct zx_softc
*, struct wsdisplay_cmap
*);
172 struct wsdisplay_accessops zx_accessops
= {
175 NULL
, /* alloc_screen */
176 NULL
, /* free_screen */
177 NULL
, /* show_screen */
178 NULL
, /* load_font */
183 const struct wsscreen_descr
*_zx_scrlist
[] = {
187 struct wsscreen_list zx_screenlist
= {
188 sizeof(_zx_scrlist
) / sizeof(struct wsscreen_descr
*),
193 extern const u_char rasops_cmap
[768];
195 static struct vcons_screen zx_console_screen
;
196 #endif /* NWSDISPLAY > 0 */
199 zx_match(device_t parent
, cfdata_t cf
, void *aux
)
201 struct sbus_attach_args
*sa
;
203 sa
= (struct sbus_attach_args
*)aux
;
205 return (strcmp(sa
->sa_name
, "SUNW,leo") == 0);
209 zx_attach(device_t parent
, device_t self
, void *args
)
212 struct sbus_attach_args
*sa
;
213 bus_space_handle_t bh
;
217 struct wsemuldisplaydev_attach_args aa
;
218 struct rasops_info
*ri
= &zx_console_screen
.scr_ri
;
219 unsigned long defattr
;
221 int isconsole
, width
, height
;
223 sc
= device_private(self
);
230 sc
->sc_paddr
= sbus_bus_addr(bt
, sa
->sa_slot
, sa
->sa_offset
);
232 if (sbus_bus_map(bt
, sa
->sa_slot
, sa
->sa_offset
+ ZX_OFF_SS0
,
233 0x800000, BUS_SPACE_MAP_LINEAR
| BUS_SPACE_MAP_LARGE
, &bh
) != 0) {
234 aprint_error_dev(self
, "can't map bits\n");
237 fb
->fb_pixels
= (void *)bus_space_vaddr(bt
, bh
);
238 sc
->sc_pixels
= (uint32_t *)fb
->fb_pixels
;
240 if (sbus_bus_map(bt
, sa
->sa_slot
, sa
->sa_offset
+ ZX_OFF_LC_SS0_USR
,
241 PAGE_SIZE
, BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
242 aprint_error_dev(self
, "can't map zc\n");
248 if (sbus_bus_map(bt
, sa
->sa_slot
, sa
->sa_offset
+ ZX_OFF_LD_SS0
,
249 PAGE_SIZE
, BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
250 aprint_error_dev(self
, "can't map ld/ss0\n");
255 if (sbus_bus_map(bt
, sa
->sa_slot
, sa
->sa_offset
+ ZX_OFF_LD_SS1
,
256 PAGE_SIZE
, BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
257 aprint_error_dev(self
, "can't map ld/ss1\n");
262 if (sbus_bus_map(bt
, sa
->sa_slot
, sa
->sa_offset
+ ZX_OFF_LX_CROSS
,
263 PAGE_SIZE
, BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
264 aprint_error_dev(self
, "can't map zx\n");
269 if (sbus_bus_map(bt
, sa
->sa_slot
, sa
->sa_offset
+ ZX_OFF_LX_CURSOR
,
270 PAGE_SIZE
, BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
271 aprint_error_dev(self
, "can't map zcu\n");
276 fb
->fb_driver
= &zx_fbdriver
;
277 fb
->fb_device
= sc
->sc_dv
;
278 fb
->fb_flags
= device_cfdata(sc
->sc_dv
)->cf_flags
& FB_USERMASK
;
280 fb
->fb_linebytes
= prom_getpropint(sa
->sa_node
, "linebytes", 8192);
282 width
= prom_getpropint(sa
->sa_node
, "width", 1280);
283 height
= prom_getpropint(sa
->sa_node
, "height", 1024);
284 fb_setsize_obp(fb
, 32, width
, height
, sa
->sa_node
);
286 fb
->fb_type
.fb_cmsize
= 256;
287 fb
->fb_type
.fb_depth
= 32;
288 fb
->fb_type
.fb_size
= fb
->fb_type
.fb_height
* fb
->fb_linebytes
;
289 fb
->fb_type
.fb_type
= FBTYPE_SUNLEO
;
291 printf(": %d x %d", fb
->fb_type
.fb_width
, fb
->fb_type
.fb_height
);
292 isconsole
= fb_is_console(sa
->sa_node
);
294 printf(" (console)");
297 if (sa
->sa_nintr
!= 0)
298 bus_intr_establish(bt
, sa
->sa_pri
, IPL_NONE
, zx_intr
, sc
);
300 sc
->sc_cmap
= malloc(768, M_DEVBUF
, M_NOWAIT
);
304 sc
->sc_width
= fb
->fb_type
.fb_width
;
305 sc
->sc_stride
= 8192; /* 32 bit */
306 sc
->sc_height
= fb
->fb_type
.fb_height
;
308 /* setup rasops and so on for wsdisplay */
310 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
311 sc
->sc_bg
= WS_DEFAULT_BG
;
313 vcons_init(&sc
->vd
, sc
, &zx_defaultscreen
, &zx_accessops
);
314 sc
->vd
.init_screen
= zx_init_screen
;
317 /* we mess with zx_console_screen only once */
318 vcons_init_screen(&sc
->vd
, &zx_console_screen
, 1,
320 zx_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
322 zx_defaultscreen
.textops
= &ri
->ri_ops
;
323 zx_defaultscreen
.capabilities
= WSSCREEN_WSCOLORS
;
324 zx_defaultscreen
.nrows
= ri
->ri_rows
;
325 zx_defaultscreen
.ncols
= ri
->ri_cols
;
326 zx_fillrect(sc
, 0, 0, width
, height
,
327 ri
->ri_devcmap
[defattr
>> 16], ZX_STD_ROP
);
328 wsdisplay_cnattach(&zx_defaultscreen
, ri
, 0, 0, defattr
);
329 vcons_replay_msgbuf(&zx_console_screen
);
332 * we're not the console so we just clear the screen and don't
333 * set up any sort of text display
335 if (zx_defaultscreen
.textops
== NULL
) {
338 * we want the console settings to win, so we only
339 * touch anything when we find an untouched screen
340 * definition. In this case we fill it from fb to
341 * avoid problems in case no zx is the console
343 ri
= &sc
->sc_fb
.fb_rinfo
;
344 zx_defaultscreen
.textops
= &ri
->ri_ops
;
345 zx_defaultscreen
.capabilities
= ri
->ri_caps
;
346 zx_defaultscreen
.nrows
= ri
->ri_rows
;
347 zx_defaultscreen
.ncols
= ri
->ri_cols
;
351 aa
.scrdata
= &zx_screenlist
;
352 aa
.console
= isconsole
;
353 aa
.accessops
= &zx_accessops
;
354 aa
.accesscookie
= &sc
->vd
;
355 config_found(sc
->sc_dv
, &aa
, wsemuldisplaydevprint
);
357 fb_attach(&sc
->sc_fb
, isconsole
);
361 zxopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
364 if (device_lookup(&zx_cd
, minor(dev
)) == NULL
)
370 zxclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
374 sc
= device_lookup_private(&zx_cd
, minor(dev
));
382 zxioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
387 uint32_t curbits
[2][32];
390 sc
= device_lookup_private(&zx_cd
, minor(dev
));
394 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
398 #define fba ((struct fbgattr *)data)
399 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
400 fba
->owner
= 0; /* XXX ??? */
401 fba
->fbtype
= sc
->sc_fb
.fb_type
;
402 fba
->sattr
.flags
= 0;
403 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
404 fba
->sattr
.dev_specific
[0] = -1;
405 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
406 fba
->emu_types
[1] = -1;
407 fba
->emu_types
[2] = -1;
412 *(int *)data
= ((sc
->sc_flags
& ZX_BLANKED
) != 0);
417 zx_unblank(sc
->sc_dv
);
423 cm
= (struct fbcmap
*)data
;
424 if (cm
->index
> 256 || cm
->count
> 256 - cm
->index
)
426 rv
= copyout(sc
->sc_cmap
+ cm
->index
, cm
->red
, cm
->count
);
428 rv
= copyout(sc
->sc_cmap
+ 256 + cm
->index
, cm
->green
,
431 rv
= copyout(sc
->sc_cmap
+ 512 + cm
->index
, cm
->blue
,
436 cm
= (struct fbcmap
*)data
;
437 if (cm
->index
> 256 || cm
->count
> 256 - cm
->index
)
439 rv
= copyin(cm
->red
, sc
->sc_cmap
+ cm
->index
, cm
->count
);
441 rv
= copyin(cm
->green
, sc
->sc_cmap
+ 256 + cm
->index
,
444 rv
= copyin(cm
->blue
, sc
->sc_cmap
+ 512 + cm
->index
,
450 *(struct fbcurpos
*)data
= sc
->sc_curpos
;
454 sc
->sc_curpos
= *(struct fbcurpos
*)data
;
459 ((struct fbcurpos
*)data
)->x
= 32;
460 ((struct fbcurpos
*)data
)->y
= 32;
464 cu
= (struct fbcursor
*)data
;
467 if ((v
& FB_CUR_SETSHAPE
) != 0) {
468 if ((u_int
)cu
->size
.x
> 32 || (u_int
)cu
->size
.y
> 32)
470 count
= cu
->size
.y
* 4;
471 rv
= copyin(cu
->mask
, curbits
[0], count
);
474 rv
= copyin(cu
->image
, curbits
[1], count
);
478 if ((v
& FB_CUR_SETCUR
) != 0) {
480 zx_cursor_unblank(sc
);
484 if ((v
& (FB_CUR_SETPOS
| FB_CUR_SETHOT
)) != 0) {
485 if ((v
& FB_CUR_SETPOS
) != 0)
486 sc
->sc_curpos
= cu
->pos
;
487 if ((v
& FB_CUR_SETHOT
) != 0)
488 sc
->sc_curhot
= cu
->hot
;
491 if ((v
& FB_CUR_SETCMAP
) != 0) {
492 if (cu
->cmap
.index
> 2 ||
493 cu
->cmap
.count
> 2 - cu
->cmap
.index
)
495 for (i
= 0; i
< cu
->cmap
.count
; i
++) {
496 if ((v
= fubyte(&cu
->cmap
.red
[i
])) < 0)
498 sc
->sc_curcmap
[i
+ cu
->cmap
.index
+ 0] = v
;
499 if ((v
= fubyte(&cu
->cmap
.green
[i
])) < 0)
501 sc
->sc_curcmap
[i
+ cu
->cmap
.index
+ 2] = v
;
502 if ((v
= fubyte(&cu
->cmap
.blue
[i
])) < 0)
504 sc
->sc_curcmap
[i
+ cu
->cmap
.index
+ 4] = v
;
508 if ((v
& FB_CUR_SETSHAPE
) != 0) {
509 sc
->sc_cursize
= cu
->size
;
510 count
= cu
->size
.y
* 4;
511 memset(sc
->sc_curbits
, 0, sizeof(sc
->sc_curbits
));
512 memcpy(sc
->sc_curbits
[0], curbits
[0], count
);
513 memcpy(sc
->sc_curbits
[1], curbits
[1], count
);
519 cu
= (struct fbcursor
*)data
;
521 cu
->set
= FB_CUR_SETALL
;
522 cu
->enable
= ((sc
->sc_flags
& ZX_CURSOR
) != 0);
523 cu
->pos
= sc
->sc_curpos
;
524 cu
->hot
= sc
->sc_curhot
;
525 cu
->size
= sc
->sc_cursize
;
527 if (cu
->image
!= NULL
) {
528 count
= sc
->sc_cursize
.y
* 4;
529 rv
= copyout(sc
->sc_curbits
[1], cu
->image
, count
);
532 rv
= copyout(sc
->sc_curbits
[0], cu
->mask
, count
);
536 if (cu
->cmap
.red
!= NULL
) {
537 if (cu
->cmap
.index
> 2 ||
538 cu
->cmap
.count
> 2 - cu
->cmap
.index
)
540 for (i
= 0; i
< cu
->cmap
.count
; i
++) {
541 v
= sc
->sc_curcmap
[i
+ cu
->cmap
.index
+ 0];
542 if (subyte(&cu
->cmap
.red
[i
], v
))
544 v
= sc
->sc_curcmap
[i
+ cu
->cmap
.index
+ 2];
545 if (subyte(&cu
->cmap
.green
[i
], v
))
547 v
= sc
->sc_curcmap
[i
+ cu
->cmap
.index
+ 4];
548 if (subyte(&cu
->cmap
.blue
[i
], v
))
559 log(LOG_NOTICE
, "zxioctl(0x%lx) (%s[%d])\n", cmd
,
560 l
->l_proc
->p_comm
, l
->l_proc
->p_pid
);
569 zx_intr(void *cookie
)
576 zx_reset(struct zx_softc
*sc
)
581 fbt
= &sc
->sc_fb
.fb_type
;
583 zx_cross_loadwid(sc
, ZX_WID_DBL_8
, 0, 0x2c0);
584 zx_cross_loadwid(sc
, ZX_WID_DBL_8
, 1, 0x30);
585 zx_cross_loadwid(sc
, ZX_WID_DBL_8
, 2, 0x20);
586 zx_cross_loadwid(sc
, ZX_WID_DBL_24
, 1, 0x30);
588 i
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzdss1
, zd_misc
);
589 i
|= ZX_SS1_MISC_ENABLE
;
590 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss1
, zd_misc
, i
);
592 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_wid
, 1);
593 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_widclip
, 0);
594 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_wmask
, 0xffff);
595 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_vclipmin
, 0);
596 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_vclipmax
,
597 (fbt
->fb_width
- 1) | ((fbt
->fb_height
- 1) << 16));
598 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_fg
, 0);
599 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_planemask
, 0xffffffff);
600 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_rop
, ZX_STD_ROP
);
602 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_extent
,
603 (fbt
->fb_width
- 1) | ((fbt
->fb_height
- 1) << 11));
604 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_addrspace
,
605 ZX_ADDRSPC_FONT_OBGR
);
606 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_fontt
, 0);
608 for (i
= 0; i
< 256; i
++) {
609 sc
->sc_cmap
[i
] = rasops_cmap
[i
* 3];
610 sc
->sc_cmap
[i
+ 256] = rasops_cmap
[i
* 3 + 1];
611 sc
->sc_cmap
[i
+ 512] = rasops_cmap
[i
* 3 + 2];
618 zx_cross_wait(struct zx_softc
*sc
)
622 for (i
= 300000; i
!= 0; i
--) {
623 if ((bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
) &
624 ZX_CROSS_CSR_PROGRESS
) == 0)
630 printf("zx_cross_wait: timed out\n");
636 zx_cross_loadwid(struct zx_softc
*sc
, u_int type
, u_int index
, u_int value
)
640 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, ZX_CROSS_TYPE_WID
);
642 if (zx_cross_wait(sc
))
645 if (type
== ZX_WID_DBL_8
)
646 tmp
= (index
& 0x0f) + 0x40;
647 else if (type
== ZX_WID_DBL_24
)
650 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, 0x5800 + tmp
);
651 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_value
, value
);
652 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, ZX_CROSS_TYPE_WID
);
653 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
,
654 ZX_CROSS_CSR_UNK
| ZX_CROSS_CSR_UNK2
);
660 zx_cmap_put(struct zx_softc
*sc
)
665 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, ZX_CROSS_TYPE_CLUT0
);
669 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
,
670 ZX_CROSS_TYPE_CLUTDATA
);
672 for (i
= 0, b
= sc
->sc_cmap
; i
< 256; i
++) {
674 t
|= b
[i
+ 256] << 8;
675 t
|= b
[i
+ 512] << 16;
676 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_value
, t
);
679 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, ZX_CROSS_TYPE_CLUT0
);
680 i
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
);
681 i
= i
| ZX_CROSS_CSR_UNK
| ZX_CROSS_CSR_UNK2
;
682 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
, i
);
687 zx_cursor_move(struct zx_softc
*sc
)
691 x
= sc
->sc_curpos
.x
- sc
->sc_curhot
.x
;
692 y
= sc
->sc_curpos
.y
- sc
->sc_curhot
.y
;
706 if (sx
!= sc
->sc_shiftx
|| sy
!= sc
->sc_shifty
) {
712 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_sxy
,
713 ((y
& 0x7ff) << 11) | (x
& 0x7ff));
714 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
715 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) | 0x30);
718 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
719 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) | 0x80);
723 zx_cursor_set(struct zx_softc
*sc
)
727 if ((sc
->sc_flags
& ZX_CURSOR
) != 0)
728 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
729 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) &
732 for (j
= 0; j
< 2; j
++) {
733 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_type
, 0x20 << j
);
735 for (i
= sc
->sc_shifty
; i
< 32; i
++) {
736 data
= sc
->sc_curbits
[j
][i
];
737 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_data
,
738 data
>> sc
->sc_shiftx
);
740 for (i
= sc
->sc_shifty
; i
!= 0; i
--)
741 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_data
, 0);
744 if ((sc
->sc_flags
& ZX_CURSOR
) != 0)
745 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
746 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) | 0x80);
750 zx_cursor_blank(struct zx_softc
*sc
)
753 sc
->sc_flags
&= ~ZX_CURSOR
;
754 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
755 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) & ~0x80);
759 zx_cursor_unblank(struct zx_softc
*sc
)
762 sc
->sc_flags
|= ZX_CURSOR
;
763 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
764 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) | 0x80);
768 zx_cursor_color(struct zx_softc
*sc
)
772 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_type
, 0x50);
774 tmp
= sc
->sc_curcmap
[0] | (sc
->sc_curcmap
[2] << 8) |
775 (sc
->sc_curcmap
[4] << 16);
776 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_data
, tmp
);
778 tmp
= sc
->sc_curcmap
[1] | (sc
->sc_curcmap
[3] << 8) |
779 (sc
->sc_curcmap
[5] << 16);
780 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_data
, sc
->sc_curcmap
[1]);
782 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
,
783 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzcu
, zcu_misc
) | 0x03);
787 zx_blank(device_t dv
)
791 sc
= device_private(dv
);
793 if ((sc
->sc_flags
& ZX_BLANKED
) != 0)
795 sc
->sc_flags
|= ZX_BLANKED
;
797 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, ZX_CROSS_TYPE_VIDEO
);
798 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
,
799 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
) &
800 ~ZX_CROSS_CSR_ENABLE
);
804 zx_unblank(device_t dv
)
808 sc
= device_private(dv
);
810 if ((sc
->sc_flags
& ZX_BLANKED
) == 0)
812 sc
->sc_flags
&= ~ZX_BLANKED
;
814 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_type
, ZX_CROSS_TYPE_VIDEO
);
815 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
,
816 bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzx
, zx_csr
) |
817 ZX_CROSS_CSR_ENABLE
);
821 zxmmap(dev_t dev
, off_t off
, int prot
)
824 const struct zx_mmo
*mm
, *mmmax
;
826 sc
= device_lookup_private(&zx_cd
, minor(dev
));
827 off
= trunc_page(off
);
829 mmmax
= mm
+ sizeof(zx_mmo
) / sizeof(zx_mmo
[0]);
831 for (; mm
< mmmax
; mm
++)
832 if (off
>= mm
->mo_va
&& off
< mm
->mo_va
+ mm
->mo_size
) {
833 off
= off
- mm
->mo_va
+ mm
->mo_pa
;
834 return (bus_space_mmap(sc
->sc_bt
, sc
->sc_paddr
,
835 off
, prot
, BUS_SPACE_MAP_LINEAR
));
842 zx_fillrect(struct zx_softc
*sc
, int x
, int y
, int w
, int h
, uint32_t bg
,
847 while ((bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_csr
) &
848 ZX_CSR_BLT_BUSY
) != 0)
851 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_rop
, rop
);
852 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_fg
, bg
);
853 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_extent
,
854 (w
- 1) | ((h
- 1) << 11));
855 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_fill
,
856 x
| (y
<< 11) | 0x80000000);
860 zx_copyrect(struct zx_softc
*sc
, int sx
, int sy
, int dx
, int dy
, int w
,
868 if (sy
< dy
|| sx
< dx
) {
877 while ((bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_csr
) &
878 ZX_CSR_BLT_BUSY
) != 0)
881 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_rop
, ZX_STD_ROP
);
882 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_extent
,
883 w
| (h
<< 11) | dir
);
884 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_src
, sx
| (sy
<< 11));
885 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_copy
, dx
| (dy
<< 11));
889 zx_do_cursor(void *cookie
, int on
, int row
, int col
)
891 struct rasops_info
*ri
= cookie
;
892 struct vcons_screen
*scr
= ri
->ri_hw
;
893 struct zx_softc
*sc
= scr
->scr_cookie
;
896 wi
= ri
->ri_font
->fontwidth
;
897 he
= ri
->ri_font
->fontheight
;
899 if (ri
->ri_flg
& RI_CURSOR
) {
900 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
901 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
902 zx_fillrect(sc
, x
, y
, wi
, he
, 0xff000000,
903 ZX_ROP_NEW_XOR_OLD
| ZX_ATTR_WE_ENABLE
| ZX_ATTR_OE_ENABLE
|
905 ri
->ri_flg
&= ~RI_CURSOR
;
913 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
914 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
915 zx_fillrect(sc
, x
, y
, wi
, he
, 0xff000000,
916 ZX_ROP_NEW_XOR_OLD
| ZX_ATTR_WE_ENABLE
| ZX_ATTR_OE_ENABLE
|
918 ri
->ri_flg
|= RI_CURSOR
;
923 zx_erasecols(void *cookie
, int row
, int startcol
, int ncols
, long attr
)
925 struct rasops_info
*ri
= cookie
;
926 struct vcons_screen
*scr
= ri
->ri_hw
;
927 struct zx_softc
*sc
= scr
->scr_cookie
;
928 int32_t x
, y
, width
, height
, bg
;
930 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* startcol
;
931 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
932 width
= ri
->ri_font
->fontwidth
* ncols
;
933 height
= ri
->ri_font
->fontheight
;
934 bg
= ((uint32_t)ri
->ri_devcmap
[(attr
>> 16) & 0xff]) << 24;
935 zx_fillrect(sc
, x
, y
, width
, height
, bg
, ZX_STD_ROP
);
939 zx_eraserows(void *cookie
, int row
, int nrows
, long attr
)
941 struct rasops_info
*ri
= cookie
;
942 struct vcons_screen
*scr
= ri
->ri_hw
;
943 struct zx_softc
*sc
= scr
->scr_cookie
;
944 int32_t x
, y
, width
, height
, bg
;
946 if ((row
== 0) && (nrows
== ri
->ri_rows
)) {
948 width
= ri
->ri_width
;
949 height
= ri
->ri_height
;
952 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
953 width
= ri
->ri_emuwidth
;
954 height
= ri
->ri_font
->fontheight
* nrows
;
956 bg
= ((uint32_t)ri
->ri_devcmap
[(attr
>> 16) & 0xff]) << 24;
957 zx_fillrect(sc
, x
, y
, width
, height
, bg
, ZX_STD_ROP
);
961 zx_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
963 struct rasops_info
*ri
= cookie
;
964 struct vcons_screen
*scr
= ri
->ri_hw
;
965 struct zx_softc
*sc
= scr
->scr_cookie
;
966 int32_t x
, ys
, yd
, width
, height
;
969 ys
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* srcrow
;
970 yd
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* dstrow
;
971 width
= ri
->ri_emuwidth
;
972 height
= ri
->ri_font
->fontheight
* nrows
;
973 zx_copyrect(sc
, x
, ys
, x
, yd
, width
, height
);
977 zx_copycols(void *cookie
, int row
, int srccol
, int dstcol
, int ncols
)
979 struct rasops_info
*ri
= cookie
;
980 struct vcons_screen
*scr
= ri
->ri_hw
;
981 struct zx_softc
*sc
= scr
->scr_cookie
;
982 int32_t xs
, xd
, y
, width
, height
;
984 xs
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* srccol
;
985 xd
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* dstcol
;
986 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
987 width
= ri
->ri_font
->fontwidth
* ncols
;
988 height
= ri
->ri_font
->fontheight
;
989 zx_copyrect(sc
, xs
, y
, xd
, y
, width
, height
);
993 zx_putchar(void *cookie
, int row
, int col
, u_int uc
, long attr
)
995 struct rasops_info
*ri
= cookie
;
996 struct vcons_screen
*scr
= ri
->ri_hw
;
997 struct zx_softc
*sc
= scr
->scr_cookie
;
998 struct wsdisplay_font
*font
;
999 volatile uint32_t *dp
;
1004 rasops_unpack_attr(attr
, &fg
, &bg
, &ul
);
1005 bg
= ((uint32_t)ri
->ri_devcmap
[bg
]) << 24;
1006 fg
= ((uint32_t)ri
->ri_devcmap
[fg
]) << 24;
1010 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* col
;
1011 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1012 zx_fillrect(sc
, x
, y
, ri
->ri_font
->fontwidth
,
1013 ri
->ri_font
->fontheight
, bg
, ZX_STD_ROP
);
1019 dp
= (volatile uint32_t *)sc
->sc_pixels
+
1020 ((row
* font
->fontheight
+ ri
->ri_yorigin
) << 11) +
1021 (col
* font
->fontwidth
+ ri
->ri_xorigin
);
1022 fb
= (uint8_t *)font
->data
+ (uc
- font
->firstchar
) *
1026 while ((bus_space_read_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_csr
) &
1027 ZX_CSR_BLT_BUSY
) != 0)
1030 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_rop
, ZX_STD_ROP
);
1031 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_fg
, fg
);
1032 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzdss0
, zd_bg
, bg
);
1033 bus_space_write_4(sc
->sc_bt
, sc
->sc_bhzc
, zc_fontmsk
,
1034 0xffffffff << (32 - font
->fontwidth
));
1036 if (font
->fontwidth
<= 8) {
1037 for (i
= font
->fontheight
; i
!= 0; i
--, dp
+= 2048) {
1042 for (i
= font
->fontheight
; i
!= 0; i
--, dp
+= 2048) {
1043 *dp
= *((uint16_t *)fb
) << 16;
1056 zx_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
1059 /* we'll probably need to add more stuff here */
1060 struct vcons_data
*vd
= v
;
1061 struct zx_softc
*sc
= vd
->cookie
;
1062 struct wsdisplay_fbinfo
*wdf
;
1063 struct rasops_info
*ri
= &sc
->sc_fb
.fb_rinfo
;
1064 struct vcons_screen
*ms
= sc
->vd
.active
;
1066 case WSDISPLAYIO_GTYPE
:
1067 *(u_int
*)data
= WSDISPLAY_TYPE_SUNTCX
;
1069 case WSDISPLAYIO_GINFO
:
1071 wdf
->height
= ri
->ri_height
;
1072 wdf
->width
= ri
->ri_width
;
1073 wdf
->depth
= ri
->ri_depth
;
1077 case WSDISPLAYIO_GETCMAP
:
1078 return zx_getcmap(sc
,
1079 (struct wsdisplay_cmap
*)data
);
1080 case WSDISPLAYIO_PUTCMAP
:
1081 return zx_putcmap(sc
,
1082 (struct wsdisplay_cmap
*)data
);
1084 case WSDISPLAYIO_SMODE
:
1086 int new_mode
= *(int*)data
;
1087 if (new_mode
!= sc
->sc_mode
)
1089 sc
->sc_mode
= new_mode
;
1090 if(new_mode
== WSDISPLAYIO_MODE_EMUL
)
1093 vcons_redraw_screen(ms
);
1098 return EPASSTHROUGH
;
1102 zx_mmap(void *v
, void *vs
, off_t offset
, int prot
)
1104 /* I'm not at all sure this is the right thing to do */
1105 return zxmmap(0, offset
, prot
); /* assume minor dev 0 for now */
1109 zx_putcmap(struct zx_softc
*sc
, struct wsdisplay_cmap
*cm
)
1111 u_int index
= cm
->index
;
1112 u_int count
= cm
->count
;
1114 if (index
>= 256 || count
> 256 || index
+ count
> 256)
1117 for (i
= 0; i
< count
; i
++)
1119 error
= copyin(&cm
->red
[i
],
1120 &sc
->sc_cmap
[index
+ i
], 1);
1123 error
= copyin(&cm
->green
[i
],
1124 &sc
->sc_cmap
[index
+ i
+ 256], 1);
1127 error
= copyin(&cm
->blue
[i
],
1128 &sc
->sc_cmap
[index
+ i
+ 512], 1);
1138 zx_getcmap(struct zx_softc
*sc
, struct wsdisplay_cmap
*cm
)
1140 u_int index
= cm
->index
;
1141 u_int count
= cm
->count
;
1144 if (index
>= 256 || count
> 256 || index
+ count
> 256)
1147 for (i
= 0; i
< count
; i
++)
1149 error
= copyout(&sc
->sc_cmap
[index
+ i
],
1153 error
= copyout(&sc
->sc_cmap
[index
+ i
+ 256],
1157 error
= copyout(&sc
->sc_cmap
[index
+ i
+ 256],
1167 zx_init_screen(void *cookie
, struct vcons_screen
*scr
,
1168 int existing
, long *defattr
)
1170 struct zx_softc
*sc
= cookie
;
1171 struct rasops_info
*ri
= &scr
->scr_ri
;
1173 ri
->ri_depth
= 8; /*sc->sc_fb.fb_type.fb_depth = 32;*/
1174 ri
->ri_width
= sc
->sc_width
;
1175 ri
->ri_height
= sc
->sc_height
;
1176 ri
->ri_stride
= sc
->sc_stride
;
1177 ri
->ri_flg
= RI_CENTER
;
1179 ri
->ri_bits
= (void *)sc
->sc_pixels
;
1181 rasops_init(ri
, sc
->sc_height
/8, sc
->sc_width
/8);
1182 ri
->ri_caps
= WSSCREEN_WSCOLORS
| WSSCREEN_REVERSE
;
1183 rasops_reconfig(ri
, sc
->sc_height
/ ri
->ri_font
->fontheight
,
1184 sc
->sc_width
/ ri
->ri_font
->fontwidth
);
1188 ri
->ri_ops
.cursor
= zx_do_cursor
;
1189 ri
->ri_ops
.copycols
= zx_copycols
;
1190 ri
->ri_ops
.copyrows
= zx_copyrows
;
1191 ri
->ri_ops
.erasecols
= zx_erasecols
;
1192 ri
->ri_ops
.eraserows
= zx_eraserows
;
1193 ri
->ri_ops
.putchar
= zx_putchar
;
1196 #endif /* NWSDISPLAY > 0 */