cgtwo.c revision 1.1 1 /* $NetBSD: cgtwo.c,v 1.1 1995/09/17 20:53:43 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
70 #include <sparc/dev/cgtworeg.h>
71 #include <sparc/dev/sbusvar.h>
72
73 /* per-display variables */
74 struct cgtwo_softc {
75 struct device sc_dev; /* base device */
76 struct sbusdev sc_sd; /* sbus device */
77 struct fbdevice sc_fb; /* frame buffer device */
78 caddr_t sc_phys; /* display RAM (phys addr) */
79 volatile struct cg2reg *sc_reg; /* CG2 control registers */
80 };
81
82 /* autoconfiguration driver */
83 static void cgtwoattach(struct device *, struct device *, void *);
84 static int cgtwomatch(struct device *, void *, void *);
85 int cgtwoopen __P((dev_t, int, int, struct proc *));
86 int cgtwoclose __P((dev_t, int, int, struct proc *));
87 int cgtwoioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
88 int cgtwommap __P((dev_t, int, int));
89 static void cgtwounblank(struct device *);
90
91 struct cfdriver cgtwocd = {
92 NULL, "cgtwo", cgtwomatch, cgtwoattach,
93 DV_DULL, sizeof(struct cgtwo_softc)
94 };
95
96 /* frame buffer generic driver */
97 static struct fbdriver cgtwofbdriver = {
98 cgtwounblank, cgtwoopen, cgtwoclose, cgtwoioctl, cgtwommap
99 };
100
101 extern int fbnode;
102 extern struct tty *fbconstty;
103 extern int (*v_putc)();
104 extern int nullop();
105 static int cgtwo_cnputc();
106
107 static void cgtwoloadcmap __P((struct cgtwo_softc *, int, int));
108
109 /*
110 * Match a cgtwo.
111 */
112 int
113 cgtwomatch(parent, vcf, aux)
114 struct device *parent;
115 void *vcf, *aux;
116 {
117 struct cfdata *cf = vcf;
118 struct confargs *ca = aux;
119 struct romaux *ra = &ca->ca_ra;
120
121 if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
122 return (0);
123 if (ca->ca_bustype == BUS_SBUS)
124 return(1);
125 ra->ra_len = NBPG;
126 return (probeget(ra->ra_vaddr, 4) != -1);
127 }
128
129 /*
130 * Attach a display. We need to notice if it is the console, too.
131 */
132 void
133 cgtwoattach(parent, self, args)
134 struct device *parent, *self;
135 void *args;
136 {
137 register struct cgtwo_softc *sc = (struct cgtwo_softc *)self;
138 register struct confargs *ca = args;
139 register int node, ramsize, i;
140 register struct cgtwo_all *p;
141 int isconsole;
142 int sbus = 1;
143 char *nam;
144
145 sc->sc_fb.fb_driver = &cgtwofbdriver;
146 sc->sc_fb.fb_device = &sc->sc_dev;
147 /*
148 * The defaults below match my screen, but are not guaranteed
149 * to be correct as defaults go...
150 */
151 sc->sc_fb.fb_type.fb_type = FBTYPE_SUN2COLOR;
152 switch (ca->ca_bustype) {
153 case BUS_OBIO:
154 case BUS_VME32:
155 case BUS_VME16:
156 sbus = node = 0;
157 sc->sc_fb.fb_type.fb_width = 1152;
158 sc->sc_fb.fb_type.fb_height = 900;
159 sc->sc_fb.fb_linebytes = 1152;
160 nam = "cgtwo";
161 break;
162 case BUS_SBUS:
163 node = ca->ca_ra.ra_node;
164 sc->sc_fb.fb_type.fb_width = getpropint(node, "width", 1152);
165 sc->sc_fb.fb_type.fb_height = getpropint(node, "height", 900);
166 sc->sc_fb.fb_linebytes = getpropint(node, "linebytes", 1152);
167 nam = getpropstring(node, "model");
168 break;
169 }
170
171 ramsize = roundup(sc->sc_fb.fb_type.fb_height * sc->sc_fb.fb_linebytes,
172 NBPG);
173 sc->sc_fb.fb_type.fb_depth = 8;
174 sc->sc_fb.fb_type.fb_cmsize = 256;
175 sc->sc_fb.fb_type.fb_size = ramsize;
176 printf(": %s, %d x %d", nam,
177 sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height);
178
179 /*
180 * When the ROM has mapped in a cgtwo display, the address
181 * maps only the video RAM, so in any case we have to map the
182 * registers ourselves. We only need the video RAM if we are
183 * going to print characters via rconsole.
184 */
185 isconsole = node == fbnode && fbconstty != NULL;
186 sc->sc_phys = (caddr_t)ca->ca_ra.ra_paddr;
187 if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) {
188 /* this probably cannot happen, but what the heck */
189 sc->sc_fb.fb_pixels = mapiodev(sc->sc_phys, ramsize,
190 ca->ca_bustype);
191 }
192 sc->sc_reg = (volatile struct cg2reg *)
193 mapiodev((caddr_t)sc->sc_phys + CG2_CTLREG_OFF, CG2_CTLREG_SIZE,
194 ca->ca_bustype);
195
196 if (isconsole) {
197 printf(" (console)\n");
198 #ifdef RCONSOLE
199 fbrcons_init(&sc->sc_fb);
200 #endif
201 } else
202 printf("\n");
203 if (sbus)
204 sbus_establish(&sc->sc_sd, &sc->sc_dev);
205 if (node == fbnode)
206 fb_attach(&sc->sc_fb);
207 }
208
209 int
210 cgtwoopen(dev, flags, mode, p)
211 dev_t dev;
212 int flags, mode;
213 struct proc *p;
214 {
215 int unit = minor(dev);
216
217 if (unit >= cgtwocd.cd_ndevs || cgtwocd.cd_devs[unit] == NULL)
218 return (ENXIO);
219 return (0);
220 }
221
222 int
223 cgtwoclose(dev, flags, mode, p)
224 dev_t dev;
225 int flags, mode;
226 struct proc *p;
227 {
228
229 return (0);
230 }
231
232 int
233 cgtwoioctl(dev, cmd, data, flags, p)
234 dev_t dev;
235 u_long cmd;
236 register caddr_t data;
237 int flags;
238 struct proc *p;
239 {
240 register struct cgtwo_softc *sc = cgtwocd.cd_devs[minor(dev)];
241 register struct fbgattr *fba;
242 int error;
243
244 switch (cmd) {
245
246 case FBIOGTYPE:
247 *(struct fbtype *)data = sc->sc_fb.fb_type;
248 break;
249
250 case FBIOGATTR:
251 fba = (struct fbgattr *)data;
252 fba->real_type = sc->sc_fb.fb_type.fb_type;
253 fba->owner = 0; /* XXX ??? */
254 fba->fbtype = sc->sc_fb.fb_type;
255 fba->sattr.flags = 0;
256 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
257 fba->sattr.dev_specific[0] = -1;
258 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
259 fba->emu_types[1] = -1;
260 break;
261
262 case FBIOGETCMAP:
263 return cgtwogetcmap(sc, data);
264
265 case FBIOPUTCMAP:
266 return cgtwoputcmap(sc, data);
267
268 case FBIOGVIDEO:
269 *(int *)data = sc->sc_reg->status.video_enab;
270 break;
271
272 case FBIOSVIDEO:
273 sc->sc_reg->status.video_enab = (*(int*)data) & 1;
274 break;
275
276 default:
277 return (ENOTTY);
278 }
279 return (0);
280 }
281
282 /*
283 * Undo the effect of an FBIOSVIDEO that turns the video off.
284 */
285 static void
286 cgtwounblank(dev)
287 struct device *dev;
288 {
289 struct cgtwo_softc *sc = (struct cgtwo_softc *)dev;
290 sc->sc_reg->status.video_enab = 1;
291 }
292
293 /*
294 */
295 int
296 cgtwogetcmap(sc, cmap)
297 register struct cgtwo_softc *sc;
298 register struct fbcmap *cmap;
299 {
300 u_char red[CG2_CMSIZE], green[CG2_CMSIZE], blue[CG2_CMSIZE];
301 int error, start, count, ecount;
302 register u_int i;
303 register u_short *p;
304
305 start = cmap->index;
306 count = cmap->count;
307 ecount = start + count;
308 if (start >= CG2_CMSIZE || ecount > CG2_CMSIZE)
309 return (EINVAL);
310
311 /* XXX - Wait for retrace? */
312
313 /* Copy hardware to local arrays. */
314 p = &sc->sc_reg->redmap[start];
315 for (i = start; i < ecount; i++)
316 red[i] = *p++;
317 p = &sc->sc_reg->greenmap[start];
318 for (i = start; i < ecount; i++)
319 green[i] = *p++;
320 p = &sc->sc_reg->bluemap[start];
321 for (i = start; i < ecount; i++)
322 blue[i] = *p++;
323
324 /* Copy local arrays to user space. */
325 if ((error = copyout(red + start, cmap->red, count)) != 0)
326 return (error);
327 if ((error = copyout(green + start, cmap->green, count)) != 0)
328 return (error);
329 if ((error = copyout(blue + start, cmap->blue, count)) != 0)
330 return (error);
331
332 return (0);
333 }
334
335 /*
336 */
337 int
338 cgtwoputcmap(sc, cmap)
339 register struct cgtwo_softc *sc;
340 register struct fbcmap *cmap;
341 {
342 u_char red[CG2_CMSIZE], green[CG2_CMSIZE], blue[CG2_CMSIZE];
343 int error, start, count, ecount;
344 register u_int i;
345 register u_short *p;
346
347 start = cmap->index;
348 count = cmap->count;
349 ecount = start + count;
350 if (start >= CG2_CMSIZE || ecount > CG2_CMSIZE)
351 return (EINVAL);
352
353 /* Copy from user space to local arrays. */
354 if ((error = copyin(cmap->red, red + start, count)) != 0)
355 return (error);
356 if ((error = copyin(cmap->green, green + start, count)) != 0)
357 return (error);
358 if ((error = copyin(cmap->blue, blue + start, count)) != 0)
359 return (error);
360
361 /* XXX - Wait for retrace? */
362
363 /* Copy from local arrays to hardware. */
364 p = &sc->sc_reg->redmap[start];
365 for (i = start; i < ecount; i++)
366 *p++ = red[i];
367 p = &sc->sc_reg->greenmap[start];
368 for (i = start; i < ecount; i++)
369 *p++ = green[i];
370 p = &sc->sc_reg->bluemap[start];
371 for (i = start; i < ecount; i++)
372 *p++ = blue[i];
373
374 return (0);
375 }
376
377 /*
378 * Return the address that would map the given device at the given
379 * offset, allowing for the given protection, or return -1 for error.
380 */
381 int
382 cgtwommap(dev, off, prot)
383 dev_t dev;
384 int off, prot;
385 {
386 register struct cgtwo_softc *sc = cgtwocd.cd_devs[minor(dev)];
387
388 if (off & PGOFSET)
389 panic("cgtwommap");
390
391 if ((unsigned)off >= sc->sc_fb.fb_type.fb_size)
392 return (-1);
393
394 return ((int)sc->sc_phys + off + PMAP_OBIO + PMAP_NC);
395 }
396