Annotation of sys/arch/hp300/dev/diofb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: diofb.c,v 1.16 2006/11/29 19:08:19 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2005, Miodrag Vallat
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25: * POSSIBILITY OF SUCH DAMAGE.
26: */
27: /*
28: * Copyright (c) 1988 University of Utah.
29: * Copyright (c) 1990, 1993
30: * The Regents of the University of California. All rights reserved.
31: *
32: * This code is derived from software contributed to Berkeley by
33: * the Systems Programming Group of the University of Utah Computer
34: * Science Department.
35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. Neither the name of the University nor the names of its contributors
45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
47: *
48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: */
60:
61: #include <sys/param.h>
62: #include <sys/conf.h>
63: #include <sys/proc.h>
64: #include <sys/ioctl.h>
65: #include <sys/tty.h>
66: #include <sys/systm.h>
67: #include <sys/device.h>
68:
69: #include <machine/autoconf.h>
70: #include <machine/cpu.h>
71:
72: #include <hp300/dev/dioreg.h>
73: #include <hp300/dev/diovar.h>
74:
75: #include <dev/wscons/wsconsio.h>
76: #include <dev/wscons/wsdisplayvar.h>
77: #include <dev/rasops/rasops.h>
78:
79: #include <hp300/dev/diofbreg.h>
80: #include <hp300/dev/diofbvar.h>
81:
82: extern int rasops_alloc_cattr(void *, int, int, int, long *);
83:
84: int diofb_alloc_attr(void *, int, int, int, long *);
85: void diofb_copycols(void *, int, int, int, int);
86: void diofb_erasecols(void *, int, int, int, long);
87: void diofb_copyrows(void *, int, int, int);
88: void diofb_eraserows(void *, int, int, long);
89: void diofb_do_cursor(struct rasops_info *);
90:
91: /*
92: * Frame buffer geometry initialization
93: */
94:
95: int
96: diofb_fbinquire(struct diofb *fb, int scode, struct diofbreg *fbr)
97: {
98: int fboff, regsize;
99:
100: if (ISIIOVA(fbr))
101: fb->regaddr = (caddr_t)IIOP(fbr);
102: else
103: fb->regaddr = dio_scodetopa(scode);
104:
105: if (fb->fbwidth == 0 || fb->fbheight == 0) {
106: fb->fbwidth = (fbr->fbwmsb << 8) | fbr->fbwlsb;
107: fb->fbheight = (fbr->fbhmsb << 8) | fbr->fbhlsb;
108: }
109: fb->fbsize = fb->fbwidth * fb->fbheight;
110:
111: fb->regkva = (caddr_t)fbr;
112: fboff = (fbr->fbomsb << 8) | fbr->fbolsb;
113: fb->fbaddr = (caddr_t) (*((u_char *)fbr + fboff) << 16);
114:
115: if (fb->regaddr >= (caddr_t)DIOII_BASE) {
116: /*
117: * For DIO-II space the fbaddr just computed is
118: * the offset from the select code base (regaddr)
119: * of the framebuffer. Hence it is also implicitly
120: * the size of the set.
121: */
122: regsize = (int)fb->fbaddr;
123: fb->fbaddr += (int)fb->regaddr;
124: fb->fbkva = (caddr_t)fbr + regsize;
125: } else {
126: /*
127: * For internal or DIO-I space we need to map the separate
128: * framebuffer.
129: */
130: fb->fbkva = iomap(fb->fbaddr, fb->fbsize);
131: if (fb->fbkva == NULL)
132: return (ENOMEM);
133: }
134: if (fb->dwidth == 0 || fb->dheight == 0) {
135: fb->dwidth = (fbr->dwmsb << 8) | fbr->dwlsb;
136: fb->dheight = (fbr->dhmsb << 8) | fbr->dhlsb;
137: }
138:
139: /*
140: * Some displays, such as the DaVinci, appear to return a display
141: * height larger than the frame buffer height.
142: */
143: if (fb->dwidth > fb->fbwidth)
144: fb->dwidth = fb->fbwidth;
145: if (fb->dheight > fb->fbheight)
146: fb->dheight = fb->fbheight;
147:
148: fb->planes = fbr->num_planes;
149: if (fb->planes > 8)
150: fb->planes = 8;
151: fb->planemask = (1 << fb->planes) - 1;
152:
153: fb->mapmode = WSDISPLAYIO_MODE_DUMBFB;
154:
155: return (0);
156: }
157:
158: /*
159: * Frame buffer rasops and colormap setup
160: */
161:
162: void
163: diofb_fbsetup(struct diofb *fb)
164: {
165: struct rasops_info *ri = &fb->ri;
166:
167: /*
168: * Pretend we are an 8bpp frame buffer, unless ri_depth is already
169: * initialized, since this is how it is supposed to be addressed.
170: * (Hyperion forces 1bpp because it is really 1bpp addressed).
171: */
172: if (ri->ri_depth == 0)
173: ri->ri_depth = 8;
174: ri->ri_stride = (fb->fbwidth * ri->ri_depth) / 8;
175:
176: ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
177: /* We don't really support colors on less than 4bpp frame buffers */
178: if (fb->planes < 4)
179: ri->ri_flg |= RI_FORCEMONO;
180: ri->ri_bits = fb->fbkva;
181: ri->ri_width = fb->dwidth;
182: ri->ri_height = fb->dheight;
183: ri->ri_hw = fb;
184:
185: /*
186: * Ask for an unholy big display, rasops will trim this to more
187: * reasonable values.
188: */
189: rasops_init(ri, 160, 160);
190:
191: diofb_resetcmap(fb);
192:
193: /*
194: * For low depth frame buffers, since we have faked a 8bpp frame buffer
195: * to rasops, we actually have to remove capabilities.
196: */
197: if (fb->planes == 4) {
198: ri->ri_ops.alloc_attr = diofb_alloc_attr;
199: ri->ri_caps &= ~WSSCREEN_HILIT;
200: }
201:
202: ri->ri_ops.copycols = diofb_copycols;
203: ri->ri_ops.erasecols = diofb_erasecols;
204: if (ri->ri_depth != 1) {
205: ri->ri_ops.copyrows = diofb_copyrows;
206: ri->ri_ops.eraserows = diofb_eraserows;
207: ri->ri_do_cursor = diofb_do_cursor;
208: }
209:
210: /* Clear entire display, including non visible areas */
211: (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, fb->fbheight, RR_CLEAR, 0xff);
212:
213: strlcpy(fb->wsd.name, "std", sizeof(fb->wsd.name));
214: fb->wsd.ncols = ri->ri_cols;
215: fb->wsd.nrows = ri->ri_rows;
216: fb->wsd.textops = &ri->ri_ops;
217: fb->wsd.fontwidth = ri->ri_font->fontwidth;
218: fb->wsd.fontheight = ri->ri_font->fontheight;
219: fb->wsd.capabilities = ri->ri_caps;
220: }
221:
222: /*
223: * Setup default emulation mode colormap
224: */
225: void
226: diofb_resetcmap(struct diofb *fb)
227: {
228: const u_char *color;
229: u_int i;
230:
231: /* start with the rasops colormap */
232: color = (const u_char *)rasops_cmap;
233: for (i = 0; i < 256; i++) {
234: fb->cmap.r[i] = *color++;
235: fb->cmap.g[i] = *color++;
236: fb->cmap.b[i] = *color++;
237: }
238:
239: /*
240: * Tweak colormap
241: *
242: * Due to the way rasops cursor work, we need to provide
243: * copies of the 8 or 16 basic colors at extra locations
244: * in 4bpp and 6bpp mode. This is because missing planes
245: * accept writes but read back as zero.
246: *
247: * So, in 6bpp mode:
248: * 00 gets inverted to ff, read back as 3f
249: * 3f gets inverted to c0, read back as 00
250: * and in 4bpp mode:
251: * 00 gets inverted to ff, read back as 0f
252: * 0f gets inverted to f0, read back as 00
253: */
254:
255: switch (fb->planes) {
256: case 6:
257: /*
258: * 00-0f normal colors
259: * 30-3f inverted colors
260: * c0-cf normal colors
261: * f0-ff inverted colors
262: */
263: bcopy(fb->cmap.r + 0x00, fb->cmap.r + 0xc0, 0x10);
264: bcopy(fb->cmap.g + 0x00, fb->cmap.g + 0xc0, 0x10);
265: bcopy(fb->cmap.b + 0x00, fb->cmap.b + 0xc0, 0x10);
266: bcopy(fb->cmap.r + 0xf0, fb->cmap.r + 0x30, 0x10);
267: bcopy(fb->cmap.g + 0xf0, fb->cmap.g + 0x30, 0x10);
268: bcopy(fb->cmap.b + 0xf0, fb->cmap.b + 0x30, 0x10);
269: break;
270: case 4:
271: /*
272: * 00-07 normal colors
273: * 08-0f inverted colors
274: * highlighted colors are not available.
275: */
276: bcopy(fb->cmap.r + 0xf8, fb->cmap.r + 0x08, 0x08);
277: bcopy(fb->cmap.g + 0xf8, fb->cmap.g + 0x08, 0x08);
278: bcopy(fb->cmap.b + 0xf8, fb->cmap.b + 0x08, 0x08);
279: break;
280: }
281: }
282:
283: /*
284: * Attachment helpers
285: */
286:
287: void
288: diofb_cnattach(struct diofb *fb)
289: {
290: long defattr;
291: struct rasops_info *ri;
292:
293: ri = &fb->ri;
294: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
295: wsdisplay_cnattach(&fb->wsd, ri, 0, 0, defattr);
296: }
297:
298: void
299: diofb_end_attach(void *sc, struct wsdisplay_accessops *accessops,
300: struct diofb *fb, int console, const char *descr)
301: {
302: struct wsemuldisplaydev_attach_args waa;
303:
304: printf(": %dx%d", fb->dwidth, fb->dheight);
305:
306: if (fb->planes == 1)
307: printf(" monochrome");
308: else
309: printf("x%d", fb->planes);
310:
311: if (descr != NULL)
312: printf(" %s", descr);
313: printf(" frame buffer\n");
314:
315: fb->scrlist[0] = &fb->wsd;
316: fb->wsl.nscreens = 1;
317: fb->wsl.screens = (const struct wsscreen_descr **)fb->scrlist;
318:
319: waa.console = console;
320: waa.scrdata = &fb->wsl;
321: waa.accessops = accessops;
322: waa.accesscookie = fb;
323: waa.defaultscreens = 0;
324:
325: config_found((struct device *)sc, &waa, wsemuldisplaydevprint);
326: }
327:
328: /*
329: * Common wsdisplay emulops for DIO frame buffers
330: */
331:
332: int
333: diofb_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
334: {
335: if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
336: return (EINVAL);
337:
338: return (rasops_alloc_cattr(cookie, fg, bg, flg, attr));
339: }
340:
341: void
342: diofb_copycols(void *cookie, int row, int src, int dst, int n)
343: {
344: struct rasops_info *ri = cookie;
345: struct diofb *fb = ri->ri_hw;
346:
347: n *= ri->ri_font->fontwidth;
348: src *= ri->ri_font->fontwidth;
349: dst *= ri->ri_font->fontwidth;
350: row *= ri->ri_font->fontheight;
351:
352: (*fb->bmv)(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
353: ri->ri_xorigin + dst, ri->ri_yorigin + row,
354: n, ri->ri_font->fontheight, RR_COPY, 0xff);
355: }
356:
357: void
358: diofb_copyrows(void *cookie, int src, int dst, int n)
359: {
360: struct rasops_info *ri = cookie;
361: struct diofb *fb = ri->ri_hw;
362:
363: n *= ri->ri_font->fontheight;
364: src *= ri->ri_font->fontheight;
365: dst *= ri->ri_font->fontheight;
366:
367: (*fb->bmv)(fb, ri->ri_xorigin, ri->ri_yorigin + src,
368: ri->ri_xorigin, ri->ri_yorigin + dst,
369: ri->ri_emuwidth, n, RR_COPY, 0xff);
370: }
371:
372: void
373: diofb_erasecols(void *cookie, int row, int col, int num, long attr)
374: {
375: struct rasops_info *ri = cookie;
376: struct diofb *fb = ri->ri_hw;
377: int fg, bg;
378: int snum, scol, srow;
379:
380: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
381:
382: snum = num * ri->ri_font->fontwidth;
383: scol = col * ri->ri_font->fontwidth + ri->ri_xorigin;
384: srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
385:
386: /*
387: * If this is too tricky for the simple raster ops engine,
388: * pass the fun to rasops.
389: */
390: if ((*fb->bmv)(fb, scol, srow, scol, srow, snum,
391: ri->ri_font->fontheight, RR_CLEAR, 0xff ^ bg) != 0)
392: rasops_erasecols(cookie, row, col, num, attr);
393: }
394:
395: void
396: diofb_eraserows(void *cookie, int row, int num, long attr)
397: {
398: struct rasops_info *ri = cookie;
399: struct diofb *fb = ri->ri_hw;
400: int fg, bg;
401: int srow, snum;
402: int rc;
403:
404: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
405: bg ^= 0xff;
406:
407: if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
408: rc = (*fb->bmv)(fb, 0, 0, 0, 0, ri->ri_width, ri->ri_height,
409: RR_CLEAR, bg);
410: } else {
411: srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
412: snum = num * ri->ri_font->fontheight;
413: rc = (*fb->bmv)(fb, ri->ri_xorigin, srow, ri->ri_xorigin,
414: srow, ri->ri_emuwidth, snum, RR_CLEAR, bg);
415: }
416: if (rc != 0)
417: rasops_eraserows(cookie, row, num, attr);
418: }
419:
420: void
421: diofb_do_cursor(struct rasops_info *ri)
422: {
423: struct diofb *fb = ri->ri_hw;
424: int x, y;
425:
426: x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
427: y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
428: (*fb->bmv)(fb, x, y, x, y, ri->ri_font->fontwidth,
429: ri->ri_font->fontheight, RR_INVERT, 0xff);
430: }
431:
432: /*
433: * Common wsdisplay accessops for DIO frame buffers
434: */
435:
436: int
437: diofb_alloc_screen(void *v, const struct wsscreen_descr *type,
438: void **cookiep, int *curxp, int *curyp, long *attrp)
439: {
440: struct diofb *fb = v;
441: struct rasops_info *ri = &fb->ri;
442:
443: if (fb->nscreens > 0)
444: return (ENOMEM);
445:
446: *cookiep = ri;
447: *curxp = *curyp = 0;
448: ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
449: fb->nscreens++;
450:
451: return (0);
452: }
453:
454: void
455: diofb_free_screen(void *v, void *cookie)
456: {
457: struct diofb *fb = v;
458:
459: fb->nscreens--;
460: }
461:
462: int
463: diofb_show_screen(void *v, void *cookie, int waitok,
464: void (*cb)(void *, int, int), void *cbarg)
465: {
466: return (0);
467: }
468:
469: paddr_t
470: diofb_mmap(void * v, off_t offset, int prot)
471: {
472: struct diofb *fb = v;
473:
474: if ((offset & PAGE_MASK) != 0)
475: return (-1);
476:
477: switch (fb->mapmode) {
478: case WSDISPLAYIO_MODE_MAPPED:
479: if (offset >= 0 && offset < DIOFB_REGSPACE)
480: return (((paddr_t)fb->regaddr + offset) >> PGSHIFT);
481: offset -= DIOFB_REGSPACE;
482: /* FALLTHROUGH */
483: case WSDISPLAYIO_MODE_DUMBFB:
484: if (offset >= 0 && offset < fb->fbsize)
485: return (((paddr_t)fb->fbaddr + offset) >> PGSHIFT);
486: break;
487: }
488:
489: return (-1);
490: }
491:
492: int
493: diofb_getcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
494: {
495: u_int index = cm->index, count = cm->count;
496: u_int colcount = 1 << fb->planes;
497: int error;
498:
499: if (index >= colcount || count > colcount - index)
500: return (EINVAL);
501:
502: if ((error = copyout(fb->cmap.r + index, cm->red, count)) != 0)
503: return (error);
504: if ((error = copyout(fb->cmap.g + index, cm->green, count)) != 0)
505: return (error);
506: if ((error = copyout(fb->cmap.b + index, cm->blue, count)) != 0)
507: return (error);
508:
509: return (0);
510: }
CVSweb