1/*	$NetBSD: gbox.c,v 1.2 2011/02/12 16:40:29 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
127struct	gbox_softc {
128	device_t	sc_dev;
129	struct diofb	*sc_fb;
130	struct diofb	sc_fb_store;
131	int		sc_scode;
132};
133
134static int	gbox_dio_match(device_t, cfdata_t, void *);
135static void	gbox_dio_attach(device_t, device_t, void *);
136static int	gbox_intio_match(device_t, cfdata_t, void *);
137static void	gbox_intio_attach(device_t, device_t, void *);
138
139CFATTACH_DECL_NEW(gbox_dio, sizeof(struct gbox_softc),
140    gbox_dio_match, gbox_dio_attach, NULL, NULL);
141
142CFATTACH_DECL_NEW(gbox_intio, sizeof(struct gbox_softc),
143    gbox_intio_match, gbox_intio_attach, NULL, NULL);
144
145static int	gbox_reset(struct diofb *, int, struct diofbreg *);
146static void	gbox_restore(struct diofb *);
147static int	gbox_setcmap(struct diofb *, struct wsdisplay_cmap *);
148static void	gbox_setcolor(struct diofb *, u_int);
149static int	gbox_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t,
150		    uint16_t, uint16_t, uint16_t, int16_t, int16_t);
151
152static int	gbox_ioctl(void *, void *, u_long, void *, int, struct lwp *);
153
154static 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 */
166int
167gbox_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
187void
188gbox_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
209int
210gbox_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
225void
226gbox_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
260const uint8_t crtc_init_data[] = {
261    0x29, 0x20, 0x23, 0x04, 0x30, 0x0b, 0x30,
262    0x30, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00
263};
264
265int
266gbox_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
311void
312gbox_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
340int
341gbox_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
381void
382gbox_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
394int
395gbox_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
422int
423gbox_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 */
461int
462gboxcnattach(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