Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.15
      1 /* $NetBSD: sfb.c,v 1.15 1999/05/07 08:00:31 nisimura Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1998 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.15 1999/05/07 08:00:31 nisimura Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/kernel.h>
     40 #include <sys/device.h>
     41 #include <sys/malloc.h>
     42 #include <sys/buf.h>
     43 #include <sys/ioctl.h>
     44 #include <vm/vm.h>
     45 
     46 #include <machine/bus.h>
     47 #include <machine/intr.h>
     48 
     49 #include <dev/rcons/raster.h>
     50 #include <dev/wscons/wsconsio.h>
     51 #include <dev/wscons/wscons_raster.h>
     52 #include <dev/wscons/wsdisplayvar.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 /* XXX BUS'IFYING XXX */
     61 
     62 #if defined(pmax)
     63 #define	machine_btop(x) mips_btop(x)
     64 #define	MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
     65 #endif
     66 
     67 #if defined(__alpha__) || defined(alpha)
     68 #define machine_btop(x) alpha_btop(x)
     69 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
     70 #endif
     71 
     72 /*
     73  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
     74  * obscure register layout such as 2nd and 3rd Bt459 registers are
     75  * adjacent each other in a word, i.e.,
     76  *	struct bt459triplet {
     77  * 		struct {
     78  *			u_int8_t u0;
     79  *			u_int8_t u1;
     80  *			u_int8_t u2;
     81  *			unsigned :8;
     82  *		} bt_lo;
     83  *		...
     84  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
     85  */
     86 struct bt459reg {
     87         u_int32_t       bt_lo;
     88         u_int32_t       bt_hi;
     89         u_int32_t       bt_reg;
     90         u_int32_t       bt_cmap;
     91 };
     92 
     93 /* XXX XXX XXX */
     94 
     95 struct fb_devconfig {
     96 	vaddr_t dc_vaddr;		/* memory space virtual base address */
     97 	paddr_t dc_paddr;		/* memory space physical base address */
     98 	vsize_t dc_size;		/* size of slot memory */
     99 	int	dc_wid;			/* width of frame buffer */
    100 	int	dc_ht;			/* height of frame buffer */
    101 	int	dc_depth;		/* depth, bits per pixel */
    102 	int	dc_rowbytes;		/* bytes in a FB scan line */
    103 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
    104 	struct raster	dc_raster;	/* raster description */
    105 	struct rcons	dc_rcons;	/* raster blitter control info */
    106 	int	    dc_blanked;		/* currently has video disabled */
    107 };
    108 
    109 struct hwcmap256 {
    110 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
    111 	u_int8_t r[CMAP_SIZE];
    112 	u_int8_t g[CMAP_SIZE];
    113 	u_int8_t b[CMAP_SIZE];
    114 };
    115 
    116 struct hwcursor64 {
    117 	struct wsdisplay_curpos cc_pos;
    118 	struct wsdisplay_curpos cc_hot;
    119 	struct wsdisplay_curpos cc_size;
    120 	struct wsdisplay_curpos cc_magic;
    121 #define	CURSOR_MAX_SIZE	64
    122 	u_int8_t cc_color[6];
    123 	u_int64_t cc_image[64 + 64];
    124 };
    125 
    126 struct sfb_softc {
    127 	struct device sc_dev;
    128 	struct fb_devconfig *sc_dc;	/* device configuration */
    129 	struct hwcmap256 sc_cmap;	/* software copy of colormap */
    130 	struct hwcursor64 sc_cursor;	/* software copy of cursor */
    131 	int sc_curenb;			/* cursor sprite enabled */
    132 	int sc_changed;			/* need update of colormap */
    133 #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
    134 #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
    135 #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
    136 #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
    137 #define	DATA_ALL_CHANGED	0x0f
    138 	int nscreens;
    139 };
    140 
    141 #define	HX_MAGIC_X 368
    142 #define	HX_MAGIC_Y 38
    143 
    144 int  sfbmatch __P((struct device *, struct cfdata *, void *));
    145 void sfbattach __P((struct device *, struct device *, void *));
    146 
    147 struct cfattach sfb_ca = {
    148 	sizeof(struct sfb_softc), sfbmatch, sfbattach,
    149 };
    150 
    151 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    152 struct fb_devconfig sfb_console_dc;
    153 tc_addr_t sfb_consaddr;
    154 
    155 void	sfb_cursor __P((void *, int, int, int));
    156 int	sfb_mapchar __P((void *, int, unsigned int *));
    157 void	sfb_putchar __P((void *, int, int, u_int, long));
    158 void	sfb_copycols __P((void *, int, int, int, int));
    159 void	sfb_erasecols __P((void *, int, int, int, long));
    160 void	sfb_copyrows __P((void *, int, int, int));
    161 void	sfb_eraserows __P((void *, int, int, long));
    162 int	sfb_alloc_attr __P((void *, int, int, int, long *));
    163 #define	rcons_alloc_attr sfb_alloc_attr
    164 
    165 struct wsdisplay_emulops sfb_emulops = {
    166 	sfb_cursor,			/* could use hardware cursor; punt */
    167 	sfb_mapchar,
    168 	sfb_putchar,
    169 	sfb_copycols,
    170 	sfb_erasecols,
    171 	sfb_copyrows,
    172 	sfb_eraserows,
    173 	sfb_alloc_attr
    174 };
    175 
    176 struct wsscreen_descr sfb_stdscreen = {
    177 	"std", 0, 0,
    178 	&sfb_emulops,
    179 	0, 0,
    180 	0
    181 };
    182 
    183 const struct wsscreen_descr *_sfb_scrlist[] = {
    184 	&sfb_stdscreen,
    185 };
    186 
    187 struct wsscreen_list sfb_screenlist = {
    188 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    189 };
    190 
    191 int	sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    192 int	sfbmmap __P((void *, off_t, int));
    193 
    194 int	sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    195 				      void **, int *, int *, long *));
    196 void	sfb_free_screen __P((void *, void *));
    197 void	sfb_show_screen __P((void *, void *));
    198 
    199 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 int  sfbintr __P((void *));
    210 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 /* XXX XXX XXX */
    220 #define	BT459_SELECT(vdac, regno) do {		\
    221 	vdac->bt_lo = (regno) & 0x00ff;		\
    222 	vdac->bt_hi = ((regno)& 0x0f00) >> 8;	\
    223 	tc_wmb();				\
    224    } while (0)
    225 /* XXX XXX XXX */
    226 
    227 /*
    228  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
    229  *   M M M M I I I I		M I M I M I M I
    230  *	[ before ]		   [ after ]
    231  *   3 2 1 0 3 2 1 0		0 0 1 1 2 2 3 3
    232  *   7 6 5 4 7 6 5 4		4 4 5 5 6 6 7 7
    233  */
    234 const static u_int8_t shuffle[256] = {
    235 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
    236 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
    237 	0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
    238 	0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
    239 	0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
    240 	0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
    241 	0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
    242 	0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
    243 	0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
    244 	0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
    245 	0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
    246 	0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
    247 	0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
    248 	0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
    249 	0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
    250 	0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
    251 	0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
    252 	0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
    253 	0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
    254 	0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
    255 	0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
    256 	0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
    257 	0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
    258 	0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
    259 	0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
    260 	0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
    261 	0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
    262 	0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
    263 	0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
    264 	0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
    265 	0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
    266 	0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
    267 };
    268 
    269 int
    270 sfbmatch(parent, match, aux)
    271 	struct device *parent;
    272 	struct cfdata *match;
    273 	void *aux;
    274 {
    275 	struct tc_attach_args *ta = aux;
    276 
    277 	if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
    278 		return (0);
    279 
    280 	return (1);
    281 }
    282 
    283 void
    284 sfb_getdevconfig(dense_addr, dc)
    285 	tc_addr_t dense_addr;
    286 	struct fb_devconfig *dc;
    287 {
    288 	struct raster *rap;
    289 	struct rcons *rcp;
    290 	caddr_t sfbasic;
    291 	int i, hsetup, vsetup, vbase;
    292 
    293 	dc->dc_vaddr = dense_addr;
    294 	dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
    295 
    296 	sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    297 	hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
    298 	vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
    299 	vbase  = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) & 0x1ff;
    300 
    301 	dc->dc_wid = (hsetup & 0x1ff) << 2;
    302 	dc->dc_ht = (vsetup & 0x7ff);
    303 	dc->dc_depth = 8;
    304 	dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
    305 	dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
    306 	dc->dc_blanked = 0;
    307 
    308 	/* initialize colormap and cursor resource */
    309 	sfbinit(dc);
    310 
    311 	/* clear the screen */
    312 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    313 		*(u_int32_t *)(dc->dc_videobase + i) = 0x0;
    314 
    315 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
    316 
    317 	/* initialize the raster */
    318 	rap = &dc->dc_raster;
    319 	rap->width = dc->dc_wid;
    320 	rap->height = dc->dc_ht;
    321 	rap->depth = dc->dc_depth;
    322 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    323 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    324 	rap->data = sfbasic;
    325 
    326 	/* initialize the raster console blitter */
    327 	rcp = &dc->dc_rcons;
    328 	rcp->rc_sp = rap;
    329 	rcp->rc_crow = rcp->rc_ccol = -1;
    330 	rcp->rc_crowp = &rcp->rc_crow;
    331 	rcp->rc_ccolp = &rcp->rc_ccol;
    332 	rcons_init(rcp, 34, 80);
    333 
    334 	sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    335 	sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    336 }
    337 
    338 void
    339 sfbattach(parent, self, aux)
    340 	struct device *parent, *self;
    341 	void *aux;
    342 {
    343 	struct sfb_softc *sc = (struct sfb_softc *)self;
    344 	struct tc_attach_args *ta = aux;
    345 	struct wsemuldisplaydev_attach_args waa;
    346 	struct hwcmap256 *cm;
    347 	caddr_t sfbasic;
    348 	int console;
    349 
    350 	console = (ta->ta_addr == sfb_consaddr);
    351 	if (console) {
    352 		sc->sc_dc = &sfb_console_dc;
    353 		sc->nscreens = 1;
    354 	}
    355 	else {
    356 		sc->sc_dc = (struct fb_devconfig *)
    357 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    358 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    359 	}
    360 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    361 	    sc->sc_dc->dc_depth);
    362 
    363 	cm = &sc->sc_cmap;
    364 	memset(cm, 255, sizeof(struct hwcmap256));	/* XXX */
    365 	cm->r[0] = cm->g[0] = cm->b[0] = 0;		/* XXX */
    366 
    367 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    368 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    369 
    370         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
    371 
    372 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    373 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    374 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    375 
    376 	waa.console = console;
    377 	waa.scrdata = &sfb_screenlist;
    378 	waa.accessops = &sfb_accessops;
    379 	waa.accesscookie = sc;
    380 
    381 	config_found(self, &waa, wsemuldisplaydevprint);
    382 }
    383 
    384 int
    385 sfbioctl(v, cmd, data, flag, p)
    386 	void *v;
    387 	u_long cmd;
    388 	caddr_t data;
    389 	int flag;
    390 	struct proc *p;
    391 {
    392 	struct sfb_softc *sc = v;
    393 	struct fb_devconfig *dc = sc->sc_dc;
    394 	int turnoff;
    395 
    396 	switch (cmd) {
    397 	case WSDISPLAYIO_GTYPE:
    398 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    399 		return (0);
    400 
    401 	case WSDISPLAYIO_GINFO:
    402 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    403 		wsd_fbip->height = sc->sc_dc->dc_ht;
    404 		wsd_fbip->width = sc->sc_dc->dc_wid;
    405 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    406 		wsd_fbip->cmsize = CMAP_SIZE;
    407 #undef fbt
    408 		return (0);
    409 
    410 	case WSDISPLAYIO_GETCMAP:
    411 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    412 
    413 	case WSDISPLAYIO_PUTCMAP:
    414 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    415 
    416 	case WSDISPLAYIO_SVIDEO:
    417 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    418 		if ((dc->dc_blanked == 0) ^ turnoff) {
    419 			dc->dc_blanked = turnoff;
    420 			/* XXX later XXX */
    421 		}
    422 		return (0);
    423 
    424 	case WSDISPLAYIO_GVIDEO:
    425 		*(u_int *)data = dc->dc_blanked ?
    426 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    427 		return (0);
    428 
    429 	case WSDISPLAYIO_GCURPOS:
    430 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    431 		return (0);
    432 
    433 	case WSDISPLAYIO_SCURPOS:
    434 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    435 		bt459_set_curpos(sc);
    436 		return (0);
    437 
    438 	case WSDISPLAYIO_GCURMAX:
    439 		((struct wsdisplay_curpos *)data)->x =
    440 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    441 		return (0);
    442 
    443 	case WSDISPLAYIO_GCURSOR:
    444 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    445 
    446 	case WSDISPLAYIO_SCURSOR:
    447 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    448 	}
    449 	return ENOTTY;
    450 }
    451 
    452 int
    453 sfbmmap(v, offset, prot)
    454 	void *v;
    455 	off_t offset;
    456 	int prot;
    457 {
    458 	struct sfb_softc *sc = v;
    459 
    460 	if (offset >= SFB_SIZE || offset < 0)
    461 		return (-1);
    462 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    463 }
    464 
    465 int
    466 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    467 	void *v;
    468 	const struct wsscreen_descr *type;
    469 	void **cookiep;
    470 	int *curxp, *curyp;
    471 	long *attrp;
    472 {
    473 	struct sfb_softc *sc = v;
    474 	long defattr;
    475 
    476 	if (sc->nscreens > 0)
    477 		return (ENOMEM);
    478 
    479 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    480 	*curxp = 0;
    481 	*curyp = 0;
    482 	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    483 	*attrp = defattr;
    484 	sc->nscreens++;
    485 	return (0);
    486 }
    487 
    488 void
    489 sfb_free_screen(v, cookie)
    490 	void *v;
    491 	void *cookie;
    492 {
    493 	struct sfb_softc *sc = v;
    494 
    495 	if (sc->sc_dc == &sfb_console_dc)
    496 		panic("sfb_free_screen: console");
    497 
    498 	sc->nscreens--;
    499 }
    500 
    501 void
    502 sfb_show_screen(v, cookie)
    503 	void *v;
    504 	void *cookie;
    505 {
    506 }
    507 
    508 int
    509 sfb_cnattach(addr)
    510         tc_addr_t addr;
    511 {
    512         struct fb_devconfig *dcp = &sfb_console_dc;
    513         long defattr;
    514 
    515         sfb_getdevconfig(addr, dcp);
    516 
    517         rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    518 
    519         wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
    520                            0, 0, defattr);
    521         sfb_consaddr = addr;
    522         return(0);
    523 }
    524 
    525 int
    526 sfbintr(arg)
    527 	void *arg;
    528 {
    529 	struct sfb_softc *sc = arg;
    530 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    531 	caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
    532 	struct bt459reg *vdac;
    533 	int v;
    534 
    535 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    536 	/* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
    537 
    538 	if (sc->sc_changed == 0)
    539 		return (1);
    540 
    541 	vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    542 	v = sc->sc_changed;
    543 	sc->sc_changed = 0;
    544 
    545 	if (v & DATA_ENB_CHANGED) {
    546 		BT459_SELECT(vdac, BT459_REG_CCR);
    547 		vdac->bt_reg = (sc->sc_curenb) ? 0xc0 : 0x00;
    548 	}
    549 	if (v & DATA_CURCMAP_CHANGED) {
    550 		u_int8_t *cp = sc->sc_cursor.cc_color;
    551 
    552 		BT459_SELECT(vdac, BT459_REG_CCOLOR_2);
    553 		vdac->bt_reg = cp[1];	tc_wmb();
    554 		vdac->bt_reg = cp[3];	tc_wmb();
    555 		vdac->bt_reg = cp[5];	tc_wmb();
    556 
    557 		vdac->bt_reg = cp[0];	tc_wmb();
    558 		vdac->bt_reg = cp[2];	tc_wmb();
    559 		vdac->bt_reg = cp[4];	tc_wmb();
    560 	}
    561 	if (v & DATA_CURSHAPE_CHANGED) {
    562 		u_int8_t *ip, *mp, img, msk;
    563 		u_int8_t u;
    564 		int bcnt;
    565 
    566 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    567 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    568 
    569 		bcnt = 0;
    570 		BT459_SELECT(vdac, BT459_REG_CRAM_BASE+0);
    571 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    572 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    573 			/* pad right half 32 pixel when smaller than 33 */
    574 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    575 				vdac->bt_reg = 0; tc_wmb();
    576 				vdac->bt_reg = 0; tc_wmb();
    577 			}
    578 			else {
    579 				img = *ip++;
    580 				msk = *mp++;
    581 				img &= msk;	/* cookie off image */
    582 				u = (msk & 0x0f) << 4 | (img & 0x0f);
    583 				vdac->bt_reg = shuffle[u];	tc_wmb();
    584 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
    585 				vdac->bt_reg = shuffle[u];	tc_wmb();
    586 			}
    587 			bcnt += 2;
    588 		}
    589 		/* pad unoccupied scan lines */
    590 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    591 			vdac->bt_reg = 0; tc_wmb();
    592 			vdac->bt_reg = 0; tc_wmb();
    593 			bcnt += 2;
    594 		}
    595 	}
    596 	if (v & DATA_CMAP_CHANGED) {
    597 		struct hwcmap256 *cm = &sc->sc_cmap;
    598 		int index;
    599 
    600 		BT459_SELECT(vdac, 0);
    601 		for (index = 0; index < CMAP_SIZE; index++) {
    602 			vdac->bt_cmap = cm->r[index];	tc_wmb();
    603 			vdac->bt_cmap = cm->g[index];	tc_wmb();
    604 			vdac->bt_cmap = cm->b[index];	tc_wmb();
    605 		}
    606 	}
    607 	return (1);
    608 }
    609 
    610 void
    611 sfbinit(dc)
    612 	struct fb_devconfig *dc;
    613 {
    614 	caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    615 	struct bt459reg *vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
    616 	int i;
    617 
    618 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 0;
    619 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    620 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    621 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;
    622 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;
    623 
    624 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    625 
    626 	BT459_SELECT(vdac, BT459_REG_COMMAND_0);
    627 	vdac->bt_reg = 0x40; /* CMD0 */	tc_wmb();
    628 	vdac->bt_reg = 0x0;  /* CMD1 */	tc_wmb();
    629 	vdac->bt_reg = 0xc0; /* CMD2 */	tc_wmb();
    630 	vdac->bt_reg = 0xff; /* PRM */	tc_wmb();
    631 	vdac->bt_reg = 0;    /* 205 */	tc_wmb();
    632 	vdac->bt_reg = 0x0;  /* PBM */	tc_wmb();
    633 	vdac->bt_reg = 0;    /* 207 */	tc_wmb();
    634 	vdac->bt_reg = 0x0;  /* ORM */	tc_wmb();
    635 	vdac->bt_reg = 0x0;  /* OBM */	tc_wmb();
    636 	vdac->bt_reg = 0x0;  /* ILV */	tc_wmb();
    637 	vdac->bt_reg = 0x0;  /* TEST */	tc_wmb();
    638 
    639 	BT459_SELECT(vdac, BT459_REG_CCR);
    640 	vdac->bt_reg = 0x0;	tc_wmb();
    641 	vdac->bt_reg = 0x0;	tc_wmb();
    642 	vdac->bt_reg = 0x0;	tc_wmb();
    643 	vdac->bt_reg = 0x0;	tc_wmb();
    644 	vdac->bt_reg = 0x0;	tc_wmb();
    645 	vdac->bt_reg = 0x0;	tc_wmb();
    646 	vdac->bt_reg = 0x0;	tc_wmb();
    647 	vdac->bt_reg = 0x0;	tc_wmb();
    648 	vdac->bt_reg = 0x0;	tc_wmb();
    649 	vdac->bt_reg = 0x0;	tc_wmb();
    650 	vdac->bt_reg = 0x0;	tc_wmb();
    651 	vdac->bt_reg = 0x0;	tc_wmb();
    652 	vdac->bt_reg = 0x0;	tc_wmb();
    653 
    654 	/* build sane colormap */
    655 	BT459_SELECT(vdac, 0);
    656 	vdac->bt_cmap = 0;	tc_wmb();
    657 	vdac->bt_cmap = 0;	tc_wmb();
    658 	vdac->bt_cmap = 0;	tc_wmb();
    659 	for (i = 1; i < CMAP_SIZE; i++) {
    660 		vdac->bt_cmap = 0xff;	tc_wmb();
    661 		vdac->bt_cmap = 0xff;	tc_wmb();
    662 		vdac->bt_cmap = 0xff;	tc_wmb();
    663 	}
    664 
    665 	/* clear out cursor image */
    666 	BT459_SELECT(vdac, BT459_REG_CRAM_BASE);
    667 	for (i = 0; i < 1024; i++)
    668 		vdac->bt_reg = 0xff;	tc_wmb();
    669 
    670 	/*
    671 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    672 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    673 	 * image color.  CCOLOR_1 will be never used.
    674 	 */
    675 	BT459_SELECT(vdac, BT459_REG_CCOLOR_1);
    676 	vdac->bt_reg = 0xff;	tc_wmb();
    677 	vdac->bt_reg = 0xff;	tc_wmb();
    678 	vdac->bt_reg = 0xff;	tc_wmb();
    679 
    680 	vdac->bt_reg = 0;	tc_wmb();
    681 	vdac->bt_reg = 0;	tc_wmb();
    682 	vdac->bt_reg = 0;	tc_wmb();
    683 
    684 	vdac->bt_reg = 0xff;	tc_wmb();
    685 	vdac->bt_reg = 0xff;	tc_wmb();
    686 	vdac->bt_reg = 0xff;	tc_wmb();
    687 }
    688 
    689 static int
    690 get_cmap(sc, p)
    691 	struct sfb_softc *sc;
    692 	struct wsdisplay_cmap *p;
    693 {
    694 	u_int index = p->index, count = p->count;
    695 
    696 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    697 		return (EINVAL);
    698 
    699 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    700 	    !uvm_useracc(p->green, count, B_WRITE) ||
    701 	    !uvm_useracc(p->blue, count, B_WRITE))
    702 		return (EFAULT);
    703 
    704 	copyout(&sc->sc_cmap.r[index], p->red, count);
    705 	copyout(&sc->sc_cmap.g[index], p->green, count);
    706 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    707 
    708 	return (0);
    709 }
    710 
    711 static int
    712 set_cmap(sc, p)
    713 	struct sfb_softc *sc;
    714 	struct wsdisplay_cmap *p;
    715 {
    716 	u_int index = p->index, count = p->count;
    717 
    718 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    719 		return (EINVAL);
    720 
    721 	if (!uvm_useracc(p->red, count, B_READ) ||
    722 	    !uvm_useracc(p->green, count, B_READ) ||
    723 	    !uvm_useracc(p->blue, count, B_READ))
    724 		return (EFAULT);
    725 
    726 	copyin(p->red, &sc->sc_cmap.r[index], count);
    727 	copyin(p->green, &sc->sc_cmap.g[index], count);
    728 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    729 
    730 	sc->sc_changed |= DATA_CMAP_CHANGED;
    731 
    732 	return (0);
    733 }
    734 
    735 
    736 static int
    737 set_cursor(sc, p)
    738 	struct sfb_softc *sc;
    739 	struct wsdisplay_cursor *p;
    740 {
    741 #define	cc (&sc->sc_cursor)
    742 	int v, index, count, icount;
    743 
    744 	v = p->which;
    745 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    746 		index = p->cmap.index;
    747 		count = p->cmap.count;
    748 		if (index >= 2 || (index + count) > 2)
    749 			return (EINVAL);
    750 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    751 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    752 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    753 			return (EFAULT);
    754 	}
    755 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    756 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    757 			return (EINVAL);
    758 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    759 		if (!uvm_useracc(p->image, icount, B_READ) ||
    760 		    !uvm_useracc(p->mask, icount, B_READ))
    761 			return (EFAULT);
    762 	}
    763 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    764 		if (v & WSDISPLAY_CURSOR_DOCUR)
    765 			cc->cc_hot = p->hot;
    766 		if (v & WSDISPLAY_CURSOR_DOPOS)
    767 			set_curpos(sc, &p->pos);
    768 		bt459_set_curpos(sc);
    769 	}
    770 
    771 	sc->sc_changed = 0;
    772 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    773 		sc->sc_curenb = p->enable;
    774 		sc->sc_changed |= DATA_ENB_CHANGED;
    775 	}
    776 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    777 		copyin(p->cmap.red, &cc->cc_color[index], count);
    778 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    779 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    780 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    781 	}
    782 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    783 		cc->cc_size = p->size;
    784 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    785 		copyin(p->image, cc->cc_image, icount);
    786 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    787 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    788 	}
    789 
    790 	return (0);
    791 #undef cc
    792 }
    793 
    794 static int
    795 get_cursor(sc, p)
    796 	struct sfb_softc *sc;
    797 	struct wsdisplay_cursor *p;
    798 {
    799 	return (ENOTTY); /* XXX */
    800 }
    801 
    802 static void
    803 set_curpos(sc, curpos)
    804 	struct sfb_softc *sc;
    805 	struct wsdisplay_curpos *curpos;
    806 {
    807 	struct fb_devconfig *dc = sc->sc_dc;
    808 	int x = curpos->x, y = curpos->y;
    809 
    810 	if (y < 0)
    811 		y = 0;
    812 	else if (y > dc->dc_ht)
    813 		y = dc->dc_ht;
    814 	if (x < 0)
    815 		x = 0;
    816 	else if (x > dc->dc_wid)
    817 		x = dc->dc_wid;
    818 	sc->sc_cursor.cc_pos.x = x;
    819 	sc->sc_cursor.cc_pos.y = y;
    820 }
    821 
    822 static void
    823 bt459_set_curpos(sc)
    824 	struct sfb_softc *sc;
    825 {
    826 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    827 	struct bt459reg *vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    828 	int x, y, s;
    829 
    830 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    831 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    832 
    833 	x += sc->sc_cursor.cc_magic.x;
    834 	y += sc->sc_cursor.cc_magic.y;
    835 
    836 	s = spltty();
    837 
    838 	BT459_SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    839 	vdac->bt_reg = x;	tc_wmb();
    840 	vdac->bt_reg = x >> 8;	tc_wmb();
    841 	vdac->bt_reg = y;	tc_wmb();
    842 	vdac->bt_reg = y >> 8;	tc_wmb();
    843 
    844 	splx(s);
    845 }
    846 
    847 #define	MODE_SIMPLE		0
    848 #define	MODE_OPAQUESTIPPLE	1
    849 #define	MODE_OPAQUELINE		2
    850 #define	MODE_TRANSPARENTSTIPPLE	5
    851 #define	MODE_TRANSPARENTLINE	6
    852 #define	MODE_COPY		7
    853 
    854 #define	SFBALIGNMASK		0x7
    855 #define	SFBSTIPPLEALL1		0xffffffff
    856 #define	SFBSTIPPLEBITS		32
    857 #define	SFBSTIPPLEBITMASK	0x1f
    858 #define	SFBSTIPPLEBYTESDONE	32
    859 
    860 /*
    861  * Paint (or unpaint) the cursor.
    862  */
    863 void
    864 sfb_cursor(id, on, row, col)
    865 	void *id;
    866 	int on, row, col;
    867 {
    868 	struct rcons *rc = id;
    869 	int x, y;
    870 
    871 	/* turn the cursor off */
    872 	if (!on) {
    873 		/* make sure it's on */
    874 		if ((rc->rc_bits & RC_CURSOR) == 0)
    875 			return;
    876 
    877 		row = *rc->rc_crowp;
    878 		col = *rc->rc_ccolp;
    879 	} else {
    880 		/* unpaint the old copy. */
    881 		*rc->rc_crowp = row;
    882 		*rc->rc_ccolp = col;
    883 	}
    884 
    885 	x = col * rc->rc_font->width + rc->rc_xorigin;
    886 	y = row * rc->rc_font->height + rc->rc_yorigin;
    887 
    888 	raster_op(rc->rc_sp, x, y,
    889 	    rc->rc_font->width, rc->rc_font->height,
    890 	    RAS_INVERT,
    891 	    (struct raster *) 0, 0, 0);
    892 
    893 	rc->rc_bits ^= RC_CURSOR;
    894 }
    895 
    896 /*
    897  * Actually write a string to the frame buffer.
    898  */
    899 int
    900 sfb_mapchar(id, uni, index)
    901 	void *id;
    902 	int uni;
    903 	unsigned int *index;
    904 {
    905 	if (uni < 128) {
    906 		*index = uni;
    907 		return (5);
    908 	}
    909 	*index = ' ';
    910 	return (0);
    911 }
    912 
    913 /*
    914  * Actually write a string to the frame buffer.
    915  */
    916 void
    917 sfb_putchar(id, row, col, uc, attr)
    918 	void *id;
    919 	int row, col;
    920 	u_int uc;
    921 	long attr;
    922 {
    923 	struct rcons *rc = id;
    924 	int x, y, op;
    925 	u_char help;
    926 
    927 	x = col * rc->rc_font->width + rc->rc_xorigin;
    928 	y = row * rc->rc_font->height + rc->rc_font_ascent + rc->rc_yorigin;
    929 
    930 	op = RAS_SRC;
    931 	if ((attr != 0) ^ ((rc->rc_bits & RC_INVERT) != 0))
    932 		op = RAS_NOT(op);
    933 	help = uc & 0xff;
    934 	raster_textn(rc->rc_sp, x, y, op, rc->rc_font, &help, 1);
    935 }
    936 
    937 /*
    938  * Copy columns (characters) in a row (line).
    939  */
    940 void
    941 sfb_copycols(id, row, srccol, dstcol, ncols)
    942 	void *id;
    943 	int row, srccol, dstcol, ncols;
    944 {
    945 	struct rcons *rc = id;
    946 	int y, srcx, dstx, nx;
    947 
    948 	y = rc->rc_yorigin + rc->rc_font->height * row;
    949 	srcx = rc->rc_xorigin + rc->rc_font->width * srccol;
    950 	dstx = rc->rc_xorigin + rc->rc_font->width * dstcol;
    951 	nx = rc->rc_font->width * ncols;
    952 
    953 	raster_op(rc->rc_sp, dstx, y,
    954 	    nx, rc->rc_font->height, RAS_SRC,
    955 	    rc->rc_sp, srcx, y);
    956 }
    957 
    958 /*
    959  * Clear columns (characters) in a row (line).
    960  */
    961 void
    962 sfb_erasecols(id, row, startcol, ncols, fillattr)
    963 	void *id;
    964 	int row, startcol, ncols;
    965 	long fillattr;
    966 {
    967 	struct rcons *rc = id;
    968 	struct raster *rap = rc->rc_sp;
    969 	caddr_t sfb, p;
    970 	int scanspan, startx, height, width, align, w, y;
    971 	u_int32_t lmask, rmask;
    972 
    973 	scanspan = rap->linelongs * 4;
    974 	y = rc->rc_yorigin + rc->rc_font->height * row;
    975 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
    976 	height = rc->rc_font->height;
    977 	w = rc->rc_font->width * ncols;
    978 
    979 	p = (caddr_t)rap->pixels + y * scanspan + startx;
    980 	align = (long)p & SFBALIGNMASK;
    981 	p -= align;
    982 	width = w + align;
    983 	lmask = SFBSTIPPLEALL1 << align;
    984 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    985 	sfb = rap->data;
    986 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
    987 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
    988 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = 0;
    989 	if (width <= SFBSTIPPLEBITS) {
    990 		while (height > 0) {
    991 			*(u_int32_t *)(sfb + SFB_ASIC_ADDRESS) = (long)p;
    992 			*(u_int32_t *)(sfb + SFB_ASIC_START) = lmask & rmask;
    993 			p += scanspan;
    994 			height--;
    995 		}
    996 	}
    997 	else {
    998 		caddr_t q = p;
    999 		while (height > 0) {
   1000 			*(u_int32_t *)p = lmask;
   1001 			width -= 2 * SFBSTIPPLEBITS;
   1002 			while (width > 0) {
   1003 				p += SFBSTIPPLEBYTESDONE;
   1004 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1005 				width -= SFBSTIPPLEBITS;
   1006 			}
   1007 			p += SFBSTIPPLEBYTESDONE;
   1008 			*(u_int32_t *)p = rmask;
   1009 
   1010 			p = (q += scanspan);
   1011 			width = w + align;
   1012 			height--;
   1013 		}
   1014 	}
   1015 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1016 }
   1017 
   1018 /*
   1019  * Copy rows (lines).
   1020  */
   1021 void
   1022 sfb_copyrows(id, srcrow, dstrow, nrows)
   1023 	void *id;
   1024 	int srcrow, dstrow, nrows;
   1025 {
   1026 	struct rcons *rc = id;
   1027 	struct raster *rap = rc->rc_sp;
   1028 	caddr_t sfb, p;
   1029 	int scanspan, offset, srcy, height, width, align, w;
   1030 	u_int32_t lmask, rmask;
   1031 
   1032 	scanspan = rap->linelongs * 4;
   1033 	height = rc->rc_font->height * nrows;
   1034 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1035 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1036 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1037 		scanspan = -scanspan;
   1038 		srcy += height;
   1039 	}
   1040 
   1041 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1042 	align = (long)p & SFBALIGNMASK;
   1043 	p -= align;
   1044 	w = rc->rc_font->width * rc->rc_maxcol;
   1045 	width = w + align;
   1046 	lmask = SFBSTIPPLEALL1 << align;
   1047 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1048 	sfb = rap->data;
   1049 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
   1050 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1051 	*(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = 0;
   1052 	if (width <= SFBSTIPPLEBITS) {
   1053 		/* never happens */;
   1054 	}
   1055 	else {
   1056 		caddr_t q = p;
   1057 		while (height > 0) {
   1058 			*(u_int32_t *)p = lmask;
   1059 			*(u_int32_t *)(p + offset) = lmask;
   1060 			width -= 2 * SFBSTIPPLEBITS;
   1061 			while (width > 0) {
   1062 				p += SFBSTIPPLEBYTESDONE;
   1063 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1064 				*(u_int32_t *)(p + offset) = SFBSTIPPLEALL1;
   1065 				width -= SFBSTIPPLEBITS;
   1066 			}
   1067 			p += SFBSTIPPLEBYTESDONE;
   1068 			*(u_int32_t *)p = rmask;
   1069 			*(u_int32_t *)(p + offset) = rmask;
   1070 
   1071 			p = (q += scanspan);
   1072 			width = w + align;
   1073 			height--;
   1074 		}
   1075 	}
   1076 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1077 }
   1078 
   1079 /*
   1080  * Erase rows (lines).
   1081  */
   1082 void
   1083 sfb_eraserows(id, startrow, nrows, fillattr)
   1084 	void *id;
   1085 	int startrow, nrows;
   1086 	long fillattr;
   1087 {
   1088 	struct rcons *rc = id;
   1089 	struct raster *rap = rc->rc_sp;
   1090 	caddr_t sfb, p;
   1091 	int scanspan, starty, height, width, align, w;
   1092 	u_int32_t lmask, rmask;
   1093 
   1094 	scanspan = rap->linelongs * 4;
   1095 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1096 	height = rc->rc_font->height * nrows;
   1097 
   1098 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1099 	align = (long)p & SFBALIGNMASK;
   1100 	p -= align;
   1101 	w = rc->rc_font->width * rc->rc_maxcol;
   1102 	width = w + align;
   1103 	lmask = SFBSTIPPLEALL1 << align;
   1104 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1105 	sfb = rap->data;
   1106 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
   1107 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1108 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = 0;
   1109 	if (width <= SFBSTIPPLEBITS) {
   1110 		/* never happens */;
   1111 	}
   1112 	else {
   1113 		caddr_t q = p;
   1114 		while (height > 0) {
   1115 			*(u_int32_t *)p = lmask;
   1116 			width -= 2 * SFBSTIPPLEBITS;
   1117 			while (width > 0) {
   1118 				p += SFBSTIPPLEBYTESDONE;
   1119 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1120 				width -= SFBSTIPPLEBITS;
   1121 			}
   1122 			p += SFBSTIPPLEBYTESDONE;
   1123 			*(u_int32_t *)p = rmask;
   1124 
   1125 			p = (q += scanspan);
   1126 			width = w + align;
   1127 			height--;
   1128 		}
   1129 	}
   1130 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1131 }
   1132 
   1133 int
   1134 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1135 	void *id;
   1136 	int fg, bg, flags;
   1137 	long *attrp;
   1138 {
   1139 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1140 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1141 		return (EINVAL);
   1142 	if (flags & WSATTR_REVERSE)
   1143 		*attrp = 1;
   1144 	else
   1145 		*attrp = 0;
   1146 	return (0);
   1147 }
   1148