bw2.c revision 1.17.4.3 1 1.17.4.3 nathanw /* $NetBSD: bw2.c,v 1.17.4.3 2002/09/17 21:18:14 nathanw Exp $ */
2 1.17.4.2 nathanw
3 1.17.4.2 nathanw /*
4 1.17.4.2 nathanw * Copyright (c) 1992, 1993
5 1.17.4.2 nathanw * The Regents of the University of California. All rights reserved.
6 1.17.4.2 nathanw *
7 1.17.4.2 nathanw * This software was developed by the Computer Systems Engineering group
8 1.17.4.2 nathanw * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 1.17.4.2 nathanw * contributed to Berkeley.
10 1.17.4.2 nathanw *
11 1.17.4.2 nathanw * All advertising materials mentioning features or use of this software
12 1.17.4.2 nathanw * must display the following acknowledgement:
13 1.17.4.2 nathanw * This product includes software developed by the University of
14 1.17.4.2 nathanw * California, Lawrence Berkeley Laboratory.
15 1.17.4.2 nathanw *
16 1.17.4.2 nathanw * Redistribution and use in source and binary forms, with or without
17 1.17.4.2 nathanw * modification, are permitted provided that the following conditions
18 1.17.4.2 nathanw * are met:
19 1.17.4.2 nathanw * 1. Redistributions of source code must retain the above copyright
20 1.17.4.2 nathanw * notice, this list of conditions and the following disclaimer.
21 1.17.4.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
22 1.17.4.2 nathanw * notice, this list of conditions and the following disclaimer in the
23 1.17.4.2 nathanw * documentation and/or other materials provided with the distribution.
24 1.17.4.2 nathanw * 3. All advertising materials mentioning features or use of this software
25 1.17.4.2 nathanw * must display the following acknowledgement:
26 1.17.4.2 nathanw * This product includes software developed by the University of
27 1.17.4.2 nathanw * California, Berkeley and its contributors.
28 1.17.4.2 nathanw * 4. Neither the name of the University nor the names of its contributors
29 1.17.4.2 nathanw * may be used to endorse or promote products derived from this software
30 1.17.4.2 nathanw * without specific prior written permission.
31 1.17.4.2 nathanw *
32 1.17.4.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 1.17.4.2 nathanw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 1.17.4.2 nathanw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 1.17.4.2 nathanw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 1.17.4.2 nathanw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 1.17.4.2 nathanw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 1.17.4.2 nathanw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 1.17.4.2 nathanw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 1.17.4.2 nathanw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 1.17.4.2 nathanw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 1.17.4.2 nathanw * SUCH DAMAGE.
43 1.17.4.2 nathanw *
44 1.17.4.2 nathanw * @(#)bwtwo.c 8.1 (Berkeley) 6/11/93
45 1.17.4.2 nathanw */
46 1.17.4.2 nathanw
47 1.17.4.2 nathanw /*
48 1.17.4.2 nathanw * black&white display (bw2) driver.
49 1.17.4.2 nathanw *
50 1.17.4.2 nathanw * Does not handle interrupts, even though they can occur.
51 1.17.4.2 nathanw */
52 1.17.4.2 nathanw
53 1.17.4.2 nathanw #include <sys/param.h>
54 1.17.4.2 nathanw #include <sys/systm.h>
55 1.17.4.2 nathanw #include <sys/conf.h>
56 1.17.4.2 nathanw #include <sys/device.h>
57 1.17.4.2 nathanw #include <sys/ioctl.h>
58 1.17.4.2 nathanw #include <sys/malloc.h>
59 1.17.4.2 nathanw #include <sys/mman.h>
60 1.17.4.2 nathanw #include <sys/proc.h>
61 1.17.4.2 nathanw #include <sys/tty.h>
62 1.17.4.2 nathanw
63 1.17.4.2 nathanw #include <uvm/uvm_extern.h>
64 1.17.4.2 nathanw
65 1.17.4.2 nathanw #include <machine/autoconf.h>
66 1.17.4.2 nathanw #include <machine/cpu.h>
67 1.17.4.2 nathanw #include <dev/sun/fbio.h>
68 1.17.4.2 nathanw #include <machine/idprom.h>
69 1.17.4.2 nathanw #include <machine/pmap.h>
70 1.17.4.2 nathanw
71 1.17.4.2 nathanw #include <sun3/dev/fbvar.h>
72 1.17.4.2 nathanw #include <sun3/dev/bw2reg.h>
73 1.17.4.2 nathanw #include <sun3/dev/p4reg.h>
74 1.17.4.2 nathanw
75 1.17.4.2 nathanw /* per-display variables */
76 1.17.4.2 nathanw struct bw2_softc {
77 1.17.4.2 nathanw struct device sc_dev; /* base device */
78 1.17.4.2 nathanw struct fbdevice sc_fb; /* frame buffer device */
79 1.17.4.2 nathanw int sc_phys; /* display RAM (phys addr) */
80 1.17.4.2 nathanw /* If using overlay plane of something, it is... */
81 1.17.4.2 nathanw int sc_ovtype; /* ... this type. */
82 1.17.4.2 nathanw int sc_video_on;
83 1.17.4.2 nathanw };
84 1.17.4.2 nathanw
85 1.17.4.2 nathanw /* autoconfiguration driver */
86 1.17.4.2 nathanw static void bw2attach __P((struct device *, struct device *, void *));
87 1.17.4.2 nathanw static int bw2match __P((struct device *, struct cfdata *, void *));
88 1.17.4.2 nathanw
89 1.17.4.2 nathanw struct cfattach bwtwo_ca = {
90 1.17.4.2 nathanw sizeof(struct bw2_softc), bw2match, bw2attach
91 1.17.4.2 nathanw };
92 1.17.4.2 nathanw
93 1.17.4.2 nathanw extern struct cfdriver bwtwo_cd;
94 1.17.4.2 nathanw
95 1.17.4.3 nathanw dev_type_open(bw2open);
96 1.17.4.3 nathanw dev_type_ioctl(bw2ioctl);
97 1.17.4.3 nathanw dev_type_mmap(bw2mmap);
98 1.17.4.3 nathanw
99 1.17.4.3 nathanw const struct cdevsw bwtwo_cdevsw = {
100 1.17.4.3 nathanw bw2open, nullclose, noread, nowrite, bw2ioctl,
101 1.17.4.3 nathanw nostop, notty, nopoll, bw2mmap,
102 1.17.4.3 nathanw };
103 1.17.4.3 nathanw
104 1.17.4.2 nathanw /* XXX we do not handle frame buffer interrupts */
105 1.17.4.2 nathanw
106 1.17.4.2 nathanw static int bw2gvideo __P((struct fbdevice *, void *));
107 1.17.4.2 nathanw static int bw2svideo __P((struct fbdevice *, void *));
108 1.17.4.2 nathanw
109 1.17.4.2 nathanw static struct fbdriver bw2fbdriver = {
110 1.17.4.3 nathanw bw2open, nullclose, bw2mmap,
111 1.17.4.2 nathanw fb_noioctl,
112 1.17.4.2 nathanw bw2gvideo, bw2svideo,
113 1.17.4.2 nathanw fb_noioctl, fb_noioctl, };
114 1.17.4.2 nathanw
115 1.17.4.2 nathanw static int
116 1.17.4.2 nathanw bw2match(parent, cf, args)
117 1.17.4.2 nathanw struct device *parent;
118 1.17.4.2 nathanw struct cfdata *cf;
119 1.17.4.2 nathanw void *args;
120 1.17.4.2 nathanw {
121 1.17.4.2 nathanw struct confargs *ca = args;
122 1.17.4.2 nathanw int mid, p4id, peekval;
123 1.17.4.2 nathanw void *p4reg;
124 1.17.4.2 nathanw
125 1.17.4.2 nathanw /* No default address support. */
126 1.17.4.2 nathanw if (ca->ca_paddr == -1)
127 1.17.4.2 nathanw return (0);
128 1.17.4.2 nathanw
129 1.17.4.2 nathanw /*
130 1.17.4.2 nathanw * Slight hack here: The low four bits of the
131 1.17.4.2 nathanw * config flags, if set, restrict the match to
132 1.17.4.2 nathanw * that machine "implementation" only.
133 1.17.4.2 nathanw */
134 1.17.4.2 nathanw mid = cf->cf_flags & IDM_IMPL_MASK;
135 1.17.4.2 nathanw if (mid && (mid != (cpu_machine_id & IDM_IMPL_MASK)))
136 1.17.4.2 nathanw return (0);
137 1.17.4.2 nathanw
138 1.17.4.2 nathanw /*
139 1.17.4.2 nathanw * Make sure something is there, and if so,
140 1.17.4.2 nathanw * see if it looks like a P4 register.
141 1.17.4.2 nathanw */
142 1.17.4.2 nathanw p4reg = bus_tmapin(ca->ca_bustype, ca->ca_paddr);
143 1.17.4.2 nathanw peekval = peek_long(p4reg);
144 1.17.4.2 nathanw p4id = (peekval == -1) ?
145 1.17.4.2 nathanw P4_NOTFOUND : fb_pfour_id(p4reg);
146 1.17.4.2 nathanw bus_tmapout(p4reg);
147 1.17.4.2 nathanw if (peekval == -1)
148 1.17.4.2 nathanw return (0);
149 1.17.4.2 nathanw
150 1.17.4.2 nathanw /*
151 1.17.4.2 nathanw * The config flag 0x40 if set means we should match
152 1.17.4.2 nathanw * only on a CG? overlay plane. We can use only the
153 1.17.4.2 nathanw * CG4 and CG8, which both have a P4 register.
154 1.17.4.2 nathanw */
155 1.17.4.2 nathanw if (cf->cf_flags & 0x40) {
156 1.17.4.2 nathanw switch (p4id) {
157 1.17.4.2 nathanw case P4_ID_COLOR8P1:
158 1.17.4.2 nathanw case P4_ID_COLOR24:
159 1.17.4.2 nathanw return (1);
160 1.17.4.2 nathanw case P4_NOTFOUND:
161 1.17.4.2 nathanw default:
162 1.17.4.2 nathanw return (0);
163 1.17.4.2 nathanw }
164 1.17.4.2 nathanw }
165 1.17.4.2 nathanw
166 1.17.4.2 nathanw /*
167 1.17.4.2 nathanw * OK, we are expecting a plain old BW2, and
168 1.17.4.2 nathanw * there may or may not be a P4 register.
169 1.17.4.2 nathanw */
170 1.17.4.2 nathanw switch (p4id) {
171 1.17.4.2 nathanw case P4_ID_BW:
172 1.17.4.2 nathanw case P4_NOTFOUND:
173 1.17.4.2 nathanw return (1);
174 1.17.4.2 nathanw default:
175 1.17.4.2 nathanw #ifdef DEBUG
176 1.17.4.2 nathanw printf("bwtwo at 0x%x match p4id=0x%x fails\n",
177 1.17.4.2 nathanw ca->ca_paddr, p4id & 0xFF);
178 1.17.4.2 nathanw #endif
179 1.17.4.2 nathanw break;
180 1.17.4.2 nathanw }
181 1.17.4.2 nathanw
182 1.17.4.2 nathanw return (0);
183 1.17.4.2 nathanw }
184 1.17.4.2 nathanw
185 1.17.4.2 nathanw /*
186 1.17.4.2 nathanw * Attach a display. We need to notice if it is the console, too.
187 1.17.4.2 nathanw */
188 1.17.4.2 nathanw static void
189 1.17.4.2 nathanw bw2attach(parent, self, args)
190 1.17.4.2 nathanw struct device *parent, *self;
191 1.17.4.2 nathanw void *args;
192 1.17.4.2 nathanw {
193 1.17.4.2 nathanw struct bw2_softc *sc = (struct bw2_softc *)self;
194 1.17.4.2 nathanw struct fbdevice *fb = &sc->sc_fb;
195 1.17.4.2 nathanw struct confargs *ca = args;
196 1.17.4.2 nathanw struct fbtype *fbt;
197 1.17.4.2 nathanw void *p4reg;
198 1.17.4.2 nathanw int p4id, tmp;
199 1.17.4.2 nathanw int pixeloffset; /* offset to framebuffer */
200 1.17.4.2 nathanw
201 1.17.4.2 nathanw fbt = &fb->fb_fbtype;
202 1.17.4.2 nathanw fbt->fb_type = FBTYPE_SUN2BW;
203 1.17.4.2 nathanw fbt->fb_width = 1152; /* default - see below */
204 1.17.4.2 nathanw fbt->fb_height = 900; /* default - see below */
205 1.17.4.2 nathanw fbt->fb_depth = 1;
206 1.17.4.2 nathanw fbt->fb_cmsize = 0;
207 1.17.4.2 nathanw fbt->fb_size = BW2_FBSIZE; /* default - see below */
208 1.17.4.2 nathanw fb->fb_driver = &bw2fbdriver;
209 1.17.4.2 nathanw fb->fb_private = sc;
210 1.17.4.2 nathanw fb->fb_name = sc->sc_dev.dv_xname;
211 1.17.4.2 nathanw fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags;
212 1.17.4.2 nathanw
213 1.17.4.2 nathanw /* Set up default pixel offset. May be changed below. */
214 1.17.4.2 nathanw pixeloffset = 0;
215 1.17.4.2 nathanw
216 1.17.4.2 nathanw /* Does it have a P4 register? */
217 1.17.4.2 nathanw p4reg = bus_mapin(ca->ca_bustype, ca->ca_paddr, 4);
218 1.17.4.2 nathanw p4id = fb_pfour_id(p4reg);
219 1.17.4.2 nathanw if (p4id != P4_NOTFOUND)
220 1.17.4.2 nathanw fb->fb_pfour = p4reg;
221 1.17.4.2 nathanw else
222 1.17.4.2 nathanw bus_mapout(p4reg, 4);
223 1.17.4.2 nathanw
224 1.17.4.2 nathanw switch (p4id) {
225 1.17.4.2 nathanw case P4_NOTFOUND:
226 1.17.4.2 nathanw pixeloffset = 0;
227 1.17.4.2 nathanw break;
228 1.17.4.2 nathanw
229 1.17.4.2 nathanw case P4_ID_BW:
230 1.17.4.2 nathanw pixeloffset = P4_BW_OFF;
231 1.17.4.2 nathanw break;
232 1.17.4.2 nathanw
233 1.17.4.2 nathanw default:
234 1.17.4.2 nathanw printf("%s: bad p4id=0x%x\n", fb->fb_name, p4id);
235 1.17.4.2 nathanw /* Must be some kinda color... */
236 1.17.4.2 nathanw /* fall through */
237 1.17.4.2 nathanw case P4_ID_COLOR8P1:
238 1.17.4.2 nathanw case P4_ID_COLOR24:
239 1.17.4.2 nathanw sc->sc_ovtype = p4id;
240 1.17.4.2 nathanw pixeloffset = P4_COLOR_OFF_OVERLAY;
241 1.17.4.2 nathanw break;
242 1.17.4.2 nathanw }
243 1.17.4.2 nathanw sc->sc_phys = ca->ca_paddr + pixeloffset;
244 1.17.4.2 nathanw
245 1.17.4.2 nathanw /*
246 1.17.4.2 nathanw * Determine width and height as follows:
247 1.17.4.2 nathanw * If it has a P4 register, use that;
248 1.17.4.2 nathanw * else if unit==0, use the EEPROM size,
249 1.17.4.2 nathanw * else make our best guess.
250 1.17.4.2 nathanw */
251 1.17.4.2 nathanw if (fb->fb_pfour)
252 1.17.4.2 nathanw fb_pfour_setsize(fb);
253 1.17.4.2 nathanw else if (sc->sc_dev.dv_unit == 0)
254 1.17.4.2 nathanw fb_eeprom_setsize(fb);
255 1.17.4.2 nathanw else {
256 1.17.4.2 nathanw /* Guess based on machine ID. */
257 1.17.4.2 nathanw switch (cpu_machine_id) {
258 1.17.4.2 nathanw #ifdef _SUN3_
259 1.17.4.2 nathanw case SUN3_MACH_60:
260 1.17.4.2 nathanw /*
261 1.17.4.2 nathanw * Only the model 60 can have hi-res.
262 1.17.4.2 nathanw * Look at the "resolution" jumper.
263 1.17.4.2 nathanw */
264 1.17.4.2 nathanw tmp = bus_peek(BUS_OBMEM, BW2_CR_PADDR, 1);
265 1.17.4.2 nathanw if ((tmp != -1) && (tmp & 0x80) == 0)
266 1.17.4.2 nathanw goto high_res;
267 1.17.4.2 nathanw break;
268 1.17.4.2 nathanw
269 1.17.4.2 nathanw case SUN3_MACH_260:
270 1.17.4.2 nathanw /* The Sun3/260 is ALWAYS high-resolution! */
271 1.17.4.2 nathanw /* fall through */
272 1.17.4.2 nathanw high_res:
273 1.17.4.2 nathanw fbt->fb_width = 1600;
274 1.17.4.2 nathanw fbt->fb_height = 1280;
275 1.17.4.2 nathanw fbt->fb_size = BW2_FBSIZE_HIRES;
276 1.17.4.2 nathanw break;
277 1.17.4.2 nathanw #endif /* SUN3 */
278 1.17.4.2 nathanw
279 1.17.4.2 nathanw default:
280 1.17.4.2 nathanw /* Leave the defaults set above. */
281 1.17.4.2 nathanw break;
282 1.17.4.2 nathanw }
283 1.17.4.2 nathanw }
284 1.17.4.2 nathanw printf(" (%dx%d)\n", fbt->fb_width, fbt->fb_height);
285 1.17.4.2 nathanw
286 1.17.4.2 nathanw /* Make sure video is on. */
287 1.17.4.2 nathanw tmp = 1;
288 1.17.4.2 nathanw bw2svideo(fb, &tmp);
289 1.17.4.2 nathanw
290 1.17.4.2 nathanw /* Let /dev/fb know we are here. */
291 1.17.4.2 nathanw fb_attach(fb, 1);
292 1.17.4.2 nathanw }
293 1.17.4.2 nathanw
294 1.17.4.2 nathanw int
295 1.17.4.2 nathanw bw2open(dev, flags, mode, p)
296 1.17.4.2 nathanw dev_t dev;
297 1.17.4.2 nathanw int flags, mode;
298 1.17.4.2 nathanw struct proc *p;
299 1.17.4.2 nathanw {
300 1.17.4.2 nathanw int unit = minor(dev);
301 1.17.4.2 nathanw
302 1.17.4.2 nathanw if (unit >= bwtwo_cd.cd_ndevs || bwtwo_cd.cd_devs[unit] == NULL)
303 1.17.4.2 nathanw return (ENXIO);
304 1.17.4.2 nathanw return (0);
305 1.17.4.2 nathanw }
306 1.17.4.2 nathanw
307 1.17.4.2 nathanw int
308 1.17.4.2 nathanw bw2ioctl(dev, cmd, data, flags, p)
309 1.17.4.2 nathanw dev_t dev;
310 1.17.4.2 nathanw u_long cmd;
311 1.17.4.2 nathanw caddr_t data;
312 1.17.4.2 nathanw int flags;
313 1.17.4.2 nathanw struct proc *p;
314 1.17.4.2 nathanw {
315 1.17.4.2 nathanw struct bw2_softc *sc = bwtwo_cd.cd_devs[minor(dev)];
316 1.17.4.2 nathanw
317 1.17.4.2 nathanw return (fbioctlfb(&sc->sc_fb, cmd, data));
318 1.17.4.2 nathanw }
319 1.17.4.2 nathanw
320 1.17.4.2 nathanw /*
321 1.17.4.2 nathanw * Return the address that would map the given device at the given
322 1.17.4.2 nathanw * offset, allowing for the given protection, or return -1 for error.
323 1.17.4.2 nathanw */
324 1.17.4.2 nathanw paddr_t
325 1.17.4.2 nathanw bw2mmap(dev, off, prot)
326 1.17.4.2 nathanw dev_t dev;
327 1.17.4.2 nathanw off_t off;
328 1.17.4.2 nathanw int prot;
329 1.17.4.2 nathanw {
330 1.17.4.2 nathanw struct bw2_softc *sc = bwtwo_cd.cd_devs[minor(dev)];
331 1.17.4.2 nathanw int size = sc->sc_fb.fb_fbtype.fb_size;
332 1.17.4.2 nathanw
333 1.17.4.2 nathanw if (off & PGOFSET)
334 1.17.4.2 nathanw panic("bw2mmap");
335 1.17.4.2 nathanw
336 1.17.4.2 nathanw if ((off < 0) || (off >= size))
337 1.17.4.2 nathanw return (-1);
338 1.17.4.2 nathanw
339 1.17.4.2 nathanw /*
340 1.17.4.2 nathanw * I turned on PMAP_NC here to disable the cache as I was
341 1.17.4.2 nathanw * getting horribly broken behaviour without it.
342 1.17.4.2 nathanw */
343 1.17.4.2 nathanw return ((sc->sc_phys + off) | PMAP_NC);
344 1.17.4.2 nathanw }
345 1.17.4.2 nathanw
346 1.17.4.2 nathanw /* FBIOGVIDEO: */
347 1.17.4.2 nathanw static int bw2gvideo(fb, data)
348 1.17.4.2 nathanw struct fbdevice *fb;
349 1.17.4.2 nathanw void *data;
350 1.17.4.2 nathanw {
351 1.17.4.2 nathanw struct bw2_softc *sc = fb->fb_private;
352 1.17.4.2 nathanw int *on = data;
353 1.17.4.2 nathanw
354 1.17.4.2 nathanw *on = sc->sc_video_on;
355 1.17.4.2 nathanw return (0);
356 1.17.4.2 nathanw }
357 1.17.4.2 nathanw
358 1.17.4.2 nathanw /* FBIOSVIDEO: */
359 1.17.4.2 nathanw static int bw2svideo(fb, data)
360 1.17.4.2 nathanw struct fbdevice *fb;
361 1.17.4.2 nathanw void *data;
362 1.17.4.2 nathanw {
363 1.17.4.2 nathanw struct bw2_softc *sc = fb->fb_private;
364 1.17.4.2 nathanw int *on = data;
365 1.17.4.2 nathanw
366 1.17.4.2 nathanw if (sc->sc_video_on == *on)
367 1.17.4.2 nathanw return (0);
368 1.17.4.2 nathanw sc->sc_video_on = *on;
369 1.17.4.2 nathanw
370 1.17.4.2 nathanw if (fb->fb_pfour)
371 1.17.4.2 nathanw fb_pfour_set_video(fb, sc->sc_video_on);
372 1.17.4.2 nathanw else
373 1.17.4.2 nathanw enable_video(sc->sc_video_on);
374 1.17.4.2 nathanw
375 1.17.4.2 nathanw return(0);
376 1.17.4.2 nathanw }
377 1.17.4.2 nathanw
378