Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.28
      1 /* $NetBSD: sfb.c,v 1.28 1999/12/02 23:04:44 drochner Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1998, 1999 Tohru Nishimura.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Tohru Nishimura
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     34 
     35 __KERNEL_RCSID(0, "$NetBSD: sfb.c,v 1.28 1999/12/02 23:04:44 drochner Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/kernel.h>
     40 #include <sys/device.h>
     41 #include <sys/malloc.h>
     42 #include <sys/buf.h>
     43 #include <sys/ioctl.h>
     44 #include <vm/vm.h>
     45 
     46 #include <machine/bus.h>
     47 #include <machine/intr.h>
     48 
     49 #include <dev/wscons/wsconsio.h>
     50 #include <dev/wscons/wsdisplayvar.h>
     51 
     52 #include <dev/rasops/rasops.h>
     53 #include <dev/wsfont/wsfont.h>
     54 
     55 #include <dev/tc/tcvar.h>
     56 #include <dev/ic/bt459reg.h>
     57 #include <dev/tc/sfbreg.h>
     58 
     59 #include <uvm/uvm_extern.h>
     60 
     61 #if defined(pmax)
     62 #define	machine_btop(x) mips_btop(x)
     63 #define	MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
     64 #endif
     65 
     66 #if defined(__alpha__) || defined(alpha)
     67 #define machine_btop(x) alpha_btop(x)
     68 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
     69 #endif
     70 
     71 /*
     72  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
     73  * obscure register layout such as 2nd and 3rd Bt459 registers are
     74  * adjacent each other in a word, i.e.,
     75  *	struct bt459triplet {
     76  * 		struct {
     77  *			u_int8_t u0;
     78  *			u_int8_t u1;
     79  *			u_int8_t u2;
     80  *			unsigned :8;
     81  *		} bt_lo;
     82  *		struct {
     83  *
     84  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
     85  *	struct bt459reg {
     86  *		   u_int32_t	   bt_lo;
     87  *		   u_int32_t	   bt_hi;
     88  *		   u_int32_t	   bt_reg;
     89  *		   u_int32_t	   bt_cmap;
     90  *	};
     91  *
     92  */
     93 
     94 /* Bt459 hardware registers */
     95 #define bt_lo	0
     96 #define bt_hi	1
     97 #define bt_reg	2
     98 #define bt_cmap 3
     99 
    100 #define REG(base, index)	*((u_int32_t *)(base) + (index))
    101 #define SELECT(vdac, regno) do {			\
    102 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
    103 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
    104 	tc_wmb();					\
    105    } while (0)
    106 
    107 struct fb_devconfig {
    108 	vaddr_t dc_vaddr;		/* memory space virtual base address */
    109 	paddr_t dc_paddr;		/* memory space physical base address */
    110 	vsize_t dc_size;		/* size of slot memory */
    111 	int	dc_wid;			/* width of frame buffer */
    112 	int	dc_ht;			/* height of frame buffer */
    113 	int	dc_depth;		/* depth, bits per pixel */
    114 	int	dc_rowbytes;		/* bytes in a FB scan line */
    115 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
    116 	int	dc_blanked;		/* currently has video disabled */
    117 
    118 	struct rasops_info rinfo;
    119 };
    120 
    121 struct hwcmap256 {
    122 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
    123 	u_int8_t r[CMAP_SIZE];
    124 	u_int8_t g[CMAP_SIZE];
    125 	u_int8_t b[CMAP_SIZE];
    126 };
    127 
    128 struct hwcursor64 {
    129 	struct wsdisplay_curpos cc_pos;
    130 	struct wsdisplay_curpos cc_hot;
    131 	struct wsdisplay_curpos cc_size;
    132 	struct wsdisplay_curpos cc_magic;
    133 #define	CURSOR_MAX_SIZE	64
    134 	u_int8_t cc_color[6];
    135 	u_int64_t cc_image[64 + 64];
    136 };
    137 
    138 struct sfb_softc {
    139 	struct device sc_dev;
    140 	struct fb_devconfig *sc_dc;	/* device configuration */
    141 	struct hwcmap256 sc_cmap;	/* software copy of colormap */
    142 	struct hwcursor64 sc_cursor;	/* software copy of cursor */
    143 	int sc_curenb;			/* cursor sprite enabled */
    144 	int sc_changed;			/* need update of colormap */
    145 #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
    146 #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
    147 #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
    148 #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
    149 #define	DATA_ALL_CHANGED	0x0f
    150 	int nscreens;
    151 };
    152 
    153 #define	HX_MAGIC_X 368
    154 #define	HX_MAGIC_Y 38
    155 
    156 static int  sfbmatch __P((struct device *, struct cfdata *, void *));
    157 static void sfbattach __P((struct device *, struct device *, void *));
    158 
    159 const struct cfattach sfb_ca = {
    160 	sizeof(struct sfb_softc), sfbmatch, sfbattach,
    161 };
    162 
    163 static void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    164 static struct fb_devconfig sfb_console_dc;
    165 static tc_addr_t sfb_consaddr;
    166 
    167 #if 0
    168 static void sfb_cursor __P((void *, int, int, int));
    169 static void sfb_copycols __P((void *, int, int, int, int));
    170 static void sfb_erasecols __P((void *, int, int, int, long));
    171 static void sfb_eraserows __P((void *, int, int, long));
    172 #endif
    173 static void sfb_putchar __P((void *, int, int, u_int, long));
    174 static void sfb_copyrows __P((void *, int, int, int));
    175 
    176 static struct wsscreen_descr sfb_stdscreen = {
    177 	"std", 0, 0,
    178 	0, /* textops */
    179 	0, 0,
    180 	WSSCREEN_REVERSE
    181 };
    182 
    183 static const struct wsscreen_descr *_sfb_scrlist[] = {
    184 	&sfb_stdscreen,
    185 };
    186 
    187 static const struct wsscreen_list sfb_screenlist = {
    188 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    189 };
    190 
    191 static int  sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    192 static int  sfbmmap __P((void *, off_t, int));
    193 
    194 static int  sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    195 				      void **, int *, int *, long *));
    196 static void sfb_free_screen __P((void *, void *));
    197 static void sfb_show_screen __P((void *, 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_depth = dc->dc_depth;
    306 	dc->rinfo.ri_bits = (void *)dc->dc_videobase;
    307 	dc->rinfo.ri_width = dc->dc_wid;
    308 	dc->rinfo.ri_height = dc->dc_ht;
    309 	dc->rinfo.ri_stride = dc->dc_rowbytes;
    310 	dc->rinfo.ri_hw = sfbasic;
    311 
    312 	/*
    313 	 * the accelerated sfb_putchar() needs LSbit left,
    314 	 * so we can't use the rasops default font
    315 	 */
    316 	wsfont_init();
    317 	/* prefer 8 pixel wide font */
    318 	if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
    319 		cookie = wsfont_find(NULL, 0, 0, 0);
    320 	if (cookie <= 0) {
    321 		printf("sfb: font table is empty\n");
    322 		return;
    323 	}
    324 	if (wsfont_lock(cookie, &dc->rinfo.ri_font,
    325 			WSFONT_R2L, WSFONT_L2R) <= 0) {
    326 		printf("sfb: couldn't lock font\n");
    327 		return;
    328 	}
    329 	dc->rinfo.ri_wsfcookie = cookie;
    330 
    331 	rasops_init(&dc->rinfo, 1000, 1000); /* as large as possible */
    332 
    333 	/* add our accelerated functions */
    334 	dc->rinfo.ri_ops.copyrows = sfb_copyrows;
    335 	dc->rinfo.ri_ops.putchar = sfb_putchar;
    336 
    337 	/* XXX shouldn't be global */
    338 	sfb_stdscreen.nrows = dc->rinfo.ri_rows;
    339 	sfb_stdscreen.ncols = dc->rinfo.ri_cols;
    340 	sfb_stdscreen.textops = &dc->rinfo.ri_ops;
    341 	sfb_stdscreen.capabilities = dc->rinfo.ri_caps;
    342 }
    343 
    344 static void
    345 sfbattach(parent, self, aux)
    346 	struct device *parent, *self;
    347 	void *aux;
    348 {
    349 	struct sfb_softc *sc = (struct sfb_softc *)self;
    350 	struct tc_attach_args *ta = aux;
    351 	struct wsemuldisplaydev_attach_args waa;
    352 	caddr_t sfbasic;
    353 	int console;
    354 
    355 	console = (ta->ta_addr == sfb_consaddr);
    356 	if (console) {
    357 		sc->sc_dc = &sfb_console_dc;
    358 		sc->nscreens = 1;
    359 	}
    360 	else {
    361 		sc->sc_dc = (struct fb_devconfig *)
    362 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    363 		memset(sc->sc_dc, 0, sizeof(struct fb_devconfig));
    364 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    365 	}
    366 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    367 	    sc->sc_dc->dc_depth);
    368 
    369 	memcpy(&sc->sc_cmap, rasops_cmap, sizeof(struct hwcmap256));
    370 
    371 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    372 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    373 
    374         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
    375 
    376 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    377 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    378 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    379 
    380 	waa.console = console;
    381 	waa.scrdata = &sfb_screenlist;
    382 	waa.accessops = &sfb_accessops;
    383 	waa.accesscookie = sc;
    384 
    385 	config_found(self, &waa, wsemuldisplaydevprint);
    386 }
    387 
    388 static int
    389 sfbioctl(v, cmd, data, flag, p)
    390 	void *v;
    391 	u_long cmd;
    392 	caddr_t data;
    393 	int flag;
    394 	struct proc *p;
    395 {
    396 	struct sfb_softc *sc = v;
    397 	struct fb_devconfig *dc = sc->sc_dc;
    398 	int turnoff;
    399 
    400 	switch (cmd) {
    401 	case WSDISPLAYIO_GTYPE:
    402 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    403 		return (0);
    404 
    405 	case WSDISPLAYIO_GINFO:
    406 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    407 		wsd_fbip->height = sc->sc_dc->dc_ht;
    408 		wsd_fbip->width = sc->sc_dc->dc_wid;
    409 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    410 		wsd_fbip->cmsize = CMAP_SIZE;
    411 #undef fbt
    412 		return (0);
    413 
    414 	case WSDISPLAYIO_GETCMAP:
    415 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    416 
    417 	case WSDISPLAYIO_PUTCMAP:
    418 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    419 
    420 	case WSDISPLAYIO_SVIDEO:
    421 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    422 		if ((dc->dc_blanked == 0) ^ turnoff) {
    423 			dc->dc_blanked = turnoff;
    424 #if 0 /* XXX later XXX */
    425 		To turn off, assign value 0 in ASIC_VIDEO_VALID register.
    426 #endif	/* XXX XXX XXX */
    427 		}
    428 		return (0);
    429 
    430 	case WSDISPLAYIO_GVIDEO:
    431 		*(u_int *)data = dc->dc_blanked ?
    432 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    433 		return (0);
    434 
    435 	case WSDISPLAYIO_GCURPOS:
    436 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    437 		return (0);
    438 
    439 	case WSDISPLAYIO_SCURPOS:
    440 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    441 		bt459_set_curpos(sc);
    442 		return (0);
    443 
    444 	case WSDISPLAYIO_GCURMAX:
    445 		((struct wsdisplay_curpos *)data)->x =
    446 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    447 		return (0);
    448 
    449 	case WSDISPLAYIO_GCURSOR:
    450 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    451 
    452 	case WSDISPLAYIO_SCURSOR:
    453 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    454 	}
    455 	return ENOTTY;
    456 }
    457 
    458 static int
    459 sfbmmap(v, offset, prot)
    460 	void *v;
    461 	off_t offset;
    462 	int prot;
    463 {
    464 	struct sfb_softc *sc = v;
    465 
    466 	if (offset >= SFB_SIZE || offset < 0)
    467 		return (-1);
    468 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    469 }
    470 
    471 static int
    472 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    473 	void *v;
    474 	const struct wsscreen_descr *type;
    475 	void **cookiep;
    476 	int *curxp, *curyp;
    477 	long *attrp;
    478 {
    479 	struct sfb_softc *sc = v;
    480 	long defattr;
    481 
    482 	if (sc->nscreens > 0)
    483 		return (ENOMEM);
    484 
    485 	*cookiep = &sc->sc_dc->rinfo; /* one and only for now */
    486 	*curxp = 0;
    487 	*curyp = 0;
    488 	(*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
    489 	*attrp = defattr;
    490 	sc->nscreens++;
    491 	return (0);
    492 }
    493 
    494 static void
    495 sfb_free_screen(v, cookie)
    496 	void *v;
    497 	void *cookie;
    498 {
    499 	struct sfb_softc *sc = v;
    500 
    501 	if (sc->sc_dc == &sfb_console_dc)
    502 		panic("sfb_free_screen: console");
    503 
    504 	sc->nscreens--;
    505 }
    506 
    507 static void
    508 sfb_show_screen(v, cookie)
    509 	void *v;
    510 	void *cookie;
    511 {
    512 }
    513 
    514 /* EXPORT */ int
    515 sfb_cnattach(addr)
    516         tc_addr_t addr;
    517 {
    518         struct fb_devconfig *dcp = &sfb_console_dc;
    519         long defattr;
    520 
    521         sfb_getdevconfig(addr, dcp);
    522 
    523         (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
    524 
    525         wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
    526         sfb_consaddr = addr;
    527         return(0);
    528 }
    529 
    530 static int
    531 sfbintr(arg)
    532 	void *arg;
    533 {
    534 	struct sfb_softc *sc = arg;
    535 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    536 	caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
    537 	caddr_t vdac;
    538 	int v;
    539 
    540 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    541 	/* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
    542 
    543 	if (sc->sc_changed == 0)
    544 		return (1);
    545 
    546 	vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    547 	v = sc->sc_changed;
    548 	sc->sc_changed = 0;
    549 
    550 	if (v & DATA_ENB_CHANGED) {
    551 		SELECT(vdac, BT459_REG_CCR);
    552 		REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
    553 	}
    554 	if (v & DATA_CURCMAP_CHANGED) {
    555 		u_int8_t *cp = sc->sc_cursor.cc_color;
    556 
    557 		SELECT(vdac, BT459_REG_CCOLOR_2);
    558 		REG(vdac, bt_reg) = cp[1];	tc_wmb();
    559 		REG(vdac, bt_reg) = cp[3];	tc_wmb();
    560 		REG(vdac, bt_reg) = cp[5];	tc_wmb();
    561 
    562 		REG(vdac, bt_reg) = cp[0];	tc_wmb();
    563 		REG(vdac, bt_reg) = cp[2];	tc_wmb();
    564 		REG(vdac, bt_reg) = cp[4];	tc_wmb();
    565 	}
    566 	if (v & DATA_CURSHAPE_CHANGED) {
    567 		u_int8_t *ip, *mp, img, msk;
    568 		u_int8_t u;
    569 		int bcnt;
    570 
    571 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    572 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    573 
    574 		bcnt = 0;
    575 		SELECT(vdac, BT459_REG_CRAM_BASE+0);
    576 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    577 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    578 			/* pad right half 32 pixel when smaller than 33 */
    579 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    580 				REG(vdac, bt_reg) = 0; tc_wmb();
    581 				REG(vdac, bt_reg) = 0; tc_wmb();
    582 			}
    583 			else {
    584 				img = *ip++;
    585 				msk = *mp++;
    586 				img &= msk;	/* cookie off image */
    587 				u = (msk & 0x0f) << 4 | (img & 0x0f);
    588 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    589 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
    590 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    591 			}
    592 			bcnt += 2;
    593 		}
    594 		/* pad unoccupied scan lines */
    595 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    596 			REG(vdac, bt_reg) = 0; tc_wmb();
    597 			REG(vdac, bt_reg) = 0; tc_wmb();
    598 			bcnt += 2;
    599 		}
    600 	}
    601 	if (v & DATA_CMAP_CHANGED) {
    602 		struct hwcmap256 *cm = &sc->sc_cmap;
    603 		int index;
    604 
    605 		SELECT(vdac, 0);
    606 		for (index = 0; index < CMAP_SIZE; index++) {
    607 			REG(vdac, bt_cmap) = cm->r[index];	tc_wmb();
    608 			REG(vdac, bt_cmap) = cm->g[index];	tc_wmb();
    609 			REG(vdac, bt_cmap) = cm->b[index];	tc_wmb();
    610 		}
    611 	}
    612 	return (1);
    613 }
    614 
    615 static void
    616 sfbinit(dc)
    617 	struct fb_devconfig *dc;
    618 {
    619 	caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    620 	caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
    621 	int i;
    622 
    623 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    624 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    625 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
    626 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;  /* ROP_COPY */
    627 
    628 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    629 
    630 	SELECT(vdac, BT459_REG_COMMAND_0);
    631 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    632 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    633 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    634 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    635 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    636 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    637 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    638 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    639 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    640 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    641 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    642 
    643 	SELECT(vdac, BT459_REG_CCR);
    644 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    645 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    646 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    647 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    648 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    649 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    650 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    651 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    652 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    653 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    654 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    655 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    656 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    657 
    658 	/* build sane colormap */
    659 	SELECT(vdac, 0);
    660 	for (i = 0; i < CMAP_SIZE; i++) {
    661 		REG(vdac, bt_cmap) = rasops_cmap[3 * i + 0];
    662 		tc_wmb();
    663 		REG(vdac, bt_cmap) = rasops_cmap[3 * i + 1];
    664 		tc_wmb();
    665 		REG(vdac, bt_cmap) = rasops_cmap[3 * i + 2];
    666 		tc_wmb();
    667 	}
    668 
    669 	/* clear out cursor image */
    670 	SELECT(vdac, BT459_REG_CRAM_BASE);
    671 	for (i = 0; i < 1024; i++)
    672 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    673 
    674 	/*
    675 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    676 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    677 	 * image color.  CCOLOR_1 will be never used.
    678 	 */
    679 	SELECT(vdac, BT459_REG_CCOLOR_1);
    680 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    681 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    682 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    683 
    684 	REG(vdac, bt_reg) = 0;		tc_wmb();
    685 	REG(vdac, bt_reg) = 0;		tc_wmb();
    686 	REG(vdac, bt_reg) = 0;		tc_wmb();
    687 
    688 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    689 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    690 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    691 }
    692 
    693 static int
    694 get_cmap(sc, p)
    695 	struct sfb_softc *sc;
    696 	struct wsdisplay_cmap *p;
    697 {
    698 	u_int index = p->index, count = p->count;
    699 
    700 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    701 		return (EINVAL);
    702 
    703 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    704 	    !uvm_useracc(p->green, count, B_WRITE) ||
    705 	    !uvm_useracc(p->blue, count, B_WRITE))
    706 		return (EFAULT);
    707 
    708 	copyout(&sc->sc_cmap.r[index], p->red, count);
    709 	copyout(&sc->sc_cmap.g[index], p->green, count);
    710 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    711 
    712 	return (0);
    713 }
    714 
    715 static int
    716 set_cmap(sc, p)
    717 	struct sfb_softc *sc;
    718 	struct wsdisplay_cmap *p;
    719 {
    720 	u_int index = p->index, count = p->count;
    721 
    722 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    723 		return (EINVAL);
    724 
    725 	if (!uvm_useracc(p->red, count, B_READ) ||
    726 	    !uvm_useracc(p->green, count, B_READ) ||
    727 	    !uvm_useracc(p->blue, count, B_READ))
    728 		return (EFAULT);
    729 
    730 	copyin(p->red, &sc->sc_cmap.r[index], count);
    731 	copyin(p->green, &sc->sc_cmap.g[index], count);
    732 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    733 
    734 	sc->sc_changed |= DATA_CMAP_CHANGED;
    735 
    736 	return (0);
    737 }
    738 
    739 
    740 static int
    741 set_cursor(sc, p)
    742 	struct sfb_softc *sc;
    743 	struct wsdisplay_cursor *p;
    744 {
    745 #define	cc (&sc->sc_cursor)
    746 	int v, index, count, icount;
    747 
    748 	v = p->which;
    749 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    750 		index = p->cmap.index;
    751 		count = p->cmap.count;
    752 		if (index >= 2 || (index + count) > 2)
    753 			return (EINVAL);
    754 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    755 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    756 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    757 			return (EFAULT);
    758 	}
    759 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    760 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    761 			return (EINVAL);
    762 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    763 		if (!uvm_useracc(p->image, icount, B_READ) ||
    764 		    !uvm_useracc(p->mask, icount, B_READ))
    765 			return (EFAULT);
    766 	}
    767 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    768 		if (v & WSDISPLAY_CURSOR_DOCUR)
    769 			cc->cc_hot = p->hot;
    770 		if (v & WSDISPLAY_CURSOR_DOPOS)
    771 			set_curpos(sc, &p->pos);
    772 		bt459_set_curpos(sc);
    773 	}
    774 
    775 	sc->sc_changed = 0;
    776 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    777 		sc->sc_curenb = p->enable;
    778 		sc->sc_changed |= DATA_ENB_CHANGED;
    779 	}
    780 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    781 		copyin(p->cmap.red, &cc->cc_color[index], count);
    782 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    783 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    784 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    785 	}
    786 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    787 		cc->cc_size = p->size;
    788 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    789 		copyin(p->image, cc->cc_image, icount);
    790 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    791 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    792 	}
    793 
    794 	return (0);
    795 #undef cc
    796 }
    797 
    798 static int
    799 get_cursor(sc, p)
    800 	struct sfb_softc *sc;
    801 	struct wsdisplay_cursor *p;
    802 {
    803 	return (ENOTTY); /* XXX */
    804 }
    805 
    806 static void
    807 set_curpos(sc, curpos)
    808 	struct sfb_softc *sc;
    809 	struct wsdisplay_curpos *curpos;
    810 {
    811 	struct fb_devconfig *dc = sc->sc_dc;
    812 	int x = curpos->x, y = curpos->y;
    813 
    814 	if (y < 0)
    815 		y = 0;
    816 	else if (y > dc->dc_ht)
    817 		y = dc->dc_ht;
    818 	if (x < 0)
    819 		x = 0;
    820 	else if (x > dc->dc_wid)
    821 		x = dc->dc_wid;
    822 	sc->sc_cursor.cc_pos.x = x;
    823 	sc->sc_cursor.cc_pos.y = y;
    824 }
    825 
    826 static void
    827 bt459_set_curpos(sc)
    828 	struct sfb_softc *sc;
    829 {
    830 	caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
    831 	int x, y, s;
    832 
    833 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    834 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    835 
    836 	x += sc->sc_cursor.cc_magic.x;
    837 	y += sc->sc_cursor.cc_magic.y;
    838 
    839 	s = spltty();
    840 
    841 	SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    842 	REG(vdac, bt_reg) = x;		tc_wmb();
    843 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    844 	REG(vdac, bt_reg) = y;		tc_wmb();
    845 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    846 
    847 	splx(s);
    848 }
    849 
    850 #define	MODE_SIMPLE		0
    851 #define	MODE_OPAQUESTIPPLE	1
    852 #define	MODE_OPAQUELINE		2
    853 #define	MODE_TRANSPARENTSTIPPLE	5
    854 #define	MODE_TRANSPARENTLINE	6
    855 #define	MODE_COPY		7
    856 
    857 /* parameters for 8bpp configuration */
    858 #define	SFBALIGNMASK		0x7
    859 #define	SFBSTIPPLEALL1		0xffffffff
    860 #define	SFBSTIPPLEBITS		32
    861 #define	SFBSTIPPLEBITMASK	0x1f
    862 #define	SFBSTIPPLEBYTESDONE	32
    863 #define	SFBCOPYALL1		0xffffffff
    864 #define	SFBCOPYBITS		32
    865 #define	SFBCOPYBITMASK		0x1f
    866 #define	SFBCOPYBYTESDONE	32
    867 
    868 #ifdef pmax
    869 #define	WRITE_MB()
    870 #define	BUMP(p) (p)
    871 #endif
    872 
    873 #ifdef alpha
    874 #define	WRITE_MB() tc_wmb()
    875 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
    876 #endif
    877 
    878 #define	SFBMODE(p, v) \
    879 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
    880 #define	SFBROP(p, v) \
    881 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
    882 #define	SFBPLANEMASK(p, v) \
    883 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
    884 #define	SFBPIXELMASK(p, v) \
    885 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
    886 #define	SFBADDRESS(p, v) \
    887 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
    888 #define	SFBSTART(p, v) \
    889 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
    890 #define	SFBPIXELSHIFT(p, v) \
    891 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
    892 #define	SFBFG(p, v) \
    893 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
    894 #define	SFBBG(p, v) \
    895 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
    896 
    897 
    898 #if 0
    899 /*
    900  * Paint (or unpaint) the cursor.
    901  */
    902 static void
    903 sfb_cursor(id, on, row, col)
    904 	void *id;
    905 	int on, row, col;
    906 {
    907 	struct rcons *rc = id;
    908 	struct raster *rap = rc->rc_sp;
    909 	caddr_t sfb, p;
    910 	int scanspan, height, width, align, x, y;
    911 	u_int32_t lmask, rmask;
    912 
    913 	/* turn the cursor off */
    914 	if (!on) {
    915 		/* make sure it's on */
    916 		if ((rc->rc_bits & RC_CURSOR) == 0)
    917 			return;
    918 
    919 		row = *rc->rc_crowp;
    920 		col = *rc->rc_ccolp;
    921 	} else {
    922 		/* unpaint the old copy. */
    923 		*rc->rc_crowp = row;
    924 		*rc->rc_ccolp = col;
    925 	}
    926 
    927 	x = col * rc->rc_font->width + rc->rc_xorigin;
    928 	y = row * rc->rc_font->height + rc->rc_yorigin;
    929 	scanspan = rap->linelongs * 4;
    930 	height = rc->rc_font->height;
    931 
    932 	p = (caddr_t)rap->pixels + y * scanspan + x;
    933 	align = (long)p & SFBALIGNMASK;
    934 	p -= align;
    935 	width = rc->rc_font->width + align;
    936 	lmask = SFBSTIPPLEALL1 << align;
    937 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    938 	sfb = rap->data;
    939 
    940 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
    941 	SFBPLANEMASK(sfb, ~0);
    942 	SFBROP(sfb, 6);			/* ROP_XOR */
    943 	SFBFG(sfb, 0x01010101);		/* (fg ^ bg) to swap fg/bg */
    944 	if (width <= SFBSTIPPLEBITS) {
    945 		lmask = lmask & rmask;
    946 		while (height > 0) {
    947 			SFBADDRESS(sfb, (long)p);
    948 			SFBSTART(sfb, lmask);
    949 			p += scanspan;
    950 			height--;
    951 		}
    952 	}
    953 	else {
    954 		caddr_t q = p;
    955 		while (height > 0) {
    956 			*(u_int32_t *)p = lmask;
    957 WRITE_MB();
    958 			p += SFBSTIPPLEBYTESDONE;
    959 			*(u_int32_t *)p = rmask;
    960 WRITE_MB();
    961 
    962 			p = (q += scanspan);
    963 			height--;
    964 		}
    965 	}
    966 	SFBMODE(sfb, MODE_SIMPLE);
    967 	SFBROP(sfb, 3);			/* ROP_COPY */
    968 
    969 	rc->rc_bits ^= RC_CURSOR;
    970 }
    971 #endif
    972 
    973 /*
    974  * Actually write a string to the frame buffer.
    975  */
    976 static void
    977 sfb_putchar(id, row, col, uc, attr)
    978 	void *id;
    979 	int row, col;
    980 	u_int uc;
    981 	long attr;
    982 {
    983 	struct rasops_info *ri = id;
    984 	caddr_t sfb, p;
    985 	int scanspan, height, width, align, x, y;
    986 	u_int32_t lmask, rmask, glyph;
    987 	u_int8_t *g;
    988 
    989 if (uc < 0x20 || uc >= 127) return; /* XXX why \033 is creaping in !? XXX */
    990 
    991 	x = col * ri->ri_font->fontwidth;
    992 	y = row * ri->ri_font->fontheight;
    993 	scanspan = ri->ri_stride;
    994 	height = ri->ri_font->fontheight;
    995 	uc -= ri->ri_font->firstchar;
    996 	g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    997 
    998 	p = ri->ri_bits + y * scanspan + x;
    999 	align = (long)p & SFBALIGNMASK;
   1000 	p -= align;
   1001 	width = ri->ri_font->fontwidth + align;
   1002 	lmask = SFBSTIPPLEALL1 << align;
   1003 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1004 	sfb = ri->ri_hw;
   1005 
   1006 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1007 	SFBPLANEMASK(sfb, ~0);
   1008 	SFBFG(sfb, ((attr >> 24)  & 0xff) * 0x01010101);
   1009 	SFBBG(sfb, ((attr >> 16)  & 0xff) * 0x01010101);
   1010 	if (width <= SFBSTIPPLEBITS) {
   1011 		lmask = lmask & rmask;
   1012 		while (height > 0) {
   1013 			glyph = g[0];
   1014 			if (ri->ri_font->fontwidth > 8)
   1015 				glyph |= (g[1] << 8);
   1016 			SFBPIXELMASK(sfb, lmask);
   1017 			SFBADDRESS(sfb, (long)p);
   1018 			SFBSTART(sfb, glyph << align);
   1019 			p += scanspan;
   1020 			g += ri->ri_font->stride;
   1021 			height--;
   1022 		}
   1023 	}
   1024 	else {
   1025 		caddr_t q = p;
   1026 		while (height > 0) {
   1027 			glyph = *g;
   1028 			SFBPIXELMASK(sfb, lmask);
   1029 WRITE_MB();
   1030 			*(u_int32_t *)p = glyph << align;
   1031 WRITE_MB();
   1032 			p += SFBSTIPPLEBYTESDONE;
   1033 			SFBPIXELMASK(sfb, rmask);
   1034 WRITE_MB();
   1035 			*(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
   1036 WRITE_MB();
   1037 
   1038 			p = (q += scanspan);
   1039 			g += 1;
   1040 			height--;
   1041 		}
   1042 	}
   1043 	SFBMODE(sfb, MODE_SIMPLE);
   1044 	SFBPIXELMASK(sfb, ~0);		/* entire pixel */
   1045 }
   1046 
   1047 #if 0
   1048 /*
   1049  * Copy characters in a line.
   1050  */
   1051 static void
   1052 sfb_copycols(id, row, srccol, dstcol, ncols)
   1053 	void *id;
   1054 	int row, srccol, dstcol, ncols;
   1055 {
   1056 	struct rcons *rc = id;
   1057 	struct raster *rap = rc->rc_sp;
   1058 	caddr_t sp, dp, basex, sfb;
   1059 	int scanspan, height, width, aligns, alignd, shift, w, y;
   1060 	u_int32_t lmasks, rmasks, lmaskd, rmaskd;
   1061 
   1062 	scanspan = rap->linelongs * 4;
   1063 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1064 	basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
   1065 	height = rc->rc_font->height;
   1066 	w = rc->rc_font->width * ncols;
   1067 
   1068 	sp = basex + rc->rc_font->width * srccol;
   1069 	aligns = (long)sp & SFBALIGNMASK;
   1070 	dp = basex + rc->rc_font->width * dstcol;
   1071 	alignd = (long)dp & SFBALIGNMASK;
   1072 	sfb = rap->data;
   1073 
   1074 	SFBMODE(sfb, MODE_COPY);
   1075 	SFBPLANEMASK(sfb, ~0);
   1076 
   1077 	/* copy forward (left-to-right) */
   1078 	if (dstcol < srccol || srccol + ncols < dstcol) {
   1079 		caddr_t sq, dq;
   1080 
   1081 		shift = alignd - aligns;
   1082 		if (shift < 0) {
   1083 			dp -= 8;		/* prime left edge */
   1084 			alignd += 8;		/* compensate it */
   1085 			width = aligns + w + 8; /* adjust total width */
   1086 			shift = 8 + shift;	/* enforce right rotate */
   1087 		}
   1088 		else if (shift > 0)
   1089 			width = aligns + w + 8; /* enfore drain at right edge */
   1090 
   1091 		lmasks = SFBCOPYALL1 << aligns;
   1092 		rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1093 		lmaskd = SFBCOPYALL1 << alignd;
   1094 		rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
   1095 
   1096 		if (w + alignd <= SFBCOPYBITS)
   1097 			goto singlewrite;
   1098 
   1099 		SFBPIXELSHIFT(sfb, shift);
   1100 		w = width;
   1101 		sq = sp;
   1102 		dq = dp;
   1103 		while (height > 0) {
   1104 			*(u_int32_t *)sp = lmasks;
   1105 WRITE_MB();
   1106 			*(u_int32_t *)dp = lmaskd;
   1107 WRITE_MB();
   1108 			width -= 2 * SFBCOPYBITS;
   1109 			while (width > 0) {
   1110 				sp += SFBCOPYBYTESDONE;
   1111 				dp += SFBCOPYBYTESDONE;
   1112 				*(u_int32_t *)sp = SFBCOPYALL1;
   1113 WRITE_MB();
   1114 				*(u_int32_t *)dp = SFBCOPYALL1;
   1115 WRITE_MB();
   1116 				width -= SFBCOPYBITS;
   1117 			}
   1118 			sp += SFBCOPYBYTESDONE;
   1119 			dp += SFBCOPYBYTESDONE;
   1120 			*(u_int32_t *)sp = rmasks;
   1121 WRITE_MB();
   1122 			*(u_int32_t *)dp = rmaskd;
   1123 WRITE_MB();
   1124 
   1125 			sp = (sq += scanspan);
   1126 			dp = (dq += scanspan);
   1127 			width = w;
   1128 			height--;
   1129 		}
   1130 	}
   1131 	/* copy backward (right-to-left) */
   1132 	else {
   1133 		caddr_t sq, dq;
   1134 
   1135 		shift = alignd - aligns;
   1136 		if (shift > 0) {
   1137 			shift = shift - 8;
   1138 			w += 8;
   1139 		}
   1140 		width = w + aligns;
   1141 		lmasks = SFBCOPYALL1 << aligns;
   1142 		rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1143 		lmaskd = SFBCOPYALL1 << alignd;
   1144 		rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
   1145 
   1146 		if (w + alignd <= SFBCOPYBITS)
   1147 			goto singlewrite;
   1148 
   1149 		SFBPIXELSHIFT(sfb, shift);
   1150 		w = width;
   1151 		sq = (sp += width);
   1152 		dq = (dp += width);
   1153 		while (height > 0) {
   1154 			*(u_int32_t *)sp = rmasks;
   1155 WRITE_MB();
   1156 			*(u_int32_t *)dp = rmaskd;
   1157 WRITE_MB();
   1158 			width -= 2 * SFBCOPYBITS;
   1159 			while (width > 0) {
   1160 				sp -= SFBCOPYBYTESDONE;
   1161 				dp -= SFBCOPYBYTESDONE;
   1162 				*(u_int32_t *)sp = SFBCOPYALL1;
   1163 WRITE_MB();
   1164 				*(u_int32_t *)dp = SFBCOPYALL1;
   1165 WRITE_MB();
   1166 				width -= SFBCOPYBITS;
   1167 			}
   1168 			sp -= SFBCOPYBYTESDONE;
   1169 			dp -= SFBCOPYBYTESDONE;
   1170 			*(u_int32_t *)sp = lmasks;
   1171 WRITE_MB();
   1172 			*(u_int32_t *)dp = lmaskd;
   1173 WRITE_MB();
   1174 
   1175 			sp = (sq += scanspan);
   1176 			dp = (dq += scanspan);
   1177 			width = w;
   1178 			height--;
   1179 		}
   1180 	}
   1181 	SFBMODE(sfb, MODE_SIMPLE);
   1182 	SFBPIXELSHIFT(sfb, 0);
   1183 	return;
   1184 
   1185 singlewrite:
   1186 	SFBPIXELSHIFT(sfb, shift);
   1187 	lmasks = lmasks & rmasks;
   1188 	lmaskd = lmaskd & rmaskd;
   1189 	while (height > 0) {
   1190 		*(u_int32_t *)sp = lmasks;
   1191 WRITE_MB();
   1192 		*(u_int32_t *)dp = lmaskd;
   1193 WRITE_MB();
   1194 		sp += scanspan;
   1195 		dp += scanspan;
   1196 		height--;
   1197 	}
   1198 	SFBMODE(sfb, MODE_SIMPLE);
   1199 	SFBPIXELSHIFT(sfb, 0);
   1200 }
   1201 #endif
   1202 
   1203 #if 0
   1204 /*
   1205  * Clear characters in a line.
   1206  */
   1207 static void
   1208 sfb_erasecols(id, row, startcol, ncols, attr)
   1209 	void *id;
   1210 	int row, startcol, ncols;
   1211 	long attr;
   1212 {
   1213 	struct rcons *rc = id;
   1214 	struct raster *rap = rc->rc_sp;
   1215 	caddr_t sfb, p;
   1216 	int scanspan, startx, height, width, align, w, y;
   1217 	u_int32_t lmask, rmask;
   1218 
   1219 	scanspan = rap->linelongs * 4;
   1220 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1221 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
   1222 	height = rc->rc_font->height;
   1223 	w = rc->rc_font->width * ncols;
   1224 
   1225 	p = (caddr_t)rap->pixels + y * scanspan + startx;
   1226 	align = (long)p & SFBALIGNMASK;
   1227 	p -= align;
   1228 	width = w + align;
   1229 	lmask = SFBSTIPPLEALL1 << align;
   1230 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1231 	sfb = rap->data;
   1232 
   1233 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1234 	SFBPLANEMASK(sfb, ~0);
   1235 	SFBFG(sfb, 0);				/* fill with bg color */
   1236 	if (width <= SFBSTIPPLEBITS) {
   1237 		lmask = lmask & rmask;
   1238 		while (height > 0) {
   1239 			SFBADDRESS(sfb, (long)p);
   1240 			SFBSTART(sfb, lmask);
   1241 			p += scanspan;
   1242 			height--;
   1243 		}
   1244 	}
   1245 	else {
   1246 		caddr_t q = p;
   1247 		while (height > 0) {
   1248 			*(u_int32_t *)p = lmask;
   1249 WRITE_MB();
   1250 			width -= 2 * SFBSTIPPLEBITS;
   1251 			while (width > 0) {
   1252 				p += SFBSTIPPLEBYTESDONE;
   1253 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1254 WRITE_MB();
   1255 				width -= SFBSTIPPLEBITS;
   1256 			}
   1257 			p += SFBSTIPPLEBYTESDONE;
   1258 			*(u_int32_t *)p = rmask;
   1259 WRITE_MB();
   1260 
   1261 			p = (q += scanspan);
   1262 			width = w + align;
   1263 			height--;
   1264 		}
   1265 	}
   1266 	SFBMODE(sfb, MODE_SIMPLE);
   1267 }
   1268 #endif
   1269 
   1270 /*
   1271  * Copy lines.
   1272  */
   1273 static void
   1274 sfb_copyrows(id, srcrow, dstrow, nrows)
   1275 	void *id;
   1276 	int srcrow, dstrow, nrows;
   1277 {
   1278 	struct rasops_info *ri = id;
   1279 	caddr_t sfb, p;
   1280 	int scanspan, offset, srcy, height, width, align, w;
   1281 	u_int32_t lmask, rmask;
   1282 
   1283 	scanspan = ri->ri_stride;
   1284 	height = ri->ri_font->fontheight * nrows;
   1285 	offset = (dstrow - srcrow) * ri->ri_yscale;
   1286 	srcy = ri->ri_font->fontheight * srcrow;
   1287 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1288 		scanspan = -scanspan;
   1289 		srcy += height;
   1290 	}
   1291 
   1292 	p = (caddr_t)(ri->ri_bits + srcy * ri->ri_stride);
   1293 	align = (long)p & SFBALIGNMASK;
   1294 	p -= align;
   1295 	w = ri->ri_emuwidth;
   1296 	width = w + align;
   1297 	lmask = SFBCOPYALL1 << align;
   1298 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1299 	sfb = ri->ri_hw;
   1300 
   1301 	SFBMODE(sfb, MODE_COPY);
   1302 	SFBPLANEMASK(sfb, ~0);
   1303 	SFBPIXELSHIFT(sfb, 0);
   1304 	if (width <= SFBCOPYBITS) {
   1305 		/* never happens */;
   1306 	}
   1307 	else {
   1308 		caddr_t q = p;
   1309 		while (height > 0) {
   1310 			*(u_int32_t *)p = lmask;
   1311 			*(u_int32_t *)(p + offset) = lmask;
   1312 			width -= 2 * SFBCOPYBITS;
   1313 			while (width > 0) {
   1314 				p += SFBCOPYBYTESDONE;
   1315 				*(u_int32_t *)p = SFBCOPYALL1;
   1316 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1317 				width -= SFBCOPYBITS;
   1318 			}
   1319 			p += SFBCOPYBYTESDONE;
   1320 			*(u_int32_t *)p = rmask;
   1321 			*(u_int32_t *)(p + offset) = rmask;
   1322 
   1323 			p = (q += scanspan);
   1324 			width = w + align;
   1325 			height--;
   1326 		}
   1327 	}
   1328 	SFBMODE(sfb, MODE_SIMPLE);
   1329 }
   1330 
   1331 #if 0
   1332 /*
   1333  * Erase lines.
   1334  */
   1335 void
   1336 sfb_eraserows(id, startrow, nrows, attr)
   1337 	void *id;
   1338 	int startrow, nrows;
   1339 	long attr;
   1340 {
   1341 	struct rcons *rc = id;
   1342 	struct raster *rap = rc->rc_sp;
   1343 	caddr_t sfb, p;
   1344 	int scanspan, starty, height, width, align, w;
   1345 	u_int32_t lmask, rmask;
   1346 
   1347 	scanspan = rap->linelongs * 4;
   1348 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1349 	height = rc->rc_font->height * nrows;
   1350 
   1351 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1352 	align = (long)p & SFBALIGNMASK;
   1353 	p -= align;
   1354 	w = rc->rc_font->width * rc->rc_maxcol;
   1355 	width = w + align;
   1356 	lmask = SFBSTIPPLEALL1 << align;
   1357 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1358 	sfb = rap->data;
   1359 
   1360 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1361 	SFBPLANEMASK(sfb, ~0);
   1362 	SFBFG(sfb, 0);				/* fill with bg color */
   1363 	if (width <= SFBSTIPPLEBITS) {
   1364 		/* never happens */;
   1365 	}
   1366 	else {
   1367 		caddr_t q = p;
   1368 		while (height > 0) {
   1369 			*(u_int32_t *)p = lmask;
   1370 WRITE_MB();
   1371 			width -= 2 * SFBSTIPPLEBITS;
   1372 			while (width > 0) {
   1373 				p += SFBSTIPPLEBYTESDONE;
   1374 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1375 WRITE_MB();
   1376 				width -= SFBSTIPPLEBITS;
   1377 			}
   1378 			p += SFBSTIPPLEBYTESDONE;
   1379 			*(u_int32_t *)p = rmask;
   1380 WRITE_MB();
   1381 
   1382 			p = (q += scanspan);
   1383 			width = w + align;
   1384 			height--;
   1385 		}
   1386 	}
   1387 	SFBMODE(sfb, MODE_SIMPLE);
   1388 }
   1389 #endif
   1390