Home | History | Annotate | Line # | Download | only in tc
sfbplus.c revision 1.12
      1 /* $NetBSD: sfbplus.c,v 1.12 2001/11/13 06:26:10 lukem Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999, 2000, 2001 Tohru Nishimura.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Tohru Nishimura
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.12 2001/11/13 06:26:10 lukem Exp $");
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/kernel.h>
     39 #include <sys/device.h>
     40 #include <sys/malloc.h>
     41 #include <sys/buf.h>
     42 #include <sys/ioctl.h>
     43 
     44 #include <machine/bus.h>
     45 #include <machine/intr.h>
     46 
     47 #include <dev/wscons/wsconsio.h>
     48 #include <dev/wscons/wsdisplayvar.h>
     49 
     50 #include <dev/rasops/rasops.h>
     51 #include <dev/wsfont/wsfont.h>
     52 
     53 #include <dev/tc/tcvar.h>
     54 #include <dev/ic/bt459reg.h>
     55 #include <dev/ic/bt463reg.h>
     56 #include <dev/tc/sfbreg.h>
     57 #include <dev/pci/tgareg.h>
     58 
     59 #include <uvm/uvm_extern.h>
     60 
     61 #if defined(pmax)
     62 #define	machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
     63 #endif
     64 
     65 #if defined(alpha)
     66 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
     67 #endif
     68 
     69 /* Bt459/Bt463 hardware registers */
     70 #define bt_lo	0
     71 #define bt_hi	1
     72 #define bt_reg	2
     73 #define bt_cmap 3
     74 
     75 #define REG(base, index)	*((u_int32_t *)(base) + (index))
     76 #define SELECT(vdac, regno) do {			\
     77 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
     78 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
     79 	tc_wmb();					\
     80    } while (0)
     81 
     82 struct hwcmap256 {
     83 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
     84 	u_int8_t r[CMAP_SIZE];
     85 	u_int8_t g[CMAP_SIZE];
     86 	u_int8_t b[CMAP_SIZE];
     87 };
     88 
     89 struct hwcursor64 {
     90 	struct wsdisplay_curpos cc_pos;
     91 	struct wsdisplay_curpos cc_hot;
     92 	struct wsdisplay_curpos cc_size;
     93 	struct wsdisplay_curpos cc_magic;
     94 #define	CURSOR_MAX_SIZE	64
     95 	u_int8_t cc_color[6];
     96 	u_int64_t cc_image[64 + 64];
     97 };
     98 
     99 struct hwops {
    100 	void (*setlut) __P((caddr_t, struct hwcmap256 *));
    101 	void (*getlut) __P((caddr_t, struct hwcmap256 *));
    102 	void (*visible) __P((caddr_t, int));
    103 	void (*locate) __P((caddr_t, struct hwcursor64 *));
    104 	void (*shape) __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    105 	void (*color) __P((caddr_t, 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 __P((struct device *, struct cfdata *, void *));
    127 static void sfbpattach __P((struct device *, struct device *, void *));
    128 
    129 const struct cfattach sfbp_ca = {
    130 	sizeof(struct sfbp_softc), sfbpmatch, sfbpattach,
    131 };
    132 
    133 static void sfbp_common_init __P((struct rasops_info *));
    134 static struct rasops_info sfbp_console_ri;
    135 static tc_addr_t sfbp_consaddr;
    136 
    137 static struct wsscreen_descr sfbp_stdscreen = {
    138 	"std", 0, 0,
    139 	NULL, /* textops */
    140 	0, 0,
    141 	WSSCREEN_REVERSE
    142 };
    143 
    144 static const struct wsscreen_descr *_sfb_scrlist[] = {
    145 	&sfbp_stdscreen,
    146 };
    147 
    148 static const struct wsscreen_list sfb_screenlist = {
    149 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    150 };
    151 
    152 static int	sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    153 static paddr_t	sfbmmap __P((void *, off_t, int));
    154 
    155 static int	sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    156 				      void **, int *, int *, long *));
    157 static void	sfb_free_screen __P((void *, void *));
    158 static int	sfb_show_screen __P((void *, void *, int,
    159 				     void (*) (void *, int, int), void *));
    160 static void sfbp_putchar __P((void *, int, int, u_int, long));
    161 static void sfbp_erasecols __P((void *, int, int, int, long));
    162 static void sfbp_eraserows __P((void *, int, int, long));
    163 static void sfbp_copyrows __P((void *, int, int, int));
    164 
    165 static const struct wsdisplay_accessops sfb_accessops = {
    166 	sfbioctl,
    167 	sfbmmap,
    168 	sfb_alloc_screen,
    169 	sfb_free_screen,
    170 	sfb_show_screen,
    171 	0 /* load_font */
    172 };
    173 
    174 static void bt459init __P((caddr_t));
    175 static void bt459visible __P((caddr_t, int));
    176 static void bt459locate __P((caddr_t, struct hwcursor64 *));
    177 static void bt459shape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    178 static void bt459color __P((caddr_t, u_int8_t *));
    179 static void bt459setlut __P((caddr_t, struct hwcmap256 *));
    180 
    181 static void sfbpvisible __P((caddr_t, int));
    182 static void sfbplocate __P((caddr_t, struct hwcursor64 *));
    183 static void sfbpshape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    184 static void bt463init __P((caddr_t));
    185 static void bt463color __P((caddr_t, u_int8_t *));
    186 static void noplut __P((caddr_t, struct hwcmap256 *));
    187 
    188 /* EXPORT */ int sfbp_cnattach __P((tc_addr_t));
    189 static int  sfbpintr __P((void *));
    190 
    191 static int  get_cmap __P((struct sfbp_softc *, struct wsdisplay_cmap *));
    192 static int  set_cmap __P((struct sfbp_softc *, struct wsdisplay_cmap *));
    193 static int  set_cursor __P((struct sfbp_softc *, struct wsdisplay_cursor *));
    194 static int  get_cursor __P((struct sfbp_softc *, struct wsdisplay_cursor *));
    195 static void set_curpos __P((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 u_int8_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(parent, match, aux)
    241 	struct device *parent;
    242 	struct cfdata *match;
    243 	void *aux;
    244 {
    245 	struct tc_attach_args *ta = aux;
    246 
    247 	if (strncmp("PMAGD   ", ta->ta_modname, TC_ROM_LLEN) != 0)
    248 		return (0);
    249 
    250 	return (1);
    251 }
    252 
    253 static void
    254 sfbpattach(parent, self, aux)
    255 	struct device *parent, *self;
    256 	void *aux;
    257 {
    258 	struct sfbp_softc *sc = (struct sfbp_softc *)self;
    259 	struct tc_attach_args *ta = aux;
    260 	struct rasops_info *ri;
    261 	struct wsemuldisplaydev_attach_args waa;
    262 	caddr_t asic;
    263 	int console;
    264 
    265 	console = (ta->ta_addr == sfbp_consaddr);
    266 	if (console) {
    267 		sc->sc_ri = ri = &sfbp_console_ri;
    268 		sc->nscreens = 1;
    269 	}
    270 	else {
    271 		MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info),
    272 			M_DEVBUF, M_NOWAIT);
    273 		if (ri == NULL) {
    274 			printf(": can't alloc memory\n");
    275 			return;
    276 		}
    277 		memset(ri, 0, sizeof(struct rasops_info));
    278 
    279 		ri->ri_hw = (void *)ta->ta_addr;
    280 		sfbp_common_init(ri);
    281 		sc->sc_ri = ri;
    282 	}
    283 	printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height,
    284 	    (ri->ri_depth != 32) ? 8 : 24);
    285 
    286 	sc->sc_vaddr = ta->ta_addr;
    287 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    288 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    289 	sc->sc_blanked = sc->sc_curenb = 0;
    290 
    291 	if (ri->ri_depth == 8) {
    292 		struct hwcmap256 *cm;
    293 		const u_int8_t *p;
    294 		int index;
    295 
    296 		sc->sc_hwops.visible = bt459visible;
    297 		sc->sc_hwops.locate = bt459locate;
    298 		sc->sc_hwops.shape = bt459shape;
    299 		sc->sc_hwops.color = bt459color;
    300 		sc->sc_hwops.setlut = bt459setlut;
    301 		sc->sc_hwops.getlut = noplut;
    302 		cm = &sc->sc_cmap;
    303 		p = rasops_cmap;
    304 		for (index = 0; index < CMAP_SIZE; index++, p += 3) {
    305 			cm->r[index] = p[0];
    306 			cm->g[index] = p[1];
    307 			cm->b[index] = p[2];
    308 		}
    309 	}
    310 	else {
    311 		sc->sc_hwops.visible = sfbpvisible;
    312 		sc->sc_hwops.locate = sfbplocate;
    313 		sc->sc_hwops.shape = sfbpshape;
    314 		sc->sc_hwops.color = bt463color;
    315 		sc->sc_hwops.setlut = noplut;
    316 		sc->sc_hwops.getlut = noplut;
    317 	}
    318 
    319         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc);
    320 
    321 	asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
    322 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    323 	*(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1;
    324 
    325 	waa.console = console;
    326 	waa.scrdata = &sfb_screenlist;
    327 	waa.accessops = &sfb_accessops;
    328 	waa.accesscookie = sc;
    329 
    330 	config_found(self, &waa, wsemuldisplaydevprint);
    331 }
    332 
    333 static void
    334 sfbp_common_init(ri)
    335 	struct rasops_info *ri;
    336 {
    337 	caddr_t base, asic;
    338 	int i, depth, hsetup, vsetup, vbase, cookie;
    339 
    340 	base = (caddr_t)ri->ri_hw;
    341 	asic = base + SFB_ASIC_OFFSET;
    342 	hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP);
    343 	vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP);
    344 	i = *(u_int32_t *)(asic + SFB_ASIC_DEEP);
    345 	depth = (i & 01) ? 32 : 8;
    346 
    347 	/*
    348 	 * - neglect 0,1 cases of hsetup register.
    349 	 * - observed 804x600?, 644x480? values.
    350 	 */
    351 
    352 	*(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    353 	vbase *= (i & 0x20) ? 2048 : 4096;	/* VRAM chip size */
    354 	if (i & 1) vbase *= 4;			/* bytes per pixel */
    355 
    356 	*(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0;
    357 	*(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0;
    358 	*(u_int32_t *)(asic + SFB_ASIC_MODE) = 0;	/* MODE_SIMPLE */
    359 	*(u_int32_t *)(asic + SFB_ASIC_ROP) = 3;	/* ROP_COPY */
    360 
    361 	/* initialize colormap and cursor hardware */
    362 	if (depth != 32) {
    363 		*(u_int32_t *)(asic + 0x180000) = 0;	/* Bt459 reset */
    364 		bt459init(base + SFB_RAMDAC_OFFSET);
    365 	}
    366 	else {
    367 		bt463init(base + SFB_RAMDAC_OFFSET);
    368 	}
    369 
    370 	ri->ri_flg = RI_CENTER;
    371 	ri->ri_flg = 0;			/* XXX 32bpp RI_CENTER fails XXX */
    372 	ri->ri_depth = depth;
    373 	ri->ri_width = (hsetup & 0x1ff) << 2;
    374 	ri->ri_height = (vsetup & 0x7ff);
    375 	ri->ri_stride = ri->ri_width * (ri->ri_depth / 8);
    376 	ri->ri_bits = base + 0x800000 + vbase;
    377 
    378 	if (depth == 32) {
    379 		ri->ri_rnum = 8;
    380 		ri->ri_gnum = 8;
    381 		ri->ri_bnum = 8;
    382 		ri->ri_rpos = 16;
    383 		ri->ri_gpos = 8;
    384 		ri->ri_bpos = 0;
    385 	}
    386 
    387 	/* clear the screen */
    388 	memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
    389 
    390 	wsfont_init();
    391 	/* prefer 12 pixel wide font */
    392 	if ((cookie = wsfont_find(NULL, 12, 0, 0)) <= 0)
    393 		cookie = wsfont_find(NULL, 0, 0, 0);
    394 	if (cookie <= 0) {
    395 		printf("sfbp: font table is empty\n");
    396 		return;
    397 	}
    398 
    399 	/* the accelerated sfbp_putchar() needs LSbit left */
    400 	if (wsfont_lock(cookie, &ri->ri_font,
    401 	    WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
    402 		printf("sfb: couldn't lock font\n");
    403 		return;
    404 	}
    405 	ri->ri_wsfcookie = cookie;
    406 
    407 	rasops_init(ri, 34, 80);
    408 
    409 	/* add our accelerated functions */
    410 	ri->ri_ops.putchar = sfbp_putchar;
    411 	ri->ri_ops.erasecols = sfbp_erasecols;
    412 	ri->ri_ops.copyrows = sfbp_copyrows;
    413 	ri->ri_ops.eraserows = sfbp_eraserows;
    414 
    415 	/* XXX shouldn't be global */
    416 	sfbp_stdscreen.nrows = ri->ri_rows;
    417 	sfbp_stdscreen.ncols = ri->ri_cols;
    418 	sfbp_stdscreen.textops = &ri->ri_ops;
    419 	sfbp_stdscreen.capabilities = ri->ri_caps;
    420 	/* our accelerated putchar can't underline */
    421 	sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
    422 }
    423 
    424 static int
    425 sfbioctl(v, cmd, data, flag, p)
    426 	void *v;
    427 	u_long cmd;
    428 	caddr_t data;
    429 	int flag;
    430 	struct proc *p;
    431 {
    432 	struct sfbp_softc *sc = v;
    433 	struct rasops_info *ri = sc->sc_ri;
    434 	int turnoff;
    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 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    477 		sc->sc_changed = WSDISPLAY_CURSOR_DOPOS;
    478 		return (0);
    479 
    480 	case WSDISPLAYIO_GCURMAX:
    481 		((struct wsdisplay_curpos *)data)->x =
    482 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    483 		return (0);
    484 
    485 	case WSDISPLAYIO_GCURSOR:
    486 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    487 
    488 	case WSDISPLAYIO_SCURSOR:
    489 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    490 	}
    491 	return (ENOTTY);
    492 }
    493 
    494 paddr_t
    495 sfbmmap(v, offset, prot)
    496 	void *v;
    497 	off_t offset;
    498 	int prot;
    499 {
    500 	struct sfbp_softc *sc = v;
    501 
    502 	if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */
    503 		return (-1);
    504 	return machine_btop(sc->sc_vaddr + offset);
    505 }
    506 
    507 static int
    508 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    509 	void *v;
    510 	const struct wsscreen_descr *type;
    511 	void **cookiep;
    512 	int *curxp, *curyp;
    513 	long *attrp;
    514 {
    515 	struct sfbp_softc *sc = v;
    516 	struct rasops_info *ri = sc->sc_ri;
    517 	long defattr;
    518 
    519 	if (sc->nscreens > 0)
    520 		return (ENOMEM);
    521 
    522 	*cookiep = ri;		 /* one and only for now */
    523 	*curxp = 0;
    524 	*curyp = 0;
    525 	(*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
    526 	*attrp = defattr;
    527 	sc->nscreens++;
    528 	return (0);
    529 }
    530 
    531 void
    532 sfb_free_screen(v, cookie)
    533 	void *v;
    534 	void *cookie;
    535 {
    536 	struct sfbp_softc *sc = v;
    537 
    538 	if (sc->sc_ri == &sfbp_console_ri)
    539 		panic("sfb_free_screen: console");
    540 
    541 	sc->nscreens--;
    542 }
    543 
    544 static int
    545 sfb_show_screen(v, cookie, waitok, cb, cbarg)
    546 	void *v;
    547 	void *cookie;
    548 	int waitok;
    549 	void (*cb) __P((void *, int, int));
    550 	void *cbarg;
    551 {
    552 
    553 	return (0);
    554 }
    555 
    556 int
    557 sfbp_cnattach(addr)
    558 	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.alloc_attr)(&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(arg)
    574 	void *arg;
    575 {
    576 #define	cc (&sc->sc_cursor)
    577 	struct sfbp_softc *sc = arg;
    578 	caddr_t base, asic;
    579 	u_int32_t sisr;
    580 	int v;
    581 
    582 	base = (caddr_t)sc->sc_ri->ri_hw;
    583 	asic = base + SFB_ASIC_OFFSET;
    584 	sisr = *((u_int32_t *)asic + TGA_REG_SISR);
    585 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    586 
    587 	if (sc->sc_changed == 0)
    588 		goto done;
    589 
    590 	v = sc->sc_changed;
    591 	if (v & WSDISPLAY_CURSOR_DOCUR)
    592 		(*sc->sc_hwops.visible)(base, sc->sc_curenb);
    593 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT))
    594 		(*sc->sc_hwops.locate)(base, cc);
    595 	if (v & WSDISPLAY_CURSOR_DOCMAP)
    596 		(*sc->sc_hwops.color)(base, cc->cc_color);
    597 	if (v & WSDISPLAY_CURSOR_DOSHAPE)
    598 		(*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image);
    599 	if (v & WSDISPLAY_CMAP_DOLUT)
    600 		(*sc->sc_hwops.setlut)(base, &sc->sc_cmap);
    601 	sc->sc_changed = 0;
    602 done:
    603 	*((u_int32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb();
    604 	return (1);
    605 #undef cc
    606 }
    607 
    608 static void
    609 bt459init(vdac)
    610 	caddr_t vdac;
    611 {
    612 	const u_int8_t *p;
    613 	int i;
    614 
    615 	SELECT(vdac, BT459_IREG_COMMAND_0);
    616 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    617 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    618 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    619 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    620 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    621 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    622 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    623 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    624 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    625 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    626 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    627 
    628 	SELECT(vdac, BT459_IREG_CCR);
    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 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    641 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    642 
    643 	/* build sane colormap */
    644 	SELECT(vdac, 0);
    645 	p = rasops_cmap;
    646 	for (i = 0; i < CMAP_SIZE; i++, p += 3) {
    647 		REG(vdac, bt_cmap) = p[0];	tc_wmb();
    648 		REG(vdac, bt_cmap) = p[1];	tc_wmb();
    649 		REG(vdac, bt_cmap) = p[2];	tc_wmb();
    650 	}
    651 
    652 	/* clear out cursor image */
    653 	SELECT(vdac, BT459_IREG_CRAM_BASE);
    654 	for (i = 0; i < 1024; i++)
    655 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    656 
    657 	/*
    658 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    659 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    660 	 * image color.  CCOLOR_1 will be never used.
    661 	 */
    662 	SELECT(vdac, BT459_IREG_CCOLOR_1);
    663 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    664 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    665 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    666 
    667 	REG(vdac, bt_reg) = 0;		tc_wmb();
    668 	REG(vdac, bt_reg) = 0;		tc_wmb();
    669 	REG(vdac, bt_reg) = 0;		tc_wmb();
    670 
    671 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    672 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    673 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    674 }
    675 
    676 static void
    677 bt463init(vdac)
    678 	caddr_t vdac;
    679 {
    680 	int i;
    681 
    682 	SELECT(vdac, BT463_IREG_COMMAND_0);
    683 	REG(vdac, bt_reg) = 0x40;	tc_wmb();	/* CMD 0 */
    684 	REG(vdac, bt_reg) = 0x48;	tc_wmb();	/* CMD 1 */
    685 	REG(vdac, bt_reg) = 0xc0;	tc_wmb();	/* CMD 2 */
    686 	REG(vdac, bt_reg) = 0;		tc_wmb();	/* !? 204 !? */
    687 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  0:7  */
    688 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  8:15 */
    689 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 16:23 */
    690 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 24:27 */
    691 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  0:7  */
    692 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  8:15 */
    693 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 16:23 */
    694 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 24:27 */
    695 	REG(vdac, bt_reg) = 0x00;	tc_wmb();
    696 
    697 	SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
    698 	for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
    699 		REG(vdac, bt_reg) = 0x00;	/*   0:7  */
    700 		REG(vdac, bt_reg) = 0xe1;	/*   8:15 */
    701 		REG(vdac, bt_reg) = 0x81; 	/*  16:23 */
    702 	}
    703 }
    704 
    705 static int
    706 get_cmap(sc, p)
    707 	struct sfbp_softc *sc;
    708 	struct wsdisplay_cmap *p;
    709 {
    710 	u_int index = p->index, count = p->count;
    711 
    712 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    713 		return (EINVAL);
    714 
    715 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    716 	    !uvm_useracc(p->green, count, B_WRITE) ||
    717 	    !uvm_useracc(p->blue, count, B_WRITE))
    718 		return (EFAULT);
    719 
    720 	copyout(&sc->sc_cmap.r[index], p->red, count);
    721 	copyout(&sc->sc_cmap.g[index], p->green, count);
    722 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    723 
    724 	return (0);
    725 }
    726 
    727 static int
    728 set_cmap(sc, p)
    729 	struct sfbp_softc *sc;
    730 	struct wsdisplay_cmap *p;
    731 {
    732 	u_int index = p->index, count = p->count;
    733 
    734 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    735 		return (EINVAL);
    736 
    737 	if (!uvm_useracc(p->red, count, B_READ) ||
    738 	    !uvm_useracc(p->green, count, B_READ) ||
    739 	    !uvm_useracc(p->blue, count, B_READ))
    740 		return (EFAULT);
    741 
    742 	copyin(p->red, &sc->sc_cmap.r[index], count);
    743 	copyin(p->green, &sc->sc_cmap.g[index], count);
    744 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    745 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    746 	return (0);
    747 }
    748 
    749 static int
    750 set_cursor(sc, p)
    751 	struct sfbp_softc *sc;
    752 	struct wsdisplay_cursor *p;
    753 {
    754 #define	cc (&sc->sc_cursor)
    755 	u_int v, index, count, icount;
    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 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    764 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    765 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    766 			return (EFAULT);
    767 	}
    768 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    769 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    770 			return (EINVAL);
    771 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    772 		if (!uvm_useracc(p->image, icount, B_READ) ||
    773 		    !uvm_useracc(p->mask, icount, B_READ))
    774 			return (EFAULT);
    775 	}
    776 
    777 	if (v & WSDISPLAY_CURSOR_DOCUR)
    778 		sc->sc_curenb = p->enable;
    779 	if (v & WSDISPLAY_CURSOR_DOPOS)
    780 		set_curpos(sc, &p->pos);
    781 	if (v & WSDISPLAY_CURSOR_DOHOT)
    782 		cc->cc_hot = p->hot;
    783 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    784 		copyin(p->cmap.red, &cc->cc_color[index], count);
    785 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    786 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    787 	}
    788 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    789 		cc->cc_size = p->size;
    790 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    791 		copyin(p->image, cc->cc_image, icount);
    792 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    793 	}
    794 	sc->sc_changed = v;
    795 
    796 	return (0);
    797 #undef cc
    798 }
    799 
    800 static int
    801 get_cursor(sc, p)
    802 	struct sfbp_softc *sc;
    803 	struct wsdisplay_cursor *p;
    804 {
    805 	return (ENOTTY); /* XXX */
    806 }
    807 
    808 static void
    809 set_curpos(sc, curpos)
    810 	struct sfbp_softc *sc;
    811 	struct wsdisplay_curpos *curpos;
    812 {
    813 	struct rasops_info *ri = sc->sc_ri;
    814 	int x = curpos->x, y = curpos->y;
    815 
    816 	if (y < 0)
    817 		y = 0;
    818 	else if (y > ri->ri_height)
    819 		y = ri->ri_height;
    820 	if (x < 0)
    821 		x = 0;
    822 	else if (x > ri->ri_width)
    823 		x = ri->ri_width;
    824 	sc->sc_cursor.cc_pos.x = x;
    825 	sc->sc_cursor.cc_pos.y = y;
    826 }
    827 
    828 static void
    829 bt459visible(hw, on)
    830 	caddr_t hw;
    831 	int on;
    832 {
    833 	hw += SFB_RAMDAC_OFFSET;
    834 	SELECT(hw, BT459_IREG_CCR);
    835 	REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
    836 	tc_wmb();
    837 }
    838 
    839 static void
    840 sfbpvisible(hw, on)
    841 	caddr_t hw;
    842 	int on;
    843 {
    844 	/* XXX use SFBplus ASIC XX */
    845 }
    846 
    847 static void
    848 bt459locate(hw, cc)
    849 	caddr_t hw;
    850 	struct hwcursor64 *cc;
    851 {
    852 	int x, y, s;
    853 
    854 	x = cc->cc_pos.x - cc->cc_hot.x;
    855 	y = cc->cc_pos.y - cc->cc_hot.y;
    856 	x += cc->cc_magic.x;
    857 	y += cc->cc_magic.y;
    858 
    859 	hw += SFB_RAMDAC_OFFSET;
    860 
    861 	s = spltty();
    862 	SELECT(hw, BT459_IREG_CURSOR_X_LOW);
    863 	REG(hw, bt_reg) = x;		tc_wmb();
    864 	REG(hw, bt_reg) = x >> 8;	tc_wmb();
    865 	REG(hw, bt_reg) = y;		tc_wmb();
    866 	REG(hw, bt_reg) = y >> 8;	tc_wmb();
    867 	splx(s);
    868 }
    869 
    870 static void
    871 sfbplocate(hw, cc)
    872 	caddr_t hw;
    873 	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(hw, cp)
    887 	caddr_t hw;
    888 	u_int8_t *cp;
    889 {
    890 
    891 	hw += SFB_RAMDAC_OFFSET;
    892 
    893 	SELECT(hw, BT459_IREG_CCOLOR_2);
    894 	REG(hw, bt_reg) = cp[1]; tc_wmb();
    895 	REG(hw, bt_reg) = cp[3]; tc_wmb();
    896 	REG(hw, bt_reg) = cp[5]; tc_wmb();
    897 
    898 	REG(hw, bt_reg) = cp[0]; tc_wmb();
    899 	REG(hw, bt_reg) = cp[2]; tc_wmb();
    900 	REG(hw, bt_reg) = cp[4]; tc_wmb();
    901 }
    902 
    903 static void
    904 bt463color(hw, cp)
    905 	caddr_t hw;
    906 	u_int8_t *cp;
    907 {
    908 }
    909 
    910 static void
    911 bt459shape(hw, size, image)
    912 	caddr_t hw;
    913 	struct wsdisplay_curpos *size;
    914 	u_int64_t *image;
    915 {
    916 	u_int8_t *ip, *mp, img, msk;
    917 	u_int8_t u;
    918 	int bcnt;
    919 
    920 	hw += SFB_RAMDAC_OFFSET;
    921 	ip = (u_int8_t *)image;
    922 	mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
    923 
    924 	bcnt = 0;
    925 	SELECT(hw, BT459_IREG_CRAM_BASE+0);
    926 	/* 64 pixel scan line is consisted with 16 byte cursor ram */
    927 	while (bcnt < size->y * 16) {
    928 		/* pad right half 32 pixel when smaller than 33 */
    929 		if ((bcnt & 0x8) && size->x < 33) {
    930 			REG(hw, bt_reg) = 0; tc_wmb();
    931 			REG(hw, bt_reg) = 0; tc_wmb();
    932 		}
    933 		else {
    934 			img = *ip++;
    935 			msk = *mp++;
    936 			img &= msk;	/* cookie off image */
    937 			u = (msk & 0x0f) << 4 | (img & 0x0f);
    938 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    939 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
    940 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    941 		}
    942 		bcnt += 2;
    943 	}
    944 	/* pad unoccupied scan lines */
    945 	while (bcnt < CURSOR_MAX_SIZE * 16) {
    946 		REG(hw, bt_reg) = 0; tc_wmb();
    947 		REG(hw, bt_reg) = 0; tc_wmb();
    948 		bcnt += 2;
    949 	}
    950 }
    951 
    952 static void
    953 sfbpshape(hw, size, image)
    954 	caddr_t hw;
    955 	struct wsdisplay_curpos *size;
    956 	u_int64_t *image;
    957 {
    958 	/* XXX use SFBplus ASIC XXX */
    959 }
    960 
    961 static void
    962 bt459setlut(hw, cm)
    963 	caddr_t hw;
    964 	struct hwcmap256 *cm;
    965 {
    966 	int index;
    967 
    968 	hw += SFB_RAMDAC_OFFSET;
    969 	SELECT(hw, 0);
    970 	for (index = 0; index < CMAP_SIZE; index++) {
    971 		REG(hw, bt_cmap) = cm->r[index];	tc_wmb();
    972 		REG(hw, bt_cmap) = cm->g[index];	tc_wmb();
    973 		REG(hw, bt_cmap) = cm->b[index];	tc_wmb();
    974 	}
    975 }
    976 
    977 static void
    978 noplut(hw, cm)
    979 	caddr_t hw;
    980 	struct hwcmap256 *cm;
    981 {
    982 }
    983 
    984 #define SFBBPP 32
    985 
    986 #define	MODE_SIMPLE		0
    987 #define	MODE_OPAQUESTIPPLE	1
    988 #define	MODE_OPAQUELINE		2
    989 #define	MODE_TRANSPARENTSTIPPLE	5
    990 #define	MODE_TRANSPARENTLINE	6
    991 #define	MODE_COPY		7
    992 
    993 #if SFBBPP == 8
    994 /* parameters for 8bpp configuration */
    995 #define	SFBALIGNMASK		0x7
    996 #define	SFBPIXELBYTES		1
    997 #define	SFBSTIPPLEALL1		0xffffffff
    998 #define	SFBSTIPPLEBITS		32
    999 #define	SFBSTIPPLEBITMASK	0x1f
   1000 #define	SFBSTIPPLEBYTESDONE	32
   1001 #define	SFBCOPYALL1		0xffffffff
   1002 #define	SFBCOPYBITS		32
   1003 #define	SFBCOPYBITMASK		0x1f
   1004 #define	SFBCOPYBYTESDONE	32
   1005 
   1006 #elif SFBBPP == 32
   1007 /* parameters for 32bpp configuration */
   1008 #define	SFBALIGNMASK		0x7
   1009 #define	SFBPIXELBYTES		4
   1010 #define	SFBSTIPPLEALL1		0x0000ffff
   1011 #define	SFBSTIPPLEBITS		16
   1012 #define	SFBSTIPPLEBITMASK	0xf
   1013 #define	SFBSTIPPLEBYTESDONE	32
   1014 #define	SFBCOPYALL1		0x000000ff
   1015 #define	SFBCOPYBITS		8
   1016 #define	SFBCOPYBITMASK		0x3
   1017 #define	SFBCOPYBYTESDONE	32
   1018 #endif
   1019 
   1020 #ifdef pmax
   1021 #define	WRITE_MB()
   1022 #define	BUMP(p) (p)
   1023 #endif
   1024 
   1025 #ifdef alpha
   1026 #define	WRITE_MB() tc_wmb()
   1027 /* registers is replicated in 1KB stride; rap round 4th iteration */
   1028 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
   1029 #endif
   1030 
   1031 #define	SFBMODE(p, v) \
   1032 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
   1033 #define	SFBROP(p, v) \
   1034 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
   1035 #define	SFBPLANEMASK(p, v) \
   1036 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
   1037 #define	SFBPIXELMASK(p, v) \
   1038 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
   1039 #define	SFBADDRESS(p, v) \
   1040 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
   1041 #define	SFBSTART(p, v) \
   1042 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
   1043 #define	SFBPIXELSHIFT(p, v) \
   1044 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
   1045 #define	SFBFG(p, v) \
   1046 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
   1047 #define	SFBBG(p, v) \
   1048 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
   1049 #define	SFBBCONT(p, v) \
   1050 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
   1051 
   1052 #define	SFBDATA(p, v) \
   1053 		(*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
   1054 
   1055 #define	SFBCOPY64BYTESDONE	8
   1056 #define	SFBCOPY64BITS		64
   1057 #define	SFBCOPY64SRC(p, v) \
   1058 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
   1059 #define	SFBCOPY64DST(p, v) \
   1060 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
   1061 
   1062 /*
   1063  * Actually write a string to the frame buffer.
   1064  */
   1065 static void
   1066 sfbp_putchar(id, row, col, uc, attr)
   1067 	void *id;
   1068 	int row, col;
   1069 	u_int uc;
   1070 	long attr;
   1071 {
   1072 	struct rasops_info *ri = id;
   1073 	caddr_t sfb, p;
   1074 	int scanspan, height, width, align, x, y;
   1075 	u_int32_t lmask, rmask, glyph;
   1076 	u_int8_t *g;
   1077 
   1078 	x = col * ri->ri_font->fontwidth;
   1079 	y = row * ri->ri_font->fontheight;
   1080 	scanspan = ri->ri_stride;
   1081 	height = ri->ri_font->fontheight;
   1082 	uc -= ri->ri_font->firstchar;
   1083 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1084 
   1085 	p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
   1086 	align = (long)p & SFBALIGNMASK;
   1087 	p -= align;
   1088 	align /= SFBPIXELBYTES;
   1089 	width = ri->ri_font->fontwidth + align;
   1090 	lmask = SFBSTIPPLEALL1 << align;
   1091 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1092 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1093 
   1094 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1095 	SFBPLANEMASK(sfb, ~0);
   1096 	SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
   1097 	SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1098 	SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
   1099 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
   1100 
   1101 	/* XXX 2B stride fonts only XXX */
   1102 	while (height > 0) {
   1103 		glyph = *(u_int16_t *)g;		/* XXX */
   1104 		*(u_int32_t *)p = glyph << align;
   1105 		p += scanspan;
   1106 		g += 2;					/* XXX */
   1107 		height--;
   1108 	}
   1109 	SFBMODE(sfb, MODE_SIMPLE);
   1110 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
   1111 }
   1112 
   1113 #undef	SFBSTIPPLEALL1
   1114 #undef	SFBSTIPPLEBITS
   1115 #undef	SFBSTIPPLEBITMASK
   1116 #define	SFBSTIPPLEALL1		SFBCOPYALL1
   1117 #define	SFBSTIPPLEBITS		SFBCOPYBITS
   1118 #define	SFBSTIPPLEBITMASK	SFBCOPYBITMASK
   1119 
   1120 /*
   1121  * Clear characters in a line.
   1122  */
   1123 static void
   1124 sfbp_erasecols(id, row, startcol, ncols, attr)
   1125 	void *id;
   1126 	int row, startcol, ncols;
   1127 	long attr;
   1128 {
   1129 	struct rasops_info *ri = id;
   1130 	caddr_t sfb, p;
   1131 	int scanspan, startx, height, width, align, w, y;
   1132 	u_int32_t lmask, rmask;
   1133 
   1134 	scanspan = ri->ri_stride;
   1135 	y = row * ri->ri_font->fontheight;
   1136 	startx = startcol * ri->ri_font->fontwidth;
   1137 	height = ri->ri_font->fontheight;
   1138 	w = ri->ri_font->fontwidth * ncols;
   1139 
   1140 	p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
   1141 	align = (long)p & SFBALIGNMASK;
   1142 	align /= SFBPIXELBYTES;
   1143 	p -= align;
   1144 	width = w + align;
   1145 	lmask = SFBSTIPPLEALL1 << align;
   1146 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1147 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1148 
   1149 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1150 	SFBPLANEMASK(sfb, ~0);
   1151 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
   1152 	if (width <= SFBSTIPPLEBITS) {
   1153 		lmask = lmask & rmask;
   1154 		while (height > 0) {
   1155 			*(u_int32_t *)p = lmask;
   1156 			p += scanspan;
   1157 			height--;
   1158 		}
   1159 	}
   1160 	else {
   1161 		caddr_t q = p;
   1162 		while (height > 0) {
   1163 			*(u_int32_t *)p = lmask;
   1164 			WRITE_MB();
   1165 			width -= 2 * SFBSTIPPLEBITS;
   1166 			while (width > 0) {
   1167 				p += SFBSTIPPLEBYTESDONE;
   1168 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1169 				WRITE_MB();
   1170 				width -= SFBSTIPPLEBITS;
   1171 			}
   1172 			p += SFBSTIPPLEBYTESDONE;
   1173 			*(u_int32_t *)p = rmask;
   1174 			WRITE_MB();
   1175 
   1176 			p = (q += scanspan);
   1177 			width = w + align;
   1178 			height--;
   1179 		}
   1180 	}
   1181 	SFBMODE(sfb, MODE_SIMPLE);
   1182 }
   1183 
   1184 #if 1
   1185 /*
   1186  * Copy lines.
   1187  */
   1188 static void
   1189 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1190 	void *id;
   1191 	int srcrow, dstrow, nrows;
   1192 {
   1193 	struct rasops_info *ri = id;
   1194 	caddr_t sfb, p;
   1195 	int scanspan, offset, srcy, height, width, align, w;
   1196 	u_int32_t lmask, rmask;
   1197 
   1198 	scanspan = ri->ri_stride;
   1199 	height = ri->ri_font->fontheight * nrows;
   1200 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1201 	srcy = ri->ri_font->fontheight * srcrow;
   1202 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1203 		scanspan = -scanspan;
   1204 		srcy += height;
   1205 	}
   1206 
   1207 	p = ri->ri_bits + srcy * ri->ri_stride;
   1208 	align = (long)p & SFBALIGNMASK;
   1209 	p -= align;
   1210 	align /= SFBPIXELBYTES;
   1211 	w = ri->ri_emuwidth;
   1212 	width = w + align;
   1213 	lmask = SFBCOPYALL1 << align;
   1214 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1215 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1216 
   1217 	SFBMODE(sfb, MODE_COPY);
   1218 	SFBPLANEMASK(sfb, ~0);
   1219 	SFBPIXELSHIFT(sfb, 0);
   1220 	if (width <= SFBCOPYBITS) {
   1221 		/* never happens */;
   1222 	}
   1223 	else {
   1224 		caddr_t q = p;
   1225 		while (height > 0) {
   1226 			*(u_int32_t *)p = lmask;
   1227 			*(u_int32_t *)(p + offset) = lmask;
   1228 			width -= 2 * SFBCOPYBITS;
   1229 			while (width > 0) {
   1230 				p += SFBCOPYBYTESDONE;
   1231 				*(u_int32_t *)p = SFBCOPYALL1;
   1232 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1233 				width -= SFBCOPYBITS;
   1234 			}
   1235 			p += SFBCOPYBYTESDONE;
   1236 			*(u_int32_t *)p = rmask;
   1237 			*(u_int32_t *)(p + offset) = rmask;
   1238 
   1239 			p = (q += scanspan);
   1240 			width = w + align;
   1241 			height--;
   1242 		}
   1243 	}
   1244 	SFBMODE(sfb, MODE_SIMPLE);
   1245 }
   1246 
   1247 #else
   1248 
   1249 
   1250 static void
   1251 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1252 	void *id;
   1253 	int srcrow, dstrow, nrows;
   1254 {
   1255 	struct rasops_info *ri = id;
   1256 	caddr_t sfb, p, q;
   1257 	int scanspan, offset, srcy, height, width, w, align;
   1258 	u_int32_t rmask, lmask;
   1259 
   1260 	scanspan = ri->ri_stride;
   1261 	height = ri->ri_font->fontheight * nrows;
   1262 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1263 	srcy = ri->ri_font->fontheight * srcrow;
   1264 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1265 		scanspan = -scanspan;
   1266 		srcy += height;
   1267 	}
   1268 
   1269 	p = ri->ri_bits + srcy * ri->ri_stride;
   1270 	align = (long)p & SFBALIGNMASK;
   1271 	w = ri->ri_emuwidth;
   1272 	width = w + align;
   1273 	lmask = SFBCOPYALL1 << align;
   1274 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1275 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1276 	q = p;
   1277 
   1278 	SFBMODE(sfb, MODE_COPY);
   1279 	SFBPLANEMASK(sfb, ~0);
   1280 	SFBPIXELSHIFT(sfb, 0);
   1281 
   1282 	if (width <= SFBCOPYBITS)
   1283 		; /* never happens */
   1284 	else if (width < SFBCOPY64BITS) {
   1285 		; /* unlikely happens */
   1286 
   1287 	}
   1288 	else {
   1289 		while (height > 0) {
   1290 			while (width >= SFBCOPY64BITS) {
   1291 				SFBCOPY64SRC(sfb, p);
   1292 				SFBCOPY64DST(sfb, p + offset);
   1293 				p += SFBCOPY64BYTESDONE;
   1294 				width -= SFBCOPY64BITS;
   1295 			}
   1296 			if (width >= SFBCOPYBITS) {
   1297 				*(u_int32_t *)p = SFBCOPYALL1;
   1298 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1299 				p += SFBCOPYBYTESDONE;
   1300 				width -= SFBCOPYBITS;
   1301 			}
   1302 			if (width > 0) {
   1303 				*(u_int32_t *)p = rmask;
   1304 				*(u_int32_t *)(p + offset) = rmask;
   1305 			}
   1306 
   1307 			p = (q += scanspan);
   1308 			width = w;
   1309 			height--;
   1310 		}
   1311 	}
   1312 	SFBMODE(sfb, MODE_SIMPLE);
   1313 }
   1314 #endif
   1315 
   1316 /*
   1317  * Erase lines.
   1318  */
   1319 static void
   1320 sfbp_eraserows(id, startrow, nrows, attr)
   1321 	void *id;
   1322 	int startrow, nrows;
   1323 	long attr;
   1324 {
   1325 	struct rasops_info *ri = id;
   1326 	caddr_t sfb, p;
   1327 	int scanspan, starty, height, width, align, w;
   1328 	u_int32_t lmask, rmask;
   1329 
   1330 	scanspan = ri->ri_stride;
   1331 	starty = ri->ri_font->fontheight * startrow;
   1332 	height = ri->ri_font->fontheight * nrows;
   1333 
   1334 	p = ri->ri_bits + starty * scanspan;
   1335 	align = (long)p & SFBALIGNMASK;
   1336 	p -= align;
   1337 	align /= SFBPIXELBYTES;
   1338 	w = ri->ri_emuwidth * SFBPIXELBYTES;
   1339 	width = w + align;
   1340 	lmask = SFBSTIPPLEALL1 << align;
   1341 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1342 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1343 
   1344 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1345 	SFBPLANEMASK(sfb, ~0);
   1346 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1347 	if (width <= SFBSTIPPLEBITS) {
   1348 		/* never happens */;
   1349 	}
   1350 	else {
   1351 		caddr_t q = p;
   1352 		while (height > 0) {
   1353 			*(u_int32_t *)p = lmask;
   1354 			WRITE_MB();
   1355 			width -= 2 * SFBSTIPPLEBITS;
   1356 			while (width > 0) {
   1357 				p += SFBSTIPPLEBYTESDONE;
   1358 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1359 				WRITE_MB();
   1360 				width -= SFBSTIPPLEBITS;
   1361 			}
   1362 			p += SFBSTIPPLEBYTESDONE;
   1363 			*(u_int32_t *)p = rmask;
   1364 			WRITE_MB();
   1365 
   1366 			p = (q += scanspan);
   1367 			width = w + align;
   1368 			height--;
   1369 		}
   1370 	}
   1371 	SFBMODE(sfb, MODE_SIMPLE);
   1372 }
   1373