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