Annotation of src/sys/dev/sun/cgsix.c, Revision 1.46.4.2
1.46.4.2! rmind 1: /* $NetBSD$ */
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: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: /*
33: * Copyright (c) 1993
34: * The Regents of the University of California. All rights reserved.
35: *
36: * This software was developed by the Computer Systems Engineering group
37: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
38: * contributed to Berkeley.
39: *
40: * All advertising materials mentioning features or use of this software
41: * must display the following acknowledgement:
42: * This product includes software developed by the University of
43: * California, Lawrence Berkeley Laboratory.
44: *
45: * Redistribution and use in source and binary forms, with or without
46: * modification, are permitted provided that the following conditions
47: * are met:
48: * 1. Redistributions of source code must retain the above copyright
49: * notice, this list of conditions and the following disclaimer.
50: * 2. Redistributions in binary form must reproduce the above copyright
51: * notice, this list of conditions and the following disclaimer in the
52: * documentation and/or other materials provided with the distribution.
1.13 agc 53: * 3. Neither the name of the University nor the names of its contributors
1.1 pk 54: * may be used to endorse or promote products derived from this software
55: * without specific prior written permission.
56: *
57: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67: * SUCH DAMAGE.
68: *
69: * @(#)cgsix.c 8.4 (Berkeley) 1/21/94
70: */
71:
72: /*
73: * color display (cgsix) driver.
74: *
75: * Does not handle interrupts, even though they can occur.
76: *
77: * XXX should defer colormap updates to vertical retrace interrupts
78: */
1.7 lukem 79:
80: #include <sys/cdefs.h>
1.46.4.2! rmind 81: __KERNEL_RCSID(0, "$NetBSD$");
1.1 pk 82:
83: #include <sys/param.h>
84: #include <sys/systm.h>
85: #include <sys/buf.h>
86: #include <sys/device.h>
87: #include <sys/ioctl.h>
88: #include <sys/malloc.h>
89: #include <sys/mman.h>
90: #include <sys/tty.h>
91: #include <sys/conf.h>
92:
93: #ifdef DEBUG
94: #include <sys/proc.h>
95: #include <sys/syslog.h>
96: #endif
97:
1.35 ad 98: #include <sys/bus.h>
1.1 pk 99:
100: #include <dev/sun/fbio.h>
101: #include <dev/sun/fbvar.h>
102:
103: #include <dev/sun/btreg.h>
104: #include <dev/sun/btvar.h>
105: #include <dev/sun/pfourreg.h>
106:
1.18 martin 107: #include <dev/wscons/wsconsio.h>
108: #include <dev/wsfont/wsfont.h>
1.1 pk 109: #include <dev/rasops/rasops.h>
1.18 martin 110:
111: #include "opt_wsemul.h"
1.20 martin 112: #include "rasops_glue.h"
1.1 pk 113:
1.23 macallan 114: #include <dev/sun/cgsixreg.h>
115: #include <dev/sun/cgsixvar.h>
116:
1.46 tsutsui 117: #include "ioconf.h"
118:
1.39 macallan 119: static void cg6_unblank(device_t);
1.33 macallan 120: static void cg6_blank(struct cgsix_softc *, int);
1.1 pk 121:
1.8 gehenna 122: dev_type_open(cgsixopen);
123: dev_type_close(cgsixclose);
124: dev_type_ioctl(cgsixioctl);
125: dev_type_mmap(cgsixmmap);
126:
127: const struct cdevsw cgsix_cdevsw = {
128: cgsixopen, cgsixclose, noread, nowrite, cgsixioctl,
1.32 martin 129: nostop, notty, nopoll, cgsixmmap, nokqfilter, D_OTHER
1.8 gehenna 130: };
1.1 pk 131:
132: /* frame buffer generic driver */
133: static struct fbdriver cg6_fbdriver = {
1.9 jdolecek 134: cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, nopoll, cgsixmmap,
135: nokqfilter
1.1 pk 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:
1.23 macallan 144: #if NWSDISPLAY > 0
1.33 macallan 145: #ifdef RASTERCONSOLE
146: #error RASTERCONSOLE and wsdisplay are mutually exclusive
147: #endif
148:
1.23 macallan 149: static void cg6_setup_palette(struct cgsix_softc *);
150:
1.18 martin 151: struct wsscreen_descr cgsix_defaultscreen = {
152: "std",
153: 0, 0, /* will be filled in -- XXX shouldn't, it's global */
1.23 macallan 154: NULL, /* textops */
155: 8, 16, /* font width/height */
1.32 martin 156: WSSCREEN_WSCOLORS, /* capabilities */
157: NULL /* modecookie */
1.18 martin 158: };
159:
1.34 christos 160: static int cgsix_ioctl(void *, void *, u_long, void *, int, struct lwp *);
1.30 jmmv 161: static paddr_t cgsix_mmap(void *, void *, off_t, int);
1.33 macallan 162: static void cgsix_init_screen(void *, struct vcons_screen *, int, long *);
163:
164: static void cgsix_clearscreen(struct cgsix_softc *);
1.23 macallan 165:
166: void cgsix_setup_mono(struct cgsix_softc *, int, int, int, int, uint32_t,
167: uint32_t);
168: void cgsix_feed_line(struct cgsix_softc *, int, uint8_t *);
169: void cgsix_rectfill(struct cgsix_softc *, int, int, int, int, uint32_t);
170:
171: int cgsix_putcmap(struct cgsix_softc *, struct wsdisplay_cmap *);
172: int cgsix_getcmap(struct cgsix_softc *, struct wsdisplay_cmap *);
173: void cgsix_putchar(void *, int, int, u_int, long);
174: void cgsix_cursor(void *, int, int, int);
175:
1.18 martin 176: struct wsdisplay_accessops cgsix_accessops = {
177: cgsix_ioctl,
178: cgsix_mmap,
1.33 macallan 179: NULL, /* alloc_screen */
180: NULL, /* free_screen */
181: NULL, /* show_screen */
1.18 martin 182: NULL, /* load_font */
183: NULL, /* pollc */
184: NULL /* scroll */
185: };
186:
187: const struct wsscreen_descr *_cgsix_scrlist[] = {
188: &cgsix_defaultscreen
189: };
190:
191: struct wsscreen_list cgsix_screenlist = {
192: sizeof(_cgsix_scrlist) / sizeof(struct wsscreen_descr *),
193: _cgsix_scrlist
194: };
195:
1.23 macallan 196:
197: extern const u_char rasops_cmap[768];
198:
199: #endif /* NWSDISPLAY > 0 */
200:
201: #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE)
202: void cg6_invert(struct cgsix_softc *, int, int, int, int);
203:
204: /* need this for both cases because ri_hw points to it */
1.33 macallan 205: static struct vcons_screen cg6_console_screen;
1.23 macallan 206: #endif
207:
1.1 pk 208: #ifdef RASTERCONSOLE
209: int cgsix_use_rasterconsole = 1;
1.18 martin 210: #endif
1.1 pk 211:
212: /*
213: * cg6 accelerated console routines.
214: *
215: * Note that buried in this code in several places is the assumption
216: * that pixels are exactly one byte wide. Since this is cg6-specific
217: * code, this seems safe. This assumption resides in things like the
218: * use of ri_emuwidth without messing around with ri_pelbytes, or the
219: * assumption that ri_font->fontwidth is the right thing to multiply
220: * character-cell counts by to get byte counts.
221: */
222:
223: /*
224: * Magic values for blitter
225: */
226:
1.5 tsutsui 227: /* Values for the mode register */
228: #define CG6_MODE ( \
229: 0x00200000 /* GX_BLIT_SRC */ \
230: | 0x00020000 /* GX_MODE_COLOR8 */ \
231: | 0x00008000 /* GX_DRAW_RENDER */ \
232: | 0x00002000 /* GX_BWRITE0_ENABLE */ \
233: | 0x00001000 /* GX_BWRITE1_DISABLE */ \
234: | 0x00000200 /* GX_BREAD_0 */ \
235: | 0x00000080 /* GX_BDISP_0 */ \
236: )
237: #define CG6_MODE_MASK ( \
238: 0x00300000 /* GX_BLIT_ALL */ \
239: | 0x00060000 /* GX_MODE_ALL */ \
240: | 0x00018000 /* GX_DRAW_ALL */ \
241: | 0x00006000 /* GX_BWRITE0_ALL */ \
242: | 0x00001800 /* GX_BWRITE1_ALL */ \
243: | 0x00000600 /* GX_BREAD_ALL */ \
244: | 0x00000180 /* GX_BDISP_ALL */ \
245: )
246:
1.1 pk 247: /* Value for the alu register for screen-to-screen copies */
248: #define CG6_ALU_COPY ( \
249: 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
250: | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
251: | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
252: | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
253: | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
254: | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
255: | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
256: | 0x0000cccc /* ALU = src */ \
257: )
258:
259: /* Value for the alu register for region fills */
260: #define CG6_ALU_FILL ( \
261: 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
262: | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
263: | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
264: | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
265: | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
266: | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
267: | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
268: | 0x0000ff00 /* ALU = fg color */ \
269: )
270:
271: /* Value for the alu register for toggling an area */
272: #define CG6_ALU_FLIP ( \
273: 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
274: | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
275: | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
276: | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
277: | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
278: | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
279: | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
280: | 0x00005555 /* ALU = ~dst */ \
281: )
282:
283: /*
284: * Wait for a blit to finish.
285: * 0x8000000 bit: function unknown; 0x20000000 bit: GX_BLT_INPROGRESS
286: */
287: #define CG6_BLIT_WAIT(fbc) do { \
288: while (((fbc)->fbc_blit & 0xa0000000) == 0xa0000000) \
289: /*EMPTY*/; \
290: } while (0)
291:
292: /*
293: * Wait for a drawing operation to finish, or at least get queued.
294: * 0x8000000 bit: function unknown; 0x20000000 bit: GX_FULL
295: */
296: #define CG6_DRAW_WAIT(fbc) do { \
297: while (((fbc)->fbc_draw & 0xa0000000) == 0xa0000000) \
298: /*EMPTY*/; \
299: } while (0)
300:
301: /*
302: * Wait for the whole engine to go idle. This may not matter in our case;
303: * I'm not sure whether blits are actually queued or not. It more likely
304: * is intended for lines and such that do get queued.
305: * 0x10000000 bit: GX_INPROGRESS
306: */
307: #define CG6_DRAIN(fbc) do { \
308: while ((fbc)->fbc_s & 0x10000000) \
309: /*EMPTY*/; \
310: } while (0)
311:
1.23 macallan 312: #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE)
1.5 tsutsui 313: static void cg6_ras_init(struct cgsix_softc *);
314: static void cg6_ras_copyrows(void *, int, int, int);
315: static void cg6_ras_copycols(void *, int, int, int, int);
316: static void cg6_ras_erasecols(void *, int, int, int, long int);
317: static void cg6_ras_eraserows(void *, int, int, long int);
1.24 macallan 318: #if defined(RASTERCONSOLE) && defined(CG6_BLIT_CURSOR)
1.5 tsutsui 319: static void cg6_ras_do_cursor(struct rasops_info *);
1.23 macallan 320: #endif
1.5 tsutsui 321: static void
322: cg6_ras_init(struct cgsix_softc *sc)
323: {
324: volatile struct cg6_fbc *fbc = sc->sc_fbc;
325:
326: CG6_DRAIN(fbc);
327: fbc->fbc_mode &= ~CG6_MODE_MASK;
328: fbc->fbc_mode |= CG6_MODE;
329: }
330:
1.1 pk 331: static void
332: cg6_ras_copyrows(void *cookie, int src, int dst, int n)
333: {
1.33 macallan 334: struct rasops_info *ri = cookie;
335: struct vcons_screen *scr = ri->ri_hw;
336: struct cgsix_softc *sc = scr->scr_cookie;
337: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1.23 macallan 338:
1.33 macallan 339: if (dst == src)
340: return;
341: if (src < 0) {
342: n += src;
343: src = 0;
344: }
345: if (src+n > ri->ri_rows)
346: n = ri->ri_rows - src;
347: if (dst < 0) {
348: n += dst;
349: dst = 0;
350: }
351: if (dst+n > ri->ri_rows)
352: n = ri->ri_rows - dst;
353: if (n <= 0)
354: return;
355: n *= ri->ri_font->fontheight;
356: src *= ri->ri_font->fontheight;
357: dst *= ri->ri_font->fontheight;
358: fbc->fbc_clip = 0;
359: fbc->fbc_s = 0;
360: fbc->fbc_offx = 0;
361: fbc->fbc_offy = 0;
362: fbc->fbc_clipminx = 0;
363: fbc->fbc_clipminy = 0;
364: fbc->fbc_clipmaxx = ri->ri_width - 1;
365: fbc->fbc_clipmaxy = ri->ri_height - 1;
366: fbc->fbc_alu = CG6_ALU_COPY;
367: fbc->fbc_x0 = ri->ri_xorigin;
368: fbc->fbc_y0 = ri->ri_yorigin + src;
369: fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
370: fbc->fbc_y1 = ri->ri_yorigin + src + n - 1;
371: fbc->fbc_x2 = ri->ri_xorigin;
372: fbc->fbc_y2 = ri->ri_yorigin + dst;
373: fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1;
374: fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1;
375: CG6_BLIT_WAIT(fbc);
376: CG6_DRAIN(fbc);
1.1 pk 377: }
378:
379: static void
380: cg6_ras_copycols(void *cookie, int row, int src, int dst, int n)
381: {
1.33 macallan 382: struct rasops_info *ri = cookie;
383: struct vcons_screen *scr = ri->ri_hw;
384: struct cgsix_softc *sc = scr->scr_cookie;
385: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1.23 macallan 386:
1.33 macallan 387: if (dst == src)
388: return;
389: if ((row < 0) || (row >= ri->ri_rows))
390: return;
391: if (src < 0) {
392: n += src;
393: src = 0;
394: }
395: if (src+n > ri->ri_cols)
396: n = ri->ri_cols - src;
397: if (dst < 0) {
398: n += dst;
399: dst = 0;
400: }
401: if (dst+n > ri->ri_cols)
402: n = ri->ri_cols - dst;
403: if (n <= 0)
404: return;
405: n *= ri->ri_font->fontwidth;
406: src *= ri->ri_font->fontwidth;
407: dst *= ri->ri_font->fontwidth;
408: row *= ri->ri_font->fontheight;
409: fbc->fbc_clip = 0;
410: fbc->fbc_s = 0;
411: fbc->fbc_offx = 0;
412: fbc->fbc_offy = 0;
413: fbc->fbc_clipminx = 0;
414: fbc->fbc_clipminy = 0;
415: fbc->fbc_clipmaxx = ri->ri_width - 1;
416: fbc->fbc_clipmaxy = ri->ri_height - 1;
417: fbc->fbc_alu = CG6_ALU_COPY;
418: fbc->fbc_x0 = ri->ri_xorigin + src;
419: fbc->fbc_y0 = ri->ri_yorigin + row;
420: fbc->fbc_x1 = ri->ri_xorigin + src + n - 1;
421: fbc->fbc_y1 = ri->ri_yorigin + row +
422: ri->ri_font->fontheight - 1;
423: fbc->fbc_x2 = ri->ri_xorigin + dst;
424: fbc->fbc_y2 = ri->ri_yorigin + row;
425: fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1;
426: fbc->fbc_y3 = ri->ri_yorigin + row +
427: ri->ri_font->fontheight - 1;
428: CG6_BLIT_WAIT(fbc);
429: CG6_DRAIN(fbc);
1.1 pk 430: }
431:
432: static void
433: cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr)
434: {
1.33 macallan 435: struct rasops_info *ri = cookie;
436: struct vcons_screen *scr = ri->ri_hw;
437: struct cgsix_softc *sc = scr->scr_cookie;
438: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1.23 macallan 439:
1.33 macallan 440: if ((row < 0) || (row >= ri->ri_rows))
441: return;
442: if (col < 0) {
443: n += col;
444: col = 0;
445: }
446: if (col+n > ri->ri_cols)
447: n = ri->ri_cols - col;
448: if (n <= 0)
449: return;
450: n *= ri->ri_font->fontwidth;
451: col *= ri->ri_font->fontwidth;
452: row *= ri->ri_font->fontheight;
453: fbc->fbc_clip = 0;
454: fbc->fbc_s = 0;
455: fbc->fbc_offx = 0;
456: fbc->fbc_offy = 0;
457: fbc->fbc_clipminx = 0;
458: fbc->fbc_clipminy = 0;
459: fbc->fbc_clipmaxx = ri->ri_width - 1;
460: fbc->fbc_clipmaxy = ri->ri_height - 1;
461: fbc->fbc_alu = CG6_ALU_FILL;
462: fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff];
463: fbc->fbc_arecty = ri->ri_yorigin + row;
464: fbc->fbc_arectx = ri->ri_xorigin + col;
465: fbc->fbc_arecty = ri->ri_yorigin + row +
466: ri->ri_font->fontheight - 1;
467: fbc->fbc_arectx = ri->ri_xorigin + col + n - 1;
468: CG6_DRAW_WAIT(fbc);
469: CG6_DRAIN(fbc);
1.1 pk 470: }
471:
472: static void
473: cg6_ras_eraserows(void *cookie, int row, int n, long int attr)
474: {
1.33 macallan 475: struct rasops_info *ri = cookie;
476: struct vcons_screen *scr = ri->ri_hw;
477: struct cgsix_softc *sc = scr->scr_cookie;
478: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1.23 macallan 479:
1.33 macallan 480: if (row < 0) {
481: n += row;
482: row = 0;
483: }
484: if (row+n > ri->ri_rows)
485: n = ri->ri_rows - row;
486: if (n <= 0)
487: return;
488: fbc->fbc_clip = 0;
489: fbc->fbc_s = 0;
490: fbc->fbc_offx = 0;
491: fbc->fbc_offy = 0;
492: fbc->fbc_clipminx = 0;
493: fbc->fbc_clipminy = 0;
494: fbc->fbc_clipmaxx = ri->ri_width - 1;
495: fbc->fbc_clipmaxy = ri->ri_height - 1;
496: fbc->fbc_alu = CG6_ALU_FILL;
497: fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff];
498: if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
499: fbc->fbc_arecty = 0;
500: fbc->fbc_arectx = 0;
501: fbc->fbc_arecty = ri->ri_height - 1;
502: fbc->fbc_arectx = ri->ri_width - 1;
503: } else {
504: row *= ri->ri_font->fontheight;
505: fbc->fbc_arecty = ri->ri_yorigin + row;
506: fbc->fbc_arectx = ri->ri_xorigin;
507: fbc->fbc_arecty = ri->ri_yorigin + row +
508: (n * ri->ri_font->fontheight) - 1;
509: fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1;
1.23 macallan 510: }
1.33 macallan 511: CG6_DRAW_WAIT(fbc);
512: CG6_DRAIN(fbc);
1.1 pk 513: }
514:
1.24 macallan 515: #if defined(RASTERCONSOLE) && defined(CG6_BLIT_CURSOR)
1.1 pk 516: /*
517: * Really want something more like fg^bg here, but that would be more
518: * or less impossible to migrate to colors. So we hope there's
519: * something not too inappropriate in the colormap...besides, it's what
520: * the non-accelerated code did. :-)
521: */
522: static void
523: cg6_ras_do_cursor(struct rasops_info *ri)
524: {
1.33 macallan 525: struct vcons_screen *scr = ri->ri_hw;
526: struct cgsix_softc *sc = scr->cookie;
1.23 macallan 527: int row, col;
528:
1.1 pk 529: row = ri->ri_crow * ri->ri_font->fontheight;
530: col = ri->ri_ccol * ri->ri_font->fontwidth;
1.24 macallan 531: cg6_invert(sc, ri->ri_xorigin + col,ri->ri_yorigin +
532: row, ri->ri_font->fontwidth, ri->ri_font->fontheight);
1.1 pk 533: }
1.23 macallan 534: #endif /* RASTERCONSOLE */
535:
536: #endif /* (NWSDISPLAY > 0) || defined(RASTERCONSOLE) */
1.1 pk 537:
538: void
1.25 tsutsui 539: cg6attach(struct cgsix_softc *sc, const char *name, int isconsole)
1.1 pk 540: {
541: struct fbdevice *fb = &sc->sc_fb;
1.23 macallan 542: #if NWSDISPLAY > 0
1.18 martin 543: struct wsemuldisplaydev_attach_args aa;
1.33 macallan 544: struct rasops_info *ri = &cg6_console_screen.scr_ri;
1.18 martin 545: unsigned long defattr;
1.20 martin 546: #endif
1.33 macallan 547:
1.1 pk 548: fb->fb_driver = &cg6_fbdriver;
549:
550: /* Don't have to map the pfour register on the cgsix. */
551: fb->fb_pfour = NULL;
552:
553: fb->fb_type.fb_cmsize = 256;
1.23 macallan 554: fb->fb_type.fb_size = sc->sc_ramsize;
555: /*fb->fb_type.fb_height * fb->fb_linebytes;*/
1.1 pk 556: printf(": %s, %d x %d", name,
557: fb->fb_type.fb_width, fb->fb_type.fb_height);
1.18 martin 558: if(sc->sc_fhc) {
1.23 macallan 559: sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) &
1.1 pk 560: (FHC_REV_MASK >> FHC_REV_SHIFT);
1.18 martin 561: } else
562: sc->sc_fhcrev=-1;
1.1 pk 563: printf(", rev %d", sc->sc_fhcrev);
564:
565: /* reset cursor & frame buffer controls */
566: cg6_reset(sc);
567:
568: /* enable video */
569: sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
570:
571: if (isconsole) {
572: printf(" (console)");
1.19 perry 573:
1.23 macallan 574: /* this is the old console attachment stuff - sparc still needs it */
1.1 pk 575: #ifdef RASTERCONSOLE
576: if (cgsix_use_rasterconsole) {
577: fbrcons_init(&sc->sc_fb);
1.23 macallan 578: /*
579: * we don't use the screen struct but keep it here to
580: * avoid ugliness in the cg6_ras_* functions
581: */
1.33 macallan 582: cg6_console_screen.scr_cookie = sc;
1.23 macallan 583: sc->sc_fb.fb_rinfo.ri_hw = &cg6_console_screen;
1.1 pk 584: sc->sc_fb.fb_rinfo.ri_ops.copyrows = cg6_ras_copyrows;
585: sc->sc_fb.fb_rinfo.ri_ops.copycols = cg6_ras_copycols;
586: sc->sc_fb.fb_rinfo.ri_ops.erasecols = cg6_ras_erasecols;
587: sc->sc_fb.fb_rinfo.ri_ops.eraserows = cg6_ras_eraserows;
1.24 macallan 588: #ifdef CG6_BLIT_CURSOR
1.1 pk 589: sc->sc_fb.fb_rinfo.ri_do_cursor = cg6_ras_do_cursor;
1.24 macallan 590: #endif
1.5 tsutsui 591: cg6_ras_init(sc);
1.1 pk 592: }
593: #endif
594: }
1.26 thorpej 595: printf("\n");
1.1 pk 596:
1.18 martin 597: fb_attach(&sc->sc_fb, isconsole);
1.23 macallan 598: sc->sc_width = fb->fb_type.fb_width;
599: sc->sc_stride = fb->fb_type.fb_width;
600: sc->sc_height = fb->fb_type.fb_height;
1.19 perry 601:
1.39 macallan 602: printf("%s: framebuffer size: %d MB\n", device_xname(sc->sc_dev),
1.24 macallan 603: sc->sc_ramsize >> 20);
604:
1.20 martin 605: #if NWSDISPLAY
606: /* setup rasops and so on for wsdisplay */
1.41 macallan 607: memcpy(sc->sc_default_cmap, rasops_cmap, 768);
1.18 martin 608: wsfont_init();
609: cg6_ras_init(sc);
1.23 macallan 610: sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
611: sc->sc_bg = WS_DEFAULT_BG;
612:
1.33 macallan 613: vcons_init(&sc->vd, sc, &cgsix_defaultscreen, &cgsix_accessops);
614: sc->vd.init_screen = cgsix_init_screen;
1.23 macallan 615:
1.45 macallan 616: cg6_setup_palette(sc);
617: cgsix_clearscreen(sc);
618:
1.27 macallan 619: if(isconsole) {
620: /* we mess with cg6_console_screen only once */
1.33 macallan 621: vcons_init_screen(&sc->vd, &cg6_console_screen, 1,
622: &defattr);
623: cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
624:
1.27 macallan 625: cgsix_defaultscreen.textops = &ri->ri_ops;
626: cgsix_defaultscreen.capabilities = ri->ri_caps;
627: cgsix_defaultscreen.nrows = ri->ri_rows;
628: cgsix_defaultscreen.ncols = ri->ri_cols;
1.33 macallan 629: SCREEN_VISIBLE(&cg6_console_screen);
630: sc->vd.active = &cg6_console_screen;
1.45 macallan 631: wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr);
632: vcons_replay_msgbuf(&cg6_console_screen);
1.27 macallan 633: } else {
634: /*
635: * we're not the console so we just clear the screen and don't
636: * set up any sort of text display
637: */
638: }
639:
640: aa.scrdata = &cgsix_screenlist;
1.18 martin 641: aa.console = isconsole;
642: aa.accessops = &cgsix_accessops;
1.33 macallan 643: aa.accesscookie = &sc->vd;
1.39 macallan 644: config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
1.23 macallan 645: #else
646: bt_initcmap(&sc->sc_cmap, 256);
647: cg6_loadcmap(sc, 0, 256);
648:
1.20 martin 649: #endif
1.1 pk 650: }
651:
652:
653: int
1.28 christos 654: cgsixopen(dev_t dev, int flags, int mode, struct lwp *l)
1.1 pk 655: {
656: int unit = minor(dev);
657:
1.38 drochner 658: if (device_lookup(&cgsix_cd, unit) == NULL)
1.22 martin 659: return ENXIO;
660: return 0;
1.1 pk 661: }
662:
663: int
1.28 christos 664: cgsixclose(dev_t dev, int flags, int mode, struct lwp *l)
1.1 pk 665: {
1.39 macallan 666: device_t dv = device_lookup(&cgsix_cd, minor(dev));
667: struct cgsix_softc *sc = device_private(dv);
1.1 pk 668:
669: cg6_reset(sc);
670:
1.23 macallan 671: #if NWSDISPLAY > 0
672: cg6_setup_palette(sc);
673: #else
1.1 pk 674: /* (re-)initialize the default color map */
675: bt_initcmap(&sc->sc_cmap, 256);
1.23 macallan 676:
1.1 pk 677: cg6_loadcmap(sc, 0, 256);
1.23 macallan 678: #endif
1.22 martin 679: return 0;
1.1 pk 680: }
681:
682: int
1.34 christos 683: cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
1.1 pk 684: {
1.38 drochner 685: struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev));
1.16 chs 686: union cursor_cmap tcm;
687: uint32_t image[32], mask[32];
1.1 pk 688: u_int count;
689: int v, error;
690:
1.18 martin 691: #ifdef CGSIX_DEBUG
692: printf("cgsixioctl(%ld)\n",cmd);
693: #endif
694:
1.1 pk 695: switch (cmd) {
696:
697: case FBIOGTYPE:
698: *(struct fbtype *)data = sc->sc_fb.fb_type;
699: break;
700:
701: case FBIOGATTR:
702: #define fba ((struct fbgattr *)data)
703: fba->real_type = sc->sc_fb.fb_type.fb_type;
704: fba->owner = 0; /* XXX ??? */
705: fba->fbtype = sc->sc_fb.fb_type;
706: fba->sattr.flags = 0;
707: fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
708: fba->sattr.dev_specific[0] = -1;
709: fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
710: fba->emu_types[1] = -1;
711: #undef fba
712: break;
713:
714: case FBIOGETCMAP:
715: #define p ((struct fbcmap *)data)
716: return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
717:
718: case FBIOPUTCMAP:
719: /* copy to software map */
720: error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
721: if (error)
1.22 martin 722: return error;
1.1 pk 723: /* now blast them into the chip */
724: /* XXX should use retrace interrupt */
725: cg6_loadcmap(sc, p->index, p->count);
726: #undef p
727: break;
728:
729: case FBIOGVIDEO:
730: *(int *)data = sc->sc_blanked;
731: break;
732:
733: case FBIOSVIDEO:
1.33 macallan 734: cg6_blank(sc, !(*(int *)data));
1.1 pk 735: break;
736:
737: /* these are for both FBIOSCURSOR and FBIOGCURSOR */
738: #define p ((struct fbcursor *)data)
739: #define cc (&sc->sc_cursor)
740:
741: case FBIOGCURSOR:
742: /* do not quite want everything here... */
743: p->set = FB_CUR_SETALL; /* close enough, anyway */
744: p->enable = cc->cc_enable;
745: p->pos = cc->cc_pos;
746: p->hot = cc->cc_hot;
747: p->size = cc->cc_size;
748:
749: /* begin ugh ... can we lose some of this crap?? */
750: if (p->image != NULL) {
751: count = cc->cc_size.y * 32 / NBBY;
1.16 chs 752: error = copyout(cc->cc_bits[1], p->image, count);
1.1 pk 753: if (error)
1.22 martin 754: return error;
1.16 chs 755: error = copyout(cc->cc_bits[0], p->mask, count);
1.1 pk 756: if (error)
1.22 martin 757: return error;
1.1 pk 758: }
759: if (p->cmap.red != NULL) {
760: error = bt_getcmap(&p->cmap,
761: (union bt_cmap *)&cc->cc_color, 2, 1);
762: if (error)
1.22 martin 763: return error;
1.1 pk 764: } else {
765: p->cmap.index = 0;
766: p->cmap.count = 2;
767: }
768: /* end ugh */
769: break;
770:
771: case FBIOSCURSOR:
772: /*
773: * For setcmap and setshape, verify parameters, so that
774: * we do not get halfway through an update and then crap
775: * out with the software state screwed up.
776: */
777: v = p->set;
778: if (v & FB_CUR_SETCMAP) {
779: /*
780: * This use of a temporary copy of the cursor
781: * colormap is not terribly efficient, but these
782: * copies are small (8 bytes)...
783: */
784: tcm = cc->cc_color;
1.23 macallan 785: error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2,
786: 1);
1.1 pk 787: if (error)
1.22 martin 788: return error;
1.1 pk 789: }
790: if (v & FB_CUR_SETSHAPE) {
791: if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32)
1.22 martin 792: return EINVAL;
1.1 pk 793: count = p->size.y * 32 / NBBY;
1.16 chs 794: error = copyin(p->image, image, count);
795: if (error)
796: return error;
797: error = copyin(p->mask, mask, count);
798: if (error)
799: return error;
1.1 pk 800: }
801:
802: /* parameters are OK; do it */
803: if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) {
804: if (v & FB_CUR_SETCUR)
805: cc->cc_enable = p->enable;
806: if (v & FB_CUR_SETPOS)
807: cc->cc_pos = p->pos;
808: if (v & FB_CUR_SETHOT)
809: cc->cc_hot = p->hot;
810: cg6_setcursor(sc);
811: }
812: if (v & FB_CUR_SETCMAP) {
813: cc->cc_color = tcm;
814: cg6_loadomap(sc); /* XXX defer to vertical retrace */
815: }
816: if (v & FB_CUR_SETSHAPE) {
817: cc->cc_size = p->size;
818: count = p->size.y * 32 / NBBY;
1.16 chs 819: memset(cc->cc_bits, 0, sizeof cc->cc_bits);
820: memcpy(cc->cc_bits[1], image, count);
821: memcpy(cc->cc_bits[0], mask, count);
1.1 pk 822: cg6_loadcursor(sc);
823: }
824: break;
825:
826: #undef p
827: #undef cc
828:
829: case FBIOGCURPOS:
830: *(struct fbcurpos *)data = sc->sc_cursor.cc_pos;
831: break;
832:
833: case FBIOSCURPOS:
834: sc->sc_cursor.cc_pos = *(struct fbcurpos *)data;
835: cg6_setcursor(sc);
836: break;
837:
838: case FBIOGCURMAX:
839: /* max cursor size is 32x32 */
840: ((struct fbcurpos *)data)->x = 32;
841: ((struct fbcurpos *)data)->y = 32;
842: break;
843:
844: default:
845: #ifdef DEBUG
846: log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd,
1.29 christos 847: l->l_proc->p_comm, l->l_proc->p_pid);
1.1 pk 848: #endif
1.22 martin 849: return ENOTTY;
1.1 pk 850: }
1.22 martin 851: return 0;
1.1 pk 852: }
853:
854: /*
855: * Clean up hardware state (e.g., after bootup or after X crashes).
856: */
857: static void
1.22 martin 858: cg6_reset(struct cgsix_softc *sc)
1.1 pk 859: {
860: volatile struct cg6_tec_xxx *tec;
861: int fhc;
862: volatile struct bt_regs *bt;
863:
864: /* hide the cursor, just in case */
865: sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF;
866:
867: /* turn off frobs in transform engine (makes X11 work) */
868: tec = sc->sc_tec;
869: tec->tec_mv = 0;
870: tec->tec_clip = 0;
871: tec->tec_vdc = 0;
872:
873: /* take care of hardware bugs in old revisions */
874: if (sc->sc_fhcrev < 5) {
875: /*
1.17 wiz 876: * Keep current resolution; set CPU to 68020, set test
1.1 pk 877: * window (size 1Kx1K), and for rev 1, disable dest cache.
878: */
879: fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 |
880: FHC_TEST |
881: (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT);
882: if (sc->sc_fhcrev < 2)
883: fhc |= FHC_DST_DISABLE;
884: *sc->sc_fhc = fhc;
885: }
886:
887: /* Enable cursor in Brooktree DAC. */
888: bt = sc->sc_bt;
889: bt->bt_addr = 0x06 << 24;
890: bt->bt_ctrl |= 0x03 << 24;
891: }
892:
893: static void
1.22 martin 894: cg6_setcursor(struct cgsix_softc *sc)
1.1 pk 895: {
896:
897: /* we need to subtract the hot-spot value here */
898: #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f)
899: sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ?
900: ((COORD(x) << 16) | (COORD(y) & 0xffff)) :
901: (THC_CURSOFF << 16) | THC_CURSOFF;
902: #undef COORD
903: }
904:
905: static void
1.22 martin 906: cg6_loadcursor(struct cgsix_softc *sc)
1.1 pk 907: {
908: volatile struct cg6_thc *thc;
909: u_int edgemask, m;
910: int i;
911:
912: /*
913: * Keep the top size.x bits. Here we *throw out* the top
914: * size.x bits from an all-one-bits word, introducing zeros in
915: * the top size.x bits, then invert all the bits to get what
916: * we really wanted as our mask. But this fails if size.x is
917: * 32---a sparc uses only the low 5 bits of the shift count---
918: * so we have to special case that.
919: */
920: edgemask = ~0;
921: if (sc->sc_cursor.cc_size.x < 32)
922: edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x);
923: thc = sc->sc_thc;
924: for (i = 0; i < 32; i++) {
925: m = sc->sc_cursor.cc_bits[0][i] & edgemask;
926: thc->thc_cursmask[i] = m;
927: thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i];
928: }
929: }
930:
931: /*
932: * Load a subset of the current (new) colormap into the color DAC.
933: */
934: static void
1.22 martin 935: cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors)
1.1 pk 936: {
937: volatile struct bt_regs *bt;
938: u_int *ip, i;
939: int count;
940:
941: ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */
942: count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
943: bt = sc->sc_bt;
944: bt->bt_addr = BT_D4M4(start) << 24;
945: while (--count >= 0) {
946: i = *ip++;
947: /* hardware that makes one want to pound boards with hammers */
948: bt->bt_cmap = i;
949: bt->bt_cmap = i << 8;
950: bt->bt_cmap = i << 16;
951: bt->bt_cmap = i << 24;
952: }
953: }
954:
955: /*
956: * Load the cursor (overlay `foreground' and `background') colors.
957: */
958: static void
1.22 martin 959: cg6_loadomap(struct cgsix_softc *sc)
1.1 pk 960: {
961: volatile struct bt_regs *bt;
962: u_int i;
963:
964: bt = sc->sc_bt;
965: bt->bt_addr = 0x01 << 24; /* set background color */
966: i = sc->sc_cursor.cc_color.cm_chip[0];
967: bt->bt_omap = i; /* R */
968: bt->bt_omap = i << 8; /* G */
969: bt->bt_omap = i << 16; /* B */
970:
971: bt->bt_addr = 0x03 << 24; /* set foreground color */
972: bt->bt_omap = i << 24; /* R */
973: i = sc->sc_cursor.cc_color.cm_chip[1];
974: bt->bt_omap = i; /* G */
975: bt->bt_omap = i << 8; /* B */
976: }
977:
1.33 macallan 978: /* blank or unblank the screen */
979: static void
980: cg6_blank(struct cgsix_softc *sc, int flag)
981: {
982:
983: if (sc->sc_blanked != flag) {
984: sc->sc_blanked = flag;
985: if (flag) {
986: sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN;
987: } else {
988: sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
989: }
990: }
991: }
992:
993: /*
994: * this is called on panic or ddb entry - force the console to the front, reset
995: * the colour map and enable drawing so we actually see the message even when X
996: * is running
997: */
1.1 pk 998: static void
1.39 macallan 999: cg6_unblank(device_t dev)
1.1 pk 1000: {
1.38 drochner 1001: struct cgsix_softc *sc = device_private(dev);
1.1 pk 1002:
1.33 macallan 1003: cg6_blank(sc, 0);
1.1 pk 1004: }
1005:
1006: /* XXX the following should be moved to a "user interface" header */
1007: /*
1008: * Base addresses at which users can mmap() the various pieces of a cg6.
1009: * Note that although the Brooktree color registers do not occupy 8K,
1010: * the X server dies if we do not allow it to map 8K there (it just maps
1011: * from 0x70000000 forwards, as a contiguous chunk).
1012: */
1013: #define CG6_USER_FBC 0x70000000
1014: #define CG6_USER_TEC 0x70001000
1015: #define CG6_USER_BTREGS 0x70002000
1016: #define CG6_USER_FHC 0x70004000
1017: #define CG6_USER_THC 0x70005000
1018: #define CG6_USER_ROM 0x70006000
1019: #define CG6_USER_RAM 0x70016000
1020: #define CG6_USER_DHC 0x80000000
1021:
1022: struct mmo {
1.2 eeh 1023: u_long mo_uaddr; /* user (virtual) address */
1024: u_long mo_size; /* size, or 0 for video ram size */
1025: u_long mo_physoff; /* offset from sc_physadr */
1.1 pk 1026: };
1027:
1028: /*
1029: * Return the address that would map the given device at the given
1030: * offset, allowing for the given protection, or return -1 for error.
1031: *
1032: * XXX needs testing against `demanding' applications (e.g., aviator)
1033: */
1034: paddr_t
1.22 martin 1035: cgsixmmap(dev_t dev, off_t off, int prot)
1.1 pk 1036: {
1.38 drochner 1037: struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev));
1.1 pk 1038: struct mmo *mo;
1039: u_int u, sz;
1040: static struct mmo mmo[] = {
1041: { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET },
1042:
1043: /* do not actually know how big most of these are! */
1044: { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET },
1045: { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET },
1046: { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET },
1047: { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET },
1048: { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET },
1049: { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET },
1050: { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET },
1051: };
1052: #define NMMO (sizeof mmo / sizeof *mmo)
1053:
1054: if (off & PGOFSET)
1055: panic("cgsixmmap");
1056:
1057: /*
1058: * Entries with size 0 map video RAM (i.e., the size in fb data).
1059: *
1060: * Since we work in pages, the fact that the map offset table's
1061: * sizes are sometimes bizarre (e.g., 1) is effectively ignored:
1062: * one byte is as good as one page.
1063: */
1064: for (mo = mmo; mo < &mmo[NMMO]; mo++) {
1.2 eeh 1065: if ((u_long)off < mo->mo_uaddr)
1.1 pk 1066: continue;
1067: u = off - mo->mo_uaddr;
1.23 macallan 1068: sz = mo->mo_size ? mo->mo_size :
1069: sc->sc_ramsize/*sc_fb.fb_type.fb_size*/;
1.1 pk 1070: if (u < sz) {
1.6 eeh 1071: return (bus_space_mmap(sc->sc_bustag,
1072: sc->sc_paddr, u+mo->mo_physoff,
1073: prot, BUS_SPACE_MAP_LINEAR));
1.1 pk 1074: }
1075: }
1076:
1077: #ifdef DEBUG
1078: {
1.10 thorpej 1079: struct proc *p = curlwp->l_proc; /* XXX */
1.4 chs 1080: log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n",
1081: (long long)off, p->p_comm, p->p_pid);
1.1 pk 1082: }
1083: #endif
1.22 martin 1084: return -1; /* not a user-map offset */
1.1 pk 1085: }
1.18 martin 1086:
1.23 macallan 1087: #if NWSDISPLAY > 0
1.18 martin 1088:
1.23 macallan 1089: static void
1090: cg6_setup_palette(struct cgsix_softc *sc)
1.18 martin 1091: {
1.23 macallan 1092: int i, j;
1.39 macallan 1093:
1.23 macallan 1094: j = 0;
1095: for (i = 0; i < 256; i++) {
1.39 macallan 1096: sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j];
1.23 macallan 1097: j++;
1.39 macallan 1098: sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j];
1.23 macallan 1099: j++;
1.39 macallan 1100: sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j];
1.23 macallan 1101: j++;
1102: }
1103: cg6_loadcmap(sc, 0, 256);
1.18 martin 1104: }
1105:
1106: int
1.34 christos 1107: cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
1.30 jmmv 1108: struct lwp *l)
1.18 martin 1109: {
1110: /* we'll probably need to add more stuff here */
1.33 macallan 1111: struct vcons_data *vd = v;
1112: struct cgsix_softc *sc = vd->cookie;
1.18 martin 1113: struct wsdisplay_fbinfo *wdf;
1114: struct rasops_info *ri = &sc->sc_fb.fb_rinfo;
1.33 macallan 1115: struct vcons_screen *ms = sc->vd.active;
1.18 martin 1116: #ifdef CGSIX_DEBUG
1117: printf("cgsix_ioctl(%ld)\n",cmd);
1118: #endif
1119: switch (cmd) {
1120: case WSDISPLAYIO_GTYPE:
1121: *(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
1122: return 0;
1123: case WSDISPLAYIO_GINFO:
1124: wdf = (void *)data;
1125: wdf->height = ri->ri_height;
1126: wdf->width = ri->ri_width;
1127: wdf->depth = ri->ri_depth;
1128: wdf->cmsize = 256;
1129: return 0;
1.19 perry 1130:
1.18 martin 1131: case WSDISPLAYIO_GETCMAP:
1.22 martin 1132: return cgsix_getcmap(sc,
1133: (struct wsdisplay_cmap *)data);
1.18 martin 1134: case WSDISPLAYIO_PUTCMAP:
1.22 martin 1135: return cgsix_putcmap(sc,
1136: (struct wsdisplay_cmap *)data);
1.19 perry 1137:
1.46.4.2! rmind 1138: case WSDISPLAYIO_LINEBYTES:
! 1139: *(u_int *)data = sc->sc_stride;
! 1140: return 0;
! 1141:
1.18 martin 1142: case WSDISPLAYIO_SMODE:
1143: {
1.23 macallan 1144: int new_mode = *(int*)data;
1145: if (new_mode != sc->sc_mode)
1.18 martin 1146: {
1.23 macallan 1147: sc->sc_mode = new_mode;
1148: if(new_mode == WSDISPLAYIO_MODE_EMUL)
1.18 martin 1149: {
1.23 macallan 1150: cg6_reset(sc);
1151: cg6_ras_init(sc);
1.33 macallan 1152: cg6_setup_palette(sc);
1153: vcons_redraw_screen(ms);
1.18 martin 1154: }
1155: }
1156: }
1157: }
1158: return EPASSTHROUGH;
1159: }
1160:
1161: paddr_t
1.30 jmmv 1162: cgsix_mmap(void *v, void *vs, off_t offset, int prot)
1.18 martin 1163: {
1.33 macallan 1164: struct vcons_data *vd = v;
1165: struct cgsix_softc *sc = vd->cookie;
1166:
1.23 macallan 1167: if(offset<sc->sc_ramsize) {
1168: return bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
1169: CGSIX_RAM_OFFSET+offset, prot, BUS_SPACE_MAP_LINEAR);
1.18 martin 1170: }
1171: /* I'm not at all sure this is the right thing to do */
1.23 macallan 1172: return cgsixmmap(0, offset, prot); /* assume minor dev 0 for now */
1.18 martin 1173: }
1174:
1.19 perry 1175: int
1.18 martin 1176: cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm)
1177: {
1178: u_int index = cm->index;
1179: u_int count = cm->count;
1180: int error,i;
1181: if (index >= 256 || count > 256 || index + count > 256)
1182: return EINVAL;
1183:
1.23 macallan 1184: for (i = 0; i < count; i++)
1.18 martin 1185: {
1.22 martin 1186: error = copyin(&cm->red[i],
1.23 macallan 1187: &sc->sc_cmap.cm_map[index + i][0], 1);
1.18 martin 1188: if (error)
1189: return error;
1.22 martin 1190: error = copyin(&cm->green[i],
1.23 macallan 1191: &sc->sc_cmap.cm_map[index + i][1],
1.22 martin 1192: 1);
1.18 martin 1193: if (error)
1194: return error;
1.22 martin 1195: error = copyin(&cm->blue[i],
1.23 macallan 1196: &sc->sc_cmap.cm_map[index + i][2], 1);
1.18 martin 1197: if (error)
1198: return error;
1199: }
1.23 macallan 1200: cg6_loadcmap(sc, index, count);
1.19 perry 1201:
1.18 martin 1202: return 0;
1203: }
1204:
1.22 martin 1205: int
1206: cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm)
1.18 martin 1207: {
1208: u_int index = cm->index;
1209: u_int count = cm->count;
1210: int error,i;
1211:
1212: if (index >= 256 || count > 256 || index + count > 256)
1213: return EINVAL;
1214:
1.23 macallan 1215: for (i = 0; i < count; i++)
1.18 martin 1216: {
1.23 macallan 1217: error = copyout(&sc->sc_cmap.cm_map[index + i][0],
1218: &cm->red[i], 1);
1.18 martin 1219: if (error)
1220: return error;
1.23 macallan 1221: error = copyout(&sc->sc_cmap.cm_map[index + i][1],
1222: &cm->green[i], 1);
1.18 martin 1223: if (error)
1224: return error;
1.23 macallan 1225: error = copyout(&sc->sc_cmap.cm_map[index + i][2],
1226: &cm->blue[i], 1);
1.18 martin 1227: if (error)
1228: return error;
1229: }
1.19 perry 1230:
1.18 martin 1231: return 0;
1232: }
1.23 macallan 1233:
1234: void
1.33 macallan 1235: cgsix_init_screen(void *cookie, struct vcons_screen *scr,
1.23 macallan 1236: int existing, long *defattr)
1237: {
1.33 macallan 1238: struct cgsix_softc *sc = cookie;
1239: struct rasops_info *ri = &scr->scr_ri;
1240:
1.23 macallan 1241: ri->ri_depth = 8;
1242: ri->ri_width = sc->sc_width;
1243: ri->ri_height = sc->sc_height;
1244: ri->ri_stride = sc->sc_stride;
1245: ri->ri_flg = RI_CENTER;
1246:
1247: ri->ri_bits = sc->sc_fb.fb_pixels;
1248:
1.43 jdc 1249: /* We need unaccelerated initial screen clear on old revisions */
1250: if (sc->sc_fhcrev < 2)
1251: memset(sc->sc_fb.fb_pixels, (*defattr >> 16) & 0xff,
1252: sc->sc_stride * sc->sc_height);
1.23 macallan 1253: rasops_init(ri, sc->sc_height/8, sc->sc_width/8);
1.33 macallan 1254: ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1.23 macallan 1255: rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
1256: sc->sc_width / ri->ri_font->fontwidth);
1257:
1258: /* enable acceleration */
1259: ri->ri_hw = scr;
1260: ri->ri_ops.copyrows = cg6_ras_copyrows;
1261: ri->ri_ops.copycols = cg6_ras_copycols;
1262: ri->ri_ops.eraserows = cg6_ras_eraserows;
1263: ri->ri_ops.erasecols = cg6_ras_erasecols;
1264: ri->ri_ops.cursor = cgsix_cursor;
1265: ri->ri_ops.putchar = cgsix_putchar;
1266: }
1267:
1268: void
1269: cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he,
1270: uint32_t col)
1271: {
1272: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1273:
1274: CG6_DRAIN(fbc);
1275: fbc->fbc_clip = 0;
1276: fbc->fbc_s = 0;
1277: fbc->fbc_offx = 0;
1278: fbc->fbc_offy = 0;
1279: fbc->fbc_clipminx = 0;
1280: fbc->fbc_clipminy = 0;
1281: fbc->fbc_clipmaxx = sc->sc_width - 1;
1282: fbc->fbc_clipmaxy = sc->sc_height - 1;
1283: fbc->fbc_alu = CG6_ALU_FILL;
1284: fbc->fbc_fg = col;
1285: fbc->fbc_arecty = ys;
1286: fbc->fbc_arectx = xs;
1287: fbc->fbc_arecty = ys + he - 1;
1288: fbc->fbc_arectx = xs + wi - 1;
1289: CG6_DRAW_WAIT(fbc);
1290: }
1291:
1292: void
1293: cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he,
1294: uint32_t fg, uint32_t bg)
1295: {
1296: volatile struct cg6_fbc *fbc=sc->sc_fbc;
1297: CG6_DRAIN(fbc);
1298: fbc->fbc_x0 = x;
1299: fbc->fbc_x1 =x + wi - 1;
1300: fbc->fbc_y0 = y;
1301: fbc->fbc_incx = 0;
1302: fbc->fbc_incy = 1;
1303: fbc->fbc_fg = fg;
1304: fbc->fbc_bg = bg;
1305: fbc->fbc_mode = 0x00140000; /* nosrc, color1 */
1306: fbc->fbc_alu = 0x0800fc30; /* colour expansion, solid bg */
1307: sc->sc_mono_width = wi;
1308: /* now feed the data into the chip */
1309: }
1310:
1311: void
1312: cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data)
1313: {
1314: int i;
1315: uint32_t latch, res = 0, shift;
1316: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1317:
1318: if (sc->sc_mono_width > 32) {
1319: /* ARGH! */
1320: } else
1321: {
1322: shift = 24;
1323: for (i = 0; i < count; i++) {
1324: latch = data[i];
1325: res |= latch << shift;
1326: shift -= 8;
1327: }
1328: fbc->fbc_font = res;
1329: }
1330: }
1331:
1332: void
1333: cgsix_putchar(void *cookie, int row, int col, u_int c, long attr)
1334: {
1.33 macallan 1335: struct rasops_info *ri = cookie;
1.46.4.1 rmind 1336: struct wsdisplay_font *font = PICK_FONT(ri, c);
1.33 macallan 1337: struct vcons_screen *scr = ri->ri_hw;
1338: struct cgsix_softc *sc = scr->scr_cookie;
1339: int inv;
1.23 macallan 1340:
1341: if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&
1342: (col < ri->ri_cols)) {
1343:
1.33 macallan 1344: if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1345:
1.23 macallan 1346: int fg, bg, uc, i;
1347: uint8_t *data;
1348: int x, y, wi, he;
1349: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1350:
1.46.4.1 rmind 1351: wi = font->fontwidth;
1352: he = font->fontheight;
1.23 macallan 1353:
1.46.4.1 rmind 1354: if (!CHAR_IN_FONT(c, font))
1.23 macallan 1355: return;
1.33 macallan 1356: inv = ((attr >> 8) & WSATTR_REVERSE);
1357: if (inv) {
1358: fg = (u_char)ri->ri_devcmap[(attr >> 16) &
1359: 0xff];
1360: bg = (u_char)ri->ri_devcmap[(attr >> 24) &
1361: 0xff];
1362: } else {
1363: bg = (u_char)ri->ri_devcmap[(attr >> 16) &
1364: 0xff];
1365: fg = (u_char)ri->ri_devcmap[(attr >> 24) &
1366: 0xff];
1367: }
1368:
1.23 macallan 1369: x = ri->ri_xorigin + col * wi;
1370: y = ri->ri_yorigin + row * he;
1.33 macallan 1371:
1.23 macallan 1372: if (c == 0x20) {
1373: cgsix_rectfill(sc, x, y, wi, he, bg);
1374: } else {
1.46.4.1 rmind 1375: uc = c - font->firstchar;
1376: data = (uint8_t *)font->data + uc *
1.23 macallan 1377: ri->ri_fontscale;
1378:
1379: cgsix_setup_mono(sc, x, y, wi, 1, fg, bg);
1380: for (i = 0; i < he; i++) {
1.46.4.1 rmind 1381: cgsix_feed_line(sc, font->stride,
1.23 macallan 1382: data);
1.46.4.1 rmind 1383: data += font->stride;
1.23 macallan 1384: }
1385: /* put the chip back to normal */
1386: fbc->fbc_incy = 0;
1387: /* nosrc, color8 */
1388: fbc->fbc_mode = 0x00120000;
1.33 macallan 1389: /*fbc->fbc_mode &= ~CG6_MODE_MASK;
1390: fbc->fbc_mode |= CG6_MODE;*/
1.23 macallan 1391: }
1392: }
1393: }
1394: }
1395:
1396: void
1397: cgsix_cursor(void *cookie, int on, int row, int col)
1398: {
1.33 macallan 1399: struct rasops_info *ri = cookie;
1400: struct vcons_screen *scr = ri->ri_hw;
1401: struct cgsix_softc *sc = scr->scr_cookie;
1.23 macallan 1402: int x, y, wi, he;
1403:
1404: wi = ri->ri_font->fontwidth;
1405: he = ri->ri_font->fontheight;
1406:
1.33 macallan 1407: if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1408: x = ri->ri_ccol * wi + ri->ri_xorigin;
1409: y = ri->ri_crow * he + ri->ri_yorigin;
1410: if (ri->ri_flg & RI_CURSOR) {
1.23 macallan 1411: cg6_invert(sc, x, y, wi, he);
1.33 macallan 1412: ri->ri_flg &= ~RI_CURSOR;
1.23 macallan 1413: }
1.33 macallan 1414: ri->ri_crow = row;
1415: ri->ri_ccol = col;
1416: if (on)
1.23 macallan 1417: {
1.33 macallan 1418: x = ri->ri_ccol * wi + ri->ri_xorigin;
1419: y = ri->ri_crow * he + ri->ri_yorigin;
1.23 macallan 1420: cg6_invert(sc, x, y, wi, he);
1.33 macallan 1421: ri->ri_flg |= RI_CURSOR;
1.23 macallan 1422: }
1.33 macallan 1423: } else
1424: {
1425: ri->ri_crow = row;
1426: ri->ri_ccol = col;
1427: ri->ri_flg &= ~RI_CURSOR;
1.23 macallan 1428: }
1429: }
1430:
1431: void
1432: cgsix_clearscreen(struct cgsix_softc *sc)
1433: {
1.33 macallan 1434: struct rasops_info *ri = &cg6_console_screen.scr_ri;
1.23 macallan 1435:
1436: if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1437: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1438:
1439: CG6_DRAIN(fbc);
1440: fbc->fbc_clip = 0;
1441: fbc->fbc_s = 0;
1442: fbc->fbc_offx = 0;
1443: fbc->fbc_offy = 0;
1444: fbc->fbc_clipminx = 0;
1445: fbc->fbc_clipminy = 0;
1446: fbc->fbc_clipmaxx = ri->ri_width - 1;
1447: fbc->fbc_clipmaxy = ri->ri_height - 1;
1448: fbc->fbc_alu = CG6_ALU_FILL;
1449: fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg];
1450: fbc->fbc_arectx = 0;
1451: fbc->fbc_arecty = 0;
1452: fbc->fbc_arectx = ri->ri_width - 1;
1453: fbc->fbc_arecty = ri->ri_height - 1;
1454: CG6_DRAW_WAIT(fbc);
1455: }
1456: }
1457:
1458: #endif /* NWSDISPLAY > 0 */
1459:
1460: #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE)
1461: void
1462: cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he)
1463: {
1464: volatile struct cg6_fbc *fbc = sc->sc_fbc;
1.33 macallan 1465: struct rasops_info *ri = &cg6_console_screen.scr_ri;
1.23 macallan 1466:
1467: CG6_DRAIN(fbc);
1468: fbc->fbc_clip = 0;
1469: fbc->fbc_s = 0;
1470: fbc->fbc_offx = 0;
1471: fbc->fbc_offy = 0;
1472: fbc->fbc_clipminx = 0;
1473: fbc->fbc_clipminy = 0;
1474: fbc->fbc_clipmaxx = ri->ri_width - 1;
1475: fbc->fbc_clipmaxy = ri->ri_height - 1;
1476: fbc->fbc_alu = CG6_ALU_FLIP;
1477: fbc->fbc_arecty = y;
1478: fbc->fbc_arectx = x;
1.24 macallan 1479: fbc->fbc_arecty = y + he - 1;
1480: fbc->fbc_arectx = x + wi - 1;
1.23 macallan 1481: CG6_DRAW_WAIT(fbc);
1482: }
1483:
1484: #endif
1.33 macallan 1485:
CVSweb <webmaster@jp.NetBSD.org>