Home | History | Annotate | Line # | Download | only in sun
      1 /*	$NetBSD: cgsix.c,v 1.74 2025/04/14 10:05:26 macallan Exp $ */
      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.
     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.
     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  */
     79 
     80 #include <sys/cdefs.h>
     81 __KERNEL_RCSID(0, "$NetBSD: cgsix.c,v 1.74 2025/04/14 10:05:26 macallan Exp $");
     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/mman.h>
     89 #include <sys/tty.h>
     90 #include <sys/conf.h>
     91 
     92 #ifdef DEBUG
     93 #include <sys/proc.h>
     94 #include <sys/syslog.h>
     95 #endif
     96 
     97 #include <sys/bus.h>
     98 
     99 #include <dev/sun/fbio.h>
    100 #include <dev/sun/fbvar.h>
    101 
    102 #include <dev/sun/btreg.h>
    103 #include <dev/sun/btvar.h>
    104 #include <dev/sun/pfourreg.h>
    105 
    106 #include <dev/wscons/wsconsio.h>
    107 #include <dev/wsfont/wsfont.h>
    108 #include <dev/rasops/rasops.h>
    109 
    110 #include "opt_wsemul.h"
    111 #include "rasops_glue.h"
    112 
    113 #include <dev/sun/cgsixreg.h>
    114 #include <dev/sun/cgsixvar.h>
    115 
    116 #include "ioconf.h"
    117 
    118 static void	cg6_unblank(device_t);
    119 static void	cg6_blank(struct cgsix_softc *, int);
    120 
    121 dev_type_open(cgsixopen);
    122 dev_type_close(cgsixclose);
    123 dev_type_ioctl(cgsixioctl);
    124 dev_type_mmap(cgsixmmap);
    125 
    126 const struct cdevsw cgsix_cdevsw = {
    127 	.d_open = cgsixopen,
    128 	.d_close = cgsixclose,
    129 	.d_read = noread,
    130 	.d_write = nowrite,
    131 	.d_ioctl = cgsixioctl,
    132 	.d_stop = nostop,
    133 	.d_tty = notty,
    134 	.d_poll = nopoll,
    135 	.d_mmap = cgsixmmap,
    136 	.d_kqfilter = nokqfilter,
    137 	.d_discard = nodiscard,
    138 	.d_flag = D_OTHER
    139 };
    140 
    141 /* frame buffer generic driver */
    142 static struct fbdriver cg6_fbdriver = {
    143 	cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, nopoll, cgsixmmap,
    144 	nokqfilter
    145 };
    146 
    147 static void cg6_reset (struct cgsix_softc *);
    148 static void cg6_loadcmap (struct cgsix_softc *, int, int);
    149 static void cg6_loadomap (struct cgsix_softc *);
    150 static void cg6_setcursor (struct cgsix_softc *);/* set position */
    151 static void cg6_loadcursor (struct cgsix_softc *);/* set shape */
    152 
    153 static void cg6_setup_palette(struct cgsix_softc *);
    154 
    155 struct wsscreen_descr cgsix_defaultscreen = {
    156 	"std",
    157 	0, 0,	/* will be filled in -- XXX shouldn't, it's global */
    158 	NULL,		/* textops */
    159 	8, 16,	/* font width/height */
    160 	WSSCREEN_WSCOLORS | WSSCREEN_RESIZE | WSSCREEN_UNDERLINE,
    161 	NULL	/* modecookie */
    162 };
    163 
    164 static int 	cgsix_ioctl(void *, void *, u_long, void *, int, struct lwp *);
    165 static paddr_t	cgsix_mmap(void *, void *, off_t, int);
    166 static void	cgsix_init_screen(void *, struct vcons_screen *, int, long *);
    167 
    168 static void	cgsix_clearscreen(struct cgsix_softc *);
    169 
    170 void 	cgsix_setup_mono(struct cgsix_softc *, int, int, int, int, uint32_t,
    171 		uint32_t);
    172 void 	cgsix_feed_line(struct cgsix_softc *, int, uint8_t *);
    173 void 	cgsix_rectfill(struct cgsix_softc *, int, int, int, int, uint32_t);
    174 void	cgsix_bitblt(void *, int, int, int, int, int, int, int);
    175 
    176 int	cgsix_putcmap(struct cgsix_softc *, struct wsdisplay_cmap *);
    177 int	cgsix_getcmap(struct cgsix_softc *, struct wsdisplay_cmap *);
    178 void	cgsix_putchar(void *, int, int, u_int, long);
    179 void	cgsix_putchar_aa(void *, int, int, u_int, long);
    180 void	cgsix_cursor(void *, int, int, int);
    181 
    182 struct wsdisplay_accessops cgsix_accessops = {
    183 	cgsix_ioctl,
    184 	cgsix_mmap,
    185 	NULL,	/* alloc_screen */
    186 	NULL,	/* free_screen */
    187 	NULL,	/* show_screen */
    188 	NULL, 	/* load_font */
    189 	NULL,	/* pollc */
    190 	NULL	/* scroll */
    191 };
    192 
    193 const struct wsscreen_descr *_cgsix_scrlist[] = {
    194 	&cgsix_defaultscreen
    195 };
    196 
    197 struct wsscreen_list cgsix_screenlist = {
    198 	sizeof(_cgsix_scrlist) / sizeof(struct wsscreen_descr *),
    199 	_cgsix_scrlist
    200 };
    201 
    202 
    203 extern const u_char rasops_cmap[768];
    204 
    205 void	cg6_invert(struct cgsix_softc *, int, int, int, int);
    206 
    207 static struct vcons_screen cg6_console_screen;
    208 
    209 /*
    210  * cg6 accelerated console routines.
    211  *
    212  * Note that buried in this code in several places is the assumption
    213  * that pixels are exactly one byte wide.  Since this is cg6-specific
    214  * code, this seems safe.  This assumption resides in things like the
    215  * use of ri_emuwidth without messing around with ri_pelbytes, or the
    216  * assumption that ri_font->fontwidth is the right thing to multiply
    217  * character-cell counts by to get byte counts.
    218  */
    219 
    220 /*
    221  * Magic values for blitter
    222  */
    223 
    224 /* Values for the mode register */
    225 #define CG6_MODE	(						\
    226 	  0x00200000 /* GX_BLIT_SRC */					\
    227 	| 0x00020000 /* GX_MODE_COLOR8 */				\
    228 	| 0x00008000 /* GX_DRAW_RENDER */				\
    229 	| 0x00002000 /* GX_BWRITE0_ENABLE */				\
    230 	| 0x00001000 /* GX_BWRITE1_DISABLE */				\
    231 	| 0x00000200 /* GX_BREAD_0 */					\
    232 	| 0x00000080 /* GX_BDISP_0 */					\
    233 )
    234 #define CG6_MODE_MASK	(						\
    235 	  0x00300000 /* GX_BLIT_ALL */					\
    236 	| 0x00060000 /* GX_MODE_ALL */					\
    237 	| 0x00018000 /* GX_DRAW_ALL */					\
    238 	| 0x00006000 /* GX_BWRITE0_ALL */				\
    239 	| 0x00001800 /* GX_BWRITE1_ALL */				\
    240 	| 0x00000600 /* GX_BREAD_ALL */					\
    241 	| 0x00000180 /* GX_BDISP_ALL */					\
    242 )
    243 
    244 /* Value for the alu register for screen-to-screen copies */
    245 #define CG6_ALU_COPY	(						\
    246 	  0x80000000 /* GX_PLANE_ONES (ignore planemask register) */	\
    247 	| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */	\
    248 	| 0x00800000 /* GX_ATTR_SUPP (function unknown) */		\
    249 	| 0x00000000 /* GX_RAST_BOOL (function unknown) */		\
    250 	| 0x00000000 /* GX_PLOT_PLOT (function unknown) */		\
    251 	| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */		\
    252 	| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */	\
    253 	| 0x0000cccc /* ALU = src */					\
    254 )
    255 
    256 /* Value for the alu register for region fills */
    257 #define CG6_ALU_FILL	(						\
    258 	  0x80000000 /* GX_PLANE_ONES (ignore planemask register) */	\
    259 	| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */	\
    260 	| 0x00800000 /* GX_ATTR_SUPP (function unknown) */		\
    261 	| 0x00000000 /* GX_RAST_BOOL (function unknown) */		\
    262 	| 0x00000000 /* GX_PLOT_PLOT (function unknown) */		\
    263 	| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */		\
    264 	| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */	\
    265 	| 0x0000ff00 /* ALU = fg color */				\
    266 )
    267 
    268 /* Value for the alu register for toggling an area */
    269 #define CG6_ALU_FLIP	(						\
    270 	  0x80000000 /* GX_PLANE_ONES (ignore planemask register) */	\
    271 	| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */	\
    272 	| 0x00800000 /* GX_ATTR_SUPP (function unknown) */		\
    273 	| 0x00000000 /* GX_RAST_BOOL (function unknown) */		\
    274 	| 0x00000000 /* GX_PLOT_PLOT (function unknown) */		\
    275 	| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */		\
    276 	| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */	\
    277 	| 0x00005555 /* ALU = ~dst */					\
    278 )
    279 
    280 /*
    281  * Run a blitter command
    282  */
    283 #define CG6_BLIT(f) { (void)f->fbc_blit; }
    284 
    285 /*
    286  * Run a drawing command
    287  */
    288 #define CG6_DRAW(f) { (void)f->fbc_draw; }
    289 
    290 /*
    291  * Wait for the whole engine to go idle.  This may not matter in our case;
    292  * I'm not sure whether blits are actually queued or not.  It more likely
    293  * is intended for lines and such that do get queued.
    294  * 0x10000000 bit: GX_INPROGRESS
    295  */
    296 #define CG6_DRAIN(fbc) do {						\
    297 	while ((fbc)->fbc_s & GX_INPROGRESS)				\
    298 		/*EMPTY*/;						\
    299 } while (0)
    300 
    301 /*
    302  * something is missing here
    303  * Waiting for GX_FULL to clear should be enough to send another command
    304  * but some CG6 ( LX onboard for example ) lock up if we do that while
    305  * it works fine on others ( a 4MB TGX+ I've got here )
    306  * So, until I figure out what's going on we wait for the blitter to go
    307  * fully idle.
    308  */
    309 #define CG6_WAIT_READY(fbc) do {					\
    310        	while (((fbc)->fbc_s & GX_INPROGRESS/*GX_FULL*/) != 0)		\
    311 		/*EMPTY*/;						\
    312 } while (0)
    313 
    314 static void cg6_ras_init(struct cgsix_softc *);
    315 static void cg6_ras_copyrows(void *, int, int, int);
    316 static void cg6_ras_copycols(void *, int, int, int, int);
    317 static void cg6_ras_erasecols(void *, int, int, int, long int);
    318 static void cg6_ras_eraserows(void *, int, int, long int);
    319 
    320 static void
    321 cg6_ras_init(struct cgsix_softc *sc)
    322 {
    323 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
    324 
    325 	CG6_DRAIN(fbc);
    326 	fbc->fbc_mode &= ~CG6_MODE_MASK;
    327 	fbc->fbc_mode |= CG6_MODE;
    328 
    329 	/* set some common drawing engine parameters */
    330 	fbc->fbc_clip = 0;
    331 	fbc->fbc_s = 0;
    332 	fbc->fbc_offx = 0;
    333 	fbc->fbc_offy = 0;
    334 	fbc->fbc_clipminx = 0;
    335 	fbc->fbc_clipminy = 0;
    336 	fbc->fbc_clipmaxx = 0x3fff;
    337 	fbc->fbc_clipmaxy = 0x3fff;
    338 }
    339 
    340 static void
    341 cg6_ras_nuke_cursor(struct rasops_info *ri)
    342 {
    343 	struct vcons_screen *scr = ri->ri_hw;
    344 	struct cgsix_softc *sc = scr->scr_cookie;
    345 	int wi, he, x, y;
    346 
    347 	if (ri->ri_flg & RI_CURSOR) {
    348 		wi = ri->ri_font->fontwidth;
    349 		he = ri->ri_font->fontheight;
    350 		x = ri->ri_ccol * wi + ri->ri_xorigin;
    351 		y = ri->ri_crow * he + ri->ri_yorigin;
    352 		cg6_invert(sc, x, y, wi, he);
    353 		ri->ri_flg &= ~RI_CURSOR;
    354 	}
    355 }
    356 
    357 static void
    358 cg6_ras_copyrows(void *cookie, int src, int dst, int n)
    359 {
    360 	struct rasops_info *ri = cookie;
    361 	struct vcons_screen *scr = ri->ri_hw;
    362 	struct cgsix_softc *sc = scr->scr_cookie;
    363 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
    364 
    365 	if (dst == src)
    366 		return;
    367 
    368 	if ((ri->ri_crow >= src && ri->ri_crow < (src + n)) &&
    369 	   (ri->ri_flg & RI_CURSOR)) {
    370 		cg6_ras_nuke_cursor(ri);
    371 	}
    372 
    373 	if (ri->ri_crow >= dst && ri->ri_crow < (dst + n))
    374 		ri->ri_flg &= ~RI_CURSOR;
    375 
    376 	n *= ri->ri_font->fontheight;
    377 	src *= ri->ri_font->fontheight;
    378 	dst *= ri->ri_font->fontheight;
    379 
    380 	CG6_WAIT_READY(fbc);
    381 
    382 	fbc->fbc_alu = CG6_ALU_COPY;
    383 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
    384 
    385 	fbc->fbc_x0 = ri->ri_xorigin;
    386 	fbc->fbc_y0 = ri->ri_yorigin + src;
    387 	fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
    388 	fbc->fbc_y1 = ri->ri_yorigin + src + n - 1;
    389 	fbc->fbc_x2 = ri->ri_xorigin;
    390 	fbc->fbc_y2 = ri->ri_yorigin + dst;
    391 	fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1;
    392 	fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1;
    393 	CG6_BLIT(fbc);
    394 }
    395 
    396 static void
    397 cg6_ras_copycols(void *cookie, int row, int src, int dst, int n)
    398 {
    399 	struct rasops_info *ri = cookie;
    400 	struct vcons_screen *scr = ri->ri_hw;
    401 	struct cgsix_softc *sc = scr->scr_cookie;
    402 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
    403 
    404 	if (dst == src)
    405 		return;
    406 
    407 	if ((row < 0) || (row >= ri->ri_rows))
    408 		return;
    409 
    410 	if (ri->ri_crow == row &&
    411 	   (ri->ri_ccol >= src && ri->ri_ccol < (src + n)) &&
    412 	   (ri->ri_flg & RI_CURSOR)) {
    413 		cg6_ras_nuke_cursor(ri);
    414 	}
    415 
    416 	if (ri->ri_crow == row &&
    417 	   (ri->ri_ccol >= dst && ri->ri_ccol < (dst + n)))
    418 		ri->ri_flg &= ~RI_CURSOR;
    419 
    420 	n *= ri->ri_font->fontwidth;
    421 	src *= ri->ri_font->fontwidth;
    422 	dst *= ri->ri_font->fontwidth;
    423 	row *= ri->ri_font->fontheight;
    424 
    425 	CG6_WAIT_READY(fbc);
    426 
    427 	fbc->fbc_alu = CG6_ALU_COPY;
    428 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
    429 
    430 	fbc->fbc_x0 = ri->ri_xorigin + src;
    431 	fbc->fbc_y0 = ri->ri_yorigin + row;
    432 	fbc->fbc_x1 = ri->ri_xorigin + src + n - 1;
    433 	fbc->fbc_y1 = ri->ri_yorigin + row +
    434 	    ri->ri_font->fontheight - 1;
    435 	fbc->fbc_x2 = ri->ri_xorigin + dst;
    436 	fbc->fbc_y2 = ri->ri_yorigin + row;
    437 	fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1;
    438 	fbc->fbc_y3 = ri->ri_yorigin + row +
    439 	    ri->ri_font->fontheight - 1;
    440 	CG6_BLIT(fbc);
    441 }
    442 
    443 static void
    444 cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr)
    445 {
    446 	struct rasops_info *ri = cookie;
    447 	struct vcons_screen *scr = ri->ri_hw;
    448 	struct cgsix_softc *sc = scr->scr_cookie;
    449 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
    450 
    451 	if (ri->ri_crow == row &&
    452 	   (ri->ri_ccol >= col && ri->ri_ccol < (col + n)))
    453 		ri->ri_flg &= ~RI_CURSOR;
    454 
    455 	n *= ri->ri_font->fontwidth;
    456 	col *= ri->ri_font->fontwidth;
    457 	row *= ri->ri_font->fontheight;
    458 
    459 	CG6_WAIT_READY(fbc);
    460 	fbc->fbc_alu = CG6_ALU_FILL;
    461 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
    462 
    463 	fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff];
    464 	fbc->fbc_arecty = ri->ri_yorigin + row;
    465 	fbc->fbc_arectx = ri->ri_xorigin + col;
    466 	fbc->fbc_arecty = ri->ri_yorigin + row +
    467 	    ri->ri_font->fontheight - 1;
    468 	fbc->fbc_arectx = ri->ri_xorigin + col + n - 1;
    469 	CG6_DRAW(fbc);
    470 }
    471 
    472 static void
    473 cg6_ras_eraserows(void *cookie, int row, int n, long int attr)
    474 {
    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;
    479 
    480 	if (ri->ri_crow >= row && ri->ri_crow < (row + n))
    481 		ri->ri_flg &= ~RI_CURSOR;
    482 
    483 	CG6_WAIT_READY(fbc);
    484 	fbc->fbc_alu = CG6_ALU_FILL;
    485 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
    486 
    487 	fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff];
    488 	if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
    489 		fbc->fbc_arecty = 0;
    490 		fbc->fbc_arectx = 0;
    491 		fbc->fbc_arecty = ri->ri_height - 1;
    492 		fbc->fbc_arectx = ri->ri_width - 1;
    493 	} else {
    494 		row *= ri->ri_font->fontheight;
    495 		fbc->fbc_arecty = ri->ri_yorigin + row;
    496 		fbc->fbc_arectx = ri->ri_xorigin;
    497 		fbc->fbc_arecty = ri->ri_yorigin + row +
    498 		    (n * ri->ri_font->fontheight) - 1;
    499 		fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1;
    500 	}
    501 	CG6_DRAW(fbc);
    502 }
    503 
    504 void
    505 cg6attach(struct cgsix_softc *sc, const char *name, int isconsole)
    506 {
    507 	struct fbdevice *fb = &sc->sc_fb;
    508 	struct wsemuldisplaydev_attach_args aa;
    509 	struct rasops_info *ri = &cg6_console_screen.scr_ri;
    510 	unsigned long defattr;
    511 
    512 	fb->fb_driver = &cg6_fbdriver;
    513 
    514 	/* Don't have to map the pfour register on the cgsix. */
    515 	fb->fb_pfour = NULL;
    516 
    517 	fb->fb_type.fb_cmsize = 256;
    518 	fb->fb_type.fb_size = sc->sc_ramsize;
    519 
    520 	printf(": %s, %d x %d", name,
    521 	       fb->fb_type.fb_width, fb->fb_type.fb_height);
    522 	if(sc->sc_fhc) {
    523 		sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) &
    524 			(FHC_REV_MASK >> FHC_REV_SHIFT);
    525 	} else
    526 		sc->sc_fhcrev=-1;
    527 	printf(", rev %d", sc->sc_fhcrev);
    528 
    529 	/* reset cursor & frame buffer controls */
    530 	cg6_reset(sc);
    531 
    532 	/* enable video */
    533 	sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
    534 
    535 	if (isconsole) {
    536 		printf(" (console)");
    537 	}
    538 	printf("\n");
    539 
    540 	fb_attach(&sc->sc_fb, isconsole);
    541 	sc->sc_width = fb->fb_type.fb_width;
    542 	sc->sc_stride = fb->fb_type.fb_width;
    543 	sc->sc_height = fb->fb_type.fb_height;
    544 
    545 	printf("%s: framebuffer size: %d MB\n", device_xname(sc->sc_dev),
    546 	    sc->sc_ramsize >> 20);
    547 
    548 	/* setup rasops and so on for wsdisplay */
    549 	memcpy(sc->sc_default_cmap, rasops_cmap, 768);
    550 	wsfont_init();
    551 	cg6_ras_init(sc);
    552 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
    553 	sc->sc_bg = WS_DEFAULT_BG;
    554 	sc->sc_fb_is_open = FALSE;
    555 
    556 	vcons_init(&sc->vd, sc, &cgsix_defaultscreen, &cgsix_accessops);
    557 	sc->vd.init_screen = cgsix_init_screen;
    558 
    559 	sc->sc_gc.gc_bitblt = cgsix_bitblt;
    560 	sc->sc_gc.gc_blitcookie = sc;
    561 	sc->sc_gc.gc_rop = CG6_ALU_COPY;
    562 	sc->vd.show_screen_cookie = &sc->sc_gc;
    563 	sc->vd.show_screen_cb = glyphcache_adapt;
    564 
    565 	if(isconsole) {
    566 		/* we mess with cg6_console_screen only once */
    567 		vcons_init_screen(&sc->vd, &cg6_console_screen, 1,
    568 		    &defattr);
    569 		sc->sc_bg = (defattr >> 16) & 0xf; /* yes, this is an index into devcmap */
    570 
    571 		/*
    572 		 * XXX
    573 		 * Is this actually necessary? We're going to use the blitter later on anyway.
    574 		 */
    575 		/* We need unaccelerated initial screen clear on old revisions */
    576 		if (sc->sc_fhcrev < 2) {
    577 			memset(sc->sc_fb.fb_pixels, ri->ri_devcmap[sc->sc_bg],
    578 			    sc->sc_stride * sc->sc_height);
    579 		} else
    580 			cgsix_clearscreen(sc);
    581 
    582 		cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
    583 
    584 		cgsix_defaultscreen.textops = &ri->ri_ops;
    585 		cgsix_defaultscreen.capabilities = ri->ri_caps;
    586 		cgsix_defaultscreen.nrows = ri->ri_rows;
    587 		cgsix_defaultscreen.ncols = ri->ri_cols;
    588 		SCREEN_VISIBLE(&cg6_console_screen);
    589 		sc->vd.active = &cg6_console_screen;
    590 		wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr);
    591 		if (ri->ri_flg & RI_ENABLE_ALPHA) {
    592 			glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
    593 				(sc->sc_ramsize / sc->sc_stride) -
    594 				  sc->sc_height - 5,
    595 				sc->sc_width,
    596 				ri->ri_font->fontwidth,
    597 				ri->ri_font->fontheight,
    598 				defattr);
    599 		}
    600 		vcons_replay_msgbuf(&cg6_console_screen);
    601 	} else {
    602 		/*
    603 		 * since we're not the console we can postpone the rest
    604 		 * until someone actually allocates a screen for us
    605 		 */
    606 		if (cg6_console_screen.scr_ri.ri_rows == 0) {
    607 			/* do some minimal setup to avoid weirdnesses later */
    608 			vcons_init_screen(&sc->vd, &cg6_console_screen, 1,
    609 			    &defattr);
    610 		} else
    611 			(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    612 		sc->sc_bg = (defattr >> 16) & 0xf;
    613 		if (ri->ri_flg & RI_ENABLE_ALPHA) {
    614 			glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
    615 				(sc->sc_ramsize / sc->sc_stride) -
    616 				  sc->sc_height - 5,
    617 				sc->sc_width,
    618 				ri->ri_font->fontwidth,
    619 				ri->ri_font->fontheight,
    620 				defattr);
    621 		}
    622 	}
    623 	cg6_setup_palette(sc);
    624 
    625 	aa.scrdata = &cgsix_screenlist;
    626 	aa.console = isconsole;
    627 	aa.accessops = &cgsix_accessops;
    628 	aa.accesscookie = &sc->vd;
    629 	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE);
    630 }
    631 
    632 
    633 int
    634 cgsixopen(dev_t dev, int flags, int mode, struct lwp *l)
    635 {
    636 	device_t dv = device_lookup(&cgsix_cd, minor(dev));
    637 	struct cgsix_softc *sc = device_private(dv);
    638 
    639 	if (dv == NULL)
    640 		return ENXIO;
    641 	sc->sc_fb_is_open = TRUE;
    642 
    643 	return 0;
    644 }
    645 
    646 int
    647 cgsixclose(dev_t dev, int flags, int mode, struct lwp *l)
    648 {
    649 	device_t dv = device_lookup(&cgsix_cd, minor(dev));
    650 	struct cgsix_softc *sc = device_private(dv);
    651 
    652 	cg6_reset(sc);
    653 	sc->sc_fb_is_open = FALSE;
    654 
    655 	if (IS_IN_EMUL_MODE(sc)) {
    656 		struct vcons_screen *ms = sc->vd.active;
    657 
    658 		cg6_ras_init(sc);
    659 		cg6_setup_palette(sc);
    660 		glyphcache_wipe(&sc->sc_gc);
    661 
    662 		/* we don't know if the screen exists */
    663 		if (ms != NULL)
    664 			vcons_redraw_screen(ms);
    665 	}
    666 	return 0;
    667 }
    668 
    669 int
    670 cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
    671 {
    672 	struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev));
    673 	union cursor_cmap tcm;
    674 	uint32_t image[32], mask[32];
    675 	u_int count;
    676 	int v, error;
    677 
    678 #ifdef CGSIX_DEBUG
    679 	printf("cgsixioctl(%lx)\n",cmd);
    680 #endif
    681 
    682 	switch (cmd) {
    683 
    684 	case FBIOGTYPE:
    685 		*(struct fbtype *)data = sc->sc_fb.fb_type;
    686 		break;
    687 
    688 	case FBIOGATTR:
    689 #define fba ((struct fbgattr *)data)
    690 		fba->real_type = sc->sc_fb.fb_type.fb_type;
    691 		fba->owner = 0;		/* XXX ??? */
    692 		fba->fbtype = sc->sc_fb.fb_type;
    693 		fba->sattr.flags = 0;
    694 		fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
    695 		fba->sattr.dev_specific[0] = -1;
    696 		fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
    697 		fba->emu_types[1] = -1;
    698 #undef fba
    699 		break;
    700 
    701 	case FBIOGETCMAP:
    702 #define	p ((struct fbcmap *)data)
    703 		return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
    704 
    705 	case FBIOPUTCMAP:
    706 		/* copy to software map */
    707 		error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
    708 		if (error)
    709 			return error;
    710 		/* now blast them into the chip */
    711 		/* XXX should use retrace interrupt */
    712 		cg6_loadcmap(sc, p->index, p->count);
    713 #undef p
    714 		break;
    715 
    716 	case FBIOGVIDEO:
    717 		*(int *)data = sc->sc_blanked;
    718 		break;
    719 
    720 	case FBIOSVIDEO:
    721 		cg6_blank(sc, !(*(int *)data));
    722 		break;
    723 
    724 /* these are for both FBIOSCURSOR and FBIOGCURSOR */
    725 #define p ((struct fbcursor *)data)
    726 #define cc (&sc->sc_cursor)
    727 
    728 	case FBIOGCURSOR:
    729 		/* do not quite want everything here... */
    730 		p->set = FB_CUR_SETALL;	/* close enough, anyway */
    731 		p->enable = cc->cc_enable;
    732 		p->pos = cc->cc_pos;
    733 		p->hot = cc->cc_hot;
    734 		p->size = cc->cc_size;
    735 
    736 		/* begin ugh ... can we lose some of this crap?? */
    737 		if (p->image != NULL) {
    738 			count = cc->cc_size.y * 32 / NBBY;
    739 			error = copyout(cc->cc_bits[1], p->image, count);
    740 			if (error)
    741 				return error;
    742 			error = copyout(cc->cc_bits[0], p->mask, count);
    743 			if (error)
    744 				return error;
    745 		}
    746 		if (p->cmap.red != NULL) {
    747 			error = bt_getcmap(&p->cmap,
    748 			    (union bt_cmap *)&cc->cc_color, 2, 1);
    749 			if (error)
    750 				return error;
    751 		} else {
    752 			p->cmap.index = 0;
    753 			p->cmap.count = 2;
    754 		}
    755 		/* end ugh */
    756 		break;
    757 
    758 	case FBIOSCURSOR:
    759 		/*
    760 		 * For setcmap and setshape, verify parameters, so that
    761 		 * we do not get halfway through an update and then crap
    762 		 * out with the software state screwed up.
    763 		 */
    764 		v = p->set;
    765 		if (v & FB_CUR_SETCMAP) {
    766 			/*
    767 			 * This use of a temporary copy of the cursor
    768 			 * colormap is not terribly efficient, but these
    769 			 * copies are small (8 bytes)...
    770 			 */
    771 			tcm = cc->cc_color;
    772 			error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2,
    773 			    1);
    774 			if (error)
    775 				return error;
    776 		}
    777 		if (v & FB_CUR_SETSHAPE) {
    778 			if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32)
    779 				return EINVAL;
    780 			count = p->size.y * 32 / NBBY;
    781 			error = copyin(p->image, image, count);
    782 			if (error)
    783 				return error;
    784 			error = copyin(p->mask, mask, count);
    785 			if (error)
    786 				return error;
    787 		}
    788 
    789 		/* parameters are OK; do it */
    790 		if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) {
    791 			if (v & FB_CUR_SETCUR)
    792 				cc->cc_enable = p->enable;
    793 			if (v & FB_CUR_SETPOS)
    794 				cc->cc_pos = p->pos;
    795 			if (v & FB_CUR_SETHOT)
    796 				cc->cc_hot = p->hot;
    797 			cg6_setcursor(sc);
    798 		}
    799 		if (v & FB_CUR_SETCMAP) {
    800 			cc->cc_color = tcm;
    801 			cg6_loadomap(sc); /* XXX defer to vertical retrace */
    802 		}
    803 		if (v & FB_CUR_SETSHAPE) {
    804 			cc->cc_size = p->size;
    805 			count = p->size.y * 32 / NBBY;
    806 			memset(cc->cc_bits, 0, sizeof cc->cc_bits);
    807 			memcpy(cc->cc_bits[1], image, count);
    808 			memcpy(cc->cc_bits[0], mask, count);
    809 			cg6_loadcursor(sc);
    810 		}
    811 		break;
    812 
    813 #undef p
    814 #undef cc
    815 
    816 	case FBIOGCURPOS:
    817 		*(struct fbcurpos *)data = sc->sc_cursor.cc_pos;
    818 		break;
    819 
    820 	case FBIOSCURPOS:
    821 		sc->sc_cursor.cc_pos = *(struct fbcurpos *)data;
    822 		cg6_setcursor(sc);
    823 		break;
    824 
    825 	case FBIOGCURMAX:
    826 		/* max cursor size is 32x32 */
    827 		((struct fbcurpos *)data)->x = 32;
    828 		((struct fbcurpos *)data)->y = 32;
    829 		break;
    830 
    831 	default:
    832 #ifdef DEBUG
    833 		log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd,
    834 		    l->l_proc->p_comm, l->l_proc->p_pid);
    835 #endif
    836 		return ENOTTY;
    837 	}
    838 	return 0;
    839 }
    840 
    841 /*
    842  * Clean up hardware state (e.g., after bootup or after X crashes).
    843  */
    844 static void
    845 cg6_reset(struct cgsix_softc *sc)
    846 {
    847 	volatile struct cg6_tec_xxx *tec;
    848 	int fhc;
    849 	volatile struct bt_regs *bt;
    850 
    851 	/* hide the cursor, just in case */
    852 	sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF;
    853 
    854 	/* turn off frobs in transform engine (makes X11 work) */
    855 	tec = sc->sc_tec;
    856 	tec->tec_mv = 0;
    857 	tec->tec_clip = 0;
    858 	tec->tec_vdc = 0;
    859 
    860 	/* take care of hardware bugs in old revisions */
    861 	if (sc->sc_fhcrev < 5) {
    862 		/*
    863 		 * Keep current resolution; set CPU to 68020, set test
    864 		 * window (size 1Kx1K), and for rev 1, disable dest cache.
    865 		 */
    866 		fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 |
    867 		    FHC_TEST |
    868 		    (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT);
    869 		if (sc->sc_fhcrev < 2)
    870 			fhc |= FHC_DST_DISABLE;
    871 		*sc->sc_fhc = fhc;
    872 	}
    873 
    874 	/* Enable cursor in Brooktree DAC. */
    875 	bt = sc->sc_bt;
    876 	bt->bt_addr = 0x06 << 24;
    877 	bt->bt_ctrl |= 0x03 << 24;
    878 }
    879 
    880 static void
    881 cg6_setcursor(struct cgsix_softc *sc)
    882 {
    883 
    884 	/* we need to subtract the hot-spot value here */
    885 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f)
    886 	sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ?
    887 	    ((COORD(x) << 16) | (COORD(y) & 0xffff)) :
    888 	    (THC_CURSOFF << 16) | THC_CURSOFF;
    889 #undef COORD
    890 }
    891 
    892 static void
    893 cg6_loadcursor(struct cgsix_softc *sc)
    894 {
    895 	volatile struct cg6_thc *thc;
    896 	u_int edgemask, m;
    897 	int i;
    898 
    899 	/*
    900 	 * Keep the top size.x bits.  Here we *throw out* the top
    901 	 * size.x bits from an all-one-bits word, introducing zeros in
    902 	 * the top size.x bits, then invert all the bits to get what
    903 	 * we really wanted as our mask.  But this fails if size.x is
    904 	 * 32---a sparc uses only the low 5 bits of the shift count---
    905 	 * so we have to special case that.
    906 	 */
    907 	edgemask = ~0;
    908 	if (sc->sc_cursor.cc_size.x < 32)
    909 		edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x);
    910 	thc = sc->sc_thc;
    911 	for (i = 0; i < 32; i++) {
    912 		m = sc->sc_cursor.cc_bits[0][i] & edgemask;
    913 		thc->thc_cursmask[i] = m;
    914 		thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i];
    915 	}
    916 }
    917 
    918 /*
    919  * Load a subset of the current (new) colormap into the color DAC.
    920  */
    921 static void
    922 cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors)
    923 {
    924 	volatile struct bt_regs *bt;
    925 	u_int *ip, i;
    926 	int count;
    927 
    928 	ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)];	/* start/4 * 3 */
    929 	count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
    930 	bt = sc->sc_bt;
    931 	bt->bt_addr = BT_D4M4(start) << 24;
    932 	while (--count >= 0) {
    933 		i = *ip++;
    934 		/* hardware that makes one want to pound boards with hammers */
    935 		bt->bt_cmap = i;
    936 		bt->bt_cmap = i << 8;
    937 		bt->bt_cmap = i << 16;
    938 		bt->bt_cmap = i << 24;
    939 	}
    940 }
    941 
    942 /*
    943  * Load the cursor (overlay `foreground' and `background') colors.
    944  */
    945 static void
    946 cg6_loadomap(struct cgsix_softc *sc)
    947 {
    948 	volatile struct bt_regs *bt;
    949 	u_int i;
    950 
    951 	bt = sc->sc_bt;
    952 	bt->bt_addr = 0x01 << 24;	/* set background color */
    953 	i = sc->sc_cursor.cc_color.cm_chip[0];
    954 	bt->bt_omap = i;		/* R */
    955 	bt->bt_omap = i << 8;		/* G */
    956 	bt->bt_omap = i << 16;		/* B */
    957 
    958 	bt->bt_addr = 0x03 << 24;	/* set foreground color */
    959 	bt->bt_omap = i << 24;		/* R */
    960 	i = sc->sc_cursor.cc_color.cm_chip[1];
    961 	bt->bt_omap = i;		/* G */
    962 	bt->bt_omap = i << 8;		/* B */
    963 }
    964 
    965 /* blank or unblank the screen */
    966 static void
    967 cg6_blank(struct cgsix_softc *sc, int flag)
    968 {
    969 
    970 	if (sc->sc_blanked != flag) {
    971 		sc->sc_blanked = flag;
    972 		if (flag) {
    973 			sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN;
    974 		} else {
    975 			sc->sc_thc->thc_misc |= THC_MISC_VIDEN;
    976 		}
    977 	}
    978 }
    979 
    980 /*
    981  * this is called on panic or ddb entry - force the console to the front, reset
    982  * the colour map and enable drawing so we actually see the message even when X
    983  * is running
    984  */
    985 static void
    986 cg6_unblank(device_t dev)
    987 {
    988 	struct cgsix_softc *sc = device_private(dev);
    989 
    990 	cg6_blank(sc, 0);
    991 }
    992 
    993 /* XXX the following should be moved to a "user interface" header */
    994 /*
    995  * Base addresses at which users can mmap() the various pieces of a cg6.
    996  * Note that although the Brooktree color registers do not occupy 8K,
    997  * the X server dies if we do not allow it to map 8K there (it just maps
    998  * from 0x70000000 forwards, as a contiguous chunk).
    999  */
   1000 #define	CG6_USER_FBC	0x70000000
   1001 #define	CG6_USER_TEC	0x70001000
   1002 #define	CG6_USER_BTREGS	0x70002000
   1003 #define	CG6_USER_FHC	0x70004000
   1004 #define	CG6_USER_THC	0x70005000
   1005 #define	CG6_USER_ROM	0x70006000
   1006 #define	CG6_USER_RAM	0x70016000
   1007 #define	CG6_USER_DHC	0x80000000
   1008 
   1009 struct mmo {
   1010 	u_long	mo_uaddr;	/* user (virtual) address */
   1011 	u_long	mo_size;	/* size, or 0 for video ram size */
   1012 	u_long	mo_physoff;	/* offset from sc_physadr */
   1013 };
   1014 
   1015 /*
   1016  * Return the address that would map the given device at the given
   1017  * offset, allowing for the given protection, or return -1 for error.
   1018  *
   1019  * XXX	needs testing against `demanding' applications (e.g., aviator)
   1020  */
   1021 paddr_t
   1022 cgsixmmap(dev_t dev, off_t off, int prot)
   1023 {
   1024 	struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev));
   1025 	struct mmo *mo;
   1026 	u_int u, sz, flags;
   1027 	static struct mmo mmo[] = {
   1028 		{ CG6_USER_RAM, 0, CGSIX_RAM_OFFSET },
   1029 
   1030 		/* do not actually know how big most of these are! */
   1031 		{ CG6_USER_FBC, 1, CGSIX_FBC_OFFSET },
   1032 		{ CG6_USER_TEC, 1, CGSIX_TEC_OFFSET },
   1033 		{ CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET },
   1034 		{ CG6_USER_FHC, 1, CGSIX_FHC_OFFSET },
   1035 		{ CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET },
   1036 		{ CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET },
   1037 		{ CG6_USER_DHC, 1, CGSIX_DHC_OFFSET },
   1038 	};
   1039 #define NMMO (sizeof mmo / sizeof *mmo)
   1040 
   1041 	if (off & PGOFSET)
   1042 		panic("cgsixmmap");
   1043 
   1044 	/*
   1045 	 * Entries with size 0 map video RAM (i.e., the size in fb data).
   1046 	 *
   1047 	 * Since we work in pages, the fact that the map offset table's
   1048 	 * sizes are sometimes bizarre (e.g., 1) is effectively ignored:
   1049 	 * one byte is as good as one page.
   1050 	 */
   1051 	for (mo = mmo; mo < &mmo[NMMO]; mo++) {
   1052 		if ((u_long)off < mo->mo_uaddr)
   1053 			continue;
   1054 		u = off - mo->mo_uaddr;
   1055 		if (mo->mo_size == 0) {
   1056 			flags = BUS_SPACE_MAP_LINEAR;
   1057 			sz = sc->sc_ramsize;
   1058 		} else {
   1059 			flags = BUS_SPACE_MAP_LINEAR;
   1060 			sz = mo->mo_size;
   1061 		}
   1062 		if (u < sz) {
   1063 			return (bus_space_mmap(sc->sc_bustag,
   1064 				sc->sc_paddr, u+mo->mo_physoff,
   1065 				prot, flags));
   1066 		}
   1067 	}
   1068 
   1069 #ifdef DEBUG
   1070 	{
   1071 	  struct proc *p = curlwp->l_proc;	/* XXX */
   1072 	  log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n",
   1073 		(long long)off, p->p_comm, p->p_pid);
   1074 	}
   1075 #endif
   1076 	return -1;	/* not a user-map offset */
   1077 }
   1078 
   1079 static void
   1080 cg6_setup_palette(struct cgsix_softc *sc)
   1081 {
   1082 	int i, j;
   1083 
   1084 	rasops_get_cmap(&cg6_console_screen.scr_ri, sc->sc_default_cmap,
   1085 	    sizeof(sc->sc_default_cmap));
   1086 	j = 0;
   1087 	for (i = 0; i < 256; i++) {
   1088 		sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j];
   1089 		j++;
   1090 		sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j];
   1091 		j++;
   1092 		sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j];
   1093 		j++;
   1094 	}
   1095 	cg6_loadcmap(sc, 0, 256);
   1096 }
   1097 
   1098 int
   1099 cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
   1100 	struct lwp *l)
   1101 {
   1102 	/* we'll probably need to add more stuff here */
   1103 	struct vcons_data *vd = v;
   1104 	struct cgsix_softc *sc = vd->cookie;
   1105 	struct wsdisplay_fbinfo *wdf;
   1106 	struct vcons_screen *ms = sc->vd.active;
   1107 
   1108 #ifdef CGSIX_DEBUG
   1109 	printf("cgsix_ioctl(%lx)\n",cmd);
   1110 #endif
   1111 	switch (cmd) {
   1112 		case WSDISPLAYIO_GTYPE:
   1113 			*(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
   1114 			return 0;
   1115 		case WSDISPLAYIO_GINFO:
   1116 			wdf = (void *)data;
   1117 			wdf->height = sc->sc_height;
   1118 			wdf->width = sc->sc_width;
   1119 			wdf->depth = 8;
   1120 			wdf->cmsize = 256;
   1121 			return 0;
   1122 
   1123 		case WSDISPLAYIO_GETCMAP:
   1124 			return cgsix_getcmap(sc,
   1125 			    (struct wsdisplay_cmap *)data);
   1126 		case WSDISPLAYIO_PUTCMAP:
   1127 			return cgsix_putcmap(sc,
   1128 			    (struct wsdisplay_cmap *)data);
   1129 
   1130 		case WSDISPLAYIO_LINEBYTES:
   1131 			*(u_int *)data = sc->sc_stride;
   1132 			return 0;
   1133 
   1134 		case WSDISPLAYIO_SMODE:
   1135 			{
   1136 				int new_mode = *(int*)data;
   1137 
   1138 				if (new_mode != sc->sc_mode) {
   1139 					sc->sc_mode = new_mode;
   1140 					if (IS_IN_EMUL_MODE(sc)) {
   1141 						cg6_reset(sc);
   1142 						cg6_ras_init(sc);
   1143 						cg6_setup_palette(sc);
   1144 						glyphcache_wipe(&sc->sc_gc);
   1145 						vcons_redraw_screen(ms);
   1146 					}
   1147 				}
   1148 			}
   1149 			return 0;
   1150 		case WSDISPLAYIO_GET_FBINFO:
   1151 			{
   1152 				struct wsdisplayio_fbinfo *fbi = data;
   1153 
   1154 				return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
   1155 			}
   1156 	}
   1157 	return EPASSTHROUGH;
   1158 }
   1159 
   1160 paddr_t
   1161 cgsix_mmap(void *v, void *vs, off_t offset, int prot)
   1162 {
   1163 	struct vcons_data *vd = v;
   1164 	struct cgsix_softc *sc = vd->cookie;
   1165 
   1166 	if (offset < sc->sc_ramsize) {
   1167 		return bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
   1168 		    CGSIX_RAM_OFFSET + offset, prot,
   1169 		    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
   1170 	}
   1171 	return -1;
   1172 }
   1173 
   1174 int
   1175 cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm)
   1176 {
   1177 	u_int index = cm->index;
   1178 	u_int count = cm->count;
   1179 	int error, i;
   1180 
   1181 	if (index >= 256 || count > 256 || index + count > 256)
   1182 		return EINVAL;
   1183 
   1184 	for (i = 0; i < count; i++)
   1185 	{
   1186 		error = copyin(&cm->red[i],
   1187 		    &sc->sc_cmap.cm_map[index + i][0], 1);
   1188 		if (error)
   1189 			return error;
   1190 		error = copyin(&cm->green[i],
   1191 		    &sc->sc_cmap.cm_map[index + i][1],
   1192 		    1);
   1193 		if (error)
   1194 			return error;
   1195 		error = copyin(&cm->blue[i],
   1196 		    &sc->sc_cmap.cm_map[index + i][2], 1);
   1197 		if (error)
   1198 			return error;
   1199 	}
   1200 	cg6_loadcmap(sc, index, count);
   1201 
   1202 	return 0;
   1203 }
   1204 
   1205 int
   1206 cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm)
   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 
   1215 	for (i = 0; i < count; i++)
   1216 	{
   1217 		error = copyout(&sc->sc_cmap.cm_map[index + i][0],
   1218 		    &cm->red[i], 1);
   1219 		if (error)
   1220 			return error;
   1221 		error = copyout(&sc->sc_cmap.cm_map[index + i][1],
   1222 		    &cm->green[i], 1);
   1223 		if (error)
   1224 			return error;
   1225 		error = copyout(&sc->sc_cmap.cm_map[index + i][2],
   1226 		    &cm->blue[i], 1);
   1227 		if (error)
   1228 			return error;
   1229 	}
   1230 
   1231 	return 0;
   1232 }
   1233 
   1234 void
   1235 cgsix_init_screen(void *cookie, struct vcons_screen *scr,
   1236     int existing, long *defattr)
   1237 {
   1238 	struct cgsix_softc *sc = cookie;
   1239 	struct rasops_info *ri = &scr->scr_ri;
   1240 	int av;
   1241 
   1242 	ri->ri_depth = 8;
   1243 	ri->ri_width = sc->sc_width;
   1244 	ri->ri_height = sc->sc_height;
   1245 	ri->ri_stride = sc->sc_stride;
   1246 	av = sc->sc_ramsize - (sc->sc_height * sc->sc_stride);
   1247 	ri->ri_flg = RI_CENTER  | RI_8BIT_IS_RGB;
   1248 	if (av > (128 * 1024)) {
   1249 		ri->ri_flg |= RI_ENABLE_ALPHA | RI_PREFER_ALPHA;
   1250 	}
   1251 	ri->ri_bits = sc->sc_fb.fb_pixels;
   1252 	scr->scr_flags |= VCONS_LOADFONT;
   1253 
   1254 	rasops_init(ri, 0, 0);
   1255 	ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE |
   1256 		      WSSCREEN_UNDERLINE | WSSCREEN_RESIZE;
   1257 	rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
   1258 		    sc->sc_width / ri->ri_font->fontwidth);
   1259 
   1260 	/* enable acceleration */
   1261 	ri->ri_hw = scr;
   1262 	ri->ri_ops.copyrows = cg6_ras_copyrows;
   1263 	ri->ri_ops.copycols = cg6_ras_copycols;
   1264 	ri->ri_ops.eraserows = cg6_ras_eraserows;
   1265 	ri->ri_ops.erasecols = cg6_ras_erasecols;
   1266 	ri->ri_ops.cursor = cgsix_cursor;
   1267 	if (FONT_IS_ALPHA(ri->ri_font)) {
   1268 		ri->ri_ops.putchar = cgsix_putchar_aa;
   1269 	} else
   1270 		ri->ri_ops.putchar = cgsix_putchar;
   1271 }
   1272 
   1273 void
   1274 cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he,
   1275     uint32_t col)
   1276 {
   1277 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1278 
   1279 	CG6_WAIT_READY(fbc);
   1280 
   1281 	fbc->fbc_alu = CG6_ALU_FILL;
   1282 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
   1283 
   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(fbc);
   1290 }
   1291 
   1292 void
   1293 cgsix_bitblt(void *cookie, int xs, int ys, int xd, int yd,
   1294     int wi, int he, int rop)
   1295 {
   1296 	struct cgsix_softc *sc = cookie;
   1297 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1298 	CG6_WAIT_READY(fbc);
   1299 
   1300 	fbc->fbc_alu = rop;
   1301 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
   1302 
   1303 	fbc->fbc_x0 = xs;
   1304 	fbc->fbc_y0 = ys;
   1305 	fbc->fbc_x1 = xs + wi - 1;
   1306 	fbc->fbc_y1 = ys + he - 1;
   1307 	fbc->fbc_x2 = xd;
   1308 	fbc->fbc_y2 = yd;
   1309 	fbc->fbc_x3 = xd + wi - 1;
   1310 	fbc->fbc_y3 = yd + he - 1;
   1311 	CG6_BLIT(fbc);
   1312 }
   1313 
   1314 void
   1315 cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he,
   1316     uint32_t fg, uint32_t bg)
   1317 {
   1318 	volatile struct cg6_fbc *fbc=sc->sc_fbc;
   1319 
   1320 	CG6_WAIT_READY(fbc);
   1321 
   1322 	fbc->fbc_x0 = x;
   1323 	fbc->fbc_x1 = x + wi - 1;
   1324 	fbc->fbc_y0 = y;
   1325 	fbc->fbc_incx = 0;
   1326 	fbc->fbc_incy = 1;
   1327 	fbc->fbc_fg = fg;
   1328 	fbc->fbc_bg = bg;
   1329 	fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
   1330 	fbc->fbc_alu = GX_PATTERN_ONES | ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET);
   1331 	sc->sc_mono_width = wi;
   1332 	/* now feed the data into the chip */
   1333 }
   1334 
   1335 void
   1336 cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data)
   1337 {
   1338 	int i;
   1339 	uint32_t latch, res = 0, shift;
   1340 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1341 
   1342 	if (sc->sc_mono_width > 32) {
   1343 		/* ARGH! */
   1344 	} else
   1345 	{
   1346 		shift = 24;
   1347 		for (i = 0; i < count; i++) {
   1348 			latch = data[i];
   1349 			res |= latch << shift;
   1350 			shift -= 8;
   1351 		}
   1352 		fbc->fbc_font = res;
   1353 	}
   1354 }
   1355 
   1356 void
   1357 cgsix_putchar(void *cookie, int row, int col, u_int c, long attr)
   1358 {
   1359 	struct rasops_info *ri = cookie;
   1360 	struct wsdisplay_font *font = PICK_FONT(ri, c);
   1361 	struct vcons_screen *scr = ri->ri_hw;
   1362 	struct cgsix_softc *sc = scr->scr_cookie;
   1363 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1364 	int fg, bg, uc, i;
   1365 	uint8_t *data;
   1366 	int x, y, wi, he;
   1367 	int inv;
   1368 
   1369 	if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
   1370 		return;
   1371 
   1372 	if (!CHAR_IN_FONT(c, font))
   1373 		return;
   1374 
   1375 	if (row == ri->ri_crow && col == ri->ri_ccol) {
   1376 		ri->ri_flg &= ~RI_CURSOR;
   1377 	}
   1378 
   1379 	wi = font->fontwidth;
   1380 	he = font->fontheight;
   1381 
   1382 	inv = ((attr >> 8) & WSATTR_REVERSE);
   1383 	if (inv) {
   1384 		fg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff];
   1385 		bg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff];
   1386 	} else {
   1387 		bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff];
   1388 		fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff];
   1389 	}
   1390 
   1391 	x = ri->ri_xorigin + col * wi;
   1392 	y = ri->ri_yorigin + row * he;
   1393 
   1394 	if (c == 0x20) {
   1395 		cgsix_rectfill(sc, x, y, wi, he, bg);
   1396 	} else {
   1397 		uc = c - font->firstchar;
   1398 		data = (uint8_t *)font->data + uc * ri->ri_fontscale;
   1399 
   1400 		cgsix_setup_mono(sc, x, y, wi, 1, fg, bg);
   1401 		for (i = 0; i < he; i++) {
   1402 			cgsix_feed_line(sc, font->stride, data);
   1403 			data += font->stride;
   1404 		}
   1405 		/* put the chip back to normal */
   1406 		fbc->fbc_incy = 0;
   1407 	}
   1408 }
   1409 
   1410 void
   1411 cgsix_putchar_aa(void *cookie, int row, int col, u_int c, long attr)
   1412 {
   1413 	struct rasops_info *ri = cookie;
   1414 	struct wsdisplay_font *font = PICK_FONT(ri, c);
   1415 	struct vcons_screen *scr = ri->ri_hw;
   1416 	struct cgsix_softc *sc = scr->scr_cookie;
   1417 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1418 
   1419 	uint32_t bg, latch = 0, bg8, fg8, pixel;
   1420 	int i, j, shift, x, y, wi, he, r, g, b, aval;
   1421 	int r1, g1, b1, r0, g0, b0, fgo, bgo;
   1422 	uint8_t *data8;
   1423 	int rv;
   1424 
   1425 	if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
   1426 		return;
   1427 
   1428 	if (!CHAR_IN_FONT(c, font))
   1429 		return;
   1430 
   1431 	if (row == ri->ri_crow && col == ri->ri_ccol) {
   1432 		ri->ri_flg &= ~RI_CURSOR;
   1433 	}
   1434 
   1435 	wi = font->fontwidth;
   1436 	he = font->fontheight;
   1437 
   1438 	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
   1439 	x = ri->ri_xorigin + col * wi;
   1440 	y = ri->ri_yorigin + row * he;
   1441 	if (c == 0x20) {
   1442 		cgsix_rectfill(sc, x, y, wi, he, bg);
   1443 		return;
   1444 	}
   1445 
   1446 	rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
   1447 	if (rv == GC_OK)
   1448 		return;
   1449 
   1450 	data8 = WSFONT_GLYPH(c, font);
   1451 
   1452 	CG6_WAIT_READY(sc->sc_fbc);
   1453 	fbc->fbc_incx = 4;
   1454 	fbc->fbc_incy = 0;
   1455 	fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR8;
   1456 	fbc->fbc_alu = CG6_ALU_COPY;
   1457 	fbc->fbc_clipmaxx = x + wi - 1;
   1458 
   1459 	/*
   1460 	 * we need the RGB colours here, so get offsets into rasops_cmap
   1461 	 */
   1462 	fgo = ((attr >> 24) & 0xf) * 3;
   1463 	bgo = ((attr >> 16) & 0xf) * 3;
   1464 
   1465 	r0 = rasops_cmap[bgo];
   1466 	r1 = rasops_cmap[fgo];
   1467 	g0 = rasops_cmap[bgo + 1];
   1468 	g1 = rasops_cmap[fgo + 1];
   1469 	b0 = rasops_cmap[bgo + 2];
   1470 	b1 = rasops_cmap[fgo + 2];
   1471 #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6))
   1472 	bg8 = R3G3B2(r0, g0, b0);
   1473 	fg8 = R3G3B2(r1, g1, b1);
   1474 
   1475 	for (i = 0; i < he; i++) {
   1476 
   1477 		CG6_WAIT_READY(fbc);
   1478 		fbc->fbc_x0 = x;
   1479 		fbc->fbc_x1 = x + 3;
   1480 		fbc->fbc_y0 = y + i;
   1481 
   1482 		shift = 24;
   1483 		for (j = 0; j < wi; j++) {
   1484 			aval = *data8;
   1485 			if (aval == 0) {
   1486 				pixel = bg8;
   1487 			} else if (aval == 255) {
   1488 				pixel = fg8;
   1489 			} else {
   1490 				r = aval * r1 + (255 - aval) * r0;
   1491 				g = aval * g1 + (255 - aval) * g0;
   1492 				b = aval * b1 + (255 - aval) * b0;
   1493 				pixel = ((r & 0xe000) >> 8) |
   1494 					((g & 0xe000) >> 11) |
   1495 					((b & 0xc000) >> 14);
   1496 			}
   1497 			data8++;
   1498 
   1499 			latch |= pixel << shift;
   1500 			if (shift == 0) {
   1501 				fbc->fbc_font = latch;
   1502 				latch = 0;
   1503 				shift = 24;
   1504 			} else
   1505 				shift -= 8;
   1506 		}
   1507 		if (shift != 24)
   1508 			fbc->fbc_font = latch;
   1509 	}
   1510 	fbc->fbc_clipmaxx = 0x3fff;
   1511 
   1512 	if (rv == GC_ADD) {
   1513 		glyphcache_add(&sc->sc_gc, c, x, y);
   1514 	}
   1515 }
   1516 
   1517 void
   1518 cgsix_cursor(void *cookie, int on, int row, int col)
   1519 {
   1520 	struct rasops_info *ri = cookie;
   1521 	struct vcons_screen *scr = ri->ri_hw;
   1522 	struct cgsix_softc *sc = scr->scr_cookie;
   1523 	int x, y, wi, he;
   1524 
   1525 	wi = ri->ri_font->fontwidth;
   1526 	he = ri->ri_font->fontheight;
   1527 
   1528 	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
   1529 		if (on) {
   1530 			if (ri->ri_flg & RI_CURSOR) {
   1531 				cg6_ras_nuke_cursor(ri);
   1532 			}
   1533 			x = col * wi + ri->ri_xorigin;
   1534 			y = row * he + ri->ri_yorigin;
   1535 			cg6_invert(sc, x, y, wi, he);
   1536 			ri->ri_flg |= RI_CURSOR;
   1537 		}
   1538 		ri->ri_crow = row;
   1539 		ri->ri_ccol = col;
   1540 	} else
   1541 	{
   1542 		ri->ri_crow = row;
   1543 		ri->ri_ccol = col;
   1544 		ri->ri_flg &= ~RI_CURSOR;
   1545 	}
   1546 }
   1547 
   1548 void
   1549 cgsix_clearscreen(struct cgsix_softc *sc)
   1550 {
   1551 	struct rasops_info *ri = &cg6_console_screen.scr_ri;
   1552 
   1553 	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
   1554 		volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1555 
   1556 		CG6_WAIT_READY(fbc);
   1557 
   1558 		fbc->fbc_alu = CG6_ALU_FILL;
   1559 		fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
   1560 
   1561 		fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg];
   1562 		fbc->fbc_arectx = 0;
   1563 		fbc->fbc_arecty = 0;
   1564 		fbc->fbc_arectx = ri->ri_width - 1;
   1565 		fbc->fbc_arecty = ri->ri_height - 1;
   1566 		CG6_DRAW(fbc);
   1567 		ri->ri_flg &= ~RI_CURSOR;
   1568 	}
   1569 }
   1570 
   1571 void
   1572 cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he)
   1573 {
   1574 	volatile struct cg6_fbc *fbc = sc->sc_fbc;
   1575 
   1576 	CG6_WAIT_READY(fbc);
   1577 
   1578 	fbc->fbc_alu = CG6_ALU_FLIP;
   1579 	fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8;
   1580 	fbc->fbc_arecty = y;
   1581 	fbc->fbc_arectx = x;
   1582 	fbc->fbc_arecty = y + he - 1;
   1583 	fbc->fbc_arectx = x + wi - 1;
   1584 	CG6_DRAW(fbc);
   1585 }
   1586 
   1587