Home | History | Annotate | Line # | Download | only in tc
sfbplus.c revision 1.30
      1 /* $NetBSD: sfbplus.c,v 1.30 2008/05/26 10:31:22 nisimura 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.30 2008/05/26 10:31:22 nisimura 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/malloc.h>
     40 #include <sys/buf.h>
     41 #include <sys/ioctl.h>
     42 
     43 #include <sys/bus.h>
     44 #include <sys/intr.h>
     45 
     46 #include <dev/wscons/wsconsio.h>
     47 #include <dev/wscons/wsdisplayvar.h>
     48 
     49 #include <dev/rasops/rasops.h>
     50 #include <dev/wsfont/wsfont.h>
     51 
     52 #include <dev/tc/tcvar.h>
     53 #include <dev/ic/bt459reg.h>
     54 #include <dev/ic/bt463reg.h>
     55 #include <dev/tc/sfbreg.h>
     56 #include <dev/pci/tgareg.h>
     57 
     58 #include <uvm/uvm_extern.h>
     59 
     60 #if defined(pmax)
     61 #define	machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
     62 #endif
     63 
     64 #if defined(alpha)
     65 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
     66 #endif
     67 
     68 /* Bt459/Bt463 hardware registers */
     69 #define bt_lo	0
     70 #define bt_hi	1
     71 #define bt_reg	2
     72 #define bt_cmap 3
     73 
     74 #define REG(base, index)	*((u_int32_t *)(base) + (index))
     75 #define SELECT(vdac, regno) do {			\
     76 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
     77 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
     78 	tc_wmb();					\
     79    } while (0)
     80 
     81 struct hwcmap256 {
     82 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
     83 	u_int8_t r[CMAP_SIZE];
     84 	u_int8_t g[CMAP_SIZE];
     85 	u_int8_t b[CMAP_SIZE];
     86 };
     87 
     88 struct hwcursor64 {
     89 	struct wsdisplay_curpos cc_pos;
     90 	struct wsdisplay_curpos cc_hot;
     91 	struct wsdisplay_curpos cc_size;
     92 	struct wsdisplay_curpos cc_magic;
     93 #define	CURSOR_MAX_SIZE	64
     94 	u_int8_t cc_color[6];
     95 	u_int64_t cc_image[CURSOR_MAX_SIZE];
     96 	u_int64_t cc_mask[CURSOR_MAX_SIZE];
     97 };
     98 
     99 struct hwops {
    100 	void (*setlut)(void *, struct hwcmap256 *);
    101 	void (*getlut)(void *, struct hwcmap256 *);
    102 	void (*visible)(void *, int);
    103 	void (*locate)(void *, struct hwcursor64 *);
    104 	void (*shape)(void *, struct wsdisplay_curpos *, u_int64_t *);
    105 	void (*color)(void *, u_int8_t *);
    106 };
    107 
    108 struct sfbp_softc {
    109 	struct device sc_dev;
    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(struct device *, struct cfdata *, void *);
    127 static void sfbpattach(struct device *, struct device *, void *);
    128 
    129 CFATTACH_DECL(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 proc *);
    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 *, u_int64_t *);
    177 static void bt459color(void *, u_int8_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 *, u_int64_t *);
    183 static void bt463init(void *);
    184 static void bt463color(void *, u_int8_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 static void sfbp_screenblank(struct sfbp_softc *, int);
    191 
    192 static int  get_cmap(struct sfbp_softc *, struct wsdisplay_cmap *);
    193 static int  set_cmap(struct sfbp_softc *, struct wsdisplay_cmap *);
    194 static int  set_cursor(struct sfbp_softc *, struct wsdisplay_cursor *);
    195 static int  get_cursor(struct sfbp_softc *, struct wsdisplay_cursor *);
    196 static void set_curpos(struct sfbp_softc *, struct wsdisplay_curpos *);
    197 
    198 /*
    199  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
    200  *   M M M M I I I I		M I M I M I M I
    201  *	[ before ]		   [ after ]
    202  *   3 2 1 0 3 2 1 0		0 0 1 1 2 2 3 3
    203  *   7 6 5 4 7 6 5 4		4 4 5 5 6 6 7 7
    204  */
    205 static const u_int8_t shuffle[256] = {
    206 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
    207 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
    208 	0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
    209 	0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
    210 	0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
    211 	0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
    212 	0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
    213 	0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
    214 	0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
    215 	0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
    216 	0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
    217 	0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
    218 	0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
    219 	0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
    220 	0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
    221 	0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
    222 	0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
    223 	0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
    224 	0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
    225 	0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
    226 	0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
    227 	0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
    228 	0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
    229 	0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
    230 	0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
    231 	0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
    232 	0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
    233 	0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
    234 	0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
    235 	0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
    236 	0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
    237 	0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
    238 };
    239 
    240 static int
    241 sfbpmatch(struct device *parent, struct cfdata *match, void *aux)
    242 {
    243 	struct tc_attach_args *ta = aux;
    244 
    245 	if (strncmp("PMAGD   ", ta->ta_modname, TC_ROM_LLEN) != 0)
    246 		return (0);
    247 
    248 	return (1);
    249 }
    250 
    251 static void
    252 sfbpattach(struct device *parent, struct device *self, void *aux)
    253 {
    254 	struct sfbp_softc *sc = device_private(self);
    255 	struct tc_attach_args *ta = aux;
    256 	struct rasops_info *ri;
    257 	struct wsemuldisplaydev_attach_args waa;
    258 	void *asic;
    259 	int console;
    260 
    261 	console = (ta->ta_addr == sfbp_consaddr);
    262 	if (console) {
    263 		sc->sc_ri = ri = &sfbp_console_ri;
    264 		sc->nscreens = 1;
    265 	}
    266 	else {
    267 		MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info),
    268 			M_DEVBUF, M_NOWAIT);
    269 		if (ri == NULL) {
    270 			printf(": can't alloc memory\n");
    271 			return;
    272 		}
    273 		memset(ri, 0, sizeof(struct rasops_info));
    274 
    275 		ri->ri_hw = (void *)ta->ta_addr;
    276 		sfbp_common_init(ri);
    277 		sc->sc_ri = ri;
    278 	}
    279 	printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height,
    280 	    (ri->ri_depth != 32) ? 8 : 24);
    281 
    282 	sc->sc_vaddr = ta->ta_addr;
    283 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    284 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    285 	sc->sc_blanked = sc->sc_curenb = 0;
    286 
    287 	if (ri->ri_depth == 8) {
    288 		sc->sc_hwops.visible = bt459visible;
    289 		sc->sc_hwops.locate = bt459locate;
    290 		sc->sc_hwops.shape = bt459shape;
    291 		sc->sc_hwops.color = bt459color;
    292 		sc->sc_hwops.setlut = bt459setlut;
    293 		sc->sc_hwops.getlut = noplut;
    294 	} else {
    295 		sc->sc_hwops.visible = sfbpvisible;
    296 		sc->sc_hwops.locate = sfbplocate;
    297 		sc->sc_hwops.shape = sfbpshape;
    298 		sc->sc_hwops.color = bt463color;
    299 		sc->sc_hwops.setlut = noplut;
    300 		sc->sc_hwops.getlut = noplut;
    301 	}
    302 	sfbp_cmap_init(sc);
    303 
    304         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc);
    305 
    306 	asic = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
    307 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    308 	*(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1;
    309 
    310 	waa.console = console;
    311 	waa.scrdata = &sfb_screenlist;
    312 	waa.accessops = &sfb_accessops;
    313 	waa.accesscookie = sc;
    314 
    315 	config_found(self, &waa, wsemuldisplaydevprint);
    316 }
    317 
    318 static void
    319 sfbp_cmap_init(struct sfbp_softc *sc)
    320 {
    321 	struct hwcmap256 *cm;
    322 	const u_int8_t *p;
    323 	int index;
    324 
    325 	if (sc->sc_ri->ri_depth != 8)
    326 		return;
    327 
    328 	cm = &sc->sc_cmap;
    329 	p = rasops_cmap;
    330 	for (index = 0; index < CMAP_SIZE; index++, p += 3) {
    331 		cm->r[index] = p[0];
    332 		cm->g[index] = p[1];
    333 		cm->b[index] = p[2];
    334 	}
    335 }
    336 
    337 static void
    338 sfbp_common_init(struct rasops_info *ri)
    339 {
    340 	void *base, *asic;
    341 	int i, depth, hsetup, vsetup, vbase, cookie;
    342 
    343 	base = (void *)ri->ri_hw;
    344 	asic = base + SFB_ASIC_OFFSET;
    345 	hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP);
    346 	vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP);
    347 	i = *(u_int32_t *)(asic + SFB_ASIC_DEEP);
    348 	depth = (i & 01) ? 32 : 8;
    349 
    350 	/*
    351 	 * - neglect 0,1 cases of hsetup register.
    352 	 * - observed 804x600?, 644x480? values.
    353 	 */
    354 
    355 	*(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    356 	vbase *= (i & 0x20) ? 2048 : 4096;	/* VRAM chip size */
    357 	if (i & 1) vbase *= 4;			/* bytes per pixel */
    358 
    359 	*(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0;
    360 	*(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0;
    361 	*(u_int32_t *)(asic + SFB_ASIC_MODE) = 0;	/* MODE_SIMPLE */
    362 	*(u_int32_t *)(asic + SFB_ASIC_ROP) = 3;	/* ROP_COPY */
    363 
    364 	/* initialize colormap and cursor hardware */
    365 	if (depth != 32) {
    366 		*(u_int32_t *)(asic + 0x180000) = 0;	/* Bt459 reset */
    367 		bt459init(base + SFB_RAMDAC_OFFSET);
    368 	}
    369 	else {
    370 		bt463init(base + SFB_RAMDAC_OFFSET);
    371 	}
    372 
    373 	ri->ri_flg = RI_CENTER;
    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 proc *p)
    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 	}
    505 	return (EPASSTHROUGH);
    506 }
    507 
    508 paddr_t
    509 sfbmmap(void *v, void *vs, off_t offset, int prot)
    510 {
    511 	struct sfbp_softc *sc = v;
    512 
    513 	if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */
    514 		return (-1);
    515 	return machine_btop(sc->sc_vaddr + offset);
    516 }
    517 
    518 static int
    519 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    520     int *curxp, int *curyp, long *attrp)
    521 {
    522 	struct sfbp_softc *sc = v;
    523 	struct rasops_info *ri = sc->sc_ri;
    524 	long defattr;
    525 
    526 	if (sc->nscreens > 0)
    527 		return (ENOMEM);
    528 
    529 	*cookiep = ri;		 /* one and only for now */
    530 	*curxp = 0;
    531 	*curyp = 0;
    532 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    533 	*attrp = defattr;
    534 	sc->nscreens++;
    535 	return (0);
    536 }
    537 
    538 void
    539 sfb_free_screen(void *v, void *cookie)
    540 {
    541 	struct sfbp_softc *sc = v;
    542 
    543 	if (sc->sc_ri == &sfbp_console_ri)
    544 		panic("sfb_free_screen: console");
    545 
    546 	sc->nscreens--;
    547 }
    548 
    549 static int
    550 sfb_show_screen(void *v, void *cookie, int waitok,
    551     void (*cb)(void *, int, int), void *cbarg)
    552 {
    553 
    554 	return (0);
    555 }
    556 
    557 int
    558 sfbp_cnattach(tc_addr_t addr)
    559 {
    560 	struct rasops_info *ri;
    561 	long defattr;
    562 
    563 	ri = &sfbp_console_ri;
    564 	ri->ri_hw = (void *)addr;
    565 	sfbp_common_init(ri);
    566 	(*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr);
    567 	wsdisplay_cnattach(&sfbp_stdscreen, ri, 0, 0, defattr);
    568 	sfbp_consaddr = addr;
    569 	return (0);
    570 }
    571 
    572 static int
    573 sfbpintr(void *arg)
    574 {
    575 #define	cc (&sc->sc_cursor)
    576 	struct sfbp_softc *sc = arg;
    577 	void *base, *asic;
    578 	u_int32_t sisr;
    579 	int v;
    580 
    581 	base = (void *)sc->sc_ri->ri_hw;
    582 	asic = base + SFB_ASIC_OFFSET;
    583 	sisr = *((u_int32_t *)asic + TGA_REG_SISR);
    584 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    585 
    586 	if (sc->sc_changed == 0)
    587 		goto done;
    588 
    589 	v = sc->sc_changed;
    590 	if (v & WSDISPLAY_CURSOR_DOCUR)
    591 		(*sc->sc_hwops.visible)(base, sc->sc_curenb);
    592 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT))
    593 		(*sc->sc_hwops.locate)(base, cc);
    594 	if (v & WSDISPLAY_CURSOR_DOCMAP)
    595 		(*sc->sc_hwops.color)(base, cc->cc_color);
    596 	if (v & WSDISPLAY_CURSOR_DOSHAPE)
    597 		(*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image);
    598 	if (v & WSDISPLAY_CMAP_DOLUT)
    599 		(*sc->sc_hwops.setlut)(base, &sc->sc_cmap);
    600 	sc->sc_changed = 0;
    601 done:
    602 	*((u_int32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb();
    603 	return (1);
    604 #undef cc
    605 }
    606 
    607 static void
    608 bt459init(void *vdac)
    609 {
    610 	const u_int8_t *p;
    611 	int i;
    612 
    613 	SELECT(vdac, BT459_IREG_COMMAND_0);
    614 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    615 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    616 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    617 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    618 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    619 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    620 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    621 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    622 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    623 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    624 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    625 
    626 	SELECT(vdac, BT459_IREG_CCR);
    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 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    640 
    641 	/* build sane colormap */
    642 	SELECT(vdac, 0);
    643 	p = rasops_cmap;
    644 	for (i = 0; i < CMAP_SIZE; i++, p += 3) {
    645 		REG(vdac, bt_cmap) = p[0];	tc_wmb();
    646 		REG(vdac, bt_cmap) = p[1];	tc_wmb();
    647 		REG(vdac, bt_cmap) = p[2];	tc_wmb();
    648 	}
    649 
    650 	/* clear out cursor image */
    651 	SELECT(vdac, BT459_IREG_CRAM_BASE);
    652 	for (i = 0; i < 1024; i++)
    653 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    654 
    655 	/*
    656 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    657 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    658 	 * image color.  CCOLOR_1 will be never used.
    659 	 */
    660 	SELECT(vdac, BT459_IREG_CCOLOR_1);
    661 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    662 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    663 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    664 
    665 	REG(vdac, bt_reg) = 0;		tc_wmb();
    666 	REG(vdac, bt_reg) = 0;		tc_wmb();
    667 	REG(vdac, bt_reg) = 0;		tc_wmb();
    668 
    669 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    670 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    671 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    672 }
    673 
    674 static void
    675 bt463init(void *vdac)
    676 {
    677 	int i;
    678 
    679 	SELECT(vdac, BT463_IREG_COMMAND_0);
    680 	REG(vdac, bt_reg) = 0x40;	tc_wmb();	/* CMD 0 */
    681 	REG(vdac, bt_reg) = 0x48;	tc_wmb();	/* CMD 1 */
    682 	REG(vdac, bt_reg) = 0xc0;	tc_wmb();	/* CMD 2 */
    683 	REG(vdac, bt_reg) = 0;		tc_wmb();	/* !? 204 !? */
    684 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  0:7  */
    685 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  8:15 */
    686 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 16:23 */
    687 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 24:27 */
    688 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  0:7  */
    689 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  8:15 */
    690 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 16:23 */
    691 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 24:27 */
    692 	REG(vdac, bt_reg) = 0x00;	tc_wmb();
    693 
    694 	SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
    695 	for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
    696 		REG(vdac, bt_reg) = 0x00;	/*   0:7  */
    697 		REG(vdac, bt_reg) = 0xe1;	/*   8:15 */
    698 		REG(vdac, bt_reg) = 0x81; 	/*  16:23 */
    699 	}
    700 }
    701 
    702 static int
    703 get_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p)
    704 {
    705 	u_int index = p->index, count = p->count;
    706 	int error;
    707 
    708 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
    709 		return (EINVAL);
    710 
    711 	error = copyout(&sc->sc_cmap.r[index], p->red, count);
    712 	if (error)
    713 		return error;
    714 	error = copyout(&sc->sc_cmap.g[index], p->green, count);
    715 	if (error)
    716 		return error;
    717 	error = copyout(&sc->sc_cmap.b[index], p->blue, count);
    718 	return error;
    719 }
    720 
    721 static int
    722 set_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p)
    723 {
    724 	struct hwcmap256 cmap;
    725 	u_int index = p->index, count = p->count;
    726 	int error, s;
    727 
    728 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
    729 		return (EINVAL);
    730 
    731 	error = copyin(p->red, &cmap.r[index], count);
    732 	if (error)
    733 		return error;
    734 	error = copyin(p->green, &cmap.g[index], count);
    735 	if (error)
    736 		return error;
    737 	error = copyin(p->blue, &cmap.b[index], count);
    738 	if (error)
    739 		return error;
    740 
    741 	s = spltty();
    742 	memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
    743 	memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
    744 	memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
    745 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    746 	splx(s);
    747 	return (0);
    748 }
    749 
    750 static int
    751 set_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p)
    752 {
    753 #define	cc (&sc->sc_cursor)
    754 	u_int v, index = 0, count = 0, icount = 0;
    755 	uint8_t r[2], g[2], b[2], image[512], mask[512];
    756 	int error, s;
    757 
    758 	v = p->which;
    759 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    760 		index = p->cmap.index;
    761 		count = p->cmap.count;
    762 		if (index >= 2 || (index + count) > 2)
    763 			return (EINVAL);
    764 		error = copyin(p->cmap.red, &r[index], count);
    765 		if (error)
    766 			return error;
    767 		error = copyin(p->cmap.green, &g[index], count);
    768 		if (error)
    769 			return error;
    770 		error = copyin(p->cmap.blue, &b[index], count);
    771 		if (error)
    772 			return error;
    773 	}
    774 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    775 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    776 			return (EINVAL);
    777 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    778 		error = copyin(p->image, image, icount);
    779 		if (error)
    780 			return error;
    781 		error = copyin(p->mask, mask, icount);
    782 		if (error)
    783 			return error;
    784 	}
    785 
    786 	s = spltty();
    787 	if (v & WSDISPLAY_CURSOR_DOCUR)
    788 		sc->sc_curenb = p->enable;
    789 	if (v & WSDISPLAY_CURSOR_DOPOS)
    790 		set_curpos(sc, &p->pos);
    791 	if (v & WSDISPLAY_CURSOR_DOHOT)
    792 		cc->cc_hot = p->hot;
    793 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    794 		memcpy(&cc->cc_color[index], &r[index], count);
    795 		memcpy(&cc->cc_color[index + 2], &g[index], count);
    796 		memcpy(&cc->cc_color[index + 4], &b[index], count);
    797 	}
    798 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    799 		cc->cc_size = p->size;
    800 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    801 		memcpy(cc->cc_image, image, icount);
    802 		memset(cc->cc_mask, 0, sizeof cc->cc_mask);
    803 		memcpy(cc->cc_mask, mask, icount);
    804 	}
    805 	sc->sc_changed |= v;
    806 	splx(s);
    807 
    808 	return (0);
    809 #undef cc
    810 }
    811 
    812 static int
    813 get_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p)
    814 {
    815 	return (EPASSTHROUGH); /* XXX */
    816 }
    817 
    818 static void
    819 set_curpos(struct sfbp_softc *sc, struct wsdisplay_curpos *curpos)
    820 {
    821 	struct rasops_info *ri = sc->sc_ri;
    822 	int x = curpos->x, y = curpos->y;
    823 
    824 	if (y < 0)
    825 		y = 0;
    826 	else if (y > ri->ri_height)
    827 		y = ri->ri_height;
    828 	if (x < 0)
    829 		x = 0;
    830 	else if (x > ri->ri_width)
    831 		x = ri->ri_width;
    832 	sc->sc_cursor.cc_pos.x = x;
    833 	sc->sc_cursor.cc_pos.y = y;
    834 }
    835 
    836 static void
    837 bt459visible(void *hw, int on)
    838 {
    839 	hw += SFB_RAMDAC_OFFSET;
    840 	SELECT(hw, BT459_IREG_CCR);
    841 	REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
    842 	tc_wmb();
    843 }
    844 
    845 static void
    846 sfbpvisible(void *hw, int on)
    847 {
    848 	/* XXX use SFBplus ASIC XX */
    849 }
    850 
    851 static void
    852 bt459locate(void *hw, struct hwcursor64 *cc)
    853 {
    854 	int x, y, s;
    855 
    856 	x = cc->cc_pos.x - cc->cc_hot.x;
    857 	y = cc->cc_pos.y - cc->cc_hot.y;
    858 	x += cc->cc_magic.x;
    859 	y += cc->cc_magic.y;
    860 
    861 	hw += SFB_RAMDAC_OFFSET;
    862 
    863 	s = spltty();
    864 	SELECT(hw, BT459_IREG_CURSOR_X_LOW);
    865 	REG(hw, bt_reg) = x;		tc_wmb();
    866 	REG(hw, bt_reg) = x >> 8;	tc_wmb();
    867 	REG(hw, bt_reg) = y;		tc_wmb();
    868 	REG(hw, bt_reg) = y >> 8;	tc_wmb();
    869 	splx(s);
    870 }
    871 
    872 static void
    873 sfbplocate(void *hw, struct hwcursor64 *cc)
    874 {
    875 	int x, y;
    876 
    877 	x = cc->cc_pos.x - cc->cc_hot.x;
    878 	y = cc->cc_pos.y - cc->cc_hot.y;
    879 
    880 	hw += SFB_ASIC_OFFSET;
    881 	*((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
    882 	tc_wmb();
    883 }
    884 
    885 static void
    886 bt459color(void *hw, u_int8_t *cp)
    887 {
    888 
    889 	hw += SFB_RAMDAC_OFFSET;
    890 
    891 	SELECT(hw, BT459_IREG_CCOLOR_2);
    892 	REG(hw, bt_reg) = cp[1]; tc_wmb();
    893 	REG(hw, bt_reg) = cp[3]; tc_wmb();
    894 	REG(hw, bt_reg) = cp[5]; tc_wmb();
    895 
    896 	REG(hw, bt_reg) = cp[0]; tc_wmb();
    897 	REG(hw, bt_reg) = cp[2]; tc_wmb();
    898 	REG(hw, bt_reg) = cp[4]; tc_wmb();
    899 }
    900 
    901 static void
    902 bt463color(void *hw, u_int8_t *cp)
    903 {
    904 }
    905 
    906 static void
    907 bt459shape(void *hw, struct wsdisplay_curpos *size, u_int64_t *image)
    908 {
    909 	u_int8_t *ip, *mp, img, msk;
    910 	u_int8_t u;
    911 	int bcnt;
    912 
    913 	hw += SFB_RAMDAC_OFFSET;
    914 	ip = (u_int8_t *)image;
    915 	mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
    916 
    917 	bcnt = 0;
    918 	SELECT(hw, BT459_IREG_CRAM_BASE+0);
    919 	/* 64 pixel scan line is consisted with 16 byte cursor ram */
    920 	while (bcnt < size->y * 16) {
    921 		/* pad right half 32 pixel when smaller than 33 */
    922 		if ((bcnt & 0x8) && size->x < 33) {
    923 			REG(hw, bt_reg) = 0; tc_wmb();
    924 			REG(hw, bt_reg) = 0; tc_wmb();
    925 		}
    926 		else {
    927 			img = *ip++;
    928 			msk = *mp++;
    929 			img &= msk;	/* cookie off image */
    930 			u = (msk & 0x0f) << 4 | (img & 0x0f);
    931 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    932 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
    933 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    934 		}
    935 		bcnt += 2;
    936 	}
    937 	/* pad unoccupied scan lines */
    938 	while (bcnt < CURSOR_MAX_SIZE * 16) {
    939 		REG(hw, bt_reg) = 0; tc_wmb();
    940 		REG(hw, bt_reg) = 0; tc_wmb();
    941 		bcnt += 2;
    942 	}
    943 }
    944 
    945 static void
    946 sfbpshape(void *hw, struct wsdisplay_curpos *size, u_int64_t *image)
    947 {
    948 	/* XXX use SFBplus ASIC XXX */
    949 }
    950 
    951 static void
    952 bt459setlut(void *hw, struct hwcmap265 *cm)
    953 {
    954 	int index;
    955 
    956 	hw += SFB_RAMDAC_OFFSET;
    957 	SELECT(hw, 0);
    958 	for (index = 0; index < CMAP_SIZE; index++) {
    959 		REG(hw, bt_cmap) = cm->r[index];	tc_wmb();
    960 		REG(hw, bt_cmap) = cm->g[index];	tc_wmb();
    961 		REG(hw, bt_cmap) = cm->b[index];	tc_wmb();
    962 	}
    963 }
    964 
    965 static void
    966 noplut(void *hw, struct hwcmap265 *cm)
    967 {
    968 }
    969 
    970 #define SFBBPP 32
    971 
    972 #define	MODE_SIMPLE		0
    973 #define	MODE_OPAQUESTIPPLE	1
    974 #define	MODE_OPAQUELINE		2
    975 #define	MODE_TRANSPARENTSTIPPLE	5
    976 #define	MODE_TRANSPARENTLINE	6
    977 #define	MODE_COPY		7
    978 
    979 #if SFBBPP == 8
    980 /* parameters for 8bpp configuration */
    981 #define	SFBALIGNMASK		0x7
    982 #define	SFBPIXELBYTES		1
    983 #define	SFBSTIPPLEALL1		0xffffffff
    984 #define	SFBSTIPPLEBITS		32
    985 #define	SFBSTIPPLEBITMASK	0x1f
    986 #define	SFBSTIPPLEBYTESDONE	32
    987 #define	SFBCOPYALL1		0xffffffff
    988 #define	SFBCOPYBITS		32
    989 #define	SFBCOPYBITMASK		0x1f
    990 #define	SFBCOPYBYTESDONE	32
    991 
    992 #elif SFBBPP == 32
    993 /* parameters for 32bpp configuration */
    994 #define	SFBALIGNMASK		0x7
    995 #define	SFBPIXELBYTES		4
    996 #define	SFBSTIPPLEALL1		0x0000ffff
    997 #define	SFBSTIPPLEBITS		16
    998 #define	SFBSTIPPLEBITMASK	0xf
    999 #define	SFBSTIPPLEBYTESDONE	32
   1000 #define	SFBCOPYALL1		0x000000ff
   1001 #define	SFBCOPYBITS		8
   1002 #define	SFBCOPYBITMASK		0x3
   1003 #define	SFBCOPYBYTESDONE	32
   1004 #endif
   1005 
   1006 #ifdef pmax
   1007 #define	WRITE_MB()
   1008 #define	BUMP(p) (p)
   1009 #endif
   1010 
   1011 #ifdef alpha
   1012 #define	WRITE_MB() tc_wmb()
   1013 /* registers is replicated in 1KB stride; rap round 4th iteration */
   1014 #define	BUMP(p) ((p) = (void *)(((long)(p) + 0x400) & ~0x1000))
   1015 #endif
   1016 
   1017 #define	SFBMODE(p, v) \
   1018 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
   1019 #define	SFBROP(p, v) \
   1020 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
   1021 #define	SFBPLANEMASK(p, v) \
   1022 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
   1023 #define	SFBPIXELMASK(p, v) \
   1024 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
   1025 #define	SFBADDRESS(p, v) \
   1026 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
   1027 #define	SFBSTART(p, v) \
   1028 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
   1029 #define	SFBPIXELSHIFT(p, v) \
   1030 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
   1031 #define	SFBFG(p, v) \
   1032 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
   1033 #define	SFBBG(p, v) \
   1034 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
   1035 #define	SFBBCONT(p, v) \
   1036 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
   1037 
   1038 #define	SFBDATA(p, v) \
   1039 		(*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
   1040 
   1041 #define	SFBCOPY64BYTESDONE	8
   1042 #define	SFBCOPY64BITS		64
   1043 #define	SFBCOPY64SRC(p, v) \
   1044 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
   1045 #define	SFBCOPY64DST(p, v) \
   1046 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
   1047 
   1048 /*
   1049  * Actually write a string to the frame buffer.
   1050  */
   1051 static void
   1052 sfbp_putchar(void *id, int row, int col, u_int uc, long attr)
   1053 {
   1054 	struct rasops_info *ri = id;
   1055 	void *sfb, *p;
   1056 	int scanspan, height, width, align, x, y;
   1057 	u_int32_t lmask, rmask, glyph;
   1058 	u_int8_t *g;
   1059 
   1060 	x = col * ri->ri_font->fontwidth;
   1061 	y = row * ri->ri_font->fontheight;
   1062 	scanspan = ri->ri_stride;
   1063 	height = ri->ri_font->fontheight;
   1064 	uc -= ri->ri_font->firstchar;
   1065 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1066 
   1067 	p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
   1068 	align = (long)p & SFBALIGNMASK;
   1069 	p -= align;
   1070 	align /= SFBPIXELBYTES;
   1071 	width = ri->ri_font->fontwidth + align;
   1072 	lmask = SFBSTIPPLEALL1 << align;
   1073 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1074 	sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
   1075 
   1076 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1077 	SFBPLANEMASK(sfb, ~0);
   1078 	SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
   1079 	SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1080 	SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
   1081 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
   1082 
   1083 	/* XXX 2B stride fonts only XXX */
   1084 	while (height > 0) {
   1085 		glyph = *(u_int16_t *)g;		/* XXX */
   1086 		*(u_int32_t *)p = glyph << align;
   1087 		p += scanspan;
   1088 		g += 2;					/* XXX */
   1089 		height--;
   1090 	}
   1091 	SFBMODE(sfb, MODE_SIMPLE);
   1092 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
   1093 }
   1094 
   1095 #undef	SFBSTIPPLEALL1
   1096 #undef	SFBSTIPPLEBITS
   1097 #undef	SFBSTIPPLEBITMASK
   1098 #define	SFBSTIPPLEALL1		SFBCOPYALL1
   1099 #define	SFBSTIPPLEBITS		SFBCOPYBITS
   1100 #define	SFBSTIPPLEBITMASK	SFBCOPYBITMASK
   1101 
   1102 /*
   1103  * Clear characters in a line.
   1104  */
   1105 static void
   1106 sfbp_erasecols(void *id, int row, int startcol, int ncols, long attr)
   1107 {
   1108 	struct rasops_info *ri = id;
   1109 	void *sfb, *p;
   1110 	int scanspan, startx, height, width, align, w, y;
   1111 	u_int32_t lmask, rmask;
   1112 
   1113 	scanspan = ri->ri_stride;
   1114 	y = row * ri->ri_font->fontheight;
   1115 	startx = startcol * ri->ri_font->fontwidth;
   1116 	height = ri->ri_font->fontheight;
   1117 	w = ri->ri_font->fontwidth * ncols;
   1118 
   1119 	p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
   1120 	align = (long)p & SFBALIGNMASK;
   1121 	align /= SFBPIXELBYTES;
   1122 	p -= align;
   1123 	width = w + align;
   1124 	lmask = SFBSTIPPLEALL1 << align;
   1125 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1126 	sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
   1127 
   1128 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1129 	SFBPLANEMASK(sfb, ~0);
   1130 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
   1131 	if (width <= SFBSTIPPLEBITS) {
   1132 		lmask = lmask & rmask;
   1133 		while (height > 0) {
   1134 			*(u_int32_t *)p = lmask;
   1135 			p += scanspan;
   1136 			height--;
   1137 		}
   1138 	}
   1139 	else {
   1140 		void *q = p;
   1141 		while (height > 0) {
   1142 			*(u_int32_t *)p = lmask;
   1143 			WRITE_MB();
   1144 			width -= 2 * SFBSTIPPLEBITS;
   1145 			while (width > 0) {
   1146 				p += SFBSTIPPLEBYTESDONE;
   1147 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1148 				WRITE_MB();
   1149 				width -= SFBSTIPPLEBITS;
   1150 			}
   1151 			p += SFBSTIPPLEBYTESDONE;
   1152 			*(u_int32_t *)p = rmask;
   1153 			WRITE_MB();
   1154 
   1155 			p = (q += scanspan);
   1156 			width = w + align;
   1157 			height--;
   1158 		}
   1159 	}
   1160 	SFBMODE(sfb, MODE_SIMPLE);
   1161 }
   1162 
   1163 #if 1
   1164 /*
   1165  * Copy lines.
   1166  */
   1167 static void
   1168 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows)
   1169 {
   1170 	struct rasops_info *ri = id;
   1171 	void *sfb, *p;
   1172 	int scanspan, offset, srcy, height, width, align, w;
   1173 	u_int32_t lmask, rmask;
   1174 
   1175 	scanspan = ri->ri_stride;
   1176 	height = ri->ri_font->fontheight * nrows;
   1177 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1178 	srcy = ri->ri_font->fontheight * srcrow;
   1179 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1180 		scanspan = -scanspan;
   1181 		srcy += height;
   1182 	}
   1183 
   1184 	p = ri->ri_bits + srcy * ri->ri_stride;
   1185 	align = (long)p & SFBALIGNMASK;
   1186 	p -= align;
   1187 	align /= SFBPIXELBYTES;
   1188 	w = ri->ri_emuwidth;
   1189 	width = w + align;
   1190 	lmask = SFBCOPYALL1 << align;
   1191 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1192 	sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
   1193 
   1194 	SFBMODE(sfb, MODE_COPY);
   1195 	SFBPLANEMASK(sfb, ~0);
   1196 	SFBPIXELSHIFT(sfb, 0);
   1197 	if (width <= SFBCOPYBITS) {
   1198 		/* never happens */;
   1199 	}
   1200 	else {
   1201 		void *q = p;
   1202 		while (height > 0) {
   1203 			*(u_int32_t *)p = lmask;
   1204 			*(u_int32_t *)(p + offset) = lmask;
   1205 			width -= 2 * SFBCOPYBITS;
   1206 			while (width > 0) {
   1207 				p += SFBCOPYBYTESDONE;
   1208 				*(u_int32_t *)p = SFBCOPYALL1;
   1209 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1210 				width -= SFBCOPYBITS;
   1211 			}
   1212 			p += SFBCOPYBYTESDONE;
   1213 			*(u_int32_t *)p = rmask;
   1214 			*(u_int32_t *)(p + offset) = rmask;
   1215 
   1216 			p = (q += scanspan);
   1217 			width = w + align;
   1218 			height--;
   1219 		}
   1220 	}
   1221 	SFBMODE(sfb, MODE_SIMPLE);
   1222 }
   1223 
   1224 #else
   1225 
   1226 
   1227 static void
   1228 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows)
   1229 {
   1230 	struct rasops_info *ri = id;
   1231 	void *sfb, *p, *q;
   1232 	int scanspan, offset, srcy, height, width, w, align;
   1233 	u_int32_t rmask, lmask;
   1234 
   1235 	scanspan = ri->ri_stride;
   1236 	height = ri->ri_font->fontheight * nrows;
   1237 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1238 	srcy = ri->ri_font->fontheight * srcrow;
   1239 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1240 		scanspan = -scanspan;
   1241 		srcy += height;
   1242 	}
   1243 
   1244 	p = ri->ri_bits + srcy * ri->ri_stride;
   1245 	align = (long)p & SFBALIGNMASK;
   1246 	w = ri->ri_emuwidth;
   1247 	width = w + align;
   1248 	lmask = SFBCOPYALL1 << align;
   1249 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1250 	sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
   1251 	q = p;
   1252 
   1253 	SFBMODE(sfb, MODE_COPY);
   1254 	SFBPLANEMASK(sfb, ~0);
   1255 	SFBPIXELSHIFT(sfb, 0);
   1256 
   1257 	if (width <= SFBCOPYBITS)
   1258 		; /* never happens */
   1259 	else if (width < SFBCOPY64BITS) {
   1260 		; /* unlikely happens */
   1261 
   1262 	}
   1263 	else {
   1264 		while (height > 0) {
   1265 			while (width >= SFBCOPY64BITS) {
   1266 				SFBCOPY64SRC(sfb, *p);
   1267 				SFBCOPY64DST(sfb, *p + offset);
   1268 				p += SFBCOPY64BYTESDONE;
   1269 				width -= SFBCOPY64BITS;
   1270 			}
   1271 			if (width >= SFBCOPYBITS) {
   1272 				*(u_int32_t *)p = SFBCOPYALL1;
   1273 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1274 				p += SFBCOPYBYTESDONE;
   1275 				width -= SFBCOPYBITS;
   1276 			}
   1277 			if (width > 0) {
   1278 				*(u_int32_t *)p = rmask;
   1279 				*(u_int32_t *)(p + offset) = rmask;
   1280 			}
   1281 
   1282 			p = (q += scanspan);
   1283 			width = w;
   1284 			height--;
   1285 		}
   1286 	}
   1287 	SFBMODE(sfb, MODE_SIMPLE);
   1288 }
   1289 #endif
   1290 
   1291 /*
   1292  * Erase lines.
   1293  */
   1294 static void
   1295 sfbp_eraserows(void *id, int startrow, int nrows, long attr)
   1296 {
   1297 	struct rasops_info *ri = id;
   1298 	void *sfb, *p;
   1299 	int scanspan, starty, height, width, align, w;
   1300 	u_int32_t lmask, rmask;
   1301 
   1302 	scanspan = ri->ri_stride;
   1303 	starty = ri->ri_font->fontheight * startrow;
   1304 	height = ri->ri_font->fontheight * nrows;
   1305 
   1306 	p = ri->ri_bits + starty * scanspan;
   1307 	align = (long)p & SFBALIGNMASK;
   1308 	p -= align;
   1309 	align /= SFBPIXELBYTES;
   1310 	w = ri->ri_emuwidth * SFBPIXELBYTES;
   1311 	width = w + align;
   1312 	lmask = SFBSTIPPLEALL1 << align;
   1313 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1314 	sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
   1315 
   1316 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1317 	SFBPLANEMASK(sfb, ~0);
   1318 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1319 	if (width <= SFBSTIPPLEBITS) {
   1320 		/* never happens */;
   1321 	}
   1322 	else {
   1323 		void *q = p;
   1324 		while (height > 0) {
   1325 			*(u_int32_t *)p = lmask;
   1326 			WRITE_MB();
   1327 			width -= 2 * SFBSTIPPLEBITS;
   1328 			while (width > 0) {
   1329 				p += SFBSTIPPLEBYTESDONE;
   1330 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1331 				WRITE_MB();
   1332 				width -= SFBSTIPPLEBITS;
   1333 			}
   1334 			p += SFBSTIPPLEBYTESDONE;
   1335 			*(u_int32_t *)p = rmask;
   1336 			WRITE_MB();
   1337 
   1338 			p = (q += scanspan);
   1339 			width = w + align;
   1340 			height--;
   1341 		}
   1342 	}
   1343 	SFBMODE(sfb, MODE_SIMPLE);
   1344 }
   1345