Annotation of src/sys/dev/sun/cgsix.c, Revision 1.3
1.3 ! eeh 1: /* $NetBSD: cgsix.c,v 1.2 2000/08/26 16:06:22 eeh Exp $ */
1.1 pk 2:
3: /*-
4: * Copyright (c) 1998 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Paul Kranenburg.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: /*
40: * Copyright (c) 1993
41: * The Regents of the University of California. All rights reserved.
42: *
43: * This software was developed by the Computer Systems Engineering group
44: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
45: * contributed to Berkeley.
46: *
47: * All advertising materials mentioning features or use of this software
48: * must display the following acknowledgement:
49: * This product includes software developed by the University of
50: * California, Lawrence Berkeley Laboratory.
51: *
52: * Redistribution and use in source and binary forms, with or without
53: * modification, are permitted provided that the following conditions
54: * are met:
55: * 1. Redistributions of source code must retain the above copyright
56: * notice, this list of conditions and the following disclaimer.
57: * 2. Redistributions in binary form must reproduce the above copyright
58: * notice, this list of conditions and the following disclaimer in the
59: * documentation and/or other materials provided with the distribution.
60: * 3. All advertising materials mentioning features or use of this software
61: * must display the following acknowledgement:
62: * This product includes software developed by the University of
63: * California, Berkeley and its contributors.
64: * 4. Neither the name of the University nor the names of its contributors
65: * may be used to endorse or promote products derived from this software
66: * without specific prior written permission.
67: *
68: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
69: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
70: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
71: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
72: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
73: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
74: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
75: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
76: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
77: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
78: * SUCH DAMAGE.
79: *
80: * @(#)cgsix.c 8.4 (Berkeley) 1/21/94
81: */
82:
83: /*
84: * color display (cgsix) driver.
85: *
86: * Does not handle interrupts, even though they can occur.
87: *
88: * XXX should defer colormap updates to vertical retrace interrupts
89: */
90:
91: #include <sys/param.h>
92: #include <sys/systm.h>
93: #include <sys/buf.h>
94: #include <sys/device.h>
95: #include <sys/ioctl.h>
96: #include <sys/malloc.h>
97: #include <sys/mman.h>
98: #include <sys/tty.h>
99: #include <sys/conf.h>
100:
101: #ifdef DEBUG
102: #include <sys/proc.h>
103: #include <sys/syslog.h>
104: #endif
105:
106: #include <uvm/uvm_extern.h>
107:
108: #include <machine/bus.h>
109:
110: #include <dev/sun/fbio.h>
111: #include <dev/sun/fbvar.h>
112:
113: #include <dev/sun/btreg.h>
114: #include <dev/sun/btvar.h>
115: #include <dev/sun/cgsixreg.h>
116: #include <dev/sun/cgsixvar.h>
117: #include <dev/sun/pfourreg.h>
118:
119: #ifdef RASTERCONSOLE
120: #include <dev/rasops/rasops.h>
121: #include <dev/wscons/wsconsio.h>
122: #endif
123:
124: #include <machine/conf.h>
125:
126: static void cg6_unblank(struct device *);
127:
128: /* cdevsw prototypes */
129: cdev_decl(cgsix);
130:
131: extern struct cfdriver cgsix_cd;
132:
133: /* frame buffer generic driver */
134: static struct fbdriver cg6_fbdriver = {
135: cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, cgsixpoll, cgsixmmap
136: };
137:
138: static void cg6_reset (struct cgsix_softc *);
139: static void cg6_loadcmap (struct cgsix_softc *, int, int);
140: static void cg6_loadomap (struct cgsix_softc *);
141: static void cg6_setcursor (struct cgsix_softc *);/* set position */
142: static void cg6_loadcursor (struct cgsix_softc *);/* set shape */
143:
144: #ifdef RASTERCONSOLE
145: int cgsix_use_rasterconsole = 1;
146:
147: /*
148: * cg6 accelerated console routines.
149: *
150: * Note that buried in this code in several places is the assumption
151: * that pixels are exactly one byte wide. Since this is cg6-specific
152: * code, this seems safe. This assumption resides in things like the
153: * use of ri_emuwidth without messing around with ri_pelbytes, or the
154: * assumption that ri_font->fontwidth is the right thing to multiply
155: * character-cell counts by to get byte counts.
156: */
157:
158: /*
159: * Magic values for blitter
160: */
161:
162: /* Value for the alu register for screen-to-screen copies */
163: #define CG6_ALU_COPY ( \
164: 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
165: | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
166: | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
167: | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
168: | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
169: | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
170: | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
171: | 0x0000cccc /* ALU = src */ \
172: )
173:
174: /* Value for the alu register for region fills */
175: #define CG6_ALU_FILL ( \
176: 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
177: | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
178: | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
179: | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
180: | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
181: | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
182: | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
183: | 0x0000ff00 /* ALU = fg color */ \
184: )
185:
186: /* Value for the alu register for toggling an area */
187: #define CG6_ALU_FLIP ( \
188: 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
189: | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
190: | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
191: | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
192: | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
193: | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
194: | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
195: | 0x00005555 /* ALU = ~dst */ \
196: )
197:
198: /*
199: * Wait for a blit to finish.
200: * 0x8000000 bit: function unknown; 0x20000000 bit: GX_BLT_INPROGRESS
201: */
202: #define CG6_BLIT_WAIT(fbc) do { \
203: while (((fbc)->fbc_blit & 0xa0000000) == 0xa0000000) \
204: /*EMPTY*/; \
205: } while (0)
206:
207: /*
208: * Wait for a drawing operation to finish, or at least get queued.
209: * 0x8000000 bit: function unknown; 0x20000000 bit: GX_FULL
210: */
211: #define CG6_DRAW_WAIT(fbc) do { \
212: while (((fbc)->fbc_draw & 0xa0000000) == 0xa0000000) \
213: /*EMPTY*/; \
214: } while (0)
215:
216: /*
217: * Wait for the whole engine to go idle. This may not matter in our case;
218: * I'm not sure whether blits are actually queued or not. It more likely
219: * is intended for lines and such that do get queued.
220: * 0x10000000 bit: GX_INPROGRESS
221: */
222: #define CG6_DRAIN(fbc) do { \
223: while ((fbc)->fbc_s & 0x10000000) \
224: /*EMPTY*/; \
225: } while (0)
226:
227: static void
228: cg6_ras_copyrows(void *cookie, int src, int dst, int n)
229: {
230: struct rasops_info *ri;
231: volatile struct cg6_fbc *fbc;
232:
233: ri = cookie;
234: if (dst == src)
235: return;
236: if (src < 0) {
237: n += src;
238: src = 0;
239: }
240: if (src+n > ri->ri_rows)
241: n = ri->ri_rows - src;
242: if (dst < 0) {
243: n += dst;
244: dst = 0;
245: }
246: if (dst+n > ri->ri_rows)
247: n = ri->ri_rows - dst;
248: if (n <= 0)
249: return;
250: n *= ri->ri_font->fontheight;
251: src *= ri->ri_font->fontheight;
252: dst *= ri->ri_font->fontheight;
253: fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
254: fbc->fbc_clip = 0;
255: fbc->fbc_s = 0;
256: fbc->fbc_offx = 0;
257: fbc->fbc_offy = 0;
258: fbc->fbc_clipminx = 0;
259: fbc->fbc_clipminy = 0;
260: fbc->fbc_clipmaxx = ri->ri_width - 1;
261: fbc->fbc_clipmaxy = ri->ri_height - 1;
262: fbc->fbc_alu = CG6_ALU_COPY;
263: fbc->fbc_x0 = ri->ri_xorigin;
264: fbc->fbc_y0 = ri->ri_yorigin + src;
265: fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
266: fbc->fbc_y1 = ri->ri_yorigin + src + n - 1;
267: fbc->fbc_x2 = ri->ri_xorigin;
268: fbc->fbc_y2 = ri->ri_yorigin + dst;
269: fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1;
270: fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1;
271: CG6_BLIT_WAIT(fbc);
272: CG6_DRAIN(fbc);
273: }
274:
275: static void
276: cg6_ras_copycols(void *cookie, int row, int src, int dst, int n)
277: {
278: struct rasops_info *ri;
279: volatile struct cg6_fbc *fbc;
280:
281: ri = cookie;
282: if (dst == src)
283: return;
284: if ((row < 0) || (row >= ri->ri_rows))
285: return;
286: if (src < 0) {
287: n += src;
288: src = 0;
289: }
290: if (src+n > ri->ri_cols)
291: n = ri->ri_cols - src;
292: if (dst < 0) {
293: n += dst;
294: dst = 0;
295: }
296: if (dst+n > ri->ri_cols)
297: n = ri->ri_cols - dst;
298: if (n <= 0)
299: return;
300: n *= ri->ri_font->fontwidth;
301: src *= ri->ri_font->fontwidth;
302: dst *= ri->ri_font->fontwidth;
303: row *= ri->ri_font->fontheight;
304: fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
305: fbc->fbc_clip = 0;
306: fbc->fbc_s = 0;
307: fbc->fbc_offx = 0;
308: fbc->fbc_offy = 0;
309: fbc->fbc_clipminx = 0;
310: fbc->fbc_clipminy = 0;
311: fbc->fbc_clipmaxx = ri->ri_width - 1;
312: fbc->fbc_clipmaxy = ri->ri_height - 1;
313: fbc->fbc_alu = CG6_ALU_COPY;
314: fbc->fbc_x0 = ri->ri_xorigin + src;
315: fbc->fbc_y0 = ri->ri_yorigin + row;
316: fbc->fbc_x1 = ri->ri_xorigin + src + n - 1;
317: fbc->fbc_y1 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
318: fbc->fbc_x2 = ri->ri_xorigin + dst;
319: fbc->fbc_y2 = ri->ri_yorigin + row;
320: fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1;
321: fbc->fbc_y3 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
322: CG6_BLIT_WAIT(fbc);
323: CG6_DRAIN(fbc);
324: }
325:
326: static void
327: cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr)
328: {
329: struct rasops_info *ri;
330: volatile struct cg6_fbc *fbc;
331:
332: ri = cookie;
333: if ((row < 0) || (row >= ri->ri_rows))
334: return;
335: if (col < 0) {
336: n += col;
337: col = 0;
338: }
339: if (col+n > ri->ri_cols)
340: n = ri->ri_cols - col;
341: if (n <= 0)
342: return;
343: n *= ri->ri_font->fontwidth;
344: col *= ri->ri_font->fontwidth;
345: row *= ri->ri_font->fontheight;
346: fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
347: fbc->fbc_clip = 0;
348: fbc->fbc_s = 0;
349: fbc->fbc_offx = 0;
350: fbc->fbc_offy = 0;
351: fbc->fbc_clipminx = 0;
352: fbc->fbc_clipminy = 0;
353: fbc->fbc_clipmaxx = ri->ri_width - 1;
354: fbc->fbc_clipmaxy = ri->ri_height - 1;
355: fbc->fbc_alu = CG6_ALU_FILL;
356: fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xf];
357: fbc->fbc_arecty = ri->ri_yorigin + row;
358: fbc->fbc_arectx = ri->ri_xorigin + col;
359: fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
360: fbc->fbc_arectx = ri->ri_xorigin + col + n - 1;
361: CG6_DRAW_WAIT(fbc);
362: CG6_DRAIN(fbc);
363: }
364:
365: static void
366: cg6_ras_eraserows(void *cookie, int row, int n, long int attr)
367: {
368: struct rasops_info *ri;
369: volatile struct cg6_fbc *fbc;
370:
371: ri = cookie;
372: if (row < 0) {
373: n += row;
374: row = 0;
375: }
376: if (row+n > ri->ri_rows)
377: n = ri->ri_rows - row;
378: if (n <= 0)
379: return;
380: fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
381: fbc->fbc_clip = 0;
382: fbc->fbc_s = 0;
383: fbc->fbc_offx = 0;
384: fbc->fbc_offy = 0;
385: fbc->fbc_clipminx = 0;
386: fbc->fbc_clipminy = 0;
387: fbc->fbc_clipmaxx = ri->ri_width - 1;
388: fbc->fbc_clipmaxy = ri->ri_height - 1;
389: fbc->fbc_alu = CG6_ALU_FILL;
390: fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xf];
391: if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
392: fbc->fbc_arecty = 0;
393: fbc->fbc_arectx = 0;
394: fbc->fbc_arecty = ri->ri_height - 1;
395: fbc->fbc_arectx = ri->ri_width - 1;
396: } else {
397: row *= ri->ri_font->fontheight;
398: fbc->fbc_arecty = ri->ri_yorigin + row;
399: fbc->fbc_arectx = ri->ri_xorigin;
400: fbc->fbc_arecty = ri->ri_yorigin + row + (n * ri->ri_font->fontheight) - 1;
401: fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1;
402: }
403: CG6_DRAW_WAIT(fbc);
404: CG6_DRAIN(fbc);
405: }
406:
407: /*
408: * Really want something more like fg^bg here, but that would be more
409: * or less impossible to migrate to colors. So we hope there's
410: * something not too inappropriate in the colormap...besides, it's what
411: * the non-accelerated code did. :-)
412: */
413: static void
414: cg6_ras_do_cursor(struct rasops_info *ri)
415: {
416: volatile struct cg6_fbc *fbc;
417: int row;
418: int col;
419:
420: row = ri->ri_crow * ri->ri_font->fontheight;
421: col = ri->ri_ccol * ri->ri_font->fontwidth;
422: fbc = ((struct cgsix_softc *)ri->ri_hw)->sc_fbc;
423: fbc->fbc_clip = 0;
424: fbc->fbc_s = 0;
425: fbc->fbc_offx = 0;
426: fbc->fbc_offy = 0;
427: fbc->fbc_clipminx = 0;
428: fbc->fbc_clipminy = 0;
429: fbc->fbc_clipmaxx = ri->ri_width - 1;
430: fbc->fbc_clipmaxy = ri->ri_height - 1;
431: fbc->fbc_alu = CG6_ALU_FLIP;
432: fbc->fbc_arecty = ri->ri_yorigin + row;
433: fbc->fbc_arectx = ri->ri_xorigin + col;
434: fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
435: fbc->fbc_arectx = ri->ri_xorigin + col + ri->ri_font->fontwidth - 1;
436: CG6_DRAW_WAIT(fbc);
437: CG6_DRAIN(fbc);
438: }
439: #endif /* RASTERCONSOLE */
440:
441: void
442: cg6attach(sc, name, isconsole)
443: struct cgsix_softc *sc;
444: char *name;
445: int isconsole;
446: {
447: struct fbdevice *fb = &sc->sc_fb;
448:
449: fb->fb_driver = &cg6_fbdriver;
450:
451: /* Don't have to map the pfour register on the cgsix. */
452: fb->fb_pfour = NULL;
453:
454: fb->fb_type.fb_cmsize = 256;
455: fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
456: printf(": %s, %d x %d", name,
457: fb->fb_type.fb_width, fb->fb_type.fb_height);
458:
459: sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) &
460: (FHC_REV_MASK >> FHC_REV_SHIFT);
461:
462: printf(", rev %d", sc->sc_fhcrev);
463:
464: /* reset cursor & frame buffer controls */
465: cg6_reset(sc);
466:
467: /* enable video */
468: sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
469:
470: if (isconsole) {
471: printf(" (console)");
472: #ifdef RASTERCONSOLE
473: if (cgsix_use_rasterconsole) {
474: fbrcons_init(&sc->sc_fb);
475: sc->sc_fb.fb_rinfo.ri_hw = sc;
476: sc->sc_fb.fb_rinfo.ri_ops.copyrows = cg6_ras_copyrows;
477: sc->sc_fb.fb_rinfo.ri_ops.copycols = cg6_ras_copycols;
478: sc->sc_fb.fb_rinfo.ri_ops.erasecols = cg6_ras_erasecols;
479: sc->sc_fb.fb_rinfo.ri_ops.eraserows = cg6_ras_eraserows;
480: sc->sc_fb.fb_rinfo.ri_do_cursor = cg6_ras_do_cursor;
481: }
482: #endif
483: }
484:
485: printf("\n");
486: fb_attach(&sc->sc_fb, isconsole);
487: }
488:
489:
490: int
491: cgsixopen(dev, flags, mode, p)
492: dev_t dev;
493: int flags, mode;
494: struct proc *p;
495: {
496: int unit = minor(dev);
497:
498: if (unit >= cgsix_cd.cd_ndevs || cgsix_cd.cd_devs[unit] == NULL)
499: return (ENXIO);
500: return (0);
501: }
502:
503: int
504: cgsixclose(dev, flags, mode, p)
505: dev_t dev;
506: int flags, mode;
507: struct proc *p;
508: {
509: struct cgsix_softc *sc = cgsix_cd.cd_devs[minor(dev)];
510:
511: cg6_reset(sc);
512:
513: /* (re-)initialize the default color map */
514: bt_initcmap(&sc->sc_cmap, 256);
515: cg6_loadcmap(sc, 0, 256);
516:
517: return (0);
518: }
519:
520: int
521: cgsixioctl(dev, cmd, data, flags, p)
522: dev_t dev;
523: u_long cmd;
524: caddr_t data;
525: int flags;
526: struct proc *p;
527: {
528: struct cgsix_softc *sc = cgsix_cd.cd_devs[minor(dev)];
529: u_int count;
530: int v, error;
531: union cursor_cmap tcm;
532:
533: switch (cmd) {
534:
535: case FBIOGTYPE:
536: *(struct fbtype *)data = sc->sc_fb.fb_type;
537: break;
538:
539: case FBIOGATTR:
540: #define fba ((struct fbgattr *)data)
541: fba->real_type = sc->sc_fb.fb_type.fb_type;
542: fba->owner = 0; /* XXX ??? */
543: fba->fbtype = sc->sc_fb.fb_type;
544: fba->sattr.flags = 0;
545: fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
546: fba->sattr.dev_specific[0] = -1;
547: fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
548: fba->emu_types[1] = -1;
549: #undef fba
550: break;
551:
552: case FBIOGETCMAP:
553: #define p ((struct fbcmap *)data)
554: return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
555:
556: case FBIOPUTCMAP:
557: /* copy to software map */
558: error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
559: if (error)
560: return (error);
561: /* now blast them into the chip */
562: /* XXX should use retrace interrupt */
563: cg6_loadcmap(sc, p->index, p->count);
564: #undef p
565: break;
566:
567: case FBIOGVIDEO:
568: *(int *)data = sc->sc_blanked;
569: break;
570:
571: case FBIOSVIDEO:
572: if (*(int *)data)
573: cg6_unblank(&sc->sc_dev);
574: else if (!sc->sc_blanked) {
575: sc->sc_blanked = 1;
576: sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN;
577: }
578: break;
579:
580: /* these are for both FBIOSCURSOR and FBIOGCURSOR */
581: #define p ((struct fbcursor *)data)
582: #define cc (&sc->sc_cursor)
583:
584: case FBIOGCURSOR:
585: /* do not quite want everything here... */
586: p->set = FB_CUR_SETALL; /* close enough, anyway */
587: p->enable = cc->cc_enable;
588: p->pos = cc->cc_pos;
589: p->hot = cc->cc_hot;
590: p->size = cc->cc_size;
591:
592: /* begin ugh ... can we lose some of this crap?? */
593: if (p->image != NULL) {
594: count = cc->cc_size.y * 32 / NBBY;
595: error = copyout((caddr_t)cc->cc_bits[1],
596: (caddr_t)p->image, count);
597: if (error)
598: return (error);
599: error = copyout((caddr_t)cc->cc_bits[0],
600: (caddr_t)p->mask, count);
601: if (error)
602: return (error);
603: }
604: if (p->cmap.red != NULL) {
605: error = bt_getcmap(&p->cmap,
606: (union bt_cmap *)&cc->cc_color, 2, 1);
607: if (error)
608: return (error);
609: } else {
610: p->cmap.index = 0;
611: p->cmap.count = 2;
612: }
613: /* end ugh */
614: break;
615:
616: case FBIOSCURSOR:
617: /*
618: * For setcmap and setshape, verify parameters, so that
619: * we do not get halfway through an update and then crap
620: * out with the software state screwed up.
621: */
622: v = p->set;
623: if (v & FB_CUR_SETCMAP) {
624: /*
625: * This use of a temporary copy of the cursor
626: * colormap is not terribly efficient, but these
627: * copies are small (8 bytes)...
628: */
629: tcm = cc->cc_color;
630: error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2, 1);
631: if (error)
632: return (error);
633: }
634: if (v & FB_CUR_SETSHAPE) {
635: if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32)
636: return (EINVAL);
637: count = p->size.y * 32 / NBBY;
638: if (!uvm_useracc(p->image, count, B_READ) ||
639: !uvm_useracc(p->mask, count, B_READ))
640: return (EFAULT);
641: }
642:
643: /* parameters are OK; do it */
644: if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) {
645: if (v & FB_CUR_SETCUR)
646: cc->cc_enable = p->enable;
647: if (v & FB_CUR_SETPOS)
648: cc->cc_pos = p->pos;
649: if (v & FB_CUR_SETHOT)
650: cc->cc_hot = p->hot;
651: cg6_setcursor(sc);
652: }
653: if (v & FB_CUR_SETCMAP) {
654: cc->cc_color = tcm;
655: cg6_loadomap(sc); /* XXX defer to vertical retrace */
656: }
657: if (v & FB_CUR_SETSHAPE) {
658: cc->cc_size = p->size;
659: count = p->size.y * 32 / NBBY;
660: bzero((caddr_t)cc->cc_bits, sizeof cc->cc_bits);
1.3 ! eeh 661: copyin(p->mask, (caddr_t)cc->cc_bits[0], count);
! 662: copyin(p->image, (caddr_t)cc->cc_bits[1], count);
1.1 pk 663: cg6_loadcursor(sc);
664: }
665: break;
666:
667: #undef p
668: #undef cc
669:
670: case FBIOGCURPOS:
671: *(struct fbcurpos *)data = sc->sc_cursor.cc_pos;
672: break;
673:
674: case FBIOSCURPOS:
675: sc->sc_cursor.cc_pos = *(struct fbcurpos *)data;
676: cg6_setcursor(sc);
677: break;
678:
679: case FBIOGCURMAX:
680: /* max cursor size is 32x32 */
681: ((struct fbcurpos *)data)->x = 32;
682: ((struct fbcurpos *)data)->y = 32;
683: break;
684:
685: default:
686: #ifdef DEBUG
687: log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd,
688: p->p_comm, p->p_pid);
689: #endif
690: return (ENOTTY);
691: }
692: return (0);
693: }
694:
695: int
696: cgsixpoll(dev, events, p)
697: dev_t dev;
698: int events;
699: struct proc *p;
700: {
701:
702: return (seltrue(dev, events, p));
703: }
704:
705: /*
706: * Clean up hardware state (e.g., after bootup or after X crashes).
707: */
708: static void
709: cg6_reset(sc)
710: struct cgsix_softc *sc;
711: {
712: volatile struct cg6_tec_xxx *tec;
713: int fhc;
714: volatile struct bt_regs *bt;
715:
716: /* hide the cursor, just in case */
717: sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF;
718:
719: /* turn off frobs in transform engine (makes X11 work) */
720: tec = sc->sc_tec;
721: tec->tec_mv = 0;
722: tec->tec_clip = 0;
723: tec->tec_vdc = 0;
724:
725: /* take care of hardware bugs in old revisions */
726: if (sc->sc_fhcrev < 5) {
727: /*
728: * Keep current resolution; set cpu to 68020, set test
729: * window (size 1Kx1K), and for rev 1, disable dest cache.
730: */
731: fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 |
732: FHC_TEST |
733: (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT);
734: if (sc->sc_fhcrev < 2)
735: fhc |= FHC_DST_DISABLE;
736: *sc->sc_fhc = fhc;
737: }
738:
739: /* Enable cursor in Brooktree DAC. */
740: bt = sc->sc_bt;
741: bt->bt_addr = 0x06 << 24;
742: bt->bt_ctrl |= 0x03 << 24;
743: }
744:
745: static void
746: cg6_setcursor(sc)
747: struct cgsix_softc *sc;
748: {
749:
750: /* we need to subtract the hot-spot value here */
751: #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f)
752: sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ?
753: ((COORD(x) << 16) | (COORD(y) & 0xffff)) :
754: (THC_CURSOFF << 16) | THC_CURSOFF;
755: #undef COORD
756: }
757:
758: static void
759: cg6_loadcursor(sc)
760: struct cgsix_softc *sc;
761: {
762: volatile struct cg6_thc *thc;
763: u_int edgemask, m;
764: int i;
765:
766: /*
767: * Keep the top size.x bits. Here we *throw out* the top
768: * size.x bits from an all-one-bits word, introducing zeros in
769: * the top size.x bits, then invert all the bits to get what
770: * we really wanted as our mask. But this fails if size.x is
771: * 32---a sparc uses only the low 5 bits of the shift count---
772: * so we have to special case that.
773: */
774: edgemask = ~0;
775: if (sc->sc_cursor.cc_size.x < 32)
776: edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x);
777: thc = sc->sc_thc;
778: for (i = 0; i < 32; i++) {
779: m = sc->sc_cursor.cc_bits[0][i] & edgemask;
780: thc->thc_cursmask[i] = m;
781: thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i];
782: }
783: }
784:
785: /*
786: * Load a subset of the current (new) colormap into the color DAC.
787: */
788: static void
789: cg6_loadcmap(sc, start, ncolors)
790: struct cgsix_softc *sc;
791: int start, ncolors;
792: {
793: volatile struct bt_regs *bt;
794: u_int *ip, i;
795: int count;
796:
797: ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */
798: count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
799: bt = sc->sc_bt;
800: bt->bt_addr = BT_D4M4(start) << 24;
801: while (--count >= 0) {
802: i = *ip++;
803: /* hardware that makes one want to pound boards with hammers */
804: bt->bt_cmap = i;
805: bt->bt_cmap = i << 8;
806: bt->bt_cmap = i << 16;
807: bt->bt_cmap = i << 24;
808: }
809: }
810:
811: /*
812: * Load the cursor (overlay `foreground' and `background') colors.
813: */
814: static void
815: cg6_loadomap(sc)
816: struct cgsix_softc *sc;
817: {
818: volatile struct bt_regs *bt;
819: u_int i;
820:
821: bt = sc->sc_bt;
822: bt->bt_addr = 0x01 << 24; /* set background color */
823: i = sc->sc_cursor.cc_color.cm_chip[0];
824: bt->bt_omap = i; /* R */
825: bt->bt_omap = i << 8; /* G */
826: bt->bt_omap = i << 16; /* B */
827:
828: bt->bt_addr = 0x03 << 24; /* set foreground color */
829: bt->bt_omap = i << 24; /* R */
830: i = sc->sc_cursor.cc_color.cm_chip[1];
831: bt->bt_omap = i; /* G */
832: bt->bt_omap = i << 8; /* B */
833: }
834:
835: static void
836: cg6_unblank(dev)
837: struct device *dev;
838: {
839: struct cgsix_softc *sc = (struct cgsix_softc *)dev;
840:
841: if (sc->sc_blanked) {
842: sc->sc_blanked = 0;
843: sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
844: }
845: }
846:
847: /* XXX the following should be moved to a "user interface" header */
848: /*
849: * Base addresses at which users can mmap() the various pieces of a cg6.
850: * Note that although the Brooktree color registers do not occupy 8K,
851: * the X server dies if we do not allow it to map 8K there (it just maps
852: * from 0x70000000 forwards, as a contiguous chunk).
853: */
854: #define CG6_USER_FBC 0x70000000
855: #define CG6_USER_TEC 0x70001000
856: #define CG6_USER_BTREGS 0x70002000
857: #define CG6_USER_FHC 0x70004000
858: #define CG6_USER_THC 0x70005000
859: #define CG6_USER_ROM 0x70006000
860: #define CG6_USER_RAM 0x70016000
861: #define CG6_USER_DHC 0x80000000
862:
863: struct mmo {
1.2 eeh 864: u_long mo_uaddr; /* user (virtual) address */
865: u_long mo_size; /* size, or 0 for video ram size */
866: u_long mo_physoff; /* offset from sc_physadr */
1.1 pk 867: };
868:
869: /*
870: * Return the address that would map the given device at the given
871: * offset, allowing for the given protection, or return -1 for error.
872: *
873: * XXX needs testing against `demanding' applications (e.g., aviator)
874: */
875: paddr_t
876: cgsixmmap(dev, off, prot)
877: dev_t dev;
878: off_t off;
879: int prot;
880: {
881: struct cgsix_softc *sc = cgsix_cd.cd_devs[minor(dev)];
882: struct mmo *mo;
883: u_int u, sz;
884: static struct mmo mmo[] = {
885: { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET },
886:
887: /* do not actually know how big most of these are! */
888: { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET },
889: { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET },
890: { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET },
891: { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET },
892: { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET },
893: { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET },
894: { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET },
895: };
896: #define NMMO (sizeof mmo / sizeof *mmo)
897:
898: if (off & PGOFSET)
899: panic("cgsixmmap");
900:
901: /*
902: * Entries with size 0 map video RAM (i.e., the size in fb data).
903: *
904: * Since we work in pages, the fact that the map offset table's
905: * sizes are sometimes bizarre (e.g., 1) is effectively ignored:
906: * one byte is as good as one page.
907: */
908: for (mo = mmo; mo < &mmo[NMMO]; mo++) {
1.2 eeh 909: if ((u_long)off < mo->mo_uaddr)
1.1 pk 910: continue;
911: u = off - mo->mo_uaddr;
912: sz = mo->mo_size ? mo->mo_size : sc->sc_fb.fb_type.fb_size;
913: if (u < sz) {
914: bus_space_handle_t bh;
915: if (bus_space_mmap(sc->sc_bustag,
916: sc->sc_btype,
917: sc->sc_paddr+u+mo->mo_physoff,
918: BUS_SPACE_MAP_LINEAR, &bh))
919: return (-1);
920:
921: return ((paddr_t)bh);
922: }
923: }
924:
925: #ifdef DEBUG
926: {
927: struct proc *p = curproc; /* XXX */
928: log(LOG_NOTICE, "cgsixmmap(0x%x) (%s[%d])\n",
929: off, p->p_comm, p->p_pid);
930: }
931: #endif
932: return (-1); /* not a user-map offset */
933: }
CVSweb <webmaster@jp.NetBSD.org>