xref: /netbsd-src/sys/arch/hp300/dev/gbox.c (revision 2ba8a55cfaf2b31db74983421e8bb25efeb13434)
1*2ba8a55cStsutsui /*	$NetBSD: gbox.c,v 1.3 2011/02/18 19:15:43 tsutsui Exp $	*/
2b04b7da8Stsutsui /*	$OpenBSD: gbox.c,v 1.15 2007/01/07 15:13:52 miod Exp $	*/
3b04b7da8Stsutsui 
4b04b7da8Stsutsui /*
5b04b7da8Stsutsui  * Copyright (c) 2005, Miodrag Vallat
6b04b7da8Stsutsui  *
7b04b7da8Stsutsui  * Redistribution and use in source and binary forms, with or without
8b04b7da8Stsutsui  * modification, are permitted provided that the following conditions
9b04b7da8Stsutsui  * are met:
10b04b7da8Stsutsui  * 1. Redistributions of source code must retain the above copyright
11b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer.
12b04b7da8Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
13b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer in the
14b04b7da8Stsutsui  *    documentation and/or other materials provided with the distribution.
15b04b7da8Stsutsui  *
16b04b7da8Stsutsui  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17b04b7da8Stsutsui  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18b04b7da8Stsutsui  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19b04b7da8Stsutsui  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20b04b7da8Stsutsui  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21b04b7da8Stsutsui  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22b04b7da8Stsutsui  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23b04b7da8Stsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24b04b7da8Stsutsui  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25b04b7da8Stsutsui  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b04b7da8Stsutsui  * POSSIBILITY OF SUCH DAMAGE.
27b04b7da8Stsutsui  */
28b04b7da8Stsutsui /*-
29b04b7da8Stsutsui  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
30b04b7da8Stsutsui  * All rights reserved.
31b04b7da8Stsutsui  *
32b04b7da8Stsutsui  * This code is derived from software contributed to The NetBSD Foundation
33b04b7da8Stsutsui  * by Jason R. Thorpe.
34b04b7da8Stsutsui  *
35b04b7da8Stsutsui  * Redistribution and use in source and binary forms, with or without
36b04b7da8Stsutsui  * modification, are permitted provided that the following conditions
37b04b7da8Stsutsui  * are met:
38b04b7da8Stsutsui  * 1. Redistributions of source code must retain the above copyright
39b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer.
40b04b7da8Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
41b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer in the
42b04b7da8Stsutsui  *    documentation and/or other materials provided with the distribution.
43b04b7da8Stsutsui  *
44b04b7da8Stsutsui  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
45b04b7da8Stsutsui  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46b04b7da8Stsutsui  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47b04b7da8Stsutsui  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
48b04b7da8Stsutsui  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49b04b7da8Stsutsui  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50b04b7da8Stsutsui  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51b04b7da8Stsutsui  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52b04b7da8Stsutsui  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53b04b7da8Stsutsui  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54b04b7da8Stsutsui  * POSSIBILITY OF SUCH DAMAGE.
55b04b7da8Stsutsui  */
56b04b7da8Stsutsui 
57b04b7da8Stsutsui /*
58b04b7da8Stsutsui  * Copyright (c) 1988 University of Utah.
59b04b7da8Stsutsui  * Copyright (c) 1990, 1993
60b04b7da8Stsutsui  *	The Regents of the University of California.  All rights reserved.
61b04b7da8Stsutsui  *
62b04b7da8Stsutsui  * This code is derived from software contributed to Berkeley by
63b04b7da8Stsutsui  * the Systems Programming Group of the University of Utah Computer
64b04b7da8Stsutsui  * Science Department.
65b04b7da8Stsutsui  *
66b04b7da8Stsutsui  * Redistribution and use in source and binary forms, with or without
67b04b7da8Stsutsui  * modification, are permitted provided that the following conditions
68b04b7da8Stsutsui  * are met:
69b04b7da8Stsutsui  * 1. Redistributions of source code must retain the above copyright
70b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer.
71b04b7da8Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
72b04b7da8Stsutsui  *    notice, this list of conditions and the following disclaimer in the
73b04b7da8Stsutsui  *    documentation and/or other materials provided with the distribution.
74b04b7da8Stsutsui  * 3. Neither the name of the University nor the names of its contributors
75b04b7da8Stsutsui  *    may be used to endorse or promote products derived from this software
76b04b7da8Stsutsui  *    without specific prior written permission.
77b04b7da8Stsutsui  *
78b04b7da8Stsutsui  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
79b04b7da8Stsutsui  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80b04b7da8Stsutsui  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81b04b7da8Stsutsui  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
82b04b7da8Stsutsui  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83b04b7da8Stsutsui  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84b04b7da8Stsutsui  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85b04b7da8Stsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86b04b7da8Stsutsui  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87b04b7da8Stsutsui  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88b04b7da8Stsutsui  * SUCH DAMAGE.
89b04b7da8Stsutsui  *
90b04b7da8Stsutsui  * from: Utah $Hdr: grf_gb.c 1.18 93/08/13$
91b04b7da8Stsutsui  *
92b04b7da8Stsutsui  *	@(#)grf_gb.c	8.4 (Berkeley) 1/12/94
93b04b7da8Stsutsui  */
94b04b7da8Stsutsui 
95b04b7da8Stsutsui /*
96b04b7da8Stsutsui  * Graphics routines for the Gatorbox.
97b04b7da8Stsutsui  *
98b04b7da8Stsutsui  * Note: In the context of this system, "gator" and "gatorbox" both refer to
99b04b7da8Stsutsui  *       HP 987x0 graphics systems.  "Gator" is not used for high res mono.
100b04b7da8Stsutsui  *       (as in 9837 Gator systems)
101b04b7da8Stsutsui  */
102b04b7da8Stsutsui 
103b04b7da8Stsutsui #include <sys/param.h>
104b04b7da8Stsutsui #include <sys/systm.h>
105b04b7da8Stsutsui #include <sys/conf.h>
106b04b7da8Stsutsui #include <sys/device.h>
107b04b7da8Stsutsui #include <sys/proc.h>
108b04b7da8Stsutsui #include <sys/ioctl.h>
109b04b7da8Stsutsui #include <sys/bus.h>
110b04b7da8Stsutsui #include <sys/cpu.h>
111b04b7da8Stsutsui 
112b04b7da8Stsutsui #include <machine/autoconf.h>
113b04b7da8Stsutsui 
114b04b7da8Stsutsui #include <hp300/dev/dioreg.h>
115b04b7da8Stsutsui #include <hp300/dev/diovar.h>
116b04b7da8Stsutsui #include <hp300/dev/diodevs.h>
117b04b7da8Stsutsui #include <hp300/dev/intiovar.h>
118b04b7da8Stsutsui 
119b04b7da8Stsutsui #include <dev/wscons/wsconsio.h>
120b04b7da8Stsutsui #include <dev/wscons/wsdisplayvar.h>
121b04b7da8Stsutsui #include <dev/rasops/rasops.h>
122b04b7da8Stsutsui 
123b04b7da8Stsutsui #include <hp300/dev/diofbreg.h>
124b04b7da8Stsutsui #include <hp300/dev/diofbvar.h>
125b04b7da8Stsutsui #include <hp300/dev/gboxreg.h>
126b04b7da8Stsutsui 
127b04b7da8Stsutsui struct	gbox_softc {
128b04b7da8Stsutsui 	device_t	sc_dev;
129b04b7da8Stsutsui 	struct diofb	*sc_fb;
130b04b7da8Stsutsui 	struct diofb	sc_fb_store;
131b04b7da8Stsutsui 	int		sc_scode;
132b04b7da8Stsutsui };
133b04b7da8Stsutsui 
1345d7f465dStsutsui static int	gbox_dio_match(device_t, cfdata_t, void *);
1355d7f465dStsutsui static void	gbox_dio_attach(device_t, device_t, void *);
1365d7f465dStsutsui static int	gbox_intio_match(device_t, cfdata_t, void *);
1375d7f465dStsutsui static void	gbox_intio_attach(device_t, device_t, void *);
138b04b7da8Stsutsui 
139b04b7da8Stsutsui CFATTACH_DECL_NEW(gbox_dio, sizeof(struct gbox_softc),
140b04b7da8Stsutsui     gbox_dio_match, gbox_dio_attach, NULL, NULL);
141b04b7da8Stsutsui 
142b04b7da8Stsutsui CFATTACH_DECL_NEW(gbox_intio, sizeof(struct gbox_softc),
143b04b7da8Stsutsui     gbox_intio_match, gbox_intio_attach, NULL, NULL);
144b04b7da8Stsutsui 
1455d7f465dStsutsui static int	gbox_reset(struct diofb *, int, struct diofbreg *);
1465d7f465dStsutsui static void	gbox_restore(struct diofb *);
1475d7f465dStsutsui static int	gbox_setcmap(struct diofb *, struct wsdisplay_cmap *);
1485d7f465dStsutsui static void	gbox_setcolor(struct diofb *, u_int);
1495d7f465dStsutsui static int	gbox_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t,
1505d7f465dStsutsui 		    uint16_t, uint16_t, uint16_t, int16_t, int16_t);
151b04b7da8Stsutsui 
1525d7f465dStsutsui static int	gbox_ioctl(void *, void *, u_long, void *, int, struct lwp *);
153b04b7da8Stsutsui 
1545d7f465dStsutsui static struct wsdisplay_accessops gbox_accessops = {
155b04b7da8Stsutsui 	gbox_ioctl,
156b04b7da8Stsutsui 	diofb_mmap,
157b04b7da8Stsutsui 	diofb_alloc_screen,
158b04b7da8Stsutsui 	diofb_free_screen,
159b04b7da8Stsutsui 	diofb_show_screen,
160b04b7da8Stsutsui 	NULL,   /* load_font */
161b04b7da8Stsutsui };
162b04b7da8Stsutsui 
163b04b7da8Stsutsui /*
164b04b7da8Stsutsui  * Attachment glue
165b04b7da8Stsutsui  */
166b04b7da8Stsutsui int
gbox_intio_match(device_t parent,cfdata_t cf,void * aux)167b04b7da8Stsutsui gbox_intio_match(device_t parent, cfdata_t cf, void *aux)
168b04b7da8Stsutsui {
169b04b7da8Stsutsui 	struct intio_attach_args *ia = aux;
170b04b7da8Stsutsui 	struct diofbreg *fbr;
171b04b7da8Stsutsui 
172b04b7da8Stsutsui 	if (strcmp("fb", ia->ia_modname) != 0)
173b04b7da8Stsutsui 		return 0;
174b04b7da8Stsutsui 
175b04b7da8Stsutsui 	fbr = (struct diofbreg *)ia->ia_addr;
176b04b7da8Stsutsui 
177b04b7da8Stsutsui 	if (badaddr((void *)fbr))
1785d7f465dStsutsui 		return 0;
179b04b7da8Stsutsui 
180b04b7da8Stsutsui 	if (fbr->id == GRFHWID && fbr->fbid == GID_GATORBOX) {
1815d7f465dStsutsui 		return 1;
182b04b7da8Stsutsui 	}
183b04b7da8Stsutsui 
1845d7f465dStsutsui 	return 0;
185b04b7da8Stsutsui }
186b04b7da8Stsutsui 
187b04b7da8Stsutsui void
gbox_intio_attach(device_t parent,device_t self,void * aux)188b04b7da8Stsutsui gbox_intio_attach(device_t parent, device_t self, void *aux)
189b04b7da8Stsutsui {
190b04b7da8Stsutsui 	struct gbox_softc *sc = device_private(self);
191b04b7da8Stsutsui 	struct intio_attach_args *ia = aux;
192b04b7da8Stsutsui 	struct diofbreg *fbr;
193b04b7da8Stsutsui 
194b04b7da8Stsutsui 	sc->sc_dev = self;
195b04b7da8Stsutsui 	fbr = (struct diofbreg *)ia->ia_addr;
196b04b7da8Stsutsui 	sc->sc_scode = CONSCODE_INTERNAL;
197b04b7da8Stsutsui 
198b04b7da8Stsutsui 	if (sc->sc_scode == conscode) {
199b04b7da8Stsutsui 		sc->sc_fb = &diofb_cn;
200b04b7da8Stsutsui 	} else {
201b04b7da8Stsutsui 		sc->sc_fb = &sc->sc_fb_store;
202b04b7da8Stsutsui 		gbox_reset(sc->sc_fb, sc->sc_scode, fbr);
203b04b7da8Stsutsui 	}
204b04b7da8Stsutsui 
205b04b7da8Stsutsui 	diofb_end_attach(self, &gbox_accessops, sc->sc_fb,
206b04b7da8Stsutsui 	    sc->sc_scode == conscode, NULL);
207b04b7da8Stsutsui }
208b04b7da8Stsutsui 
209b04b7da8Stsutsui int
gbox_dio_match(device_t parent,cfdata_t cf,void * aux)210b04b7da8Stsutsui gbox_dio_match(device_t parent, cfdata_t cf, void *aux)
211b04b7da8Stsutsui {
212b04b7da8Stsutsui 	struct dio_attach_args *da = aux;
213b04b7da8Stsutsui 
214b04b7da8Stsutsui 	/* We can not appear in DIO-II space */
215b04b7da8Stsutsui 	if (DIO_ISDIOII(da->da_scode))
2165d7f465dStsutsui 		return 0;
217b04b7da8Stsutsui 
218b04b7da8Stsutsui 	if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER &&
219b04b7da8Stsutsui 	    da->da_secid == DIO_DEVICE_SECID_GATORBOX)
2205d7f465dStsutsui 		return 1;
221b04b7da8Stsutsui 
2225d7f465dStsutsui 	return 0;
223b04b7da8Stsutsui }
224b04b7da8Stsutsui 
225b04b7da8Stsutsui void
gbox_dio_attach(device_t parent,device_t self,void * aux)226b04b7da8Stsutsui gbox_dio_attach(device_t parent, device_t self, void *aux)
227b04b7da8Stsutsui {
228b04b7da8Stsutsui 	struct gbox_softc *sc = device_private(self);
229b04b7da8Stsutsui 	struct dio_attach_args *da = aux;
230b04b7da8Stsutsui 	bus_space_handle_t bsh;
231b04b7da8Stsutsui 	struct diofbreg * fbr;
232b04b7da8Stsutsui 
233b04b7da8Stsutsui 	sc->sc_dev = self;
234b04b7da8Stsutsui 	sc->sc_scode = da->da_scode;
235b04b7da8Stsutsui 	if (sc->sc_scode == conscode) {
236b04b7da8Stsutsui 		fbr = (struct diofbreg *)conaddr;	/* already mapped */
237b04b7da8Stsutsui 		sc->sc_fb = &diofb_cn;
238b04b7da8Stsutsui 	} else {
239b04b7da8Stsutsui 		sc->sc_fb = &sc->sc_fb_store;
240b04b7da8Stsutsui 		if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0,
241b04b7da8Stsutsui 		    &bsh)) {
242b04b7da8Stsutsui 			aprint_error(": can't map framebuffer\n");
243b04b7da8Stsutsui 			return;
244b04b7da8Stsutsui 		}
245b04b7da8Stsutsui 		fbr = bus_space_vaddr(da->da_bst, bsh);
246b04b7da8Stsutsui 		if (gbox_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) {
247*2ba8a55cStsutsui 			aprint_error(": can't reset framebuffer\n");
248b04b7da8Stsutsui 			return;
249b04b7da8Stsutsui 		}
250b04b7da8Stsutsui 	}
251b04b7da8Stsutsui 
252b04b7da8Stsutsui 	diofb_end_attach(self, &gbox_accessops, sc->sc_fb,
253b04b7da8Stsutsui 	    sc->sc_scode == conscode, NULL);
254b04b7da8Stsutsui }
255b04b7da8Stsutsui 
256b04b7da8Stsutsui /*
257b04b7da8Stsutsui  * Initialize hardware and display routines.
258b04b7da8Stsutsui  */
259b04b7da8Stsutsui 
2605d7f465dStsutsui const uint8_t crtc_init_data[] = {
261b04b7da8Stsutsui     0x29, 0x20, 0x23, 0x04, 0x30, 0x0b, 0x30,
262b04b7da8Stsutsui     0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00
263b04b7da8Stsutsui };
264b04b7da8Stsutsui 
265b04b7da8Stsutsui int
gbox_reset(struct diofb * fb,int scode,struct diofbreg * fbr)266b04b7da8Stsutsui gbox_reset(struct diofb *fb, int scode, struct diofbreg *fbr)
267b04b7da8Stsutsui {
268b04b7da8Stsutsui 	int rc;
269b04b7da8Stsutsui 	u_int i;
270b04b7da8Stsutsui 
271b04b7da8Stsutsui 	/* XXX don't trust hardware, force defaults */
272b04b7da8Stsutsui 	fb->fbwidth = 1024;
273b04b7da8Stsutsui 	fb->fbheight = 1024;
274b04b7da8Stsutsui 	fb->dwidth = 1024;
275b04b7da8Stsutsui 	fb->dheight = 768;
276b04b7da8Stsutsui 	if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0)
2775d7f465dStsutsui 		return rc;
278b04b7da8Stsutsui 
279b04b7da8Stsutsui 	fb->bmv = gbox_windowmove;
280b04b7da8Stsutsui 	gbox_restore(fb);
281b04b7da8Stsutsui 
282b04b7da8Stsutsui 	/*
283b04b7da8Stsutsui 	 * Find out how many colors are available by determining
284b04b7da8Stsutsui 	 * which planes are installed.  That is, write all ones to
285b04b7da8Stsutsui 	 * a frame buffer location, see how many ones are read back.
286b04b7da8Stsutsui 	 */
287b04b7da8Stsutsui 	if (1 /* fb->planes == 0 */) {
2885d7f465dStsutsui 		volatile uint8_t *fbp;
2895d7f465dStsutsui 		uint8_t save;
290b04b7da8Stsutsui 
2915d7f465dStsutsui 		fbp = (uint8_t *)fb->fbkva;
292b04b7da8Stsutsui 		save = *fbp;
293b04b7da8Stsutsui 		*fbp = 0xff;
294b04b7da8Stsutsui 		fb->planemask = *fbp;
295b04b7da8Stsutsui 		*fbp = save;
296b04b7da8Stsutsui 
297b04b7da8Stsutsui 		for (fb->planes = 1; fb->planemask >= (1 << fb->planes);
298b04b7da8Stsutsui 		    fb->planes++);
299b04b7da8Stsutsui 		if (fb->planes > 8)
300b04b7da8Stsutsui 			fb->planes = 8;
301b04b7da8Stsutsui 		fb->planemask = (1 << fb->planes) - 1;
302b04b7da8Stsutsui 	}
303b04b7da8Stsutsui 
304b04b7da8Stsutsui 	diofb_fbsetup(fb);
305b04b7da8Stsutsui 	for (i = 0; i <= fb->planemask; i++)
306b04b7da8Stsutsui 		gbox_setcolor(fb, i);
307b04b7da8Stsutsui 
3085d7f465dStsutsui 	return 0;
309b04b7da8Stsutsui }
310b04b7da8Stsutsui 
311b04b7da8Stsutsui void
gbox_restore(struct diofb * fb)312b04b7da8Stsutsui gbox_restore(struct diofb *fb)
313b04b7da8Stsutsui {
314b04b7da8Stsutsui 	volatile struct gboxfb *gb = (struct gboxfb *)fb->regkva;
315b04b7da8Stsutsui 	u_int i;
316b04b7da8Stsutsui 
317b04b7da8Stsutsui 	/*
318b04b7da8Stsutsui 	 * The minimal info here is from the Gatorbox X driver.
319b04b7da8Stsutsui 	 */
320b04b7da8Stsutsui 	gb->write_protect = 0x0;
321b04b7da8Stsutsui 	gb->regs.interrupt = 0x4;
322b04b7da8Stsutsui 	gb->rep_rule = RR_COPY;
323b04b7da8Stsutsui 	gb->blink1 = 0xff;
324b04b7da8Stsutsui 	gb->blink2 = 0xff;
325b04b7da8Stsutsui 
326b04b7da8Stsutsui 	/*
327b04b7da8Stsutsui 	 * Program the 6845.
328b04b7da8Stsutsui 	 */
329b04b7da8Stsutsui 	for (i = 0; i < sizeof(crtc_init_data); i++) {
330b04b7da8Stsutsui 		gb->crtc_address = i;
331b04b7da8Stsutsui 		gb->crtc_data = crtc_init_data[i];
332b04b7da8Stsutsui 	}
333b04b7da8Stsutsui 
334b04b7da8Stsutsui 	tile_mover_waitbusy(gb);
335b04b7da8Stsutsui 
336b04b7da8Stsutsui 	/* Enable display */
337b04b7da8Stsutsui 	gb->regs.sec_interrupt = 0x01;
338b04b7da8Stsutsui }
339b04b7da8Stsutsui 
340b04b7da8Stsutsui int
gbox_ioctl(void * v,void * vs,u_long cmd,void * data,int flags,struct lwp * l)341b04b7da8Stsutsui gbox_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, struct lwp *l)
342b04b7da8Stsutsui {
343b04b7da8Stsutsui 	struct diofb *fb = v;
344b04b7da8Stsutsui 	struct wsdisplay_fbinfo *wdf;
345b04b7da8Stsutsui 	u_int i;
346b04b7da8Stsutsui 
347b04b7da8Stsutsui 	switch (cmd) {
348b04b7da8Stsutsui 	case WSDISPLAYIO_GTYPE:
349b04b7da8Stsutsui 		*(u_int *)data = WSDISPLAY_TYPE_GBOX;
350b04b7da8Stsutsui 		return 0;
351b04b7da8Stsutsui 	case WSDISPLAYIO_SMODE:
352b04b7da8Stsutsui 		fb->mapmode = *(u_int *)data;
353b04b7da8Stsutsui 		if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) {
354b04b7da8Stsutsui 			gbox_restore(fb);
355b04b7da8Stsutsui 			for (i = 0; i <= fb->planemask; i++)
356b04b7da8Stsutsui 				gbox_setcolor(fb, i);
357b04b7da8Stsutsui 		}
358b04b7da8Stsutsui 		return 0;
359b04b7da8Stsutsui 	case WSDISPLAYIO_GINFO:
360b04b7da8Stsutsui 		wdf = (void *)data;
361b04b7da8Stsutsui 		wdf->width = fb->ri.ri_width;
362b04b7da8Stsutsui 		wdf->height = fb->ri.ri_height;
363b04b7da8Stsutsui 		wdf->depth = fb->ri.ri_depth;
364b04b7da8Stsutsui 		wdf->cmsize = 1 << fb->planes;
365b04b7da8Stsutsui 		return 0;
366b04b7da8Stsutsui 	case WSDISPLAYIO_LINEBYTES:
367b04b7da8Stsutsui 		*(u_int *)data = fb->ri.ri_stride;
368b04b7da8Stsutsui 		return 0;
369b04b7da8Stsutsui 	case WSDISPLAYIO_GETCMAP:
3705d7f465dStsutsui 		return diofb_getcmap(fb, (struct wsdisplay_cmap *)data);
371b04b7da8Stsutsui 	case WSDISPLAYIO_PUTCMAP:
3725d7f465dStsutsui 		return gbox_setcmap(fb, (struct wsdisplay_cmap *)data);
373b04b7da8Stsutsui 	case WSDISPLAYIO_GVIDEO:
374b04b7da8Stsutsui 	case WSDISPLAYIO_SVIDEO:
375b04b7da8Stsutsui 		return EPASSTHROUGH;
376b04b7da8Stsutsui 	}
377b04b7da8Stsutsui 
378b04b7da8Stsutsui 	return EPASSTHROUGH;
379b04b7da8Stsutsui }
380b04b7da8Stsutsui 
381b04b7da8Stsutsui void
gbox_setcolor(struct diofb * fb,u_int index)382b04b7da8Stsutsui gbox_setcolor(struct diofb *fb, u_int index)
383b04b7da8Stsutsui {
384b04b7da8Stsutsui 	volatile struct gboxfb *gb = (struct gboxfb *)fb->regkva;
385b04b7da8Stsutsui 
386b04b7da8Stsutsui 	gb->creg_select = index;
387b04b7da8Stsutsui 	gb->cmap_red = fb->cmap.r[index];
388b04b7da8Stsutsui 	gb->cmap_grn = fb->cmap.g[index];
389b04b7da8Stsutsui 	gb->cmap_blu = fb->cmap.b[index];
390b04b7da8Stsutsui 	gb->cmap_write = !!index;
391b04b7da8Stsutsui 	gbcm_waitbusy(gb);
392b04b7da8Stsutsui }
393b04b7da8Stsutsui 
394b04b7da8Stsutsui int
gbox_setcmap(struct diofb * fb,struct wsdisplay_cmap * cm)395b04b7da8Stsutsui gbox_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
396b04b7da8Stsutsui {
3975d7f465dStsutsui 	uint8_t r[256], g[256], b[256];
398b04b7da8Stsutsui 	u_int index = cm->index, count = cm->count;
399b04b7da8Stsutsui 	u_int colcount = 1 << fb->planes;
400b04b7da8Stsutsui 	int error;
401b04b7da8Stsutsui 
402b04b7da8Stsutsui 	if (index >= colcount || count > colcount - index)
4035d7f465dStsutsui 		return EINVAL;
404b04b7da8Stsutsui 
405b04b7da8Stsutsui 	if ((error = copyin(cm->red, r, count)) != 0)
4065d7f465dStsutsui 		return error;
407b04b7da8Stsutsui 	if ((error = copyin(cm->green, g, count)) != 0)
4085d7f465dStsutsui 		return error;
409b04b7da8Stsutsui 	if ((error = copyin(cm->blue, b, count)) != 0)
4105d7f465dStsutsui 		return error;
411b04b7da8Stsutsui 
412b04b7da8Stsutsui 	memcpy(fb->cmap.r + index, r, count);
413b04b7da8Stsutsui 	memcpy(fb->cmap.g + index, g, count);
414b04b7da8Stsutsui 	memcpy(fb->cmap.b + index, b, count);
415b04b7da8Stsutsui 
416b04b7da8Stsutsui 	while (count-- != 0)
417b04b7da8Stsutsui 		gbox_setcolor(fb, index++);
418b04b7da8Stsutsui 
4195d7f465dStsutsui 	return 0;
420b04b7da8Stsutsui }
421b04b7da8Stsutsui 
422b04b7da8Stsutsui int
gbox_windowmove(struct diofb * fb,uint16_t sx,uint16_t sy,uint16_t dx,uint16_t dy,uint16_t cx,uint16_t cy,int16_t rop,int16_t planemask)4235d7f465dStsutsui gbox_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy,
4245d7f465dStsutsui     uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop,
425b04b7da8Stsutsui     int16_t planemask)
426b04b7da8Stsutsui {
427b04b7da8Stsutsui 	volatile struct gboxfb *gb = (struct gboxfb *)fb->regkva;
428b04b7da8Stsutsui 	int src, dest;
429b04b7da8Stsutsui 
430b04b7da8Stsutsui 	if (planemask != 0xff)
4315d7f465dStsutsui 		return EINVAL;
432b04b7da8Stsutsui 
433b04b7da8Stsutsui 	src  = (sy * 1024) + sx; /* upper left corner in pixels */
434b04b7da8Stsutsui 	dest = (dy * 1024) + dx;
435b04b7da8Stsutsui 
436b04b7da8Stsutsui 	tile_mover_waitbusy(gb);
437b04b7da8Stsutsui 
438b04b7da8Stsutsui 	gb->width = -(cx / 4);
439b04b7da8Stsutsui 	gb->height = -(cy / 4);
440b04b7da8Stsutsui 	if (src < dest)
441b04b7da8Stsutsui 		gb->rep_rule = MOVE_DOWN_RIGHT | rop;
442b04b7da8Stsutsui 	else {
443b04b7da8Stsutsui 		gb->rep_rule = MOVE_UP_LEFT | rop;
444b04b7da8Stsutsui 		/*
445b04b7da8Stsutsui 		 * Adjust to top of lower right tile of the block.
446b04b7da8Stsutsui 		 */
447b04b7da8Stsutsui 		src = src + ((cy - 4) * 1024) + (cx - 4);
448b04b7da8Stsutsui 		dest= dest + ((cy - 4) * 1024) + (cx - 4);
449b04b7da8Stsutsui 	}
4505d7f465dStsutsui 	*(volatile uint8_t *)(fb->fbkva + dest) =
4515d7f465dStsutsui 	    *(volatile uint8_t *)(fb->fbkva + src);
452b04b7da8Stsutsui 
453b04b7da8Stsutsui 	tile_mover_waitbusy(gb);
454b04b7da8Stsutsui 
4555d7f465dStsutsui 	return 0;
456b04b7da8Stsutsui }
457b04b7da8Stsutsui 
458b04b7da8Stsutsui /*
459b04b7da8Stsutsui  * Gatorbox console support
460b04b7da8Stsutsui  */
461b04b7da8Stsutsui int
gboxcnattach(bus_space_tag_t bst,bus_addr_t addr,int scode)462b04b7da8Stsutsui gboxcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode)
463b04b7da8Stsutsui {
464b04b7da8Stsutsui 	bus_space_handle_t bsh;
465b04b7da8Stsutsui 	void *va;
466b04b7da8Stsutsui 	struct diofbreg *fbr;
467b04b7da8Stsutsui 	struct diofb *fb = &diofb_cn;
468b04b7da8Stsutsui 	int size;
469b04b7da8Stsutsui 
470b04b7da8Stsutsui 	if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh))
471b04b7da8Stsutsui 		return 1;
472b04b7da8Stsutsui 	va = bus_space_vaddr(bst, bsh);
473b04b7da8Stsutsui 	fbr = va;
474b04b7da8Stsutsui 
475b04b7da8Stsutsui 	if (badaddr(va) ||
476b04b7da8Stsutsui 	    (fbr->id != GRFHWID) || (fbr->fbid != GID_GATORBOX)) {
477b04b7da8Stsutsui 		bus_space_unmap(bst, bsh, PAGE_SIZE);
478b04b7da8Stsutsui 		return 1;
479b04b7da8Stsutsui 	}
480b04b7da8Stsutsui 
481b04b7da8Stsutsui 	size = DIO_SIZE(scode, va);
482b04b7da8Stsutsui 
483b04b7da8Stsutsui 	bus_space_unmap(bst, bsh, PAGE_SIZE);
484b04b7da8Stsutsui 	if (bus_space_map(bst, addr, size, 0, &bsh))
485b04b7da8Stsutsui 		return 1;
486b04b7da8Stsutsui 	va = bus_space_vaddr(bst, bsh);
487b04b7da8Stsutsui 
488b04b7da8Stsutsui 	/*
489b04b7da8Stsutsui 	 * Initialize the framebuffer hardware.
490b04b7da8Stsutsui 	 */
491b04b7da8Stsutsui 	conscode = scode;
492b04b7da8Stsutsui 	conaddr = va;
493b04b7da8Stsutsui 	gbox_reset(fb, conscode, (struct diofbreg *)conaddr);
494b04b7da8Stsutsui 
495b04b7da8Stsutsui 	/*
496b04b7da8Stsutsui 	 * Initialize the terminal emulator.
497b04b7da8Stsutsui 	 */
498b04b7da8Stsutsui 	diofb_cnattach(fb);
499b04b7da8Stsutsui 	return 0;
500b04b7da8Stsutsui }
501