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