Annotation of sys/arch/sparc/dev/fb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: fb.c,v 1.43 2006/12/03 22:10:30 miod Exp $ */
2: /* $NetBSD: fb.c,v 1.23 1997/07/07 23:30:22 pk Exp $ */
3:
4: /*
5: * Copyright (c) 2002, 2004 Miodrag Vallat.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27: * POSSIBILITY OF SUCH DAMAGE.
28: *
29: *
30: * Copyright (c) 1992, 1993
31: * The Regents of the University of California. All rights reserved.
32: *
33: * This software was developed by the Computer Systems Engineering group
34: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
35: * contributed to Berkeley.
36: *
37: * All advertising materials mentioning features or use of this software
38: * must display the following acknowledgement:
39: * This product includes software developed by the University of
40: * California, Lawrence Berkeley Laboratory.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. Neither the name of the University nor the names of its contributors
51: * may be used to endorse or promote products derived from this software
52: * without specific prior written permission.
53: *
54: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64: * SUCH DAMAGE.
65: *
66: * @(#)fb.c 8.1 (Berkeley) 6/11/93
67: */
68:
69: /*
70: * Common wsdisplay framebuffer drivers helpers.
71: */
72:
73: #include <sys/param.h>
74: #include <sys/systm.h>
75: #include <sys/device.h>
76: #include <sys/proc.h>
77: #include <sys/conf.h>
78:
79: #include <machine/autoconf.h>
80: #include <machine/conf.h>
81: #if defined(SUN4)
82: #include <machine/eeprom.h>
83: #include <sparc/dev/pfourreg.h>
84: #endif
85:
86: #include <dev/wscons/wsdisplayvar.h>
87: #include <dev/rasops/rasops.h>
88: #include <machine/fbvar.h>
89:
90: #include "wsdisplay.h"
91:
92: /*
93: * Sun specific color indexes.
94: * Black is not really 7, but rather ~0; to fit within the 8 ANSI color
95: * palette we are using on console, we pick (~0) & 0x07 instead.
96: * This essentially swaps WSCOL_BLACK and WSCOL_WHITE.
97: */
98: #define WSCOL_SUN_WHITE 0
99: #define WSCOL_SUN_BLACK 7
100:
101: /*
102: * emergency unblank code
103: * XXX should be somewhat moved to wscons MI code
104: */
105:
106: void (*fb_burner)(void *, u_int, u_int);
107: void *fb_cookie;
108:
109: void
110: fb_unblank()
111: {
112: if (fb_burner != NULL)
113: (*fb_burner)(fb_cookie, 1, 0);
114: }
115:
116: #if NWSDISPLAY > 0
117:
118: #if defined(SUN4C) || defined(SUN4M)
119: static int a2int(char *, int);
120: #endif
121: static void fb_initwsd(struct sunfb *);
122: static void fb_updatecursor(struct rasops_info *);
123: int fb_alloc_screen(void *, const struct wsscreen_descr *, void **,
124: int *, int *, long *);
125: void fb_free_screen(void *, void *);
126: int fb_show_screen(void *, void *, int, void (*)(void *, int, int),
127: void *);
128:
129: void
130: fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height,
131: int node, int bustype)
132: {
133: int def_linebytes;
134:
135: switch (bustype) {
136: case BUS_VME16:
137: case BUS_VME32:
138: case BUS_OBIO:
139: #if defined(SUN4M)
140: /* 4m may have SBus-like framebuffer on obio */
141: if (CPU_ISSUN4M) {
142: goto obpsize;
143: }
144: #endif
145: /* Set up some defaults. */
146: sf->sf_width = def_width;
147: sf->sf_height = def_height;
148: sf->sf_depth = def_depth;
149:
150: #if defined(SUN4)
151: /*
152: * This is not particularly useful on Sun 4 VME framebuffers.
153: * The EEPROM only contains info about the built-in.
154: */
155: if (CPU_ISSUN4 && bustype == BUS_OBIO) {
156: struct eeprom *eep = (struct eeprom *)eeprom_va;
157:
158: if (ISSET(sf->sf_flags, FB_PFOUR)) {
159: volatile u_int32_t pfour;
160: u_int size;
161:
162: pfour = *sf->sf_pfour;
163:
164: /*
165: * Use the pfour register to determine
166: * the size. Note that the cgsix and
167: * cgeight don't use this size encoding.
168: * In this case, we have to settle
169: * for the defaults we were provided
170: * with.
171: */
172: if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) ||
173: (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR))
174: size = 0x00; /* invalid */
175: else
176: size = PFOUR_SIZE(pfour);
177:
178: switch (size) {
179: case PFOUR_SIZE_1152X900:
180: sf->sf_width = 1152;
181: sf->sf_height = 900;
182: break;
183: case PFOUR_SIZE_1024X1024:
184: sf->sf_width = 1024;
185: sf->sf_height = 1024;
186: break;
187: case PFOUR_SIZE_1280X1024:
188: sf->sf_width = 1280;
189: sf->sf_height = 1024;
190: break;
191: case PFOUR_SIZE_1600X1280:
192: sf->sf_width = 1600;
193: sf->sf_height = 1280;
194: break;
195: case PFOUR_SIZE_1440X1440:
196: sf->sf_width = 1440;
197: sf->sf_height = 1440;
198: break;
199: case PFOUR_SIZE_640X480:
200: sf->sf_width = 640;
201: sf->sf_height = 480;
202: break;
203: }
204: } else if (eep != NULL) {
205: switch (eep->eeScreenSize) {
206: case EE_SCR_1152X900:
207: sf->sf_width = 1152;
208: sf->sf_height = 900;
209: break;
210: case EE_SCR_1024X1024:
211: sf->sf_width = 1024;
212: sf->sf_height = 1024;
213: break;
214: case EE_SCR_1600X1280:
215: sf->sf_width = 1600;
216: sf->sf_height = 1280;
217: break;
218: case EE_SCR_1440X1440:
219: sf->sf_width = 1440;
220: sf->sf_height = 1440;
221: break;
222: }
223: }
224: }
225: #endif /* SUN4 */
226: #if defined(SUN4M)
227: if (CPU_ISSUN4M) {
228: /* XXX: need code to find 4/600 vme screen size */
229: }
230: #endif /* SUN4M */
231:
232: sf->sf_linebytes = (sf->sf_width * sf->sf_depth) / 8;
233: break;
234:
235: case BUS_SBUS:
236: #if defined(SUN4M)
237: obpsize:
238: #endif
239: sf->sf_depth = getpropint(node, "depth", def_depth);
240: sf->sf_width = getpropint(node, "width", def_width);
241: sf->sf_height = getpropint(node, "height", def_height);
242:
243: def_linebytes =
244: roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8;
245: sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes);
246:
247: /*
248: * XXX If we are configuring a board in a wider depth level
249: * than the mode it is currently operating in, the PROM will
250: * return a linebytes property tied to the current depth value,
251: * which is NOT what we are relying upon!
252: */
253: if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8)
254: sf->sf_linebytes = def_linebytes;
255:
256: break;
257: }
258:
259: sf->sf_fbsize = sf->sf_height * sf->sf_linebytes;
260: }
261:
262: #if defined(SUN4C) || defined(SUN4M)
263: static int
264: a2int(char *cp, int deflt)
265: {
266: int i = 0;
267:
268: if (*cp == '\0')
269: return (deflt);
270: while (*cp != '\0')
271: i = i * 10 + *cp++ - '0';
272: return (i);
273: }
274: #endif
275:
276: /* setup the embedded wsscreen_descr structure from rasops settings */
277: static void
278: fb_initwsd(struct sunfb *sf)
279: {
280: strlcpy(sf->sf_wsd.name, "std", sizeof(sf->sf_wsd.name));
281: sf->sf_wsd.capabilities = sf->sf_ro.ri_caps;
282: sf->sf_wsd.nrows = sf->sf_ro.ri_rows;
283: sf->sf_wsd.ncols = sf->sf_ro.ri_cols;
284: sf->sf_wsd.textops = &sf->sf_ro.ri_ops;
285: }
286:
287: static void
288: fb_updatecursor(struct rasops_info *ri)
289: {
290: struct sunfb *sf = (struct sunfb *)ri->ri_hw;
291:
292: if (sf->sf_crowp != NULL)
293: *sf->sf_crowp = ri->ri_crow;
294: if (sf->sf_ccolp != NULL)
295: *sf->sf_ccolp = ri->ri_ccol;
296: }
297:
298: void
299: fbwscons_init(struct sunfb *sf, int flags)
300: {
301: struct rasops_info *ri = &sf->sf_ro;
302: int cols, rows;
303:
304: /* ri_hw and ri_bits must have already been setup by caller */
305: ri->ri_flg = RI_CENTER | RI_FULLCLEAR | flags;
306: ri->ri_depth = sf->sf_depth;
307: ri->ri_stride = sf->sf_linebytes;
308: ri->ri_width = sf->sf_width;
309: ri->ri_height = sf->sf_height;
310:
311: #if defined(SUN4C) || defined(SUN4M)
312: if (CPU_ISSUN4COR4M) {
313: rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34);
314: cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80);
315: }
316: #endif
317: #if defined(SUN4)
318: if (CPU_ISSUN4) {
319: struct eeprom *ep = (struct eeprom *)eeprom_va;
320:
321: if (ep != NULL) {
322: rows = (u_short)ep->eeTtyRows;
323: cols = (u_short)ep->eeTtyCols;
324: /* deal with broken nvram contents... */
325: if (rows <= 0)
326: rows = 34;
327: if (cols <= 0)
328: cols = 80;
329: } else {
330: rows = 34;
331: cols = 80;
332: }
333: }
334: #endif
335:
336: rasops_init(ri, rows, cols);
337:
338: if (sf->sf_depth == 8) {
339: /*
340: * If we are running with an indexed palette, compensate
341: * the swap of black and white through ri_devcmap.
342: */
343: ri->ri_devcmap[WSCOL_SUN_BLACK] = 0;
344: ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff;
345: } else if (sf->sf_depth > 8) {
346: /*
347: * If we are running on a direct color frame buffer,
348: * make the ``normal'' white the same as the hilighted
349: * white.
350: */
351: ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8];
352: }
353: }
354:
355: void
356: fbwscons_console_init(struct sunfb *sf, int row)
357: {
358: struct rasops_info *ri = &sf->sf_ro;
359: long defattr;
360:
361: if (CPU_ISSUN4 || romgetcursoraddr(&sf->sf_crowp, &sf->sf_ccolp))
362: sf->sf_ccolp = sf->sf_crowp = NULL;
363: if (sf->sf_ccolp != NULL)
364: ri->ri_ccol = *sf->sf_ccolp;
365:
366: if (row < 0) {
367: if (sf->sf_crowp != NULL)
368: ri->ri_crow = *sf->sf_crowp;
369: else
370: /* assume last row */
371: ri->ri_crow = ri->ri_rows - 1;
372: } else {
373: /*
374: * If we force the display row, this is because the screen
375: * has been cleared or the font has been changed.
376: * In this case, choose not to keep pointers to the PROM
377: * cursor position, as the values are likely to be inaccurate
378: * upon shutdown...
379: */
380: sf->sf_crowp = sf->sf_ccolp = NULL;
381: ri->ri_crow = row;
382: }
383:
384: /*
385: * Scale back rows and columns if the font would not otherwise
386: * fit on this display. Without this we would panic later.
387: */
388: if (ri->ri_crow >= ri->ri_rows)
389: ri->ri_crow = ri->ri_rows - 1;
390: if (ri->ri_ccol >= ri->ri_cols)
391: ri->ri_ccol = ri->ri_cols - 1;
392:
393: /*
394: * Take care of updating the PROM cursor position as well if we can.
395: */
396: if (ri->ri_updatecursor == NULL &&
397: (sf->sf_ccolp != NULL || sf->sf_crowp != NULL))
398: ri->ri_updatecursor = fb_updatecursor;
399:
400: if (ISSET(ri->ri_caps, WSSCREEN_WSCOLORS))
401: ri->ri_ops.alloc_attr(ri,
402: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, &defattr);
403: else
404: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
405:
406: fb_initwsd(sf);
407: wsdisplay_cnattach(&sf->sf_wsd, ri,
408: ri->ri_ccol, ri->ri_crow, defattr);
409: }
410:
411: void
412: fbwscons_setcolormap(struct sunfb *sf,
413: void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t))
414: {
415: int i;
416: const u_char *color;
417:
418: if (sf->sf_depth <= 8 && setcolor != NULL) {
419: for (i = 0; i < 16; i++) {
420: color = &rasops_cmap[i * 3];
421: setcolor(sf, i, color[0], color[1], color[2]);
422: }
423: for (i = 240; i < 256; i++) {
424: color = &rasops_cmap[i * 3];
425: setcolor(sf, i, color[0], color[1], color[2]);
426: }
427: /*
428: * Compensate for BoW default hardware palette: existing
429: * output (which we do not want to affect) is black on
430: * white with color index 0 being white and 0xff being
431: * black.
432: */
433: setcolor(sf, WSCOL_SUN_WHITE, 0xff, 0xff, 0xff);
434: setcolor(sf, 0xff ^ WSCOL_SUN_WHITE, 0, 0, 0);
435: setcolor(sf, WSCOL_SUN_BLACK, 0, 0, 0);
436: setcolor(sf, 0xff ^ (WSCOL_SUN_BLACK), 0xff, 0xff, 0xff);
437: }
438: }
439:
440: void
441: fbwscons_attach(struct sunfb *sf, struct wsdisplay_accessops *op, int isconsole)
442: {
443: struct wsemuldisplaydev_attach_args waa;
444:
445: if (isconsole == 0) {
446: /* done in wsdisplay_cnattach() earlier if console */
447: fb_initwsd(sf);
448: } else {
449: /* remember screen burner routine */
450: fb_burner = op->burn_screen;
451: fb_cookie = sf;
452: }
453:
454: /* plug common wsdisplay_accessops if necessary */
455: if (op->alloc_screen == NULL) {
456: op->alloc_screen = fb_alloc_screen;
457: op->free_screen = fb_free_screen;
458: op->show_screen = fb_show_screen;
459: }
460:
461: sf->sf_scrlist[0] = &sf->sf_wsd;
462: sf->sf_wsl.nscreens = 1;
463: sf->sf_wsl.screens = (const struct wsscreen_descr **)sf->sf_scrlist;
464:
465: waa.console = isconsole;
466: waa.scrdata = &sf->sf_wsl;
467: waa.accessops = op;
468: waa.accesscookie = sf;
469: waa.defaultscreens = 0;
470: config_found(&sf->sf_dev, &waa, wsemuldisplaydevprint);
471: }
472:
473: /*
474: * Common wsdisplay_accessops routines.
475: */
476: int
477: fb_alloc_screen(void *v, const struct wsscreen_descr *type,
478: void **cookiep, int *curxp, int *curyp, long *attrp)
479: {
480: struct sunfb *sf = v;
481: struct rasops_info *ri = &sf->sf_ro;
482:
483: if (sf->sf_nscreens > 0)
484: return (ENOMEM);
485:
486: *cookiep = ri;
487: *curyp = 0;
488: *curxp = 0;
489: if (ISSET(ri->ri_caps, WSSCREEN_WSCOLORS))
490: ri->ri_ops.alloc_attr(ri,
491: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
492: else
493: ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
494: sf->sf_nscreens++;
495: return (0);
496: }
497:
498: void
499: fb_free_screen(void *v, void *cookie)
500: {
501: struct sunfb *sf = v;
502:
503: sf->sf_nscreens--;
504: }
505:
506: int
507: fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
508: void *cbarg)
509: {
510: return (0);
511: }
512:
513: #if defined(SUN4)
514:
515: /*
516: * Support routines for P4 framebuffers.
517: */
518:
519: /*
520: * Probe for a P4 framebuffer. Return values:
521: * PFOUR_NOTPFOUR framebuffer is not a P4 framebuffer
522: * otherwise returns P4 ID
523: */
524: int
525: fb_pfour_id(void *va)
526: {
527: volatile u_int32_t val, save, *pfour = va;
528:
529: /* Read the pfour register. */
530: save = *pfour;
531:
532: /*
533: * Try to modify the type code. If it changes, put the
534: * original value back, and notify the caller that it's
535: * not a pfour framebuffer.
536: */
537: val = save & ~PFOUR_REG_RESET;
538: *pfour = (val ^ PFOUR_FBTYPE_MASK);
539: if ((*pfour ^ val) & PFOUR_FBTYPE_MASK) {
540: *pfour = save;
541: return (PFOUR_NOTPFOUR);
542: }
543:
544: return (PFOUR_ID(val));
545: }
546:
547: /*
548: * Screen burner routine for P4
549: */
550: void
551: fb_pfour_burner(void *v, u_int enable, u_int flags)
552: {
553: struct sunfb *sf = (struct sunfb *)v;
554: volatile u_int32_t pfour;
555:
556: pfour = *sf->sf_pfour & ~(PFOUR_REG_INTCLR | PFOUR_REG_VIDEO);
557: *sf->sf_pfour = pfour | (enable ? PFOUR_REG_VIDEO : 0);
558: }
559:
560: #endif /* SUN4 */
561:
562: #endif /* NWSDISPLAY */
CVSweb