Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.39
      1 /* $NetBSD: sfb.c,v 1.39 2000/11/25 11:43:42 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.39 2000/11/25 11:43:42 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 static int
    755 set_cursor(sc, p)
    756 	struct sfb_softc *sc;
    757 	struct wsdisplay_cursor *p;
    758 {
    759 #define	cc (&sc->sc_cursor)
    760 	int v, index, count, icount;
    761 
    762 	v = p->which;
    763 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    764 		index = p->cmap.index;
    765 		count = p->cmap.count;
    766 		if (index >= 2 || (index + count) > 2)
    767 			return (EINVAL);
    768 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    769 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    770 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    771 			return (EFAULT);
    772 	}
    773 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    774 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    775 			return (EINVAL);
    776 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    777 		if (!uvm_useracc(p->image, icount, B_READ) ||
    778 		    !uvm_useracc(p->mask, icount, B_READ))
    779 			return (EFAULT);
    780 	}
    781 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    782 		if (v & WSDISPLAY_CURSOR_DOCUR)
    783 			cc->cc_hot = p->hot;
    784 		if (v & WSDISPLAY_CURSOR_DOPOS)
    785 			set_curpos(sc, &p->pos);
    786 		bt459_set_curpos(sc);
    787 	}
    788 
    789 	sc->sc_changed = 0;
    790 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    791 		sc->sc_curenb = p->enable;
    792 		sc->sc_changed |= DATA_ENB_CHANGED;
    793 	}
    794 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    795 		copyin(p->cmap.red, &cc->cc_color[index], count);
    796 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    797 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    798 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    799 	}
    800 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    801 		cc->cc_size = p->size;
    802 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    803 		copyin(p->image, cc->cc_image, icount);
    804 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    805 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    806 	}
    807 
    808 	return (0);
    809 #undef cc
    810 }
    811 
    812 static int
    813 get_cursor(sc, p)
    814 	struct sfb_softc *sc;
    815 	struct wsdisplay_cursor *p;
    816 {
    817 
    818 	return (ENOTTY); /* XXX */
    819 }
    820 
    821 static void
    822 set_curpos(sc, curpos)
    823 	struct sfb_softc *sc;
    824 	struct wsdisplay_curpos *curpos;
    825 {
    826 	struct fb_devconfig *dc = sc->sc_dc;
    827 	int x = curpos->x, y = curpos->y;
    828 
    829 	if (y < 0)
    830 		y = 0;
    831 	else if (y > dc->dc_ht)
    832 		y = dc->dc_ht;
    833 	if (x < 0)
    834 		x = 0;
    835 	else if (x > dc->dc_wid)
    836 		x = dc->dc_wid;
    837 	sc->sc_cursor.cc_pos.x = x;
    838 	sc->sc_cursor.cc_pos.y = y;
    839 }
    840 
    841 static void
    842 bt459_set_curpos(sc)
    843 	struct sfb_softc *sc;
    844 {
    845 	caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
    846 	int x, y, s;
    847 
    848 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    849 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    850 
    851 	x += sc->sc_cursor.cc_magic.x;
    852 	y += sc->sc_cursor.cc_magic.y;
    853 
    854 	s = spltty();
    855 
    856 	SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
    857 	REG(vdac, bt_reg) = x;		tc_wmb();
    858 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    859 	REG(vdac, bt_reg) = y;		tc_wmb();
    860 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    861 
    862 	splx(s);
    863 }
    864 
    865 #define	MODE_SIMPLE		0
    866 #define	MODE_OPAQUESTIPPLE	1
    867 #define	MODE_OPAQUELINE		2
    868 #define	MODE_TRANSPARENTSTIPPLE	5
    869 #define	MODE_TRANSPARENTLINE	6
    870 #define	MODE_COPY		7
    871 
    872 /* parameters for 8bpp configuration */
    873 #define	SFBALIGNMASK		0x7
    874 #define	SFBSTIPPLEALL1		0xffffffff
    875 #define	SFBSTIPPLEBITS		32
    876 #define	SFBSTIPPLEBITMASK	0x1f
    877 #define	SFBSTIPPLEBYTESDONE	32
    878 #define	SFBCOPYALL1		0xffffffff
    879 #define	SFBCOPYBITS		32
    880 #define	SFBCOPYBITMASK		0x1f
    881 #define	SFBCOPYBYTESDONE	32
    882 
    883 #if defined(pmax)
    884 #define	WRITE_MB()
    885 #define	BUMP(p) (p)
    886 #endif
    887 
    888 #if defined(alpha)
    889 #define	WRITE_MB() tc_wmb()
    890 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
    891 #endif
    892 
    893 #define	SFBMODE(p, v) \
    894 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
    895 #define	SFBROP(p, v) \
    896 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
    897 #define	SFBPLANEMASK(p, v) \
    898 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
    899 #define	SFBPIXELMASK(p, v) \
    900 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
    901 #define	SFBADDRESS(p, v) \
    902 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
    903 #define	SFBSTART(p, v) \
    904 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
    905 #define	SFBPIXELSHIFT(p, v) \
    906 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
    907 #define	SFBFG(p, v) \
    908 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
    909 #define	SFBBG(p, v) \
    910 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
    911 
    912 #if 0
    913 /*
    914  * Paint (or unpaint) the cursor.
    915  */
    916 static void
    917 sfb_cursor(id, on, row, col)
    918 	void *id;
    919 	int on, row, col;
    920 {
    921 	caddr_t sfb, p;
    922 	int scanspan, height, width, align, x, y;
    923 	u_int32_t lmask, rmask;
    924 	int fg, bg;
    925 
    926 	x = ri->ri_ccol * ri->ri_font->fontwidth;
    927 	y = ri->ri_crow * ri->ri_font->fontheight;
    928 	scanspan = ri->ri_stride;
    929 	height = ri->ri_font->fontheight;
    930 
    931 	p = ri->ri_bits + y * scanspan + x;
    932 	align = (long)p & SFBALIGNMASK;
    933 	p -= align;
    934 	width = ri->ri_font->fontwidth + align;
    935 	lmask = SFBSTIPPLEALL1 << align;
    936 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    937 	sfb = ri->ri_hw;
    938 
    939 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
    940 	SFBPLANEMASK(sfb, ~0);
    941 	SFBROP(sfb, 6);			/* ROP_XOR */
    942 	rasops_unpack_attr(attr, &fg, &bg, 0);
    943 	fg ^= bg;			/* (fg ^ bg) to swap fg/bg */
    944 	fg |= fg << 8;
    945 	fg |= fg << 16;
    946 	SFBFG(sfb, fg);
    947 	if (width <= SFBSTIPPLEBITS) {
    948 		lmask = lmask & rmask;
    949 		while (height > 0) {
    950 			SFBADDRESS(sfb, (long)p);
    951 			SFBSTART(sfb, lmask);
    952 			p += scanspan;
    953 			height--;
    954 		}
    955 	}
    956 #if supportlargerfonts
    957 	else {
    958 		caddr_t q = p;
    959 		while (height > 0) {
    960 			*(u_int32_t *)p = lmask;
    961 			WRITE_MB();
    962 			width -= 2 * SFBSTIPPLEBITS;
    963 			while (width > 0) {
    964 				p += SFBSTIPPLEBYTESDONE;
    965 				*(u_int32_t *)p = SFBSTIPPLEALL1;
    966 				WRITE_MB();
    967 				width -= SFBSTIPPLEBITS;
    968 			}
    969 			p += SFBSTIPPLEBYTESDONE;
    970 			*(u_int32_t *)p = rmask;
    971 			WRITE_MB();
    972 			p = (q += scanspan);
    973 			width = w + align;
    974 			height--;
    975 		}
    976 	}
    977 #endif
    978 	SFBMODE(sfb, MODE_SIMPLE);
    979 	SFBROP(sfb, 3);			/* ROP_COPY */
    980 }
    981 #endif
    982 
    983 /*
    984  * Actually write a string to the frame buffer.
    985  */
    986 static void
    987 sfb_putchar(id, row, col, uc, attr)
    988 	void *id;
    989 	int row, col;
    990 	u_int uc;
    991 	long attr;
    992 {
    993 	struct rasops_info *ri = id;
    994 	caddr_t sfb, p;
    995 	int scanspan, height, width, align, x, y;
    996 	u_int32_t lmask, rmask, glyph;
    997 	u_int8_t *g;
    998 	int fg, bg;
    999 
   1000 	x = col * ri->ri_font->fontwidth;
   1001 	y = row * ri->ri_font->fontheight;
   1002 	scanspan = ri->ri_stride;
   1003 	height = ri->ri_font->fontheight;
   1004 	uc -= ri->ri_font->firstchar;
   1005 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
   1006 
   1007 	p = ri->ri_bits + y * scanspan + x;
   1008 	align = (long)p & SFBALIGNMASK;
   1009 	p -= align;
   1010 	width = ri->ri_font->fontwidth + align;
   1011 	lmask = SFBSTIPPLEALL1 << align;
   1012 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1013 	sfb = ri->ri_hw;
   1014 
   1015 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1016 	SFBPLANEMASK(sfb, ~0);
   1017 	rasops_unpack_attr(attr, &fg, &bg, 0);
   1018 	fg |= fg << 8;
   1019 	fg |= fg << 16;
   1020 	bg |= bg << 8;
   1021 	bg |= bg << 16;
   1022 	SFBFG(sfb, fg);
   1023 	SFBBG(sfb, bg);
   1024 	if (1 /* width <= SFBSTIPPLEBITS */) {
   1025 		lmask = lmask & rmask;
   1026 		while (height > 0) {
   1027 			glyph = *(u_int16_t *)g;		/* XXX */
   1028 			SFBPIXELMASK(sfb, lmask);
   1029 			SFBADDRESS(sfb, (long)p);
   1030 			SFBSTART(sfb, glyph << align);
   1031 			p += scanspan;
   1032 			g += 2;					/* XXX */
   1033 			height--;
   1034 		}
   1035 	}
   1036 #if supportlargerfonts
   1037 	else {
   1038 		/*
   1039 		 * It's hard to draw oversized glyphs whose width is
   1040 		 * larger than 24 pixel.
   1041 		 */
   1042 		caddr_t q = p;
   1043 		while (height > 0) {
   1044 			/* XXX */
   1045 			/* XXX */
   1046 			/* XXX */
   1047 			p = (q += scanspan);
   1048 			g += 2;					/* XXX */
   1049 			height--;
   1050 		}
   1051 	}
   1052 #endif
   1053 	SFBMODE(sfb, MODE_SIMPLE);
   1054 	SFBPIXELMASK(sfb, ~0);		/* entire pixel */
   1055 }
   1056 
   1057 #if 0
   1058 /*
   1059  * Copy characters in a line.
   1060  */
   1061 static void
   1062 sfb_copycols(id, row, srccol, dstcol, ncols)
   1063 	void *id;
   1064 	int row, srccol, dstcol, ncols;
   1065 {
   1066 	struct rasops_info *ri = id;
   1067 	caddr_t sp, dp, basex, sfb;
   1068 	int scanspan, height, width, aligns, alignd, shift, w, y;
   1069 	u_int32_t lmaskd, rmaskd;
   1070 
   1071 	scanspan = ri->ri_stride;
   1072 	y = row * ri->ri_font->fontheight;
   1073 	basex = ri->ri_bits + y * scanspan;
   1074 	height = ri->ri_font->fontheight;
   1075 	w = ri->ri_font->fontwidth * ncols;
   1076 
   1077 	sp = basex + ri->ri_font->fontwidth * srccol;
   1078 	aligns = (long)sp & SFBALIGNMASK;
   1079 	dp = basex + ri->ri_font->fontwidth * dstcol;
   1080 	alignd = (long)dp & SFBALIGNMASK;
   1081 	sfb = ri->ri_hw;
   1082 
   1083 	SFBMODE(sfb, MODE_COPY);
   1084 	SFBPLANEMASK(sfb, ~0);
   1085 	/* small enough to fit in a single 32bit */
   1086 	if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
   1087 		SFBPIXELSHIFT(sfb, alignd - aligns);
   1088 		lmaskd = SFBCOPYALL1 << alignd;
   1089 		rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
   1090 		lmaskd = lmaskd & rmaskd;
   1091 		sp -= aligns;
   1092 		dp -= alignd;
   1093 		while (height > 0) {
   1094 			*(u_int32_t *)sp = SFBCOPYALL1;	WRITE_MB();
   1095 			*(u_int32_t *)dp = lmaskd;	WRITE_MB();
   1096 			sp += scanspan;
   1097 			dp += scanspan;
   1098 			height--;
   1099 		}
   1100 	}
   1101 	/* copy forward (left-to-right) */
   1102 	else if (dstcol < srccol || srccol + ncols < dstcol) {
   1103 		caddr_t sq, dq;
   1104 
   1105 		shift = alignd - aligns;
   1106 		if (shift < 0) {
   1107 			shift = 8 + shift;	/* enforce right rotate */
   1108 			alignd += 8;		/* bearing on left edge */
   1109 		}
   1110 		width = alignd + w;
   1111 		lmaskd = SFBCOPYALL1 << alignd;
   1112 		rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1113 		sp -= aligns;
   1114 		dp -= alignd;
   1115 
   1116 		SFBPIXELSHIFT(sfb, shift);
   1117 		w = width;
   1118 		sq = sp;
   1119 		dq = dp;
   1120 		while (height > 0) {
   1121 			*(u_int32_t *)sp = SFBCOPYALL1;	WRITE_MB();
   1122 			*(u_int32_t *)dp = lmaskd;	WRITE_MB();
   1123 			width -= 2 * SFBCOPYBITS;
   1124 			while (width > 0) {
   1125 				sp += SFBCOPYBYTESDONE;
   1126 				dp += SFBCOPYBYTESDONE;
   1127 				*(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
   1128 				*(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
   1129 				width -= SFBCOPYBITS;
   1130 			}
   1131 			sp += SFBCOPYBYTESDONE;
   1132 			dp += SFBCOPYBYTESDONE;
   1133 			*(u_int32_t *)sp = SFBCOPYALL1;	WRITE_MB();
   1134 			*(u_int32_t *)dp = rmaskd;	WRITE_MB();
   1135 			sp = (sq += scanspan);
   1136 			dp = (dq += scanspan);
   1137 			width = w;
   1138 			height--;
   1139 		}
   1140 	}
   1141 	/* copy backward (right-to-left) */
   1142 	else {
   1143 		caddr_t sq, dq;
   1144 
   1145 		shift = alignd - aligns;
   1146 		if (shift > 0) {
   1147 			shift = shift - 8;	/* force left rotate */
   1148 			alignd += 24;
   1149 		}
   1150 		width = alignd + w;
   1151 		lmaskd = SFBCOPYALL1 << alignd;
   1152 		rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1153 		sp -= aligns;
   1154 		dp -= alignd;
   1155 
   1156 		SFBPIXELSHIFT(sfb, shift);
   1157 		w = width;
   1158 		sq = sp += (((aligns + w) - 1) & ~31);
   1159 		dq = dp += (((alignd + w) - 1) & ~31);
   1160 		while (height > 0) {
   1161 			*(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
   1162 			*(u_int32_t *)dp = rmaskd;	WRITE_MB();
   1163 			width -= 2 * SFBCOPYBITS;
   1164 			while (width > 0) {
   1165 				sp -= SFBCOPYBYTESDONE;
   1166 				dp -= SFBCOPYBYTESDONE;
   1167 				*(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
   1168 				*(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
   1169 				width -= SFBCOPYBITS;
   1170 			}
   1171 			sp -= SFBCOPYBYTESDONE;
   1172 			dp -= SFBCOPYBYTESDONE;
   1173 			*(u_int32_t *)sp = SFBCOPYALL1;	WRITE_MB();
   1174 			*(u_int32_t *)dp = lmaskd;	WRITE_MB();
   1175 
   1176 			sp = (sq += scanspan);
   1177 			dp = (dq += scanspan);
   1178 			width = w;
   1179 			height--;
   1180 		}
   1181 	}
   1182 	SFBMODE(sfb, MODE_SIMPLE);
   1183 	SFBPIXELSHIFT(sfb, 0);
   1184 }
   1185 #endif
   1186 
   1187 /*
   1188  * Clear characters in a line.
   1189  */
   1190 static void
   1191 sfb_erasecols(id, row, startcol, ncols, attr)
   1192 	void *id;
   1193 	int row, startcol, ncols;
   1194 	long attr;
   1195 {
   1196 	struct rasops_info *ri = id;
   1197 	caddr_t sfb, p;
   1198 	int scanspan, startx, height, width, align, w, y;
   1199 	u_int32_t lmask, rmask;
   1200 	int fg, bg;
   1201 
   1202 	scanspan = ri->ri_stride;
   1203 	y = row * ri->ri_font->fontheight;
   1204 	startx = startcol * ri->ri_font->fontwidth;
   1205 	height = ri->ri_font->fontheight;
   1206 	w = ri->ri_font->fontwidth * ncols;
   1207 
   1208 	p = ri->ri_bits + y * scanspan + startx;
   1209 	align = (long)p & SFBALIGNMASK;
   1210 	p -= align;
   1211 	width = w + align;
   1212 	lmask = SFBSTIPPLEALL1 << align;
   1213 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1214 	sfb = ri->ri_hw;
   1215 
   1216 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1217 	SFBPLANEMASK(sfb, ~0);
   1218 	rasops_unpack_attr(attr, &fg, &bg, 0);
   1219 	bg |= bg << 8;
   1220 	bg |= bg << 16;
   1221 	SFBFG(sfb, bg);				/* fill with bg color */
   1222 	if (width <= SFBSTIPPLEBITS) {
   1223 		lmask = lmask & rmask;
   1224 		while (height > 0) {
   1225 			SFBADDRESS(sfb, (long)p);
   1226 			SFBSTART(sfb, lmask);
   1227 			p += scanspan;
   1228 			height--;
   1229 		}
   1230 	}
   1231 	else {
   1232 		caddr_t q = p;
   1233 		while (height > 0) {
   1234 			*(u_int32_t *)p = lmask;
   1235 			WRITE_MB();
   1236 			width -= 2 * SFBSTIPPLEBITS;
   1237 			while (width > 0) {
   1238 				p += SFBSTIPPLEBYTESDONE;
   1239 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1240 				WRITE_MB();
   1241 				width -= SFBSTIPPLEBITS;
   1242 			}
   1243 			p += SFBSTIPPLEBYTESDONE;
   1244 			*(u_int32_t *)p = rmask;
   1245 			WRITE_MB();
   1246 
   1247 			p = (q += scanspan);
   1248 			width = w + align;
   1249 			height--;
   1250 		}
   1251 	}
   1252 	SFBMODE(sfb, MODE_SIMPLE);
   1253 }
   1254 
   1255 /*
   1256  * Copy lines.
   1257  */
   1258 static void
   1259 sfb_copyrows(id, srcrow, dstrow, nrows)
   1260 	void *id;
   1261 	int srcrow, dstrow, nrows;
   1262 {
   1263 	struct rasops_info *ri = id;
   1264 	caddr_t sfb, p;
   1265 	int scanspan, offset, srcy, height, width, align, w;
   1266 	u_int32_t lmask, rmask;
   1267 
   1268 	scanspan = ri->ri_stride;
   1269 	height = ri->ri_font->fontheight * nrows;
   1270 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1271 	srcy = ri->ri_font->fontheight * srcrow;
   1272 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1273 		scanspan = -scanspan;
   1274 		srcy += height;
   1275 	}
   1276 
   1277 	p = ri->ri_bits + srcy * ri->ri_stride;
   1278 	align = (long)p & SFBALIGNMASK;
   1279 	p -= align;
   1280 	w = ri->ri_emuwidth;
   1281 	width = w + align;
   1282 	lmask = SFBCOPYALL1 << align;
   1283 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1284 	sfb = ri->ri_hw;
   1285 
   1286 	SFBMODE(sfb, MODE_COPY);
   1287 	SFBPLANEMASK(sfb, ~0);
   1288 	SFBPIXELSHIFT(sfb, 0);
   1289 	if (width <= SFBCOPYBITS) {
   1290 		/* never happens */;
   1291 	}
   1292 	else {
   1293 		caddr_t q = p;
   1294 		while (height > 0) {
   1295 			*(u_int32_t *)p = lmask;
   1296 			*(u_int32_t *)(p + offset) = lmask;
   1297 			width -= 2 * SFBCOPYBITS;
   1298 			while (width > 0) {
   1299 				p += SFBCOPYBYTESDONE;
   1300 				*(u_int32_t *)p = SFBCOPYALL1;
   1301 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1302 				width -= SFBCOPYBITS;
   1303 			}
   1304 			p += SFBCOPYBYTESDONE;
   1305 			*(u_int32_t *)p = rmask;
   1306 			*(u_int32_t *)(p + offset) = rmask;
   1307 
   1308 			p = (q += scanspan);
   1309 			width = w + align;
   1310 			height--;
   1311 		}
   1312 	}
   1313 	SFBMODE(sfb, MODE_SIMPLE);
   1314 }
   1315 
   1316 /*
   1317  * Erase lines.
   1318  */
   1319 void
   1320 sfb_eraserows(id, startrow, nrows, attr)
   1321 	void *id;
   1322 	int startrow, nrows;
   1323 	long attr;
   1324 {
   1325 	struct rasops_info *ri = id;
   1326 	caddr_t sfb, p;
   1327 	int scanspan, starty, height, width, align, w;
   1328 	u_int32_t lmask, rmask;
   1329 	int fg, bg;
   1330 
   1331 	scanspan = ri->ri_stride;
   1332 	starty = ri->ri_font->fontheight * startrow;
   1333 	height = ri->ri_font->fontheight * nrows;
   1334 
   1335 	p = ri->ri_bits + starty * scanspan;
   1336 	align = (long)p & SFBALIGNMASK;
   1337 	p -= align;
   1338 	w = ri->ri_emuwidth;
   1339 	width = w + align;
   1340 	lmask = SFBSTIPPLEALL1 << align;
   1341 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1342 	sfb = ri->ri_hw;
   1343 
   1344 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1345 	SFBPLANEMASK(sfb, ~0);
   1346 	rasops_unpack_attr(attr, &fg, &bg, 0);
   1347 	bg |= bg << 8;
   1348 	bg |= bg << 16;
   1349 	SFBFG(sfb, bg);				/* fill with bg color */
   1350 	if (width <= SFBSTIPPLEBITS) {
   1351 		/* never happens */;
   1352 	}
   1353 	else {
   1354 		caddr_t q = p;
   1355 		while (height > 0) {
   1356 			*(u_int32_t *)p = lmask;
   1357 			WRITE_MB();
   1358 			width -= 2 * SFBSTIPPLEBITS;
   1359 			while (width > 0) {
   1360 				p += SFBSTIPPLEBYTESDONE;
   1361 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1362 				WRITE_MB();
   1363 				width -= SFBSTIPPLEBITS;
   1364 			}
   1365 			p += SFBSTIPPLEBYTESDONE;
   1366 			*(u_int32_t *)p = rmask;
   1367 			WRITE_MB();
   1368 
   1369 			p = (q += scanspan);
   1370 			width = w + align;
   1371 			height--;
   1372 		}
   1373 	}
   1374 	SFBMODE(sfb, MODE_SIMPLE);
   1375 }
   1376