Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.20
      1 /* $NetBSD: sfb.c,v 1.20 1999/10/08 02:08:15 nisimura Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1998, 1999 Tohru Nishimura.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Tohru Nishimura
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     34 
     35 __KERNEL_RCSID(0, "$NetBSD: sfb.c,v 1.20 1999/10/08 02:08:15 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 #if defined(pmax)
     61 #define	machine_btop(x) mips_btop(x)
     62 #define	MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
     63 #endif
     64 
     65 #if defined(__alpha__) || defined(alpha)
     66 #define machine_btop(x) alpha_btop(x)
     67 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
     68 #endif
     69 
     70 /*
     71  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
     72  * obscure register layout such as 2nd and 3rd Bt459 registers are
     73  * adjacent each other in a word, i.e.,
     74  *	struct bt459triplet {
     75  * 		struct {
     76  *			u_int8_t u0;
     77  *			u_int8_t u1;
     78  *			u_int8_t u2;
     79  *			unsigned :8;
     80  *		} bt_lo;
     81  *		struct {
     82  *
     83  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
     84  *	struct bt459reg {
     85  *		   u_int32_t	   bt_lo;
     86  *		   u_int32_t	   bt_hi;
     87  *		   u_int32_t	   bt_reg;
     88  *		   u_int32_t	   bt_cmap;
     89  *	};
     90  *
     91  */
     92 
     93 /* Bt459 hardware registers */
     94 #define bt_lo	0
     95 #define bt_hi	1
     96 #define bt_reg	2
     97 #define bt_cmap 3
     98 
     99 #define REG(base, index)	*((u_int32_t *)(base) + (index))
    100 #define SELECT(vdac, regno) do {			\
    101 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
    102 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
    103 	tc_wmb();					\
    104    } while (0)
    105 
    106 struct fb_devconfig {
    107 	vaddr_t dc_vaddr;		/* memory space virtual base address */
    108 	paddr_t dc_paddr;		/* memory space physical base address */
    109 	vsize_t dc_size;		/* size of slot memory */
    110 	int	dc_wid;			/* width of frame buffer */
    111 	int	dc_ht;			/* height of frame buffer */
    112 	int	dc_depth;		/* depth, bits per pixel */
    113 	int	dc_rowbytes;		/* bytes in a FB scan line */
    114 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
    115 	struct raster	dc_raster;	/* raster description */
    116 	struct rcons	dc_rcons;	/* raster blitter control info */
    117 	int	    dc_blanked;		/* currently has video disabled */
    118 };
    119 
    120 struct hwcmap256 {
    121 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
    122 	u_int8_t r[CMAP_SIZE];
    123 	u_int8_t g[CMAP_SIZE];
    124 	u_int8_t b[CMAP_SIZE];
    125 };
    126 
    127 struct hwcursor64 {
    128 	struct wsdisplay_curpos cc_pos;
    129 	struct wsdisplay_curpos cc_hot;
    130 	struct wsdisplay_curpos cc_size;
    131 	struct wsdisplay_curpos cc_magic;
    132 #define	CURSOR_MAX_SIZE	64
    133 	u_int8_t cc_color[6];
    134 	u_int64_t cc_image[64 + 64];
    135 };
    136 
    137 struct sfb_softc {
    138 	struct device sc_dev;
    139 	struct fb_devconfig *sc_dc;	/* device configuration */
    140 	struct hwcmap256 sc_cmap;	/* software copy of colormap */
    141 	struct hwcursor64 sc_cursor;	/* software copy of cursor */
    142 	int sc_curenb;			/* cursor sprite enabled */
    143 	int sc_changed;			/* need update of colormap */
    144 #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
    145 #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
    146 #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
    147 #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
    148 #define	DATA_ALL_CHANGED	0x0f
    149 	int nscreens;
    150 };
    151 
    152 #define	HX_MAGIC_X 368
    153 #define	HX_MAGIC_Y 38
    154 
    155 int  sfbmatch __P((struct device *, struct cfdata *, void *));
    156 void sfbattach __P((struct device *, struct device *, void *));
    157 
    158 struct cfattach sfb_ca = {
    159 	sizeof(struct sfb_softc), sfbmatch, sfbattach,
    160 };
    161 
    162 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    163 struct fb_devconfig sfb_console_dc;
    164 tc_addr_t sfb_consaddr;
    165 
    166 void	sfb_cursor __P((void *, int, int, int));
    167 int	sfb_mapchar __P((void *, int, unsigned int *));
    168 void	sfb_putchar __P((void *, int, int, u_int, long));
    169 void	sfb_copycols __P((void *, int, int, int, int));
    170 void	sfb_erasecols __P((void *, int, int, int, long));
    171 void	sfb_copyrows __P((void *, int, int, int));
    172 void	sfb_eraserows __P((void *, int, int, long));
    173 int	sfb_alloc_attr __P((void *, int, int, int, long *));
    174 
    175 struct wsdisplay_emulops sfb_emulops = {
    176 	sfb_cursor,			/* could use hardware cursor; punt */
    177 	sfb_mapchar,
    178 	sfb_putchar,
    179 	sfb_copycols,
    180 	sfb_erasecols,
    181 	sfb_copyrows,
    182 	sfb_eraserows,
    183 	sfb_alloc_attr
    184 };
    185 
    186 struct wsscreen_descr sfb_stdscreen = {
    187 	"std", 0, 0,
    188 	&sfb_emulops,
    189 	0, 0,
    190 	0
    191 };
    192 
    193 const struct wsscreen_descr *_sfb_scrlist[] = {
    194 	&sfb_stdscreen,
    195 };
    196 
    197 struct wsscreen_list sfb_screenlist = {
    198 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    199 };
    200 
    201 int	sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    202 int	sfbmmap __P((void *, off_t, int));
    203 
    204 int	sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    205 				      void **, int *, int *, long *));
    206 void	sfb_free_screen __P((void *, void *));
    207 void	sfb_show_screen __P((void *, void *));
    208 
    209 struct wsdisplay_accessops sfb_accessops = {
    210 	sfbioctl,
    211 	sfbmmap,
    212 	sfb_alloc_screen,
    213 	sfb_free_screen,
    214 	sfb_show_screen,
    215 	0 /* load_font */
    216 };
    217 
    218 int  sfb_cnattach __P((tc_addr_t));
    219 int  sfbintr __P((void *));
    220 void sfbinit __P((struct fb_devconfig *));
    221 
    222 static int  get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
    223 static int  set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
    224 static int  set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
    225 static int  get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
    226 static void set_curpos __P((struct sfb_softc *, struct wsdisplay_curpos *));
    227 static void bt459_set_curpos __P((struct sfb_softc *));
    228 
    229 
    230 /*
    231  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
    232  *   M M M M I I I I		M I M I M I M I
    233  *	[ before ]		   [ after ]
    234  *   3 2 1 0 3 2 1 0		0 0 1 1 2 2 3 3
    235  *   7 6 5 4 7 6 5 4		4 4 5 5 6 6 7 7
    236  */
    237 const static u_int8_t shuffle[256] = {
    238 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
    239 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
    240 	0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
    241 	0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
    242 	0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
    243 	0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
    244 	0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
    245 	0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
    246 	0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
    247 	0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
    248 	0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
    249 	0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
    250 	0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
    251 	0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
    252 	0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
    253 	0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
    254 	0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
    255 	0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
    256 	0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
    257 	0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
    258 	0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
    259 	0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
    260 	0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
    261 	0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
    262 	0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
    263 	0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
    264 	0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
    265 	0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
    266 	0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
    267 	0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
    268 	0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
    269 	0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
    270 };
    271 
    272 int
    273 sfbmatch(parent, match, aux)
    274 	struct device *parent;
    275 	struct cfdata *match;
    276 	void *aux;
    277 {
    278 	struct tc_attach_args *ta = aux;
    279 
    280 	if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
    281 		return (0);
    282 
    283 	return (1);
    284 }
    285 
    286 void
    287 sfb_getdevconfig(dense_addr, dc)
    288 	tc_addr_t dense_addr;
    289 	struct fb_devconfig *dc;
    290 {
    291 	struct raster *rap;
    292 	struct rcons *rcp;
    293 	caddr_t sfbasic;
    294 	int i, hsetup, vsetup, vbase;
    295 
    296 	dc->dc_vaddr = dense_addr;
    297 	dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
    298 
    299 	sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    300 	hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
    301 	vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
    302 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    303 
    304 	dc->dc_wid = (hsetup & 0x1ff) << 2;
    305 	dc->dc_ht = (vsetup & 0x7ff);
    306 	dc->dc_depth = 8;
    307 	dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
    308 	dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
    309 	dc->dc_blanked = 0;
    310 
    311 	/* initialize colormap and cursor resource */
    312 	sfbinit(dc);
    313 
    314 	/* clear the screen */
    315 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    316 		*(u_int32_t *)(dc->dc_videobase + i) = 0x0;
    317 
    318 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
    319 
    320 	/* initialize the raster */
    321 	rap = &dc->dc_raster;
    322 	rap->width = dc->dc_wid;
    323 	rap->height = dc->dc_ht;
    324 	rap->depth = dc->dc_depth;
    325 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    326 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    327 	rap->data = sfbasic;
    328 
    329 	/* initialize the raster console blitter */
    330 	rcp = &dc->dc_rcons;
    331 	rcp->rc_sp = rap;
    332 	rcp->rc_crow = rcp->rc_ccol = -1;
    333 	rcp->rc_crowp = &rcp->rc_crow;
    334 	rcp->rc_ccolp = &rcp->rc_ccol;
    335 	rcons_init(rcp, 34, 80);
    336 
    337 	sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    338 	sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    339 }
    340 
    341 void
    342 sfbattach(parent, self, aux)
    343 	struct device *parent, *self;
    344 	void *aux;
    345 {
    346 	struct sfb_softc *sc = (struct sfb_softc *)self;
    347 	struct tc_attach_args *ta = aux;
    348 	struct wsemuldisplaydev_attach_args waa;
    349 	struct hwcmap256 *cm;
    350 	caddr_t sfbasic;
    351 	int console;
    352 
    353 	console = (ta->ta_addr == sfb_consaddr);
    354 	if (console) {
    355 		sc->sc_dc = &sfb_console_dc;
    356 		sc->nscreens = 1;
    357 	}
    358 	else {
    359 		sc->sc_dc = (struct fb_devconfig *)
    360 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    361 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    362 	}
    363 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    364 	    sc->sc_dc->dc_depth);
    365 
    366 	cm = &sc->sc_cmap;
    367 	memset(cm, 255, sizeof(struct hwcmap256));	/* XXX */
    368 	cm->r[0] = cm->g[0] = cm->b[0] = 0;		/* XXX */
    369 
    370 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    371 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    372 
    373         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
    374 
    375 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    376 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    377 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    378 
    379 	waa.console = console;
    380 	waa.scrdata = &sfb_screenlist;
    381 	waa.accessops = &sfb_accessops;
    382 	waa.accesscookie = sc;
    383 
    384 	config_found(self, &waa, wsemuldisplaydevprint);
    385 }
    386 
    387 int
    388 sfbioctl(v, cmd, data, flag, p)
    389 	void *v;
    390 	u_long cmd;
    391 	caddr_t data;
    392 	int flag;
    393 	struct proc *p;
    394 {
    395 	struct sfb_softc *sc = v;
    396 	struct fb_devconfig *dc = sc->sc_dc;
    397 	int turnoff;
    398 
    399 	switch (cmd) {
    400 	case WSDISPLAYIO_GTYPE:
    401 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    402 		return (0);
    403 
    404 	case WSDISPLAYIO_GINFO:
    405 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    406 		wsd_fbip->height = sc->sc_dc->dc_ht;
    407 		wsd_fbip->width = sc->sc_dc->dc_wid;
    408 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    409 		wsd_fbip->cmsize = CMAP_SIZE;
    410 #undef fbt
    411 		return (0);
    412 
    413 	case WSDISPLAYIO_GETCMAP:
    414 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    415 
    416 	case WSDISPLAYIO_PUTCMAP:
    417 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    418 
    419 	case WSDISPLAYIO_SVIDEO:
    420 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    421 		if ((dc->dc_blanked == 0) ^ turnoff) {
    422 			dc->dc_blanked = turnoff;
    423 #if 0 /* XXX later XXX */
    424 		To turn off, assign value 0 in ASIC_VIDEO_VALID register.
    425 #endif	/* XXX XXX XXX */
    426 		}
    427 		return (0);
    428 
    429 	case WSDISPLAYIO_GVIDEO:
    430 		*(u_int *)data = dc->dc_blanked ?
    431 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    432 		return (0);
    433 
    434 	case WSDISPLAYIO_GCURPOS:
    435 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    436 		return (0);
    437 
    438 	case WSDISPLAYIO_SCURPOS:
    439 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    440 		bt459_set_curpos(sc);
    441 		return (0);
    442 
    443 	case WSDISPLAYIO_GCURMAX:
    444 		((struct wsdisplay_curpos *)data)->x =
    445 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    446 		return (0);
    447 
    448 	case WSDISPLAYIO_GCURSOR:
    449 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    450 
    451 	case WSDISPLAYIO_SCURSOR:
    452 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    453 	}
    454 	return ENOTTY;
    455 }
    456 
    457 int
    458 sfbmmap(v, offset, prot)
    459 	void *v;
    460 	off_t offset;
    461 	int prot;
    462 {
    463 	struct sfb_softc *sc = v;
    464 
    465 	if (offset >= SFB_SIZE || offset < 0)
    466 		return (-1);
    467 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    468 }
    469 
    470 int
    471 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    472 	void *v;
    473 	const struct wsscreen_descr *type;
    474 	void **cookiep;
    475 	int *curxp, *curyp;
    476 	long *attrp;
    477 {
    478 	struct sfb_softc *sc = v;
    479 	long defattr;
    480 
    481 	if (sc->nscreens > 0)
    482 		return (ENOMEM);
    483 
    484 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    485 	*curxp = 0;
    486 	*curyp = 0;
    487 	sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    488 	*attrp = defattr;
    489 	sc->nscreens++;
    490 	return (0);
    491 }
    492 
    493 void
    494 sfb_free_screen(v, cookie)
    495 	void *v;
    496 	void *cookie;
    497 {
    498 	struct sfb_softc *sc = v;
    499 
    500 	if (sc->sc_dc == &sfb_console_dc)
    501 		panic("sfb_free_screen: console");
    502 
    503 	sc->nscreens--;
    504 }
    505 
    506 void
    507 sfb_show_screen(v, cookie)
    508 	void *v;
    509 	void *cookie;
    510 {
    511 }
    512 
    513 int
    514 sfb_cnattach(addr)
    515         tc_addr_t addr;
    516 {
    517         struct fb_devconfig *dcp = &sfb_console_dc;
    518         long defattr;
    519 
    520         sfb_getdevconfig(addr, dcp);
    521 
    522         sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    523 
    524         wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
    525                            0, 0, defattr);
    526         sfb_consaddr = addr;
    527         return(0);
    528 }
    529 
    530 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 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_VIDEO_VALID) = 0;
    624 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    625 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    626 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;
    627 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;
    628 
    629 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    630 
    631 	SELECT(vdac, BT459_REG_COMMAND_0);
    632 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    633 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    634 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    635 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    636 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    637 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    638 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    639 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    640 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    641 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    642 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    643 
    644 	SELECT(vdac, BT459_REG_CCR);
    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 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    658 
    659 	/* build sane colormap */
    660 	SELECT(vdac, 0);
    661 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    662 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    663 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    664 	for (i = 1; i < CMAP_SIZE; i++) {
    665 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    666 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    667 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    668 	}
    669 
    670 	/* clear out cursor image */
    671 	SELECT(vdac, BT459_REG_CRAM_BASE);
    672 	for (i = 0; i < 1024; i++)
    673 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    674 
    675 	/*
    676 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    677 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    678 	 * image color.  CCOLOR_1 will be never used.
    679 	 */
    680 	SELECT(vdac, BT459_REG_CCOLOR_1);
    681 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    682 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    683 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    684 
    685 	REG(vdac, bt_reg) = 0;	tc_wmb();
    686 	REG(vdac, bt_reg) = 0;	tc_wmb();
    687 	REG(vdac, bt_reg) = 0;	tc_wmb();
    688 
    689 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    690 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    691 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    692 }
    693 
    694 static int
    695 get_cmap(sc, p)
    696 	struct sfb_softc *sc;
    697 	struct wsdisplay_cmap *p;
    698 {
    699 	u_int index = p->index, count = p->count;
    700 
    701 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    702 		return (EINVAL);
    703 
    704 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    705 	    !uvm_useracc(p->green, count, B_WRITE) ||
    706 	    !uvm_useracc(p->blue, count, B_WRITE))
    707 		return (EFAULT);
    708 
    709 	copyout(&sc->sc_cmap.r[index], p->red, count);
    710 	copyout(&sc->sc_cmap.g[index], p->green, count);
    711 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    712 
    713 	return (0);
    714 }
    715 
    716 static int
    717 set_cmap(sc, p)
    718 	struct sfb_softc *sc;
    719 	struct wsdisplay_cmap *p;
    720 {
    721 	u_int index = p->index, count = p->count;
    722 
    723 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    724 		return (EINVAL);
    725 
    726 	if (!uvm_useracc(p->red, count, B_READ) ||
    727 	    !uvm_useracc(p->green, count, B_READ) ||
    728 	    !uvm_useracc(p->blue, count, B_READ))
    729 		return (EFAULT);
    730 
    731 	copyin(p->red, &sc->sc_cmap.r[index], count);
    732 	copyin(p->green, &sc->sc_cmap.g[index], count);
    733 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    734 
    735 	sc->sc_changed |= DATA_CMAP_CHANGED;
    736 
    737 	return (0);
    738 }
    739 
    740 
    741 static int
    742 set_cursor(sc, p)
    743 	struct sfb_softc *sc;
    744 	struct wsdisplay_cursor *p;
    745 {
    746 #define	cc (&sc->sc_cursor)
    747 	int v, index, count, icount;
    748 
    749 	v = p->which;
    750 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    751 		index = p->cmap.index;
    752 		count = p->cmap.count;
    753 		if (index >= 2 || (index + count) > 2)
    754 			return (EINVAL);
    755 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    756 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    757 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    758 			return (EFAULT);
    759 	}
    760 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    761 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    762 			return (EINVAL);
    763 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    764 		if (!uvm_useracc(p->image, icount, B_READ) ||
    765 		    !uvm_useracc(p->mask, icount, B_READ))
    766 			return (EFAULT);
    767 	}
    768 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    769 		if (v & WSDISPLAY_CURSOR_DOCUR)
    770 			cc->cc_hot = p->hot;
    771 		if (v & WSDISPLAY_CURSOR_DOPOS)
    772 			set_curpos(sc, &p->pos);
    773 		bt459_set_curpos(sc);
    774 	}
    775 
    776 	sc->sc_changed = 0;
    777 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    778 		sc->sc_curenb = p->enable;
    779 		sc->sc_changed |= DATA_ENB_CHANGED;
    780 	}
    781 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    782 		copyin(p->cmap.red, &cc->cc_color[index], count);
    783 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    784 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    785 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    786 	}
    787 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    788 		cc->cc_size = p->size;
    789 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    790 		copyin(p->image, cc->cc_image, icount);
    791 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    792 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    793 	}
    794 
    795 	return (0);
    796 #undef cc
    797 }
    798 
    799 static int
    800 get_cursor(sc, p)
    801 	struct sfb_softc *sc;
    802 	struct wsdisplay_cursor *p;
    803 {
    804 	return (ENOTTY); /* XXX */
    805 }
    806 
    807 static void
    808 set_curpos(sc, curpos)
    809 	struct sfb_softc *sc;
    810 	struct wsdisplay_curpos *curpos;
    811 {
    812 	struct fb_devconfig *dc = sc->sc_dc;
    813 	int x = curpos->x, y = curpos->y;
    814 
    815 	if (y < 0)
    816 		y = 0;
    817 	else if (y > dc->dc_ht)
    818 		y = dc->dc_ht;
    819 	if (x < 0)
    820 		x = 0;
    821 	else if (x > dc->dc_wid)
    822 		x = dc->dc_wid;
    823 	sc->sc_cursor.cc_pos.x = x;
    824 	sc->sc_cursor.cc_pos.y = y;
    825 }
    826 
    827 static void
    828 bt459_set_curpos(sc)
    829 	struct sfb_softc *sc;
    830 {
    831 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    832 	caddr_t vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    833 	int x, y, s;
    834 
    835 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    836 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    837 
    838 	x += sc->sc_cursor.cc_magic.x;
    839 	y += sc->sc_cursor.cc_magic.y;
    840 
    841 	s = spltty();
    842 
    843 	SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    844 	REG(vdac, bt_reg) = x;		tc_wmb();
    845 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    846 	REG(vdac, bt_reg) = y;		tc_wmb();
    847 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    848 
    849 	splx(s);
    850 }
    851 
    852 #define	MODE_SIMPLE		0
    853 #define	MODE_OPAQUESTIPPLE	1
    854 #define	MODE_OPAQUELINE		2
    855 #define	MODE_TRANSPARENTSTIPPLE	5
    856 #define	MODE_TRANSPARENTLINE	6
    857 #define	MODE_COPY		7
    858 
    859 #define	SFBALIGNMASK		0x7
    860 #define	SFBSTIPPLEALL1		0xffffffff
    861 #define	SFBSTIPPLEBITS		32
    862 #define	SFBSTIPPLEBITMASK	0x1f
    863 #define	SFBSTIPPLEBYTESDONE	32
    864 
    865 /*
    866  * Paint (or unpaint) the cursor.
    867  */
    868 void
    869 sfb_cursor(id, on, row, col)
    870 	void *id;
    871 	int on, row, col;
    872 {
    873 	struct rcons *rc = id;
    874 	int x, y;
    875 
    876 	/* turn the cursor off */
    877 	if (!on) {
    878 		/* make sure it's on */
    879 		if ((rc->rc_bits & RC_CURSOR) == 0)
    880 			return;
    881 
    882 		row = *rc->rc_crowp;
    883 		col = *rc->rc_ccolp;
    884 	} else {
    885 		/* unpaint the old copy. */
    886 		*rc->rc_crowp = row;
    887 		*rc->rc_ccolp = col;
    888 	}
    889 
    890 	x = col * rc->rc_font->width + rc->rc_xorigin;
    891 	y = row * rc->rc_font->height + rc->rc_yorigin;
    892 
    893 	raster_op(rc->rc_sp, x, y,
    894 	    rc->rc_font->width, rc->rc_font->height,
    895 	    RAS_INVERT,
    896 	    (struct raster *) 0, 0, 0);
    897 
    898 	rc->rc_bits ^= RC_CURSOR;
    899 }
    900 
    901 /*
    902  * Actually write a string to the frame buffer.
    903  */
    904 int
    905 sfb_mapchar(id, uni, index)
    906 	void *id;
    907 	int uni;
    908 	unsigned int *index;
    909 {
    910 	if (uni < 128) {
    911 		*index = uni;
    912 		return (5);
    913 	}
    914 	*index = ' ';
    915 	return (0);
    916 }
    917 
    918 /*
    919  * Actually write a string to the frame buffer.
    920  */
    921 void
    922 sfb_putchar(id, row, col, uc, attr)
    923 	void *id;
    924 	int row, col;
    925 	u_int uc;
    926 	long attr;
    927 {
    928 	struct rcons *rc = id;
    929 	int x, y, op;
    930 	u_char help;
    931 
    932 	x = col * rc->rc_font->width + rc->rc_xorigin;
    933 	y = row * rc->rc_font->height + rc->rc_font_ascent + rc->rc_yorigin;
    934 
    935 	op = RAS_SRC;
    936 	if ((attr != 0) ^ ((rc->rc_bits & RC_INVERT) != 0))
    937 		op = RAS_NOT(op);
    938 	help = uc & 0xff;
    939 	raster_textn(rc->rc_sp, x, y, op, rc->rc_font, &help, 1);
    940 }
    941 
    942 /*
    943  * Copy characters in a line.
    944  */
    945 void
    946 sfb_copycols(id, row, srccol, dstcol, ncols)
    947 	void *id;
    948 	int row, srccol, dstcol, ncols;
    949 {
    950 	struct rcons *rc = id;
    951 	struct raster *rap = rc->rc_sp;
    952 	caddr_t sp, dp, basex, sfb;
    953 	int scanspan, height, width, aligns, alignd, w, y;
    954 	u_int32_t lmasks, rmasks, lmaskd, rmaskd;
    955 
    956 	scanspan = rap->linelongs * 4;
    957 	y = rc->rc_yorigin + rc->rc_font->height * row;
    958 	basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
    959 	height = rc->rc_font->height;
    960 	w = rc->rc_font->width * ncols;
    961 
    962 	dp = basex + rc->rc_font->width * dstcol;
    963 	alignd = (long)dp & SFBALIGNMASK;
    964 	dp -= alignd;
    965 	width = w + alignd;
    966 	lmaskd = SFBSTIPPLEALL1 << alignd;
    967 	rmaskd = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    968 
    969 	sp = basex + rc->rc_font->width * srccol;
    970 	aligns = (long)sp & SFBALIGNMASK;
    971 	sp -= aligns;
    972 	width = w + aligns;
    973 	lmasks = SFBSTIPPLEALL1 << aligns;
    974 	rmasks = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    975 
    976 	width += (-width & SFBSTIPPLEBITMASK);
    977 	sfb = rap->data;
    978 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
    979 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
    980 	*(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = alignd - aligns;
    981 
    982 	if (width <= SFBSTIPPLEBITS) {
    983 		lmasks = lmasks & rmasks;
    984 		lmaskd = lmaskd & rmaskd;
    985 		while (height > 0) {
    986 			*(u_int32_t *)sp = lmasks;
    987 			*(u_int32_t *)dp = lmaskd;
    988 			sp += scanspan;
    989 			dp += scanspan;
    990 			height--;
    991 		}
    992 	}
    993 	/* copy forward (left-to-right) */
    994 	else if (dstcol < srccol || srccol + ncols < dstcol) {
    995 		caddr_t sq = sp, dq = dp;
    996 
    997 		w = width;
    998 		while (height > 0) {
    999 			*(u_int32_t *)sp = lmasks;
   1000 			*(u_int32_t *)dp = lmaskd;
   1001 			width -= 2 * SFBSTIPPLEBITS;
   1002 			while (width > 0) {
   1003 				sp += SFBSTIPPLEBYTESDONE;
   1004 				dp += SFBSTIPPLEBYTESDONE;
   1005 				*(u_int32_t *)sp = SFBSTIPPLEALL1;
   1006 				*(u_int32_t *)dp = SFBSTIPPLEALL1;
   1007 				width -= SFBSTIPPLEBITS;
   1008 			}
   1009 			sp += SFBSTIPPLEBYTESDONE;
   1010 			dp += SFBSTIPPLEBYTESDONE;
   1011 			*(u_int32_t *)sp = rmasks;
   1012 			*(u_int32_t *)dp = rmaskd;
   1013 
   1014 			sp = (sq += scanspan);
   1015 			dp = (dq += scanspan);
   1016 			width = w;
   1017 			height--;
   1018 		}
   1019 	}
   1020 	/* copy backward (right-to-left) */
   1021 	else {
   1022 		caddr_t sq = (sp += width), dq = (dp += width);
   1023 
   1024 		w = width;
   1025 		while (height > 0) {
   1026 			*(u_int32_t *)sp = rmasks;
   1027 			*(u_int32_t *)dp = rmaskd;
   1028 			width -= 2 * SFBSTIPPLEBITS;
   1029 			while (width > 0) {
   1030 				sp -= SFBSTIPPLEBYTESDONE;
   1031 				dp -= SFBSTIPPLEBYTESDONE;
   1032 				*(u_int32_t *)sp = SFBSTIPPLEALL1;
   1033 				*(u_int32_t *)dp = SFBSTIPPLEALL1;
   1034 				width -= SFBSTIPPLEBITS;
   1035 			}
   1036 			sp -= SFBSTIPPLEBYTESDONE;
   1037 			dp -= SFBSTIPPLEBYTESDONE;
   1038 			*(u_int32_t *)sp = lmasks;
   1039 			*(u_int32_t *)dp = lmaskd;
   1040 
   1041 			sp = (sq += scanspan);
   1042 			dp = (dq += scanspan);
   1043 			width = w;
   1044 			height--;
   1045 		}
   1046 	}
   1047 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1048 }
   1049 
   1050 /*
   1051  * Clear characters in a line.
   1052  */
   1053 void
   1054 sfb_erasecols(id, row, startcol, ncols, fillattr)
   1055 	void *id;
   1056 	int row, startcol, ncols;
   1057 	long fillattr;
   1058 {
   1059 	struct rcons *rc = id;
   1060 	struct raster *rap = rc->rc_sp;
   1061 	caddr_t sfb, p;
   1062 	int scanspan, startx, height, width, align, w, y;
   1063 	u_int32_t lmask, rmask;
   1064 
   1065 	scanspan = rap->linelongs * 4;
   1066 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1067 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
   1068 	height = rc->rc_font->height;
   1069 	w = rc->rc_font->width * ncols;
   1070 
   1071 	p = (caddr_t)rap->pixels + y * scanspan + startx;
   1072 	align = (long)p & SFBALIGNMASK;
   1073 	p -= align;
   1074 	width = w + align;
   1075 	lmask = SFBSTIPPLEALL1 << align;
   1076 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1077 	sfb = rap->data;
   1078 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
   1079 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1080 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = (fillattr == 0) ? 0 : 0x01010101;
   1081 	if (width <= SFBSTIPPLEBITS) {
   1082 		lmask = lmask & rmask;
   1083 		while (height > 0) {
   1084 			*(u_int32_t *)(sfb + SFB_ASIC_ADDRESS) = (long)p;
   1085 			*(u_int32_t *)(sfb + SFB_ASIC_START) = lmask;
   1086 			p += scanspan;
   1087 			height--;
   1088 		}
   1089 	}
   1090 	else {
   1091 		caddr_t q = p;
   1092 		while (height > 0) {
   1093 			*(u_int32_t *)p = lmask;
   1094 			width -= 2 * SFBSTIPPLEBITS;
   1095 			while (width > 0) {
   1096 				p += SFBSTIPPLEBYTESDONE;
   1097 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1098 				width -= SFBSTIPPLEBITS;
   1099 			}
   1100 			p += SFBSTIPPLEBYTESDONE;
   1101 			*(u_int32_t *)p = rmask;
   1102 
   1103 			p = (q += scanspan);
   1104 			width = w + align;
   1105 			height--;
   1106 		}
   1107 	}
   1108 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1109 }
   1110 
   1111 /*
   1112  * Copy lines.
   1113  */
   1114 void
   1115 sfb_copyrows(id, srcrow, dstrow, nrows)
   1116 	void *id;
   1117 	int srcrow, dstrow, nrows;
   1118 {
   1119 	struct rcons *rc = id;
   1120 	struct raster *rap = rc->rc_sp;
   1121 	caddr_t sfb, p;
   1122 	int scanspan, offset, srcy, height, width, align, w;
   1123 	u_int32_t lmask, rmask;
   1124 
   1125 	scanspan = rap->linelongs * 4;
   1126 	height = rc->rc_font->height * nrows;
   1127 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1128 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1129 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1130 		scanspan = -scanspan;
   1131 		srcy += height;
   1132 	}
   1133 
   1134 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1135 	align = (long)p & SFBALIGNMASK;
   1136 	p -= align;
   1137 	w = rc->rc_font->width * rc->rc_maxcol;
   1138 	width = w + align;
   1139 	lmask = SFBSTIPPLEALL1 << align;
   1140 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1141 	sfb = rap->data;
   1142 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
   1143 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1144 	*(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = 0;
   1145 	if (width <= SFBSTIPPLEBITS) {
   1146 		/* never happens */;
   1147 	}
   1148 	else {
   1149 		caddr_t q = p;
   1150 		while (height > 0) {
   1151 			*(u_int32_t *)p = lmask;
   1152 			*(u_int32_t *)(p + offset) = lmask;
   1153 			width -= 2 * SFBSTIPPLEBITS;
   1154 			while (width > 0) {
   1155 				p += SFBSTIPPLEBYTESDONE;
   1156 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1157 				*(u_int32_t *)(p + offset) = SFBSTIPPLEALL1;
   1158 				width -= SFBSTIPPLEBITS;
   1159 			}
   1160 			p += SFBSTIPPLEBYTESDONE;
   1161 			*(u_int32_t *)p = rmask;
   1162 			*(u_int32_t *)(p + offset) = rmask;
   1163 
   1164 			p = (q += scanspan);
   1165 			width = w + align;
   1166 			height--;
   1167 		}
   1168 	}
   1169 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1170 }
   1171 
   1172 /*
   1173  * Erase lines.
   1174  */
   1175 void
   1176 sfb_eraserows(id, startrow, nrows, fillattr)
   1177 	void *id;
   1178 	int startrow, nrows;
   1179 	long fillattr;
   1180 {
   1181 	struct rcons *rc = id;
   1182 	struct raster *rap = rc->rc_sp;
   1183 	caddr_t sfb, p;
   1184 	int scanspan, starty, height, width, align, w;
   1185 	u_int32_t lmask, rmask;
   1186 
   1187 	scanspan = rap->linelongs * 4;
   1188 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1189 	height = rc->rc_font->height * nrows;
   1190 
   1191 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1192 	align = (long)p & SFBALIGNMASK;
   1193 	p -= align;
   1194 	w = rc->rc_font->width * rc->rc_maxcol;
   1195 	width = w + align;
   1196 	lmask = SFBSTIPPLEALL1 << align;
   1197 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1198 	sfb = rap->data;
   1199 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
   1200 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1201 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = (fillattr == 0) ? 0 : 0x01010101;
   1202 	if (width <= SFBSTIPPLEBITS) {
   1203 		/* never happens */;
   1204 	}
   1205 	else {
   1206 		caddr_t q = p;
   1207 		while (height > 0) {
   1208 			*(u_int32_t *)p = lmask;
   1209 			width -= 2 * SFBSTIPPLEBITS;
   1210 			while (width > 0) {
   1211 				p += SFBSTIPPLEBYTESDONE;
   1212 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1213 				width -= SFBSTIPPLEBITS;
   1214 			}
   1215 			p += SFBSTIPPLEBYTESDONE;
   1216 			*(u_int32_t *)p = rmask;
   1217 
   1218 			p = (q += scanspan);
   1219 			width = w + align;
   1220 			height--;
   1221 		}
   1222 	}
   1223 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1224 }
   1225 
   1226 int
   1227 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1228 	void *id;
   1229 	int fg, bg, flags;
   1230 	long *attrp;
   1231 {
   1232 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1233 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1234 		return (EINVAL);
   1235 	if (flags & WSATTR_REVERSE)
   1236 		*attrp = 1;
   1237 	else
   1238 		*attrp = 0;
   1239 	return (0);
   1240 }
   1241