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