Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.13
      1 /* $NetBSD: sfb.c,v 1.13 1999/03/24 05:51:21 mrg 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.13 1999/03/24 05:51:21 mrg 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 #include <machine/autoconf.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 /* XXX BUS'IFYING XXX */
     62 
     63 #if defined(pmax)
     64 #define	machine_btop(x) mips_btop(x)
     65 #define	MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
     66 #endif
     67 
     68 #if defined(__alpha__) || defined(alpha)
     69 #define machine_btop(x) alpha_btop(x)
     70 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
     71 #endif
     72 
     73 /*
     74  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
     75  * obscure register layout such as 2nd and 3rd Bt459 registers are
     76  * adjacent each other in a word, i.e.,
     77  *	struct bt459triplet {
     78  * 		struct {
     79  *			u_int8_t u0;
     80  *			u_int8_t u1;
     81  *			u_int8_t u2;
     82  *			unsigned :8;
     83  *		} bt_lo;
     84  *		...
     85  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
     86  */
     87 struct bt459reg {
     88         u_int32_t       bt_lo;
     89         u_int32_t       bt_hi;
     90         u_int32_t       bt_reg;
     91         u_int32_t       bt_cmap;
     92 };
     93 
     94 /* XXX XXX XXX */
     95 
     96 struct fb_devconfig {
     97 	vaddr_t dc_vaddr;		/* memory space virtual base address */
     98 	paddr_t dc_paddr;		/* memory space physical base address */
     99 	vsize_t dc_size;		/* size of slot memory */
    100 	int	dc_wid;			/* width of frame buffer */
    101 	int	dc_ht;			/* height of frame buffer */
    102 	int	dc_depth;		/* depth, bits per pixel */
    103 	int	dc_rowbytes;		/* bytes in a FB scan line */
    104 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
    105 	struct raster	dc_raster;	/* raster description */
    106 	struct rcons	dc_rcons;	/* raster blitter control info */
    107 	int	    dc_blanked;		/* currently has video disabled */
    108 };
    109 
    110 struct hwcmap {
    111 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
    112 	u_int8_t r[CMAP_SIZE];
    113 	u_int8_t g[CMAP_SIZE];
    114 	u_int8_t b[CMAP_SIZE];
    115 };
    116 
    117 struct hwcursor {
    118 	struct wsdisplay_curpos cc_pos;
    119 	struct wsdisplay_curpos cc_hot;
    120 	struct wsdisplay_curpos cc_size;
    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 hwcmap sc_cmap;		/* software copy of colormap */
    130 	struct hwcursor 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 	short magic_x, magic_y;		/* HX cursor location offset */
    140 #define	HX_MAGIC_X 368
    141 #define	HX_MAGIC_Y 38
    142 };
    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 hwcmap *cm;
    347 	caddr_t sfbasic;
    348 	int console, i;
    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 	cm->r[0] = cm->g[0] = cm->b[0] = 0;
    365 	for (i = 1; i < CMAP_SIZE; i++) {
    366 		cm->r[i] = cm->g[i] = cm->b[i] = 0xff;
    367 	}
    368 	sc->magic_x = HX_MAGIC_X; sc->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 hwcmap *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 	x += sc->magic_x; y += sc->magic_y; /* magic offset of HX coordinate */
    833 
    834 	s = spltty();
    835 
    836 	BT459_SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    837 	vdac->bt_reg = x;	tc_wmb();
    838 	vdac->bt_reg = x >> 8;	tc_wmb();
    839 	vdac->bt_reg = y;	tc_wmb();
    840 	vdac->bt_reg = y >> 8;	tc_wmb();
    841 
    842 	splx(s);
    843 }
    844 
    845 #define	MODE_SIMPLE		0
    846 #define	MODE_OPAQUESTIPPLE	1
    847 #define	MODE_OPAQUELINE		2
    848 #define	MODE_TRANSPARENTSTIPPLE	5
    849 #define	MODE_TRANSPARENTLINE	6
    850 #define	MODE_COPY		7
    851 
    852 #define	SFBALIGNMASK		0x7
    853 #define	SFBSTIPPLEALL1		0xffffffff
    854 #define	SFBSTIPPLEBITS		32
    855 #define	SFBSTIPPLEBITMASK	0x1f
    856 #define	SFBSTIPPLEBYTESDONE	32
    857 
    858 /*
    859  * Paint (or unpaint) the cursor.
    860  */
    861 void
    862 sfb_cursor(id, on, row, col)
    863 	void *id;
    864 	int on, row, col;
    865 {
    866 	struct rcons *rc = id;
    867 	int x, y;
    868 
    869 	/* turn the cursor off */
    870 	if (!on) {
    871 		/* make sure it's on */
    872 		if ((rc->rc_bits & RC_CURSOR) == 0)
    873 			return;
    874 
    875 		row = *rc->rc_crowp;
    876 		col = *rc->rc_ccolp;
    877 	} else {
    878 		/* unpaint the old copy. */
    879 		*rc->rc_crowp = row;
    880 		*rc->rc_ccolp = col;
    881 	}
    882 
    883 	x = col * rc->rc_font->width + rc->rc_xorigin;
    884 	y = row * rc->rc_font->height + rc->rc_yorigin;
    885 
    886 	raster_op(rc->rc_sp, x, y,
    887 	    rc->rc_font->width, rc->rc_font->height,
    888 	    RAS_INVERT,
    889 	    (struct raster *) 0, 0, 0);
    890 
    891 	rc->rc_bits ^= RC_CURSOR;
    892 }
    893 
    894 /*
    895  * Actually write a string to the frame buffer.
    896  */
    897 int
    898 sfb_mapchar(id, uni, index)
    899 	void *id;
    900 	int uni;
    901 	unsigned int *index;
    902 {
    903 	if (uni < 128) {
    904 		*index = uni;
    905 		return (5);
    906 	}
    907 	*index = ' ';
    908 	return (0);
    909 }
    910 
    911 /*
    912  * Actually write a string to the frame buffer.
    913  */
    914 void
    915 sfb_putchar(id, row, col, uc, attr)
    916 	void *id;
    917 	int row, col;
    918 	u_int uc;
    919 	long attr;
    920 {
    921 	struct rcons *rc = id;
    922 	int x, y, op;
    923 	u_char help;
    924 
    925 	x = col * rc->rc_font->width + rc->rc_xorigin;
    926 	y = row * rc->rc_font->height + rc->rc_font_ascent + rc->rc_yorigin;
    927 
    928 	op = RAS_SRC;
    929 	if ((attr != 0) ^ ((rc->rc_bits & RC_INVERT) != 0))
    930 		op = RAS_NOT(op);
    931 	help = uc & 0xff;
    932 	raster_textn(rc->rc_sp, x, y, op, rc->rc_font, &help, 1);
    933 }
    934 
    935 /*
    936  * Copy columns (characters) in a row (line).
    937  */
    938 void
    939 sfb_copycols(id, row, srccol, dstcol, ncols)
    940 	void *id;
    941 	int row, srccol, dstcol, ncols;
    942 {
    943 	struct rcons *rc = id;
    944 	int y, srcx, dstx, nx;
    945 
    946 	y = rc->rc_yorigin + rc->rc_font->height * row;
    947 	srcx = rc->rc_xorigin + rc->rc_font->width * srccol;
    948 	dstx = rc->rc_xorigin + rc->rc_font->width * dstcol;
    949 	nx = rc->rc_font->width * ncols;
    950 
    951 	raster_op(rc->rc_sp, dstx, y,
    952 	    nx, rc->rc_font->height, RAS_SRC,
    953 	    rc->rc_sp, srcx, y);
    954 }
    955 
    956 /*
    957  * Clear columns (characters) in a row (line).
    958  */
    959 void
    960 sfb_erasecols(id, row, startcol, ncols, fillattr)
    961 	void *id;
    962 	int row, startcol, ncols;
    963 	long fillattr;
    964 {
    965 	struct rcons *rc = id;
    966 	struct raster *rap = rc->rc_sp;
    967 	caddr_t sfb, p;
    968 	int scanspan, startx, height, width, align, w, y;
    969 	u_int32_t lmask, rmask;
    970 
    971 	scanspan = rap->linelongs * 4;
    972 	y = rc->rc_yorigin + rc->rc_font->height * row;
    973 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
    974 	height = rc->rc_font->height;
    975 	w = rc->rc_font->width * ncols;
    976 
    977 	p = (caddr_t)rap->pixels + y * scanspan + startx;
    978 	align = (long)p & SFBALIGNMASK;
    979 	p -= align;
    980 	width = w + align;
    981 	lmask = SFBSTIPPLEALL1 << align;
    982 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    983 	sfb = rap->data;
    984 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
    985 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
    986 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = 0;
    987 	if (width <= SFBSTIPPLEBITS) {
    988 		while (height > 0) {
    989 			*(u_int32_t *)(sfb + SFB_ASIC_ADDRESS) = (long)p;
    990 			*(u_int32_t *)(sfb + SFB_ASIC_START) = lmask & rmask;
    991 			p += scanspan;
    992 			height--;
    993 		}
    994 	}
    995 	else {
    996 		caddr_t q = p;
    997 		while (height > 0) {
    998 			*(u_int32_t *)p = lmask;
    999 			width -= 2 * SFBSTIPPLEBITS;
   1000 			while (width > 0) {
   1001 				p += SFBSTIPPLEBYTESDONE;
   1002 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1003 				width -= SFBSTIPPLEBITS;
   1004 			}
   1005 			p += SFBSTIPPLEBYTESDONE;
   1006 			*(u_int32_t *)p = rmask;
   1007 
   1008 			p = (q += scanspan);
   1009 			width = w + align;
   1010 			height--;
   1011 		}
   1012 	}
   1013 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1014 }
   1015 
   1016 /*
   1017  * Copy rows (lines).
   1018  */
   1019 void
   1020 sfb_copyrows(id, srcrow, dstrow, nrows)
   1021 	void *id;
   1022 	int srcrow, dstrow, nrows;
   1023 {
   1024 	struct rcons *rc = id;
   1025 	struct raster *rap = rc->rc_sp;
   1026 	caddr_t sfb, p;
   1027 	int scanspan, offset, srcy, height, width, align, w;
   1028 	u_int32_t lmask, rmask;
   1029 
   1030 	scanspan = rap->linelongs * 4;
   1031 	height = rc->rc_font->height * nrows;
   1032 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1033 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1034 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1035 		scanspan = -scanspan;
   1036 		srcy += height;
   1037 	}
   1038 
   1039 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1040 	align = (long)p & SFBALIGNMASK;
   1041 	p -= align;
   1042 	w = rc->rc_font->width * rc->rc_maxcol;
   1043 	width = w + align;
   1044 	lmask = SFBSTIPPLEALL1 << align;
   1045 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1046 	sfb = rap->data;
   1047 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
   1048 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1049 	*(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = 0;
   1050 	if (width <= SFBSTIPPLEBITS) {
   1051 		/* never happens */;
   1052 	}
   1053 	else {
   1054 		caddr_t q = p;
   1055 		while (height > 0) {
   1056 			*(u_int32_t *)p = lmask;
   1057 			*(u_int32_t *)(p + offset) = lmask;
   1058 			width -= 2 * SFBSTIPPLEBITS;
   1059 			while (width > 0) {
   1060 				p += SFBSTIPPLEBYTESDONE;
   1061 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1062 				*(u_int32_t *)(p + offset) = SFBSTIPPLEALL1;
   1063 				width -= SFBSTIPPLEBITS;
   1064 			}
   1065 			p += SFBSTIPPLEBYTESDONE;
   1066 			*(u_int32_t *)p = rmask;
   1067 			*(u_int32_t *)(p + offset) = rmask;
   1068 
   1069 			p = (q += scanspan);
   1070 			width = w + align;
   1071 			height--;
   1072 		}
   1073 	}
   1074 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1075 }
   1076 
   1077 /*
   1078  * Erase rows (lines).
   1079  */
   1080 void
   1081 sfb_eraserows(id, startrow, nrows, fillattr)
   1082 	void *id;
   1083 	int startrow, nrows;
   1084 	long fillattr;
   1085 {
   1086 	struct rcons *rc = id;
   1087 	struct raster *rap = rc->rc_sp;
   1088 	caddr_t sfb, p;
   1089 	int scanspan, starty, height, width, align, w;
   1090 	u_int32_t lmask, rmask;
   1091 
   1092 	scanspan = rap->linelongs * 4;
   1093 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1094 	height = rc->rc_font->height * nrows;
   1095 
   1096 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1097 	align = (long)p & SFBALIGNMASK;
   1098 	p -= align;
   1099 	w = rc->rc_font->width * rc->rc_maxcol;
   1100 	width = w + align;
   1101 	lmask = SFBSTIPPLEALL1 << align;
   1102 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1103 	sfb = rap->data;
   1104 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
   1105 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1106 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = 0;
   1107 	if (width <= SFBSTIPPLEBITS) {
   1108 		/* never happens */;
   1109 	}
   1110 	else {
   1111 		caddr_t q = p;
   1112 		while (height > 0) {
   1113 			*(u_int32_t *)p = lmask;
   1114 			width -= 2 * SFBSTIPPLEBITS;
   1115 			while (width > 0) {
   1116 				p += SFBSTIPPLEBYTESDONE;
   1117 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1118 				width -= SFBSTIPPLEBITS;
   1119 			}
   1120 			p += SFBSTIPPLEBYTESDONE;
   1121 			*(u_int32_t *)p = rmask;
   1122 
   1123 			p = (q += scanspan);
   1124 			width = w + align;
   1125 			height--;
   1126 		}
   1127 	}
   1128 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1129 }
   1130 
   1131 int
   1132 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1133 	void *id;
   1134 	int fg, bg, flags;
   1135 	long *attrp;
   1136 {
   1137 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1138 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1139 		return (EINVAL);
   1140 	if (flags & WSATTR_REVERSE)
   1141 		*attrp = 1;
   1142 	else
   1143 		*attrp = 0;
   1144 	return (0);
   1145 }
   1146