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