Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / sun / cgsix.c
blob1b4301814b2a6ded190ff0ec0185198682a8272d
1 /* $NetBSD: cgsix.c,v 1.45 2009/08/20 02:49:30 macallan Exp $ */
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Paul Kranenburg.
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.
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.
33 * Copyright (c) 1993
34 * The Regents of the University of California. All rights reserved.
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.
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.
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.
53 * 3. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
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.
69 * @(#)cgsix.c 8.4 (Berkeley) 1/21/94
73 * color display (cgsix) driver.
75 * Does not handle interrupts, even though they can occur.
77 * XXX should defer colormap updates to vertical retrace interrupts
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: cgsix.c,v 1.45 2009/08/20 02:49:30 macallan Exp $");
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>
93 #ifdef DEBUG
94 #include <sys/proc.h>
95 #include <sys/syslog.h>
96 #endif
98 #include <uvm/uvm_extern.h>
100 #include <sys/bus.h>
102 #include <dev/sun/fbio.h>
103 #include <dev/sun/fbvar.h>
105 #include <dev/sun/btreg.h>
106 #include <dev/sun/btvar.h>
107 #include <dev/sun/pfourreg.h>
109 #include <dev/wscons/wsconsio.h>
110 #include <dev/wsfont/wsfont.h>
111 #include <dev/rasops/rasops.h>
113 #include "opt_wsemul.h"
114 #include "rasops_glue.h"
116 #include <dev/sun/cgsixreg.h>
117 #include <dev/sun/cgsixvar.h>
119 #include "ioconf.h"
121 static void cg6_unblank(device_t);
122 static void cg6_blank(struct cgsix_softc *, int);
124 dev_type_open(cgsixopen);
125 dev_type_close(cgsixclose);
126 dev_type_ioctl(cgsixioctl);
127 dev_type_mmap(cgsixmmap);
129 const struct cdevsw cgsix_cdevsw = {
130 cgsixopen, cgsixclose, noread, nowrite, cgsixioctl,
131 nostop, notty, nopoll, cgsixmmap, nokqfilter, D_OTHER
134 /* frame buffer generic driver */
135 static struct fbdriver cg6_fbdriver = {
136 cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, nopoll, cgsixmmap,
137 nokqfilter
140 static void cg6_reset (struct cgsix_softc *);
141 static void cg6_loadcmap (struct cgsix_softc *, int, int);
142 static void cg6_loadomap (struct cgsix_softc *);
143 static void cg6_setcursor (struct cgsix_softc *);/* set position */
144 static void cg6_loadcursor (struct cgsix_softc *);/* set shape */
146 #if NWSDISPLAY > 0
147 #ifdef RASTERCONSOLE
148 #error RASTERCONSOLE and wsdisplay are mutually exclusive
149 #endif
151 static void cg6_setup_palette(struct cgsix_softc *);
153 struct wsscreen_descr cgsix_defaultscreen = {
154 "std",
155 0, 0, /* will be filled in -- XXX shouldn't, it's global */
156 NULL, /* textops */
157 8, 16, /* font width/height */
158 WSSCREEN_WSCOLORS, /* capabilities */
159 NULL /* modecookie */
162 static int cgsix_ioctl(void *, void *, u_long, void *, int, struct lwp *);
163 static paddr_t cgsix_mmap(void *, void *, off_t, int);
164 static void cgsix_init_screen(void *, struct vcons_screen *, int, long *);
166 static void cgsix_clearscreen(struct cgsix_softc *);
168 void cgsix_setup_mono(struct cgsix_softc *, int, int, int, int, uint32_t,
169 uint32_t);
170 void cgsix_feed_line(struct cgsix_softc *, int, uint8_t *);
171 void cgsix_rectfill(struct cgsix_softc *, int, int, int, int, uint32_t);
173 int cgsix_putcmap(struct cgsix_softc *, struct wsdisplay_cmap *);
174 int cgsix_getcmap(struct cgsix_softc *, struct wsdisplay_cmap *);
175 void cgsix_putchar(void *, int, int, u_int, long);
176 void cgsix_cursor(void *, int, int, int);
178 struct wsdisplay_accessops cgsix_accessops = {
179 cgsix_ioctl,
180 cgsix_mmap,
181 NULL, /* alloc_screen */
182 NULL, /* free_screen */
183 NULL, /* show_screen */
184 NULL, /* load_font */
185 NULL, /* pollc */
186 NULL /* scroll */
189 const struct wsscreen_descr *_cgsix_scrlist[] = {
190 &cgsix_defaultscreen
193 struct wsscreen_list cgsix_screenlist = {
194 sizeof(_cgsix_scrlist) / sizeof(struct wsscreen_descr *),
195 _cgsix_scrlist
199 extern const u_char rasops_cmap[768];
201 #endif /* NWSDISPLAY > 0 */
203 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE)
204 void cg6_invert(struct cgsix_softc *, int, int, int, int);
206 /* need this for both cases because ri_hw points to it */
207 static struct vcons_screen cg6_console_screen;
208 #endif
210 #ifdef RASTERCONSOLE
211 int cgsix_use_rasterconsole = 1;
212 #endif
215 * cg6 accelerated console routines.
217 * Note that buried in this code in several places is the assumption
218 * that pixels are exactly one byte wide. Since this is cg6-specific
219 * code, this seems safe. This assumption resides in things like the
220 * use of ri_emuwidth without messing around with ri_pelbytes, or the
221 * assumption that ri_font->fontwidth is the right thing to multiply
222 * character-cell counts by to get byte counts.
226 * Magic values for blitter
229 /* Values for the mode register */
230 #define CG6_MODE ( \
231 0x00200000 /* GX_BLIT_SRC */ \
232 | 0x00020000 /* GX_MODE_COLOR8 */ \
233 | 0x00008000 /* GX_DRAW_RENDER */ \
234 | 0x00002000 /* GX_BWRITE0_ENABLE */ \
235 | 0x00001000 /* GX_BWRITE1_DISABLE */ \
236 | 0x00000200 /* GX_BREAD_0 */ \
237 | 0x00000080 /* GX_BDISP_0 */ \
239 #define CG6_MODE_MASK ( \
240 0x00300000 /* GX_BLIT_ALL */ \
241 | 0x00060000 /* GX_MODE_ALL */ \
242 | 0x00018000 /* GX_DRAW_ALL */ \
243 | 0x00006000 /* GX_BWRITE0_ALL */ \
244 | 0x00001800 /* GX_BWRITE1_ALL */ \
245 | 0x00000600 /* GX_BREAD_ALL */ \
246 | 0x00000180 /* GX_BDISP_ALL */ \
249 /* Value for the alu register for screen-to-screen copies */
250 #define CG6_ALU_COPY ( \
251 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
252 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
253 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
254 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
255 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
256 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
257 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
258 | 0x0000cccc /* ALU = src */ \
261 /* Value for the alu register for region fills */
262 #define CG6_ALU_FILL ( \
263 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
264 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
265 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
266 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
267 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
268 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
269 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
270 | 0x0000ff00 /* ALU = fg color */ \
273 /* Value for the alu register for toggling an area */
274 #define CG6_ALU_FLIP ( \
275 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \
276 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \
277 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \
278 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \
279 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \
280 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \
281 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \
282 | 0x00005555 /* ALU = ~dst */ \
286 * Wait for a blit to finish.
287 * 0x8000000 bit: function unknown; 0x20000000 bit: GX_BLT_INPROGRESS
289 #define CG6_BLIT_WAIT(fbc) do { \
290 while (((fbc)->fbc_blit & 0xa0000000) == 0xa0000000) \
291 /*EMPTY*/; \
292 } while (0)
295 * Wait for a drawing operation to finish, or at least get queued.
296 * 0x8000000 bit: function unknown; 0x20000000 bit: GX_FULL
298 #define CG6_DRAW_WAIT(fbc) do { \
299 while (((fbc)->fbc_draw & 0xa0000000) == 0xa0000000) \
300 /*EMPTY*/; \
301 } while (0)
304 * Wait for the whole engine to go idle. This may not matter in our case;
305 * I'm not sure whether blits are actually queued or not. It more likely
306 * is intended for lines and such that do get queued.
307 * 0x10000000 bit: GX_INPROGRESS
309 #define CG6_DRAIN(fbc) do { \
310 while ((fbc)->fbc_s & 0x10000000) \
311 /*EMPTY*/; \
312 } while (0)
314 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE)
315 static void cg6_ras_init(struct cgsix_softc *);
316 static void cg6_ras_copyrows(void *, int, int, int);
317 static void cg6_ras_copycols(void *, int, int, int, int);
318 static void cg6_ras_erasecols(void *, int, int, int, long int);
319 static void cg6_ras_eraserows(void *, int, int, long int);
320 #if defined(RASTERCONSOLE) && defined(CG6_BLIT_CURSOR)
321 static void cg6_ras_do_cursor(struct rasops_info *);
322 #endif
323 static void
324 cg6_ras_init(struct cgsix_softc *sc)
326 volatile struct cg6_fbc *fbc = sc->sc_fbc;
328 CG6_DRAIN(fbc);
329 fbc->fbc_mode &= ~CG6_MODE_MASK;
330 fbc->fbc_mode |= CG6_MODE;
333 static void
334 cg6_ras_copyrows(void *cookie, int src, int dst, int n)
336 struct rasops_info *ri = cookie;
337 struct vcons_screen *scr = ri->ri_hw;
338 struct cgsix_softc *sc = scr->scr_cookie;
339 volatile struct cg6_fbc *fbc = sc->sc_fbc;
341 if (dst == src)
342 return;
343 if (src < 0) {
344 n += src;
345 src = 0;
347 if (src+n > ri->ri_rows)
348 n = ri->ri_rows - src;
349 if (dst < 0) {
350 n += dst;
351 dst = 0;
353 if (dst+n > ri->ri_rows)
354 n = ri->ri_rows - dst;
355 if (n <= 0)
356 return;
357 n *= ri->ri_font->fontheight;
358 src *= ri->ri_font->fontheight;
359 dst *= ri->ri_font->fontheight;
360 fbc->fbc_clip = 0;
361 fbc->fbc_s = 0;
362 fbc->fbc_offx = 0;
363 fbc->fbc_offy = 0;
364 fbc->fbc_clipminx = 0;
365 fbc->fbc_clipminy = 0;
366 fbc->fbc_clipmaxx = ri->ri_width - 1;
367 fbc->fbc_clipmaxy = ri->ri_height - 1;
368 fbc->fbc_alu = CG6_ALU_COPY;
369 fbc->fbc_x0 = ri->ri_xorigin;
370 fbc->fbc_y0 = ri->ri_yorigin + src;
371 fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
372 fbc->fbc_y1 = ri->ri_yorigin + src + n - 1;
373 fbc->fbc_x2 = ri->ri_xorigin;
374 fbc->fbc_y2 = ri->ri_yorigin + dst;
375 fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1;
376 fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1;
377 CG6_BLIT_WAIT(fbc);
378 CG6_DRAIN(fbc);
381 static void
382 cg6_ras_copycols(void *cookie, int row, int src, int dst, int n)
384 struct rasops_info *ri = cookie;
385 struct vcons_screen *scr = ri->ri_hw;
386 struct cgsix_softc *sc = scr->scr_cookie;
387 volatile struct cg6_fbc *fbc = sc->sc_fbc;
389 if (dst == src)
390 return;
391 if ((row < 0) || (row >= ri->ri_rows))
392 return;
393 if (src < 0) {
394 n += src;
395 src = 0;
397 if (src+n > ri->ri_cols)
398 n = ri->ri_cols - src;
399 if (dst < 0) {
400 n += dst;
401 dst = 0;
403 if (dst+n > ri->ri_cols)
404 n = ri->ri_cols - dst;
405 if (n <= 0)
406 return;
407 n *= ri->ri_font->fontwidth;
408 src *= ri->ri_font->fontwidth;
409 dst *= ri->ri_font->fontwidth;
410 row *= ri->ri_font->fontheight;
411 fbc->fbc_clip = 0;
412 fbc->fbc_s = 0;
413 fbc->fbc_offx = 0;
414 fbc->fbc_offy = 0;
415 fbc->fbc_clipminx = 0;
416 fbc->fbc_clipminy = 0;
417 fbc->fbc_clipmaxx = ri->ri_width - 1;
418 fbc->fbc_clipmaxy = ri->ri_height - 1;
419 fbc->fbc_alu = CG6_ALU_COPY;
420 fbc->fbc_x0 = ri->ri_xorigin + src;
421 fbc->fbc_y0 = ri->ri_yorigin + row;
422 fbc->fbc_x1 = ri->ri_xorigin + src + n - 1;
423 fbc->fbc_y1 = ri->ri_yorigin + row +
424 ri->ri_font->fontheight - 1;
425 fbc->fbc_x2 = ri->ri_xorigin + dst;
426 fbc->fbc_y2 = ri->ri_yorigin + row;
427 fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1;
428 fbc->fbc_y3 = ri->ri_yorigin + row +
429 ri->ri_font->fontheight - 1;
430 CG6_BLIT_WAIT(fbc);
431 CG6_DRAIN(fbc);
434 static void
435 cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr)
437 struct rasops_info *ri = cookie;
438 struct vcons_screen *scr = ri->ri_hw;
439 struct cgsix_softc *sc = scr->scr_cookie;
440 volatile struct cg6_fbc *fbc = sc->sc_fbc;
442 if ((row < 0) || (row >= ri->ri_rows))
443 return;
444 if (col < 0) {
445 n += col;
446 col = 0;
448 if (col+n > ri->ri_cols)
449 n = ri->ri_cols - col;
450 if (n <= 0)
451 return;
452 n *= ri->ri_font->fontwidth;
453 col *= ri->ri_font->fontwidth;
454 row *= ri->ri_font->fontheight;
455 fbc->fbc_clip = 0;
456 fbc->fbc_s = 0;
457 fbc->fbc_offx = 0;
458 fbc->fbc_offy = 0;
459 fbc->fbc_clipminx = 0;
460 fbc->fbc_clipminy = 0;
461 fbc->fbc_clipmaxx = ri->ri_width - 1;
462 fbc->fbc_clipmaxy = ri->ri_height - 1;
463 fbc->fbc_alu = CG6_ALU_FILL;
464 fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff];
465 fbc->fbc_arecty = ri->ri_yorigin + row;
466 fbc->fbc_arectx = ri->ri_xorigin + col;
467 fbc->fbc_arecty = ri->ri_yorigin + row +
468 ri->ri_font->fontheight - 1;
469 fbc->fbc_arectx = ri->ri_xorigin + col + n - 1;
470 CG6_DRAW_WAIT(fbc);
471 CG6_DRAIN(fbc);
474 static void
475 cg6_ras_eraserows(void *cookie, int row, int n, long int attr)
477 struct rasops_info *ri = cookie;
478 struct vcons_screen *scr = ri->ri_hw;
479 struct cgsix_softc *sc = scr->scr_cookie;
480 volatile struct cg6_fbc *fbc = sc->sc_fbc;
482 if (row < 0) {
483 n += row;
484 row = 0;
486 if (row+n > ri->ri_rows)
487 n = ri->ri_rows - row;
488 if (n <= 0)
489 return;
490 fbc->fbc_clip = 0;
491 fbc->fbc_s = 0;
492 fbc->fbc_offx = 0;
493 fbc->fbc_offy = 0;
494 fbc->fbc_clipminx = 0;
495 fbc->fbc_clipminy = 0;
496 fbc->fbc_clipmaxx = ri->ri_width - 1;
497 fbc->fbc_clipmaxy = ri->ri_height - 1;
498 fbc->fbc_alu = CG6_ALU_FILL;
499 fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff];
500 if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
501 fbc->fbc_arecty = 0;
502 fbc->fbc_arectx = 0;
503 fbc->fbc_arecty = ri->ri_height - 1;
504 fbc->fbc_arectx = ri->ri_width - 1;
505 } else {
506 row *= ri->ri_font->fontheight;
507 fbc->fbc_arecty = ri->ri_yorigin + row;
508 fbc->fbc_arectx = ri->ri_xorigin;
509 fbc->fbc_arecty = ri->ri_yorigin + row +
510 (n * ri->ri_font->fontheight) - 1;
511 fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1;
513 CG6_DRAW_WAIT(fbc);
514 CG6_DRAIN(fbc);
517 #if defined(RASTERCONSOLE) && defined(CG6_BLIT_CURSOR)
519 * Really want something more like fg^bg here, but that would be more
520 * or less impossible to migrate to colors. So we hope there's
521 * something not too inappropriate in the colormap...besides, it's what
522 * the non-accelerated code did. :-)
524 static void
525 cg6_ras_do_cursor(struct rasops_info *ri)
527 struct vcons_screen *scr = ri->ri_hw;
528 struct cgsix_softc *sc = scr->cookie;
529 int row, col;
531 row = ri->ri_crow * ri->ri_font->fontheight;
532 col = ri->ri_ccol * ri->ri_font->fontwidth;
533 cg6_invert(sc, ri->ri_xorigin + col,ri->ri_yorigin +
534 row, ri->ri_font->fontwidth, ri->ri_font->fontheight);
536 #endif /* RASTERCONSOLE */
538 #endif /* (NWSDISPLAY > 0) || defined(RASTERCONSOLE) */
540 void
541 cg6attach(struct cgsix_softc *sc, const char *name, int isconsole)
543 struct fbdevice *fb = &sc->sc_fb;
544 #if NWSDISPLAY > 0
545 struct wsemuldisplaydev_attach_args aa;
546 struct rasops_info *ri = &cg6_console_screen.scr_ri;
547 unsigned long defattr;
548 #endif
550 fb->fb_driver = &cg6_fbdriver;
552 /* Don't have to map the pfour register on the cgsix. */
553 fb->fb_pfour = NULL;
555 fb->fb_type.fb_cmsize = 256;
556 fb->fb_type.fb_size = sc->sc_ramsize;
557 /*fb->fb_type.fb_height * fb->fb_linebytes;*/
558 printf(": %s, %d x %d", name,
559 fb->fb_type.fb_width, fb->fb_type.fb_height);
560 if(sc->sc_fhc) {
561 sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) &
562 (FHC_REV_MASK >> FHC_REV_SHIFT);
563 } else
564 sc->sc_fhcrev=-1;
565 printf(", rev %d", sc->sc_fhcrev);
567 /* reset cursor & frame buffer controls */
568 cg6_reset(sc);
570 /* enable video */
571 sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
573 if (isconsole) {
574 printf(" (console)");
576 /* this is the old console attachment stuff - sparc still needs it */
577 #ifdef RASTERCONSOLE
578 if (cgsix_use_rasterconsole) {
579 fbrcons_init(&sc->sc_fb);
581 * we don't use the screen struct but keep it here to
582 * avoid ugliness in the cg6_ras_* functions
584 cg6_console_screen.scr_cookie = sc;
585 sc->sc_fb.fb_rinfo.ri_hw = &cg6_console_screen;
586 sc->sc_fb.fb_rinfo.ri_ops.copyrows = cg6_ras_copyrows;
587 sc->sc_fb.fb_rinfo.ri_ops.copycols = cg6_ras_copycols;
588 sc->sc_fb.fb_rinfo.ri_ops.erasecols = cg6_ras_erasecols;
589 sc->sc_fb.fb_rinfo.ri_ops.eraserows = cg6_ras_eraserows;
590 #ifdef CG6_BLIT_CURSOR
591 sc->sc_fb.fb_rinfo.ri_do_cursor = cg6_ras_do_cursor;
592 #endif
593 cg6_ras_init(sc);
595 #endif
597 printf("\n");
599 fb_attach(&sc->sc_fb, isconsole);
600 sc->sc_width = fb->fb_type.fb_width;
601 sc->sc_stride = fb->fb_type.fb_width;
602 sc->sc_height = fb->fb_type.fb_height;
604 printf("%s: framebuffer size: %d MB\n", device_xname(sc->sc_dev),
605 sc->sc_ramsize >> 20);
607 #if NWSDISPLAY
608 /* setup rasops and so on for wsdisplay */
609 memcpy(sc->sc_default_cmap, rasops_cmap, 768);
610 wsfont_init();
611 cg6_ras_init(sc);
612 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
613 sc->sc_bg = WS_DEFAULT_BG;
615 vcons_init(&sc->vd, sc, &cgsix_defaultscreen, &cgsix_accessops);
616 sc->vd.init_screen = cgsix_init_screen;
618 cg6_setup_palette(sc);
619 cgsix_clearscreen(sc);
621 if(isconsole) {
622 /* we mess with cg6_console_screen only once */
623 vcons_init_screen(&sc->vd, &cg6_console_screen, 1,
624 &defattr);
625 cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
627 cgsix_defaultscreen.textops = &ri->ri_ops;
628 cgsix_defaultscreen.capabilities = ri->ri_caps;
629 cgsix_defaultscreen.nrows = ri->ri_rows;
630 cgsix_defaultscreen.ncols = ri->ri_cols;
631 SCREEN_VISIBLE(&cg6_console_screen);
632 sc->vd.active = &cg6_console_screen;
633 wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr);
634 vcons_replay_msgbuf(&cg6_console_screen);
635 } else {
637 * we're not the console so we just clear the screen and don't
638 * set up any sort of text display
640 if (cgsix_defaultscreen.textops == NULL) {
642 * ugly, but...
643 * we want the console settings to win, so we only
644 * touch anything when we find an untouched screen
645 * definition. In this case we fill it from fb to
646 * avoid problems in case no cgsix is the console
648 ri = &sc->sc_fb.fb_rinfo;
649 cgsix_defaultscreen.textops = &ri->ri_ops;
650 cgsix_defaultscreen.capabilities = ri->ri_caps;
651 cgsix_defaultscreen.nrows = ri->ri_rows;
652 cgsix_defaultscreen.ncols = ri->ri_cols;
656 aa.scrdata = &cgsix_screenlist;
657 aa.console = isconsole;
658 aa.accessops = &cgsix_accessops;
659 aa.accesscookie = &sc->vd;
660 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
661 #else
662 bt_initcmap(&sc->sc_cmap, 256);
663 cg6_loadcmap(sc, 0, 256);
665 #endif
670 cgsixopen(dev_t dev, int flags, int mode, struct lwp *l)
672 int unit = minor(dev);
674 if (device_lookup(&cgsix_cd, unit) == NULL)
675 return ENXIO;
676 return 0;
680 cgsixclose(dev_t dev, int flags, int mode, struct lwp *l)
682 device_t dv = device_lookup(&cgsix_cd, minor(dev));
683 struct cgsix_softc *sc = device_private(dv);
685 cg6_reset(sc);
687 #if NWSDISPLAY > 0
688 cg6_setup_palette(sc);
689 #else
690 /* (re-)initialize the default color map */
691 bt_initcmap(&sc->sc_cmap, 256);
693 cg6_loadcmap(sc, 0, 256);
694 #endif
695 return 0;
699 cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
701 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev));
702 union cursor_cmap tcm;
703 uint32_t image[32], mask[32];
704 u_int count;
705 int v, error;
707 #ifdef CGSIX_DEBUG
708 printf("cgsixioctl(%ld)\n",cmd);
709 #endif
711 switch (cmd) {
713 case FBIOGTYPE:
714 *(struct fbtype *)data = sc->sc_fb.fb_type;
715 break;
717 case FBIOGATTR:
718 #define fba ((struct fbgattr *)data)
719 fba->real_type = sc->sc_fb.fb_type.fb_type;
720 fba->owner = 0; /* XXX ??? */
721 fba->fbtype = sc->sc_fb.fb_type;
722 fba->sattr.flags = 0;
723 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
724 fba->sattr.dev_specific[0] = -1;
725 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
726 fba->emu_types[1] = -1;
727 #undef fba
728 break;
730 case FBIOGETCMAP:
731 #define p ((struct fbcmap *)data)
732 return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
734 case FBIOPUTCMAP:
735 /* copy to software map */
736 error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
737 if (error)
738 return error;
739 /* now blast them into the chip */
740 /* XXX should use retrace interrupt */
741 cg6_loadcmap(sc, p->index, p->count);
742 #undef p
743 break;
745 case FBIOGVIDEO:
746 *(int *)data = sc->sc_blanked;
747 break;
749 case FBIOSVIDEO:
750 cg6_blank(sc, !(*(int *)data));
751 break;
753 /* these are for both FBIOSCURSOR and FBIOGCURSOR */
754 #define p ((struct fbcursor *)data)
755 #define cc (&sc->sc_cursor)
757 case FBIOGCURSOR:
758 /* do not quite want everything here... */
759 p->set = FB_CUR_SETALL; /* close enough, anyway */
760 p->enable = cc->cc_enable;
761 p->pos = cc->cc_pos;
762 p->hot = cc->cc_hot;
763 p->size = cc->cc_size;
765 /* begin ugh ... can we lose some of this crap?? */
766 if (p->image != NULL) {
767 count = cc->cc_size.y * 32 / NBBY;
768 error = copyout(cc->cc_bits[1], p->image, count);
769 if (error)
770 return error;
771 error = copyout(cc->cc_bits[0], p->mask, count);
772 if (error)
773 return error;
775 if (p->cmap.red != NULL) {
776 error = bt_getcmap(&p->cmap,
777 (union bt_cmap *)&cc->cc_color, 2, 1);
778 if (error)
779 return error;
780 } else {
781 p->cmap.index = 0;
782 p->cmap.count = 2;
784 /* end ugh */
785 break;
787 case FBIOSCURSOR:
789 * For setcmap and setshape, verify parameters, so that
790 * we do not get halfway through an update and then crap
791 * out with the software state screwed up.
793 v = p->set;
794 if (v & FB_CUR_SETCMAP) {
796 * This use of a temporary copy of the cursor
797 * colormap is not terribly efficient, but these
798 * copies are small (8 bytes)...
800 tcm = cc->cc_color;
801 error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2,
803 if (error)
804 return error;
806 if (v & FB_CUR_SETSHAPE) {
807 if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32)
808 return EINVAL;
809 count = p->size.y * 32 / NBBY;
810 error = copyin(p->image, image, count);
811 if (error)
812 return error;
813 error = copyin(p->mask, mask, count);
814 if (error)
815 return error;
818 /* parameters are OK; do it */
819 if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) {
820 if (v & FB_CUR_SETCUR)
821 cc->cc_enable = p->enable;
822 if (v & FB_CUR_SETPOS)
823 cc->cc_pos = p->pos;
824 if (v & FB_CUR_SETHOT)
825 cc->cc_hot = p->hot;
826 cg6_setcursor(sc);
828 if (v & FB_CUR_SETCMAP) {
829 cc->cc_color = tcm;
830 cg6_loadomap(sc); /* XXX defer to vertical retrace */
832 if (v & FB_CUR_SETSHAPE) {
833 cc->cc_size = p->size;
834 count = p->size.y * 32 / NBBY;
835 memset(cc->cc_bits, 0, sizeof cc->cc_bits);
836 memcpy(cc->cc_bits[1], image, count);
837 memcpy(cc->cc_bits[0], mask, count);
838 cg6_loadcursor(sc);
840 break;
842 #undef p
843 #undef cc
845 case FBIOGCURPOS:
846 *(struct fbcurpos *)data = sc->sc_cursor.cc_pos;
847 break;
849 case FBIOSCURPOS:
850 sc->sc_cursor.cc_pos = *(struct fbcurpos *)data;
851 cg6_setcursor(sc);
852 break;
854 case FBIOGCURMAX:
855 /* max cursor size is 32x32 */
856 ((struct fbcurpos *)data)->x = 32;
857 ((struct fbcurpos *)data)->y = 32;
858 break;
860 default:
861 #ifdef DEBUG
862 log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd,
863 l->l_proc->p_comm, l->l_proc->p_pid);
864 #endif
865 return ENOTTY;
867 return 0;
871 * Clean up hardware state (e.g., after bootup or after X crashes).
873 static void
874 cg6_reset(struct cgsix_softc *sc)
876 volatile struct cg6_tec_xxx *tec;
877 int fhc;
878 volatile struct bt_regs *bt;
880 /* hide the cursor, just in case */
881 sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF;
883 /* turn off frobs in transform engine (makes X11 work) */
884 tec = sc->sc_tec;
885 tec->tec_mv = 0;
886 tec->tec_clip = 0;
887 tec->tec_vdc = 0;
889 /* take care of hardware bugs in old revisions */
890 if (sc->sc_fhcrev < 5) {
892 * Keep current resolution; set CPU to 68020, set test
893 * window (size 1Kx1K), and for rev 1, disable dest cache.
895 fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 |
896 FHC_TEST |
897 (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT);
898 if (sc->sc_fhcrev < 2)
899 fhc |= FHC_DST_DISABLE;
900 *sc->sc_fhc = fhc;
903 /* Enable cursor in Brooktree DAC. */
904 bt = sc->sc_bt;
905 bt->bt_addr = 0x06 << 24;
906 bt->bt_ctrl |= 0x03 << 24;
909 static void
910 cg6_setcursor(struct cgsix_softc *sc)
913 /* we need to subtract the hot-spot value here */
914 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f)
915 sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ?
916 ((COORD(x) << 16) | (COORD(y) & 0xffff)) :
917 (THC_CURSOFF << 16) | THC_CURSOFF;
918 #undef COORD
921 static void
922 cg6_loadcursor(struct cgsix_softc *sc)
924 volatile struct cg6_thc *thc;
925 u_int edgemask, m;
926 int i;
929 * Keep the top size.x bits. Here we *throw out* the top
930 * size.x bits from an all-one-bits word, introducing zeros in
931 * the top size.x bits, then invert all the bits to get what
932 * we really wanted as our mask. But this fails if size.x is
933 * 32---a sparc uses only the low 5 bits of the shift count---
934 * so we have to special case that.
936 edgemask = ~0;
937 if (sc->sc_cursor.cc_size.x < 32)
938 edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x);
939 thc = sc->sc_thc;
940 for (i = 0; i < 32; i++) {
941 m = sc->sc_cursor.cc_bits[0][i] & edgemask;
942 thc->thc_cursmask[i] = m;
943 thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i];
948 * Load a subset of the current (new) colormap into the color DAC.
950 static void
951 cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors)
953 volatile struct bt_regs *bt;
954 u_int *ip, i;
955 int count;
957 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */
958 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
959 bt = sc->sc_bt;
960 bt->bt_addr = BT_D4M4(start) << 24;
961 while (--count >= 0) {
962 i = *ip++;
963 /* hardware that makes one want to pound boards with hammers */
964 bt->bt_cmap = i;
965 bt->bt_cmap = i << 8;
966 bt->bt_cmap = i << 16;
967 bt->bt_cmap = i << 24;
972 * Load the cursor (overlay `foreground' and `background') colors.
974 static void
975 cg6_loadomap(struct cgsix_softc *sc)
977 volatile struct bt_regs *bt;
978 u_int i;
980 bt = sc->sc_bt;
981 bt->bt_addr = 0x01 << 24; /* set background color */
982 i = sc->sc_cursor.cc_color.cm_chip[0];
983 bt->bt_omap = i; /* R */
984 bt->bt_omap = i << 8; /* G */
985 bt->bt_omap = i << 16; /* B */
987 bt->bt_addr = 0x03 << 24; /* set foreground color */
988 bt->bt_omap = i << 24; /* R */
989 i = sc->sc_cursor.cc_color.cm_chip[1];
990 bt->bt_omap = i; /* G */
991 bt->bt_omap = i << 8; /* B */
994 /* blank or unblank the screen */
995 static void
996 cg6_blank(struct cgsix_softc *sc, int flag)
999 if (sc->sc_blanked != flag) {
1000 sc->sc_blanked = flag;
1001 if (flag) {
1002 sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN;
1003 } else {
1004 sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
1010 * this is called on panic or ddb entry - force the console to the front, reset
1011 * the colour map and enable drawing so we actually see the message even when X
1012 * is running
1014 static void
1015 cg6_unblank(device_t dev)
1017 struct cgsix_softc *sc = device_private(dev);
1019 cg6_blank(sc, 0);
1022 /* XXX the following should be moved to a "user interface" header */
1024 * Base addresses at which users can mmap() the various pieces of a cg6.
1025 * Note that although the Brooktree color registers do not occupy 8K,
1026 * the X server dies if we do not allow it to map 8K there (it just maps
1027 * from 0x70000000 forwards, as a contiguous chunk).
1029 #define CG6_USER_FBC 0x70000000
1030 #define CG6_USER_TEC 0x70001000
1031 #define CG6_USER_BTREGS 0x70002000
1032 #define CG6_USER_FHC 0x70004000
1033 #define CG6_USER_THC 0x70005000
1034 #define CG6_USER_ROM 0x70006000
1035 #define CG6_USER_RAM 0x70016000
1036 #define CG6_USER_DHC 0x80000000
1038 struct mmo {
1039 u_long mo_uaddr; /* user (virtual) address */
1040 u_long mo_size; /* size, or 0 for video ram size */
1041 u_long mo_physoff; /* offset from sc_physadr */
1045 * Return the address that would map the given device at the given
1046 * offset, allowing for the given protection, or return -1 for error.
1048 * XXX needs testing against `demanding' applications (e.g., aviator)
1050 paddr_t
1051 cgsixmmap(dev_t dev, off_t off, int prot)
1053 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev));
1054 struct mmo *mo;
1055 u_int u, sz;
1056 static struct mmo mmo[] = {
1057 { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET },
1059 /* do not actually know how big most of these are! */
1060 { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET },
1061 { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET },
1062 { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET },
1063 { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET },
1064 { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET },
1065 { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET },
1066 { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET },
1068 #define NMMO (sizeof mmo / sizeof *mmo)
1070 if (off & PGOFSET)
1071 panic("cgsixmmap");
1074 * Entries with size 0 map video RAM (i.e., the size in fb data).
1076 * Since we work in pages, the fact that the map offset table's
1077 * sizes are sometimes bizarre (e.g., 1) is effectively ignored:
1078 * one byte is as good as one page.
1080 for (mo = mmo; mo < &mmo[NMMO]; mo++) {
1081 if ((u_long)off < mo->mo_uaddr)
1082 continue;
1083 u = off - mo->mo_uaddr;
1084 sz = mo->mo_size ? mo->mo_size :
1085 sc->sc_ramsize/*sc_fb.fb_type.fb_size*/;
1086 if (u < sz) {
1087 return (bus_space_mmap(sc->sc_bustag,
1088 sc->sc_paddr, u+mo->mo_physoff,
1089 prot, BUS_SPACE_MAP_LINEAR));
1093 #ifdef DEBUG
1095 struct proc *p = curlwp->l_proc; /* XXX */
1096 log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n",
1097 (long long)off, p->p_comm, p->p_pid);
1099 #endif
1100 return -1; /* not a user-map offset */
1103 #if NWSDISPLAY > 0
1105 static void
1106 cg6_setup_palette(struct cgsix_softc *sc)
1108 int i, j;
1110 j = 0;
1111 for (i = 0; i < 256; i++) {
1112 sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j];
1113 j++;
1114 sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j];
1115 j++;
1116 sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j];
1117 j++;
1119 cg6_loadcmap(sc, 0, 256);
1123 cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
1124 struct lwp *l)
1126 /* we'll probably need to add more stuff here */
1127 struct vcons_data *vd = v;
1128 struct cgsix_softc *sc = vd->cookie;
1129 struct wsdisplay_fbinfo *wdf;
1130 struct rasops_info *ri = &sc->sc_fb.fb_rinfo;
1131 struct vcons_screen *ms = sc->vd.active;
1132 #ifdef CGSIX_DEBUG
1133 printf("cgsix_ioctl(%ld)\n",cmd);
1134 #endif
1135 switch (cmd) {
1136 case WSDISPLAYIO_GTYPE:
1137 *(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
1138 return 0;
1139 case WSDISPLAYIO_GINFO:
1140 wdf = (void *)data;
1141 wdf->height = ri->ri_height;
1142 wdf->width = ri->ri_width;
1143 wdf->depth = ri->ri_depth;
1144 wdf->cmsize = 256;
1145 return 0;
1147 case WSDISPLAYIO_GETCMAP:
1148 return cgsix_getcmap(sc,
1149 (struct wsdisplay_cmap *)data);
1150 case WSDISPLAYIO_PUTCMAP:
1151 return cgsix_putcmap(sc,
1152 (struct wsdisplay_cmap *)data);
1154 case WSDISPLAYIO_SMODE:
1156 int new_mode = *(int*)data;
1157 if (new_mode != sc->sc_mode)
1159 sc->sc_mode = new_mode;
1160 if(new_mode == WSDISPLAYIO_MODE_EMUL)
1162 cg6_reset(sc);
1163 cg6_ras_init(sc);
1164 cg6_setup_palette(sc);
1165 vcons_redraw_screen(ms);
1170 return EPASSTHROUGH;
1173 paddr_t
1174 cgsix_mmap(void *v, void *vs, off_t offset, int prot)
1176 struct vcons_data *vd = v;
1177 struct cgsix_softc *sc = vd->cookie;
1179 if(offset<sc->sc_ramsize) {
1180 return bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
1181 CGSIX_RAM_OFFSET+offset, prot, BUS_SPACE_MAP_LINEAR);
1183 /* I'm not at all sure this is the right thing to do */
1184 return cgsixmmap(0, offset, prot); /* assume minor dev 0 for now */
1188 cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm)
1190 u_int index = cm->index;
1191 u_int count = cm->count;
1192 int error,i;
1193 if (index >= 256 || count > 256 || index + count > 256)
1194 return EINVAL;
1196 for (i = 0; i < count; i++)
1198 error = copyin(&cm->red[i],
1199 &sc->sc_cmap.cm_map[index + i][0], 1);
1200 if (error)
1201 return error;
1202 error = copyin(&cm->green[i],
1203 &sc->sc_cmap.cm_map[index + i][1],
1205 if (error)
1206 return error;
1207 error = copyin(&cm->blue[i],
1208 &sc->sc_cmap.cm_map[index + i][2], 1);
1209 if (error)
1210 return error;
1212 cg6_loadcmap(sc, index, count);
1214 return 0;
1218 cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm)
1220 u_int index = cm->index;
1221 u_int count = cm->count;
1222 int error,i;
1224 if (index >= 256 || count > 256 || index + count > 256)
1225 return EINVAL;
1227 for (i = 0; i < count; i++)
1229 error = copyout(&sc->sc_cmap.cm_map[index + i][0],
1230 &cm->red[i], 1);
1231 if (error)
1232 return error;
1233 error = copyout(&sc->sc_cmap.cm_map[index + i][1],
1234 &cm->green[i], 1);
1235 if (error)
1236 return error;
1237 error = copyout(&sc->sc_cmap.cm_map[index + i][2],
1238 &cm->blue[i], 1);
1239 if (error)
1240 return error;
1243 return 0;
1246 void
1247 cgsix_init_screen(void *cookie, struct vcons_screen *scr,
1248 int existing, long *defattr)
1250 struct cgsix_softc *sc = cookie;
1251 struct rasops_info *ri = &scr->scr_ri;
1253 ri->ri_depth = 8;
1254 ri->ri_width = sc->sc_width;
1255 ri->ri_height = sc->sc_height;
1256 ri->ri_stride = sc->sc_stride;
1257 ri->ri_flg = RI_CENTER;
1259 ri->ri_bits = sc->sc_fb.fb_pixels;
1261 /* We need unaccelerated initial screen clear on old revisions */
1262 if (sc->sc_fhcrev < 2)
1263 memset(sc->sc_fb.fb_pixels, (*defattr >> 16) & 0xff,
1264 sc->sc_stride * sc->sc_height);
1265 rasops_init(ri, sc->sc_height/8, sc->sc_width/8);
1266 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1267 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
1268 sc->sc_width / ri->ri_font->fontwidth);
1270 /* enable acceleration */
1271 ri->ri_hw = scr;
1272 ri->ri_ops.copyrows = cg6_ras_copyrows;
1273 ri->ri_ops.copycols = cg6_ras_copycols;
1274 ri->ri_ops.eraserows = cg6_ras_eraserows;
1275 ri->ri_ops.erasecols = cg6_ras_erasecols;
1276 ri->ri_ops.cursor = cgsix_cursor;
1277 ri->ri_ops.putchar = cgsix_putchar;
1280 void
1281 cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he,
1282 uint32_t col)
1284 volatile struct cg6_fbc *fbc = sc->sc_fbc;
1286 CG6_DRAIN(fbc);
1287 fbc->fbc_clip = 0;
1288 fbc->fbc_s = 0;
1289 fbc->fbc_offx = 0;
1290 fbc->fbc_offy = 0;
1291 fbc->fbc_clipminx = 0;
1292 fbc->fbc_clipminy = 0;
1293 fbc->fbc_clipmaxx = sc->sc_width - 1;
1294 fbc->fbc_clipmaxy = sc->sc_height - 1;
1295 fbc->fbc_alu = CG6_ALU_FILL;
1296 fbc->fbc_fg = col;
1297 fbc->fbc_arecty = ys;
1298 fbc->fbc_arectx = xs;
1299 fbc->fbc_arecty = ys + he - 1;
1300 fbc->fbc_arectx = xs + wi - 1;
1301 CG6_DRAW_WAIT(fbc);
1304 void
1305 cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he,
1306 uint32_t fg, uint32_t bg)
1308 volatile struct cg6_fbc *fbc=sc->sc_fbc;
1309 CG6_DRAIN(fbc);
1310 fbc->fbc_x0 = x;
1311 fbc->fbc_x1 =x + wi - 1;
1312 fbc->fbc_y0 = y;
1313 fbc->fbc_incx = 0;
1314 fbc->fbc_incy = 1;
1315 fbc->fbc_fg = fg;
1316 fbc->fbc_bg = bg;
1317 fbc->fbc_mode = 0x00140000; /* nosrc, color1 */
1318 fbc->fbc_alu = 0x0800fc30; /* colour expansion, solid bg */
1319 sc->sc_mono_width = wi;
1320 /* now feed the data into the chip */
1323 void
1324 cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data)
1326 int i;
1327 uint32_t latch, res = 0, shift;
1328 volatile struct cg6_fbc *fbc = sc->sc_fbc;
1330 if (sc->sc_mono_width > 32) {
1331 /* ARGH! */
1332 } else
1334 shift = 24;
1335 for (i = 0; i < count; i++) {
1336 latch = data[i];
1337 res |= latch << shift;
1338 shift -= 8;
1340 fbc->fbc_font = res;
1344 void
1345 cgsix_putchar(void *cookie, int row, int col, u_int c, long attr)
1347 struct rasops_info *ri = cookie;
1348 struct vcons_screen *scr = ri->ri_hw;
1349 struct cgsix_softc *sc = scr->scr_cookie;
1350 int inv;
1352 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&
1353 (col < ri->ri_cols)) {
1355 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1357 int fg, bg, uc, i;
1358 uint8_t *data;
1359 int x, y, wi, he;
1360 volatile struct cg6_fbc *fbc = sc->sc_fbc;
1362 wi = ri->ri_font->fontwidth;
1363 he = ri->ri_font->fontheight;
1365 if (!CHAR_IN_FONT(c, ri->ri_font))
1366 return;
1367 inv = ((attr >> 8) & WSATTR_REVERSE);
1368 if (inv) {
1369 fg = (u_char)ri->ri_devcmap[(attr >> 16) &
1370 0xff];
1371 bg = (u_char)ri->ri_devcmap[(attr >> 24) &
1372 0xff];
1373 } else {
1374 bg = (u_char)ri->ri_devcmap[(attr >> 16) &
1375 0xff];
1376 fg = (u_char)ri->ri_devcmap[(attr >> 24) &
1377 0xff];
1380 x = ri->ri_xorigin + col * wi;
1381 y = ri->ri_yorigin + row * he;
1383 if (c == 0x20) {
1384 cgsix_rectfill(sc, x, y, wi, he, bg);
1385 } else {
1386 uc = c-ri->ri_font->firstchar;
1387 data = (uint8_t *)ri->ri_font->data + uc *
1388 ri->ri_fontscale;
1390 cgsix_setup_mono(sc, x, y, wi, 1, fg, bg);
1391 for (i = 0; i < he; i++) {
1392 cgsix_feed_line(sc, ri->ri_font->stride,
1393 data);
1394 data += ri->ri_font->stride;
1396 /* put the chip back to normal */
1397 fbc->fbc_incy = 0;
1398 /* nosrc, color8 */
1399 fbc->fbc_mode = 0x00120000;
1400 /*fbc->fbc_mode &= ~CG6_MODE_MASK;
1401 fbc->fbc_mode |= CG6_MODE;*/
1407 void
1408 cgsix_cursor(void *cookie, int on, int row, int col)
1410 struct rasops_info *ri = cookie;
1411 struct vcons_screen *scr = ri->ri_hw;
1412 struct cgsix_softc *sc = scr->scr_cookie;
1413 int x, y, wi, he;
1415 wi = ri->ri_font->fontwidth;
1416 he = ri->ri_font->fontheight;
1418 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1419 x = ri->ri_ccol * wi + ri->ri_xorigin;
1420 y = ri->ri_crow * he + ri->ri_yorigin;
1421 if (ri->ri_flg & RI_CURSOR) {
1422 cg6_invert(sc, x, y, wi, he);
1423 ri->ri_flg &= ~RI_CURSOR;
1425 ri->ri_crow = row;
1426 ri->ri_ccol = col;
1427 if (on)
1429 x = ri->ri_ccol * wi + ri->ri_xorigin;
1430 y = ri->ri_crow * he + ri->ri_yorigin;
1431 cg6_invert(sc, x, y, wi, he);
1432 ri->ri_flg |= RI_CURSOR;
1434 } else
1436 ri->ri_crow = row;
1437 ri->ri_ccol = col;
1438 ri->ri_flg &= ~RI_CURSOR;
1442 void
1443 cgsix_clearscreen(struct cgsix_softc *sc)
1445 struct rasops_info *ri = &cg6_console_screen.scr_ri;
1447 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1448 volatile struct cg6_fbc *fbc = sc->sc_fbc;
1450 CG6_DRAIN(fbc);
1451 fbc->fbc_clip = 0;
1452 fbc->fbc_s = 0;
1453 fbc->fbc_offx = 0;
1454 fbc->fbc_offy = 0;
1455 fbc->fbc_clipminx = 0;
1456 fbc->fbc_clipminy = 0;
1457 fbc->fbc_clipmaxx = ri->ri_width - 1;
1458 fbc->fbc_clipmaxy = ri->ri_height - 1;
1459 fbc->fbc_alu = CG6_ALU_FILL;
1460 fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg];
1461 fbc->fbc_arectx = 0;
1462 fbc->fbc_arecty = 0;
1463 fbc->fbc_arectx = ri->ri_width - 1;
1464 fbc->fbc_arecty = ri->ri_height - 1;
1465 CG6_DRAW_WAIT(fbc);
1469 #endif /* NWSDISPLAY > 0 */
1471 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE)
1472 void
1473 cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he)
1475 volatile struct cg6_fbc *fbc = sc->sc_fbc;
1476 struct rasops_info *ri = &cg6_console_screen.scr_ri;
1478 CG6_DRAIN(fbc);
1479 fbc->fbc_clip = 0;
1480 fbc->fbc_s = 0;
1481 fbc->fbc_offx = 0;
1482 fbc->fbc_offy = 0;
1483 fbc->fbc_clipminx = 0;
1484 fbc->fbc_clipminy = 0;
1485 fbc->fbc_clipmaxx = ri->ri_width - 1;
1486 fbc->fbc_clipmaxy = ri->ri_height - 1;
1487 fbc->fbc_alu = CG6_ALU_FLIP;
1488 fbc->fbc_arecty = y;
1489 fbc->fbc_arectx = x;
1490 fbc->fbc_arecty = y + he - 1;
1491 fbc->fbc_arectx = x + wi - 1;
1492 CG6_DRAW_WAIT(fbc);
1495 #endif