1*c7fb772bSthorpej /* $NetBSD: zx.c,v 1.47 2021/08/07 16:19:15 thorpej Exp $ */
2ca0ac2c7Sad
3ca0ac2c7Sad /*
4ca0ac2c7Sad * Copyright (c) 2002 The NetBSD Foundation, Inc.
5ca0ac2c7Sad * All rights reserved.
6ca0ac2c7Sad *
7ca0ac2c7Sad * This code is derived from software contributed to The NetBSD Foundation
8ca0ac2c7Sad * by Andrew Doran.
9ca0ac2c7Sad *
10ca0ac2c7Sad * Redistribution and use in source and binary forms, with or without
11ca0ac2c7Sad * modification, are permitted provided that the following conditions
12ca0ac2c7Sad * are met:
13ca0ac2c7Sad * 1. Redistributions of source code must retain the above copyright
14ca0ac2c7Sad * notice, this list of conditions and the following disclaimer.
15ca0ac2c7Sad * 2. Redistributions in binary form must reproduce the above copyright
16ca0ac2c7Sad * notice, this list of conditions and the following disclaimer in the
17ca0ac2c7Sad * documentation and/or other materials provided with the distribution.
18ca0ac2c7Sad *
19ca0ac2c7Sad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ca0ac2c7Sad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ca0ac2c7Sad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ca0ac2c7Sad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ca0ac2c7Sad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ca0ac2c7Sad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ca0ac2c7Sad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ca0ac2c7Sad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ca0ac2c7Sad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ca0ac2c7Sad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ca0ac2c7Sad * POSSIBILITY OF SUCH DAMAGE.
30ca0ac2c7Sad */
31ca0ac2c7Sad
32ca0ac2c7Sad /*
33ca0ac2c7Sad * Driver for the Sun ZX display adapter. This would be called 'leo', but
34ca0ac2c7Sad * NetBSD/amiga already has a driver by that name. The XFree86 and Linux
35ca0ac2c7Sad * drivers were used as "living documentation" when writing this; thanks
36ca0ac2c7Sad * to the authors.
37ca0ac2c7Sad *
38ca0ac2c7Sad * Issues (which can be solved with wscons, happily enough):
39ca0ac2c7Sad *
40ca0ac2c7Sad * o There is lots of unnecessary mucking about rasops in here, primarily
41ca0ac2c7Sad * to appease the sparc fb code.
42ca0ac2c7Sad */
43ca0ac2c7Sad
44ca0ac2c7Sad #include <sys/cdefs.h>
45*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: zx.c,v 1.47 2021/08/07 16:19:15 thorpej Exp $");
46ca0ac2c7Sad
47ca0ac2c7Sad #include <sys/param.h>
48ca0ac2c7Sad #include <sys/systm.h>
49ca0ac2c7Sad #include <sys/device.h>
50ca0ac2c7Sad #include <sys/ioctl.h>
51ca0ac2c7Sad #include <sys/malloc.h>
52ca0ac2c7Sad #include <sys/mman.h>
53ca0ac2c7Sad #include <sys/tty.h>
54ca0ac2c7Sad #include <sys/conf.h>
55ca0ac2c7Sad #include <sys/syslog.h>
56ca0ac2c7Sad #include <sys/buf.h>
57a7e80793Suebayasi #ifdef DEBUG
58a7e80793Suebayasi /* for log(9) in zxioctl() */
59a7e80793Suebayasi #include <sys/lwp.h>
60a7e80793Suebayasi #include <sys/proc.h>
61a7e80793Suebayasi #endif
62ca0ac2c7Sad
63a2a38285Sad #include <sys/bus.h>
64ca0ac2c7Sad #include <machine/autoconf.h>
65ca0ac2c7Sad
66ca0ac2c7Sad #include <dev/sun/fbio.h>
67ca0ac2c7Sad #include <dev/sun/fbvar.h>
68ca0ac2c7Sad
69c7d8ba24Smacallan #include "wsdisplay.h"
70c7d8ba24Smacallan #include <dev/wscons/wsconsio.h>
71c7d8ba24Smacallan #include <dev/wsfont/wsfont.h>
72c7d8ba24Smacallan #include <dev/rasops/rasops.h>
73c7d8ba24Smacallan #include <dev/wscons/wsdisplay_vconsvar.h>
74c7d8ba24Smacallan
75c7d8ba24Smacallan #include "opt_wsemul.h"
76c7d8ba24Smacallan
77ca0ac2c7Sad #include <dev/sbus/zxreg.h>
78ca0ac2c7Sad #include <dev/sbus/zxvar.h>
79ca0ac2c7Sad #include <dev/sbus/sbusvar.h>
80ca0ac2c7Sad
81ca0ac2c7Sad #include <dev/wscons/wsconsio.h>
82ca0ac2c7Sad
8308c90221Stsutsui #include "ioconf.h"
8408c90221Stsutsui
85ca0ac2c7Sad #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
86ca0ac2c7Sad ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
87ca0ac2c7Sad
88c7d8ba24Smacallan static void zx_attach(device_t, device_t, void *);
89d16a259fScegger static int zx_match(device_t, cfdata_t, void *);
90ca0ac2c7Sad
91c7d8ba24Smacallan static void zx_blank(device_t);
92c7d8ba24Smacallan static int zx_cmap_put(struct zx_softc *);
93c7d8ba24Smacallan static void zx_copyrect(struct zx_softc *, int, int, int, int, int, int);
94c7d8ba24Smacallan static int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int);
95c7d8ba24Smacallan static int zx_cross_wait(struct zx_softc *);
96c7d8ba24Smacallan static void zx_fillrect(struct zx_softc *, int, int, int, int, uint32_t, int);
97c7d8ba24Smacallan static int zx_intr(void *);
98c7d8ba24Smacallan static void zx_reset(struct zx_softc *);
99c7d8ba24Smacallan static void zx_unblank(device_t);
100ca0ac2c7Sad
101c7d8ba24Smacallan static void zx_cursor_blank(struct zx_softc *);
102c7d8ba24Smacallan static void zx_cursor_color(struct zx_softc *);
103c7d8ba24Smacallan static void zx_cursor_move(struct zx_softc *);
104c7d8ba24Smacallan static void zx_cursor_set(struct zx_softc *);
105c7d8ba24Smacallan static void zx_cursor_unblank(struct zx_softc *);
106ca0ac2c7Sad
107c7d8ba24Smacallan static void zx_copycols(void *, int, int, int, int);
108c7d8ba24Smacallan static void zx_copyrows(void *, int, int, int);
109c7d8ba24Smacallan static void zx_do_cursor(void *, int, int, int);
110c7d8ba24Smacallan static void zx_erasecols(void *, int, int, int, long);
111c7d8ba24Smacallan static void zx_eraserows(void *, int, int, long);
112c7d8ba24Smacallan static void zx_putchar(void *, int, int, u_int, long);
113ca0ac2c7Sad
114ca0ac2c7Sad struct zx_mmo {
115ca0ac2c7Sad off_t mo_va;
116ca0ac2c7Sad off_t mo_pa;
117ca0ac2c7Sad off_t mo_size;
118ca0ac2c7Sad } static const zx_mmo[] = {
119ca0ac2c7Sad { ZX_FB0_VOFF, ZX_OFF_SS0, 0x00800000 },
120ca0ac2c7Sad { ZX_LC0_VOFF, ZX_OFF_LC_SS0_USR, 0x00001000 },
121ca0ac2c7Sad { ZX_LD0_VOFF, ZX_OFF_LD_SS0, 0x00001000 },
122ca0ac2c7Sad { ZX_LX0_CURSOR_VOFF, ZX_OFF_LX_CURSOR, 0x00001000 },
123ca0ac2c7Sad { ZX_FB1_VOFF, ZX_OFF_SS1, 0x00800000 },
124ca0ac2c7Sad { ZX_LC1_VOFF, ZX_OFF_LC_SS1_USR, 0x00001000 },
125ca0ac2c7Sad { ZX_LD1_VOFF, ZX_OFF_LD_SS1, 0x00001000 },
126ca0ac2c7Sad { ZX_LX_KRN_VOFF, ZX_OFF_LX_CROSS, 0x00001000 },
127ca0ac2c7Sad { ZX_LC0_KRN_VOFF, ZX_OFF_LC_SS0_KRN, 0x00001000 },
128ca0ac2c7Sad { ZX_LC1_KRN_VOFF, ZX_OFF_LC_SS1_KRN, 0x00001000 },
129ca0ac2c7Sad { ZX_LD_GBL_VOFF, ZX_OFF_LD_GBL, 0x00001000 },
130ca0ac2c7Sad };
131ca0ac2c7Sad
132c7d8ba24Smacallan CFATTACH_DECL_NEW(zx, sizeof(struct zx_softc),
133b75a007dSthorpej zx_match, zx_attach, NULL, NULL);
134ca0ac2c7Sad
135c7d8ba24Smacallan static dev_type_open(zxopen);
136c7d8ba24Smacallan static dev_type_close(zxclose);
137c7d8ba24Smacallan static dev_type_ioctl(zxioctl);
138c7d8ba24Smacallan static dev_type_mmap(zxmmap);
139ca0ac2c7Sad
140ca0ac2c7Sad static struct fbdriver zx_fbdriver = {
141ca0ac2c7Sad zx_unblank, zxopen, zxclose, zxioctl, nopoll, zxmmap
142ca0ac2c7Sad };
143ca0ac2c7Sad
144c7d8ba24Smacallan struct wsscreen_descr zx_defaultscreen = {
145c7d8ba24Smacallan "std",
146c7d8ba24Smacallan 0, 0, /* will be filled in -- XXX shouldn't, it's global */
147c7d8ba24Smacallan /* doesn't matter - you can't really have more than one leo */
148c7d8ba24Smacallan NULL, /* textops */
149c7d8ba24Smacallan 8, 16, /* font width/height */
150c7d8ba24Smacallan WSSCREEN_WSCOLORS, /* capabilities */
151c7d8ba24Smacallan NULL /* modecookie */
152c7d8ba24Smacallan };
153c7d8ba24Smacallan
154c7d8ba24Smacallan static int zx_ioctl(void *, void *, u_long, void *, int, struct lwp *);
155c7d8ba24Smacallan static paddr_t zx_mmap(void *, void *, off_t, int);
156c7d8ba24Smacallan static void zx_init_screen(void *, struct vcons_screen *, int, long *);
157c7d8ba24Smacallan
158c7d8ba24Smacallan static int zx_putcmap(struct zx_softc *, struct wsdisplay_cmap *);
159c7d8ba24Smacallan static int zx_getcmap(struct zx_softc *, struct wsdisplay_cmap *);
160c7d8ba24Smacallan
161c7d8ba24Smacallan struct wsdisplay_accessops zx_accessops = {
162c7d8ba24Smacallan zx_ioctl,
163c7d8ba24Smacallan zx_mmap,
164c7d8ba24Smacallan NULL, /* alloc_screen */
165c7d8ba24Smacallan NULL, /* free_screen */
166c7d8ba24Smacallan NULL, /* show_screen */
167c7d8ba24Smacallan NULL, /* load_font */
168c7d8ba24Smacallan NULL, /* pollc */
169c7d8ba24Smacallan NULL /* scroll */
170c7d8ba24Smacallan };
171c7d8ba24Smacallan
172c7d8ba24Smacallan const struct wsscreen_descr *_zx_scrlist[] = {
173c7d8ba24Smacallan &zx_defaultscreen
174c7d8ba24Smacallan };
175c7d8ba24Smacallan
176c7d8ba24Smacallan struct wsscreen_list zx_screenlist = {
177c7d8ba24Smacallan sizeof(_zx_scrlist) / sizeof(struct wsscreen_descr *),
178c7d8ba24Smacallan _zx_scrlist
179c7d8ba24Smacallan };
180c7d8ba24Smacallan
181c7d8ba24Smacallan
182c7d8ba24Smacallan extern const u_char rasops_cmap[768];
183c7d8ba24Smacallan
184c7d8ba24Smacallan static struct vcons_screen zx_console_screen;
185c7d8ba24Smacallan
186c7d8ba24Smacallan static int
zx_match(device_t parent,cfdata_t cf,void * aux)187d16a259fScegger zx_match(device_t parent, cfdata_t cf, void *aux)
188ca0ac2c7Sad {
189ca0ac2c7Sad struct sbus_attach_args *sa;
190ca0ac2c7Sad
191ca0ac2c7Sad sa = (struct sbus_attach_args *)aux;
192ca0ac2c7Sad
193ca0ac2c7Sad return (strcmp(sa->sa_name, "SUNW,leo") == 0);
194ca0ac2c7Sad }
195ca0ac2c7Sad
196c7d8ba24Smacallan static void
zx_attach(device_t parent,device_t self,void * args)197c7d8ba24Smacallan zx_attach(device_t parent, device_t self, void *args)
198ca0ac2c7Sad {
199ca0ac2c7Sad struct zx_softc *sc;
200ca0ac2c7Sad struct sbus_attach_args *sa;
201ca0ac2c7Sad bus_space_handle_t bh;
202ca0ac2c7Sad bus_space_tag_t bt;
203ca0ac2c7Sad struct fbdevice *fb;
204c7d8ba24Smacallan struct wsemuldisplaydev_attach_args aa;
205c7d8ba24Smacallan struct rasops_info *ri = &zx_console_screen.scr_ri;
206c7d8ba24Smacallan unsigned long defattr;
20708f5b97bSmacallan int isconsole, width, height;
208ca0ac2c7Sad
2091a9e64b4Sdrochner sc = device_private(self);
210c7d8ba24Smacallan sc->sc_dv = self;
211c7d8ba24Smacallan
212ca0ac2c7Sad sa = args;
213ca0ac2c7Sad fb = &sc->sc_fb;
214ca0ac2c7Sad bt = sa->sa_bustag;
215ca0ac2c7Sad sc->sc_bt = bt;
216ca0ac2c7Sad sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);
217ca0ac2c7Sad
2180483b5b9Smacallan if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
2190483b5b9Smacallan 0x800000, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, &bh) != 0) {
2204c5fa20dScegger aprint_error_dev(self, "can't map bits\n");
221ca0ac2c7Sad return;
222ca0ac2c7Sad }
22353524e44Schristos fb->fb_pixels = (void *)bus_space_vaddr(bt, bh);
224579b9cbdStsutsui sc->sc_pixels = (uint32_t *)fb->fb_pixels;
225ca0ac2c7Sad
226ca0ac2c7Sad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
227ca0ac2c7Sad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
2284c5fa20dScegger aprint_error_dev(self, "can't map zc\n");
229ca0ac2c7Sad return;
230ca0ac2c7Sad }
231c7d8ba24Smacallan
232f8fb75a4Stsutsui sc->sc_bhzc = bh;
233ca0ac2c7Sad
234ca0ac2c7Sad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
235ca0ac2c7Sad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
2364c5fa20dScegger aprint_error_dev(self, "can't map ld/ss0\n");
237ca0ac2c7Sad return;
238ca0ac2c7Sad }
239f8fb75a4Stsutsui sc->sc_bhzdss0 = bh;
240ca0ac2c7Sad
241ca0ac2c7Sad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
242ca0ac2c7Sad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
2434c5fa20dScegger aprint_error_dev(self, "can't map ld/ss1\n");
244ca0ac2c7Sad return;
245ca0ac2c7Sad }
246f8fb75a4Stsutsui sc->sc_bhzdss1 = bh;
247ca0ac2c7Sad
248ca0ac2c7Sad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
249ca0ac2c7Sad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
2504c5fa20dScegger aprint_error_dev(self, "can't map zx\n");
251ca0ac2c7Sad return;
252ca0ac2c7Sad }
253f8fb75a4Stsutsui sc->sc_bhzx = bh;
254ca0ac2c7Sad
255ca0ac2c7Sad if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
256ca0ac2c7Sad PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) {
2574c5fa20dScegger aprint_error_dev(self, "can't map zcu\n");
258ca0ac2c7Sad return;
259ca0ac2c7Sad }
260f8fb75a4Stsutsui sc->sc_bhzcu = bh;
261ca0ac2c7Sad
262ca0ac2c7Sad fb->fb_driver = &zx_fbdriver;
263c7d8ba24Smacallan fb->fb_device = sc->sc_dv;
264c7d8ba24Smacallan fb->fb_flags = device_cfdata(sc->sc_dv)->cf_flags & FB_USERMASK;
265ca0ac2c7Sad fb->fb_pfour = NULL;
266768601d6Stsutsui fb->fb_linebytes = prom_getpropint(sa->sa_node, "linebytes", 8192);
267ca0ac2c7Sad
268768601d6Stsutsui width = prom_getpropint(sa->sa_node, "width", 1280);
269768601d6Stsutsui height = prom_getpropint(sa->sa_node, "height", 1024);
270768601d6Stsutsui fb_setsize_obp(fb, 32, width, height, sa->sa_node);
271ca0ac2c7Sad
272ca0ac2c7Sad fb->fb_type.fb_cmsize = 256;
273ca0ac2c7Sad fb->fb_type.fb_depth = 32;
274ca0ac2c7Sad fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
275ca0ac2c7Sad fb->fb_type.fb_type = FBTYPE_SUNLEO;
276ca0ac2c7Sad
277ca0ac2c7Sad printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height);
278ca0ac2c7Sad isconsole = fb_is_console(sa->sa_node);
279ca0ac2c7Sad if (isconsole)
280ca0ac2c7Sad printf(" (console)");
281ca0ac2c7Sad printf("\n");
282ca0ac2c7Sad
283ca0ac2c7Sad if (sa->sa_nintr != 0)
284725a6aebSpk bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc);
285ca0ac2c7Sad
286d47bcd29Schs sc->sc_cmap = malloc(768, M_DEVBUF, M_WAITOK);
287ca0ac2c7Sad zx_reset(sc);
288ca0ac2c7Sad
289c7d8ba24Smacallan sc->sc_width = fb->fb_type.fb_width;
290c7d8ba24Smacallan sc->sc_stride = 8192; /* 32 bit */
291c7d8ba24Smacallan sc->sc_height = fb->fb_type.fb_height;
292c7d8ba24Smacallan
293c7d8ba24Smacallan /* setup rasops and so on for wsdisplay */
294c7d8ba24Smacallan wsfont_init();
295c7d8ba24Smacallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
296c7d8ba24Smacallan sc->sc_bg = WS_DEFAULT_BG;
297c7d8ba24Smacallan
298c7d8ba24Smacallan vcons_init(&sc->vd, sc, &zx_defaultscreen, &zx_accessops);
299c7d8ba24Smacallan sc->vd.init_screen = zx_init_screen;
300c7d8ba24Smacallan
301c7d8ba24Smacallan if (isconsole) {
302c7d8ba24Smacallan /* we mess with zx_console_screen only once */
303c7d8ba24Smacallan vcons_init_screen(&sc->vd, &zx_console_screen, 1,
304c7d8ba24Smacallan &defattr);
305c7d8ba24Smacallan zx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
306c7d8ba24Smacallan
307c7d8ba24Smacallan zx_defaultscreen.textops = &ri->ri_ops;
308c7d8ba24Smacallan zx_defaultscreen.capabilities = WSSCREEN_WSCOLORS;
309c7d8ba24Smacallan zx_defaultscreen.nrows = ri->ri_rows;
310c7d8ba24Smacallan zx_defaultscreen.ncols = ri->ri_cols;
31108f5b97bSmacallan zx_fillrect(sc, 0, 0, width, height,
31208f5b97bSmacallan ri->ri_devcmap[defattr >> 16], ZX_STD_ROP);
313c7d8ba24Smacallan wsdisplay_cnattach(&zx_defaultscreen, ri, 0, 0, defattr);
314647d0c59Smacallan vcons_replay_msgbuf(&zx_console_screen);
315c7d8ba24Smacallan } else {
316ca0ac2c7Sad /*
317c7d8ba24Smacallan * we're not the console so we just clear the screen and don't
318c7d8ba24Smacallan * set up any sort of text display
319ca0ac2c7Sad */
320c7d8ba24Smacallan if (zx_defaultscreen.textops == NULL) {
321c7d8ba24Smacallan /*
322c7d8ba24Smacallan * ugly, but...
323c7d8ba24Smacallan * we want the console settings to win, so we only
324c7d8ba24Smacallan * touch anything when we find an untouched screen
325c7d8ba24Smacallan * definition. In this case we fill it from fb to
326c7d8ba24Smacallan * avoid problems in case no zx is the console
327c7d8ba24Smacallan */
328c7d8ba24Smacallan zx_defaultscreen.textops = &ri->ri_ops;
329c7d8ba24Smacallan zx_defaultscreen.capabilities = ri->ri_caps;
330c7d8ba24Smacallan zx_defaultscreen.nrows = ri->ri_rows;
331c7d8ba24Smacallan zx_defaultscreen.ncols = ri->ri_cols;
332c7d8ba24Smacallan }
333ca0ac2c7Sad }
334ca0ac2c7Sad
335c7d8ba24Smacallan aa.scrdata = &zx_screenlist;
336c7d8ba24Smacallan aa.console = isconsole;
337c7d8ba24Smacallan aa.accessops = &zx_accessops;
338c7d8ba24Smacallan aa.accesscookie = &sc->vd;
339*c7fb772bSthorpej config_found(sc->sc_dv, &aa, wsemuldisplaydevprint, CFARGS_NONE);
340c7d8ba24Smacallan fb_attach(&sc->sc_fb, isconsole);
341c7d8ba24Smacallan }
342c7d8ba24Smacallan
343c7d8ba24Smacallan static int
zxopen(dev_t dev,int flags,int mode,struct lwp * l)34495e1ffb1Schristos zxopen(dev_t dev, int flags, int mode, struct lwp *l)
345ca0ac2c7Sad {
346ca0ac2c7Sad
347ca0ac2c7Sad if (device_lookup(&zx_cd, minor(dev)) == NULL)
348ca0ac2c7Sad return (ENXIO);
349ca0ac2c7Sad return (0);
350ca0ac2c7Sad }
351ca0ac2c7Sad
352c7d8ba24Smacallan static int
zxclose(dev_t dev,int flags,int mode,struct lwp * l)35395e1ffb1Schristos zxclose(dev_t dev, int flags, int mode, struct lwp *l)
354ca0ac2c7Sad {
355ca0ac2c7Sad struct zx_softc *sc;
356ca0ac2c7Sad
35796434039Scegger sc = device_lookup_private(&zx_cd, minor(dev));
358ca0ac2c7Sad
359ca0ac2c7Sad zx_reset(sc);
360ca0ac2c7Sad zx_cursor_blank(sc);
361ca0ac2c7Sad return (0);
362ca0ac2c7Sad }
363ca0ac2c7Sad
364c7d8ba24Smacallan static int
zxioctl(dev_t dev,u_long cmd,void * data,int flags,struct lwp * l)36553524e44Schristos zxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
366ca0ac2c7Sad {
367ca0ac2c7Sad struct zx_softc *sc;
368ca0ac2c7Sad struct fbcmap *cm;
369ca0ac2c7Sad struct fbcursor *cu;
370e07f0b93Schs uint32_t curbits[2][32];
371bfad2cbbSchristos int rv, v, count, i, error;
372ca0ac2c7Sad
37396434039Scegger sc = device_lookup_private(&zx_cd, minor(dev));
374ca0ac2c7Sad
375ca0ac2c7Sad switch (cmd) {
376ca0ac2c7Sad case FBIOGTYPE:
377ca0ac2c7Sad *(struct fbtype *)data = sc->sc_fb.fb_type;
378ca0ac2c7Sad break;
379ca0ac2c7Sad
380ca0ac2c7Sad case FBIOGATTR:
381ca0ac2c7Sad #define fba ((struct fbgattr *)data)
382ca0ac2c7Sad fba->real_type = sc->sc_fb.fb_type.fb_type;
383ca0ac2c7Sad fba->owner = 0; /* XXX ??? */
384ca0ac2c7Sad fba->fbtype = sc->sc_fb.fb_type;
385ca0ac2c7Sad fba->sattr.flags = 0;
386ca0ac2c7Sad fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
387ca0ac2c7Sad fba->sattr.dev_specific[0] = -1;
388ca0ac2c7Sad fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
389ca0ac2c7Sad fba->emu_types[1] = -1;
390ca0ac2c7Sad fba->emu_types[2] = -1;
391ca0ac2c7Sad #undef fba
392ca0ac2c7Sad break;
393ca0ac2c7Sad
394ca0ac2c7Sad case FBIOGVIDEO:
395ca0ac2c7Sad *(int *)data = ((sc->sc_flags & ZX_BLANKED) != 0);
396ca0ac2c7Sad break;
397ca0ac2c7Sad
398ca0ac2c7Sad case FBIOSVIDEO:
399ca0ac2c7Sad if (*(int *)data)
400c7d8ba24Smacallan zx_unblank(sc->sc_dv);
401ca0ac2c7Sad else
402c7d8ba24Smacallan zx_blank(sc->sc_dv);
403ca0ac2c7Sad break;
404ca0ac2c7Sad
405ca0ac2c7Sad case FBIOGETCMAP:
406ca0ac2c7Sad cm = (struct fbcmap *)data;
407ca0ac2c7Sad if (cm->index > 256 || cm->count > 256 - cm->index)
408ca0ac2c7Sad return (EINVAL);
409ca0ac2c7Sad rv = copyout(sc->sc_cmap + cm->index, cm->red, cm->count);
41060c69eb3Sad if (rv == 0)
411ca0ac2c7Sad rv = copyout(sc->sc_cmap + 256 + cm->index, cm->green,
412ca0ac2c7Sad cm->count);
41360c69eb3Sad if (rv == 0)
414ca0ac2c7Sad rv = copyout(sc->sc_cmap + 512 + cm->index, cm->blue,
415ca0ac2c7Sad cm->count);
416ca0ac2c7Sad return (rv);
417ca0ac2c7Sad
418ca0ac2c7Sad case FBIOPUTCMAP:
419ca0ac2c7Sad cm = (struct fbcmap *)data;
420ca0ac2c7Sad if (cm->index > 256 || cm->count > 256 - cm->index)
421ca0ac2c7Sad return (EINVAL);
422ca0ac2c7Sad rv = copyin(cm->red, sc->sc_cmap + cm->index, cm->count);
42360c69eb3Sad if (rv == 0)
424ca0ac2c7Sad rv = copyin(cm->green, sc->sc_cmap + 256 + cm->index,
425ca0ac2c7Sad cm->count);
42660c69eb3Sad if (rv == 0)
427ca0ac2c7Sad rv = copyin(cm->blue, sc->sc_cmap + 512 + cm->index,
428ca0ac2c7Sad cm->count);
429ca0ac2c7Sad zx_cmap_put(sc);
430ca0ac2c7Sad return (rv);
431ca0ac2c7Sad
432ca0ac2c7Sad case FBIOGCURPOS:
433ca0ac2c7Sad *(struct fbcurpos *)data = sc->sc_curpos;
434ca0ac2c7Sad break;
435ca0ac2c7Sad
436ca0ac2c7Sad case FBIOSCURPOS:
437ca0ac2c7Sad sc->sc_curpos = *(struct fbcurpos *)data;
438ca0ac2c7Sad zx_cursor_move(sc);
439ca0ac2c7Sad break;
440ca0ac2c7Sad
441ca0ac2c7Sad case FBIOGCURMAX:
442ca0ac2c7Sad ((struct fbcurpos *)data)->x = 32;
443ca0ac2c7Sad ((struct fbcurpos *)data)->y = 32;
444ca0ac2c7Sad break;
445ca0ac2c7Sad
446ca0ac2c7Sad case FBIOSCURSOR:
447ca0ac2c7Sad cu = (struct fbcursor *)data;
448ca0ac2c7Sad v = cu->set;
449ca0ac2c7Sad
450ca0ac2c7Sad if ((v & FB_CUR_SETSHAPE) != 0) {
451ca0ac2c7Sad if ((u_int)cu->size.x > 32 || (u_int)cu->size.y > 32)
452ca0ac2c7Sad return (EINVAL);
453ca0ac2c7Sad count = cu->size.y * 4;
454e07f0b93Schs rv = copyin(cu->mask, curbits[0], count);
455e07f0b93Schs if (rv)
456e07f0b93Schs return rv;
457e07f0b93Schs rv = copyin(cu->image, curbits[1], count);
458e07f0b93Schs if (rv)
459e07f0b93Schs return rv;
460ca0ac2c7Sad }
461ca0ac2c7Sad if ((v & FB_CUR_SETCUR) != 0) {
462ca0ac2c7Sad if (cu->enable)
463ca0ac2c7Sad zx_cursor_unblank(sc);
464ca0ac2c7Sad else
465ca0ac2c7Sad zx_cursor_blank(sc);
466ca0ac2c7Sad }
467ca0ac2c7Sad if ((v & (FB_CUR_SETPOS | FB_CUR_SETHOT)) != 0) {
468ca0ac2c7Sad if ((v & FB_CUR_SETPOS) != 0)
469ca0ac2c7Sad sc->sc_curpos = cu->pos;
470ca0ac2c7Sad if ((v & FB_CUR_SETHOT) != 0)
471ca0ac2c7Sad sc->sc_curhot = cu->hot;
472ca0ac2c7Sad zx_cursor_move(sc);
473ca0ac2c7Sad }
474ca0ac2c7Sad if ((v & FB_CUR_SETCMAP) != 0) {
475ca0ac2c7Sad if (cu->cmap.index > 2 ||
476ca0ac2c7Sad cu->cmap.count > 2 - cu->cmap.index)
477ca0ac2c7Sad return (EINVAL);
47842620a4aSthorpej
47942620a4aSthorpej uint8_t red[2], green[2], blue[2];
48042620a4aSthorpej const u_int cnt = cu->cmap.count;
48142620a4aSthorpej
48242620a4aSthorpej if (cnt &&
48342620a4aSthorpej ((error = copyin(cu->cmap.red, red, cnt)) ||
48442620a4aSthorpej (error = copyin(cu->cmap.green, green, cnt)) ||
48542620a4aSthorpej (error = copyin(cu->cmap.blue, blue, cnt)))) {
48642620a4aSthorpej return error;
48742620a4aSthorpej }
48842620a4aSthorpej
48942620a4aSthorpej for (i = 0; i < cnt; i++) {
49042620a4aSthorpej sc->sc_curcmap[i + cu->cmap.index + 0] =
49142620a4aSthorpej red[i];
49242620a4aSthorpej sc->sc_curcmap[i + cu->cmap.index + 2] =
49342620a4aSthorpej green[i];
49442620a4aSthorpej sc->sc_curcmap[i + cu->cmap.index + 4] =
49542620a4aSthorpej blue[i];
496ca0ac2c7Sad }
497ca0ac2c7Sad zx_cursor_color(sc);
498ca0ac2c7Sad }
499ca0ac2c7Sad if ((v & FB_CUR_SETSHAPE) != 0) {
500ca0ac2c7Sad sc->sc_cursize = cu->size;
501ca0ac2c7Sad count = cu->size.y * 4;
502ca0ac2c7Sad memset(sc->sc_curbits, 0, sizeof(sc->sc_curbits));
503e07f0b93Schs memcpy(sc->sc_curbits[0], curbits[0], count);
504e07f0b93Schs memcpy(sc->sc_curbits[1], curbits[1], count);
505ca0ac2c7Sad zx_cursor_set(sc);
506ca0ac2c7Sad }
507ca0ac2c7Sad break;
508ca0ac2c7Sad
509ca0ac2c7Sad case FBIOGCURSOR:
510ca0ac2c7Sad cu = (struct fbcursor *)data;
511ca0ac2c7Sad
512ca0ac2c7Sad cu->set = FB_CUR_SETALL;
513ca0ac2c7Sad cu->enable = ((sc->sc_flags & ZX_CURSOR) != 0);
514ca0ac2c7Sad cu->pos = sc->sc_curpos;
515ca0ac2c7Sad cu->hot = sc->sc_curhot;
516ca0ac2c7Sad cu->size = sc->sc_cursize;
517ca0ac2c7Sad
518ca0ac2c7Sad if (cu->image != NULL) {
519ca0ac2c7Sad count = sc->sc_cursize.y * 4;
520e07f0b93Schs rv = copyout(sc->sc_curbits[1], cu->image, count);
521ca0ac2c7Sad if (rv)
522ca0ac2c7Sad return (rv);
523e07f0b93Schs rv = copyout(sc->sc_curbits[0], cu->mask, count);
524ca0ac2c7Sad if (rv)
525ca0ac2c7Sad return (rv);
526ca0ac2c7Sad }
527ca0ac2c7Sad if (cu->cmap.red != NULL) {
528bfad2cbbSchristos uint8_t red[2], green[2], blue[2];
529bfad2cbbSchristos const uint8_t *ccm = sc->sc_curcmap;
530bfad2cbbSchristos cm = &cu->cmap;
531bfad2cbbSchristos
532bfad2cbbSchristos if (cm->index > 2 || cm->count > 2 - cm->index)
533bfad2cbbSchristos return EINVAL;
534bfad2cbbSchristos
535bfad2cbbSchristos for (i = 0; i < cm->count; i++) {
536bfad2cbbSchristos red[i] = ccm[i + cm->index + 0];
537bfad2cbbSchristos green[i] = ccm[i + cm->index + 2];
538bfad2cbbSchristos blue[i] = ccm[i + cm->index + 4];
539ca0ac2c7Sad }
540bfad2cbbSchristos
541bfad2cbbSchristos if ((error = copyout(red, cm->red, cm->count)) ||
542bfad2cbbSchristos (error = copyout(green, cm->green, cm->count)) ||
543bfad2cbbSchristos (error = copyout(blue, cm->blue, cm->count)))
544bfad2cbbSchristos return error;
545ca0ac2c7Sad } else {
546ca0ac2c7Sad cu->cmap.index = 0;
547ca0ac2c7Sad cu->cmap.count = 2;
548ca0ac2c7Sad }
549ca0ac2c7Sad break;
550ca0ac2c7Sad
551ca0ac2c7Sad default:
552ca0ac2c7Sad #ifdef DEBUG
553ca0ac2c7Sad log(LOG_NOTICE, "zxioctl(0x%lx) (%s[%d])\n", cmd,
554517cd323Sjdc l->l_proc->p_comm, l->l_proc->p_pid);
555ca0ac2c7Sad #endif
556ca0ac2c7Sad return (ENOTTY);
557ca0ac2c7Sad }
558ca0ac2c7Sad
559ca0ac2c7Sad return (0);
560ca0ac2c7Sad }
561ca0ac2c7Sad
562c7d8ba24Smacallan static int
zx_intr(void * cookie)563ca0ac2c7Sad zx_intr(void *cookie)
564ca0ac2c7Sad {
565ca0ac2c7Sad
566ca0ac2c7Sad return (1);
567ca0ac2c7Sad }
568ca0ac2c7Sad
569c7d8ba24Smacallan static void
zx_reset(struct zx_softc * sc)570ca0ac2c7Sad zx_reset(struct zx_softc *sc)
571ca0ac2c7Sad {
572ca0ac2c7Sad struct fbtype *fbt;
573ca0ac2c7Sad u_int i;
574ca0ac2c7Sad
575ca0ac2c7Sad fbt = &sc->sc_fb.fb_type;
576ca0ac2c7Sad
577ca0ac2c7Sad zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0);
578ca0ac2c7Sad zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30);
579ca0ac2c7Sad zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20);
580ca0ac2c7Sad zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30);
581ca0ac2c7Sad
582f8fb75a4Stsutsui i = bus_space_read_4(sc->sc_bt, sc->sc_bhzdss1, zd_misc);
583ca0ac2c7Sad i |= ZX_SS1_MISC_ENABLE;
584f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss1, zd_misc, i);
585ca0ac2c7Sad
586c7d8ba24Smacallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_wid, 1);
587f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_widclip, 0);
588f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_wmask, 0xffff);
589f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_vclipmin, 0);
590f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_vclipmax,
591ca0ac2c7Sad (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 16));
592f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, 0);
593c7d8ba24Smacallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_planemask, 0xffffffff);
594f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP);
595ca0ac2c7Sad
596f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent,
597ca0ac2c7Sad (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 11));
598f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_addrspace,
599f8fb75a4Stsutsui ZX_ADDRSPC_FONT_OBGR);
600f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fontt, 0);
601ca0ac2c7Sad
602ca0ac2c7Sad for (i = 0; i < 256; i++) {
603ca0ac2c7Sad sc->sc_cmap[i] = rasops_cmap[i * 3];
604ca0ac2c7Sad sc->sc_cmap[i + 256] = rasops_cmap[i * 3 + 1];
605ca0ac2c7Sad sc->sc_cmap[i + 512] = rasops_cmap[i * 3 + 2];
606ca0ac2c7Sad }
607ca0ac2c7Sad
608ca0ac2c7Sad zx_cmap_put(sc);
609ca0ac2c7Sad }
610ca0ac2c7Sad
611c7d8ba24Smacallan static int
zx_cross_wait(struct zx_softc * sc)612ca0ac2c7Sad zx_cross_wait(struct zx_softc *sc)
613ca0ac2c7Sad {
614ca0ac2c7Sad int i;
615ca0ac2c7Sad
616ca0ac2c7Sad for (i = 300000; i != 0; i--) {
617f8fb75a4Stsutsui if ((bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) &
618f8fb75a4Stsutsui ZX_CROSS_CSR_PROGRESS) == 0)
619ca0ac2c7Sad break;
620ca0ac2c7Sad DELAY(1);
621ca0ac2c7Sad }
622ca0ac2c7Sad
623ca0ac2c7Sad if (i == 0)
624ca0ac2c7Sad printf("zx_cross_wait: timed out\n");
625ca0ac2c7Sad
626ca0ac2c7Sad return (i);
627ca0ac2c7Sad }
628ca0ac2c7Sad
629c7d8ba24Smacallan static int
zx_cross_loadwid(struct zx_softc * sc,u_int type,u_int index,u_int value)630ca0ac2c7Sad zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value)
631ca0ac2c7Sad {
632cd23cf5cSchs u_int tmp = 0;
633ca0ac2c7Sad
634f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_WID);
635ca0ac2c7Sad
636ca0ac2c7Sad if (zx_cross_wait(sc))
637ca0ac2c7Sad return (1);
638ca0ac2c7Sad
639ca0ac2c7Sad if (type == ZX_WID_DBL_8)
640ca0ac2c7Sad tmp = (index & 0x0f) + 0x40;
641ca0ac2c7Sad else if (type == ZX_WID_DBL_24)
642ca0ac2c7Sad tmp = index & 0x3f;
643ca0ac2c7Sad
644f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, 0x5800 + tmp);
645f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_value, value);
646f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_WID);
647f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr,
648f8fb75a4Stsutsui ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2);
649ca0ac2c7Sad
650ca0ac2c7Sad return (0);
651ca0ac2c7Sad }
652ca0ac2c7Sad
653c7d8ba24Smacallan static int
zx_cmap_put(struct zx_softc * sc)654ca0ac2c7Sad zx_cmap_put(struct zx_softc *sc)
655ca0ac2c7Sad {
656ca0ac2c7Sad const u_char *b;
657ca0ac2c7Sad u_int i, t;
658ca0ac2c7Sad
659f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_CLUT0);
660c7d8ba24Smacallan
661c7d8ba24Smacallan zx_cross_wait(sc);
662ca0ac2c7Sad
663f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type,
664f8fb75a4Stsutsui ZX_CROSS_TYPE_CLUTDATA);
665ca0ac2c7Sad
666ca0ac2c7Sad for (i = 0, b = sc->sc_cmap; i < 256; i++) {
667ca0ac2c7Sad t = b[i];
668ca0ac2c7Sad t |= b[i + 256] << 8;
669ca0ac2c7Sad t |= b[i + 512] << 16;
670f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_value, t);
671ca0ac2c7Sad }
672ca0ac2c7Sad
673f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_CLUT0);
674f8fb75a4Stsutsui i = bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr);
675ca0ac2c7Sad i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2;
676f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, i);
677ca0ac2c7Sad return (0);
678ca0ac2c7Sad }
679ca0ac2c7Sad
680c7d8ba24Smacallan static void
zx_cursor_move(struct zx_softc * sc)681ca0ac2c7Sad zx_cursor_move(struct zx_softc *sc)
682ca0ac2c7Sad {
683ca0ac2c7Sad int sx, sy, x, y;
684ca0ac2c7Sad
685ca0ac2c7Sad x = sc->sc_curpos.x - sc->sc_curhot.x;
686ca0ac2c7Sad y = sc->sc_curpos.y - sc->sc_curhot.y;
687ca0ac2c7Sad
688ca0ac2c7Sad if (x < 0) {
689d1579b2dSriastradh sx = uimin(-x, 32);
690ca0ac2c7Sad x = 0;
691ca0ac2c7Sad } else
692ca0ac2c7Sad sx = 0;
693ca0ac2c7Sad
694ca0ac2c7Sad if (y < 0) {
695d1579b2dSriastradh sy = uimin(-y, 32);
696ca0ac2c7Sad y = 0;
697ca0ac2c7Sad } else
698ca0ac2c7Sad sy = 0;
699ca0ac2c7Sad
700ca0ac2c7Sad if (sx != sc->sc_shiftx || sy != sc->sc_shifty) {
701ca0ac2c7Sad sc->sc_shiftx = sx;
702ca0ac2c7Sad sc->sc_shifty = sy;
703ca0ac2c7Sad zx_cursor_set(sc);
704ca0ac2c7Sad }
705ca0ac2c7Sad
706f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_sxy,
707f8fb75a4Stsutsui ((y & 0x7ff) << 11) | (x & 0x7ff));
708f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
709f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x30);
710ca0ac2c7Sad
711ca0ac2c7Sad /* XXX Necessary? */
712f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
713f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80);
714ca0ac2c7Sad }
715ca0ac2c7Sad
716c7d8ba24Smacallan static void
zx_cursor_set(struct zx_softc * sc)717ca0ac2c7Sad zx_cursor_set(struct zx_softc *sc)
718ca0ac2c7Sad {
719ca0ac2c7Sad int i, j, data;
720ca0ac2c7Sad
72160c69eb3Sad if ((sc->sc_flags & ZX_CURSOR) != 0)
722f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
723f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) &
724f8fb75a4Stsutsui ~0x80);
725ca0ac2c7Sad
726ca0ac2c7Sad for (j = 0; j < 2; j++) {
727f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_type, 0x20 << j);
72860c69eb3Sad
729ca0ac2c7Sad for (i = sc->sc_shifty; i < 32; i++) {
730ca0ac2c7Sad data = sc->sc_curbits[j][i];
731f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data,
732f8fb75a4Stsutsui data >> sc->sc_shiftx);
733ca0ac2c7Sad }
734ca0ac2c7Sad for (i = sc->sc_shifty; i != 0; i--)
735f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, 0);
736ca0ac2c7Sad }
73760c69eb3Sad
73860c69eb3Sad if ((sc->sc_flags & ZX_CURSOR) != 0)
739f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
740f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80);
741ca0ac2c7Sad }
742ca0ac2c7Sad
743c7d8ba24Smacallan static void
zx_cursor_blank(struct zx_softc * sc)744ca0ac2c7Sad zx_cursor_blank(struct zx_softc *sc)
745ca0ac2c7Sad {
746ca0ac2c7Sad
747ca0ac2c7Sad sc->sc_flags &= ~ZX_CURSOR;
748f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
749f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) & ~0x80);
750ca0ac2c7Sad }
751ca0ac2c7Sad
752c7d8ba24Smacallan static void
zx_cursor_unblank(struct zx_softc * sc)753ca0ac2c7Sad zx_cursor_unblank(struct zx_softc *sc)
754ca0ac2c7Sad {
755ca0ac2c7Sad
756ca0ac2c7Sad sc->sc_flags |= ZX_CURSOR;
757f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
758f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80);
759ca0ac2c7Sad }
760ca0ac2c7Sad
761c7d8ba24Smacallan static void
zx_cursor_color(struct zx_softc * sc)762ca0ac2c7Sad zx_cursor_color(struct zx_softc *sc)
763ca0ac2c7Sad {
764579b9cbdStsutsui uint8_t tmp;
765ca0ac2c7Sad
766f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_type, 0x50);
767ca0ac2c7Sad
768ca0ac2c7Sad tmp = sc->sc_curcmap[0] | (sc->sc_curcmap[2] << 8) |
769ca0ac2c7Sad (sc->sc_curcmap[4] << 16);
770f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, tmp);
771ca0ac2c7Sad
772ca0ac2c7Sad tmp = sc->sc_curcmap[1] | (sc->sc_curcmap[3] << 8) |
773ca0ac2c7Sad (sc->sc_curcmap[5] << 16);
77424ebd355Sthorpej bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, tmp);
775ca0ac2c7Sad
776f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc,
777f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x03);
778ca0ac2c7Sad }
779ca0ac2c7Sad
780c7d8ba24Smacallan static void
zx_blank(device_t dv)781c7d8ba24Smacallan zx_blank(device_t dv)
782ca0ac2c7Sad {
783ca0ac2c7Sad struct zx_softc *sc;
784ca0ac2c7Sad
7851a9e64b4Sdrochner sc = device_private(dv);
786ca0ac2c7Sad
787ca0ac2c7Sad if ((sc->sc_flags & ZX_BLANKED) != 0)
788ca0ac2c7Sad return;
789ca0ac2c7Sad sc->sc_flags |= ZX_BLANKED;
790ca0ac2c7Sad
791f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_VIDEO);
792f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr,
793f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) &
794f8fb75a4Stsutsui ~ZX_CROSS_CSR_ENABLE);
795ca0ac2c7Sad }
796ca0ac2c7Sad
797c7d8ba24Smacallan static void
zx_unblank(device_t dv)798c7d8ba24Smacallan zx_unblank(device_t dv)
799ca0ac2c7Sad {
800ca0ac2c7Sad struct zx_softc *sc;
801ca0ac2c7Sad
8021a9e64b4Sdrochner sc = device_private(dv);
803ca0ac2c7Sad
804ca0ac2c7Sad if ((sc->sc_flags & ZX_BLANKED) == 0)
805ca0ac2c7Sad return;
806ca0ac2c7Sad sc->sc_flags &= ~ZX_BLANKED;
807ca0ac2c7Sad
808f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_VIDEO);
809f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr,
810f8fb75a4Stsutsui bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) |
811f8fb75a4Stsutsui ZX_CROSS_CSR_ENABLE);
812ca0ac2c7Sad }
813ca0ac2c7Sad
814c7d8ba24Smacallan static paddr_t
zxmmap(dev_t dev,off_t off,int prot)815ca0ac2c7Sad zxmmap(dev_t dev, off_t off, int prot)
816ca0ac2c7Sad {
817ca0ac2c7Sad struct zx_softc *sc;
818b22c03afStsutsui const struct zx_mmo *mm, *mmmax;
819ca0ac2c7Sad
82096434039Scegger sc = device_lookup_private(&zx_cd, minor(dev));
82160c69eb3Sad off = trunc_page(off);
822ca0ac2c7Sad mm = zx_mmo;
823b22c03afStsutsui mmmax = mm + sizeof(zx_mmo) / sizeof(zx_mmo[0]);
824ca0ac2c7Sad
825b22c03afStsutsui for (; mm < mmmax; mm++)
826ca0ac2c7Sad if (off >= mm->mo_va && off < mm->mo_va + mm->mo_size) {
827ca0ac2c7Sad off = off - mm->mo_va + mm->mo_pa;
828ca0ac2c7Sad return (bus_space_mmap(sc->sc_bt, sc->sc_paddr,
829ca0ac2c7Sad off, prot, BUS_SPACE_MAP_LINEAR));
830ca0ac2c7Sad }
831ca0ac2c7Sad
832ca0ac2c7Sad return (-1);
833ca0ac2c7Sad }
834ca0ac2c7Sad
835c7d8ba24Smacallan static void
zx_fillrect(struct zx_softc * sc,int x,int y,int w,int h,uint32_t bg,int rop)836c7d8ba24Smacallan zx_fillrect(struct zx_softc *sc, int x, int y, int w, int h, uint32_t bg,
837ca0ac2c7Sad int rop)
838ca0ac2c7Sad {
839ca0ac2c7Sad
840ca0ac2c7Sad
841f8fb75a4Stsutsui while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) &
842f8fb75a4Stsutsui ZX_CSR_BLT_BUSY) != 0)
843ca0ac2c7Sad ;
844ca0ac2c7Sad
845f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, rop);
846c7d8ba24Smacallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, bg);
847647d0c59Smacallan bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent,
848647d0c59Smacallan (w - 1) | ((h - 1) << 11));
849f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fill,
850f8fb75a4Stsutsui x | (y << 11) | 0x80000000);
851ca0ac2c7Sad }
852ca0ac2c7Sad
853c7d8ba24Smacallan static void
zx_copyrect(struct zx_softc * sc,int sx,int sy,int dx,int dy,int w,int h)854c7d8ba24Smacallan zx_copyrect(struct zx_softc *sc, int sx, int sy, int dx, int dy, int w,
855ca0ac2c7Sad int h)
856ca0ac2c7Sad {
857c7d8ba24Smacallan uint32_t dir;
858ca0ac2c7Sad
8597190e17cSmacallan w -= 1;
8607190e17cSmacallan h -= 1;
8617190e17cSmacallan
862ca0ac2c7Sad if (sy < dy || sx < dx) {
863ca0ac2c7Sad dir = 0x80000000;
864ca0ac2c7Sad sx += w;
865ca0ac2c7Sad sy += h;
866ca0ac2c7Sad dx += w;
867ca0ac2c7Sad dy += h;
868ca0ac2c7Sad } else
869ca0ac2c7Sad dir = 0;
870ca0ac2c7Sad
871f8fb75a4Stsutsui while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) &
872f8fb75a4Stsutsui ZX_CSR_BLT_BUSY) != 0)
873ca0ac2c7Sad ;
874ca0ac2c7Sad
875f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP);
876f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent,
877f8fb75a4Stsutsui w | (h << 11) | dir);
878f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_src, sx | (sy << 11));
879f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_copy, dx | (dy << 11));
880ca0ac2c7Sad }
881ca0ac2c7Sad
882c7d8ba24Smacallan static void
zx_do_cursor(void * cookie,int on,int row,int col)883c7d8ba24Smacallan zx_do_cursor(void *cookie, int on, int row, int col)
884ca0ac2c7Sad {
885c7d8ba24Smacallan struct rasops_info *ri = cookie;
886c7d8ba24Smacallan struct vcons_screen *scr = ri->ri_hw;
887c7d8ba24Smacallan struct zx_softc *sc = scr->scr_cookie;
888c7d8ba24Smacallan int x, y, wi, he;
889ca0ac2c7Sad
890c7d8ba24Smacallan wi = ri->ri_font->fontwidth;
891c7d8ba24Smacallan he = ri->ri_font->fontheight;
892c7d8ba24Smacallan
893c7d8ba24Smacallan if (ri->ri_flg & RI_CURSOR) {
894c7d8ba24Smacallan x = ri->ri_ccol * wi + ri->ri_xorigin;
895c7d8ba24Smacallan y = ri->ri_crow * he + ri->ri_yorigin;
896c7d8ba24Smacallan zx_fillrect(sc, x, y, wi, he, 0xff000000,
897ca0ac2c7Sad ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
898ca0ac2c7Sad ZX_ATTR_FORCE_WID);
899c7d8ba24Smacallan ri->ri_flg &= ~RI_CURSOR;
900ca0ac2c7Sad }
901ca0ac2c7Sad
902c7d8ba24Smacallan ri->ri_crow = row;
903c7d8ba24Smacallan ri->ri_ccol = col;
904c7d8ba24Smacallan
905c7d8ba24Smacallan if (on)
906ca0ac2c7Sad {
907c7d8ba24Smacallan x = ri->ri_ccol * wi + ri->ri_xorigin;
908c7d8ba24Smacallan y = ri->ri_crow * he + ri->ri_yorigin;
909c7d8ba24Smacallan zx_fillrect(sc, x, y, wi, he, 0xff000000,
910c7d8ba24Smacallan ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
911c7d8ba24Smacallan ZX_ATTR_FORCE_WID);
912c7d8ba24Smacallan ri->ri_flg |= RI_CURSOR;
913c7d8ba24Smacallan }
914ca0ac2c7Sad }
915ca0ac2c7Sad
916c7d8ba24Smacallan static void
zx_erasecols(void * cookie,int row,int startcol,int ncols,long attr)917c7d8ba24Smacallan zx_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
918ca0ac2c7Sad {
919c7d8ba24Smacallan struct rasops_info *ri = cookie;
920c7d8ba24Smacallan struct vcons_screen *scr = ri->ri_hw;
921c7d8ba24Smacallan struct zx_softc *sc = scr->scr_cookie;
922c7d8ba24Smacallan int32_t x, y, width, height, bg;
923ca0ac2c7Sad
924c7d8ba24Smacallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
925c7d8ba24Smacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row;
926c7d8ba24Smacallan width = ri->ri_font->fontwidth * ncols;
927c7d8ba24Smacallan height = ri->ri_font->fontheight;
928c7d8ba24Smacallan bg = ((uint32_t)ri->ri_devcmap[(attr >> 16) & 0xff]) << 24;
929c7d8ba24Smacallan zx_fillrect(sc, x, y, width, height, bg, ZX_STD_ROP);
930ca0ac2c7Sad }
931ca0ac2c7Sad
932c7d8ba24Smacallan static void
zx_eraserows(void * cookie,int row,int nrows,long attr)933c7d8ba24Smacallan zx_eraserows(void *cookie, int row, int nrows, long attr)
934ca0ac2c7Sad {
935c7d8ba24Smacallan struct rasops_info *ri = cookie;
936c7d8ba24Smacallan struct vcons_screen *scr = ri->ri_hw;
937c7d8ba24Smacallan struct zx_softc *sc = scr->scr_cookie;
938c7d8ba24Smacallan int32_t x, y, width, height, bg;
939ca0ac2c7Sad
940c7d8ba24Smacallan if ((row == 0) && (nrows == ri->ri_rows)) {
941c7d8ba24Smacallan x = y = 0;
942c7d8ba24Smacallan width = ri->ri_width;
943c7d8ba24Smacallan height = ri->ri_height;
944c7d8ba24Smacallan } else {
945c7d8ba24Smacallan x = ri->ri_xorigin;
946c7d8ba24Smacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row;
947c7d8ba24Smacallan width = ri->ri_emuwidth;
948c7d8ba24Smacallan height = ri->ri_font->fontheight * nrows;
949c7d8ba24Smacallan }
950c7d8ba24Smacallan bg = ((uint32_t)ri->ri_devcmap[(attr >> 16) & 0xff]) << 24;
951c7d8ba24Smacallan zx_fillrect(sc, x, y, width, height, bg, ZX_STD_ROP);
952ca0ac2c7Sad }
953ca0ac2c7Sad
954c7d8ba24Smacallan static void
zx_copyrows(void * cookie,int srcrow,int dstrow,int nrows)955c7d8ba24Smacallan zx_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
956ca0ac2c7Sad {
957c7d8ba24Smacallan struct rasops_info *ri = cookie;
958c7d8ba24Smacallan struct vcons_screen *scr = ri->ri_hw;
959c7d8ba24Smacallan struct zx_softc *sc = scr->scr_cookie;
960c7d8ba24Smacallan int32_t x, ys, yd, width, height;
961ca0ac2c7Sad
962c7d8ba24Smacallan x = ri->ri_xorigin;
963c7d8ba24Smacallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
964c7d8ba24Smacallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
965c7d8ba24Smacallan width = ri->ri_emuwidth;
966c7d8ba24Smacallan height = ri->ri_font->fontheight * nrows;
967c7d8ba24Smacallan zx_copyrect(sc, x, ys, x, yd, width, height);
968ca0ac2c7Sad }
969ca0ac2c7Sad
970c7d8ba24Smacallan static void
zx_copycols(void * cookie,int row,int srccol,int dstcol,int ncols)971c7d8ba24Smacallan zx_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
972c7d8ba24Smacallan {
973c7d8ba24Smacallan struct rasops_info *ri = cookie;
974c7d8ba24Smacallan struct vcons_screen *scr = ri->ri_hw;
975c7d8ba24Smacallan struct zx_softc *sc = scr->scr_cookie;
976c7d8ba24Smacallan int32_t xs, xd, y, width, height;
977c7d8ba24Smacallan
978c7d8ba24Smacallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
979c7d8ba24Smacallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
980c7d8ba24Smacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row;
981c7d8ba24Smacallan width = ri->ri_font->fontwidth * ncols;
982c7d8ba24Smacallan height = ri->ri_font->fontheight;
983c7d8ba24Smacallan zx_copyrect(sc, xs, y, xd, y, width, height);
984c7d8ba24Smacallan }
985c7d8ba24Smacallan
986c7d8ba24Smacallan static void
zx_putchar(void * cookie,int row,int col,u_int uc,long attr)987ca0ac2c7Sad zx_putchar(void *cookie, int row, int col, u_int uc, long attr)
988ca0ac2c7Sad {
989c7d8ba24Smacallan struct rasops_info *ri = cookie;
9901c134541Smacallan struct wsdisplay_font *font = PICK_FONT(ri, uc);
991c7d8ba24Smacallan struct vcons_screen *scr = ri->ri_hw;
992c7d8ba24Smacallan struct zx_softc *sc = scr->scr_cookie;
993579b9cbdStsutsui volatile uint32_t *dp;
994579b9cbdStsutsui uint8_t *fb;
995c7d8ba24Smacallan int fs, i, ul;
996c7d8ba24Smacallan uint32_t fg, bg;
997ca0ac2c7Sad
998c7d8ba24Smacallan rasops_unpack_attr(attr, &fg, &bg, &ul);
999c7d8ba24Smacallan bg = ((uint32_t)ri->ri_devcmap[bg]) << 24;
1000c7d8ba24Smacallan fg = ((uint32_t)ri->ri_devcmap[fg]) << 24;
1001ca0ac2c7Sad if (uc == ' ') {
1002c7d8ba24Smacallan int x, y;
1003c7d8ba24Smacallan
10041c134541Smacallan x = ri->ri_xorigin + font->fontwidth * col;
10051c134541Smacallan y = ri->ri_yorigin + font->fontheight * row;
10061c134541Smacallan zx_fillrect(sc, x, y, font->fontwidth,
10071c134541Smacallan font->fontheight, bg, ZX_STD_ROP);
1008ca0ac2c7Sad return;
1009ca0ac2c7Sad }
1010ca0ac2c7Sad
1011579b9cbdStsutsui dp = (volatile uint32_t *)sc->sc_pixels +
1012c7d8ba24Smacallan ((row * font->fontheight + ri->ri_yorigin) << 11) +
1013c7d8ba24Smacallan (col * font->fontwidth + ri->ri_xorigin);
1014579b9cbdStsutsui fb = (uint8_t *)font->data + (uc - font->firstchar) *
1015ca0ac2c7Sad ri->ri_fontscale;
1016ca0ac2c7Sad fs = font->stride;
1017ca0ac2c7Sad
1018f8fb75a4Stsutsui while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) &
1019f8fb75a4Stsutsui ZX_CSR_BLT_BUSY) != 0)
1020ca0ac2c7Sad ;
1021ca0ac2c7Sad
1022f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP);
1023c7d8ba24Smacallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, fg);
1024c7d8ba24Smacallan bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_bg, bg);
1025f8fb75a4Stsutsui bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fontmsk,
1026c7d8ba24Smacallan 0xffffffff << (32 - font->fontwidth));
1027ca0ac2c7Sad
1028c7d8ba24Smacallan if (font->fontwidth <= 8) {
1029c7d8ba24Smacallan for (i = font->fontheight; i != 0; i--, dp += 2048) {
1030ca0ac2c7Sad *dp = *fb << 24;
1031ca0ac2c7Sad fb += fs;
1032ca0ac2c7Sad }
1033ca0ac2c7Sad } else {
1034c7d8ba24Smacallan for (i = font->fontheight; i != 0; i--, dp += 2048) {
1035579b9cbdStsutsui *dp = *((uint16_t *)fb) << 16;
1036ca0ac2c7Sad fb += fs;
1037ca0ac2c7Sad }
1038ca0ac2c7Sad }
1039ca0ac2c7Sad
1040ca0ac2c7Sad if (ul) {
1041ca0ac2c7Sad dp -= 4096;
1042ca0ac2c7Sad *dp = 0xffffffff;
1043ca0ac2c7Sad }
1044ca0ac2c7Sad }
1045c7d8ba24Smacallan
1046c7d8ba24Smacallan static int
zx_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)1047c7d8ba24Smacallan zx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
1048c7d8ba24Smacallan struct lwp *l)
1049c7d8ba24Smacallan {
1050c7d8ba24Smacallan /* we'll probably need to add more stuff here */
1051c7d8ba24Smacallan struct vcons_data *vd = v;
1052c7d8ba24Smacallan struct zx_softc *sc = vd->cookie;
1053c7d8ba24Smacallan struct wsdisplay_fbinfo *wdf;
1054c7d8ba24Smacallan struct vcons_screen *ms = sc->vd.active;
105594553692Smacallan struct rasops_info *ri = &ms->scr_ri;
1056c7d8ba24Smacallan switch (cmd) {
1057c7d8ba24Smacallan case WSDISPLAYIO_GTYPE:
1058c7d8ba24Smacallan *(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
1059c7d8ba24Smacallan return 0;
1060c7d8ba24Smacallan case WSDISPLAYIO_GINFO:
1061c7d8ba24Smacallan wdf = (void *)data;
1062c7d8ba24Smacallan wdf->height = ri->ri_height;
1063c7d8ba24Smacallan wdf->width = ri->ri_width;
1064c7d8ba24Smacallan wdf->depth = ri->ri_depth;
1065c7d8ba24Smacallan wdf->cmsize = 256;
1066c7d8ba24Smacallan return 0;
1067c7d8ba24Smacallan
1068c7d8ba24Smacallan case WSDISPLAYIO_GETCMAP:
1069c7d8ba24Smacallan return zx_getcmap(sc,
1070c7d8ba24Smacallan (struct wsdisplay_cmap *)data);
1071c7d8ba24Smacallan case WSDISPLAYIO_PUTCMAP:
1072c7d8ba24Smacallan return zx_putcmap(sc,
1073c7d8ba24Smacallan (struct wsdisplay_cmap *)data);
1074c7d8ba24Smacallan
1075c7d8ba24Smacallan case WSDISPLAYIO_SMODE:
1076c7d8ba24Smacallan {
1077c7d8ba24Smacallan int new_mode = *(int*)data;
1078c7d8ba24Smacallan if (new_mode != sc->sc_mode)
1079c7d8ba24Smacallan {
1080c7d8ba24Smacallan sc->sc_mode = new_mode;
1081c7d8ba24Smacallan if(new_mode == WSDISPLAYIO_MODE_EMUL)
1082c7d8ba24Smacallan {
1083647d0c59Smacallan zx_reset(sc);
1084c7d8ba24Smacallan vcons_redraw_screen(ms);
1085c7d8ba24Smacallan }
1086c7d8ba24Smacallan }
1087c7d8ba24Smacallan }
108894553692Smacallan return 0;
1089c7d8ba24Smacallan }
1090c7d8ba24Smacallan return EPASSTHROUGH;
1091c7d8ba24Smacallan }
1092c7d8ba24Smacallan
1093c7d8ba24Smacallan static paddr_t
zx_mmap(void * v,void * vs,off_t offset,int prot)1094c7d8ba24Smacallan zx_mmap(void *v, void *vs, off_t offset, int prot)
1095c7d8ba24Smacallan {
1096c7d8ba24Smacallan /* I'm not at all sure this is the right thing to do */
1097c7d8ba24Smacallan return zxmmap(0, offset, prot); /* assume minor dev 0 for now */
1098c7d8ba24Smacallan }
1099c7d8ba24Smacallan
1100c7d8ba24Smacallan static int
zx_putcmap(struct zx_softc * sc,struct wsdisplay_cmap * cm)1101c7d8ba24Smacallan zx_putcmap(struct zx_softc *sc, struct wsdisplay_cmap *cm)
1102c7d8ba24Smacallan {
1103c7d8ba24Smacallan u_int index = cm->index;
1104c7d8ba24Smacallan u_int count = cm->count;
1105c7d8ba24Smacallan int error,i;
1106c7d8ba24Smacallan if (index >= 256 || count > 256 || index + count > 256)
1107c7d8ba24Smacallan return EINVAL;
1108c7d8ba24Smacallan
1109c7d8ba24Smacallan for (i = 0; i < count; i++)
1110c7d8ba24Smacallan {
1111c7d8ba24Smacallan error = copyin(&cm->red[i],
1112c7d8ba24Smacallan &sc->sc_cmap[index + i], 1);
1113c7d8ba24Smacallan if (error)
1114c7d8ba24Smacallan return error;
1115c7d8ba24Smacallan error = copyin(&cm->green[i],
1116c7d8ba24Smacallan &sc->sc_cmap[index + i + 256], 1);
1117c7d8ba24Smacallan if (error)
1118c7d8ba24Smacallan return error;
1119c7d8ba24Smacallan error = copyin(&cm->blue[i],
1120c7d8ba24Smacallan &sc->sc_cmap[index + i + 512], 1);
1121c7d8ba24Smacallan if (error)
1122c7d8ba24Smacallan return error;
1123c7d8ba24Smacallan }
1124c7d8ba24Smacallan zx_cmap_put(sc);
1125c7d8ba24Smacallan
1126c7d8ba24Smacallan return 0;
1127c7d8ba24Smacallan }
1128c7d8ba24Smacallan
1129c7d8ba24Smacallan static int
zx_getcmap(struct zx_softc * sc,struct wsdisplay_cmap * cm)1130c7d8ba24Smacallan zx_getcmap(struct zx_softc *sc, struct wsdisplay_cmap *cm)
1131c7d8ba24Smacallan {
1132c7d8ba24Smacallan u_int index = cm->index;
1133c7d8ba24Smacallan u_int count = cm->count;
1134c7d8ba24Smacallan int error,i;
1135c7d8ba24Smacallan
1136c7d8ba24Smacallan if (index >= 256 || count > 256 || index + count > 256)
1137c7d8ba24Smacallan return EINVAL;
1138c7d8ba24Smacallan
1139c7d8ba24Smacallan for (i = 0; i < count; i++)
1140c7d8ba24Smacallan {
1141c7d8ba24Smacallan error = copyout(&sc->sc_cmap[index + i],
1142c7d8ba24Smacallan &cm->red[i], 1);
1143c7d8ba24Smacallan if (error)
1144c7d8ba24Smacallan return error;
1145c7d8ba24Smacallan error = copyout(&sc->sc_cmap[index + i + 256],
1146c7d8ba24Smacallan &cm->green[i], 1);
1147c7d8ba24Smacallan if (error)
1148c7d8ba24Smacallan return error;
1149c7d8ba24Smacallan error = copyout(&sc->sc_cmap[index + i + 256],
1150c7d8ba24Smacallan &cm->blue[i], 1);
1151c7d8ba24Smacallan if (error)
1152c7d8ba24Smacallan return error;
1153c7d8ba24Smacallan }
1154c7d8ba24Smacallan
1155c7d8ba24Smacallan return 0;
1156c7d8ba24Smacallan }
1157c7d8ba24Smacallan
1158c7d8ba24Smacallan static void
zx_init_screen(void * cookie,struct vcons_screen * scr,int existing,long * defattr)1159c7d8ba24Smacallan zx_init_screen(void *cookie, struct vcons_screen *scr,
1160c7d8ba24Smacallan int existing, long *defattr)
1161c7d8ba24Smacallan {
1162c7d8ba24Smacallan struct zx_softc *sc = cookie;
1163c7d8ba24Smacallan struct rasops_info *ri = &scr->scr_ri;
1164c7d8ba24Smacallan
1165c7d8ba24Smacallan ri->ri_depth = 8; /*sc->sc_fb.fb_type.fb_depth = 32;*/
1166c7d8ba24Smacallan ri->ri_width = sc->sc_width;
1167c7d8ba24Smacallan ri->ri_height = sc->sc_height;
1168c7d8ba24Smacallan ri->ri_stride = sc->sc_stride;
1169c7d8ba24Smacallan ri->ri_flg = RI_CENTER;
1170c7d8ba24Smacallan
1171c7d8ba24Smacallan ri->ri_bits = (void *)sc->sc_pixels;
1172c7d8ba24Smacallan
11732cbec7eeSmacallan rasops_init(ri, 0, 0);
1174c7d8ba24Smacallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1175c7d8ba24Smacallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
1176c7d8ba24Smacallan sc->sc_width / ri->ri_font->fontwidth);
1177c7d8ba24Smacallan
1178c7d8ba24Smacallan ri->ri_hw = scr;
1179c7d8ba24Smacallan
1180c7d8ba24Smacallan ri->ri_ops.cursor = zx_do_cursor;
1181c7d8ba24Smacallan ri->ri_ops.copycols = zx_copycols;
1182c7d8ba24Smacallan ri->ri_ops.copyrows = zx_copyrows;
1183c7d8ba24Smacallan ri->ri_ops.erasecols = zx_erasecols;
1184c7d8ba24Smacallan ri->ri_ops.eraserows = zx_eraserows;
1185c7d8ba24Smacallan ri->ri_ops.putchar = zx_putchar;
1186c7d8ba24Smacallan }
1187