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