cgtwo.c revision 1.7 1 /* $NetBSD: cgtwo.c,v 1.7 1995/11/29 01:45:44 pk Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 * from: @(#)cgthree.c 8.2 (Berkeley) 10/30/93
45 */
46
47 /*
48 * color display (cgtwo) driver.
49 *
50 * Does not handle interrupts, even though they can occur.
51 *
52 * XXX should defer colormap updates to vertical retrace interrupts
53 */
54
55 #include <sys/param.h>
56 #include <sys/buf.h>
57 #include <sys/device.h>
58 #include <sys/ioctl.h>
59 #include <sys/malloc.h>
60 #include <sys/mman.h>
61 #include <sys/tty.h>
62
63 #include <vm/vm.h>
64
65 #include <machine/fbio.h>
66 #include <machine/autoconf.h>
67 #include <machine/pmap.h>
68 #include <machine/fbvar.h>
69 #if defined(SUN4)
70 #include <machine/eeprom.h>
71 #endif
72
73 #include <machine/cgtworeg.h>
74
75 /* per-display variables */
76 struct cgtwo_softc {
77 struct device sc_dev; /* base device */
78 struct fbdevice sc_fb; /* frame buffer device */
79 caddr_t sc_phys; /* display RAM (phys addr) */
80 volatile struct cg2statusreg *sc_reg; /* CG2 control registers */
81 volatile u_short *sc_cmap;
82 #define sc_redmap(sc) ((sc)->sc_cmap)
83 #define sc_greenmap(sc) ((sc)->sc_cmap + CG2_CMSIZE)
84 #define sc_bluemap(sc) ((sc)->sc_cmap + 2 * CG2_CMSIZE)
85 };
86
87 /* autoconfiguration driver */
88 static void cgtwoattach(struct device *, struct device *, void *);
89 static int cgtwomatch(struct device *, void *, void *);
90 int cgtwoopen __P((dev_t, int, int, struct proc *));
91 int cgtwoclose __P((dev_t, int, int, struct proc *));
92 int cgtwoioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
93 int cgtwommap __P((dev_t, int, int));
94 static void cgtwounblank(struct device *);
95
96 struct cfdriver cgtwocd = {
97 NULL, "cgtwo", cgtwomatch, cgtwoattach,
98 DV_DULL, sizeof(struct cgtwo_softc)
99 };
100
101 /* frame buffer generic driver */
102 static struct fbdriver cgtwofbdriver = {
103 cgtwounblank, cgtwoopen, cgtwoclose, cgtwoioctl, cgtwommap
104 };
105
106 extern int fbnode;
107 extern struct tty *fbconstty;
108 extern int nullop();
109 static int cgtwo_cnputc();
110
111 static void cgtwoloadcmap __P((struct cgtwo_softc *, int, int));
112
113 /*
114 * Match a cgtwo.
115 */
116 int
117 cgtwomatch(parent, vcf, aux)
118 struct device *parent;
119 void *vcf, *aux;
120 {
121 struct cfdata *cf = vcf;
122 struct confargs *ca = aux;
123 struct romaux *ra = &ca->ca_ra;
124 int probe;
125 caddr_t tmp;
126
127 if (ca->ca_bustype != BUS_VME16)
128 return (0);
129
130 if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
131 return (0);
132
133 #if defined(SUN4)
134 if (cputyp != CPU_SUN4 || cf->cf_unit != 0)
135 return (0);
136
137 /* XXX - Must do our own mapping at CG2_CTLREG_OFF */
138 bus_untmp();
139 tmp = (caddr_t)bus_tmp(ra->ra_paddr + CG2_CTLREG_OFF, ca->ca_bustype);
140 if (probeget(tmp, 2) != -1)
141 return 1;
142 #endif
143 return 0;
144 }
145
146 /*
147 * Attach a display. We need to notice if it is the console, too.
148 */
149 void
150 cgtwoattach(parent, self, args)
151 struct device *parent, *self;
152 void *args;
153 {
154 register struct cgtwo_softc *sc = (struct cgtwo_softc *)self;
155 register struct confargs *ca = args;
156 register int node, i;
157 register struct cgtwo_all *p;
158 int isconsole;
159 char *nam;
160
161 sc->sc_fb.fb_driver = &cgtwofbdriver;
162 sc->sc_fb.fb_device = &sc->sc_dev;
163 sc->sc_fb.fb_type.fb_type = FBTYPE_SUN2COLOR;
164 sc->sc_fb.fb_flags = sc->sc_dev.dv_cfdata->cf_flags;
165
166 switch (ca->ca_bustype) {
167 case BUS_VME16:
168 node = 0;
169 nam = "cgtwo";
170 break;
171
172 default:
173 panic("cgtwoattach: impossible bustype");
174 /* NOTREACHED */
175 }
176
177 sc->sc_fb.fb_type.fb_depth = 8;
178 fb_setsize(&sc->sc_fb, sc->sc_fb.fb_type.fb_depth,
179 1152, 900, node, ca->ca_bustype);
180
181 sc->sc_fb.fb_type.fb_cmsize = 256;
182 sc->sc_fb.fb_type.fb_size = roundup(CG2_MAPPED_SIZE, NBPG);
183 printf(": %s, %d x %d", nam,
184 sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height);
185
186 /*
187 * When the ROM has mapped in a cgtwo display, the address
188 * maps only the video RAM, so in any case we have to map the
189 * registers ourselves. We only need the video RAM if we are
190 * going to print characters via rconsole.
191 */
192 #if defined(SUN4)
193 if (cputyp == CPU_SUN4) {
194 struct eeprom *eep = (struct eeprom *)eeprom_va;
195 /*
196 * Assume this is the console if there's no eeprom info
197 * to be found.
198 */
199 if (eep == NULL || eep->eeConsole == EE_CONS_COLOR)
200 isconsole = (fbconstty != NULL);
201 else
202 isconsole = 0;
203 }
204 #endif
205 sc->sc_phys = (caddr_t)ca->ca_ra.ra_paddr;
206 if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) {
207 /* this probably cannot happen, but what the heck */
208 sc->sc_fb.fb_pixels = mapiodev(sc->sc_phys + CG2_PIXMAP_OFF,
209 CG2_PIXMAP_SIZE,
210 ca->ca_bustype);
211 }
212 #ifndef offsetof
213 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
214 #endif
215
216 sc->sc_reg = (volatile struct cg2statusreg *)
217 mapiodev((caddr_t)sc->sc_phys +
218 CG2_ROPMEM_OFF + offsetof(struct cg2fb, status.reg),
219 sizeof(struct cg2statusreg), ca->ca_bustype);
220
221 sc->sc_cmap = (volatile u_short *)
222 mapiodev((caddr_t)sc->sc_phys +
223 CG2_ROPMEM_OFF + offsetof(struct cg2fb, redmap[0]),
224 3 * CG2_CMSIZE, ca->ca_bustype);
225
226 if (isconsole) {
227 printf(" (console)\n");
228 #ifdef RASTERCONSOLE
229 fbrcons_init(&sc->sc_fb);
230 #endif
231 } else
232 printf("\n");
233 if (node == fbnode || cputyp == CPU_SUN4)
234 fb_attach(&sc->sc_fb, isconsole);
235 }
236
237 int
238 cgtwoopen(dev, flags, mode, p)
239 dev_t dev;
240 int flags, mode;
241 struct proc *p;
242 {
243 int unit = minor(dev);
244
245 if (unit >= cgtwocd.cd_ndevs || cgtwocd.cd_devs[unit] == NULL)
246 return (ENXIO);
247 return (0);
248 }
249
250 int
251 cgtwoclose(dev, flags, mode, p)
252 dev_t dev;
253 int flags, mode;
254 struct proc *p;
255 {
256
257 return (0);
258 }
259
260 int
261 cgtwoioctl(dev, cmd, data, flags, p)
262 dev_t dev;
263 u_long cmd;
264 register caddr_t data;
265 int flags;
266 struct proc *p;
267 {
268 register struct cgtwo_softc *sc = cgtwocd.cd_devs[minor(dev)];
269 register struct fbgattr *fba;
270 int error;
271
272 switch (cmd) {
273
274 case FBIOGTYPE:
275 *(struct fbtype *)data = sc->sc_fb.fb_type;
276 break;
277
278 case FBIOGATTR:
279 fba = (struct fbgattr *)data;
280 fba->real_type = sc->sc_fb.fb_type.fb_type;
281 fba->owner = 0; /* XXX ??? */
282 fba->fbtype = sc->sc_fb.fb_type;
283 fba->sattr.flags = 0;
284 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
285 fba->sattr.dev_specific[0] = -1;
286 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
287 fba->emu_types[1] = -1;
288 break;
289
290 case FBIOGETCMAP:
291 return cgtwogetcmap(sc, data);
292
293 case FBIOPUTCMAP:
294 return cgtwoputcmap(sc, data);
295
296 case FBIOGVIDEO:
297 *(int *)data = sc->sc_reg->video_enab;
298 break;
299
300 case FBIOSVIDEO:
301 sc->sc_reg->video_enab = (*(int*)data) & 1;
302 break;
303
304 default:
305 return (ENOTTY);
306 }
307 return (0);
308 }
309
310 /*
311 * Undo the effect of an FBIOSVIDEO that turns the video off.
312 */
313 static void
314 cgtwounblank(dev)
315 struct device *dev;
316 {
317 struct cgtwo_softc *sc = (struct cgtwo_softc *)dev;
318 sc->sc_reg->video_enab = 1;
319 }
320
321 /*
322 */
323 int
324 cgtwogetcmap(sc, cmap)
325 register struct cgtwo_softc *sc;
326 register struct fbcmap *cmap;
327 {
328 u_char red[CG2_CMSIZE], green[CG2_CMSIZE], blue[CG2_CMSIZE];
329 int error, start, count, ecount;
330 register u_int i;
331 register volatile u_short *p;
332
333 start = cmap->index;
334 count = cmap->count;
335 ecount = start + count;
336 if (start >= CG2_CMSIZE || ecount > CG2_CMSIZE)
337 return (EINVAL);
338
339 /* XXX - Wait for retrace? */
340
341 /* Copy hardware to local arrays. */
342 p = &sc_redmap(sc)[start];
343 for (i = start; i < ecount; i++)
344 red[i] = *p++;
345 p = &sc_greenmap(sc)[start];
346 for (i = start; i < ecount; i++)
347 green[i] = *p++;
348 p = &sc_bluemap(sc)[start];
349 for (i = start; i < ecount; i++)
350 blue[i] = *p++;
351
352 /* Copy local arrays to user space. */
353 if ((error = copyout(red + start, cmap->red, count)) != 0)
354 return (error);
355 if ((error = copyout(green + start, cmap->green, count)) != 0)
356 return (error);
357 if ((error = copyout(blue + start, cmap->blue, count)) != 0)
358 return (error);
359
360 return (0);
361 }
362
363 /*
364 */
365 int
366 cgtwoputcmap(sc, cmap)
367 register struct cgtwo_softc *sc;
368 register struct fbcmap *cmap;
369 {
370 u_char red[CG2_CMSIZE], green[CG2_CMSIZE], blue[CG2_CMSIZE];
371 int error, start, count, ecount;
372 register u_int i;
373 register volatile u_short *p;
374
375 start = cmap->index;
376 count = cmap->count;
377 ecount = start + count;
378 if (start >= CG2_CMSIZE || ecount > CG2_CMSIZE)
379 return (EINVAL);
380
381 /* Copy from user space to local arrays. */
382 if ((error = copyin(cmap->red, red + start, count)) != 0)
383 return (error);
384 if ((error = copyin(cmap->green, green + start, count)) != 0)
385 return (error);
386 if ((error = copyin(cmap->blue, blue + start, count)) != 0)
387 return (error);
388
389 /* XXX - Wait for retrace? */
390
391 /* Copy from local arrays to hardware. */
392 p = &sc_redmap(sc)[start];
393 for (i = start; i < ecount; i++)
394 *p++ = red[i];
395 p = &sc_greenmap(sc)[start];
396 for (i = start; i < ecount; i++)
397 *p++ = green[i];
398 p = &sc_bluemap(sc)[start];
399 for (i = start; i < ecount; i++)
400 *p++ = blue[i];
401
402 return (0);
403 }
404
405 /*
406 * Return the address that would map the given device at the given
407 * offset, allowing for the given protection, or return -1 for error.
408 */
409 int
410 cgtwommap(dev, off, prot)
411 dev_t dev;
412 int off, prot;
413 {
414 register struct cgtwo_softc *sc = cgtwocd.cd_devs[minor(dev)];
415
416 if (off & PGOFSET)
417 panic("cgtwommap");
418
419 if ((unsigned)off >= sc->sc_fb.fb_type.fb_size)
420 return (-1);
421
422 return ((int)sc->sc_phys + off + PMAP_VME32 + PMAP_NC);
423 }
424