Home | History | Annotate | Line # | Download | only in tc
sfbplus.c revision 1.19
      1 /* $NetBSD: sfbplus.c,v 1.19 2003/11/13 03:09:29 chs 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.19 2003/11/13 03:09:29 chs Exp $");
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/kernel.h>
     39 #include <sys/device.h>
     40 #include <sys/malloc.h>
     41 #include <sys/buf.h>
     42 #include <sys/ioctl.h>
     43 
     44 #include <machine/bus.h>
     45 #include <machine/intr.h>
     46 
     47 #include <dev/wscons/wsconsio.h>
     48 #include <dev/wscons/wsdisplayvar.h>
     49 
     50 #include <dev/rasops/rasops.h>
     51 #include <dev/wsfont/wsfont.h>
     52 
     53 #include <dev/tc/tcvar.h>
     54 #include <dev/ic/bt459reg.h>
     55 #include <dev/ic/bt463reg.h>
     56 #include <dev/tc/sfbreg.h>
     57 #include <dev/pci/tgareg.h>
     58 
     59 #include <uvm/uvm_extern.h>
     60 
     61 #if defined(pmax)
     62 #define	machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
     63 #endif
     64 
     65 #if defined(alpha)
     66 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
     67 #endif
     68 
     69 /* Bt459/Bt463 hardware registers */
     70 #define bt_lo	0
     71 #define bt_hi	1
     72 #define bt_reg	2
     73 #define bt_cmap 3
     74 
     75 #define REG(base, index)	*((u_int32_t *)(base) + (index))
     76 #define SELECT(vdac, regno) do {			\
     77 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
     78 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
     79 	tc_wmb();					\
     80    } while (0)
     81 
     82 struct hwcmap256 {
     83 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
     84 	u_int8_t r[CMAP_SIZE];
     85 	u_int8_t g[CMAP_SIZE];
     86 	u_int8_t b[CMAP_SIZE];
     87 };
     88 
     89 struct hwcursor64 {
     90 	struct wsdisplay_curpos cc_pos;
     91 	struct wsdisplay_curpos cc_hot;
     92 	struct wsdisplay_curpos cc_size;
     93 	struct wsdisplay_curpos cc_magic;
     94 #define	CURSOR_MAX_SIZE	64
     95 	u_int8_t cc_color[6];
     96 	u_int64_t cc_image[CURSOR_MAX_SIZE];
     97 	u_int64_t cc_mask[CURSOR_MAX_SIZE];
     98 };
     99 
    100 struct hwops {
    101 	void (*setlut) __P((caddr_t, struct hwcmap256 *));
    102 	void (*getlut) __P((caddr_t, struct hwcmap256 *));
    103 	void (*visible) __P((caddr_t, int));
    104 	void (*locate) __P((caddr_t, struct hwcursor64 *));
    105 	void (*shape) __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    106 	void (*color) __P((caddr_t, u_int8_t *));
    107 };
    108 
    109 struct sfbp_softc {
    110 	struct device sc_dev;
    111 	vaddr_t sc_vaddr;
    112 	size_t sc_size;
    113 	struct rasops_info *sc_ri;
    114 	struct hwcmap256 sc_cmap;	/* software copy of colormap */
    115 	struct hwcursor64 sc_cursor;	/* software copy of cursor */
    116 	int sc_blanked;
    117 	int sc_curenb;			/* cursor sprite enabled */
    118 	int sc_changed;			/* need update of hardware */
    119 #define	WSDISPLAY_CMAP_DOLUT	0x20
    120 	int nscreens;
    121 	struct hwops sc_hwops;
    122 };
    123 
    124 #define	HX_MAGIC_X	368
    125 #define	HX_MAGIC_Y	38
    126 
    127 static int  sfbpmatch __P((struct device *, struct cfdata *, void *));
    128 static void sfbpattach __P((struct device *, struct device *, void *));
    129 
    130 CFATTACH_DECL(sfbp, sizeof(struct sfbp_softc),
    131     sfbpmatch, sfbpattach, NULL, NULL);
    132 
    133 static void sfbp_common_init __P((struct rasops_info *));
    134 static struct rasops_info sfbp_console_ri;
    135 static tc_addr_t sfbp_consaddr;
    136 
    137 static struct wsscreen_descr sfbp_stdscreen = {
    138 	"std", 0, 0,
    139 	NULL, /* textops */
    140 	0, 0,
    141 	WSSCREEN_REVERSE
    142 };
    143 
    144 static const struct wsscreen_descr *_sfb_scrlist[] = {
    145 	&sfbp_stdscreen,
    146 };
    147 
    148 static const struct wsscreen_list sfb_screenlist = {
    149 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    150 };
    151 
    152 static int	sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    153 static paddr_t	sfbmmap __P((void *, off_t, int));
    154 
    155 static int	sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    156 				      void **, int *, int *, long *));
    157 static void	sfb_free_screen __P((void *, void *));
    158 static int	sfb_show_screen __P((void *, void *, int,
    159 				     void (*) (void *, int, int), void *));
    160 static void sfbp_putchar __P((void *, int, int, u_int, long));
    161 static void sfbp_erasecols __P((void *, int, int, int, long));
    162 static void sfbp_eraserows __P((void *, int, int, long));
    163 static void sfbp_copyrows __P((void *, int, int, int));
    164 
    165 static const struct wsdisplay_accessops sfb_accessops = {
    166 	sfbioctl,
    167 	sfbmmap,
    168 	sfb_alloc_screen,
    169 	sfb_free_screen,
    170 	sfb_show_screen,
    171 	0 /* load_font */
    172 };
    173 
    174 static void bt459init __P((caddr_t));
    175 static void bt459visible __P((caddr_t, int));
    176 static void bt459locate __P((caddr_t, struct hwcursor64 *));
    177 static void bt459shape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    178 static void bt459color __P((caddr_t, u_int8_t *));
    179 static void bt459setlut __P((caddr_t, struct hwcmap256 *));
    180 
    181 static void sfbpvisible __P((caddr_t, int));
    182 static void sfbplocate __P((caddr_t, struct hwcursor64 *));
    183 static void sfbpshape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
    184 static void bt463init __P((caddr_t));
    185 static void bt463color __P((caddr_t, u_int8_t *));
    186 static void noplut __P((caddr_t, struct hwcmap256 *));
    187 
    188 /* EXPORT */ int sfbp_cnattach __P((tc_addr_t));
    189 static int  sfbpintr __P((void *));
    190 
    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 (EPASSTHROUGH);
    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.allocattr)(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.allocattr)(&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 	int error;
    714 
    715 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
    716 		return (EINVAL);
    717 
    718 	error = copyout(&sc->sc_cmap.r[index], p->red, count);
    719 	if (error)
    720 		return error;
    721 	error = copyout(&sc->sc_cmap.g[index], p->green, count);
    722 	if (error)
    723 		return error;
    724 	error = copyout(&sc->sc_cmap.b[index], p->blue, count);
    725 	return error;
    726 }
    727 
    728 static int
    729 set_cmap(sc, p)
    730 	struct sfbp_softc *sc;
    731 	struct wsdisplay_cmap *p;
    732 {
    733 	struct hwcmap256 cmap;
    734 	u_int index = p->index, count = p->count;
    735 	int error;
    736 
    737 	if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
    738 		return (EINVAL);
    739 
    740 	error = copyin(p->red, &cmap.r[index], count);
    741 	if (error)
    742 		return error;
    743 	error = copyin(p->green, &cmap.g[index], count);
    744 	if (error)
    745 		return error;
    746 	error = copyin(p->blue, &cmap.b[index], count);
    747 	if (error)
    748 		return error;
    749 	memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
    750 	memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
    751 	memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
    752 	sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
    753 	return (0);
    754 }
    755 
    756 static int
    757 set_cursor(sc, p)
    758 	struct sfbp_softc *sc;
    759 	struct wsdisplay_cursor *p;
    760 {
    761 #define	cc (&sc->sc_cursor)
    762 	u_int v, index = 0, count = 0, icount = 0;
    763 	uint8_t r[2], g[2], b[2], image[512], mask[512];
    764 	int error;
    765 
    766 	v = p->which;
    767 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    768 		index = p->cmap.index;
    769 		count = p->cmap.count;
    770 		if (index >= 2 || (index + count) > 2)
    771 			return (EINVAL);
    772 		error = copyin(p->cmap.red, &r[index], count);
    773 		if (error)
    774 			return error;
    775 		error = copyin(p->cmap.green, &g[index], count);
    776 		if (error)
    777 			return error;
    778 		error = copyin(p->cmap.blue, &b[index], count);
    779 		if (error)
    780 			return error;
    781 	}
    782 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    783 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    784 			return (EINVAL);
    785 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    786 		error = copyin(p->image, image, icount);
    787 		if (error)
    788 			return error;
    789 		error = copyin(p->mask, mask, icount);
    790 		if (error)
    791 			return error;
    792 	}
    793 
    794 	if (v & WSDISPLAY_CURSOR_DOCUR)
    795 		sc->sc_curenb = p->enable;
    796 	if (v & WSDISPLAY_CURSOR_DOPOS)
    797 		set_curpos(sc, &p->pos);
    798 	if (v & WSDISPLAY_CURSOR_DOHOT)
    799 		cc->cc_hot = p->hot;
    800 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    801 		memcpy(&cc->cc_color[index], &r[index], count);
    802 		memcpy(&cc->cc_color[index + 2], &g[index], count);
    803 		memcpy(&cc->cc_color[index + 4], &b[index], count);
    804 	}
    805 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    806 		cc->cc_size = p->size;
    807 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    808 		memcpy(cc->cc_image, image, icount);
    809 		memset(cc->cc_mask, 0, sizeof cc->cc_mask);
    810 		memcpy(cc->cc_mask, mask, icount);
    811 	}
    812 	sc->sc_changed = v;
    813 
    814 	return (0);
    815 #undef cc
    816 }
    817 
    818 static int
    819 get_cursor(sc, p)
    820 	struct sfbp_softc *sc;
    821 	struct wsdisplay_cursor *p;
    822 {
    823 	return (EPASSTHROUGH); /* XXX */
    824 }
    825 
    826 static void
    827 set_curpos(sc, curpos)
    828 	struct sfbp_softc *sc;
    829 	struct wsdisplay_curpos *curpos;
    830 {
    831 	struct rasops_info *ri = sc->sc_ri;
    832 	int x = curpos->x, y = curpos->y;
    833 
    834 	if (y < 0)
    835 		y = 0;
    836 	else if (y > ri->ri_height)
    837 		y = ri->ri_height;
    838 	if (x < 0)
    839 		x = 0;
    840 	else if (x > ri->ri_width)
    841 		x = ri->ri_width;
    842 	sc->sc_cursor.cc_pos.x = x;
    843 	sc->sc_cursor.cc_pos.y = y;
    844 }
    845 
    846 static void
    847 bt459visible(hw, on)
    848 	caddr_t hw;
    849 	int on;
    850 {
    851 	hw += SFB_RAMDAC_OFFSET;
    852 	SELECT(hw, BT459_IREG_CCR);
    853 	REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
    854 	tc_wmb();
    855 }
    856 
    857 static void
    858 sfbpvisible(hw, on)
    859 	caddr_t hw;
    860 	int on;
    861 {
    862 	/* XXX use SFBplus ASIC XX */
    863 }
    864 
    865 static void
    866 bt459locate(hw, cc)
    867 	caddr_t hw;
    868 	struct hwcursor64 *cc;
    869 {
    870 	int x, y, s;
    871 
    872 	x = cc->cc_pos.x - cc->cc_hot.x;
    873 	y = cc->cc_pos.y - cc->cc_hot.y;
    874 	x += cc->cc_magic.x;
    875 	y += cc->cc_magic.y;
    876 
    877 	hw += SFB_RAMDAC_OFFSET;
    878 
    879 	s = spltty();
    880 	SELECT(hw, BT459_IREG_CURSOR_X_LOW);
    881 	REG(hw, bt_reg) = x;		tc_wmb();
    882 	REG(hw, bt_reg) = x >> 8;	tc_wmb();
    883 	REG(hw, bt_reg) = y;		tc_wmb();
    884 	REG(hw, bt_reg) = y >> 8;	tc_wmb();
    885 	splx(s);
    886 }
    887 
    888 static void
    889 sfbplocate(hw, cc)
    890 	caddr_t hw;
    891 	struct hwcursor64 *cc;
    892 {
    893 	int x, y;
    894 
    895 	x = cc->cc_pos.x - cc->cc_hot.x;
    896 	y = cc->cc_pos.y - cc->cc_hot.y;
    897 
    898 	hw += SFB_ASIC_OFFSET;
    899 	*((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
    900 	tc_wmb();
    901 }
    902 
    903 static void
    904 bt459color(hw, cp)
    905 	caddr_t hw;
    906 	u_int8_t *cp;
    907 {
    908 
    909 	hw += SFB_RAMDAC_OFFSET;
    910 
    911 	SELECT(hw, BT459_IREG_CCOLOR_2);
    912 	REG(hw, bt_reg) = cp[1]; tc_wmb();
    913 	REG(hw, bt_reg) = cp[3]; tc_wmb();
    914 	REG(hw, bt_reg) = cp[5]; tc_wmb();
    915 
    916 	REG(hw, bt_reg) = cp[0]; tc_wmb();
    917 	REG(hw, bt_reg) = cp[2]; tc_wmb();
    918 	REG(hw, bt_reg) = cp[4]; tc_wmb();
    919 }
    920 
    921 static void
    922 bt463color(hw, cp)
    923 	caddr_t hw;
    924 	u_int8_t *cp;
    925 {
    926 }
    927 
    928 static void
    929 bt459shape(hw, size, image)
    930 	caddr_t hw;
    931 	struct wsdisplay_curpos *size;
    932 	u_int64_t *image;
    933 {
    934 	u_int8_t *ip, *mp, img, msk;
    935 	u_int8_t u;
    936 	int bcnt;
    937 
    938 	hw += SFB_RAMDAC_OFFSET;
    939 	ip = (u_int8_t *)image;
    940 	mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
    941 
    942 	bcnt = 0;
    943 	SELECT(hw, BT459_IREG_CRAM_BASE+0);
    944 	/* 64 pixel scan line is consisted with 16 byte cursor ram */
    945 	while (bcnt < size->y * 16) {
    946 		/* pad right half 32 pixel when smaller than 33 */
    947 		if ((bcnt & 0x8) && size->x < 33) {
    948 			REG(hw, bt_reg) = 0; tc_wmb();
    949 			REG(hw, bt_reg) = 0; tc_wmb();
    950 		}
    951 		else {
    952 			img = *ip++;
    953 			msk = *mp++;
    954 			img &= msk;	/* cookie off image */
    955 			u = (msk & 0x0f) << 4 | (img & 0x0f);
    956 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    957 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
    958 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    959 		}
    960 		bcnt += 2;
    961 	}
    962 	/* pad unoccupied scan lines */
    963 	while (bcnt < CURSOR_MAX_SIZE * 16) {
    964 		REG(hw, bt_reg) = 0; tc_wmb();
    965 		REG(hw, bt_reg) = 0; tc_wmb();
    966 		bcnt += 2;
    967 	}
    968 }
    969 
    970 static void
    971 sfbpshape(hw, size, image)
    972 	caddr_t hw;
    973 	struct wsdisplay_curpos *size;
    974 	u_int64_t *image;
    975 {
    976 	/* XXX use SFBplus ASIC XXX */
    977 }
    978 
    979 static void
    980 bt459setlut(hw, cm)
    981 	caddr_t hw;
    982 	struct hwcmap256 *cm;
    983 {
    984 	int index;
    985 
    986 	hw += SFB_RAMDAC_OFFSET;
    987 	SELECT(hw, 0);
    988 	for (index = 0; index < CMAP_SIZE; index++) {
    989 		REG(hw, bt_cmap) = cm->r[index];	tc_wmb();
    990 		REG(hw, bt_cmap) = cm->g[index];	tc_wmb();
    991 		REG(hw, bt_cmap) = cm->b[index];	tc_wmb();
    992 	}
    993 }
    994 
    995 static void
    996 noplut(hw, cm)
    997 	caddr_t hw;
    998 	struct hwcmap256 *cm;
    999 {
   1000 }
   1001 
   1002 #define SFBBPP 32
   1003 
   1004 #define	MODE_SIMPLE		0
   1005 #define	MODE_OPAQUESTIPPLE	1
   1006 #define	MODE_OPAQUELINE		2
   1007 #define	MODE_TRANSPARENTSTIPPLE	5
   1008 #define	MODE_TRANSPARENTLINE	6
   1009 #define	MODE_COPY		7
   1010 
   1011 #if SFBBPP == 8
   1012 /* parameters for 8bpp configuration */
   1013 #define	SFBALIGNMASK		0x7
   1014 #define	SFBPIXELBYTES		1
   1015 #define	SFBSTIPPLEALL1		0xffffffff
   1016 #define	SFBSTIPPLEBITS		32
   1017 #define	SFBSTIPPLEBITMASK	0x1f
   1018 #define	SFBSTIPPLEBYTESDONE	32
   1019 #define	SFBCOPYALL1		0xffffffff
   1020 #define	SFBCOPYBITS		32
   1021 #define	SFBCOPYBITMASK		0x1f
   1022 #define	SFBCOPYBYTESDONE	32
   1023 
   1024 #elif SFBBPP == 32
   1025 /* parameters for 32bpp configuration */
   1026 #define	SFBALIGNMASK		0x7
   1027 #define	SFBPIXELBYTES		4
   1028 #define	SFBSTIPPLEALL1		0x0000ffff
   1029 #define	SFBSTIPPLEBITS		16
   1030 #define	SFBSTIPPLEBITMASK	0xf
   1031 #define	SFBSTIPPLEBYTESDONE	32
   1032 #define	SFBCOPYALL1		0x000000ff
   1033 #define	SFBCOPYBITS		8
   1034 #define	SFBCOPYBITMASK		0x3
   1035 #define	SFBCOPYBYTESDONE	32
   1036 #endif
   1037 
   1038 #ifdef pmax
   1039 #define	WRITE_MB()
   1040 #define	BUMP(p) (p)
   1041 #endif
   1042 
   1043 #ifdef alpha
   1044 #define	WRITE_MB() tc_wmb()
   1045 /* registers is replicated in 1KB stride; rap round 4th iteration */
   1046 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
   1047 #endif
   1048 
   1049 #define	SFBMODE(p, v) \
   1050 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
   1051 #define	SFBROP(p, v) \
   1052 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
   1053 #define	SFBPLANEMASK(p, v) \
   1054 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
   1055 #define	SFBPIXELMASK(p, v) \
   1056 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
   1057 #define	SFBADDRESS(p, v) \
   1058 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
   1059 #define	SFBSTART(p, v) \
   1060 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
   1061 #define	SFBPIXELSHIFT(p, v) \
   1062 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
   1063 #define	SFBFG(p, v) \
   1064 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
   1065 #define	SFBBG(p, v) \
   1066 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
   1067 #define	SFBBCONT(p, v) \
   1068 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
   1069 
   1070 #define	SFBDATA(p, v) \
   1071 		(*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
   1072 
   1073 #define	SFBCOPY64BYTESDONE	8
   1074 #define	SFBCOPY64BITS		64
   1075 #define	SFBCOPY64SRC(p, v) \
   1076 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
   1077 #define	SFBCOPY64DST(p, v) \
   1078 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
   1079 
   1080 /*
   1081  * Actually write a string to the frame buffer.
   1082  */
   1083 static void
   1084 sfbp_putchar(id, row, col, uc, attr)
   1085 	void *id;
   1086 	int row, col;
   1087 	u_int uc;
   1088 	long attr;
   1089 {
   1090 	struct rasops_info *ri = id;
   1091 	caddr_t sfb, p;
   1092 	int scanspan, height, width, align, x, y;
   1093 	u_int32_t lmask, rmask, glyph;
   1094 	u_int8_t *g;
   1095 
   1096 	x = col * ri->ri_font->fontwidth;
   1097 	y = row * ri->ri_font->fontheight;
   1098 	scanspan = ri->ri_stride;
   1099 	height = ri->ri_font->fontheight;
   1100 	uc -= ri->ri_font->firstchar;
   1101 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1102 
   1103 	p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
   1104 	align = (long)p & SFBALIGNMASK;
   1105 	p -= align;
   1106 	align /= SFBPIXELBYTES;
   1107 	width = ri->ri_font->fontwidth + align;
   1108 	lmask = SFBSTIPPLEALL1 << align;
   1109 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1110 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1111 
   1112 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1113 	SFBPLANEMASK(sfb, ~0);
   1114 	SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
   1115 	SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1116 	SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
   1117 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
   1118 
   1119 	/* XXX 2B stride fonts only XXX */
   1120 	while (height > 0) {
   1121 		glyph = *(u_int16_t *)g;		/* XXX */
   1122 		*(u_int32_t *)p = glyph << align;
   1123 		p += scanspan;
   1124 		g += 2;					/* XXX */
   1125 		height--;
   1126 	}
   1127 	SFBMODE(sfb, MODE_SIMPLE);
   1128 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
   1129 }
   1130 
   1131 #undef	SFBSTIPPLEALL1
   1132 #undef	SFBSTIPPLEBITS
   1133 #undef	SFBSTIPPLEBITMASK
   1134 #define	SFBSTIPPLEALL1		SFBCOPYALL1
   1135 #define	SFBSTIPPLEBITS		SFBCOPYBITS
   1136 #define	SFBSTIPPLEBITMASK	SFBCOPYBITMASK
   1137 
   1138 /*
   1139  * Clear characters in a line.
   1140  */
   1141 static void
   1142 sfbp_erasecols(id, row, startcol, ncols, attr)
   1143 	void *id;
   1144 	int row, startcol, ncols;
   1145 	long attr;
   1146 {
   1147 	struct rasops_info *ri = id;
   1148 	caddr_t sfb, p;
   1149 	int scanspan, startx, height, width, align, w, y;
   1150 	u_int32_t lmask, rmask;
   1151 
   1152 	scanspan = ri->ri_stride;
   1153 	y = row * ri->ri_font->fontheight;
   1154 	startx = startcol * ri->ri_font->fontwidth;
   1155 	height = ri->ri_font->fontheight;
   1156 	w = ri->ri_font->fontwidth * ncols;
   1157 
   1158 	p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
   1159 	align = (long)p & SFBALIGNMASK;
   1160 	align /= SFBPIXELBYTES;
   1161 	p -= align;
   1162 	width = w + align;
   1163 	lmask = SFBSTIPPLEALL1 << align;
   1164 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1165 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1166 
   1167 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1168 	SFBPLANEMASK(sfb, ~0);
   1169 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
   1170 	if (width <= SFBSTIPPLEBITS) {
   1171 		lmask = lmask & rmask;
   1172 		while (height > 0) {
   1173 			*(u_int32_t *)p = lmask;
   1174 			p += scanspan;
   1175 			height--;
   1176 		}
   1177 	}
   1178 	else {
   1179 		caddr_t q = p;
   1180 		while (height > 0) {
   1181 			*(u_int32_t *)p = lmask;
   1182 			WRITE_MB();
   1183 			width -= 2 * SFBSTIPPLEBITS;
   1184 			while (width > 0) {
   1185 				p += SFBSTIPPLEBYTESDONE;
   1186 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1187 				WRITE_MB();
   1188 				width -= SFBSTIPPLEBITS;
   1189 			}
   1190 			p += SFBSTIPPLEBYTESDONE;
   1191 			*(u_int32_t *)p = rmask;
   1192 			WRITE_MB();
   1193 
   1194 			p = (q += scanspan);
   1195 			width = w + align;
   1196 			height--;
   1197 		}
   1198 	}
   1199 	SFBMODE(sfb, MODE_SIMPLE);
   1200 }
   1201 
   1202 #if 1
   1203 /*
   1204  * Copy lines.
   1205  */
   1206 static void
   1207 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1208 	void *id;
   1209 	int srcrow, dstrow, nrows;
   1210 {
   1211 	struct rasops_info *ri = id;
   1212 	caddr_t sfb, p;
   1213 	int scanspan, offset, srcy, height, width, align, w;
   1214 	u_int32_t lmask, rmask;
   1215 
   1216 	scanspan = ri->ri_stride;
   1217 	height = ri->ri_font->fontheight * nrows;
   1218 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1219 	srcy = ri->ri_font->fontheight * srcrow;
   1220 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1221 		scanspan = -scanspan;
   1222 		srcy += height;
   1223 	}
   1224 
   1225 	p = ri->ri_bits + srcy * ri->ri_stride;
   1226 	align = (long)p & SFBALIGNMASK;
   1227 	p -= align;
   1228 	align /= SFBPIXELBYTES;
   1229 	w = ri->ri_emuwidth;
   1230 	width = w + align;
   1231 	lmask = SFBCOPYALL1 << align;
   1232 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1233 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1234 
   1235 	SFBMODE(sfb, MODE_COPY);
   1236 	SFBPLANEMASK(sfb, ~0);
   1237 	SFBPIXELSHIFT(sfb, 0);
   1238 	if (width <= SFBCOPYBITS) {
   1239 		/* never happens */;
   1240 	}
   1241 	else {
   1242 		caddr_t q = p;
   1243 		while (height > 0) {
   1244 			*(u_int32_t *)p = lmask;
   1245 			*(u_int32_t *)(p + offset) = lmask;
   1246 			width -= 2 * SFBCOPYBITS;
   1247 			while (width > 0) {
   1248 				p += SFBCOPYBYTESDONE;
   1249 				*(u_int32_t *)p = SFBCOPYALL1;
   1250 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1251 				width -= SFBCOPYBITS;
   1252 			}
   1253 			p += SFBCOPYBYTESDONE;
   1254 			*(u_int32_t *)p = rmask;
   1255 			*(u_int32_t *)(p + offset) = rmask;
   1256 
   1257 			p = (q += scanspan);
   1258 			width = w + align;
   1259 			height--;
   1260 		}
   1261 	}
   1262 	SFBMODE(sfb, MODE_SIMPLE);
   1263 }
   1264 
   1265 #else
   1266 
   1267 
   1268 static void
   1269 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1270 	void *id;
   1271 	int srcrow, dstrow, nrows;
   1272 {
   1273 	struct rasops_info *ri = id;
   1274 	caddr_t sfb, p, q;
   1275 	int scanspan, offset, srcy, height, width, w, align;
   1276 	u_int32_t rmask, lmask;
   1277 
   1278 	scanspan = ri->ri_stride;
   1279 	height = ri->ri_font->fontheight * nrows;
   1280 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1281 	srcy = ri->ri_font->fontheight * srcrow;
   1282 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1283 		scanspan = -scanspan;
   1284 		srcy += height;
   1285 	}
   1286 
   1287 	p = ri->ri_bits + srcy * ri->ri_stride;
   1288 	align = (long)p & SFBALIGNMASK;
   1289 	w = ri->ri_emuwidth;
   1290 	width = w + align;
   1291 	lmask = SFBCOPYALL1 << align;
   1292 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1293 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1294 	q = p;
   1295 
   1296 	SFBMODE(sfb, MODE_COPY);
   1297 	SFBPLANEMASK(sfb, ~0);
   1298 	SFBPIXELSHIFT(sfb, 0);
   1299 
   1300 	if (width <= SFBCOPYBITS)
   1301 		; /* never happens */
   1302 	else if (width < SFBCOPY64BITS) {
   1303 		; /* unlikely happens */
   1304 
   1305 	}
   1306 	else {
   1307 		while (height > 0) {
   1308 			while (width >= SFBCOPY64BITS) {
   1309 				SFBCOPY64SRC(sfb, p);
   1310 				SFBCOPY64DST(sfb, p + offset);
   1311 				p += SFBCOPY64BYTESDONE;
   1312 				width -= SFBCOPY64BITS;
   1313 			}
   1314 			if (width >= SFBCOPYBITS) {
   1315 				*(u_int32_t *)p = SFBCOPYALL1;
   1316 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1317 				p += SFBCOPYBYTESDONE;
   1318 				width -= SFBCOPYBITS;
   1319 			}
   1320 			if (width > 0) {
   1321 				*(u_int32_t *)p = rmask;
   1322 				*(u_int32_t *)(p + offset) = rmask;
   1323 			}
   1324 
   1325 			p = (q += scanspan);
   1326 			width = w;
   1327 			height--;
   1328 		}
   1329 	}
   1330 	SFBMODE(sfb, MODE_SIMPLE);
   1331 }
   1332 #endif
   1333 
   1334 /*
   1335  * Erase lines.
   1336  */
   1337 static void
   1338 sfbp_eraserows(id, startrow, nrows, attr)
   1339 	void *id;
   1340 	int startrow, nrows;
   1341 	long attr;
   1342 {
   1343 	struct rasops_info *ri = id;
   1344 	caddr_t sfb, p;
   1345 	int scanspan, starty, height, width, align, w;
   1346 	u_int32_t lmask, rmask;
   1347 
   1348 	scanspan = ri->ri_stride;
   1349 	starty = ri->ri_font->fontheight * startrow;
   1350 	height = ri->ri_font->fontheight * nrows;
   1351 
   1352 	p = ri->ri_bits + starty * scanspan;
   1353 	align = (long)p & SFBALIGNMASK;
   1354 	p -= align;
   1355 	align /= SFBPIXELBYTES;
   1356 	w = ri->ri_emuwidth * SFBPIXELBYTES;
   1357 	width = w + align;
   1358 	lmask = SFBSTIPPLEALL1 << align;
   1359 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1360 	sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
   1361 
   1362 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1363 	SFBPLANEMASK(sfb, ~0);
   1364 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1365 	if (width <= SFBSTIPPLEBITS) {
   1366 		/* never happens */;
   1367 	}
   1368 	else {
   1369 		caddr_t q = p;
   1370 		while (height > 0) {
   1371 			*(u_int32_t *)p = lmask;
   1372 			WRITE_MB();
   1373 			width -= 2 * SFBSTIPPLEBITS;
   1374 			while (width > 0) {
   1375 				p += SFBSTIPPLEBYTESDONE;
   1376 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1377 				WRITE_MB();
   1378 				width -= SFBSTIPPLEBITS;
   1379 			}
   1380 			p += SFBSTIPPLEBYTESDONE;
   1381 			*(u_int32_t *)p = rmask;
   1382 			WRITE_MB();
   1383 
   1384 			p = (q += scanspan);
   1385 			width = w + align;
   1386 			height--;
   1387 		}
   1388 	}
   1389 	SFBMODE(sfb, MODE_SIMPLE);
   1390 }
   1391