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