Annotation of sys/arch/luna88k/dev/lunafb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: lunafb.c,v 1.8 2006/11/29 12:13:54 miod Exp $ */
2: /* $NetBSD: lunafb.c,v 1.7.6.1 2002/08/07 01:48:34 lukem Exp $ */
3:
4: /*-
5: * Copyright (c) 2000 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Tohru Nishimura.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/conf.h>
43: #include <sys/device.h>
44: #include <sys/ioctl.h>
45: #include <sys/malloc.h>
46: #include <sys/mman.h>
47: #include <sys/proc.h>
48: #include <sys/tty.h>
49: #include <sys/errno.h>
50: #include <sys/buf.h>
51:
52: #include <uvm/uvm_extern.h>
53:
54: #include <dev/wscons/wsconsio.h>
55: #include <dev/wscons/wsdisplayvar.h>
56: #include <dev/rasops/rasops.h>
57:
58: #include <machine/cpu.h>
59: #include <machine/autoconf.h>
60:
61: struct bt454 {
62: u_int8_t bt_addr; /* map address register */
63: u_int8_t bt_cmap; /* colormap data register */
64: };
65:
66: struct bt458 {
67: u_int8_t bt_addr; /* map address register */
68: unsigned :24;
69: u_int8_t bt_cmap; /* colormap data register */
70: unsigned :24;
71: u_int8_t bt_ctrl; /* control register */
72: unsigned :24;
73: u_int8_t bt_omap; /* overlay (cursor) map register */
74: unsigned :24;
75: };
76:
77: #define OMFB_RFCNT 0xB1000000 /* video h-origin/v-origin */
78: #define OMFB_PLANEMASK 0xB1040000 /* planemask register */
79: #define OMFB_FB_WADDR 0xB1080008 /* common plane */
80: #define OMFB_FB_RADDR 0xB10C0008 /* plane #0 */
81: #define OMFB_ROPFUNC 0xB12C0000 /* ROP function code */
82: #define OMFB_RAMDAC 0xC1100000 /* Bt454/Bt458 RAMDAC */
83: #define OMFB_SIZE (0xB1300000 - 0xB1080000 + NBPG)
84:
85: struct om_hwdevconfig {
86: int dc_wid; /* width of frame buffer */
87: int dc_ht; /* height of frame buffer */
88: int dc_depth; /* depth, bits per pixel */
89: int dc_rowbytes; /* bytes in a FB scan line */
90: int dc_cmsize; /* colormap size */
91: vaddr_t dc_videobase; /* base of flat frame buffer */
92: struct rasops_info dc_ri; /* raster blitter variables */
93: };
94:
95: struct hwcmap {
96: #define CMAP_SIZE 256
97: u_int8_t r[CMAP_SIZE];
98: u_int8_t g[CMAP_SIZE];
99: u_int8_t b[CMAP_SIZE];
100: };
101:
102: struct omfb_softc {
103: struct device sc_dev; /* base device */
104: struct om_hwdevconfig *sc_dc; /* device configuration */
105: struct hwcmap sc_cmap; /* software copy of colormap */
106: int nscreens;
107: };
108:
109: int omgetcmap(struct omfb_softc *, struct wsdisplay_cmap *);
110: int omsetcmap(struct omfb_softc *, struct wsdisplay_cmap *);
111:
112: struct om_hwdevconfig omfb_console_dc;
113: void omfb_getdevconfig(paddr_t, struct om_hwdevconfig *);
114:
115: /* in omrasops.c */
116: void om_cursor(void *, int, int, int);
117: void om_putchar(void *, int, int, u_int, long);
118: void om_copycols(void *, int, int, int, int);
119: void om_copyrows(void *, int, int, int num);
120: void om_erasecols(void *, int, int, int, long);
121: void om_eraserows(void *, int, int, long);
122:
123: struct wsscreen_descr omfb_stdscreen = {
124: "std"
125: };
126:
127: const struct wsscreen_descr *_omfb_scrlist[] = {
128: &omfb_stdscreen,
129: };
130:
131: const struct wsscreen_list omfb_screenlist = {
132: sizeof(_omfb_scrlist) / sizeof(struct wsscreen_descr *), _omfb_scrlist
133: };
134:
135: int omfbioctl(void *, u_long, caddr_t, int, struct proc *);
136: paddr_t omfbmmap(void *, off_t, int);
137: int omfb_alloc_screen(void *, const struct wsscreen_descr *,
138: void **, int *, int *, long *);
139: void omfb_free_screen(void *, void *);
140: int omfb_show_screen(void *, void *, int,
141: void (*) (void *, int, int), void *);
142:
143: const struct wsdisplay_accessops omfb_accessops = {
144: omfbioctl,
145: omfbmmap,
146: omfb_alloc_screen,
147: omfb_free_screen,
148: omfb_show_screen,
149: NULL, /* load_font */
150: NULL, /* scrollback */
151: NULL, /* getchar */
152: NULL /* burner */
153: };
154:
155: int omfbmatch(struct device *, void *, void *);
156: void omfbattach(struct device *, struct device *, void *);
157:
158: const struct cfattach fb_ca = {
159: sizeof(struct omfb_softc), omfbmatch, omfbattach
160: };
161:
162: struct cfdriver fb_cd = {
163: NULL, "fb", DV_DULL
164: };
165:
166: extern int hwplanebits; /* hardware plane bits; retrieved at boot */
167:
168: int omfb_console;
169: int omfb_cnattach(void);
170:
171: int
172: omfbmatch(parent, cf, aux)
173: struct device *parent;
174: void *cf, *aux;
175: {
176: struct mainbus_attach_args *ma = aux;
177:
178: if (strcmp(ma->ma_name, fb_cd.cd_name))
179: return (0);
180: #if 0 /* XXX badaddr() bombs if no framebuffer is installed */
181: if (badaddr((caddr_t)ma->ma_addr, 4))
182: return (0);
183: #else
184: if (hwplanebits == 0)
185: return (0);
186: #endif
187: return (1);
188: }
189:
190: void
191: omfbattach(parent, self, args)
192: struct device *parent, *self;
193: void *args;
194: {
195: struct omfb_softc *sc = (struct omfb_softc *)self;
196: struct wsemuldisplaydev_attach_args waa;
197:
198: if (omfb_console) {
199: sc->sc_dc = &omfb_console_dc;
200: sc->nscreens = 1;
201: }
202: else {
203: sc->sc_dc = (struct om_hwdevconfig *)
204: malloc(sizeof(struct om_hwdevconfig), M_DEVBUF, M_WAITOK);
205: omfb_getdevconfig(OMFB_FB_WADDR, sc->sc_dc);
206: }
207: printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
208: sc->sc_dc->dc_depth);
209:
210: #if 0 /* WHITE on BLACK */
211: cm = &sc->sc_cmap;
212: memset(cm, 255, sizeof(struct hwcmap));
213: cm->r[0] = cm->g[0] = cm->b[0] = 0;
214: #endif
215: waa.console = omfb_console;
216: waa.scrdata = &omfb_screenlist;
217: waa.accessops = &omfb_accessops;
218: waa.accesscookie = sc;
219: waa.defaultscreens = 0;
220:
221: config_found(self, &waa, wsemuldisplaydevprint);
222: }
223:
224: /* EXPORT */ int
225: omfb_cnattach()
226: {
227: struct om_hwdevconfig *dc = &omfb_console_dc;
228: struct rasops_info *ri = &dc->dc_ri;
229: long defattr;
230:
231: omfb_getdevconfig(OMFB_FB_WADDR, dc);
232: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
233: wsdisplay_cnattach(&omfb_stdscreen, ri, 0, 0, defattr);
234: omfb_console = 1;
235: return (0);
236: }
237:
238: int
239: omfbioctl(v, cmd, data, flag, p)
240: void *v;
241: u_long cmd;
242: caddr_t data;
243: int flag;
244: struct proc *p;
245: {
246: struct omfb_softc *sc = v;
247: struct om_hwdevconfig *dc = sc->sc_dc;
248:
249: switch (cmd) {
250: case WSDISPLAYIO_GTYPE:
251: *(u_int *)data = WSDISPLAY_TYPE_LUNA;
252: break;
253:
254: case WSDISPLAYIO_GINFO:
255: #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
256: wsd_fbip->height = dc->dc_ht;
257: wsd_fbip->width = dc->dc_wid;
258: wsd_fbip->depth = dc->dc_depth;
259: wsd_fbip->cmsize = dc->dc_cmsize;
260: #undef fbt
261: break;
262:
263: case WSDISPLAYIO_GETCMAP:
264: return omgetcmap(sc, (struct wsdisplay_cmap *)data);
265:
266: case WSDISPLAYIO_PUTCMAP:
267: return omsetcmap(sc, (struct wsdisplay_cmap *)data);
268:
269: case WSDISPLAYIO_SVIDEO:
270: case WSDISPLAYIO_GVIDEO:
271: break;
272:
273: case WSDISPLAYIO_GCURPOS:
274: case WSDISPLAYIO_SCURPOS:
275: case WSDISPLAYIO_GCURMAX:
276: case WSDISPLAYIO_GCURSOR:
277: case WSDISPLAYIO_SCURSOR:
278: default:
279: return (-1);
280: }
281:
282: return (0);
283: }
284:
285: /*
286: * Return the address that would map the given device at the given
287: * offset, allowing for the given protection, or return -1 for error.
288: */
289:
290: paddr_t
291: omfbmmap(v, offset, prot)
292: void *v;
293: off_t offset;
294: int prot;
295: {
296: struct omfb_softc *sc = v;
297:
298: if (offset & PGOFSET)
299: return (-1);
300: if (offset >= OMFB_SIZE || offset < 0)
301: return (-1);
302:
303: return atop(trunc_page(sc->sc_dc->dc_videobase) + offset);
304: }
305:
306: int
307: omgetcmap(sc, p)
308: struct omfb_softc *sc;
309: struct wsdisplay_cmap *p;
310: {
311: u_int index = p->index, count = p->count;
312: unsigned int cmsize;
313: int error;
314:
315: cmsize = sc->sc_dc->dc_cmsize;
316: if (index >= cmsize || count > cmsize - index)
317: return (EINVAL);
318:
319: error = copyout(&sc->sc_cmap.r[index], p->red, count);
320: if (error != 0)
321: return (error);
322: error = copyout(&sc->sc_cmap.g[index], p->green, count);
323: if (error != 0)
324: return (error);
325: error = copyout(&sc->sc_cmap.b[index], p->blue, count);
326: if (error != 0)
327: return (error);
328:
329: return (0);
330: }
331:
332: int
333: omsetcmap(sc, p)
334: struct omfb_softc *sc;
335: struct wsdisplay_cmap *p;
336: {
337: u_int index = p->index, count = p->count;
338: unsigned int cmsize, i;
339: int error;
340:
341: cmsize = sc->sc_dc->dc_cmsize;
342: if (index >= cmsize || count > cmsize - index)
343: return (EINVAL);
344:
345: error = copyin(p->red, &sc->sc_cmap.r[index], count);
346: if (error != 0)
347: return (error);
348: error = copyin(p->green, &sc->sc_cmap.g[index], count);
349: if (error != 0)
350: return (error);
351: error = copyin(p->blue, &sc->sc_cmap.b[index], count);
352: if (error != 0)
353: return (error);
354:
355: if (hwplanebits == 4) {
356: struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
357: odac->bt_addr = index;
358: for (i = index; i < count; i++) {
359: odac->bt_cmap = sc->sc_cmap.r[i];
360: odac->bt_cmap = sc->sc_cmap.g[i];
361: odac->bt_cmap = sc->sc_cmap.b[i];
362: }
363: }
364: else if (hwplanebits == 8) {
365: struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
366: ndac->bt_addr = index;
367: for (i = index; i < count; i++) {
368: ndac->bt_cmap = sc->sc_cmap.r[i];
369: ndac->bt_cmap = sc->sc_cmap.g[i];
370: ndac->bt_cmap = sc->sc_cmap.b[i];
371: }
372: }
373: return (0);
374: }
375:
376: void
377: omfb_getdevconfig(paddr, dc)
378: paddr_t paddr;
379: struct om_hwdevconfig *dc;
380: {
381: int bpp, i;
382: struct rasops_info *ri;
383: union {
384: struct { short h, v; } p;
385: u_int32_t u;
386: } rfcnt;
387:
388: switch (hwplanebits) {
389: case 8:
390: bpp = 8; /* XXX check monochrome bit in DIPSW */
391: break;
392: default:
393: case 4:
394: bpp = 4; /* XXX check monochrome bit in DIPSW */
395: break;
396: case 1:
397: bpp = 1;
398: break;
399: }
400: dc->dc_wid = 1280;
401: dc->dc_ht = 1024;
402: dc->dc_depth = bpp;
403: dc->dc_rowbytes = 2048 / 8;
404: dc->dc_cmsize = (bpp == 1) ? 0 : 1 << bpp;
405: dc->dc_videobase = paddr;
406:
407: #if 0 /* WHITE on BLACK XXX experiment resulted in WHITE on SKYBLUE... */
408: if (hwplanebits == 4) {
409: /* XXX Need Bt454 initialization */
410: struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
411: odac->bt_addr = 0;
412: odac->bt_cmap = 0;
413: odac->bt_cmap = 0;
414: odac->bt_cmap = 0;
415: for (i = 1; i < 16; i++) {
416: odac->bt_cmap = 255;
417: odac->bt_cmap = 255;
418: odac->bt_cmap = 255;
419: }
420: }
421: else if (hwplanebits == 8) {
422: struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
423:
424: ndac->bt_addr = 0x04;
425: ndac->bt_ctrl = 0xff; /* all planes will be read */
426: ndac->bt_ctrl = 0x00; /* all planes have non-blink */
427: ndac->bt_ctrl = 0x43; /* pallete enabled, ovly plane */
428: ndac->bt_ctrl = 0x00; /* no test mode */
429: ndac->bt_addr = 0;
430: ndac->bt_cmap = 0;
431: ndac->bt_cmap = 0;
432: ndac->bt_cmap = 0;
433: for (i = 1; i < 256; i++) {
434: ndac->bt_cmap = 255;
435: ndac->bt_cmap = 255;
436: ndac->bt_cmap = 255;
437: }
438: }
439: #endif
440:
441: /* adjust h/v origin on screen */
442: rfcnt.p.h = 7;
443: rfcnt.p.v = -27;
444: *(u_int32_t *)OMFB_RFCNT = rfcnt.u; /* single write of 0x007ffe6 */
445:
446: /* clear the screen */
447: *(u_int32_t *)OMFB_PLANEMASK = 0xff;
448: ((u_int32_t *)OMFB_ROPFUNC)[5] = ~0; /* ROP copy */
449: for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++)
450: *((u_int32_t *)dc->dc_videobase + i) = 0;
451: *(u_int32_t *)OMFB_PLANEMASK = 0x01;
452:
453: /* initialize the raster */
454: ri = &dc->dc_ri;
455: ri->ri_width = dc->dc_wid;
456: ri->ri_height = dc->dc_ht;
457: ri->ri_depth = 1; /* since planes are independently addressed */
458: ri->ri_stride = dc->dc_rowbytes;
459: ri->ri_bits = (void *)dc->dc_videobase;
460: ri->ri_flg = RI_CENTER;
461: ri->ri_hw = dc;
462:
463: rasops_init(ri, 35, 80);
464:
465: omfb_stdscreen.ncols = ri->ri_cols;
466: omfb_stdscreen.nrows = ri->ri_rows;
467: ri->ri_ops.cursor = om_cursor;
468: ri->ri_ops.putchar = om_putchar;
469: ri->ri_ops.copycols = om_copycols;
470: ri->ri_ops.erasecols = om_erasecols;
471: ri->ri_ops.copyrows = om_copyrows;
472: ri->ri_ops.eraserows = om_eraserows;
473: omfb_stdscreen.textops = &ri->ri_ops;
474: omfb_stdscreen.fontwidth = ri->ri_font->fontwidth;
475: omfb_stdscreen.fontheight = ri->ri_font->fontheight;
476: omfb_stdscreen.capabilities = ri->ri_caps & ~WSSCREEN_UNDERLINE;
477: }
478:
479: int
480: omfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
481: void *v;
482: const struct wsscreen_descr *type;
483: void **cookiep;
484: int *curxp, *curyp;
485: long *attrp;
486: {
487: struct omfb_softc *sc = v;
488: struct rasops_info *ri = &sc->sc_dc->dc_ri;
489:
490: if (sc->nscreens > 0)
491: return (ENOMEM);
492:
493: *cookiep = ri;
494: *curxp = 0;
495: *curyp = 0;
496: ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
497: sc->nscreens++;
498: return (0);
499: }
500:
501: void
502: omfb_free_screen(v, cookie)
503: void *v;
504: void *cookie;
505: {
506: struct omfb_softc *sc = v;
507:
508: sc->nscreens--;
509: }
510:
511: int
512: omfb_show_screen(v, cookie, waitok, cb, cbarg)
513: void *v;
514: void *cookie;
515: int waitok;
516: void (*cb)(void *, int, int);
517: void *cbarg;
518: {
519: return 0;
520: }
CVSweb