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