Home | History | Annotate | Line # | Download | only in tc
sfbplus.c revision 1.13
      1 /* $NetBSD: sfbplus.c,v 1.13 2002/03/13 15:05:17 ad Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999, 2000, 2001 Tohru Nishimura.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Tohru Nishimura
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.13 2002/03/13 15:05:17 ad Exp $");
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/kernel.h>
     39 #include <sys/device.h>
     40 #include <sys/malloc.h>
     41 #include <sys/buf.h>
     42 #include <sys/ioctl.h>
     43 
     44 #include <machine/bus.h>
     45 #include <machine/intr.h>
     46 
     47 #include <dev/wscons/wsconsio.h>
     48 #include <dev/wscons/wsdisplayvar.h>
     49 
     50 #include <dev/rasops/rasops.h>
     51 #include <dev/wsfont/wsfont.h>
     52 
     53 #include <dev/tc/tcvar.h>
     54 #include <dev/ic/bt459reg.h>
     55 #include <dev/ic/bt463reg.h>
     56 #include <dev/tc/sfbreg.h>
     57 #include <dev/pci/tgareg.h>
     58 
     59 #include <uvm/uvm_extern.h>
     60 
     61 #if defined(pmax)
     62 #define	machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
     63 #endif
     64 
     65 #if defined(alpha)
     66 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
     67 #endif
     68 
     69 /* Bt459/Bt463 hardware registers */
     70 #define bt_lo	0
     71 #define bt_hi	1
     72 #define bt_reg	2
     73 #define bt_cmap 3
     74 
     75 #define REG(base, index)	*((u_int32_t *)(base) + (index))
     76 #define SELECT(vdac, regno) do {			\
     77 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
     78 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
     79 	tc_wmb();					\
     80    } while (0)
     81 
     82 struct hwcmap256 {
     83 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
     84 	u_int8_t r[CMAP_SIZE];
     85 	u_int8_t g[CMAP_SIZE];
     86 	u_int8_t b[CMAP_SIZE];
     87 };
     88 
     89 struct hwcursor64 {
     90 	struct wsdisplay_curpos cc_pos;
     91 	struct wsdisplay_curpos cc_hot;
     92 	struct wsdisplay_curpos cc_size;
     93 	struct wsdisplay_curpos cc_magic;
     94 #define	CURSOR_MAX_SIZE	64
     95 	u_int8_t cc_color[6];
     96 	u_int64_t cc_image[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 	cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
    393 	    WSDISPLAY_FONTORDER_L2R);
    394 	if (cookie <= 0)
    395 		cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
    396 		    WSDISPLAY_FONTORDER_L2R);
    397 	if (cookie <= 0) {
    398 		printf("sfbp: font table is empty\n");
    399 		return;
    400 	}
    401 
    402 	/* the accelerated sfbp_putchar() needs LSbit left */
    403 	if (wsfont_lock(cookie, &ri->ri_font)) {
    404 		printf("sfb: couldn't lock font\n");
    405 		return;
    406 	}
    407 	ri->ri_wsfcookie = cookie;
    408 
    409 	rasops_init(ri, 34, 80);
    410 
    411 	/* add our accelerated functions */
    412 	ri->ri_ops.putchar = sfbp_putchar;
    413 	ri->ri_ops.erasecols = sfbp_erasecols;
    414 	ri->ri_ops.copyrows = sfbp_copyrows;
    415 	ri->ri_ops.eraserows = sfbp_eraserows;
    416 
    417 	/* XXX shouldn't be global */
    418 	sfbp_stdscreen.nrows = ri->ri_rows;
    419 	sfbp_stdscreen.ncols = ri->ri_cols;
    420 	sfbp_stdscreen.textops = &ri->ri_ops;
    421 	sfbp_stdscreen.capabilities = ri->ri_caps;
    422 	/* our accelerated putchar can't underline */
    423 	sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
    424 }
    425 
    426 static int
    427 sfbioctl(v, cmd, data, flag, p)
    428 	void *v;
    429 	u_long cmd;
    430 	caddr_t data;
    431 	int flag;
    432 	struct proc *p;
    433 {
    434 	struct sfbp_softc *sc = v;
    435 	struct rasops_info *ri = sc->sc_ri;
    436 	int turnoff;
    437 
    438 	switch (cmd) {
    439 	case WSDISPLAYIO_GTYPE:
    440 		*(u_int *)data = WSDISPLAY_TYPE_SFBP;
    441 		return (0);
    442 
    443 	case WSDISPLAYIO_GINFO:
    444 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    445 		wsd_fbip->height = ri->ri_height;
    446 		wsd_fbip->width = ri->ri_width;
    447 		wsd_fbip->depth = ri->ri_depth;
    448 		wsd_fbip->cmsize = CMAP_SIZE;	/* XXX */
    449 #undef fbt
    450 		return (0);
    451 
    452 	case WSDISPLAYIO_GETCMAP:
    453 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    454 
    455 	case WSDISPLAYIO_PUTCMAP:
    456 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    457 
    458 	case WSDISPLAYIO_SVIDEO:
    459 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    460 		if ((sc->sc_blanked == 0) ^ turnoff) {
    461 			sc->sc_blanked = turnoff;
    462 #if 0 /* XXX later XXX */
    463 	Low order 3bit control visibilities of screen and builtin cursor.
    464 #endif	/* XXX XXX XXX */
    465 		}
    466 		return (0);
    467 
    468 	case WSDISPLAYIO_GVIDEO:
    469 		*(u_int *)data = sc->sc_blanked ?
    470 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    471 		return (0);
    472 
    473 	case WSDISPLAYIO_GCURPOS:
    474 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    475 		return (0);
    476 
    477 	case WSDISPLAYIO_SCURPOS:
    478 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    479 		sc->sc_changed = WSDISPLAY_CURSOR_DOPOS;
    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 	return (ENOTTY);
    494 }
    495 
    496 paddr_t
    497 sfbmmap(v, offset, prot)
    498 	void *v;
    499 	off_t offset;
    500 	int prot;
    501 {
    502 	struct sfbp_softc *sc = v;
    503 
    504 	if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */
    505 		return (-1);
    506 	return machine_btop(sc->sc_vaddr + offset);
    507 }
    508 
    509 static int
    510 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    511 	void *v;
    512 	const struct wsscreen_descr *type;
    513 	void **cookiep;
    514 	int *curxp, *curyp;
    515 	long *attrp;
    516 {
    517 	struct sfbp_softc *sc = v;
    518 	struct rasops_info *ri = sc->sc_ri;
    519 	long defattr;
    520 
    521 	if (sc->nscreens > 0)
    522 		return (ENOMEM);
    523 
    524 	*cookiep = ri;		 /* one and only for now */
    525 	*curxp = 0;
    526 	*curyp = 0;
    527 	(*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
    528 	*attrp = defattr;
    529 	sc->nscreens++;
    530 	return (0);
    531 }
    532 
    533 void
    534 sfb_free_screen(v, cookie)
    535 	void *v;
    536 	void *cookie;
    537 {
    538 	struct sfbp_softc *sc = v;
    539 
    540 	if (sc->sc_ri == &sfbp_console_ri)
    541 		panic("sfb_free_screen: console");
    542 
    543 	sc->nscreens--;
    544 }
    545 
    546 static int
    547 sfb_show_screen(v, cookie, waitok, cb, cbarg)
    548 	void *v;
    549 	void *cookie;
    550 	int waitok;
    551 	void (*cb) __P((void *, int, int));
    552 	void *cbarg;
    553 {
    554 
    555 	return (0);
    556 }
    557 
    558 int
    559 sfbp_cnattach(addr)
    560 	tc_addr_t addr;
    561 {
    562 	struct rasops_info *ri;
    563 	long defattr;
    564 
    565 	ri = &sfbp_console_ri;
    566 	ri->ri_hw = (void *)addr;
    567 	sfbp_common_init(ri);
    568 	(*ri->ri_ops.alloc_attr)(&ri, 0, 0, 0, &defattr);
    569 	wsdisplay_cnattach(&sfbp_stdscreen, ri, 0, 0, defattr);
    570 	sfbp_consaddr = addr;
    571 	return (0);
    572 }
    573 
    574 static int
    575 sfbpintr(arg)
    576 	void *arg;
    577 {
    578 #define	cc (&sc->sc_cursor)
    579 	struct sfbp_softc *sc = arg;
    580 	caddr_t base, asic;
    581 	u_int32_t sisr;
    582 	int v;
    583 
    584 	base = (caddr_t)sc->sc_ri->ri_hw;
    585 	asic = base + SFB_ASIC_OFFSET;
    586 	sisr = *((u_int32_t *)asic + TGA_REG_SISR);
    587 	*(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
    588 
    589 	if (sc->sc_changed == 0)
    590 		goto done;
    591 
    592 	v = sc->sc_changed;
    593 	if (v & WSDISPLAY_CURSOR_DOCUR)
    594 		(*sc->sc_hwops.visible)(base, sc->sc_curenb);
    595 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT))
    596 		(*sc->sc_hwops.locate)(base, cc);
    597 	if (v & WSDISPLAY_CURSOR_DOCMAP)
    598 		(*sc->sc_hwops.color)(base, cc->cc_color);
    599 	if (v & WSDISPLAY_CURSOR_DOSHAPE)
    600 		(*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image);
    601 	if (v & WSDISPLAY_CMAP_DOLUT)
    602 		(*sc->sc_hwops.setlut)(base, &sc->sc_cmap);
    603 	sc->sc_changed = 0;
    604 done:
    605 	*((u_int32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb();
    606 	return (1);
    607 #undef cc
    608 }
    609 
    610 static void
    611 bt459init(vdac)
    612 	caddr_t vdac;
    613 {
    614 	const u_int8_t *p;
    615 	int i;
    616 
    617 	SELECT(vdac, BT459_IREG_COMMAND_0);
    618 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    619 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    620 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    621 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    622 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    623 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    624 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    625 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    626 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    627 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    628 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    629 
    630 	SELECT(vdac, BT459_IREG_CCR);
    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 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    643 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    644 
    645 	/* build sane colormap */
    646 	SELECT(vdac, 0);
    647 	p = rasops_cmap;
    648 	for (i = 0; i < CMAP_SIZE; i++, p += 3) {
    649 		REG(vdac, bt_cmap) = p[0];	tc_wmb();
    650 		REG(vdac, bt_cmap) = p[1];	tc_wmb();
    651 		REG(vdac, bt_cmap) = p[2];	tc_wmb();
    652 	}
    653 
    654 	/* clear out cursor image */
    655 	SELECT(vdac, BT459_IREG_CRAM_BASE);
    656 	for (i = 0; i < 1024; i++)
    657 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    658 
    659 	/*
    660 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    661 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    662 	 * image color.  CCOLOR_1 will be never used.
    663 	 */
    664 	SELECT(vdac, BT459_IREG_CCOLOR_1);
    665 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    666 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    667 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    668 
    669 	REG(vdac, bt_reg) = 0;		tc_wmb();
    670 	REG(vdac, bt_reg) = 0;		tc_wmb();
    671 	REG(vdac, bt_reg) = 0;		tc_wmb();
    672 
    673 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    674 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    675 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    676 }
    677 
    678 static void
    679 bt463init(vdac)
    680 	caddr_t vdac;
    681 {
    682 	int i;
    683 
    684 	SELECT(vdac, BT463_IREG_COMMAND_0);
    685 	REG(vdac, bt_reg) = 0x40;	tc_wmb();	/* CMD 0 */
    686 	REG(vdac, bt_reg) = 0x48;	tc_wmb();	/* CMD 1 */
    687 	REG(vdac, bt_reg) = 0xc0;	tc_wmb();	/* CMD 2 */
    688 	REG(vdac, bt_reg) = 0;		tc_wmb();	/* !? 204 !? */
    689 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  0:7  */
    690 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane  8:15 */
    691 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 16:23 */
    692 	REG(vdac, bt_reg) = 0xff;	tc_wmb();	/* plane 24:27 */
    693 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  0:7  */
    694 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink  8:15 */
    695 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 16:23 */
    696 	REG(vdac, bt_reg) = 0x00;	tc_wmb();	/* blink 24:27 */
    697 	REG(vdac, bt_reg) = 0x00;	tc_wmb();
    698 
    699 	SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
    700 	for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
    701 		REG(vdac, bt_reg) = 0x00;	/*   0:7  */
    702 		REG(vdac, bt_reg) = 0xe1;	/*   8:15 */
    703 		REG(vdac, bt_reg) = 0x81; 	/*  16:23 */
    704 	}
    705 }
    706 
    707 static int
    708 get_cmap(sc, p)
    709 	struct sfbp_softc *sc;
    710 	struct wsdisplay_cmap *p;
    711 {
    712 	u_int index = p->index, count = p->count;
    713 
    714 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    715 		return (EINVAL);
    716 
    717 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    718 	    !uvm_useracc(p->green, count, B_WRITE) ||
    719 	    !uvm_useracc(p->blue, count, B_WRITE))
    720 		return (EFAULT);
    721 
    722 	copyout(&sc->sc_cmap.r[index], p->red, count);
    723 	copyout(&sc->sc_cmap.g[index], p->green, count);
    724 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    725 
    726 	return (0);
    727 }
    728 
    729 static int
    730 set_cmap(sc, p)
    731 	struct sfbp_softc *sc;
    732 	struct wsdisplay_cmap *p;
    733 {
    734 	u_int index = p->index, count = p->count;
    735 
    736 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    737 		return (EINVAL);
    738 
    739 	if (!uvm_useracc(p->red, count, B_READ) ||
    740 	    !uvm_useracc(p->green, count, B_READ) ||
    741 	    !uvm_useracc(p->blue, count, B_READ))
    742 		return (EFAULT);
    743 
    744 	copyin(p->red, &sc->sc_cmap.r[index], count);
    745 	copyin(p->green, &sc->sc_cmap.g[index], count);
    746 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    747 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    748 	return (0);
    749 }
    750 
    751 static int
    752 set_cursor(sc, p)
    753 	struct sfbp_softc *sc;
    754 	struct wsdisplay_cursor *p;
    755 {
    756 #define	cc (&sc->sc_cursor)
    757 	u_int v, index, count, icount;
    758 
    759 	v = p->which;
    760 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    761 		index = p->cmap.index;
    762 		count = p->cmap.count;
    763 		if (index >= 2 || (index + count) > 2)
    764 			return (EINVAL);
    765 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    766 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    767 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    768 			return (EFAULT);
    769 	}
    770 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    771 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    772 			return (EINVAL);
    773 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    774 		if (!uvm_useracc(p->image, icount, B_READ) ||
    775 		    !uvm_useracc(p->mask, icount, B_READ))
    776 			return (EFAULT);
    777 	}
    778 
    779 	if (v & WSDISPLAY_CURSOR_DOCUR)
    780 		sc->sc_curenb = p->enable;
    781 	if (v & WSDISPLAY_CURSOR_DOPOS)
    782 		set_curpos(sc, &p->pos);
    783 	if (v & WSDISPLAY_CURSOR_DOHOT)
    784 		cc->cc_hot = p->hot;
    785 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    786 		copyin(p->cmap.red, &cc->cc_color[index], count);
    787 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    788 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    789 	}
    790 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    791 		cc->cc_size = p->size;
    792 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    793 		copyin(p->image, cc->cc_image, icount);
    794 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    795 	}
    796 	sc->sc_changed = v;
    797 
    798 	return (0);
    799 #undef cc
    800 }
    801 
    802 static int
    803 get_cursor(sc, p)
    804 	struct sfbp_softc *sc;
    805 	struct wsdisplay_cursor *p;
    806 {
    807 	return (ENOTTY); /* XXX */
    808 }
    809 
    810 static void
    811 set_curpos(sc, curpos)
    812 	struct sfbp_softc *sc;
    813 	struct wsdisplay_curpos *curpos;
    814 {
    815 	struct rasops_info *ri = sc->sc_ri;
    816 	int x = curpos->x, y = curpos->y;
    817 
    818 	if (y < 0)
    819 		y = 0;
    820 	else if (y > ri->ri_height)
    821 		y = ri->ri_height;
    822 	if (x < 0)
    823 		x = 0;
    824 	else if (x > ri->ri_width)
    825 		x = ri->ri_width;
    826 	sc->sc_cursor.cc_pos.x = x;
    827 	sc->sc_cursor.cc_pos.y = y;
    828 }
    829 
    830 static void
    831 bt459visible(hw, on)
    832 	caddr_t hw;
    833 	int on;
    834 {
    835 	hw += SFB_RAMDAC_OFFSET;
    836 	SELECT(hw, BT459_IREG_CCR);
    837 	REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
    838 	tc_wmb();
    839 }
    840 
    841 static void
    842 sfbpvisible(hw, on)
    843 	caddr_t hw;
    844 	int on;
    845 {
    846 	/* XXX use SFBplus ASIC XX */
    847 }
    848 
    849 static void
    850 bt459locate(hw, cc)
    851 	caddr_t hw;
    852 	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(hw, cc)
    874 	caddr_t hw;
    875 	struct hwcursor64 *cc;
    876 {
    877 	int x, y;
    878 
    879 	x = cc->cc_pos.x - cc->cc_hot.x;
    880 	y = cc->cc_pos.y - cc->cc_hot.y;
    881 
    882 	hw += SFB_ASIC_OFFSET;
    883 	*((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
    884 	tc_wmb();
    885 }
    886 
    887 static void
    888 bt459color(hw, cp)
    889 	caddr_t hw;
    890 	u_int8_t *cp;
    891 {
    892 
    893 	hw += SFB_RAMDAC_OFFSET;
    894 
    895 	SELECT(hw, BT459_IREG_CCOLOR_2);
    896 	REG(hw, bt_reg) = cp[1]; tc_wmb();
    897 	REG(hw, bt_reg) = cp[3]; tc_wmb();
    898 	REG(hw, bt_reg) = cp[5]; tc_wmb();
    899 
    900 	REG(hw, bt_reg) = cp[0]; tc_wmb();
    901 	REG(hw, bt_reg) = cp[2]; tc_wmb();
    902 	REG(hw, bt_reg) = cp[4]; tc_wmb();
    903 }
    904 
    905 static void
    906 bt463color(hw, cp)
    907 	caddr_t hw;
    908 	u_int8_t *cp;
    909 {
    910 }
    911 
    912 static void
    913 bt459shape(hw, size, image)
    914 	caddr_t hw;
    915 	struct wsdisplay_curpos *size;
    916 	u_int64_t *image;
    917 {
    918 	u_int8_t *ip, *mp, img, msk;
    919 	u_int8_t u;
    920 	int bcnt;
    921 
    922 	hw += SFB_RAMDAC_OFFSET;
    923 	ip = (u_int8_t *)image;
    924 	mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
    925 
    926 	bcnt = 0;
    927 	SELECT(hw, BT459_IREG_CRAM_BASE+0);
    928 	/* 64 pixel scan line is consisted with 16 byte cursor ram */
    929 	while (bcnt < size->y * 16) {
    930 		/* pad right half 32 pixel when smaller than 33 */
    931 		if ((bcnt & 0x8) && size->x < 33) {
    932 			REG(hw, bt_reg) = 0; tc_wmb();
    933 			REG(hw, bt_reg) = 0; tc_wmb();
    934 		}
    935 		else {
    936 			img = *ip++;
    937 			msk = *mp++;
    938 			img &= msk;	/* cookie off image */
    939 			u = (msk & 0x0f) << 4 | (img & 0x0f);
    940 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    941 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
    942 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    943 		}
    944 		bcnt += 2;
    945 	}
    946 	/* pad unoccupied scan lines */
    947 	while (bcnt < CURSOR_MAX_SIZE * 16) {
    948 		REG(hw, bt_reg) = 0; tc_wmb();
    949 		REG(hw, bt_reg) = 0; tc_wmb();
    950 		bcnt += 2;
    951 	}
    952 }
    953 
    954 static void
    955 sfbpshape(hw, size, image)
    956 	caddr_t hw;
    957 	struct wsdisplay_curpos *size;
    958 	u_int64_t *image;
    959 {
    960 	/* XXX use SFBplus ASIC XXX */
    961 }
    962 
    963 static void
    964 bt459setlut(hw, cm)
    965 	caddr_t hw;
    966 	struct hwcmap256 *cm;
    967 {
    968 	int index;
    969 
    970 	hw += SFB_RAMDAC_OFFSET;
    971 	SELECT(hw, 0);
    972 	for (index = 0; index < CMAP_SIZE; index++) {
    973 		REG(hw, bt_cmap) = cm->r[index];	tc_wmb();
    974 		REG(hw, bt_cmap) = cm->g[index];	tc_wmb();
    975 		REG(hw, bt_cmap) = cm->b[index];	tc_wmb();
    976 	}
    977 }
    978 
    979 static void
    980 noplut(hw, cm)
    981 	caddr_t hw;
    982 	struct hwcmap256 *cm;
    983 {
    984 }
    985 
    986 #define SFBBPP 32
    987 
    988 #define	MODE_SIMPLE		0
    989 #define	MODE_OPAQUESTIPPLE	1
    990 #define	MODE_OPAQUELINE		2
    991 #define	MODE_TRANSPARENTSTIPPLE	5
    992 #define	MODE_TRANSPARENTLINE	6
    993 #define	MODE_COPY		7
    994 
    995 #if SFBBPP == 8
    996 /* parameters for 8bpp configuration */
    997 #define	SFBALIGNMASK		0x7
    998 #define	SFBPIXELBYTES		1
    999 #define	SFBSTIPPLEALL1		0xffffffff
   1000 #define	SFBSTIPPLEBITS		32
   1001 #define	SFBSTIPPLEBITMASK	0x1f
   1002 #define	SFBSTIPPLEBYTESDONE	32
   1003 #define	SFBCOPYALL1		0xffffffff
   1004 #define	SFBCOPYBITS		32
   1005 #define	SFBCOPYBITMASK		0x1f
   1006 #define	SFBCOPYBYTESDONE	32
   1007 
   1008 #elif SFBBPP == 32
   1009 /* parameters for 32bpp configuration */
   1010 #define	SFBALIGNMASK		0x7
   1011 #define	SFBPIXELBYTES		4
   1012 #define	SFBSTIPPLEALL1		0x0000ffff
   1013 #define	SFBSTIPPLEBITS		16
   1014 #define	SFBSTIPPLEBITMASK	0xf
   1015 #define	SFBSTIPPLEBYTESDONE	32
   1016 #define	SFBCOPYALL1		0x000000ff
   1017 #define	SFBCOPYBITS		8
   1018 #define	SFBCOPYBITMASK		0x3
   1019 #define	SFBCOPYBYTESDONE	32
   1020 #endif
   1021 
   1022 #ifdef pmax
   1023 #define	WRITE_MB()
   1024 #define	BUMP(p) (p)
   1025 #endif
   1026 
   1027 #ifdef alpha
   1028 #define	WRITE_MB() tc_wmb()
   1029 /* registers is replicated in 1KB stride; rap round 4th iteration */
   1030 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
   1031 #endif
   1032 
   1033 #define	SFBMODE(p, v) \
   1034 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
   1035 #define	SFBROP(p, v) \
   1036 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
   1037 #define	SFBPLANEMASK(p, v) \
   1038 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
   1039 #define	SFBPIXELMASK(p, v) \
   1040 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
   1041 #define	SFBADDRESS(p, v) \
   1042 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
   1043 #define	SFBSTART(p, v) \
   1044 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
   1045 #define	SFBPIXELSHIFT(p, v) \
   1046 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
   1047 #define	SFBFG(p, v) \
   1048 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
   1049 #define	SFBBG(p, v) \
   1050 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
   1051 #define	SFBBCONT(p, v) \
   1052 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
   1053 
   1054 #define	SFBDATA(p, v) \
   1055 		(*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
   1056 
   1057 #define	SFBCOPY64BYTESDONE	8
   1058 #define	SFBCOPY64BITS		64
   1059 #define	SFBCOPY64SRC(p, v) \
   1060 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
   1061 #define	SFBCOPY64DST(p, v) \
   1062 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
   1063 
   1064 /*
   1065  * Actually write a string to the frame buffer.
   1066  */
   1067 static void
   1068 sfbp_putchar(id, row, col, uc, attr)
   1069 	void *id;
   1070 	int row, col;
   1071 	u_int uc;
   1072 	long attr;
   1073 {
   1074 	struct rasops_info *ri = id;
   1075 	caddr_t sfb, p;
   1076 	int scanspan, height, width, align, x, y;
   1077 	u_int32_t lmask, rmask, glyph;
   1078 	u_int8_t *g;
   1079 
   1080 	x = col * ri->ri_font->fontwidth;
   1081 	y = row * ri->ri_font->fontheight;
   1082 	scanspan = ri->ri_stride;
   1083 	height = ri->ri_font->fontheight;
   1084 	uc -= ri->ri_font->firstchar;
   1085 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1086 
   1087 	p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
   1088 	align = (long)p & SFBALIGNMASK;
   1089 	p -= align;
   1090 	align /= SFBPIXELBYTES;
   1091 	width = ri->ri_font->fontwidth + align;
   1092 	lmask = SFBSTIPPLEALL1 << align;
   1093 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1094 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1095 
   1096 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1097 	SFBPLANEMASK(sfb, ~0);
   1098 	SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
   1099 	SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1100 	SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
   1101 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
   1102 
   1103 	/* XXX 2B stride fonts only XXX */
   1104 	while (height > 0) {
   1105 		glyph = *(u_int16_t *)g;		/* XXX */
   1106 		*(u_int32_t *)p = glyph << align;
   1107 		p += scanspan;
   1108 		g += 2;					/* XXX */
   1109 		height--;
   1110 	}
   1111 	SFBMODE(sfb, MODE_SIMPLE);
   1112 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
   1113 }
   1114 
   1115 #undef	SFBSTIPPLEALL1
   1116 #undef	SFBSTIPPLEBITS
   1117 #undef	SFBSTIPPLEBITMASK
   1118 #define	SFBSTIPPLEALL1		SFBCOPYALL1
   1119 #define	SFBSTIPPLEBITS		SFBCOPYBITS
   1120 #define	SFBSTIPPLEBITMASK	SFBCOPYBITMASK
   1121 
   1122 /*
   1123  * Clear characters in a line.
   1124  */
   1125 static void
   1126 sfbp_erasecols(id, row, startcol, ncols, attr)
   1127 	void *id;
   1128 	int row, startcol, ncols;
   1129 	long attr;
   1130 {
   1131 	struct rasops_info *ri = id;
   1132 	caddr_t sfb, p;
   1133 	int scanspan, startx, height, width, align, w, y;
   1134 	u_int32_t lmask, rmask;
   1135 
   1136 	scanspan = ri->ri_stride;
   1137 	y = row * ri->ri_font->fontheight;
   1138 	startx = startcol * ri->ri_font->fontwidth;
   1139 	height = ri->ri_font->fontheight;
   1140 	w = ri->ri_font->fontwidth * ncols;
   1141 
   1142 	p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
   1143 	align = (long)p & SFBALIGNMASK;
   1144 	align /= SFBPIXELBYTES;
   1145 	p -= align;
   1146 	width = w + align;
   1147 	lmask = SFBSTIPPLEALL1 << align;
   1148 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1149 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1150 
   1151 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1152 	SFBPLANEMASK(sfb, ~0);
   1153 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
   1154 	if (width <= SFBSTIPPLEBITS) {
   1155 		lmask = lmask & rmask;
   1156 		while (height > 0) {
   1157 			*(u_int32_t *)p = lmask;
   1158 			p += scanspan;
   1159 			height--;
   1160 		}
   1161 	}
   1162 	else {
   1163 		caddr_t q = p;
   1164 		while (height > 0) {
   1165 			*(u_int32_t *)p = lmask;
   1166 			WRITE_MB();
   1167 			width -= 2 * SFBSTIPPLEBITS;
   1168 			while (width > 0) {
   1169 				p += SFBSTIPPLEBYTESDONE;
   1170 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1171 				WRITE_MB();
   1172 				width -= SFBSTIPPLEBITS;
   1173 			}
   1174 			p += SFBSTIPPLEBYTESDONE;
   1175 			*(u_int32_t *)p = rmask;
   1176 			WRITE_MB();
   1177 
   1178 			p = (q += scanspan);
   1179 			width = w + align;
   1180 			height--;
   1181 		}
   1182 	}
   1183 	SFBMODE(sfb, MODE_SIMPLE);
   1184 }
   1185 
   1186 #if 1
   1187 /*
   1188  * Copy lines.
   1189  */
   1190 static void
   1191 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1192 	void *id;
   1193 	int srcrow, dstrow, nrows;
   1194 {
   1195 	struct rasops_info *ri = id;
   1196 	caddr_t sfb, p;
   1197 	int scanspan, offset, srcy, height, width, align, w;
   1198 	u_int32_t lmask, rmask;
   1199 
   1200 	scanspan = ri->ri_stride;
   1201 	height = ri->ri_font->fontheight * nrows;
   1202 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1203 	srcy = ri->ri_font->fontheight * srcrow;
   1204 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1205 		scanspan = -scanspan;
   1206 		srcy += height;
   1207 	}
   1208 
   1209 	p = ri->ri_bits + srcy * ri->ri_stride;
   1210 	align = (long)p & SFBALIGNMASK;
   1211 	p -= align;
   1212 	align /= SFBPIXELBYTES;
   1213 	w = ri->ri_emuwidth;
   1214 	width = w + align;
   1215 	lmask = SFBCOPYALL1 << align;
   1216 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1217 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1218 
   1219 	SFBMODE(sfb, MODE_COPY);
   1220 	SFBPLANEMASK(sfb, ~0);
   1221 	SFBPIXELSHIFT(sfb, 0);
   1222 	if (width <= SFBCOPYBITS) {
   1223 		/* never happens */;
   1224 	}
   1225 	else {
   1226 		caddr_t q = p;
   1227 		while (height > 0) {
   1228 			*(u_int32_t *)p = lmask;
   1229 			*(u_int32_t *)(p + offset) = lmask;
   1230 			width -= 2 * SFBCOPYBITS;
   1231 			while (width > 0) {
   1232 				p += SFBCOPYBYTESDONE;
   1233 				*(u_int32_t *)p = SFBCOPYALL1;
   1234 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1235 				width -= SFBCOPYBITS;
   1236 			}
   1237 			p += SFBCOPYBYTESDONE;
   1238 			*(u_int32_t *)p = rmask;
   1239 			*(u_int32_t *)(p + offset) = rmask;
   1240 
   1241 			p = (q += scanspan);
   1242 			width = w + align;
   1243 			height--;
   1244 		}
   1245 	}
   1246 	SFBMODE(sfb, MODE_SIMPLE);
   1247 }
   1248 
   1249 #else
   1250 
   1251 
   1252 static void
   1253 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1254 	void *id;
   1255 	int srcrow, dstrow, nrows;
   1256 {
   1257 	struct rasops_info *ri = id;
   1258 	caddr_t sfb, p, q;
   1259 	int scanspan, offset, srcy, height, width, w, align;
   1260 	u_int32_t rmask, lmask;
   1261 
   1262 	scanspan = ri->ri_stride;
   1263 	height = ri->ri_font->fontheight * nrows;
   1264 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1265 	srcy = ri->ri_font->fontheight * srcrow;
   1266 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1267 		scanspan = -scanspan;
   1268 		srcy += height;
   1269 	}
   1270 
   1271 	p = ri->ri_bits + srcy * ri->ri_stride;
   1272 	align = (long)p & SFBALIGNMASK;
   1273 	w = ri->ri_emuwidth;
   1274 	width = w + align;
   1275 	lmask = SFBCOPYALL1 << align;
   1276 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1277 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1278 	q = p;
   1279 
   1280 	SFBMODE(sfb, MODE_COPY);
   1281 	SFBPLANEMASK(sfb, ~0);
   1282 	SFBPIXELSHIFT(sfb, 0);
   1283 
   1284 	if (width <= SFBCOPYBITS)
   1285 		; /* never happens */
   1286 	else if (width < SFBCOPY64BITS) {
   1287 		; /* unlikely happens */
   1288 
   1289 	}
   1290 	else {
   1291 		while (height > 0) {
   1292 			while (width >= SFBCOPY64BITS) {
   1293 				SFBCOPY64SRC(sfb, p);
   1294 				SFBCOPY64DST(sfb, p + offset);
   1295 				p += SFBCOPY64BYTESDONE;
   1296 				width -= SFBCOPY64BITS;
   1297 			}
   1298 			if (width >= SFBCOPYBITS) {
   1299 				*(u_int32_t *)p = SFBCOPYALL1;
   1300 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1301 				p += SFBCOPYBYTESDONE;
   1302 				width -= SFBCOPYBITS;
   1303 			}
   1304 			if (width > 0) {
   1305 				*(u_int32_t *)p = rmask;
   1306 				*(u_int32_t *)(p + offset) = rmask;
   1307 			}
   1308 
   1309 			p = (q += scanspan);
   1310 			width = w;
   1311 			height--;
   1312 		}
   1313 	}
   1314 	SFBMODE(sfb, MODE_SIMPLE);
   1315 }
   1316 #endif
   1317 
   1318 /*
   1319  * Erase lines.
   1320  */
   1321 static void
   1322 sfbp_eraserows(id, startrow, nrows, attr)
   1323 	void *id;
   1324 	int startrow, nrows;
   1325 	long attr;
   1326 {
   1327 	struct rasops_info *ri = id;
   1328 	caddr_t sfb, p;
   1329 	int scanspan, starty, height, width, align, w;
   1330 	u_int32_t lmask, rmask;
   1331 
   1332 	scanspan = ri->ri_stride;
   1333 	starty = ri->ri_font->fontheight * startrow;
   1334 	height = ri->ri_font->fontheight * nrows;
   1335 
   1336 	p = ri->ri_bits + starty * scanspan;
   1337 	align = (long)p & SFBALIGNMASK;
   1338 	p -= align;
   1339 	align /= SFBPIXELBYTES;
   1340 	w = ri->ri_emuwidth * SFBPIXELBYTES;
   1341 	width = w + align;
   1342 	lmask = SFBSTIPPLEALL1 << align;
   1343 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1344 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1345 
   1346 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1347 	SFBPLANEMASK(sfb, ~0);
   1348 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1349 	if (width <= SFBSTIPPLEBITS) {
   1350 		/* never happens */;
   1351 	}
   1352 	else {
   1353 		caddr_t q = p;
   1354 		while (height > 0) {
   1355 			*(u_int32_t *)p = lmask;
   1356 			WRITE_MB();
   1357 			width -= 2 * SFBSTIPPLEBITS;
   1358 			while (width > 0) {
   1359 				p += SFBSTIPPLEBYTESDONE;
   1360 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1361 				WRITE_MB();
   1362 				width -= SFBSTIPPLEBITS;
   1363 			}
   1364 			p += SFBSTIPPLEBYTESDONE;
   1365 			*(u_int32_t *)p = rmask;
   1366 			WRITE_MB();
   1367 
   1368 			p = (q += scanspan);
   1369 			width = w + align;
   1370 			height--;
   1371 		}
   1372 	}
   1373 	SFBMODE(sfb, MODE_SIMPLE);
   1374 }
   1375