Annotation of sys/arch/mac68k/dev/macfb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: macfb.c,v 1.18 2006/11/29 12:13:54 miod Exp $ */
2: /* $NetBSD: macfb.c,v 1.11 2005/01/15 16:00:59 chs Exp $ */
3: /*
4: * Copyright (c) 1998 Matt DeBergalis
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Matt DeBergalis
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/kernel.h>
36: #include <sys/device.h>
37: #include <sys/malloc.h>
38:
39: #include <machine/cpu.h>
40: #include <machine/bus.h>
41:
42: #include <mac68k/dev/nubus.h>
43:
44: #include <uvm/uvm_extern.h>
45:
46: #include <dev/wscons/wsconsio.h>
47: #include <dev/wscons/wsdisplayvar.h>
48: #include <dev/rasops/rasops.h>
49:
50: #include <mac68k/dev/macfbvar.h>
51:
52: struct cfdriver macfb_cd = {
53: NULL, "macfb", DV_DULL
54: };
55:
56: int macfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
57: paddr_t macfb_mmap(void *, off_t, int);
58: int macfb_alloc_screen(void *, const struct wsscreen_descr *,
59: void **, int *, int *, long *);
60: void macfb_free_screen(void *, void *);
61: int macfb_show_screen(void *, void *, int,
62: void (*)(void *, int, int), void *);
63:
64: const struct wsdisplay_accessops macfb_accessops = {
65: macfb_ioctl,
66: macfb_mmap,
67: macfb_alloc_screen,
68: macfb_free_screen,
69: macfb_show_screen,
70: NULL, /* load_font */
71: NULL, /* scrollback */
72: NULL, /* getchar */
73: NULL /* burner */
74: };
75:
76: int macfb_alloc_cattr(void *, int, int, int, long *);
77: int macfb_alloc_hattr(void *, int, int, int, long *);
78: int macfb_alloc_mattr(void *, int, int, int, long *);
79: int macfb_color_setup(struct macfb_devconfig *);
80: int macfb_getcmap(struct macfb_devconfig *, struct wsdisplay_cmap *);
81: int macfb_init(struct macfb_devconfig *);
82: int macfb_is_console(paddr_t);
83: void macfb_palette_setup(struct macfb_devconfig *);
84: int macfb_putcmap(struct macfb_devconfig *, struct wsdisplay_cmap *);
85:
86: paddr_t macfb_consaddr;
87:
88: static struct macfb_devconfig macfb_console_dc;
89:
90: /* From Booter via locore */
91: extern long videoaddr;
92: extern long videorowbytes;
93: extern long videobitdepth;
94: extern u_long videosize;
95: extern u_int32_t mac68k_vidphys;
96: extern u_int32_t mac68k_vidlen;
97:
98: extern int rasops_alloc_cattr(void *, int, int, int, long *);
99:
100: int
101: macfb_is_console(paddr_t addr)
102: {
103: if (addr != macfb_consaddr && (addr >= NBBASE && addr < NBTOP)) {
104: /*
105: * This is in the NuBus standard slot space range, so we
106: * may well have to look at 0xFssxxxxx, too. Mask off the
107: * slot number and duplicate it in bits 20-23, per IM:V
108: * pp 459, 463, and IM:VI ch 30 p 17.
109: * Note: this is an ugly hack and I wish I knew what
110: * to do about it. -- sr
111: */
112: addr = (paddr_t)(((u_long)addr & 0xff0fffff) |
113: (((u_long)addr & 0x0f000000) >> 4));
114: }
115: return ((mac68k_machine.serial_console & 0x03) == 0
116: && (addr == macfb_consaddr));
117: }
118:
119: int
120: macfb_init(struct macfb_devconfig *dc)
121: {
122: struct rasops_info *ri = &dc->dc_ri;
123: int bgcolor;
124:
125: bzero(ri, sizeof(*ri));
126: ri->ri_depth = dc->dc_depth;
127: ri->ri_stride = dc->dc_rowbytes;
128: ri->ri_flg = RI_CENTER;
129: ri->ri_bits = (void *)(dc->dc_vaddr + dc->dc_offset);
130: ri->ri_width = dc->dc_wid;
131: ri->ri_height = dc->dc_ht;
132: ri->ri_hw = dc;
133:
134: /* swap B and R if necessary */
135: switch (ri->ri_depth) {
136: case 16:
137: ri->ri_rnum = 5;
138: ri->ri_rpos = 11;
139: ri->ri_gnum = 6;
140: ri->ri_gpos = 5;
141: ri->ri_bnum = 5;
142: ri->ri_bpos = 0;
143: break;
144: case 24:
145: case 32:
146: ri->ri_rnum = 8;
147: ri->ri_rpos = 16;
148: ri->ri_gnum = 8;
149: ri->ri_gpos = 8;
150: ri->ri_bnum = 8;
151: ri->ri_bpos = 0;
152: break;
153: }
154:
155: /*
156: * Ask for an unholy big display, rasops will trim this to more
157: * reasonable values.
158: */
159: if (rasops_init(ri, 160, 160) != 0)
160: return (-1);
161:
162: bgcolor = macfb_color_setup(dc);
163:
164: /*
165: * Clear display. We can't pass RI_CLEAR in ri_flg and have rasops
166: * do it for us until we know how to setup the colormap first.
167: */
168: memset((char *)dc->dc_vaddr + dc->dc_offset, bgcolor,
169: dc->dc_rowbytes * dc->dc_ht);
170:
171: strlcpy(dc->dc_wsd.name, "std", sizeof(dc->dc_wsd.name));
172: dc->dc_wsd.ncols = ri->ri_cols;
173: dc->dc_wsd.nrows = ri->ri_rows;
174: dc->dc_wsd.textops = &ri->ri_ops;
175: dc->dc_wsd.fontwidth = ri->ri_font->fontwidth;
176: dc->dc_wsd.fontheight = ri->ri_font->fontheight;
177: dc->dc_wsd.capabilities = ri->ri_caps;
178:
179: return (0);
180: }
181:
182: int
183: macfb_color_setup(struct macfb_devconfig *dc)
184: {
185: extern int rasops_alloc_cattr(void *, int, int, int, long *);
186: struct rasops_info *ri = &dc->dc_ri;
187:
188: /* nothing to do for non-indexed modes... */
189: if (ri->ri_depth > 8)
190: return (0); /* fill in black */
191:
192: if (dc->dc_setcolor == NULL || ISSET(dc->dc_flags, FB_MACOS_PALETTE) ||
193: ri->ri_depth < 2) {
194: /*
195: * Until we know how to setup the colormap, or if we are
196: * already initialized (i.e. glass console), constrain ourselves
197: * to mono mode. Note that we need to use our own alloc_attr
198: * routine to compensate for inverted black and white colors.
199: */
200: ri->ri_ops.alloc_attr = macfb_alloc_mattr;
201: ri->ri_caps &= ~(WSSCREEN_WSCOLORS | WSSCREEN_HILIT);
202: if (ri->ri_depth == 8)
203: ri->ri_devcmap[15] = 0xffffffff;
204:
205: macfb_palette_setup(dc);
206:
207: return (0xff); /* fill in black inherited from MacOS */
208: }
209:
210: /* start from the rasops colormap */
211: bcopy(rasops_cmap, dc->dc_cmap, 256 * 3);
212:
213: switch (ri->ri_depth) {
214: case 2:
215: /*
216: * 2bpp mode does not really have colors, only two gray
217: * shades in addition to black and white, to allow
218: * hilighting.
219: *
220: * Our palette needs to be:
221: * 00 black
222: * 01 dark gray (highlighted black, sort of)
223: * 02 light gray (normal white)
224: * 03 white (highlighted white)
225: */
226: bcopy(dc->dc_cmap + (255 - WSCOL_WHITE) * 3,
227: dc->dc_cmap + 1 * 3, 3);
228: bcopy(dc->dc_cmap + WSCOL_WHITE * 3, dc->dc_cmap + 2 * 3, 3);
229: bcopy(dc->dc_cmap + (8 + WSCOL_WHITE) * 3,
230: dc->dc_cmap + 3 * 3, 3);
231: ri->ri_caps |= WSSCREEN_HILIT;
232: ri->ri_ops.alloc_attr = macfb_alloc_hattr;
233: break;
234: case 4:
235: /*
236: * Tweak colormap
237: *
238: * Due to the way rasops cursor work, we need to provide
239: * inverted copies of the 8 basic colors as the other 8
240: * in 4bpp mode.
241: */
242: bcopy(dc->dc_cmap + (256 - 8) * 3, dc->dc_cmap + 8 * 3, 8 * 3);
243: ri->ri_caps |= WSSCREEN_WSCOLORS;
244: ri->ri_ops.alloc_attr = macfb_alloc_cattr;
245: break;
246: default:
247: case 8:
248: break;
249: }
250:
251: (*dc->dc_setcolor)(dc, 0, 1 << ri->ri_depth);
252:
253: return (WSCOL_BLACK); /* fill in our own black */
254: }
255:
256: /*
257: * Initialize a black and white, MacOS compatible, shadow colormap.
258: * This is necessary if we still want to be able to run X11 with colors.
259: */
260: void
261: macfb_palette_setup(struct macfb_devconfig *dc)
262: {
263: memset(dc->dc_cmap, 0xff, 3); /* white */
264: bzero(dc->dc_cmap + 3, 255 * 3); /* black */
265: }
266:
267: /*
268: * Attribute allocator for monochrome displays (either 1bpp or no colormap
269: * control). Note that the colors we return are indexes into ri_devcmap which
270: * will select the actual bits.
271: */
272: int
273: macfb_alloc_mattr(void *cookie, int fg, int bg, int flg, long *attr)
274: {
275: if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
276: return (EINVAL);
277:
278: /*
279: * Default values are white on black. However, on indexed displays,
280: * 0 is white and all bits set is black.
281: */
282: if ((flg & WSATTR_REVERSE) != 0) {
283: fg = 15;
284: bg = 0;
285: } else {
286: fg = 0;
287: bg = 15;
288: }
289:
290: *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
291: return (0);
292: }
293:
294: /*
295: * Attribute allocator for 2bpp displays.
296: * Note that the colors we return are indexes into ri_devcmap which will
297: * select the actual bits.
298: */
299: int
300: macfb_alloc_hattr(void *cookie, int fg, int bg, int flg, long *attr)
301: {
302: if ((flg & (WSATTR_BLINK | WSATTR_WSCOLORS)) != 0)
303: return (EINVAL);
304:
305: if ((flg & WSATTR_REVERSE) != 0) {
306: fg = WSCOL_BLACK;
307: bg = WSCOL_WHITE;
308: } else {
309: fg = WSCOL_WHITE;
310: bg = WSCOL_BLACK;
311: }
312:
313: if ((flg & WSATTR_HILIT) != 0)
314: fg += 8;
315:
316: *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
317: return (0);
318: }
319:
320: /*
321: * Attribute allocator for 4bpp displays.
322: */
323: int
324: macfb_alloc_cattr(void *cookie, int fg, int bg, int flg, long *attr)
325: {
326: if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
327: return (EINVAL);
328:
329: return (rasops_alloc_cattr(cookie, fg, bg, flg, attr));
330: }
331:
332: void
333: macfb_attach_common(struct macfb_softc *sc, struct macfb_devconfig *dc)
334: {
335: struct wsemuldisplaydev_attach_args waa;
336: int isconsole;
337:
338: /* Print hardware characteristics. */
339: printf("%s: %dx%d, ", sc->sc_dev.dv_xname, dc->dc_wid, dc->dc_ht);
340: if (dc->dc_depth == 1)
341: printf("monochrome");
342: else
343: printf("%dbit color", dc->dc_depth);
344: printf(" display\n");
345:
346: isconsole = macfb_is_console(sc->sc_basepa + dc->dc_offset);
347:
348: if (isconsole) {
349: macfb_console_dc.dc_setcolor = dc->dc_setcolor;
350: macfb_console_dc.dc_cmapregs = dc->dc_cmapregs;
351: free(dc, M_DEVBUF);
352: dc = sc->sc_dc = &macfb_console_dc;
353: dc->dc_nscreens = 1;
354: macfb_color_setup(dc);
355: /* XXX at this point we should reset the emulation to have
356: * it pick better attributes for kernel messages. Oh well. */
357: } else {
358: sc->sc_dc = dc;
359: if (macfb_init(dc) != 0)
360: return;
361: }
362:
363: dc->dc_scrlist[0] = &dc->dc_wsd;
364: dc->dc_screenlist.nscreens = 1;
365: dc->dc_screenlist.screens =
366: (const struct wsscreen_descr **)dc->dc_scrlist;
367:
368: waa.console = isconsole;
369: waa.scrdata = &dc->dc_screenlist;
370: waa.accessops = &macfb_accessops;
371: waa.accesscookie = sc;
372: waa.defaultscreens = 0;
373:
374: config_found((struct device *)sc, &waa, wsemuldisplaydevprint);
375: }
376:
377: int
378: macfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
379: {
380: struct macfb_softc *sc = v;
381: struct macfb_devconfig *dc = sc->sc_dc;
382: struct wsdisplay_fbinfo *wdf;
383:
384: switch (cmd) {
385: case WSDISPLAYIO_GTYPE:
386: *(int *)data = WSDISPLAY_TYPE_MAC68K;
387: break;
388: case WSDISPLAYIO_GINFO:
389: wdf = (struct wsdisplay_fbinfo *)data;
390: wdf->height = dc->dc_ri.ri_height;
391: wdf->width = dc->dc_ri.ri_width;
392: wdf->depth = dc->dc_ri.ri_depth;
393: if (dc->dc_ri.ri_depth > 8 || dc->dc_setcolor == NULL)
394: wdf->cmsize = 0;
395: else
396: wdf->cmsize = 1 << dc->dc_ri.ri_depth;
397: break;
398: case WSDISPLAYIO_LINEBYTES:
399: *(u_int *)data = dc->dc_ri.ri_stride;
400: break;
401: case WSDISPLAYIO_GETCMAP:
402: if (dc->dc_ri.ri_depth > 8 || dc->dc_setcolor == NULL)
403: return (0);
404: return (macfb_getcmap(dc, (struct wsdisplay_cmap *)data));
405: case WSDISPLAYIO_PUTCMAP:
406: if (dc->dc_ri.ri_depth > 8 || dc->dc_setcolor == NULL)
407: return (0);
408: return (macfb_putcmap(dc, (struct wsdisplay_cmap *)data));
409: case WSDISPLAYIO_SMODE:
410: if (dc->dc_ri.ri_depth > 8 || dc->dc_setcolor == NULL)
411: return (0);
412: if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL &&
413: ISSET(dc->dc_flags, FB_MACOS_PALETTE)) {
414: macfb_palette_setup(dc);
415: (*dc->dc_setcolor)(dc, 0, 1 << dc->dc_ri.ri_depth);
416: /* clear display */
417: memset((char *)dc->dc_vaddr + dc->dc_offset, 0xff,
418: dc->dc_rowbytes * dc->dc_ht);
419: }
420: break;
421: case WSDISPLAYIO_GVIDEO:
422: case WSDISPLAYIO_SVIDEO:
423: break;
424: default:
425: return (-1);
426: }
427:
428: return (0);
429: }
430:
431: paddr_t
432: macfb_mmap(void *v, off_t offset, int prot)
433: {
434: struct macfb_softc *sc = v;
435: struct macfb_devconfig *dc = sc->sc_dc;
436: paddr_t addr;
437:
438: if (offset >= 0 &&
439: offset < round_page(dc->dc_size))
440: addr = atop(dc->dc_paddr + dc->dc_offset + offset);
441: else
442: addr = (-1);
443:
444: return addr;
445: }
446:
447: int
448: macfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
449: int *curxp, int *curyp, long *defattrp)
450: {
451: struct macfb_softc *sc = v;
452: struct rasops_info *ri = &sc->sc_dc->dc_ri;
453:
454: if (sc->sc_dc->dc_nscreens > 0)
455: return (ENOMEM);
456:
457: *cookiep = ri;
458: *curxp = *curyp = 0;
459: ri->ri_ops.alloc_attr(ri, 0, 0, 0, defattrp);
460: sc->sc_dc->dc_nscreens++;
461:
462: return (0);
463: }
464:
465: void
466: macfb_free_screen(void *v, void *cookie)
467: {
468: struct macfb_softc *sc = v;
469:
470: sc->sc_dc->dc_nscreens--;
471: }
472:
473: int
474: macfb_show_screen(void *v, void *cookie, int waitok,
475: void (*cb)(void *, int, int), void *cbarg)
476: {
477: return (0);
478: }
479:
480: int
481: macfb_getcmap(struct macfb_devconfig *dc, struct wsdisplay_cmap *cm)
482: {
483: u_int index = cm->index, count = cm->count;
484: u_int colcount = 1 << dc->dc_ri.ri_depth;
485: int i, error;
486: u_int8_t ramp[256], *c, *r;
487:
488: if (index >= colcount || count > colcount - index)
489: return (EINVAL);
490:
491: /* extract reds */
492: c = dc->dc_cmap + 0 + index * 3;
493: for (i = count, r = ramp; i != 0; i--)
494: *r++ = *c, c += 3;
495: if ((error = copyout(ramp, cm->red, count)) != 0)
496: return (error);
497:
498: /* extract greens */
499: c = dc->dc_cmap + 1 + index * 3;
500: for (i = count, r = ramp; i != 0; i--)
501: *r++ = *c, c += 3;
502: if ((error = copyout(ramp, cm->green, count)) != 0)
503: return (error);
504:
505: /* extract blues */
506: c = dc->dc_cmap + 2 + index * 3;
507: for (i = count, r = ramp; i != 0; i--)
508: *r++ = *c, c += 3;
509: if ((error = copyout(ramp, cm->blue, count)) != 0)
510: return (error);
511:
512: return (0);
513: }
514:
515: int
516: macfb_putcmap(struct macfb_devconfig *dc, struct wsdisplay_cmap *cm)
517: {
518: u_int index = cm->index, count = cm->count;
519: u_int colcount = 1 << dc->dc_ri.ri_depth;
520: int i, error;
521: u_int8_t r[256], g[256], b[256], *nr, *ng, *nb, *c;
522:
523: if (index >= colcount || count > colcount - index)
524: return (EINVAL);
525:
526: if ((error = copyin(cm->red, r, count)) != 0)
527: return (error);
528: if ((error = copyin(cm->green, g, count)) != 0)
529: return (error);
530: if ((error = copyin(cm->blue, b, count)) != 0)
531: return (error);
532:
533: nr = r, ng = g, nb = b;
534: c = dc->dc_cmap + index * 3;
535: for (i = count; i != 0; i--) {
536: *c++ = *nr++;
537: *c++ = *ng++;
538: *c++ = *nb++;
539: }
540:
541: (*dc->dc_setcolor)(dc, index, index + count);
542:
543: return (0);
544: }
545:
546: int
547: macfb_cnattach()
548: {
549: struct macfb_devconfig *dc = &macfb_console_dc;
550: long defattr;
551: struct rasops_info *ri;
552:
553: dc->dc_vaddr = trunc_page(videoaddr);
554: dc->dc_paddr = trunc_page(mac68k_vidphys);
555: dc->dc_offset = m68k_page_offset(mac68k_vidphys);
556: dc->dc_wid = videosize & 0xffff;
557: dc->dc_ht = (videosize >> 16) & 0xffff;
558: dc->dc_depth = videobitdepth;
559: dc->dc_rowbytes = videorowbytes;
560: dc->dc_size = (mac68k_vidlen > 0) ?
561: mac68k_vidlen : dc->dc_ht * dc->dc_rowbytes;
562:
563: /* set up the display */
564: dc->dc_flags |= FB_MACOS_PALETTE;
565: if (macfb_init(dc) != 0)
566: return (-1);
567:
568: ri = &dc->dc_ri;
569: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
570: wsdisplay_cnattach(&dc->dc_wsd, ri, 0, 0, defattr);
571:
572: macfb_consaddr = mac68k_vidphys;
573: return (0);
574: }
CVSweb