Home | History | Annotate | Line # | Download | only in tc
sfbplus.c revision 1.10
      1 /* $NetBSD: sfbplus.c,v 1.10 2001/08/05 18:07:55 jdolecek 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.10 2001/08/05 18:07:55 jdolecek 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, TC_ROM_LLEN) != 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 
    286 	/*
    287 	 * - neglect 0,1 cases of hsetup register.
    288 	 * - observed 804x600?, 644x480? values.
    289 	 */
    290 	dc->dc_wid = (hsetup & 0x1ff) << 2;
    291 	dc->dc_ht = (vsetup & 0x7ff);
    292 	dc->dc_depth = (i & 1) ? 32 : 8;
    293 	dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
    294 	dc->dc_blanked = 0;
    295 
    296 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    297 	vbase *= (i & 0x20) ? 2048 : 4096;	/* VRAM chip size */
    298 	if (i & 1) vbase *= 4;			/* bytes per pixel */
    299 	dc->dc_videobase = dc->dc_vaddr + 0x800000 + vbase;
    300 
    301 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    302 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    303 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;	/* MODE_SIMPLE */
    304 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;	/* ROP_COPY */
    305 
    306 	/* initialize colormap and cursor resource */
    307 	sfbpinit(dc);
    308 
    309 	/* clear the screen */
    310 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    311 		*(u_int32_t *)(dc->dc_videobase + i) = 0x0;
    312 
    313 	ri = &dc->rinfo;
    314 	ri->ri_flg = RI_CENTER;
    315 	ri->ri_flg = 0;			/* XXX PATCH HOLES in rasops */
    316 	ri->ri_depth = dc->dc_depth;
    317 	ri->ri_bits = (void *)dc->dc_videobase;
    318 	ri->ri_width = dc->dc_wid;
    319 	ri->ri_height = dc->dc_ht;
    320 	ri->ri_stride = dc->dc_rowbytes;
    321 	ri->ri_hw = sfbasic;
    322 
    323 	if (dc->dc_depth == 32) {
    324 		ri->ri_rnum = 8;
    325 		ri->ri_gnum = 8;
    326 		ri->ri_bnum = 8;
    327 		ri->ri_rpos = 16;
    328 		ri->ri_gpos = 8;
    329 		ri->ri_bpos = 0;
    330 	}
    331 
    332 	wsfont_init();
    333 	/* prefer 8 pixel wide font */
    334 	if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
    335 		cookie = wsfont_find(NULL, 0, 0, 0);
    336 	if (cookie <= 0) {
    337 		printf("sfbp: font table is empty\n");
    338 		return;
    339 	}
    340 
    341 	/* the accelerated sfbp_putchar() needs LSbit left */
    342 	if (wsfont_lock(cookie, &dc->rinfo.ri_font,
    343 	    WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
    344 		printf("sfb: couldn't lock font\n");
    345 		return;
    346 	}
    347 	dc->rinfo.ri_wsfcookie = cookie;
    348 
    349 	rasops_init(&dc->rinfo, 34, 80);
    350 
    351 	/* add our accelerated functions */
    352 	dc->rinfo.ri_ops.putchar = sfbp_putchar;
    353 	dc->rinfo.ri_ops.erasecols = sfbp_erasecols;
    354 	dc->rinfo.ri_ops.copyrows = sfbp_copyrows;
    355 	dc->rinfo.ri_ops.eraserows = sfbp_eraserows;
    356 
    357 	/* XXX shouldn't be global */
    358 	sfbp_stdscreen.nrows = dc->rinfo.ri_rows;
    359 	sfbp_stdscreen.ncols = dc->rinfo.ri_cols;
    360 	sfbp_stdscreen.textops = &dc->rinfo.ri_ops;
    361 	sfbp_stdscreen.capabilities = dc->rinfo.ri_caps;
    362 	/* our accelerated putchar can't underline */
    363 	sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
    364 }
    365 
    366 static void
    367 sfbpattach(parent, self, aux)
    368 	struct device *parent, *self;
    369 	void *aux;
    370 {
    371 	struct sfbp_softc *sc = (struct sfbp_softc *)self;
    372 	struct tc_attach_args *ta = aux;
    373 	struct wsemuldisplaydev_attach_args waa;
    374 	caddr_t sfbasic;
    375 	int console;
    376 
    377 	console = (ta->ta_addr == sfbp_consaddr);
    378 	if (console) {
    379 		sc->sc_dc = &sfbp_console_dc;
    380 		sc->nscreens = 1;
    381 	}
    382 	else {
    383 		sc->sc_dc = (struct fb_devconfig *)
    384 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    385 		sfbp_getdevconfig(ta->ta_addr, sc->sc_dc);
    386 	}
    387 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    388 	    (sc->sc_dc->dc_depth != 32) ? 8 : 24);
    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) = 0x48;	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 	u_int v, index, count, icount;
    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 
    807 	if (v & WSDISPLAY_CURSOR_DOCUR)
    808 		sc->sc_curenb = p->enable;
    809 	if (v & WSDISPLAY_CURSOR_DOPOS)
    810 		set_curpos(sc, &p->pos);
    811 	if (v & WSDISPLAY_CURSOR_DOHOT)
    812 		cc->cc_hot = p->hot;
    813 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    814 		copyin(p->cmap.red, &cc->cc_color[index], count);
    815 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    816 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    817 	}
    818 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    819 		cc->cc_size = p->size;
    820 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    821 		copyin(p->image, cc->cc_image, icount);
    822 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    823 	}
    824 	sc->sc_changed = v;
    825 
    826 	return (0);
    827 #undef cc
    828 }
    829 
    830 static int
    831 get_cursor(sc, p)
    832 	struct sfbp_softc *sc;
    833 	struct wsdisplay_cursor *p;
    834 {
    835 	return (ENOTTY); /* XXX */
    836 }
    837 
    838 static void
    839 set_curpos(sc, curpos)
    840 	struct sfbp_softc *sc;
    841 	struct wsdisplay_curpos *curpos;
    842 {
    843 	struct fb_devconfig *dc = sc->sc_dc;
    844 	int x = curpos->x, y = curpos->y;
    845 
    846 	if (y < 0)
    847 		y = 0;
    848 	else if (y > dc->dc_ht)
    849 		y = dc->dc_ht;
    850 	if (x < 0)
    851 		x = 0;
    852 	else if (x > dc->dc_wid)
    853 		x = dc->dc_wid;
    854 	sc->sc_cursor.cc_pos.x = x;
    855 	sc->sc_cursor.cc_pos.y = y;
    856 }
    857 
    858 static void
    859 bt459visible(hw, on)
    860 	void *hw;
    861 	int on;
    862 {
    863 	SELECT(hw, BT459_IREG_CCR);
    864 	REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
    865 	tc_wmb();
    866 }
    867 
    868 static void
    869 sfbpvisible(hw, on)
    870 	void *hw;
    871 	int on;
    872 {
    873 	/* XXX use SFBplus ASIC XX */
    874 }
    875 
    876 static void
    877 bt459locate(hw, cc)
    878 	void *hw;
    879 	struct hwcursor64 *cc;
    880 {
    881 	int x, y, s;
    882 
    883 	x = cc->cc_pos.x - cc->cc_hot.x;
    884 	y = cc->cc_pos.y - cc->cc_hot.y;
    885 	x += cc->cc_magic.x;
    886 	y += cc->cc_magic.y;
    887 
    888 	s = spltty();
    889 	SELECT(hw, BT459_IREG_CURSOR_X_LOW);
    890 	REG(hw, bt_reg) = x;		tc_wmb();
    891 	REG(hw, bt_reg) = x >> 8;	tc_wmb();
    892 	REG(hw, bt_reg) = y;		tc_wmb();
    893 	REG(hw, bt_reg) = y >> 8;	tc_wmb();
    894 	splx(s);
    895 }
    896 
    897 static void
    898 sfbplocate(hw, cc)
    899 	void *hw;
    900 	struct hwcursor64 *cc;
    901 {
    902 	int x, y;
    903 
    904 	x = cc->cc_pos.x - cc->cc_hot.x;
    905 	y = cc->cc_pos.y - cc->cc_hot.y;
    906 	*((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
    907 	tc_wmb();
    908 }
    909 
    910 static void
    911 bt459color(hw, cp)
    912 	void *hw;
    913 	u_int8_t *cp;
    914 {
    915 	SELECT(hw, BT459_IREG_CCOLOR_2);
    916 	REG(hw, bt_reg) = cp[1]; tc_wmb();
    917 	REG(hw, bt_reg) = cp[3]; tc_wmb();
    918 	REG(hw, bt_reg) = cp[5]; tc_wmb();
    919 
    920 	REG(hw, bt_reg) = cp[0]; tc_wmb();
    921 	REG(hw, bt_reg) = cp[2]; tc_wmb();
    922 	REG(hw, bt_reg) = cp[4]; tc_wmb();
    923 }
    924 
    925 static void
    926 bt463color(hw, cp)
    927 	void *hw;
    928 	u_int8_t *cp;
    929 {
    930 }
    931 
    932 static void
    933 bt459shape(hw, size, image)
    934 	void *hw;
    935 	struct wsdisplay_curpos *size;
    936 	u_int64_t *image;
    937 {
    938 	u_int8_t *ip, *mp, img, msk;
    939 	u_int8_t u;
    940 	int bcnt;
    941 
    942 	ip = (u_int8_t *)image;
    943 	mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
    944 
    945 	bcnt = 0;
    946 	SELECT(hw, BT459_IREG_CRAM_BASE+0);
    947 	/* 64 pixel scan line is consisted with 16 byte cursor ram */
    948 	while (bcnt < size->y * 16) {
    949 		/* pad right half 32 pixel when smaller than 33 */
    950 		if ((bcnt & 0x8) && size->x < 33) {
    951 			REG(hw, bt_reg) = 0; tc_wmb();
    952 			REG(hw, bt_reg) = 0; tc_wmb();
    953 		}
    954 		else {
    955 			img = *ip++;
    956 			msk = *mp++;
    957 			img &= msk;	/* cookie off image */
    958 			u = (msk & 0x0f) << 4 | (img & 0x0f);
    959 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    960 			u = (msk & 0xf0) | (img & 0xf0) >> 4;
    961 			REG(hw, bt_reg) = shuffle[u];	tc_wmb();
    962 		}
    963 		bcnt += 2;
    964 	}
    965 	/* pad unoccupied scan lines */
    966 	while (bcnt < CURSOR_MAX_SIZE * 16) {
    967 		REG(hw, bt_reg) = 0; tc_wmb();
    968 		REG(hw, bt_reg) = 0; tc_wmb();
    969 		bcnt += 2;
    970 	}
    971 }
    972 
    973 static void
    974 sfbpshape(hw, size, image)
    975 	void *hw;
    976 	struct wsdisplay_curpos *size;
    977 	u_int64_t *image;
    978 {
    979 	/* XXX use SFBplus ASIC XXX */
    980 }
    981 
    982 static void
    983 bt459setlut(hw, cm)
    984 	void *hw;
    985 	struct hwcmap256 *cm;
    986 {
    987 	int index;
    988 
    989 	SELECT(hw, 0);
    990 	for (index = 0; index < CMAP_SIZE; index++) {
    991 		REG(hw, bt_cmap) = cm->r[index];	tc_wmb();
    992 		REG(hw, bt_cmap) = cm->g[index];	tc_wmb();
    993 		REG(hw, bt_cmap) = cm->b[index];	tc_wmb();
    994 	}
    995 }
    996 
    997 static void
    998 noplut(hw, cm)
    999 	void *hw;
   1000 	struct hwcmap256 *cm;
   1001 {
   1002 }
   1003 
   1004 #define SFBBPP 32
   1005 
   1006 #define	MODE_SIMPLE		0
   1007 #define	MODE_OPAQUESTIPPLE	1
   1008 #define	MODE_OPAQUELINE		2
   1009 #define	MODE_TRANSPARENTSTIPPLE	5
   1010 #define	MODE_TRANSPARENTLINE	6
   1011 #define	MODE_COPY		7
   1012 
   1013 #if SFBBPP == 8
   1014 /* parameters for 8bpp configuration */
   1015 #define	SFBALIGNMASK		0x7
   1016 #define	SFBPIXELBYTES		1
   1017 #define	SFBSTIPPLEALL1		0xffffffff
   1018 #define	SFBSTIPPLEBITS		32
   1019 #define	SFBSTIPPLEBITMASK	0x1f
   1020 #define	SFBSTIPPLEBYTESDONE	32
   1021 #define	SFBCOPYALL1		0xffffffff
   1022 #define	SFBCOPYBITS		32
   1023 #define	SFBCOPYBITMASK		0x1f
   1024 #define	SFBCOPYBYTESDONE	32
   1025 
   1026 #elif SFBBPP == 32
   1027 /* parameters for 32bpp configuration */
   1028 #define	SFBALIGNMASK		0x7
   1029 #define	SFBPIXELBYTES		4
   1030 #define	SFBSTIPPLEALL1		0x0000ffff
   1031 #define	SFBSTIPPLEBITS		16
   1032 #define	SFBSTIPPLEBITMASK	0xf
   1033 #define	SFBSTIPPLEBYTESDONE	32
   1034 #define	SFBCOPYALL1		0x000000ff
   1035 #define	SFBCOPYBITS		8
   1036 #define	SFBCOPYBITMASK		0x3
   1037 #define	SFBCOPYBYTESDONE	32
   1038 #endif
   1039 
   1040 #ifdef pmax
   1041 #define	WRITE_MB()
   1042 #define	BUMP(p) (p)
   1043 #endif
   1044 
   1045 #ifdef alpha
   1046 #define	WRITE_MB() tc_wmb()
   1047 /* registers is replicated in 1KB stride; rap round 4th iteration */
   1048 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
   1049 #endif
   1050 
   1051 #define	SFBMODE(p, v) \
   1052 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
   1053 #define	SFBROP(p, v) \
   1054 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
   1055 #define	SFBPLANEMASK(p, v) \
   1056 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
   1057 #define	SFBPIXELMASK(p, v) \
   1058 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
   1059 #define	SFBADDRESS(p, v) \
   1060 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
   1061 #define	SFBSTART(p, v) \
   1062 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
   1063 #define	SFBPIXELSHIFT(p, v) \
   1064 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
   1065 #define	SFBFG(p, v) \
   1066 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
   1067 #define	SFBBG(p, v) \
   1068 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
   1069 #define	SFBBCONT(p, v) \
   1070 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
   1071 
   1072 #define	SFBDATA(p, v) \
   1073 		(*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
   1074 
   1075 #define	SFBCOPY64BYTESDONE	8
   1076 #define	SFBCOPY64BITS		64
   1077 #define	SFBCOPY64SRC(p, v) \
   1078 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
   1079 #define	SFBCOPY64DST(p, v) \
   1080 		(*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
   1081 
   1082 /*
   1083  * Actually write a string to the frame buffer.
   1084  */
   1085 static void
   1086 sfbp_putchar(id, row, col, uc, attr)
   1087 	void *id;
   1088 	int row, col;
   1089 	u_int uc;
   1090 	long attr;
   1091 {
   1092 	struct rasops_info *ri = id;
   1093 	caddr_t sfb, p;
   1094 	int scanspan, height, width, align, x, y;
   1095 	u_int32_t lmask, rmask, glyph;
   1096 	u_int8_t *g;
   1097 
   1098 	x = col * ri->ri_font->fontwidth;
   1099 	y = row * ri->ri_font->fontheight;
   1100 	scanspan = ri->ri_stride;
   1101 	height = ri->ri_font->fontheight;
   1102 	uc -= ri->ri_font->firstchar;
   1103 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1104 
   1105 	p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
   1106 	align = (long)p & SFBALIGNMASK;
   1107 	p -= align;
   1108 	align /= SFBPIXELBYTES;
   1109 	width = ri->ri_font->fontwidth + align;
   1110 	lmask = SFBSTIPPLEALL1 << align;
   1111 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1112 	sfb = ri->ri_hw;
   1113 
   1114 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1115 	SFBPLANEMASK(sfb, ~0);
   1116 	SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
   1117 	SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1118 	SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
   1119 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
   1120 
   1121 	/* XXX 2B stride fonts only XXX */
   1122 	while (height > 0) {
   1123 		glyph = *(u_int16_t *)g;		/* XXX */
   1124 		*(u_int32_t *)p = glyph << align;
   1125 		p += scanspan;
   1126 		g += 2;					/* XXX */
   1127 		height--;
   1128 	}
   1129 	SFBMODE(sfb, MODE_SIMPLE);
   1130 	*((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
   1131 }
   1132 
   1133 #undef	SFBSTIPPLEALL1
   1134 #undef	SFBSTIPPLEBITS
   1135 #undef	SFBSTIPPLEBITMASK
   1136 #define	SFBSTIPPLEALL1		SFBCOPYALL1
   1137 #define	SFBSTIPPLEBITS		SFBCOPYBITS
   1138 #define	SFBSTIPPLEBITMASK	SFBCOPYBITMASK
   1139 
   1140 /*
   1141  * Clear characters in a line.
   1142  */
   1143 static void
   1144 sfbp_erasecols(id, row, startcol, ncols, attr)
   1145 	void *id;
   1146 	int row, startcol, ncols;
   1147 	long attr;
   1148 {
   1149 	struct rasops_info *ri = id;
   1150 	caddr_t sfb, p;
   1151 	int scanspan, startx, height, width, align, w, y;
   1152 	u_int32_t lmask, rmask;
   1153 
   1154 	scanspan = ri->ri_stride;
   1155 	y = row * ri->ri_font->fontheight;
   1156 	startx = startcol * ri->ri_font->fontwidth;
   1157 	height = ri->ri_font->fontheight;
   1158 	w = ri->ri_font->fontwidth * ncols;
   1159 
   1160 	p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
   1161 	align = (long)p & SFBALIGNMASK;
   1162 	align /= SFBPIXELBYTES;
   1163 	p -= align;
   1164 	width = w + align;
   1165 	lmask = SFBSTIPPLEALL1 << align;
   1166 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1167 	sfb = ri->ri_hw;
   1168 
   1169 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1170 	SFBPLANEMASK(sfb, ~0);
   1171 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
   1172 	if (width <= SFBSTIPPLEBITS) {
   1173 		lmask = lmask & rmask;
   1174 		while (height > 0) {
   1175 			*(u_int32_t *)p = lmask;
   1176 			p += scanspan;
   1177 			height--;
   1178 		}
   1179 	}
   1180 	else {
   1181 		caddr_t q = p;
   1182 		while (height > 0) {
   1183 			*(u_int32_t *)p = lmask;
   1184 			WRITE_MB();
   1185 			width -= 2 * SFBSTIPPLEBITS;
   1186 			while (width > 0) {
   1187 				p += SFBSTIPPLEBYTESDONE;
   1188 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1189 				WRITE_MB();
   1190 				width -= SFBSTIPPLEBITS;
   1191 			}
   1192 			p += SFBSTIPPLEBYTESDONE;
   1193 			*(u_int32_t *)p = rmask;
   1194 			WRITE_MB();
   1195 
   1196 			p = (q += scanspan);
   1197 			width = w + align;
   1198 			height--;
   1199 		}
   1200 	}
   1201 	SFBMODE(sfb, MODE_SIMPLE);
   1202 }
   1203 
   1204 #if 1
   1205 /*
   1206  * Copy lines.
   1207  */
   1208 static void
   1209 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1210 	void *id;
   1211 	int srcrow, dstrow, nrows;
   1212 {
   1213 	struct rasops_info *ri = id;
   1214 	caddr_t sfb, p;
   1215 	int scanspan, offset, srcy, height, width, align, w;
   1216 	u_int32_t lmask, rmask;
   1217 
   1218 	scanspan = ri->ri_stride;
   1219 	height = ri->ri_font->fontheight * nrows;
   1220 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1221 	srcy = ri->ri_font->fontheight * srcrow;
   1222 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1223 		scanspan = -scanspan;
   1224 		srcy += height;
   1225 	}
   1226 
   1227 	p = ri->ri_bits + srcy * ri->ri_stride;
   1228 	align = (long)p & SFBALIGNMASK;
   1229 	p -= align;
   1230 	align /= SFBPIXELBYTES;
   1231 	w = ri->ri_emuwidth;
   1232 	width = w + align;
   1233 	lmask = SFBCOPYALL1 << align;
   1234 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1235 	sfb = ri->ri_hw;
   1236 
   1237 	SFBMODE(sfb, MODE_COPY);
   1238 	SFBPLANEMASK(sfb, ~0);
   1239 	SFBPIXELSHIFT(sfb, 0);
   1240 	if (width <= SFBCOPYBITS) {
   1241 		/* never happens */;
   1242 	}
   1243 	else {
   1244 		caddr_t q = p;
   1245 		while (height > 0) {
   1246 			*(u_int32_t *)p = lmask;
   1247 			*(u_int32_t *)(p + offset) = lmask;
   1248 			width -= 2 * SFBCOPYBITS;
   1249 			while (width > 0) {
   1250 				p += SFBCOPYBYTESDONE;
   1251 				*(u_int32_t *)p = SFBCOPYALL1;
   1252 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1253 				width -= SFBCOPYBITS;
   1254 			}
   1255 			p += SFBCOPYBYTESDONE;
   1256 			*(u_int32_t *)p = rmask;
   1257 			*(u_int32_t *)(p + offset) = rmask;
   1258 
   1259 			p = (q += scanspan);
   1260 			width = w + align;
   1261 			height--;
   1262 		}
   1263 	}
   1264 	SFBMODE(sfb, MODE_SIMPLE);
   1265 }
   1266 
   1267 #else
   1268 
   1269 
   1270 static void
   1271 sfbp_copyrows(id, srcrow, dstrow, nrows)
   1272 	void *id;
   1273 	int srcrow, dstrow, nrows;
   1274 {
   1275 	struct rasops_info *ri = id;
   1276 	caddr_t sfb, p, q;
   1277 	int scanspan, offset, srcy, height, width, w, align;
   1278 	u_int32_t rmask, lmask;
   1279 
   1280 	scanspan = ri->ri_stride;
   1281 	height = ri->ri_font->fontheight * nrows;
   1282 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1283 	srcy = ri->ri_font->fontheight * srcrow;
   1284 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1285 		scanspan = -scanspan;
   1286 		srcy += height;
   1287 	}
   1288 
   1289 	p = ri->ri_bits + srcy * ri->ri_stride;
   1290 	align = (long)p & SFBALIGNMASK;
   1291 	w = ri->ri_emuwidth;
   1292 	width = w + align;
   1293 	lmask = SFBCOPYALL1 << align;
   1294 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1295 	sfb = ri->ri_hw;
   1296 	q = p;
   1297 
   1298 	SFBMODE(sfb, MODE_COPY);
   1299 	SFBPLANEMASK(sfb, ~0);
   1300 	SFBPIXELSHIFT(sfb, 0);
   1301 
   1302 	if (width <= SFBCOPYBITS)
   1303 		; /* never happens */
   1304 	else if (width < SFBCOPY64BITS) {
   1305 		; /* unlikely happens */
   1306 
   1307 	}
   1308 	else {
   1309 		while (height > 0) {
   1310 			while (width >= SFBCOPY64BITS) {
   1311 				SFBCOPY64SRC(sfb, p);
   1312 				SFBCOPY64DST(sfb, p + offset);
   1313 				p += SFBCOPY64BYTESDONE;
   1314 				width -= SFBCOPY64BITS;
   1315 			}
   1316 			if (width >= SFBCOPYBITS) {
   1317 				*(u_int32_t *)p = SFBCOPYALL1;
   1318 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1319 				p += SFBCOPYBYTESDONE;
   1320 				width -= SFBCOPYBITS;
   1321 			}
   1322 			if (width > 0) {
   1323 				*(u_int32_t *)p = rmask;
   1324 				*(u_int32_t *)(p + offset) = rmask;
   1325 			}
   1326 
   1327 			p = (q += scanspan);
   1328 			width = w;
   1329 			height--;
   1330 		}
   1331 	}
   1332 	SFBMODE(sfb, MODE_SIMPLE);
   1333 }
   1334 #endif
   1335 
   1336 /*
   1337  * Erase lines.
   1338  */
   1339 static void
   1340 sfbp_eraserows(id, startrow, nrows, attr)
   1341 	void *id;
   1342 	int startrow, nrows;
   1343 	long attr;
   1344 {
   1345 	struct rasops_info *ri = id;
   1346 	caddr_t sfb, p;
   1347 	int scanspan, starty, height, width, align, w;
   1348 	u_int32_t lmask, rmask;
   1349 
   1350 	scanspan = ri->ri_stride;
   1351 	starty = ri->ri_font->fontheight * startrow;
   1352 	height = ri->ri_font->fontheight * nrows;
   1353 
   1354 	p = ri->ri_bits + starty * scanspan;
   1355 	align = (long)p & SFBALIGNMASK;
   1356 	p -= align;
   1357 	align /= SFBPIXELBYTES;
   1358 	w = ri->ri_emuwidth * SFBPIXELBYTES;
   1359 	width = w + align;
   1360 	lmask = SFBSTIPPLEALL1 << align;
   1361 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1362 	sfb = ri->ri_hw;
   1363 
   1364 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1365 	SFBPLANEMASK(sfb, ~0);
   1366 	SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
   1367 	if (width <= SFBSTIPPLEBITS) {
   1368 		/* never happens */;
   1369 	}
   1370 	else {
   1371 		caddr_t q = p;
   1372 		while (height > 0) {
   1373 			*(u_int32_t *)p = lmask;
   1374 			WRITE_MB();
   1375 			width -= 2 * SFBSTIPPLEBITS;
   1376 			while (width > 0) {
   1377 				p += SFBSTIPPLEBYTESDONE;
   1378 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1379 				WRITE_MB();
   1380 				width -= SFBSTIPPLEBITS;
   1381 			}
   1382 			p += SFBSTIPPLEBYTESDONE;
   1383 			*(u_int32_t *)p = rmask;
   1384 			WRITE_MB();
   1385 
   1386 			p = (q += scanspan);
   1387 			width = w + align;
   1388 			height--;
   1389 		}
   1390 	}
   1391 	SFBMODE(sfb, MODE_SIMPLE);
   1392 }
   1393