Home | History | Annotate | Line # | Download | only in tc
sfbplus.c revision 1.20
      1 /* $NetBSD: sfbplus.c,v 1.20 2003/12/17 03:59:33 ad Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999, 2000, 2001 Tohru Nishimura.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Tohru Nishimura
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.20 2003/12/17 03:59:33 ad Exp $");
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/kernel.h>
     39 #include <sys/device.h>
     40 #include <sys/malloc.h>
     41 #include <sys/buf.h>
     42 #include <sys/ioctl.h>
     43 
     44 #include <machine/bus.h>
     45 #include <machine/intr.h>
     46 
     47 #include <dev/wscons/wsconsio.h>
     48 #include <dev/wscons/wsdisplayvar.h>
     49 
     50 #include <dev/rasops/rasops.h>
     51 #include <dev/wsfont/wsfont.h>
     52 
     53 #include <dev/tc/tcvar.h>
     54 #include <dev/ic/bt459reg.h>
     55 #include <dev/ic/bt463reg.h>
     56 #include <dev/tc/sfbreg.h>
     57 #include <dev/pci/tgareg.h>
     58 
     59 #include <uvm/uvm_extern.h>
     60 
     61 #if defined(pmax)
     62 #define	machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
     63 #endif
     64 
     65 #if defined(alpha)
     66 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
     67 #endif
     68 
     69 /* Bt459/Bt463 hardware registers */
     70 #define bt_lo	0
     71 #define bt_hi	1
     72 #define bt_reg	2
     73 #define bt_cmap 3
     74 
     75 #define REG(base, index)	*((u_int32_t *)(base) + (index))
     76 #define SELECT(vdac, regno) do {			\
     77 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
     78 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
     79 	tc_wmb();					\
     80    } while (0)
     81 
     82 struct hwcmap256 {
     83 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
     84 	u_int8_t r[CMAP_SIZE];
     85 	u_int8_t g[CMAP_SIZE];
     86 	u_int8_t b[CMAP_SIZE];
     87 };
     88 
     89 struct hwcursor64 {
     90 	struct wsdisplay_curpos cc_pos;
     91 	struct wsdisplay_curpos cc_hot;
     92 	struct wsdisplay_curpos cc_size;
     93 	struct wsdisplay_curpos cc_magic;
     94 #define	CURSOR_MAX_SIZE	64
     95 	u_int8_t cc_color[6];
     96 	u_int64_t cc_image[CURSOR_MAX_SIZE];
     97 	u_int64_t cc_mask[CURSOR_MAX_SIZE];
     98 };
     99 
    100 struct hwops {
    101 	void (*setlut) __P((caddr_t, struct hwcmap256 *));
    102 	void (*getlut) __P((caddr_t, struct hwcmap256 *));
    103 	void (*visible) __P((caddr_t, int));
    104 	void (*locate) __P((caddr_t, struct hwcursor64 *));
    105 	void (*shape) __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    106 	void (*color) __P((caddr_t, u_int8_t *));
    107 };
    108 
    109 struct sfbp_softc {
    110 	struct device sc_dev;
    111 	vaddr_t sc_vaddr;
    112 	size_t sc_size;
    113 	struct rasops_info *sc_ri;
    114 	struct hwcmap256 sc_cmap;	/* software copy of colormap */
    115 	struct hwcursor64 sc_cursor;	/* software copy of cursor */
    116 	int sc_blanked;
    117 	int sc_curenb;			/* cursor sprite enabled */
    118 	int sc_changed;			/* need update of hardware */
    119 #define	WSDISPLAY_CMAP_DOLUT	0x20
    120 	int nscreens;
    121 	struct hwops sc_hwops;
    122 };
    123 
    124 #define	HX_MAGIC_X	368
    125 #define	HX_MAGIC_Y	38
    126 
    127 static int  sfbpmatch __P((struct device *, struct cfdata *, void *));
    128 static void sfbpattach __P((struct device *, struct device *, void *));
    129 
    130 CFATTACH_DECL(sfbp, sizeof(struct sfbp_softc),
    131     sfbpmatch, sfbpattach, NULL, NULL);
    132 
    133 static void sfbp_common_init __P((struct rasops_info *));
    134 static struct rasops_info sfbp_console_ri;
    135 static tc_addr_t sfbp_consaddr;
    136 
    137 static struct wsscreen_descr sfbp_stdscreen = {
    138 	"std", 0, 0,
    139 	NULL, /* textops */
    140 	0, 0,
    141 	WSSCREEN_REVERSE
    142 };
    143 
    144 static const struct wsscreen_descr *_sfb_scrlist[] = {
    145 	&sfbp_stdscreen,
    146 };
    147 
    148 static const struct wsscreen_list sfb_screenlist = {
    149 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    150 };
    151 
    152 static int	sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    153 static paddr_t	sfbmmap __P((void *, off_t, int));
    154 
    155 static int	sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    156 				      void **, int *, int *, long *));
    157 static void	sfb_free_screen __P((void *, void *));
    158 static int	sfb_show_screen __P((void *, void *, int,
    159 				     void (*) (void *, int, int), void *));
    160 static void sfbp_putchar __P((void *, int, int, u_int, long));
    161 static void sfbp_erasecols __P((void *, int, int, int, long));
    162 static void sfbp_eraserows __P((void *, int, int, long));
    163 static void sfbp_copyrows __P((void *, int, int, int));
    164 
    165 static const struct wsdisplay_accessops sfb_accessops = {
    166 	sfbioctl,
    167 	sfbmmap,
    168 	sfb_alloc_screen,
    169 	sfb_free_screen,
    170 	sfb_show_screen,
    171 	0 /* load_font */
    172 };
    173 
    174 static void bt459init __P((caddr_t));
    175 static void bt459visible __P((caddr_t, int));
    176 static void bt459locate __P((caddr_t, struct hwcursor64 *));
    177 static void bt459shape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    178 static void bt459color __P((caddr_t, u_int8_t *));
    179 static void bt459setlut __P((caddr_t, struct hwcmap256 *));
    180 
    181 static void sfbpvisible __P((caddr_t, int));
    182 static void sfbplocate __P((caddr_t, struct hwcursor64 *));
    183 static void sfbpshape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    184 static void bt463init __P((caddr_t));
    185 static void bt463color __P((caddr_t, u_int8_t *));
    186 static void noplut __P((caddr_t, struct hwcmap256 *));
    187 
    188 /* EXPORT */ int sfbp_cnattach __P((tc_addr_t));
    189 static int  sfbpintr __P((void *));
    190 static void sfbp_cmap_init __P((struct sfbp_softc *));
    191 static void sfbp_screenblank __P((struct sfbp_softc *, int));
    192 
    193 static int  get_cmap __P((struct sfbp_softc *, struct wsdisplay_cmap *));
    194 static int  set_cmap __P((struct sfbp_softc *, struct wsdisplay_cmap *));
    195 static int  set_cursor __P((struct sfbp_softc *, struct wsdisplay_cursor *));
    196 static int  get_cursor __P((struct sfbp_softc *, struct wsdisplay_cursor *));
    197 static void set_curpos __P((struct sfbp_softc *, struct wsdisplay_curpos *));
    198 
    199 /*
    200  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
    201  *   M M M M I I I I		M I M I M I M I
    202  *	[ before ]		   [ after ]
    203  *   3 2 1 0 3 2 1 0		0 0 1 1 2 2 3 3
    204  *   7 6 5 4 7 6 5 4		4 4 5 5 6 6 7 7
    205  */
    206 static const u_int8_t shuffle[256] = {
    207 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
    208 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
    209 	0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
    210 	0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
    211 	0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
    212 	0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
    213 	0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
    214 	0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
    215 	0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
    216 	0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
    217 	0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
    218 	0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
    219 	0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
    220 	0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
    221 	0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
    222 	0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
    223 	0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
    224 	0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
    225 	0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
    226 	0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
    227 	0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
    228 	0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
    229 	0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
    230 	0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
    231 	0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
    232 	0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
    233 	0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
    234 	0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
    235 	0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
    236 	0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
    237 	0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
    238 	0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
    239 };
    240 
    241 static int
    242 sfbpmatch(parent, match, aux)
    243 	struct device *parent;
    244 	struct cfdata *match;
    245 	void *aux;
    246 {
    247 	struct tc_attach_args *ta = aux;
    248 
    249 	if (strncmp("PMAGD   ", ta->ta_modname, TC_ROM_LLEN) != 0)
    250 		return (0);
    251 
    252 	return (1);
    253 }
    254 
    255 static void
    256 sfbpattach(parent, self, aux)
    257 	struct device *parent, *self;
    258 	void *aux;
    259 {
    260 	struct sfbp_softc *sc = (struct sfbp_softc *)self;
    261 	struct tc_attach_args *ta = aux;
    262 	struct rasops_info *ri;
    263 	struct wsemuldisplaydev_attach_args waa;
    264 	caddr_t asic;
    265 	int console;
    266 
    267 	console = (ta->ta_addr == sfbp_consaddr);
    268 	if (console) {
    269 		sc->sc_ri = ri = &sfbp_console_ri;
    270 		sc->nscreens = 1;
    271 	}
    272 	else {
    273 		MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info),
    274 			M_DEVBUF, M_NOWAIT);
    275 		if (ri == NULL) {
    276 			printf(": can't alloc memory\n");
    277 			return;
    278 		}
    279 		memset(ri, 0, sizeof(struct rasops_info));
    280 
    281 		ri->ri_hw = (void *)ta->ta_addr;
    282 		sfbp_common_init(ri);
    283 		sc->sc_ri = ri;
    284 	}
    285 	printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height,
    286 	    (ri->ri_depth != 32) ? 8 : 24);
    287 
    288 	sc->sc_vaddr = ta->ta_addr;
    289 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    290 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    291 	sc->sc_blanked = sc->sc_curenb = 0;
    292 
    293 	if (ri->ri_depth == 8) {
    294 		sc->sc_hwops.visible = bt459visible;
    295 		sc->sc_hwops.locate = bt459locate;
    296 		sc->sc_hwops.shape = bt459shape;
    297 		sc->sc_hwops.color = bt459color;
    298 		sc->sc_hwops.setlut = bt459setlut;
    299 		sc->sc_hwops.getlut = noplut;
    300 	} else {
    301 		sc->sc_hwops.visible = sfbpvisible;
    302 		sc->sc_hwops.locate = sfbplocate;
    303 		sc->sc_hwops.shape = sfbpshape;
    304 		sc->sc_hwops.color = bt463color;
    305 		sc->sc_hwops.setlut = noplut;
    306 		sc->sc_hwops.getlut = noplut;
    307 	}
    308 	sfbp_cmap_init(sc);
    309 
    310         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc);
    311 
    312 	asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
    313 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    314 	*(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1;
    315 
    316 	waa.console = console;
    317 	waa.scrdata = &sfb_screenlist;
    318 	waa.accessops = &sfb_accessops;
    319 	waa.accesscookie = sc;
    320 
    321 	config_found(self, &waa, wsemuldisplaydevprint);
    322 }
    323 
    324 static void
    325 sfbp_cmap_init(sc)
    326 	struct sfb_softc *sc;
    327 {
    328 	struct hwcmap256 *cm;
    329 	const u_int8_t *p;
    330 	int index;
    331 
    332 	if (sc->sc_ri->ri_depth != 8)
    333 		return;
    334 
    335 	cm = &sc->sc_cmap;
    336 	p = rasops_cmap;
    337 	for (index = 0; index < CMAP_SIZE; index++, p += 3) {
    338 		cm->r[index] = p[0];
    339 		cm->g[index] = p[1];
    340 		cm->b[index] = p[2];
    341 	}
    342 }
    343 
    344 static void
    345 sfbp_common_init(ri)
    346 	struct rasops_info *ri;
    347 {
    348 	caddr_t base, asic;
    349 	int i, depth, hsetup, vsetup, vbase, cookie;
    350 
    351 	base = (caddr_t)ri->ri_hw;
    352 	asic = base + SFB_ASIC_OFFSET;
    353 	hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP);
    354 	vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP);
    355 	i = *(u_int32_t *)(asic + SFB_ASIC_DEEP);
    356 	depth = (i & 01) ? 32 : 8;
    357 
    358 	/*
    359 	 * - neglect 0,1 cases of hsetup register.
    360 	 * - observed 804x600?, 644x480? values.
    361 	 */
    362 
    363 	*(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    364 	vbase *= (i & 0x20) ? 2048 : 4096;	/* VRAM chip size */
    365 	if (i & 1) vbase *= 4;			/* bytes per pixel */
    366 
    367 	*(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0;
    368 	*(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0;
    369 	*(u_int32_t *)(asic + SFB_ASIC_MODE) = 0;	/* MODE_SIMPLE */
    370 	*(u_int32_t *)(asic + SFB_ASIC_ROP) = 3;	/* ROP_COPY */
    371 
    372 	/* initialize colormap and cursor hardware */
    373 	if (depth != 32) {
    374 		*(u_int32_t *)(asic + 0x180000) = 0;	/* Bt459 reset */
    375 		bt459init(base + SFB_RAMDAC_OFFSET);
    376 	}
    377 	else {
    378 		bt463init(base + SFB_RAMDAC_OFFSET);
    379 	}
    380 
    381 	ri->ri_flg = RI_CENTER;
    382 	ri->ri_flg = 0;			/* XXX 32bpp RI_CENTER fails XXX */
    383 	ri->ri_depth = depth;
    384 	ri->ri_width = (hsetup & 0x1ff) << 2;
    385 	ri->ri_height = (vsetup & 0x7ff);
    386 	ri->ri_stride = ri->ri_width * (ri->ri_depth / 8);
    387 	ri->ri_bits = base + 0x800000 + vbase;
    388 
    389 	if (depth == 32) {
    390 		ri->ri_rnum = 8;
    391 		ri->ri_gnum = 8;
    392 		ri->ri_bnum = 8;
    393 		ri->ri_rpos = 16;
    394 		ri->ri_gpos = 8;
    395 		ri->ri_bpos = 0;
    396 	}
    397 
    398 	/* clear the screen */
    399 	memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    400 
    401 	wsfont_init();
    402 	/* prefer 12 pixel wide font */
    403 	cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
    404 	    WSDISPLAY_FONTORDER_L2R);
    405 	if (cookie <= 0)
    406 		cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
    407 		    WSDISPLAY_FONTORDER_L2R);
    408 	if (cookie <= 0) {
    409 		printf("sfbp: font table is empty\n");
    410 		return;
    411 	}
    412 
    413 	/* the accelerated sfbp_putchar() needs LSbit left */
    414 	if (wsfont_lock(cookie, &ri->ri_font)) {
    415 		printf("sfb: couldn't lock font\n");
    416 		return;
    417 	}
    418 	ri->ri_wsfcookie = cookie;
    419 
    420 	rasops_init(ri, 34, 80);
    421 
    422 	/* add our accelerated functions */
    423 	ri->ri_ops.putchar = sfbp_putchar;
    424 	ri->ri_ops.erasecols = sfbp_erasecols;
    425 	ri->ri_ops.copyrows = sfbp_copyrows;
    426 	ri->ri_ops.eraserows = sfbp_eraserows;
    427 
    428 	/* XXX shouldn't be global */
    429 	sfbp_stdscreen.nrows = ri->ri_rows;
    430 	sfbp_stdscreen.ncols = ri->ri_cols;
    431 	sfbp_stdscreen.textops = &ri->ri_ops;
    432 	sfbp_stdscreen.capabilities = ri->ri_caps;
    433 	/* our accelerated putchar can't underline */
    434 	sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
    435 }
    436 
    437 static int
    438 sfbioctl(v, cmd, data, flag, p)
    439 	void *v;
    440 	u_long cmd;
    441 	caddr_t data;
    442 	int flag;
    443 	struct proc *p;
    444 {
    445 	struct sfbp_softc *sc = v;
    446 	struct rasops_info *ri = sc->sc_ri;
    447 	int turnoff, s;
    448 
    449 	switch (cmd) {
    450 	case WSDISPLAYIO_GTYPE:
    451 		*(u_int *)data = WSDISPLAY_TYPE_SFBP;
    452 		return (0);
    453 
    454 	case WSDISPLAYIO_GINFO:
    455 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    456 		wsd_fbip->height = ri->ri_height;
    457 		wsd_fbip->width = ri->ri_width;
    458 		wsd_fbip->depth = ri->ri_depth;
    459 		wsd_fbip->cmsize = CMAP_SIZE;	/* XXX */
    460 #undef fbt
    461 		return (0);
    462 
    463 	case WSDISPLAYIO_GETCMAP:
    464 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    465 
    466 	case WSDISPLAYIO_PUTCMAP:
    467 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    468 
    469 	case WSDISPLAYIO_SVIDEO:
    470 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    471 		if ((sc->sc_blanked == 0) ^ turnoff) {
    472 			sc->sc_blanked = turnoff;
    473 #if 0 /* XXX later XXX */
    474 	Low order 3bit control visibilities of screen and builtin cursor.
    475 #endif	/* XXX XXX XXX */
    476 		}
    477 		return (0);
    478 
    479 	case WSDISPLAYIO_GVIDEO:
    480 		*(u_int *)data = sc->sc_blanked ?
    481 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    482 		return (0);
    483 
    484 	case WSDISPLAYIO_GCURPOS:
    485 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    486 		return (0);
    487 
    488 	case WSDISPLAYIO_SCURPOS:
    489 		s = spltty();
    490 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    491 		sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
    492 		splx(s);
    493 		return (0);
    494 
    495 	case WSDISPLAYIO_GCURMAX:
    496 		((struct wsdisplay_curpos *)data)->x =
    497 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    498 		return (0);
    499 
    500 	case WSDISPLAYIO_GCURSOR:
    501 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    502 
    503 	case WSDISPLAYIO_SCURSOR:
    504 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    505 
    506 	case WSDISPLAYIO_SMODE:
    507 		if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
    508 			s = spltty();
    509 			sfbp_cmap_init(sc);
    510 			sc->sc_curenb = 0;
    511 			sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
    512 			    WSDISPLAY_CMAP_DOLUT);
    513 			splx(s);
    514 		}
    515 		return (0);
    516 	}
    517 	}
    518 	return (EPASSTHROUGH);
    519 }
    520 
    521 paddr_t
    522 sfbmmap(v, offset, prot)
    523 	void *v;
    524 	off_t offset;
    525 	int prot;
    526 {
    527 	struct sfbp_softc *sc = v;
    528 
    529 	if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */
    530 		return (-1);
    531 	return machine_btop(sc->sc_vaddr + offset);
    532 }
    533 
    534 static int
    535 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    536 	void *v;
    537 	const struct wsscreen_descr *type;
    538 	void **cookiep;
    539 	int *curxp, *curyp;
    540 	long *attrp;
    541 {
    542 	struct sfbp_softc *sc = v;
    543 	struct rasops_info *ri = sc->sc_ri;
    544 	long defattr;
    545 
    546 	if (sc->nscreens > 0)
    547 		return (ENOMEM);
    548 
    549 	*cookiep = ri;		 /* one and only for now */
    550 	*curxp = 0;
    551 	*curyp = 0;
    552 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    553 	*attrp = defattr;
    554 	sc->nscreens++;
    555 	return (0);
    556 }
    557 
    558 void
    559 sfb_free_screen(v, cookie)
    560 	void *v;
    561 	void *cookie;
    562 {
    563 	struct sfbp_softc *sc = v;
    564 
    565 	if (sc->sc_ri == &sfbp_console_ri)
    566 		panic("sfb_free_screen: console");
    567 
    568 	sc->nscreens--;
    569 }
    570 
    571 static int
    572 sfb_show_screen(v, cookie, waitok, cb, cbarg)
    573 	void *v;
    574 	void *cookie;
    575 	int waitok;
    576 	void (*cb) __P((void *, int, int));
    577 	void *cbarg;
    578 {
    579 
    580 	return (0);
    581 }
    582 
    583 int
    584 sfbp_cnattach(addr)
    585 	tc_addr_t addr;
    586 {
    587 	struct rasops_info *ri;
    588 	long defattr;
    589 
    590 	ri = &sfbp_console_ri;
    591 	ri->ri_hw = (void *)addr;
    592 	sfbp_common_init(ri);
    593 	(*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr);
    594 	wsdisplay_cnattach(&sfbp_stdscreen, ri, 0, 0, defattr);
    595 	sfbp_consaddr = addr;
    596 	return (0);
    597 }
    598 
    599 static int
    600 sfbpintr(arg)
    601 	void *arg;
    602 {
    603 #define	cc (&sc->sc_cursor)
    604 	struct sfbp_softc *sc = arg;
    605 	caddr_t base, asic;
    606 	u_int32_t sisr;
    607 	int v;
    608 
    609 	base = (caddr_t)sc->sc_ri->ri_hw;
    610 	asic = base + SFB_ASIC_OFFSET;
    611 	sisr = *((u_int32_t *)asic + TGA_REG_SISR);
    612 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    613 
    614 	if (sc->sc_changed == 0)
    615 		goto done;
    616 
    617 	v = sc->sc_changed;
    618 	if (v & WSDISPLAY_CURSOR_DOCUR)
    619 		(*sc->sc_hwops.visible)(base, sc->sc_curenb);
    620 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT))
    621 		(*sc->sc_hwops.locate)(base, cc);
    622 	if (v & WSDISPLAY_CURSOR_DOCMAP)
    623 		(*sc->sc_hwops.color)(base, cc->cc_color);
    624 	if (v & WSDISPLAY_CURSOR_DOSHAPE)
    625 		(*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image);
    626 	if (v & WSDISPLAY_CMAP_DOLUT)
    627 		(*sc->sc_hwops.setlut)(base, &sc->sc_cmap);
    628 	sc->sc_changed = 0;
    629 done:
    630 	*((u_int32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb();
    631 	return (1);
    632 #undef cc
    633 }
    634 
    635 static void
    636 bt459init(vdac)
    637 	caddr_t vdac;
    638 {
    639 	const u_int8_t *p;
    640 	int i;
    641 
    642 	SELECT(vdac, BT459_IREG_COMMAND_0);
    643 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    644 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    645 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    646 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    647 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    648 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    649 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    650 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    651 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    652 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    653 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    654 
    655 	SELECT(vdac, BT459_IREG_CCR);
    656 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    657 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    658 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    659 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    660 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    661 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    662 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    663 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    664 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    665 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    666 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    667 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    668 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    669 
    670 	/* build sane colormap */
    671 	SELECT(vdac, 0);
    672 	p = rasops_cmap;
    673 	for (i = 0; i < CMAP_SIZE; i++, p += 3) {
    674 		REG(vdac, bt_cmap) = p[0];	tc_wmb();
    675 		REG(vdac, bt_cmap) = p[1];	tc_wmb();
    676 		REG(vdac, bt_cmap) = p[2];	tc_wmb();
    677 	}
    678 
    679 	/* clear out cursor image */
    680 	SELECT(vdac, BT459_IREG_CRAM_BASE);
    681 	for (i = 0; i < 1024; i++)
    682 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    683 
    684 	/*
    685 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    686 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    687 	 * image color.  CCOLOR_1 will be never used.
    688 	 */
    689 	SELECT(vdac, BT459_IREG_CCOLOR_1);
    690 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    691 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    692 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    693 
    694 	REG(vdac, bt_reg) = 0;		tc_wmb();
    695 	REG(vdac, bt_reg) = 0;		tc_wmb();
    696 	REG(vdac, bt_reg) = 0;		tc_wmb();
    697 
    698 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    699 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    700 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    701 }
    702 
    703 static void
    704 bt463init(vdac)
    705 	caddr_t vdac;
    706 {
    707 	int i;
    708 
    709 	SELECT(vdac, BT463_IREG_COMMAND_0);
    710 	REG(vdac, bt_reg) = 0x40;	tc_wmb();	/* CMD 0 */
    711 	REG(vdac, bt_reg) = 0x48;	tc_wmb();	/* CMD 1 */
    712 	REG(vdac, bt_reg) = 0xc0;	tc_wmb();	/* CMD 2 */
    713 	REG(vdac, bt_reg) = 0;		tc_wmb();	/* !? 204 !? */
    714 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  0:7  */
    715 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  8:15 */
    716 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 16:23 */
    717 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 24:27 */
    718 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  0:7  */
    719 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  8:15 */
    720 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 16:23 */
    721 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 24:27 */
    722 	REG(vdac, bt_reg) = 0x00;	tc_wmb();
    723 
    724 	SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
    725 	for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
    726 		REG(vdac, bt_reg) = 0x00;	/*   0:7  */
    727 		REG(vdac, bt_reg) = 0xe1;	/*   8:15 */
    728 		REG(vdac, bt_reg) = 0x81; 	/*  16:23 */
    729 	}
    730 }
    731 
    732 static int
    733 get_cmap(sc, p)
    734 	struct sfbp_softc *sc;
    735 	struct wsdisplay_cmap *p;
    736 {
    737 	u_int index = p->index, count = p->count;
    738 	int error;
    739 
    740 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
    741 		return (EINVAL);
    742 
    743 	error = copyout(&sc->sc_cmap.r[index], p->red, count);
    744 	if (error)
    745 		return error;
    746 	error = copyout(&sc->sc_cmap.g[index], p->green, count);
    747 	if (error)
    748 		return error;
    749 	error = copyout(&sc->sc_cmap.b[index], p->blue, count);
    750 	return error;
    751 }
    752 
    753 static int
    754 set_cmap(sc, p)
    755 	struct sfbp_softc *sc;
    756 	struct wsdisplay_cmap *p;
    757 {
    758 	struct hwcmap256 cmap;
    759 	u_int index = p->index, count = p->count;
    760 	int error, s;
    761 
    762 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
    763 		return (EINVAL);
    764 
    765 	error = copyin(p->red, &cmap.r[index], count);
    766 	if (error)
    767 		return error;
    768 	error = copyin(p->green, &cmap.g[index], count);
    769 	if (error)
    770 		return error;
    771 	error = copyin(p->blue, &cmap.b[index], count);
    772 	if (error)
    773 		return error;
    774 
    775 	s = spltty();
    776 	memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
    777 	memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
    778 	memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
    779 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    780 	splx(s);
    781 	return (0);
    782 }
    783 
    784 static int
    785 set_cursor(sc, p)
    786 	struct sfbp_softc *sc;
    787 	struct wsdisplay_cursor *p;
    788 {
    789 #define	cc (&sc->sc_cursor)
    790 	u_int v, index = 0, count = 0, icount = 0;
    791 	uint8_t r[2], g[2], b[2], image[512], mask[512];
    792 	int error, s;
    793 
    794 	v = p->which;
    795 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    796 		index = p->cmap.index;
    797 		count = p->cmap.count;
    798 		if (index >= 2 || (index + count) > 2)
    799 			return (EINVAL);
    800 		error = copyin(p->cmap.red, &r[index], count);
    801 		if (error)
    802 			return error;
    803 		error = copyin(p->cmap.green, &g[index], count);
    804 		if (error)
    805 			return error;
    806 		error = copyin(p->cmap.blue, &b[index], count);
    807 		if (error)
    808 			return error;
    809 	}
    810 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    811 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    812 			return (EINVAL);
    813 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    814 		error = copyin(p->image, image, icount);
    815 		if (error)
    816 			return error;
    817 		error = copyin(p->mask, mask, icount);
    818 		if (error)
    819 			return error;
    820 	}
    821 
    822 	s = spltty();
    823 	if (v & WSDISPLAY_CURSOR_DOCUR)
    824 		sc->sc_curenb = p->enable;
    825 	if (v & WSDISPLAY_CURSOR_DOPOS)
    826 		set_curpos(sc, &p->pos);
    827 	if (v & WSDISPLAY_CURSOR_DOHOT)
    828 		cc->cc_hot = p->hot;
    829 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    830 		memcpy(&cc->cc_color[index], &r[index], count);
    831 		memcpy(&cc->cc_color[index + 2], &g[index], count);
    832 		memcpy(&cc->cc_color[index + 4], &b[index], count);
    833 	}
    834 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    835 		cc->cc_size = p->size;
    836 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    837 		memcpy(cc->cc_image, image, icount);
    838 		memset(cc->cc_mask, 0, sizeof cc->cc_mask);
    839 		memcpy(cc->cc_mask, mask, icount);
    840 	}
    841 	sc->sc_changed |= v;
    842 	splx(s);
    843 
    844 	return (0);
    845 #undef cc
    846 }
    847 
    848 static int
    849 get_cursor(sc, p)
    850 	struct sfbp_softc *sc;
    851 	struct wsdisplay_cursor *p;
    852 {
    853 	return (EPASSTHROUGH); /* XXX */
    854 }
    855 
    856 static void
    857 set_curpos(sc, curpos)
    858 	struct sfbp_softc *sc;
    859 	struct wsdisplay_curpos *curpos;
    860 {
    861 	struct rasops_info *ri = sc->sc_ri;
    862 	int x = curpos->x, y = curpos->y;
    863 
    864 	if (y < 0)
    865 		y = 0;
    866 	else if (y > ri->ri_height)
    867 		y = ri->ri_height;
    868 	if (x < 0)
    869 		x = 0;
    870 	else if (x > ri->ri_width)
    871 		x = ri->ri_width;
    872 	sc->sc_cursor.cc_pos.x = x;
    873 	sc->sc_cursor.cc_pos.y = y;
    874 }
    875 
    876 static void
    877 bt459visible(hw, on)
    878 	caddr_t hw;
    879 	int on;
    880 {
    881 	hw += SFB_RAMDAC_OFFSET;
    882 	SELECT(hw, BT459_IREG_CCR);
    883 	REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
    884 	tc_wmb();
    885 }
    886 
    887 static void
    888 sfbpvisible(hw, on)
    889 	caddr_t hw;
    890 	int on;
    891 {
    892 	/* XXX use SFBplus ASIC XX */
    893 }
    894 
    895 static void
    896 bt459locate(hw, cc)
    897 	caddr_t hw;
    898 	struct hwcursor64 *cc;
    899 {
    900 	int x, y, s;
    901 
    902 	x = cc->cc_pos.x - cc->cc_hot.x;
    903 	y = cc->cc_pos.y - cc->cc_hot.y;
    904 	x += cc->cc_magic.x;
    905 	y += cc->cc_magic.y;
    906 
    907 	hw += SFB_RAMDAC_OFFSET;
    908 
    909 	s = spltty();
    910 	SELECT(hw, BT459_IREG_CURSOR_X_LOW);
    911 	REG(hw, bt_reg) = x;		tc_wmb();
    912 	REG(hw, bt_reg) = x >> 8;	tc_wmb();
    913 	REG(hw, bt_reg) = y;		tc_wmb();
    914 	REG(hw, bt_reg) = y >> 8;	tc_wmb();
    915 	splx(s);
    916 }
    917 
    918 static void
    919 sfbplocate(hw, cc)
    920 	caddr_t hw;
    921 	struct hwcursor64 *cc;
    922 {
    923 	int x, y;
    924 
    925 	x = cc->cc_pos.x - cc->cc_hot.x;
    926 	y = cc->cc_pos.y - cc->cc_hot.y;
    927 
    928 	hw += SFB_ASIC_OFFSET;
    929 	*((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
    930 	tc_wmb();
    931 }
    932 
    933 static void
    934 bt459color(hw, cp)
    935 	caddr_t hw;
    936 	u_int8_t *cp;
    937 {
    938 
    939 	hw += SFB_RAMDAC_OFFSET;
    940 
    941 	SELECT(hw, BT459_IREG_CCOLOR_2);
    942 	REG(hw, bt_reg) = cp[1]; tc_wmb();
    943 	REG(hw, bt_reg) = cp[3]; tc_wmb();
    944 	REG(hw, bt_reg) = cp[5]; tc_wmb();
    945 
    946 	REG(hw, bt_reg) = cp[0]; tc_wmb();
    947 	REG(hw, bt_reg) = cp[2]; tc_wmb();
    948 	REG(hw, bt_reg) = cp[4]; tc_wmb();
    949 }
    950 
    951 static void
    952 bt463color(hw, cp)
    953 	caddr_t hw;
    954 	u_int8_t *cp;
    955 {
    956 }
    957 
    958 static void
    959 bt459shape(hw, size, image)
    960 	caddr_t hw;
    961 	struct wsdisplay_curpos *size;
    962 	u_int64_t *image;
    963 {
    964 	u_int8_t *ip, *mp, img, msk;
    965 	u_int8_t u;
    966 	int bcnt;
    967 
    968 	hw += SFB_RAMDAC_OFFSET;
    969 	ip = (u_int8_t *)image;
    970 	mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
    971 
    972 	bcnt = 0;
    973 	SELECT(hw, BT459_IREG_CRAM_BASE+0);
    974 	/* 64 pixel scan line is consisted with 16 byte cursor ram */
    975 	while (bcnt < size->y * 16) {
    976 		/* pad right half 32 pixel when smaller than 33 */
    977 		if ((bcnt & 0x8) && size->x < 33) {
    978 			REG(hw, bt_reg) = 0; tc_wmb();
    979 			REG(hw, bt_reg) = 0; tc_wmb();
    980 		}
    981 		else {
    982 			img = *ip++;
    983 			msk = *mp++;
    984 			img &= msk;	/* cookie off image */
    985 			u = (msk & 0x0f) << 4 | (img & 0x0f);
    986 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    987 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
    988 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    989 		}
    990 		bcnt += 2;
    991 	}
    992 	/* pad unoccupied scan lines */
    993 	while (bcnt < CURSOR_MAX_SIZE * 16) {
    994 		REG(hw, bt_reg) = 0; tc_wmb();
    995 		REG(hw, bt_reg) = 0; tc_wmb();
    996 		bcnt += 2;
    997 	}
    998 }
    999 
   1000 static void
   1001 sfbpshape(hw, size, image)
   1002 	caddr_t hw;
   1003 	struct wsdisplay_curpos *size;
   1004 	u_int64_t *image;
   1005 {
   1006 	/* XXX use SFBplus ASIC XXX */
   1007 }
   1008 
   1009 static void
   1010 bt459setlut(hw, cm)
   1011 	caddr_t hw;
   1012 	struct hwcmap256 *cm;
   1013 {
   1014 	int index;
   1015 
   1016 	hw += SFB_RAMDAC_OFFSET;
   1017 	SELECT(hw, 0);
   1018 	for (index = 0; index < CMAP_SIZE; index++) {
   1019 		REG(hw, bt_cmap) = cm->r[index];	tc_wmb();
   1020 		REG(hw, bt_cmap) = cm->g[index];	tc_wmb();
   1021 		REG(hw, bt_cmap) = cm->b[index];	tc_wmb();
   1022 	}
   1023 }
   1024 
   1025 static void
   1026 noplut(hw, cm)
   1027 	caddr_t hw;
   1028 	struct hwcmap256 *cm;
   1029 {
   1030 }
   1031 
   1032 #define SFBBPP 32
   1033 
   1034 #define	MODE_SIMPLE		0
   1035 #define	MODE_OPAQUESTIPPLE	1
   1036 #define	MODE_OPAQUELINE		2
   1037 #define	MODE_TRANSPARENTSTIPPLE	5
   1038 #define	MODE_TRANSPARENTLINE	6
   1039 #define	MODE_COPY		7
   1040 
   1041 #if SFBBPP == 8
   1042 /* parameters for 8bpp configuration */
   1043 #define	SFBALIGNMASK		0x7
   1044 #define	SFBPIXELBYTES		1
   1045 #define	SFBSTIPPLEALL1		0xffffffff
   1046 #define	SFBSTIPPLEBITS		32
   1047 #define	SFBSTIPPLEBITMASK	0x1f
   1048 #define	SFBSTIPPLEBYTESDONE	32
   1049 #define	SFBCOPYALL1		0xffffffff
   1050 #define	SFBCOPYBITS		32
   1051 #define	SFBCOPYBITMASK		0x1f
   1052 #define	SFBCOPYBYTESDONE	32
   1053 
   1054 #elif SFBBPP == 32
   1055 /* parameters for 32bpp configuration */
   1056 #define	SFBALIGNMASK		0x7
   1057 #define	SFBPIXELBYTES		4
   1058 #define	SFBSTIPPLEALL1		0x0000ffff
   1059 #define	SFBSTIPPLEBITS		16
   1060 #define	SFBSTIPPLEBITMASK	0xf
   1061 #define	SFBSTIPPLEBYTESDONE	32
   1062 #define	SFBCOPYALL1		0x000000ff
   1063 #define	SFBCOPYBITS		8
   1064 #define	SFBCOPYBITMASK		0x3
   1065 #define	SFBCOPYBYTESDONE	32
   1066 #endif
   1067 
   1068 #ifdef pmax
   1069 #define	WRITE_MB()
   1070 #define	BUMP(p) (p)
   1071 #endif
   1072 
   1073 #ifdef alpha
   1074 #define	WRITE_MB() tc_wmb()
   1075 /* registers is replicated in 1KB stride; rap round 4th iteration */
   1076 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
   1077 #endif
   1078 
   1079 #define	SFBMODE(p, v) \
   1080 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
   1081 #define	SFBROP(p, v) \
   1082 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
   1083 #define	SFBPLANEMASK(p, v) \
   1084 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
   1085 #define	SFBPIXELMASK(p, v) \
   1086 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
   1087 #define	SFBADDRESS(p, v) \
   1088 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
   1089 #define	SFBSTART(p, v) \
   1090 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
   1091 #define	SFBPIXELSHIFT(p, v) \
   1092 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
   1093 #define	SFBFG(p, v) \
   1094 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
   1095 #define	SFBBG(p, v) \
   1096 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
   1097 #define	SFBBCONT(p, v) \
   1098 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
   1099 
   1100 #define	SFBDATA(p, v) \
   1101 		(*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
   1102 
   1103 #define	SFBCOPY64BYTESDONE	8
   1104 #define	SFBCOPY64BITS		64
   1105 #define	SFBCOPY64SRC(p, v) \
   1106 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
   1107 #define	SFBCOPY64DST(p, v) \
   1108 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
   1109 
   1110 /*
   1111  * Actually write a string to the frame buffer.
   1112  */
   1113 static void
   1114 sfbp_putchar(id, row, col, uc, attr)
   1115 	void *id;
   1116 	int row, col;
   1117 	u_int uc;
   1118 	long attr;
   1119 {
   1120 	struct rasops_info *ri = id;
   1121 	caddr_t sfb, p;
   1122 	int scanspan, height, width, align, x, y;
   1123 	u_int32_t lmask, rmask, glyph;
   1124 	u_int8_t *g;
   1125 
   1126 	x = col * ri->ri_font->fontwidth;
   1127 	y = row * ri->ri_font->fontheight;
   1128 	scanspan = ri->ri_stride;
   1129 	height = ri->ri_font->fontheight;
   1130 	uc -= ri->ri_font->firstchar;
   1131 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1132 
   1133 	p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
   1134 	align = (long)p & SFBALIGNMASK;
   1135 	p -= align;
   1136 	align /= SFBPIXELBYTES;
   1137 	width = ri->ri_font->fontwidth + align;
   1138 	lmask = SFBSTIPPLEALL1 << align;
   1139 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1140 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1141 
   1142 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1143 	SFBPLANEMASK(sfb, ~0);
   1144 	SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
   1145 	SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1146 	SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
   1147 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
   1148 
   1149 	/* XXX 2B stride fonts only XXX */
   1150 	while (height > 0) {
   1151 		glyph = *(u_int16_t *)g;		/* XXX */
   1152 		*(u_int32_t *)p = glyph << align;
   1153 		p += scanspan;
   1154 		g += 2;					/* XXX */
   1155 		height--;
   1156 	}
   1157 	SFBMODE(sfb, MODE_SIMPLE);
   1158 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
   1159 }
   1160 
   1161 #undef	SFBSTIPPLEALL1
   1162 #undef	SFBSTIPPLEBITS
   1163 #undef	SFBSTIPPLEBITMASK
   1164 #define	SFBSTIPPLEALL1		SFBCOPYALL1
   1165 #define	SFBSTIPPLEBITS		SFBCOPYBITS
   1166 #define	SFBSTIPPLEBITMASK	SFBCOPYBITMASK
   1167 
   1168 /*
   1169  * Clear characters in a line.
   1170  */
   1171 static void
   1172 sfbp_erasecols(id, row, startcol, ncols, attr)
   1173 	void *id;
   1174 	int row, startcol, ncols;
   1175 	long attr;
   1176 {
   1177 	struct rasops_info *ri = id;
   1178 	caddr_t sfb, p;
   1179 	int scanspan, startx, height, width, align, w, y;
   1180 	u_int32_t lmask, rmask;
   1181 
   1182 	scanspan = ri->ri_stride;
   1183 	y = row * ri->ri_font->fontheight;
   1184 	startx = startcol * ri->ri_font->fontwidth;
   1185 	height = ri->ri_font->fontheight;
   1186 	w = ri->ri_font->fontwidth * ncols;
   1187 
   1188 	p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
   1189 	align = (long)p & SFBALIGNMASK;
   1190 	align /= SFBPIXELBYTES;
   1191 	p -= align;
   1192 	width = w + align;
   1193 	lmask = SFBSTIPPLEALL1 << align;
   1194 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1195 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1196 
   1197 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1198 	SFBPLANEMASK(sfb, ~0);
   1199 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
   1200 	if (width <= SFBSTIPPLEBITS) {
   1201 		lmask = lmask & rmask;
   1202 		while (height > 0) {
   1203 			*(u_int32_t *)p = lmask;
   1204 			p += scanspan;
   1205 			height--;
   1206 		}
   1207 	}
   1208 	else {
   1209 		caddr_t q = p;
   1210 		while (height > 0) {
   1211 			*(u_int32_t *)p = lmask;
   1212 			WRITE_MB();
   1213 			width -= 2 * SFBSTIPPLEBITS;
   1214 			while (width > 0) {
   1215 				p += SFBSTIPPLEBYTESDONE;
   1216 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1217 				WRITE_MB();
   1218 				width -= SFBSTIPPLEBITS;
   1219 			}
   1220 			p += SFBSTIPPLEBYTESDONE;
   1221 			*(u_int32_t *)p = rmask;
   1222 			WRITE_MB();
   1223 
   1224 			p = (q += scanspan);
   1225 			width = w + align;
   1226 			height--;
   1227 		}
   1228 	}
   1229 	SFBMODE(sfb, MODE_SIMPLE);
   1230 }
   1231 
   1232 #if 1
   1233 /*
   1234  * Copy lines.
   1235  */
   1236 static void
   1237 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1238 	void *id;
   1239 	int srcrow, dstrow, nrows;
   1240 {
   1241 	struct rasops_info *ri = id;
   1242 	caddr_t sfb, p;
   1243 	int scanspan, offset, srcy, height, width, align, w;
   1244 	u_int32_t lmask, rmask;
   1245 
   1246 	scanspan = ri->ri_stride;
   1247 	height = ri->ri_font->fontheight * nrows;
   1248 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1249 	srcy = ri->ri_font->fontheight * srcrow;
   1250 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1251 		scanspan = -scanspan;
   1252 		srcy += height;
   1253 	}
   1254 
   1255 	p = ri->ri_bits + srcy * ri->ri_stride;
   1256 	align = (long)p & SFBALIGNMASK;
   1257 	p -= align;
   1258 	align /= SFBPIXELBYTES;
   1259 	w = ri->ri_emuwidth;
   1260 	width = w + align;
   1261 	lmask = SFBCOPYALL1 << align;
   1262 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1263 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1264 
   1265 	SFBMODE(sfb, MODE_COPY);
   1266 	SFBPLANEMASK(sfb, ~0);
   1267 	SFBPIXELSHIFT(sfb, 0);
   1268 	if (width <= SFBCOPYBITS) {
   1269 		/* never happens */;
   1270 	}
   1271 	else {
   1272 		caddr_t q = p;
   1273 		while (height > 0) {
   1274 			*(u_int32_t *)p = lmask;
   1275 			*(u_int32_t *)(p + offset) = lmask;
   1276 			width -= 2 * SFBCOPYBITS;
   1277 			while (width > 0) {
   1278 				p += SFBCOPYBYTESDONE;
   1279 				*(u_int32_t *)p = SFBCOPYALL1;
   1280 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1281 				width -= SFBCOPYBITS;
   1282 			}
   1283 			p += SFBCOPYBYTESDONE;
   1284 			*(u_int32_t *)p = rmask;
   1285 			*(u_int32_t *)(p + offset) = rmask;
   1286 
   1287 			p = (q += scanspan);
   1288 			width = w + align;
   1289 			height--;
   1290 		}
   1291 	}
   1292 	SFBMODE(sfb, MODE_SIMPLE);
   1293 }
   1294 
   1295 #else
   1296 
   1297 
   1298 static void
   1299 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1300 	void *id;
   1301 	int srcrow, dstrow, nrows;
   1302 {
   1303 	struct rasops_info *ri = id;
   1304 	caddr_t sfb, p, q;
   1305 	int scanspan, offset, srcy, height, width, w, align;
   1306 	u_int32_t rmask, lmask;
   1307 
   1308 	scanspan = ri->ri_stride;
   1309 	height = ri->ri_font->fontheight * nrows;
   1310 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1311 	srcy = ri->ri_font->fontheight * srcrow;
   1312 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1313 		scanspan = -scanspan;
   1314 		srcy += height;
   1315 	}
   1316 
   1317 	p = ri->ri_bits + srcy * ri->ri_stride;
   1318 	align = (long)p & SFBALIGNMASK;
   1319 	w = ri->ri_emuwidth;
   1320 	width = w + align;
   1321 	lmask = SFBCOPYALL1 << align;
   1322 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1323 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1324 	q = p;
   1325 
   1326 	SFBMODE(sfb, MODE_COPY);
   1327 	SFBPLANEMASK(sfb, ~0);
   1328 	SFBPIXELSHIFT(sfb, 0);
   1329 
   1330 	if (width <= SFBCOPYBITS)
   1331 		; /* never happens */
   1332 	else if (width < SFBCOPY64BITS) {
   1333 		; /* unlikely happens */
   1334 
   1335 	}
   1336 	else {
   1337 		while (height > 0) {
   1338 			while (width >= SFBCOPY64BITS) {
   1339 				SFBCOPY64SRC(sfb, p);
   1340 				SFBCOPY64DST(sfb, p + offset);
   1341 				p += SFBCOPY64BYTESDONE;
   1342 				width -= SFBCOPY64BITS;
   1343 			}
   1344 			if (width >= SFBCOPYBITS) {
   1345 				*(u_int32_t *)p = SFBCOPYALL1;
   1346 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1347 				p += SFBCOPYBYTESDONE;
   1348 				width -= SFBCOPYBITS;
   1349 			}
   1350 			if (width > 0) {
   1351 				*(u_int32_t *)p = rmask;
   1352 				*(u_int32_t *)(p + offset) = rmask;
   1353 			}
   1354 
   1355 			p = (q += scanspan);
   1356 			width = w;
   1357 			height--;
   1358 		}
   1359 	}
   1360 	SFBMODE(sfb, MODE_SIMPLE);
   1361 }
   1362 #endif
   1363 
   1364 /*
   1365  * Erase lines.
   1366  */
   1367 static void
   1368 sfbp_eraserows(id, startrow, nrows, attr)
   1369 	void *id;
   1370 	int startrow, nrows;
   1371 	long attr;
   1372 {
   1373 	struct rasops_info *ri = id;
   1374 	caddr_t sfb, p;
   1375 	int scanspan, starty, height, width, align, w;
   1376 	u_int32_t lmask, rmask;
   1377 
   1378 	scanspan = ri->ri_stride;
   1379 	starty = ri->ri_font->fontheight * startrow;
   1380 	height = ri->ri_font->fontheight * nrows;
   1381 
   1382 	p = ri->ri_bits + starty * scanspan;
   1383 	align = (long)p & SFBALIGNMASK;
   1384 	p -= align;
   1385 	align /= SFBPIXELBYTES;
   1386 	w = ri->ri_emuwidth * SFBPIXELBYTES;
   1387 	width = w + align;
   1388 	lmask = SFBSTIPPLEALL1 << align;
   1389 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1390 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1391 
   1392 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1393 	SFBPLANEMASK(sfb, ~0);
   1394 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1395 	if (width <= SFBSTIPPLEBITS) {
   1396 		/* never happens */;
   1397 	}
   1398 	else {
   1399 		caddr_t q = p;
   1400 		while (height > 0) {
   1401 			*(u_int32_t *)p = lmask;
   1402 			WRITE_MB();
   1403 			width -= 2 * SFBSTIPPLEBITS;
   1404 			while (width > 0) {
   1405 				p += SFBSTIPPLEBYTESDONE;
   1406 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1407 				WRITE_MB();
   1408 				width -= SFBSTIPPLEBITS;
   1409 			}
   1410 			p += SFBSTIPPLEBYTESDONE;
   1411 			*(u_int32_t *)p = rmask;
   1412 			WRITE_MB();
   1413 
   1414 			p = (q += scanspan);
   1415 			width = w + align;
   1416 			height--;
   1417 		}
   1418 	}
   1419 	SFBMODE(sfb, MODE_SIMPLE);
   1420 }
   1421