Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.35
      1 /* $NetBSD: sfb.c,v 1.35 2000/03/16 05:48:28 nisimura 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.35 2000/03/16 05:48:28 nisimura Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/kernel.h>
     40 #include <sys/device.h>
     41 #include <sys/malloc.h>
     42 #include <sys/buf.h>
     43 #include <sys/ioctl.h>
     44 #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)
     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 static void sfb_putchar __P((void *, int, int, u_int, long));
    168 static void sfb_erasecols __P((void *, int, int, int, long));
    169 static void sfb_eraserows __P((void *, int, int, long));
    170 static void sfb_copyrows __P((void *, int, int, int));
    171 #if 0
    172 static void sfb_cursor __P((void *, int, int, int));
    173 static void sfb_copycols __P((void *, int, int, int, int));
    174 #endif
    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_flg = RI_CENTER;
    307 	dc->rinfo.ri_depth = dc->dc_depth;
    308 	dc->rinfo.ri_bits = (void *)dc->dc_videobase;
    309 	dc->rinfo.ri_width = dc->dc_wid;
    310 	dc->rinfo.ri_height = dc->dc_ht;
    311 	dc->rinfo.ri_stride = dc->dc_rowbytes;
    312 	dc->rinfo.ri_hw = sfbasic;
    313 
    314 	wsfont_init();
    315 	/* prefer 8 pixel wide font */
    316 	if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
    317 		cookie = wsfont_find(NULL, 0, 0, 0);
    318 	if (cookie <= 0) {
    319 		printf("sfb: font table is empty\n");
    320 		return;
    321 	}
    322 
    323 	/* the accelerated sfb_putchar() needs LSbit left */
    324 	if (wsfont_lock(cookie, &dc->rinfo.ri_font,
    325 	    WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
    326 		printf("sfb: couldn't lock font\n");
    327 		return;
    328 	}
    329 	dc->rinfo.ri_wsfcookie = cookie;
    330 
    331 	rasops_init(&dc->rinfo, 34, 80);
    332 
    333 	/* add our accelerated functions */
    334 	dc->rinfo.ri_ops.putchar = sfb_putchar;
    335 	dc->rinfo.ri_ops.erasecols = sfb_erasecols;
    336 	dc->rinfo.ri_ops.copyrows = sfb_copyrows;
    337 	dc->rinfo.ri_ops.eraserows = sfb_eraserows;
    338 
    339 	/* XXX shouldn't be global */
    340 	sfb_stdscreen.nrows = dc->rinfo.ri_rows;
    341 	sfb_stdscreen.ncols = dc->rinfo.ri_cols;
    342 	sfb_stdscreen.textops = &dc->rinfo.ri_ops;
    343 	sfb_stdscreen.capabilities = dc->rinfo.ri_caps;
    344 	/* our accelerated putchar can't underline */
    345 	sfb_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
    346 }
    347 
    348 static void
    349 sfbattach(parent, self, aux)
    350 	struct device *parent, *self;
    351 	void *aux;
    352 {
    353 	struct sfb_softc *sc = (struct sfb_softc *)self;
    354 	struct tc_attach_args *ta = aux;
    355 	struct wsemuldisplaydev_attach_args waa;
    356 	caddr_t sfbasic;
    357 	int console;
    358 
    359 	console = (ta->ta_addr == sfb_consaddr);
    360 	if (console) {
    361 		sc->sc_dc = &sfb_console_dc;
    362 		sc->nscreens = 1;
    363 	}
    364 	else {
    365 		sc->sc_dc = (struct fb_devconfig *)
    366 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    367 		memset(sc->sc_dc, 0, sizeof(struct fb_devconfig));
    368 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    369 	}
    370 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    371 	    sc->sc_dc->dc_depth);
    372 
    373 	memcpy(&sc->sc_cmap, rasops_cmap, sizeof(struct hwcmap256));
    374 
    375 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    376 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    377 
    378         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
    379 
    380 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    381 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    382 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    383 
    384 	waa.console = console;
    385 	waa.scrdata = &sfb_screenlist;
    386 	waa.accessops = &sfb_accessops;
    387 	waa.accesscookie = sc;
    388 
    389 	config_found(self, &waa, wsemuldisplaydevprint);
    390 }
    391 
    392 static int
    393 sfbioctl(v, cmd, data, flag, p)
    394 	void *v;
    395 	u_long cmd;
    396 	caddr_t data;
    397 	int flag;
    398 	struct proc *p;
    399 {
    400 	struct sfb_softc *sc = v;
    401 	struct fb_devconfig *dc = sc->sc_dc;
    402 	int turnoff;
    403 
    404 	switch (cmd) {
    405 	case WSDISPLAYIO_GTYPE:
    406 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    407 		return (0);
    408 
    409 	case WSDISPLAYIO_GINFO:
    410 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    411 		wsd_fbip->height = sc->sc_dc->dc_ht;
    412 		wsd_fbip->width = sc->sc_dc->dc_wid;
    413 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    414 		wsd_fbip->cmsize = CMAP_SIZE;
    415 #undef fbt
    416 		return (0);
    417 
    418 	case WSDISPLAYIO_GETCMAP:
    419 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    420 
    421 	case WSDISPLAYIO_PUTCMAP:
    422 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    423 
    424 	case WSDISPLAYIO_SVIDEO:
    425 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    426 		if ((dc->dc_blanked == 0) ^ turnoff) {
    427 			dc->dc_blanked = turnoff;
    428 #if 0 /* XXX later XXX */
    429 		To turn off, assign value 0 in ASIC_VIDEO_VALID register.
    430 #endif	/* XXX XXX XXX */
    431 		}
    432 		return (0);
    433 
    434 	case WSDISPLAYIO_GVIDEO:
    435 		*(u_int *)data = dc->dc_blanked ?
    436 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    437 		return (0);
    438 
    439 	case WSDISPLAYIO_GCURPOS:
    440 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    441 		return (0);
    442 
    443 	case WSDISPLAYIO_SCURPOS:
    444 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    445 		bt459_set_curpos(sc);
    446 		return (0);
    447 
    448 	case WSDISPLAYIO_GCURMAX:
    449 		((struct wsdisplay_curpos *)data)->x =
    450 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    451 		return (0);
    452 
    453 	case WSDISPLAYIO_GCURSOR:
    454 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    455 
    456 	case WSDISPLAYIO_SCURSOR:
    457 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    458 	}
    459 	return ENOTTY;
    460 }
    461 
    462 static int
    463 sfbmmap(v, offset, prot)
    464 	void *v;
    465 	off_t offset;
    466 	int prot;
    467 {
    468 	struct sfb_softc *sc = v;
    469 
    470 	if (offset >= SFB_SIZE || offset < 0)
    471 		return (-1);
    472 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    473 }
    474 
    475 static int
    476 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    477 	void *v;
    478 	const struct wsscreen_descr *type;
    479 	void **cookiep;
    480 	int *curxp, *curyp;
    481 	long *attrp;
    482 {
    483 	struct sfb_softc *sc = v;
    484 	long defattr;
    485 
    486 	if (sc->nscreens > 0)
    487 		return (ENOMEM);
    488 
    489 	*cookiep = &sc->sc_dc->rinfo; /* one and only for now */
    490 	*curxp = 0;
    491 	*curyp = 0;
    492 	(*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
    493 	*attrp = defattr;
    494 	sc->nscreens++;
    495 	return (0);
    496 }
    497 
    498 static void
    499 sfb_free_screen(v, cookie)
    500 	void *v;
    501 	void *cookie;
    502 {
    503 	struct sfb_softc *sc = v;
    504 
    505 	if (sc->sc_dc == &sfb_console_dc)
    506 		panic("sfb_free_screen: console");
    507 
    508 	sc->nscreens--;
    509 }
    510 
    511 static int
    512 sfb_show_screen(v, cookie, waitok, cb, cbarg)
    513 	void *v;
    514 	void *cookie;
    515 	int waitok;
    516 	void (*cb) __P((void *, int, int));
    517 	void *cbarg;
    518 {
    519 
    520 	return (0);
    521 }
    522 
    523 /* EXPORT */ int
    524 sfb_cnattach(addr)
    525         tc_addr_t addr;
    526 {
    527         struct fb_devconfig *dcp = &sfb_console_dc;
    528         long defattr;
    529 
    530         sfb_getdevconfig(addr, dcp);
    531 
    532         (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
    533 
    534         wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
    535         sfb_consaddr = addr;
    536         return(0);
    537 }
    538 
    539 static int
    540 sfbintr(arg)
    541 	void *arg;
    542 {
    543 	struct sfb_softc *sc = arg;
    544 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    545 	caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
    546 	caddr_t vdac;
    547 	int v;
    548 
    549 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    550 	/* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
    551 
    552 	if (sc->sc_changed == 0)
    553 		return (1);
    554 
    555 	vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    556 	v = sc->sc_changed;
    557 	sc->sc_changed = 0;
    558 
    559 	if (v & DATA_ENB_CHANGED) {
    560 		SELECT(vdac, BT459_IREG_CCR);
    561 		REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
    562 	}
    563 	if (v & DATA_CURCMAP_CHANGED) {
    564 		u_int8_t *cp = sc->sc_cursor.cc_color;
    565 
    566 		SELECT(vdac, BT459_IREG_CCOLOR_2);
    567 		REG(vdac, bt_reg) = cp[1];	tc_wmb();
    568 		REG(vdac, bt_reg) = cp[3];	tc_wmb();
    569 		REG(vdac, bt_reg) = cp[5];	tc_wmb();
    570 
    571 		REG(vdac, bt_reg) = cp[0];	tc_wmb();
    572 		REG(vdac, bt_reg) = cp[2];	tc_wmb();
    573 		REG(vdac, bt_reg) = cp[4];	tc_wmb();
    574 	}
    575 	if (v & DATA_CURSHAPE_CHANGED) {
    576 		u_int8_t *ip, *mp, img, msk;
    577 		u_int8_t u;
    578 		int bcnt;
    579 
    580 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    581 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    582 
    583 		bcnt = 0;
    584 		SELECT(vdac, BT459_IREG_CRAM_BASE+0);
    585 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    586 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    587 			/* pad right half 32 pixel when smaller than 33 */
    588 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    589 				REG(vdac, bt_reg) = 0; tc_wmb();
    590 				REG(vdac, bt_reg) = 0; tc_wmb();
    591 			}
    592 			else {
    593 				img = *ip++;
    594 				msk = *mp++;
    595 				img &= msk;	/* cookie off image */
    596 				u = (msk & 0x0f) << 4 | (img & 0x0f);
    597 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    598 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
    599 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    600 			}
    601 			bcnt += 2;
    602 		}
    603 		/* pad unoccupied scan lines */
    604 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    605 			REG(vdac, bt_reg) = 0; tc_wmb();
    606 			REG(vdac, bt_reg) = 0; tc_wmb();
    607 			bcnt += 2;
    608 		}
    609 	}
    610 	if (v & DATA_CMAP_CHANGED) {
    611 		struct hwcmap256 *cm = &sc->sc_cmap;
    612 		int index;
    613 
    614 		SELECT(vdac, 0);
    615 		for (index = 0; index < CMAP_SIZE; index++) {
    616 			REG(vdac, bt_cmap) = cm->r[index];	tc_wmb();
    617 			REG(vdac, bt_cmap) = cm->g[index];	tc_wmb();
    618 			REG(vdac, bt_cmap) = cm->b[index];	tc_wmb();
    619 		}
    620 	}
    621 	return (1);
    622 }
    623 
    624 static void
    625 sfbinit(dc)
    626 	struct fb_devconfig *dc;
    627 {
    628 	caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    629 	caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
    630 	int i;
    631 
    632 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    633 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    634 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
    635 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;  /* ROP_COPY */
    636 
    637 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    638 
    639 	SELECT(vdac, BT459_IREG_COMMAND_0);
    640 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    641 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    642 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    643 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    644 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    645 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    646 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    647 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    648 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    649 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    650 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    651 
    652 	SELECT(vdac, BT459_IREG_CCR);
    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 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    666 
    667 	/* build sane colormap */
    668 	SELECT(vdac, 0);
    669 	for (i = 0; i < CMAP_SIZE; i++) {
    670 		REG(vdac, bt_cmap) = rasops_cmap[3 * i + 0];
    671 		tc_wmb();
    672 		REG(vdac, bt_cmap) = rasops_cmap[3 * i + 1];
    673 		tc_wmb();
    674 		REG(vdac, bt_cmap) = rasops_cmap[3 * i + 2];
    675 		tc_wmb();
    676 	}
    677 
    678 	/* clear out cursor image */
    679 	SELECT(vdac, BT459_IREG_CRAM_BASE);
    680 	for (i = 0; i < 1024; i++)
    681 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    682 
    683 	/*
    684 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    685 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    686 	 * image color.  CCOLOR_1 will be never used.
    687 	 */
    688 	SELECT(vdac, BT459_IREG_CCOLOR_1);
    689 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    690 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    691 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    692 
    693 	REG(vdac, bt_reg) = 0;		tc_wmb();
    694 	REG(vdac, bt_reg) = 0;		tc_wmb();
    695 	REG(vdac, bt_reg) = 0;		tc_wmb();
    696 
    697 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    698 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    699 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    700 }
    701 
    702 static int
    703 get_cmap(sc, p)
    704 	struct sfb_softc *sc;
    705 	struct wsdisplay_cmap *p;
    706 {
    707 	u_int index = p->index, count = p->count;
    708 
    709 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    710 		return (EINVAL);
    711 
    712 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    713 	    !uvm_useracc(p->green, count, B_WRITE) ||
    714 	    !uvm_useracc(p->blue, count, B_WRITE))
    715 		return (EFAULT);
    716 
    717 	copyout(&sc->sc_cmap.r[index], p->red, count);
    718 	copyout(&sc->sc_cmap.g[index], p->green, count);
    719 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    720 
    721 	return (0);
    722 }
    723 
    724 static int
    725 set_cmap(sc, p)
    726 	struct sfb_softc *sc;
    727 	struct wsdisplay_cmap *p;
    728 {
    729 	u_int index = p->index, count = p->count;
    730 
    731 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    732 		return (EINVAL);
    733 
    734 	if (!uvm_useracc(p->red, count, B_READ) ||
    735 	    !uvm_useracc(p->green, count, B_READ) ||
    736 	    !uvm_useracc(p->blue, count, B_READ))
    737 		return (EFAULT);
    738 
    739 	copyin(p->red, &sc->sc_cmap.r[index], count);
    740 	copyin(p->green, &sc->sc_cmap.g[index], count);
    741 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    742 
    743 	sc->sc_changed |= DATA_CMAP_CHANGED;
    744 
    745 	return (0);
    746 }
    747 
    748 
    749 static int
    750 set_cursor(sc, p)
    751 	struct sfb_softc *sc;
    752 	struct wsdisplay_cursor *p;
    753 {
    754 #define	cc (&sc->sc_cursor)
    755 	int v, index, count, icount;
    756 
    757 	v = p->which;
    758 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    759 		index = p->cmap.index;
    760 		count = p->cmap.count;
    761 		if (index >= 2 || (index + count) > 2)
    762 			return (EINVAL);
    763 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    764 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    765 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    766 			return (EFAULT);
    767 	}
    768 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    769 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    770 			return (EINVAL);
    771 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    772 		if (!uvm_useracc(p->image, icount, B_READ) ||
    773 		    !uvm_useracc(p->mask, icount, B_READ))
    774 			return (EFAULT);
    775 	}
    776 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    777 		if (v & WSDISPLAY_CURSOR_DOCUR)
    778 			cc->cc_hot = p->hot;
    779 		if (v & WSDISPLAY_CURSOR_DOPOS)
    780 			set_curpos(sc, &p->pos);
    781 		bt459_set_curpos(sc);
    782 	}
    783 
    784 	sc->sc_changed = 0;
    785 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    786 		sc->sc_curenb = p->enable;
    787 		sc->sc_changed |= DATA_ENB_CHANGED;
    788 	}
    789 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    790 		copyin(p->cmap.red, &cc->cc_color[index], count);
    791 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    792 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    793 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    794 	}
    795 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    796 		cc->cc_size = p->size;
    797 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    798 		copyin(p->image, cc->cc_image, icount);
    799 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    800 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    801 	}
    802 
    803 	return (0);
    804 #undef cc
    805 }
    806 
    807 static int
    808 get_cursor(sc, p)
    809 	struct sfb_softc *sc;
    810 	struct wsdisplay_cursor *p;
    811 {
    812 
    813 	return (ENOTTY); /* XXX */
    814 }
    815 
    816 static void
    817 set_curpos(sc, curpos)
    818 	struct sfb_softc *sc;
    819 	struct wsdisplay_curpos *curpos;
    820 {
    821 	struct fb_devconfig *dc = sc->sc_dc;
    822 	int x = curpos->x, y = curpos->y;
    823 
    824 	if (y < 0)
    825 		y = 0;
    826 	else if (y > dc->dc_ht)
    827 		y = dc->dc_ht;
    828 	if (x < 0)
    829 		x = 0;
    830 	else if (x > dc->dc_wid)
    831 		x = dc->dc_wid;
    832 	sc->sc_cursor.cc_pos.x = x;
    833 	sc->sc_cursor.cc_pos.y = y;
    834 }
    835 
    836 static void
    837 bt459_set_curpos(sc)
    838 	struct sfb_softc *sc;
    839 {
    840 	caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
    841 	int x, y, s;
    842 
    843 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    844 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    845 
    846 	x += sc->sc_cursor.cc_magic.x;
    847 	y += sc->sc_cursor.cc_magic.y;
    848 
    849 	s = spltty();
    850 
    851 	SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
    852 	REG(vdac, bt_reg) = x;		tc_wmb();
    853 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    854 	REG(vdac, bt_reg) = y;		tc_wmb();
    855 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    856 
    857 	splx(s);
    858 }
    859 
    860 #define	MODE_SIMPLE		0
    861 #define	MODE_OPAQUESTIPPLE	1
    862 #define	MODE_OPAQUELINE		2
    863 #define	MODE_TRANSPARENTSTIPPLE	5
    864 #define	MODE_TRANSPARENTLINE	6
    865 #define	MODE_COPY		7
    866 
    867 /* parameters for 8bpp configuration */
    868 #define	SFBALIGNMASK		0x7
    869 #define	SFBSTIPPLEALL1		0xffffffff
    870 #define	SFBSTIPPLEBITS		32
    871 #define	SFBSTIPPLEBITMASK	0x1f
    872 #define	SFBSTIPPLEBYTESDONE	32
    873 #define	SFBCOPYALL1		0xffffffff
    874 #define	SFBCOPYBITS		32
    875 #define	SFBCOPYBITMASK		0x1f
    876 #define	SFBCOPYBYTESDONE	32
    877 
    878 #if defined(pmax)
    879 #define	WRITE_MB()
    880 #define	BUMP(p) (p)
    881 #endif
    882 
    883 #if defined(alpha)
    884 #define	WRITE_MB() tc_wmb()
    885 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
    886 #endif
    887 
    888 #define	SFBMODE(p, v) \
    889 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
    890 #define	SFBROP(p, v) \
    891 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
    892 #define	SFBPLANEMASK(p, v) \
    893 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
    894 #define	SFBPIXELMASK(p, v) \
    895 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
    896 #define	SFBADDRESS(p, v) \
    897 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
    898 #define	SFBSTART(p, v) \
    899 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
    900 #define	SFBPIXELSHIFT(p, v) \
    901 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
    902 #define	SFBFG(p, v) \
    903 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
    904 #define	SFBBG(p, v) \
    905 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
    906 
    907 
    908 #if 0
    909 /*
    910  * Paint (or unpaint) the cursor.
    911  */
    912 static void
    913 sfb_cursor(id, on, row, col)
    914 	void *id;
    915 	int on, row, col;
    916 {
    917 	struct rasops_info *ri = id;
    918 	caddr_t sfb, p;
    919 	int scanspan, height, width, align, x, y;
    920 	u_int32_t lmask, rmask;
    921 	int fg, bg;
    922 
    923 	/* turn the cursor off */
    924 	if (!on) {
    925 		/* make sure it's on */
    926 		if ((rc->rc_bits & RC_CURSOR) == 0)
    927 			return;
    928 
    929 		row = *rc->rc_crowp;
    930 		col = *rc->rc_ccolp;
    931 	} else {
    932 		/* unpaint the old copy. */
    933 		*rc->rc_crowp = row;
    934 		*rc->rc_ccolp = col;
    935 	}
    936 
    937 	x = col * ri->ri_font->fontwidth;
    938 	y = row * ri->ri_font->fontheight;
    939 	scanspan = ri->ri_stride;
    940 	height = ri->ri_font->fontheight;
    941 
    942 	p = ri->ri_bits + y * scanspan + x;
    943 	align = (long)p & SFBALIGNMASK;
    944 	p -= align;
    945 	width = ri->ri_font->fontwidth + align;
    946 	lmask = SFBSTIPPLEALL1 << align;
    947 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    948 	sfb = ri->ri_hw;
    949 
    950 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
    951 	SFBPLANEMASK(sfb, ~0);
    952 	SFBROP(sfb, 6);			/* ROP_XOR */
    953 	rasops_unpack_attr(attr, &fg, &bg, 0);
    954 	fg ^= bg;			/* (fg ^ bg) to swap fg/bg */
    955 	fg |= fg << 8;
    956 	fg |= fg << 16;
    957 	SFBFG(sfb, fg);
    958 	if (width <= SFBSTIPPLEBITS) {
    959 		lmask = lmask & rmask;
    960 		while (height > 0) {
    961 			SFBADDRESS(sfb, (long)p);
    962 			SFBSTART(sfb, lmask);
    963 			p += scanspan;
    964 			height--;
    965 		}
    966 	}
    967 	else {
    968 		caddr_t q = p;
    969 		while (height > 0) {
    970 			*(u_int32_t *)p = lmask;
    971 WRITE_MB();
    972 			p += SFBSTIPPLEBYTESDONE;
    973 			*(u_int32_t *)p = rmask;
    974 WRITE_MB();
    975 
    976 			p = (q += scanspan);
    977 			height--;
    978 		}
    979 	}
    980 	SFBMODE(sfb, MODE_SIMPLE);
    981 	SFBROP(sfb, 3);			/* ROP_COPY */
    982 
    983 	rc->rc_bits ^= RC_CURSOR;
    984 }
    985 #endif
    986 
    987 /*
    988  * Actually write a string to the frame buffer.
    989  */
    990 static void
    991 sfb_putchar(id, row, col, uc, attr)
    992 	void *id;
    993 	int row, col;
    994 	u_int uc;
    995 	long attr;
    996 {
    997 	struct rasops_info *ri = id;
    998 	caddr_t sfb, p;
    999 	int scanspan, height, width, align, x, y;
   1000 	u_int32_t lmask, rmask, glyph;
   1001 	u_int8_t *g;
   1002 	int fg, bg;
   1003 
   1004 	x = col * ri->ri_font->fontwidth;
   1005 	y = row * ri->ri_font->fontheight;
   1006 	scanspan = ri->ri_stride;
   1007 	height = ri->ri_font->fontheight;
   1008 	uc -= ri->ri_font->firstchar;
   1009 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1010 
   1011 	p = ri->ri_bits + y * scanspan + x;
   1012 	align = (long)p & SFBALIGNMASK;
   1013 	p -= align;
   1014 	width = ri->ri_font->fontwidth + align;
   1015 	lmask = SFBSTIPPLEALL1 << align;
   1016 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1017 	sfb = ri->ri_hw;
   1018 
   1019 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1020 	SFBPLANEMASK(sfb, ~0);
   1021 	rasops_unpack_attr(attr, &fg, &bg, 0);
   1022 	fg |= fg << 8;
   1023 	fg |= fg << 16;
   1024 	bg |= bg << 8;
   1025 	bg |= bg << 16;
   1026 	SFBFG(sfb, fg);
   1027 	SFBBG(sfb, bg);
   1028 	if (1 /* width <= SFBSTIPPLEBITS */) {
   1029 		lmask = lmask & rmask;
   1030 		while (height > 0) {
   1031 			glyph = *(u_int16_t *)g;		/* XXX */
   1032 			SFBPIXELMASK(sfb, lmask);
   1033 			SFBADDRESS(sfb, (long)p);
   1034 			SFBSTART(sfb, glyph << align);
   1035 			p += scanspan;
   1036 			g += 2;					/* XXX */
   1037 			height--;
   1038 		}
   1039 	}
   1040 #if supportlargerfonts
   1041 	else {
   1042 		caddr_t q = p;
   1043 		while (height > 0) {
   1044 			glyph = *(u_int16_t *)g;		/* XXX */
   1045 			SFBPIXELMASK(sfb, lmask);
   1046 WRITE_MB();
   1047 			*(u_int32_t *)p = glyph << align;
   1048 WRITE_MB();
   1049 			p += SFBSTIPPLEBYTESDONE;
   1050 			SFBPIXELMASK(sfb, rmask);
   1051 WRITE_MB();
   1052 			*(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
   1053 WRITE_MB();
   1054 
   1055 			p = (q += scanspan);
   1056 			g += 2;					/* XXX */
   1057 			height--;
   1058 		}
   1059 	}
   1060 #endif
   1061 	SFBMODE(sfb, MODE_SIMPLE);
   1062 	SFBPIXELMASK(sfb, ~0);		/* entire pixel */
   1063 }
   1064 
   1065 #if 0
   1066 /*
   1067  * Copy characters in a line.
   1068  */
   1069 static void
   1070 sfb_copycols(id, row, srccol, dstcol, ncols)
   1071 	void *id;
   1072 	int row, srccol, dstcol, ncols;
   1073 {
   1074 	struct rasops_info *ri = id;
   1075 	caddr_t sp, dp, basex, sfb;
   1076 	int scanspan, height, width, aligns, alignd, shift, w, y;
   1077 	u_int32_t lmasks, rmasks, lmaskd, rmaskd;
   1078 
   1079 	scanspan = ri->ri_stride;
   1080 	y = row * ri->ri_font->fontheight;
   1081 	basex = (caddr_t)rap->pixels + y * scanspan;
   1082 	height = ri->ri_font->fontheight;
   1083 	w = ri->ri_font->fontwidth * ncols;
   1084 
   1085 	sp = basex + ri->ri_font->fontwidth * srccol;
   1086 	aligns = (long)sp & SFBALIGNMASK;
   1087 	dp = basex + ri->ri_font->fontwidth * dstcol;
   1088 	alignd = (long)dp & SFBALIGNMASK;
   1089 	sfb = ri->ri_hw;
   1090 
   1091 	SFBMODE(sfb, MODE_COPY);
   1092 	SFBPLANEMASK(sfb, ~0);
   1093 
   1094 	/* copy forward (left-to-right) */
   1095 	if (dstcol < srccol || srccol + ncols < dstcol) {
   1096 		caddr_t sq, dq;
   1097 
   1098 		shift = alignd - aligns;
   1099 		if (shift < 0) {
   1100 			shift = 8 + shift;	/* enforce right rotate */
   1101 			alignd += 8;		/* bearing on left edge */
   1102 			w += 8;			/* enlarge to left */
   1103 		}
   1104 		width = aligns + w;
   1105 
   1106 		sp -= aligns;
   1107 		dp -= alignd;
   1108 		lmasks = SFBCOPYALL1 << aligns;
   1109 		rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1110 		lmaskd = SFBCOPYALL1 << alignd;
   1111 		rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
   1112 
   1113 		if (w + alignd <= SFBCOPYBITS)
   1114 			goto singlewrite;
   1115 
   1116 		SFBPIXELSHIFT(sfb, shift);
   1117 		w = width;
   1118 		sq = sp;
   1119 		dq = dp;
   1120 		while (height > 0) {
   1121 			*(u_int32_t *)sp = lmasks;
   1122 WRITE_MB();
   1123 			*(u_int32_t *)dp = lmaskd;
   1124 WRITE_MB();
   1125 			width -= 2 * SFBCOPYBITS;
   1126 			while (width > 0) {
   1127 				sp += SFBCOPYBYTESDONE;
   1128 				dp += SFBCOPYBYTESDONE;
   1129 				*(u_int32_t *)sp = SFBCOPYALL1;
   1130 WRITE_MB();
   1131 				*(u_int32_t *)dp = SFBCOPYALL1;
   1132 WRITE_MB();
   1133 				width -= SFBCOPYBITS;
   1134 			}
   1135 			sp += SFBCOPYBYTESDONE;
   1136 			dp += SFBCOPYBYTESDONE;
   1137 			*(u_int32_t *)sp = rmasks;
   1138 WRITE_MB();
   1139 			*(u_int32_t *)dp = rmaskd;
   1140 WRITE_MB();
   1141 
   1142 			sp = (sq += scanspan);
   1143 			dp = (dq += scanspan);
   1144 			width = w;
   1145 			height--;
   1146 		}
   1147 	}
   1148 	/* copy backward (right-to-left) */
   1149 	else {
   1150 		caddr_t sq, dq;
   1151 
   1152 		shift = alignd - aligns;
   1153 		if (shift > 0) {
   1154 			shift = shift - 8;	/* force left rotate */
   1155 			aligns += 8;		/* flush edge at left end */
   1156 		}
   1157 		width = aligns + w;
   1158 
   1159 		sp -= aligns;
   1160 		dp -= alignd;
   1161 		lmasks = SFBCOPYALL1 << aligns;
   1162 		rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1163 		lmaskd = SFBCOPYALL1 << alignd;
   1164 		rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
   1165 
   1166 		if (w + alignd <= SFBCOPYBITS)
   1167 			goto singlewrite;
   1168 
   1169 		SFBPIXELSHIFT(sfb, shift);
   1170 		w = width;
   1171 		sq = sp += ((width - 1) & ~31);
   1172 		dq = dp += (((w + alignd) - 1) & ~31);
   1173 		while (height > 0) {
   1174 			*(u_int32_t *)sp = rmasks;
   1175 WRITE_MB();
   1176 			*(u_int32_t *)dp = rmaskd;
   1177 WRITE_MB();
   1178 			width -= 2 * SFBCOPYBITS;
   1179 			while (width > 0) {
   1180 				sp -= SFBCOPYBYTESDONE;
   1181 				dp -= SFBCOPYBYTESDONE;
   1182 				*(u_int32_t *)sp = SFBCOPYALL1;
   1183 WRITE_MB();
   1184 				*(u_int32_t *)dp = SFBCOPYALL1;
   1185 WRITE_MB();
   1186 				width -= SFBCOPYBITS;
   1187 			}
   1188 			sp -= SFBCOPYBYTESDONE;
   1189 			dp -= SFBCOPYBYTESDONE;
   1190 			*(u_int32_t *)sp = lmasks;
   1191 WRITE_MB();
   1192 			*(u_int32_t *)dp = lmaskd;
   1193 WRITE_MB();
   1194 
   1195 			sp = (sq += scanspan);
   1196 			dp = (dq += scanspan);
   1197 			width = w;
   1198 			height--;
   1199 		}
   1200 	}
   1201 	SFBMODE(sfb, MODE_SIMPLE);
   1202 	SFBPIXELSHIFT(sfb, 0);
   1203 	return;
   1204 
   1205 singlewrite:
   1206 	SFBPIXELSHIFT(sfb, shift);
   1207 	lmasks = lmasks & rmasks;
   1208 	lmaskd = lmaskd & rmaskd;
   1209 	while (height > 0) {
   1210 		*(u_int32_t *)sp = lmasks;
   1211 WRITE_MB();
   1212 		*(u_int32_t *)dp = lmaskd;
   1213 WRITE_MB();
   1214 		sp += scanspan;
   1215 		dp += scanspan;
   1216 		height--;
   1217 	}
   1218 	SFBMODE(sfb, MODE_SIMPLE);
   1219 	SFBPIXELSHIFT(sfb, 0);
   1220 }
   1221 #endif
   1222 
   1223 /*
   1224  * Clear characters in a line.
   1225  */
   1226 static void
   1227 sfb_erasecols(id, row, startcol, ncols, attr)
   1228 	void *id;
   1229 	int row, startcol, ncols;
   1230 	long attr;
   1231 {
   1232 	struct rasops_info *ri = id;
   1233 	caddr_t sfb, p;
   1234 	int scanspan, startx, height, width, align, w, y;
   1235 	u_int32_t lmask, rmask;
   1236 	int fg, bg;
   1237 
   1238 	scanspan = ri->ri_stride;
   1239 	y = row * ri->ri_font->fontheight;
   1240 	startx = startcol * ri->ri_font->fontwidth;
   1241 	height = ri->ri_font->fontheight;
   1242 	w = ri->ri_font->fontwidth * ncols;
   1243 
   1244 	p = ri->ri_bits + y * scanspan + startx;
   1245 	align = (long)p & SFBALIGNMASK;
   1246 	p -= align;
   1247 	width = w + align;
   1248 	lmask = SFBSTIPPLEALL1 << align;
   1249 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1250 	sfb = ri->ri_hw;
   1251 
   1252 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1253 	SFBPLANEMASK(sfb, ~0);
   1254 	rasops_unpack_attr(attr, &fg, &bg, 0);
   1255 	bg |= bg << 8;
   1256 	bg |= bg << 16;
   1257 	SFBFG(sfb, bg);				/* fill with bg color */
   1258 	if (width <= SFBSTIPPLEBITS) {
   1259 		lmask = lmask & rmask;
   1260 		while (height > 0) {
   1261 			SFBADDRESS(sfb, (long)p);
   1262 			SFBSTART(sfb, lmask);
   1263 			p += scanspan;
   1264 			height--;
   1265 		}
   1266 	}
   1267 	else {
   1268 		caddr_t q = p;
   1269 		while (height > 0) {
   1270 			*(u_int32_t *)p = lmask;
   1271 WRITE_MB();
   1272 			width -= 2 * SFBSTIPPLEBITS;
   1273 			while (width > 0) {
   1274 				p += SFBSTIPPLEBYTESDONE;
   1275 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1276 WRITE_MB();
   1277 				width -= SFBSTIPPLEBITS;
   1278 			}
   1279 			p += SFBSTIPPLEBYTESDONE;
   1280 			*(u_int32_t *)p = rmask;
   1281 WRITE_MB();
   1282 
   1283 			p = (q += scanspan);
   1284 			width = w + align;
   1285 			height--;
   1286 		}
   1287 	}
   1288 	SFBMODE(sfb, MODE_SIMPLE);
   1289 }
   1290 
   1291 /*
   1292  * Copy lines.
   1293  */
   1294 static void
   1295 sfb_copyrows(id, srcrow, dstrow, nrows)
   1296 	void *id;
   1297 	int srcrow, dstrow, nrows;
   1298 {
   1299 	struct rasops_info *ri = id;
   1300 	caddr_t sfb, p;
   1301 	int scanspan, offset, srcy, height, width, align, w;
   1302 	u_int32_t lmask, rmask;
   1303 
   1304 	scanspan = ri->ri_stride;
   1305 	height = ri->ri_font->fontheight * nrows;
   1306 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1307 	srcy = ri->ri_font->fontheight * srcrow;
   1308 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1309 		scanspan = -scanspan;
   1310 		srcy += height;
   1311 	}
   1312 
   1313 	p = ri->ri_bits + srcy * ri->ri_stride;
   1314 	align = (long)p & SFBALIGNMASK;
   1315 	p -= align;
   1316 	w = ri->ri_emuwidth;
   1317 	width = w + align;
   1318 	lmask = SFBCOPYALL1 << align;
   1319 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1320 	sfb = ri->ri_hw;
   1321 
   1322 	SFBMODE(sfb, MODE_COPY);
   1323 	SFBPLANEMASK(sfb, ~0);
   1324 	SFBPIXELSHIFT(sfb, 0);
   1325 	if (width <= SFBCOPYBITS) {
   1326 		/* never happens */;
   1327 	}
   1328 	else {
   1329 		caddr_t q = p;
   1330 		while (height > 0) {
   1331 			*(u_int32_t *)p = lmask;
   1332 			*(u_int32_t *)(p + offset) = lmask;
   1333 			width -= 2 * SFBCOPYBITS;
   1334 			while (width > 0) {
   1335 				p += SFBCOPYBYTESDONE;
   1336 				*(u_int32_t *)p = SFBCOPYALL1;
   1337 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1338 				width -= SFBCOPYBITS;
   1339 			}
   1340 			p += SFBCOPYBYTESDONE;
   1341 			*(u_int32_t *)p = rmask;
   1342 			*(u_int32_t *)(p + offset) = rmask;
   1343 
   1344 			p = (q += scanspan);
   1345 			width = w + align;
   1346 			height--;
   1347 		}
   1348 	}
   1349 	SFBMODE(sfb, MODE_SIMPLE);
   1350 }
   1351 
   1352 /*
   1353  * Erase lines.
   1354  */
   1355 void
   1356 sfb_eraserows(id, startrow, nrows, attr)
   1357 	void *id;
   1358 	int startrow, nrows;
   1359 	long attr;
   1360 {
   1361 	struct rasops_info *ri = id;
   1362 	caddr_t sfb, p;
   1363 	int scanspan, starty, height, width, align, w;
   1364 	u_int32_t lmask, rmask;
   1365 	int fg, bg;
   1366 
   1367 	scanspan = ri->ri_stride;
   1368 	starty = ri->ri_font->fontheight * startrow;
   1369 	height = ri->ri_font->fontheight * nrows;
   1370 
   1371 	p = ri->ri_bits + starty * scanspan;
   1372 	align = (long)p & SFBALIGNMASK;
   1373 	p -= align;
   1374 	w = ri->ri_emuwidth;
   1375 	width = w + align;
   1376 	lmask = SFBSTIPPLEALL1 << align;
   1377 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1378 	sfb = ri->ri_hw;
   1379 
   1380 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1381 	SFBPLANEMASK(sfb, ~0);
   1382 	rasops_unpack_attr(attr, &fg, &bg, 0);
   1383 	bg |= bg << 8;
   1384 	bg |= bg << 16;
   1385 	SFBFG(sfb, bg);				/* fill with bg color */
   1386 	if (width <= SFBSTIPPLEBITS) {
   1387 		/* never happens */;
   1388 	}
   1389 	else {
   1390 		caddr_t q = p;
   1391 		while (height > 0) {
   1392 			*(u_int32_t *)p = lmask;
   1393 WRITE_MB();
   1394 			width -= 2 * SFBSTIPPLEBITS;
   1395 			while (width > 0) {
   1396 				p += SFBSTIPPLEBYTESDONE;
   1397 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1398 WRITE_MB();
   1399 				width -= SFBSTIPPLEBITS;
   1400 			}
   1401 			p += SFBSTIPPLEBYTESDONE;
   1402 			*(u_int32_t *)p = rmask;
   1403 WRITE_MB();
   1404 
   1405 			p = (q += scanspan);
   1406 			width = w + align;
   1407 			height--;
   1408 		}
   1409 	}
   1410 	SFBMODE(sfb, MODE_SIMPLE);
   1411 }
   1412