Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.17
      1 /* $NetBSD: sfb.c,v 1.17 1999/06/11 01:44:47 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.17 1999/06/11 01:44:47 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 #define bt_lo	0
     94 #define bt_hi	1
     95 #define bt_reg	2
     96 #define bt_cmap 3
     97 
     98 #define REG(base, index)	*((u_int32_t *)(base) + (index))
     99 #define SELECT(vdac, regno) do {			\
    100 	REG(vdac, bt_lo) = ((regno) & 0x00ff);		\
    101 	REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8;	\
    102 	tc_wmb();					\
    103    } while (0)
    104 
    105 struct fb_devconfig {
    106 	vaddr_t dc_vaddr;		/* memory space virtual base address */
    107 	paddr_t dc_paddr;		/* memory space physical base address */
    108 	vsize_t dc_size;		/* size of slot memory */
    109 	int	dc_wid;			/* width of frame buffer */
    110 	int	dc_ht;			/* height of frame buffer */
    111 	int	dc_depth;		/* depth, bits per pixel */
    112 	int	dc_rowbytes;		/* bytes in a FB scan line */
    113 	vaddr_t	dc_videobase;		/* base of flat frame buffer */
    114 	struct raster	dc_raster;	/* raster description */
    115 	struct rcons	dc_rcons;	/* raster blitter control info */
    116 	int	    dc_blanked;		/* currently has video disabled */
    117 };
    118 
    119 struct hwcmap256 {
    120 #define	CMAP_SIZE	256	/* 256 R/G/B entries */
    121 	u_int8_t r[CMAP_SIZE];
    122 	u_int8_t g[CMAP_SIZE];
    123 	u_int8_t b[CMAP_SIZE];
    124 };
    125 
    126 struct hwcursor64 {
    127 	struct wsdisplay_curpos cc_pos;
    128 	struct wsdisplay_curpos cc_hot;
    129 	struct wsdisplay_curpos cc_size;
    130 	struct wsdisplay_curpos cc_magic;
    131 #define	CURSOR_MAX_SIZE	64
    132 	u_int8_t cc_color[6];
    133 	u_int64_t cc_image[64 + 64];
    134 };
    135 
    136 struct sfb_softc {
    137 	struct device sc_dev;
    138 	struct fb_devconfig *sc_dc;	/* device configuration */
    139 	struct hwcmap256 sc_cmap;	/* software copy of colormap */
    140 	struct hwcursor64 sc_cursor;	/* software copy of cursor */
    141 	int sc_curenb;			/* cursor sprite enabled */
    142 	int sc_changed;			/* need update of colormap */
    143 #define	DATA_ENB_CHANGED	0x01	/* cursor enable changed */
    144 #define	DATA_CURCMAP_CHANGED	0x02	/* cursor colormap changed */
    145 #define	DATA_CURSHAPE_CHANGED	0x04	/* cursor size, image, mask changed */
    146 #define	DATA_CMAP_CHANGED	0x08	/* colormap changed */
    147 #define	DATA_ALL_CHANGED	0x0f
    148 	int nscreens;
    149 };
    150 
    151 #define	HX_MAGIC_X 368
    152 #define	HX_MAGIC_Y 38
    153 
    154 int  sfbmatch __P((struct device *, struct cfdata *, void *));
    155 void sfbattach __P((struct device *, struct device *, void *));
    156 
    157 struct cfattach sfb_ca = {
    158 	sizeof(struct sfb_softc), sfbmatch, sfbattach,
    159 };
    160 
    161 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    162 struct fb_devconfig sfb_console_dc;
    163 tc_addr_t sfb_consaddr;
    164 
    165 void	sfb_cursor __P((void *, int, int, int));
    166 int	sfb_mapchar __P((void *, int, unsigned int *));
    167 void	sfb_putchar __P((void *, int, int, u_int, long));
    168 void	sfb_copycols __P((void *, int, int, int, int));
    169 void	sfb_erasecols __P((void *, int, int, int, long));
    170 void	sfb_copyrows __P((void *, int, int, int));
    171 void	sfb_eraserows __P((void *, int, int, long));
    172 int	sfb_alloc_attr __P((void *, int, int, int, long *));
    173 #define	rcons_alloc_attr sfb_alloc_attr
    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 	vbase  = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) & 0x1ff;
    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 			/* XXX later XXX */
    424 		}
    425 		return (0);
    426 
    427 	case WSDISPLAYIO_GVIDEO:
    428 		*(u_int *)data = dc->dc_blanked ?
    429 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    430 		return (0);
    431 
    432 	case WSDISPLAYIO_GCURPOS:
    433 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    434 		return (0);
    435 
    436 	case WSDISPLAYIO_SCURPOS:
    437 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    438 		bt459_set_curpos(sc);
    439 		return (0);
    440 
    441 	case WSDISPLAYIO_GCURMAX:
    442 		((struct wsdisplay_curpos *)data)->x =
    443 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    444 		return (0);
    445 
    446 	case WSDISPLAYIO_GCURSOR:
    447 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    448 
    449 	case WSDISPLAYIO_SCURSOR:
    450 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    451 	}
    452 	return ENOTTY;
    453 }
    454 
    455 int
    456 sfbmmap(v, offset, prot)
    457 	void *v;
    458 	off_t offset;
    459 	int prot;
    460 {
    461 	struct sfb_softc *sc = v;
    462 
    463 	if (offset >= SFB_SIZE || offset < 0)
    464 		return (-1);
    465 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    466 }
    467 
    468 int
    469 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    470 	void *v;
    471 	const struct wsscreen_descr *type;
    472 	void **cookiep;
    473 	int *curxp, *curyp;
    474 	long *attrp;
    475 {
    476 	struct sfb_softc *sc = v;
    477 	long defattr;
    478 
    479 	if (sc->nscreens > 0)
    480 		return (ENOMEM);
    481 
    482 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    483 	*curxp = 0;
    484 	*curyp = 0;
    485 	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    486 	*attrp = defattr;
    487 	sc->nscreens++;
    488 	return (0);
    489 }
    490 
    491 void
    492 sfb_free_screen(v, cookie)
    493 	void *v;
    494 	void *cookie;
    495 {
    496 	struct sfb_softc *sc = v;
    497 
    498 	if (sc->sc_dc == &sfb_console_dc)
    499 		panic("sfb_free_screen: console");
    500 
    501 	sc->nscreens--;
    502 }
    503 
    504 void
    505 sfb_show_screen(v, cookie)
    506 	void *v;
    507 	void *cookie;
    508 {
    509 }
    510 
    511 int
    512 sfb_cnattach(addr)
    513         tc_addr_t addr;
    514 {
    515         struct fb_devconfig *dcp = &sfb_console_dc;
    516         long defattr;
    517 
    518         sfb_getdevconfig(addr, dcp);
    519 
    520         rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    521 
    522         wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
    523                            0, 0, defattr);
    524         sfb_consaddr = addr;
    525         return(0);
    526 }
    527 
    528 int
    529 sfbintr(arg)
    530 	void *arg;
    531 {
    532 	struct sfb_softc *sc = arg;
    533 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    534 	caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
    535 	caddr_t vdac;
    536 	int v;
    537 
    538 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    539 	/* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
    540 
    541 	if (sc->sc_changed == 0)
    542 		return (1);
    543 
    544 	vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    545 	v = sc->sc_changed;
    546 	sc->sc_changed = 0;
    547 
    548 	if (v & DATA_ENB_CHANGED) {
    549 		SELECT(vdac, BT459_REG_CCR);
    550 		REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
    551 	}
    552 	if (v & DATA_CURCMAP_CHANGED) {
    553 		u_int8_t *cp = sc->sc_cursor.cc_color;
    554 
    555 		SELECT(vdac, BT459_REG_CCOLOR_2);
    556 		REG(vdac, bt_reg) = cp[1];	tc_wmb();
    557 		REG(vdac, bt_reg) = cp[3];	tc_wmb();
    558 		REG(vdac, bt_reg) = cp[5];	tc_wmb();
    559 
    560 		REG(vdac, bt_reg) = cp[0];	tc_wmb();
    561 		REG(vdac, bt_reg) = cp[2];	tc_wmb();
    562 		REG(vdac, bt_reg) = cp[4];	tc_wmb();
    563 	}
    564 	if (v & DATA_CURSHAPE_CHANGED) {
    565 		u_int8_t *ip, *mp, img, msk;
    566 		u_int8_t u;
    567 		int bcnt;
    568 
    569 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    570 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    571 
    572 		bcnt = 0;
    573 		SELECT(vdac, BT459_REG_CRAM_BASE+0);
    574 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    575 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    576 			/* pad right half 32 pixel when smaller than 33 */
    577 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    578 				REG(vdac, bt_reg) = 0; tc_wmb();
    579 				REG(vdac, bt_reg) = 0; tc_wmb();
    580 			}
    581 			else {
    582 				img = *ip++;
    583 				msk = *mp++;
    584 				img &= msk;	/* cookie off image */
    585 				u = (msk & 0x0f) << 4 | (img & 0x0f);
    586 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    587 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
    588 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    589 			}
    590 			bcnt += 2;
    591 		}
    592 		/* pad unoccupied scan lines */
    593 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    594 			REG(vdac, bt_reg) = 0; tc_wmb();
    595 			REG(vdac, bt_reg) = 0; tc_wmb();
    596 			bcnt += 2;
    597 		}
    598 	}
    599 	if (v & DATA_CMAP_CHANGED) {
    600 		struct hwcmap256 *cm = &sc->sc_cmap;
    601 		int index;
    602 
    603 		SELECT(vdac, 0);
    604 		for (index = 0; index < CMAP_SIZE; index++) {
    605 			REG(vdac, bt_cmap) = cm->r[index];	tc_wmb();
    606 			REG(vdac, bt_cmap) = cm->g[index];	tc_wmb();
    607 			REG(vdac, bt_cmap) = cm->b[index];	tc_wmb();
    608 		}
    609 	}
    610 	return (1);
    611 }
    612 
    613 void
    614 sfbinit(dc)
    615 	struct fb_devconfig *dc;
    616 {
    617 	caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    618 	caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
    619 	int i;
    620 
    621 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 0;
    622 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    623 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    624 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;
    625 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;
    626 
    627 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    628 
    629 	SELECT(vdac, BT459_REG_COMMAND_0);
    630 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    631 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    632 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    633 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    634 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    635 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    636 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    637 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    638 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    639 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    640 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    641 
    642 	SELECT(vdac, BT459_REG_CCR);
    643 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    644 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    645 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    646 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    647 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    648 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    649 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    650 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    651 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    652 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    653 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    654 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    655 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    656 
    657 	/* build sane colormap */
    658 	SELECT(vdac, 0);
    659 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    660 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    661 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    662 	for (i = 1; i < CMAP_SIZE; i++) {
    663 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    664 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    665 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    666 	}
    667 
    668 	/* clear out cursor image */
    669 	SELECT(vdac, BT459_REG_CRAM_BASE);
    670 	for (i = 0; i < 1024; i++)
    671 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    672 
    673 	/*
    674 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    675 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    676 	 * image color.  CCOLOR_1 will be never used.
    677 	 */
    678 	SELECT(vdac, BT459_REG_CCOLOR_1);
    679 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    680 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    681 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    682 
    683 	REG(vdac, bt_reg) = 0;	tc_wmb();
    684 	REG(vdac, bt_reg) = 0;	tc_wmb();
    685 	REG(vdac, bt_reg) = 0;	tc_wmb();
    686 
    687 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    688 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    689 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    690 }
    691 
    692 static int
    693 get_cmap(sc, p)
    694 	struct sfb_softc *sc;
    695 	struct wsdisplay_cmap *p;
    696 {
    697 	u_int index = p->index, count = p->count;
    698 
    699 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    700 		return (EINVAL);
    701 
    702 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    703 	    !uvm_useracc(p->green, count, B_WRITE) ||
    704 	    !uvm_useracc(p->blue, count, B_WRITE))
    705 		return (EFAULT);
    706 
    707 	copyout(&sc->sc_cmap.r[index], p->red, count);
    708 	copyout(&sc->sc_cmap.g[index], p->green, count);
    709 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    710 
    711 	return (0);
    712 }
    713 
    714 static int
    715 set_cmap(sc, p)
    716 	struct sfb_softc *sc;
    717 	struct wsdisplay_cmap *p;
    718 {
    719 	u_int index = p->index, count = p->count;
    720 
    721 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    722 		return (EINVAL);
    723 
    724 	if (!uvm_useracc(p->red, count, B_READ) ||
    725 	    !uvm_useracc(p->green, count, B_READ) ||
    726 	    !uvm_useracc(p->blue, count, B_READ))
    727 		return (EFAULT);
    728 
    729 	copyin(p->red, &sc->sc_cmap.r[index], count);
    730 	copyin(p->green, &sc->sc_cmap.g[index], count);
    731 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    732 
    733 	sc->sc_changed |= DATA_CMAP_CHANGED;
    734 
    735 	return (0);
    736 }
    737 
    738 
    739 static int
    740 set_cursor(sc, p)
    741 	struct sfb_softc *sc;
    742 	struct wsdisplay_cursor *p;
    743 {
    744 #define	cc (&sc->sc_cursor)
    745 	int v, index, count, icount;
    746 
    747 	v = p->which;
    748 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    749 		index = p->cmap.index;
    750 		count = p->cmap.count;
    751 		if (index >= 2 || (index + count) > 2)
    752 			return (EINVAL);
    753 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    754 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    755 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    756 			return (EFAULT);
    757 	}
    758 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    759 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    760 			return (EINVAL);
    761 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    762 		if (!uvm_useracc(p->image, icount, B_READ) ||
    763 		    !uvm_useracc(p->mask, icount, B_READ))
    764 			return (EFAULT);
    765 	}
    766 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    767 		if (v & WSDISPLAY_CURSOR_DOCUR)
    768 			cc->cc_hot = p->hot;
    769 		if (v & WSDISPLAY_CURSOR_DOPOS)
    770 			set_curpos(sc, &p->pos);
    771 		bt459_set_curpos(sc);
    772 	}
    773 
    774 	sc->sc_changed = 0;
    775 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    776 		sc->sc_curenb = p->enable;
    777 		sc->sc_changed |= DATA_ENB_CHANGED;
    778 	}
    779 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    780 		copyin(p->cmap.red, &cc->cc_color[index], count);
    781 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    782 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    783 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    784 	}
    785 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    786 		cc->cc_size = p->size;
    787 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    788 		copyin(p->image, cc->cc_image, icount);
    789 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    790 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    791 	}
    792 
    793 	return (0);
    794 #undef cc
    795 }
    796 
    797 static int
    798 get_cursor(sc, p)
    799 	struct sfb_softc *sc;
    800 	struct wsdisplay_cursor *p;
    801 {
    802 	return (ENOTTY); /* XXX */
    803 }
    804 
    805 static void
    806 set_curpos(sc, curpos)
    807 	struct sfb_softc *sc;
    808 	struct wsdisplay_curpos *curpos;
    809 {
    810 	struct fb_devconfig *dc = sc->sc_dc;
    811 	int x = curpos->x, y = curpos->y;
    812 
    813 	if (y < 0)
    814 		y = 0;
    815 	else if (y > dc->dc_ht)
    816 		y = dc->dc_ht;
    817 	if (x < 0)
    818 		x = 0;
    819 	else if (x > dc->dc_wid)
    820 		x = dc->dc_wid;
    821 	sc->sc_cursor.cc_pos.x = x;
    822 	sc->sc_cursor.cc_pos.y = y;
    823 }
    824 
    825 static void
    826 bt459_set_curpos(sc)
    827 	struct sfb_softc *sc;
    828 {
    829 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    830 	caddr_t vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    831 	int x, y, s;
    832 
    833 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    834 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    835 
    836 	x += sc->sc_cursor.cc_magic.x;
    837 	y += sc->sc_cursor.cc_magic.y;
    838 
    839 	s = spltty();
    840 
    841 	SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    842 	REG(vdac, bt_reg) = x;		tc_wmb();
    843 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    844 	REG(vdac, bt_reg) = y;		tc_wmb();
    845 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    846 
    847 	splx(s);
    848 }
    849 
    850 #define	MODE_SIMPLE		0
    851 #define	MODE_OPAQUESTIPPLE	1
    852 #define	MODE_OPAQUELINE		2
    853 #define	MODE_TRANSPARENTSTIPPLE	5
    854 #define	MODE_TRANSPARENTLINE	6
    855 #define	MODE_COPY		7
    856 
    857 #define	SFBALIGNMASK		0x7
    858 #define	SFBSTIPPLEALL1		0xffffffff
    859 #define	SFBSTIPPLEBITS		32
    860 #define	SFBSTIPPLEBITMASK	0x1f
    861 #define	SFBSTIPPLEBYTESDONE	32
    862 
    863 /*
    864  * Paint (or unpaint) the cursor.
    865  */
    866 void
    867 sfb_cursor(id, on, row, col)
    868 	void *id;
    869 	int on, row, col;
    870 {
    871 	struct rcons *rc = id;
    872 	int x, y;
    873 
    874 	/* turn the cursor off */
    875 	if (!on) {
    876 		/* make sure it's on */
    877 		if ((rc->rc_bits & RC_CURSOR) == 0)
    878 			return;
    879 
    880 		row = *rc->rc_crowp;
    881 		col = *rc->rc_ccolp;
    882 	} else {
    883 		/* unpaint the old copy. */
    884 		*rc->rc_crowp = row;
    885 		*rc->rc_ccolp = col;
    886 	}
    887 
    888 	x = col * rc->rc_font->width + rc->rc_xorigin;
    889 	y = row * rc->rc_font->height + rc->rc_yorigin;
    890 
    891 	raster_op(rc->rc_sp, x, y,
    892 	    rc->rc_font->width, rc->rc_font->height,
    893 	    RAS_INVERT,
    894 	    (struct raster *) 0, 0, 0);
    895 
    896 	rc->rc_bits ^= RC_CURSOR;
    897 }
    898 
    899 /*
    900  * Actually write a string to the frame buffer.
    901  */
    902 int
    903 sfb_mapchar(id, uni, index)
    904 	void *id;
    905 	int uni;
    906 	unsigned int *index;
    907 {
    908 	if (uni < 128) {
    909 		*index = uni;
    910 		return (5);
    911 	}
    912 	*index = ' ';
    913 	return (0);
    914 }
    915 
    916 /*
    917  * Actually write a string to the frame buffer.
    918  */
    919 void
    920 sfb_putchar(id, row, col, uc, attr)
    921 	void *id;
    922 	int row, col;
    923 	u_int uc;
    924 	long attr;
    925 {
    926 	struct rcons *rc = id;
    927 	int x, y, op;
    928 	u_char help;
    929 
    930 	x = col * rc->rc_font->width + rc->rc_xorigin;
    931 	y = row * rc->rc_font->height + rc->rc_font_ascent + rc->rc_yorigin;
    932 
    933 	op = RAS_SRC;
    934 	if ((attr != 0) ^ ((rc->rc_bits & RC_INVERT) != 0))
    935 		op = RAS_NOT(op);
    936 	help = uc & 0xff;
    937 	raster_textn(rc->rc_sp, x, y, op, rc->rc_font, &help, 1);
    938 }
    939 
    940 /*
    941  * Copy characters in a line.
    942  */
    943 void
    944 sfb_copycols(id, row, srccol, dstcol, ncols)
    945 	void *id;
    946 	int row, srccol, dstcol, ncols;
    947 {
    948 	struct rcons *rc = id;
    949 	struct raster *rap = rc->rc_sp;
    950 	caddr_t sp, dp, basex, sfb;
    951 	int scanspan, height, width, aligns, alignd, w, y;
    952 	u_int32_t lmasks, rmasks, lmaskd, rmaskd;
    953 
    954 	scanspan = rap->linelongs * 4;
    955 	y = rc->rc_yorigin + rc->rc_font->height * row;
    956 	basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
    957 	height = rc->rc_font->height;
    958 	w = rc->rc_font->width * ncols;
    959 
    960 	dp = basex + rc->rc_font->width * dstcol;
    961 	alignd = (long)dp & SFBALIGNMASK;
    962 	dp -= alignd;
    963 	width = w + alignd;
    964 	lmaskd = SFBSTIPPLEALL1 << alignd;
    965 	rmaskd = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    966 
    967 	sp = basex + rc->rc_font->width * srccol;
    968 	aligns = (long)sp & SFBALIGNMASK;
    969 	sp -= aligns;
    970 	width = w + aligns;
    971 	lmasks = SFBSTIPPLEALL1 << aligns;
    972 	rmasks = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    973 
    974 	width += (-width & SFBSTIPPLEBITMASK);
    975 	sfb = rap->data;
    976 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
    977 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
    978 	*(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = alignd - aligns;
    979 
    980 	if (width <= SFBSTIPPLEBITS) {
    981 		while (height > 0) {
    982 			*(u_int32_t *)sp = lmasks & rmasks;
    983 			*(u_int32_t *)dp = lmaskd & rmaskd;
    984 			sp += scanspan;
    985 			dp += scanspan;
    986 			height--;
    987 		}
    988 	}
    989 	/* copy forward (left-to-right) */
    990 	else if (dstcol < srccol || srccol + ncols < dstcol) {
    991 		caddr_t sq = sp, dq = dp;
    992 
    993 		w = width;
    994 		while (height > 0) {
    995 			*(u_int32_t *)sp = lmasks;
    996 			*(u_int32_t *)dp = lmaskd;
    997 			width -= 2 * SFBSTIPPLEBITS;
    998 			while (width > 0) {
    999 				sp += SFBSTIPPLEBYTESDONE;
   1000 				dp += SFBSTIPPLEBYTESDONE;
   1001 				*(u_int32_t *)sp = SFBSTIPPLEALL1;
   1002 				*(u_int32_t *)dp = SFBSTIPPLEALL1;
   1003 				width -= SFBSTIPPLEBITS;
   1004 			}
   1005 			sp += SFBSTIPPLEBYTESDONE;
   1006 			dp += SFBSTIPPLEBYTESDONE;
   1007 			*(u_int32_t *)sp = rmasks;
   1008 			*(u_int32_t *)dp = rmaskd;
   1009 
   1010 			sp = (sq += scanspan);
   1011 			dp = (dq += scanspan);
   1012 			width = w;
   1013 			height--;
   1014 		}
   1015 	}
   1016 	/* copy backward (right-to-left) */
   1017 	else {
   1018 		caddr_t sq = (sp += width), dq = (dp += width);
   1019 
   1020 		w = width;
   1021 		while (height > 0) {
   1022 			*(u_int32_t *)sp = rmasks;
   1023 			*(u_int32_t *)dp = rmaskd;
   1024 			width -= 2 * SFBSTIPPLEBITS;
   1025 			while (width > 0) {
   1026 				sp -= SFBSTIPPLEBYTESDONE;
   1027 				dp -= SFBSTIPPLEBYTESDONE;
   1028 				*(u_int32_t *)sp = SFBSTIPPLEALL1;
   1029 				*(u_int32_t *)dp = SFBSTIPPLEALL1;
   1030 				width -= SFBSTIPPLEBITS;
   1031 			}
   1032 			sp -= SFBSTIPPLEBYTESDONE;
   1033 			dp -= SFBSTIPPLEBYTESDONE;
   1034 			*(u_int32_t *)sp = lmasks;
   1035 			*(u_int32_t *)dp = lmaskd;
   1036 
   1037 			sp = (sq += scanspan);
   1038 			dp = (dq += scanspan);
   1039 			width = w;
   1040 			height--;
   1041 		}
   1042 	}
   1043 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1044 }
   1045 
   1046 /*
   1047  * Clear characters in a line.
   1048  */
   1049 void
   1050 sfb_erasecols(id, row, startcol, ncols, fillattr)
   1051 	void *id;
   1052 	int row, startcol, ncols;
   1053 	long fillattr;
   1054 {
   1055 	struct rcons *rc = id;
   1056 	struct raster *rap = rc->rc_sp;
   1057 	caddr_t sfb, p;
   1058 	int scanspan, startx, height, width, align, w, y;
   1059 	u_int32_t lmask, rmask;
   1060 
   1061 	scanspan = rap->linelongs * 4;
   1062 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1063 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
   1064 	height = rc->rc_font->height;
   1065 	w = rc->rc_font->width * ncols;
   1066 
   1067 	p = (caddr_t)rap->pixels + y * scanspan + startx;
   1068 	align = (long)p & SFBALIGNMASK;
   1069 	p -= align;
   1070 	width = w + align;
   1071 	lmask = SFBSTIPPLEALL1 << align;
   1072 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1073 	sfb = rap->data;
   1074 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
   1075 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1076 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = 0;
   1077 	if (width <= SFBSTIPPLEBITS) {
   1078 		while (height > 0) {
   1079 			*(u_int32_t *)(sfb + SFB_ASIC_ADDRESS) = (long)p;
   1080 			*(u_int32_t *)(sfb + SFB_ASIC_START) = lmask & rmask;
   1081 			p += scanspan;
   1082 			height--;
   1083 		}
   1084 	}
   1085 	else {
   1086 		caddr_t q = p;
   1087 		while (height > 0) {
   1088 			*(u_int32_t *)p = lmask;
   1089 			width -= 2 * SFBSTIPPLEBITS;
   1090 			while (width > 0) {
   1091 				p += SFBSTIPPLEBYTESDONE;
   1092 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1093 				width -= SFBSTIPPLEBITS;
   1094 			}
   1095 			p += SFBSTIPPLEBYTESDONE;
   1096 			*(u_int32_t *)p = rmask;
   1097 
   1098 			p = (q += scanspan);
   1099 			width = w + align;
   1100 			height--;
   1101 		}
   1102 	}
   1103 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1104 }
   1105 
   1106 /*
   1107  * Copy lines.
   1108  */
   1109 void
   1110 sfb_copyrows(id, srcrow, dstrow, nrows)
   1111 	void *id;
   1112 	int srcrow, dstrow, nrows;
   1113 {
   1114 	struct rcons *rc = id;
   1115 	struct raster *rap = rc->rc_sp;
   1116 	caddr_t sfb, p;
   1117 	int scanspan, offset, srcy, height, width, align, w;
   1118 	u_int32_t lmask, rmask;
   1119 
   1120 	scanspan = rap->linelongs * 4;
   1121 	height = rc->rc_font->height * nrows;
   1122 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1123 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1124 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1125 		scanspan = -scanspan;
   1126 		srcy += height;
   1127 	}
   1128 
   1129 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1130 	align = (long)p & SFBALIGNMASK;
   1131 	p -= align;
   1132 	w = rc->rc_font->width * rc->rc_maxcol;
   1133 	width = w + align;
   1134 	lmask = SFBSTIPPLEALL1 << align;
   1135 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1136 	sfb = rap->data;
   1137 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
   1138 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1139 	*(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = 0;
   1140 	if (width <= SFBSTIPPLEBITS) {
   1141 		/* never happens */;
   1142 	}
   1143 	else {
   1144 		caddr_t q = p;
   1145 		while (height > 0) {
   1146 			*(u_int32_t *)p = lmask;
   1147 			*(u_int32_t *)(p + offset) = lmask;
   1148 			width -= 2 * SFBSTIPPLEBITS;
   1149 			while (width > 0) {
   1150 				p += SFBSTIPPLEBYTESDONE;
   1151 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1152 				*(u_int32_t *)(p + offset) = SFBSTIPPLEALL1;
   1153 				width -= SFBSTIPPLEBITS;
   1154 			}
   1155 			p += SFBSTIPPLEBYTESDONE;
   1156 			*(u_int32_t *)p = rmask;
   1157 			*(u_int32_t *)(p + offset) = rmask;
   1158 
   1159 			p = (q += scanspan);
   1160 			width = w + align;
   1161 			height--;
   1162 		}
   1163 	}
   1164 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1165 }
   1166 
   1167 /*
   1168  * Erase characters in a line.
   1169  */
   1170 void
   1171 sfb_eraserows(id, startrow, nrows, fillattr)
   1172 	void *id;
   1173 	int startrow, nrows;
   1174 	long fillattr;
   1175 {
   1176 	struct rcons *rc = id;
   1177 	struct raster *rap = rc->rc_sp;
   1178 	caddr_t sfb, p;
   1179 	int scanspan, starty, height, width, align, w;
   1180 	u_int32_t lmask, rmask;
   1181 
   1182 	scanspan = rap->linelongs * 4;
   1183 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1184 	height = rc->rc_font->height * nrows;
   1185 
   1186 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1187 	align = (long)p & SFBALIGNMASK;
   1188 	p -= align;
   1189 	w = rc->rc_font->width * rc->rc_maxcol;
   1190 	width = w + align;
   1191 	lmask = SFBSTIPPLEALL1 << align;
   1192 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1193 	sfb = rap->data;
   1194 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
   1195 	*(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
   1196 	*(u_int32_t *)(sfb + SFB_ASIC_FG) = 0;
   1197 	if (width <= SFBSTIPPLEBITS) {
   1198 		/* never happens */;
   1199 	}
   1200 	else {
   1201 		caddr_t q = p;
   1202 		while (height > 0) {
   1203 			*(u_int32_t *)p = lmask;
   1204 			width -= 2 * SFBSTIPPLEBITS;
   1205 			while (width > 0) {
   1206 				p += SFBSTIPPLEBYTESDONE;
   1207 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1208 				width -= SFBSTIPPLEBITS;
   1209 			}
   1210 			p += SFBSTIPPLEBYTESDONE;
   1211 			*(u_int32_t *)p = rmask;
   1212 
   1213 			p = (q += scanspan);
   1214 			width = w + align;
   1215 			height--;
   1216 		}
   1217 	}
   1218 	*(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
   1219 }
   1220 
   1221 int
   1222 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1223 	void *id;
   1224 	int fg, bg, flags;
   1225 	long *attrp;
   1226 {
   1227 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1228 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1229 		return (EINVAL);
   1230 	if (flags & WSATTR_REVERSE)
   1231 		*attrp = 1;
   1232 	else
   1233 		*attrp = 0;
   1234 	return (0);
   1235 }
   1236