cgfour.c revision 1.15 1 /* $NetBSD: cgfour.c,v 1.15 1998/01/12 20:23:42 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1995 Theo de Raadt. All rights reserved.
41 * Copyright (c) 1992, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by Theo de Raadt.
47 *
48 * This software was developed by the Computer Systems Engineering group
49 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
50 * contributed to Berkeley.
51 *
52 * All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by the University of
55 * California, Lawrence Berkeley Laboratory.
56 *
57 * Redistribution and use in source and binary forms, with or without
58 * modification, are permitted provided that the following conditions
59 * are met:
60 * 1. Redistributions of source code must retain the above copyright
61 * notice, this list of conditions and the following disclaimer.
62 * 2. Redistributions in binary form must reproduce the above copyright
63 * notice, this list of conditions and the following disclaimer in the
64 * documentation and/or other materials provided with the distribution.
65 * 3. All advertising materials mentioning features or use of this software
66 * must display the following acknowledgement:
67 * This product includes software developed by the University of
68 * California, Berkeley and its contributors.
69 * 4. Neither the name of the University nor the names of its contributors
70 * may be used to endorse or promote products derived from this software
71 * without specific prior written permission.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
74 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
77 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
78 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
79 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
80 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
81 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
82 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83 * SUCH DAMAGE.
84 *
85 * from @(#)cgthree.c 8.2 (Berkeley) 10/30/93
86 */
87
88 /*
89 * color display (cgfour) driver.
90 *
91 * Does not handle interrupts, even though they can occur.
92 *
93 * XXX should defer colormap updates to vertical retrace interrupts
94 */
95
96 #include <sys/param.h>
97 #include <sys/systm.h>
98 #include <sys/buf.h>
99 #include <sys/device.h>
100 #include <sys/ioctl.h>
101 #include <sys/malloc.h>
102 #include <sys/mman.h>
103 #include <sys/tty.h>
104 #include <sys/conf.h>
105
106 #include <vm/vm.h>
107
108 #include <machine/fbio.h>
109 #include <machine/autoconf.h>
110 #include <machine/pmap.h>
111 #include <machine/fbvar.h>
112 #include <machine/eeprom.h>
113 #include <machine/conf.h>
114
115 #include <sparc/dev/btreg.h>
116 #include <sparc/dev/btvar.h>
117 #include <sparc/dev/pfourreg.h>
118
119 /* per-display variables */
120 struct cgfour_softc {
121 struct device sc_dev; /* base device */
122 struct fbdevice sc_fb; /* frame buffer device */
123 struct rom_reg sc_phys; /* display RAM (phys addr) */
124 volatile struct fbcontrol *sc_fbc; /* Brooktree registers */
125 int sc_bustype; /* type of bus we live on */
126 union bt_cmap sc_cmap; /* Brooktree color map */
127 };
128
129 /* autoconfiguration driver */
130 static void cgfourattach __P((struct device *, struct device *, void *));
131 static int cgfourmatch __P((struct device *, struct cfdata *, void *));
132 #if defined(SUN4)
133 static void cgfourunblank __P((struct device *));
134 #endif
135
136 /* cdevsw prototypes */
137 cdev_decl(cgfour);
138
139 struct cfattach cgfour_ca = {
140 sizeof(struct cgfour_softc), cgfourmatch, cgfourattach
141 };
142
143 extern struct cfdriver cgfour_cd;
144
145 #if defined(SUN4)
146 /* frame buffer generic driver */
147 static struct fbdriver cgfourfbdriver = {
148 cgfourunblank, cgfouropen, cgfourclose, cgfourioctl, cgfourpoll,
149 cgfourmmap
150 };
151
152 extern int fbnode;
153 extern struct tty *fbconstty;
154
155 static void cgfourloadcmap __P((struct cgfour_softc *, int, int));
156 static int cgfour_get_video __P((struct cgfour_softc *));
157 static void cgfour_set_video __P((struct cgfour_softc *, int));
158 #endif
159
160 /*
161 * Match a cgfour.
162 */
163 int
164 cgfourmatch(parent, cf, aux)
165 struct device *parent;
166 struct cfdata *cf;
167 void *aux;
168 {
169 struct confargs *ca = aux;
170 struct romaux *ra = &ca->ca_ra;
171
172 if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
173 return (0);
174
175 /*
176 * Mask out invalid flags from the user.
177 */
178 cf->cf_flags &= FB_USERMASK;
179
180 /*
181 * Only exists on a sun4.
182 */
183 if (!CPU_ISSUN4)
184 return (0);
185
186 /*
187 * Only exists on obio.
188 */
189 if (ca->ca_bustype != BUS_OBIO)
190 return (0);
191
192 /*
193 * Make sure there's hardware there.
194 */
195 if (probeget(ra->ra_vaddr, 4) == -1)
196 return (0);
197
198 #if defined(SUN4)
199 /*
200 * Check the pfour register.
201 */
202 if (fb_pfour_id(ra->ra_vaddr) == PFOUR_ID_COLOR8P1) {
203 cf->cf_flags |= FB_PFOUR;
204 return (1);
205 }
206 #endif
207
208 return (0);
209 }
210
211 /*
212 * Attach a display. We need to notice if it is the console, too.
213 */
214 void
215 cgfourattach(parent, self, args)
216 struct device *parent, *self;
217 void *args;
218 {
219 #if defined(SUN4)
220 register struct cgfour_softc *sc = (struct cgfour_softc *)self;
221 register struct confargs *ca = args;
222 register int node = 0, ramsize, i;
223 register volatile struct bt_regs *bt;
224 struct fbdevice *fb = &sc->sc_fb;
225 int isconsole;
226
227 fb->fb_driver = &cgfourfbdriver;
228 fb->fb_device = &sc->sc_dev;
229 fb->fb_type.fb_type = FBTYPE_SUN4COLOR;
230 fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags;
231
232 /*
233 * Only pfour cgfours, thank you...
234 */
235 if ((ca->ca_bustype != BUS_OBIO) ||
236 ((fb->fb_flags & FB_PFOUR) == 0)) {
237 printf("%s: ignoring; not a pfour\n", sc->sc_dev.dv_xname);
238 return;
239 }
240
241 /* Map the pfour register. */
242 fb->fb_pfour = (volatile u_int32_t *)
243 mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t));
244
245 ramsize = PFOUR_COLOR_OFF_END - PFOUR_COLOR_OFF_OVERLAY;
246
247 fb->fb_type.fb_depth = 8;
248 fb_setsize(fb, fb->fb_type.fb_depth, 1152, 900, node, ca->ca_bustype);
249
250 fb->fb_type.fb_cmsize = 256;
251 fb->fb_type.fb_size = ramsize;
252 printf(": cgfour/p4, %d x %d", fb->fb_type.fb_width,
253 fb->fb_type.fb_height);
254
255 isconsole = 0;
256
257 if (CPU_ISSUN4) {
258 struct eeprom *eep = (struct eeprom *)eeprom_va;
259
260 /*
261 * Assume this is the console if there's no eeprom info
262 * to be found.
263 */
264 if (eep == NULL || eep->eeConsole == EE_CONS_P4OPT)
265 isconsole = (fbconstty != NULL);
266 }
267
268 #if 0
269 /*
270 * We don't do any of the console handling here. Instead,
271 * we let the bwtwo driver pick up the overlay plane and
272 * use it instead. Rconsole should have better performance
273 * with the 1-bit depth.
274 * -- Jason R. Thorpe <thorpej (at) NetBSD.ORG>
275 */
276
277 /*
278 * When the ROM has mapped in a cgfour display, the address
279 * maps only the video RAM, so in any case we have to map the
280 * registers ourselves. We only need the video RAM if we are
281 * going to print characters via rconsole.
282 */
283
284 if (isconsole) {
285 /* XXX this is kind of a waste */
286 fb->fb_pixels = mapiodev(ca->ca_ra.ra_reg,
287 PFOUR_COLOR_OFF_OVERLAY, ramsize);
288 }
289 #endif
290
291 /* Map the Brooktree. */
292 sc->sc_fbc = (volatile struct fbcontrol *)
293 mapiodev(ca->ca_ra.ra_reg,
294 PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol));
295
296 sc->sc_phys = ca->ca_ra.ra_reg[0];
297 sc->sc_bustype = ca->ca_bustype;
298
299 /* grab initial (current) color map */
300 bt = &sc->sc_fbc->fbc_dac;
301 bt->bt_addr = 0;
302 for (i = 0; i < 256 * 3 / 4; i++)
303 ((char *)&sc->sc_cmap)[i] = bt->bt_cmap >> 24;
304
305 BT_INIT(bt, 24);
306
307 #if 0 /* See above. */
308 if (isconsole) {
309 printf(" (console)\n");
310 #if defined(RASTERCONSOLE) && 0 /* XXX been told it doesn't work well. */
311 fbrcons_init(fb);
312 #endif
313 } else
314 #endif /* 0 */
315 printf("\n");
316
317 /*
318 * Even though we're not using rconsole, we'd still like
319 * to notice if we're the console framebuffer.
320 */
321 fb_attach(fb, isconsole);
322 #endif
323 }
324
325 int
326 cgfouropen(dev, flags, mode, p)
327 dev_t dev;
328 int flags, mode;
329 struct proc *p;
330 {
331 int unit = minor(dev);
332
333 if (unit >= cgfour_cd.cd_ndevs || cgfour_cd.cd_devs[unit] == NULL)
334 return (ENXIO);
335 return (0);
336 }
337
338 int
339 cgfourclose(dev, flags, mode, p)
340 dev_t dev;
341 int flags, mode;
342 struct proc *p;
343 {
344
345 return (0);
346 }
347
348 int
349 cgfourioctl(dev, cmd, data, flags, p)
350 dev_t dev;
351 u_long cmd;
352 register caddr_t data;
353 int flags;
354 struct proc *p;
355 {
356 #if defined(SUN4)
357 register struct cgfour_softc *sc = cgfour_cd.cd_devs[minor(dev)];
358 register struct fbgattr *fba;
359 int error;
360
361 switch (cmd) {
362
363 case FBIOGTYPE:
364 *(struct fbtype *)data = sc->sc_fb.fb_type;
365 break;
366
367 case FBIOGATTR:
368 fba = (struct fbgattr *)data;
369 fba->real_type = sc->sc_fb.fb_type.fb_type;
370 fba->owner = 0; /* XXX ??? */
371 fba->fbtype = sc->sc_fb.fb_type;
372 fba->sattr.flags = 0;
373 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
374 fba->sattr.dev_specific[0] = -1;
375 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
376 fba->emu_types[1] = -1;
377 break;
378
379 case FBIOGETCMAP:
380 return (bt_getcmap((struct fbcmap *)data, &sc->sc_cmap, 256));
381
382 case FBIOPUTCMAP:
383 /* copy to software map */
384 #define p ((struct fbcmap *)data)
385 error = bt_putcmap(p, &sc->sc_cmap, 256);
386 if (error)
387 return (error);
388 /* now blast them into the chip */
389 /* XXX should use retrace interrupt */
390 cgfourloadcmap(sc, p->index, p->count);
391 #undef p
392 break;
393
394 case FBIOGVIDEO:
395 *(int *)data = cgfour_get_video(sc);
396 break;
397
398 case FBIOSVIDEO:
399 cgfour_set_video(sc, *(int *)data);
400 break;
401
402 default:
403 return (ENOTTY);
404 }
405 #endif
406 return (0);
407 }
408
409 int
410 cgfourpoll(dev, events, p)
411 dev_t dev;
412 int events;
413 struct proc *p;
414 {
415
416 return (seltrue(dev, events, p));
417 }
418
419 /*
420 * Return the address that would map the given device at the given
421 * offset, allowing for the given protection, or return -1 for error.
422 *
423 * the cg4 maps it's overlay plane for 128K, followed by the enable
424 * plane for 128K, followed by the colour plane (for as much colour
425 * as their is.)
426 *
427 * As well, mapping at an offset of 0x04000000 causes the cg4 to map
428 * only it's colour plane, at 0.
429 */
430 int
431 cgfourmmap(dev, off, prot)
432 dev_t dev;
433 int off, prot;
434 {
435 register struct cgfour_softc *sc = cgfour_cd.cd_devs[minor(dev)];
436 int poff;
437
438 #define START_ENABLE (128*1024)
439 #define START_COLOR ((128*1024) + (128*1024))
440 #define COLOR_SIZE (sc->sc_fb.fb_type.fb_width * \
441 sc->sc_fb.fb_type.fb_height)
442 #define END_COLOR (START_COLOR + COLOR_SIZE)
443 #define NOOVERLAY (0x04000000)
444
445 if (off & PGOFSET)
446 panic("cgfourmap");
447
448 if ((u_int)off >= NOOVERLAY) {
449 off -= NOOVERLAY;
450
451 /*
452 * X11 maps a huge chunk of the frame buffer; far more than
453 * there really is. We compensate by double-mapping the
454 * first page for as many other pages as it wants
455 */
456 while (off >= COLOR_SIZE)
457 off -= COLOR_SIZE; /* XXX thorpej ??? */
458
459 poff = off + PFOUR_COLOR_OFF_COLOR;
460 } else if ((u_int)off < START_ENABLE) {
461 /*
462 * in overlay plane
463 */
464 poff = PFOUR_COLOR_OFF_OVERLAY + off;
465 } else if ((u_int)off < START_COLOR) {
466 /*
467 * in enable plane
468 */
469 poff = (off - START_ENABLE) + PFOUR_COLOR_OFF_ENABLE;
470 } else if ((u_int)off < sc->sc_fb.fb_type.fb_size) {
471 /*
472 * in colour plane
473 */
474 poff = (off - START_COLOR) + PFOUR_COLOR_OFF_COLOR;
475 } else
476 return (-1);
477
478 return (REG2PHYS(&sc->sc_phys, poff) | PMAP_NC);
479 }
480
481 #if defined(SUN4)
482 /*
483 * Undo the effect of an FBIOSVIDEO that turns the video off.
484 */
485 static void
486 cgfourunblank(dev)
487 struct device *dev;
488 {
489
490 cgfour_set_video((struct cgfour_softc *)dev, 1);
491 }
492
493 static int
494 cgfour_get_video(sc)
495 struct cgfour_softc *sc;
496 {
497
498 return (fb_pfour_get_video(&sc->sc_fb));
499 }
500
501 static void
502 cgfour_set_video(sc, enable)
503 struct cgfour_softc *sc;
504 int enable;
505 {
506
507 fb_pfour_set_video(&sc->sc_fb, enable);
508 }
509
510 /*
511 * Load a subset of the current (new) colormap into the Brooktree DAC.
512 */
513 static void
514 cgfourloadcmap(sc, start, ncolors)
515 register struct cgfour_softc *sc;
516 register int start, ncolors;
517 {
518 register volatile struct bt_regs *bt;
519 register u_int *ip, i;
520 register int count;
521
522 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */
523 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
524 bt = &sc->sc_fbc->fbc_dac;
525 bt->bt_addr = BT_D4M4(start) << 24;
526 while (--count >= 0) {
527 i = *ip++;
528 /* hardware that makes one want to pound boards with hammers */
529 bt->bt_cmap = i;
530 bt->bt_cmap = i << 8;
531 bt->bt_cmap = i << 16;
532 bt->bt_cmap = i << 24;
533 }
534 }
535 #endif
536