FreeBSD/Linux Kernel Cross Reference
sys/dev/sun/fb.c
1 /* $NetBSD: fb.c,v 1.19 2004/03/19 16:05:25 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. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)fb.c 8.1 (Berkeley) 6/11/93
41 */
42
43 /*
44 * /dev/fb (indirect frame buffer driver). This is gross; we should
45 * just build cdevsw[] dynamically.
46 */
47
48 #include <sys/cdefs.h>
49 __KERNEL_RCSID(0, "$NetBSD: fb.c,v 1.19 2004/03/19 16:05:25 pk Exp $");
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/device.h>
54 #include <sys/proc.h>
55 #include <sys/conf.h>
56
57 #include <machine/promlib.h>
58 #include <machine/autoconf.h>
59 #include <machine/kbd.h>
60 #include <machine/eeprom.h>
61 #include <sparc/dev/cons.h>
62
63 #include <dev/sun/fbio.h>
64 #include <dev/sun/fbvar.h>
65
66 #include "kbd.h"
67 #include "pfour.h"
68
69 static struct fbdevice *devfb;
70
71 dev_type_open(fbopen);
72 dev_type_close(fbclose);
73 dev_type_ioctl(fbioctl);
74 dev_type_poll(fbpoll);
75 dev_type_mmap(fbmmap);
76 dev_type_kqfilter(fbkqfilter);
77
78 const struct cdevsw fb_cdevsw = {
79 fbopen, fbclose, noread, nowrite, fbioctl,
80 nostop, notty, fbpoll, fbmmap, fbkqfilter,
81 };
82
83 void
84 fb_unblank()
85 {
86
87 if (devfb)
88 (*devfb->fb_driver->fbd_unblank)(devfb->fb_device);
89 }
90
91 /*
92 * Helper function for frame buffer devices. Decides whether
93 * the device can be the console output device according to
94 * PROM info. The result from this function may not be conclusive
95 * on machines with old PROMs; in that case, drivers should consult
96 * other sources of configuration information (e.g. EEPROM entries).
97 */
98 int
99 fb_is_console(node)
100 int node;
101 {
102 #if !defined(SUN4U)
103 int fbnode;
104
105 switch (prom_version()) {
106 case PROM_OLDMON:
107 /* `node' is not valid; just check for any fb device */
108 return (prom_stdout() == PROMDEV_SCREEN);
109
110 case PROM_OBP_V0:
111 /*
112 * First, check if prom_stdout() represents a frame buffer,
113 * then match on the `fb' property on the root node, if any.
114 */
115 if (prom_stdout() != PROMDEV_SCREEN)
116 return (0);
117
118 fbnode = prom_getpropint(findroot(), "fb", 0);
119 return (fbnode == 0 || node == fbnode);
120
121 case PROM_OBP_V2:
122 case PROM_OBP_V3:
123 case PROM_OPENFIRM:
124 /* Just match the nodes */
125 return (node == prom_stdout_node);
126 }
127
128 return (0);
129 #else
130 return (node == prom_stdout_node);
131 #endif
132 }
133
134 void
135 fb_attach(fb, isconsole)
136 struct fbdevice *fb;
137 int isconsole;
138 {
139 static int no_replace, seen_force;
140
141 /*
142 * We've already had a framebuffer forced into /dev/fb. Don't
143 * allow any more, even if this is the console.
144 */
145 if (seen_force) {
146 if (devfb) { /* sanity */
147 printf("%s: /dev/fb already full\n",
148 fb->fb_device->dv_xname);
149 return;
150 } else
151 seen_force = 0;
152 }
153
154 /*
155 * Check to see if we're being forced into /dev/fb.
156 */
157 if (fb->fb_flags & FB_FORCE) {
158 if (devfb)
159 printf("%s: forcefully replacing %s\n",
160 fb->fb_device->dv_xname,
161 devfb->fb_device->dv_xname);
162 devfb = fb;
163 seen_force = no_replace = 1;
164 goto attached;
165 }
166
167 /*
168 * Check to see if we're the console. If we are, then replace
169 * any currently existing framebuffer.
170 */
171 if (isconsole) {
172 if (devfb)
173 printf("%s: replacing %s\n", fb->fb_device->dv_xname,
174 devfb->fb_device->dv_xname);
175 devfb = fb;
176 no_replace = 1;
177 goto attached;
178 }
179
180 /*
181 * For the final case, we check to see if we can replace an
182 * existing framebuffer, if not, say so and return.
183 */
184 if (no_replace) {
185 if (devfb) { /* sanity */
186 printf("%s: /dev/fb already full\n",
187 fb->fb_device->dv_xname);
188 return;
189 } else
190 no_replace = 0;
191 }
192
193 if (devfb)
194 printf("%s: replacing %s\n", fb->fb_device->dv_xname,
195 devfb->fb_device->dv_xname);
196 devfb = fb;
197
198 attached:
199 printf("%s: attached to /dev/fb\n", devfb->fb_device->dv_xname);
200 }
201
202 int
203 fbopen(dev, flags, mode, p)
204 dev_t dev;
205 int flags, mode;
206 struct proc *p;
207 {
208
209 if (devfb == NULL)
210 return (ENXIO);
211 return (devfb->fb_driver->fbd_open)(dev, flags, mode, p);
212 }
213
214 int
215 fbclose(dev, flags, mode, p)
216 dev_t dev;
217 int flags, mode;
218 struct proc *p;
219 {
220
221 return (devfb->fb_driver->fbd_close)(dev, flags, mode, p);
222 }
223
224 int
225 fbioctl(dev, cmd, data, flags, p)
226 dev_t dev;
227 u_long cmd;
228 caddr_t data;
229 int flags;
230 struct proc *p;
231 {
232
233 return (devfb->fb_driver->fbd_ioctl)(dev, cmd, data, flags, p);
234 }
235
236 int
237 fbpoll(dev, events, p)
238 dev_t dev;
239 int events;
240 struct proc *p;
241 {
242
243 return (devfb->fb_driver->fbd_poll)(dev, events, p);
244 }
245
246 int
247 fbkqfilter(dev, kn)
248 dev_t dev;
249 struct knote *kn;
250 {
251
252 return (devfb->fb_driver->fbd_kqfilter)(dev, kn);
253 }
254
255 paddr_t
256 fbmmap(dev, off, prot)
257 dev_t dev;
258 off_t off;
259 int prot;
260 {
261 paddr_t (*map)__P((dev_t, off_t, int)) = devfb->fb_driver->fbd_mmap;
262
263 if (map == NULL)
264 return (-1);
265 return (map(dev, off, prot));
266 }
267
268 void
269 fb_setsize_obp(fb, depth, def_width, def_height, node)
270 struct fbdevice *fb;
271 int depth, def_width, def_height, node;
272 {
273 fb->fb_type.fb_width = prom_getpropint(node, "width", def_width);
274 fb->fb_type.fb_height = prom_getpropint(node, "height", def_height);
275 fb->fb_linebytes = prom_getpropint(node, "linebytes",
276 (fb->fb_type.fb_width * depth) / 8);
277 }
278
279 void
280 fb_setsize_eeprom(fb, depth, def_width, def_height)
281 struct fbdevice *fb;
282 int depth, def_width, def_height;
283 {
284 #if !defined(SUN4U)
285 struct eeprom *eep = (struct eeprom *)eeprom_va;
286
287 if (!CPU_ISSUN4) {
288 printf("fb_setsize_eeprom: not sun4\n");
289 return;
290 }
291
292 /* Set up some defaults. */
293 fb->fb_type.fb_width = def_width;
294 fb->fb_type.fb_height = def_height;
295
296 if (fb->fb_flags & FB_PFOUR) {
297 #if NPFOUR > 0
298 fb_setsize_pfour(fb);
299 #endif
300 } else if (eep != NULL) {
301 switch (eep->eeScreenSize) {
302 case EE_SCR_1152X900:
303 fb->fb_type.fb_width = 1152;
304 fb->fb_type.fb_height = 900;
305 break;
306
307 case EE_SCR_1024X1024:
308 fb->fb_type.fb_width = 1024;
309 fb->fb_type.fb_height = 1024;
310 break;
311
312 case EE_SCR_1600X1280:
313 fb->fb_type.fb_width = 1600;
314 fb->fb_type.fb_height = 1280;
315 break;
316
317 case EE_SCR_1440X1440:
318 fb->fb_type.fb_width = 1440;
319 fb->fb_type.fb_height = 1440;
320 break;
321
322 default:
323 /*
324 * XXX: Do nothing, I guess.
325 * Should we print a warning about
326 * an unknown value? --thorpej
327 */
328 break;
329 }
330 }
331
332 fb->fb_linebytes = (fb->fb_type.fb_width * depth) / 8;
333 #endif /* !SUN4U */
334 }
335
336
337
338 #ifdef RASTERCONSOLE
339 #include <machine/kbd.h>
340
341 static void fb_bell __P((int));
342
343 static void
344 fb_bell(on)
345 int on;
346 {
347 #if NKBD > 0
348 kbd_bell(on);
349 #endif
350 }
351
352 void
353 fbrcons_init(fb)
354 struct fbdevice *fb;
355 {
356 struct rconsole *rc = &fb->fb_rcons;
357 struct rasops_info *ri = &fb->fb_rinfo;
358 int maxrow, maxcol;
359 #if !defined(RASTERCONS_FULLSCREEN)
360 int *row, *col;
361 #endif
362
363 /* Set up what rasops needs to know about */
364 bzero(ri, sizeof *ri);
365 ri->ri_stride = fb->fb_linebytes;
366 ri->ri_bits = (caddr_t)fb->fb_pixels;
367 ri->ri_depth = fb->fb_type.fb_depth;
368 ri->ri_width = fb->fb_type.fb_width;
369 ri->ri_height = fb->fb_type.fb_height;
370 maxrow = 5000;
371 maxcol = 5000;
372
373 #if !defined(RASTERCONS_FULLSCREEN)
374 #if !defined(SUN4U)
375 if (CPU_ISSUN4) {
376 struct eeprom *eep = (struct eeprom *)eeprom_va;
377
378 if (eep == NULL) {
379 maxcol = 80;
380 maxrow = 34;
381 } else {
382 maxcol = eep->eeTtyCols;
383 maxrow = eep->eeTtyRows;
384 }
385 }
386 #endif /* !SUN4U */
387 if (!CPU_ISSUN4) {
388 char buf[6+1]; /* Enough for six digits */
389 maxcol = (prom_getoption("screen-#columns", buf, sizeof buf) == 0)
390 ? strtoul(buf, NULL, 10)
391 : 80;
392
393 maxrow = (prom_getoption("screen-#rows", buf, sizeof buf) != 0)
394 ? strtoul(buf, NULL, 10)
395 : 34;
396
397 }
398 #endif /* !RASTERCONS_FULLSCREEN */
399 /*
400 * - force monochrome output
401 * - eraserows() hack to clear the *entire* display
402 * - cursor is currently enabled
403 * - center output
404 */
405 ri->ri_flg = RI_FULLCLEAR | RI_CURSOR | RI_CENTER;
406
407 /* Get operations set and connect to rcons */
408 if (rasops_init(ri, maxrow, maxcol))
409 panic("fbrcons_init: rasops_init failed!");
410
411 if (ri->ri_depth == 8) {
412 int i;
413 for (i = 0; i < 16; i++) {
414
415 /*
416 * Cmap entries are repeated four times in the
417 * 32 bit wide `devcmap' entries for optimization
418 * purposes; see rasops(9)
419 */
420 #define I_TO_DEVCMAP(i) ((i) | ((i)<<8) | ((i)<<16) | ((i)<<24))
421
422 /*
423 * Use existing colormap entries for black and white
424 */
425 if ((i & 7) == WSCOL_BLACK) {
426 ri->ri_devcmap[i] = I_TO_DEVCMAP(255);
427 continue;
428 }
429
430 if ((i & 7) == WSCOL_WHITE) {
431 ri->ri_devcmap[i] = I_TO_DEVCMAP(0);
432 continue;
433 }
434 /*
435 * Other entries refer to ANSI map, which for now
436 * is setup in bt_subr.c
437 */
438 ri->ri_devcmap[i] = I_TO_DEVCMAP(i + 1);
439 #undef I_TO_DEVCMAP
440 }
441 }
442
443 rc->rc_row = rc->rc_col = 0;
444 #if !defined(RASTERCONS_FULLSCREEN)
445 /* Determine addresses of prom emulator row and column */
446 if (!CPU_ISSUN4 && !romgetcursoraddr(&row, &col)) {
447 rc->rc_row = *row;
448 rc->rc_col = *col;
449 }
450 #endif
451 ri->ri_crow = rc->rc_row;
452 ri->ri_ccol = rc->rc_col;
453
454 rc->rc_ops = &ri->ri_ops;
455 rc->rc_cookie = ri;
456 rc->rc_bell = fb_bell;
457 rc->rc_maxcol = ri->ri_cols;
458 rc->rc_maxrow = ri->ri_rows;
459 rc->rc_width = ri->ri_emuwidth;
460 rc->rc_height = ri->ri_emuheight;
461 rc->rc_deffgcolor = WSCOL_BLACK;
462 rc->rc_defbgcolor = WSCOL_WHITE;
463 rcons_init(rc, 0);
464
465 /* Hook up virtual console */
466 v_putc = rcons_cnputc;
467 }
468
469 int
470 fbrcons_rows()
471 {
472 return (devfb ? devfb->fb_rcons.rc_maxrow : 0);
473 }
474
475 int
476 fbrcons_cols()
477 {
478 return (devfb ? devfb->fb_rcons.rc_maxcol : 0);
479 }
480 #endif /* RASTERCONSOLE */
Cache object: 387bebb3834c8697f61c2fbfaba61a6a
|