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