Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.27
      1 /* $NetBSD: sfb.c,v 1.27 1999/11/29 07:50:54 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.27 1999/11/29 07:50:54 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 static int  sfbmatch __P((struct device *, struct cfdata *, void *));
    156 static void sfbattach __P((struct device *, struct device *, void *));
    157 
    158 const struct cfattach sfb_ca = {
    159 	sizeof(struct sfb_softc), sfbmatch, sfbattach,
    160 };
    161 
    162 static void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
    163 static struct fb_devconfig sfb_console_dc;
    164 static tc_addr_t sfb_consaddr;
    165 
    166 static void sfb_cursor __P((void *, int, int, int));
    167 static int  sfb_mapchar __P((void *, int, unsigned int *));
    168 static void sfb_putchar __P((void *, int, int, u_int, long));
    169 static void sfb_copycols __P((void *, int, int, int, int));
    170 static void sfb_erasecols __P((void *, int, int, int, long));
    171 static void sfb_copyrows __P((void *, int, int, int));
    172 static void sfb_eraserows __P((void *, int, int, long));
    173 static int  sfb_alloc_attr __P((void *, int, int, int, long *));
    174 
    175 static const 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 static struct wsscreen_descr sfb_stdscreen = {
    187 	"std", 0, 0,
    188 	&sfb_emulops,
    189 	0, 0,
    190 	WSSCREEN_REVERSE
    191 };
    192 
    193 static const struct wsscreen_descr *_sfb_scrlist[] = {
    194 	&sfb_stdscreen,
    195 };
    196 
    197 static const struct wsscreen_list sfb_screenlist = {
    198 	sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
    199 };
    200 
    201 static int  sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
    202 static int  sfbmmap __P((void *, off_t, int));
    203 
    204 static int  sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
    205 				      void **, int *, int *, long *));
    206 static void sfb_free_screen __P((void *, void *));
    207 static void sfb_show_screen __P((void *, void *));
    208 
    209 static const 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 static int  sfbintr __P((void *));
    220 static 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 static const 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 static 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 	return (1);
    283 }
    284 
    285 static 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 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    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 	/* initialize the raster */
    318 	rap = &dc->dc_raster;
    319 	rap->width = dc->dc_wid;
    320 	rap->height = dc->dc_ht;
    321 	rap->depth = dc->dc_depth;
    322 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    323 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    324 	rap->data = sfbasic;
    325 
    326 	/* initialize the raster console blitter */
    327 	rcp = &dc->dc_rcons;
    328 	rcp->rc_sp = rap;
    329 	rcp->rc_crow = rcp->rc_ccol = -1;
    330 	rcp->rc_crowp = &rcp->rc_crow;
    331 	rcp->rc_ccolp = &rcp->rc_ccol;
    332 	rcons_init(rcp, 34, 80);
    333 
    334 	sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    335 	sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    336 }
    337 
    338 static void
    339 sfbattach(parent, self, aux)
    340 	struct device *parent, *self;
    341 	void *aux;
    342 {
    343 	struct sfb_softc *sc = (struct sfb_softc *)self;
    344 	struct tc_attach_args *ta = aux;
    345 	struct wsemuldisplaydev_attach_args waa;
    346 	struct hwcmap256 *cm;
    347 	caddr_t sfbasic;
    348 	int console;
    349 
    350 	console = (ta->ta_addr == sfb_consaddr);
    351 	if (console) {
    352 		sc->sc_dc = &sfb_console_dc;
    353 		sc->nscreens = 1;
    354 	}
    355 	else {
    356 		sc->sc_dc = (struct fb_devconfig *)
    357 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    358 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    359 	}
    360 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    361 	    sc->sc_dc->dc_depth);
    362 
    363 	cm = &sc->sc_cmap;
    364 	memset(cm, 255, sizeof(struct hwcmap256));	/* XXX */
    365 	cm->r[0] = cm->g[0] = cm->b[0] = 0;		/* XXX */
    366 
    367 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    368 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    369 
    370         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
    371 
    372 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    373 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    374 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    375 
    376 	waa.console = console;
    377 	waa.scrdata = &sfb_screenlist;
    378 	waa.accessops = &sfb_accessops;
    379 	waa.accesscookie = sc;
    380 
    381 	config_found(self, &waa, wsemuldisplaydevprint);
    382 }
    383 
    384 static int
    385 sfbioctl(v, cmd, data, flag, p)
    386 	void *v;
    387 	u_long cmd;
    388 	caddr_t data;
    389 	int flag;
    390 	struct proc *p;
    391 {
    392 	struct sfb_softc *sc = v;
    393 	struct fb_devconfig *dc = sc->sc_dc;
    394 	int turnoff;
    395 
    396 	switch (cmd) {
    397 	case WSDISPLAYIO_GTYPE:
    398 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    399 		return (0);
    400 
    401 	case WSDISPLAYIO_GINFO:
    402 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    403 		wsd_fbip->height = sc->sc_dc->dc_ht;
    404 		wsd_fbip->width = sc->sc_dc->dc_wid;
    405 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    406 		wsd_fbip->cmsize = CMAP_SIZE;
    407 #undef fbt
    408 		return (0);
    409 
    410 	case WSDISPLAYIO_GETCMAP:
    411 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    412 
    413 	case WSDISPLAYIO_PUTCMAP:
    414 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    415 
    416 	case WSDISPLAYIO_SVIDEO:
    417 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    418 		if ((dc->dc_blanked == 0) ^ turnoff) {
    419 			dc->dc_blanked = turnoff;
    420 #if 0 /* XXX later XXX */
    421 		To turn off, assign value 0 in ASIC_VIDEO_VALID register.
    422 #endif	/* XXX XXX 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 static 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 static 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 	sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    485 	*attrp = defattr;
    486 	sc->nscreens++;
    487 	return (0);
    488 }
    489 
    490 static 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 static void
    504 sfb_show_screen(v, cookie)
    505 	void *v;
    506 	void *cookie;
    507 {
    508 }
    509 
    510 /* EXPORT */ 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         sfb_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 static 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 static 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_PLANEMASK) = ~0;
    621 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    622 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
    623 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;  /* ROP_COPY */
    624 
    625 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    626 
    627 	SELECT(vdac, BT459_REG_COMMAND_0);
    628 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    629 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    630 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    631 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    632 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    633 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    634 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    635 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    636 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    637 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    638 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    639 
    640 	SELECT(vdac, BT459_REG_CCR);
    641 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    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 
    655 	/* build sane colormap */
    656 	SELECT(vdac, 0);
    657 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    658 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    659 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    660 	for (i = 1; i < CMAP_SIZE; i++) {
    661 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    662 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    663 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    664 	}
    665 
    666 	/* clear out cursor image */
    667 	SELECT(vdac, BT459_REG_CRAM_BASE);
    668 	for (i = 0; i < 1024; i++)
    669 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    670 
    671 	/*
    672 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    673 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    674 	 * image color.  CCOLOR_1 will be never used.
    675 	 */
    676 	SELECT(vdac, BT459_REG_CCOLOR_1);
    677 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    678 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    679 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    680 
    681 	REG(vdac, bt_reg) = 0;		tc_wmb();
    682 	REG(vdac, bt_reg) = 0;		tc_wmb();
    683 	REG(vdac, bt_reg) = 0;		tc_wmb();
    684 
    685 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    686 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    687 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    688 }
    689 
    690 static int
    691 get_cmap(sc, p)
    692 	struct sfb_softc *sc;
    693 	struct wsdisplay_cmap *p;
    694 {
    695 	u_int index = p->index, count = p->count;
    696 
    697 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    698 		return (EINVAL);
    699 
    700 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    701 	    !uvm_useracc(p->green, count, B_WRITE) ||
    702 	    !uvm_useracc(p->blue, count, B_WRITE))
    703 		return (EFAULT);
    704 
    705 	copyout(&sc->sc_cmap.r[index], p->red, count);
    706 	copyout(&sc->sc_cmap.g[index], p->green, count);
    707 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    708 
    709 	return (0);
    710 }
    711 
    712 static int
    713 set_cmap(sc, p)
    714 	struct sfb_softc *sc;
    715 	struct wsdisplay_cmap *p;
    716 {
    717 	u_int index = p->index, count = p->count;
    718 
    719 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    720 		return (EINVAL);
    721 
    722 	if (!uvm_useracc(p->red, count, B_READ) ||
    723 	    !uvm_useracc(p->green, count, B_READ) ||
    724 	    !uvm_useracc(p->blue, count, B_READ))
    725 		return (EFAULT);
    726 
    727 	copyin(p->red, &sc->sc_cmap.r[index], count);
    728 	copyin(p->green, &sc->sc_cmap.g[index], count);
    729 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    730 
    731 	sc->sc_changed |= DATA_CMAP_CHANGED;
    732 
    733 	return (0);
    734 }
    735 
    736 
    737 static int
    738 set_cursor(sc, p)
    739 	struct sfb_softc *sc;
    740 	struct wsdisplay_cursor *p;
    741 {
    742 #define	cc (&sc->sc_cursor)
    743 	int v, index, count, icount;
    744 
    745 	v = p->which;
    746 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    747 		index = p->cmap.index;
    748 		count = p->cmap.count;
    749 		if (index >= 2 || (index + count) > 2)
    750 			return (EINVAL);
    751 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    752 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    753 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    754 			return (EFAULT);
    755 	}
    756 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    757 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    758 			return (EINVAL);
    759 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    760 		if (!uvm_useracc(p->image, icount, B_READ) ||
    761 		    !uvm_useracc(p->mask, icount, B_READ))
    762 			return (EFAULT);
    763 	}
    764 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    765 		if (v & WSDISPLAY_CURSOR_DOCUR)
    766 			cc->cc_hot = p->hot;
    767 		if (v & WSDISPLAY_CURSOR_DOPOS)
    768 			set_curpos(sc, &p->pos);
    769 		bt459_set_curpos(sc);
    770 	}
    771 
    772 	sc->sc_changed = 0;
    773 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    774 		sc->sc_curenb = p->enable;
    775 		sc->sc_changed |= DATA_ENB_CHANGED;
    776 	}
    777 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    778 		copyin(p->cmap.red, &cc->cc_color[index], count);
    779 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    780 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    781 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    782 	}
    783 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    784 		cc->cc_size = p->size;
    785 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    786 		copyin(p->image, cc->cc_image, icount);
    787 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    788 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    789 	}
    790 
    791 	return (0);
    792 #undef cc
    793 }
    794 
    795 static int
    796 get_cursor(sc, p)
    797 	struct sfb_softc *sc;
    798 	struct wsdisplay_cursor *p;
    799 {
    800 	return (ENOTTY); /* XXX */
    801 }
    802 
    803 static void
    804 set_curpos(sc, curpos)
    805 	struct sfb_softc *sc;
    806 	struct wsdisplay_curpos *curpos;
    807 {
    808 	struct fb_devconfig *dc = sc->sc_dc;
    809 	int x = curpos->x, y = curpos->y;
    810 
    811 	if (y < 0)
    812 		y = 0;
    813 	else if (y > dc->dc_ht)
    814 		y = dc->dc_ht;
    815 	if (x < 0)
    816 		x = 0;
    817 	else if (x > dc->dc_wid)
    818 		x = dc->dc_wid;
    819 	sc->sc_cursor.cc_pos.x = x;
    820 	sc->sc_cursor.cc_pos.y = y;
    821 }
    822 
    823 static void
    824 bt459_set_curpos(sc)
    825 	struct sfb_softc *sc;
    826 {
    827 	caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
    828 	int x, y, s;
    829 
    830 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    831 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    832 
    833 	x += sc->sc_cursor.cc_magic.x;
    834 	y += sc->sc_cursor.cc_magic.y;
    835 
    836 	s = spltty();
    837 
    838 	SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    839 	REG(vdac, bt_reg) = x;		tc_wmb();
    840 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    841 	REG(vdac, bt_reg) = y;		tc_wmb();
    842 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    843 
    844 	splx(s);
    845 }
    846 
    847 #define	MODE_SIMPLE		0
    848 #define	MODE_OPAQUESTIPPLE	1
    849 #define	MODE_OPAQUELINE		2
    850 #define	MODE_TRANSPARENTSTIPPLE	5
    851 #define	MODE_TRANSPARENTLINE	6
    852 #define	MODE_COPY		7
    853 
    854 /* parameters for 8bpp configuration */
    855 #define	SFBALIGNMASK		0x7
    856 #define	SFBSTIPPLEALL1		0xffffffff
    857 #define	SFBSTIPPLEBITS		32
    858 #define	SFBSTIPPLEBITMASK	0x1f
    859 #define	SFBSTIPPLEBYTESDONE	32
    860 #define	SFBCOPYALL1		0xffffffff
    861 #define	SFBCOPYBITS		32
    862 #define	SFBCOPYBITMASK		0x1f
    863 #define	SFBCOPYBYTESDONE	32
    864 
    865 #ifdef pmax
    866 #define	WRITE_MB()
    867 #define	BUMP(p) (p)
    868 #endif
    869 
    870 #ifdef alpha
    871 #define	WRITE_MB() tc_wmb()
    872 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
    873 #endif
    874 
    875 #define	SFBMODE(p, v) \
    876 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
    877 #define	SFBROP(p, v) \
    878 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
    879 #define	SFBPLANEMASK(p, v) \
    880 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
    881 #define	SFBPIXELMASK(p, v) \
    882 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
    883 #define	SFBADDRESS(p, v) \
    884 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
    885 #define	SFBSTART(p, v) \
    886 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
    887 #define	SFBPIXELSHIFT(p, v) \
    888 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
    889 #define	SFBFG(p, v) \
    890 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
    891 #define	SFBBG(p, v) \
    892 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
    893 
    894 
    895 /*
    896  * Paint (or unpaint) the cursor.
    897  */
    898 static void
    899 sfb_cursor(id, on, row, col)
    900 	void *id;
    901 	int on, row, col;
    902 {
    903 	struct rcons *rc = id;
    904 	struct raster *rap = rc->rc_sp;
    905 	caddr_t sfb, p;
    906 	int scanspan, height, width, align, x, y;
    907 	u_int32_t lmask, rmask;
    908 
    909 	/* turn the cursor off */
    910 	if (!on) {
    911 		/* make sure it's on */
    912 		if ((rc->rc_bits & RC_CURSOR) == 0)
    913 			return;
    914 
    915 		row = *rc->rc_crowp;
    916 		col = *rc->rc_ccolp;
    917 	} else {
    918 		/* unpaint the old copy. */
    919 		*rc->rc_crowp = row;
    920 		*rc->rc_ccolp = col;
    921 	}
    922 
    923 	x = col * rc->rc_font->width + rc->rc_xorigin;
    924 	y = row * rc->rc_font->height + rc->rc_yorigin;
    925 	scanspan = rap->linelongs * 4;
    926 	height = rc->rc_font->height;
    927 
    928 	p = (caddr_t)rap->pixels + y * scanspan + x;
    929 	align = (long)p & SFBALIGNMASK;
    930 	p -= align;
    931 	width = rc->rc_font->width + align;
    932 	lmask = SFBSTIPPLEALL1 << align;
    933 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    934 	sfb = rap->data;
    935 
    936 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
    937 	SFBPLANEMASK(sfb, ~0);
    938 	SFBROP(sfb, 6);			/* ROP_XOR */
    939 	SFBFG(sfb, 0x01010101);		/* (fg ^ bg) to swap fg/bg */
    940 	if (width <= SFBSTIPPLEBITS) {
    941 		lmask = lmask & rmask;
    942 		while (height > 0) {
    943 			SFBADDRESS(sfb, (long)p);
    944 			SFBSTART(sfb, lmask);
    945 			p += scanspan;
    946 			height--;
    947 		}
    948 	}
    949 	else {
    950 		caddr_t q = p;
    951 		while (height > 0) {
    952 			*(u_int32_t *)p = lmask;
    953 WRITE_MB();
    954 			p += SFBSTIPPLEBYTESDONE;
    955 			*(u_int32_t *)p = rmask;
    956 WRITE_MB();
    957 
    958 			p = (q += scanspan);
    959 			height--;
    960 		}
    961 	}
    962 	SFBMODE(sfb, MODE_SIMPLE);
    963 	SFBROP(sfb, 3);			/* ROP_COPY */
    964 
    965 	rc->rc_bits ^= RC_CURSOR;
    966 }
    967 
    968 /*
    969  * Actually write a string to the frame buffer.
    970  */
    971 static int
    972 sfb_mapchar(id, uni, index)
    973 	void *id;
    974 	int uni;
    975 	unsigned int *index;
    976 {
    977 	if (uni < 128) {
    978 		*index = uni;
    979 		return (5);
    980 	}
    981 	*index = ' ';
    982 	return (0);
    983 }
    984 
    985 /*
    986  * Actually write a string to the frame buffer.
    987  */
    988 static void
    989 sfb_putchar(id, row, col, uc, attr)
    990 	void *id;
    991 	int row, col;
    992 	u_int uc;
    993 	long attr;
    994 {
    995 	struct rcons *rc = id;
    996 	struct raster *rap = rc->rc_sp;
    997 	caddr_t sfb, p;
    998 	int scanspan, height, width, align, x, y;
    999 	u_int32_t lmask, rmask, glyph;
   1000 	u_int32_t *g;
   1001 
   1002 if (uc < 0x20 || uc >= 127) return; /* XXX why \033 is creaping in !? XXX */
   1003 
   1004 	x = col * rc->rc_font->width + rc->rc_xorigin;
   1005 	y = row * rc->rc_font->height + rc->rc_yorigin;
   1006 	scanspan = rap->linelongs * 4;
   1007 	height = rc->rc_font->height;
   1008 	g = rc->rc_font->chars[uc].r->pixels;
   1009 
   1010 	p = (caddr_t)rap->pixels + y * scanspan + x;
   1011 	align = (long)p & SFBALIGNMASK;
   1012 	p -= align;
   1013 	width = rc->rc_font->width + align;
   1014 	lmask = SFBSTIPPLEALL1 << align;
   1015 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1016 	sfb = rap->data;
   1017 	attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
   1018 
   1019 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1020 	SFBPLANEMASK(sfb, ~0);
   1021 	SFBFG(sfb, (attr == 0) ? 0x01010101 : 0);
   1022 	SFBBG(sfb, (attr == 0) ? 0 : 0x01010101);
   1023 	if (width <= SFBSTIPPLEBITS) {
   1024 		lmask = lmask & rmask;
   1025 		while (height > 0) {
   1026 			glyph = *g;
   1027 			SFBPIXELMASK(sfb, lmask);
   1028 			SFBADDRESS(sfb, (long)p);
   1029 			SFBSTART(sfb, glyph << align);
   1030 			p += scanspan;
   1031 			g += 1;
   1032 			height--;
   1033 		}
   1034 	}
   1035 	else {
   1036 		caddr_t q = p;
   1037 		while (height > 0) {
   1038 			glyph = *g;
   1039 			SFBPIXELMASK(sfb, lmask);
   1040 WRITE_MB();
   1041 			*(u_int32_t *)p = glyph << align;
   1042 WRITE_MB();
   1043 			p += SFBSTIPPLEBYTESDONE;
   1044 			SFBPIXELMASK(sfb, rmask);
   1045 WRITE_MB();
   1046 			*(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
   1047 WRITE_MB();
   1048 
   1049 			p = (q += scanspan);
   1050 			g += 1;
   1051 			height--;
   1052 		}
   1053 	}
   1054 	SFBMODE(sfb, MODE_SIMPLE);
   1055 	SFBPIXELMASK(sfb, ~0);		/* entire pixel */
   1056 }
   1057 
   1058 /*
   1059  * Copy characters in a line.
   1060  */
   1061 static void
   1062 sfb_copycols(id, row, srccol, dstcol, ncols)
   1063 	void *id;
   1064 	int row, srccol, dstcol, ncols;
   1065 {
   1066 	struct rcons *rc = id;
   1067 	struct raster *rap = rc->rc_sp;
   1068 	caddr_t sp, dp, basex, sfb;
   1069 	int scanspan, height, width, aligns, alignd, shift, w, y;
   1070 	u_int32_t lmasks, rmasks, lmaskd, rmaskd;
   1071 
   1072 	scanspan = rap->linelongs * 4;
   1073 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1074 	basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
   1075 	height = rc->rc_font->height;
   1076 	w = rc->rc_font->width * ncols;
   1077 
   1078 	sp = basex + rc->rc_font->width * srccol;
   1079 	aligns = (long)sp & SFBALIGNMASK;
   1080 	dp = basex + rc->rc_font->width * dstcol;
   1081 	alignd = (long)dp & SFBALIGNMASK;
   1082 	sfb = rap->data;
   1083 
   1084 	SFBMODE(sfb, MODE_COPY);
   1085 	SFBPLANEMASK(sfb, ~0);
   1086 
   1087 	/* copy forward (left-to-right) */
   1088 	if (dstcol < srccol || srccol + ncols < dstcol) {
   1089 		caddr_t sq, dq;
   1090 
   1091 		shift = alignd - aligns;
   1092 		if (shift < 0) {
   1093 			dp -= 8;		/* prime left edge */
   1094 			alignd += 8;		/* compensate it */
   1095 			width = aligns + w + 8; /* adjust total width */
   1096 			shift = 8 + shift;	/* enforce right rotate */
   1097 		}
   1098 		else if (shift > 0)
   1099 			width = aligns + w + 8; /* enfore drain at right edge */
   1100 
   1101 		lmasks = SFBCOPYALL1 << aligns;
   1102 		rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1103 		lmaskd = SFBCOPYALL1 << alignd;
   1104 		rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
   1105 
   1106 		if (w + alignd <= SFBCOPYBITS)
   1107 			goto singlewrite;
   1108 
   1109 		SFBPIXELSHIFT(sfb, shift);
   1110 		w = width;
   1111 		sq = sp;
   1112 		dq = dp;
   1113 		while (height > 0) {
   1114 			*(u_int32_t *)sp = lmasks;
   1115 WRITE_MB();
   1116 			*(u_int32_t *)dp = lmaskd;
   1117 WRITE_MB();
   1118 			width -= 2 * SFBCOPYBITS;
   1119 			while (width > 0) {
   1120 				sp += SFBCOPYBYTESDONE;
   1121 				dp += SFBCOPYBYTESDONE;
   1122 				*(u_int32_t *)sp = SFBCOPYALL1;
   1123 WRITE_MB();
   1124 				*(u_int32_t *)dp = SFBCOPYALL1;
   1125 WRITE_MB();
   1126 				width -= SFBCOPYBITS;
   1127 			}
   1128 			sp += SFBCOPYBYTESDONE;
   1129 			dp += SFBCOPYBYTESDONE;
   1130 			*(u_int32_t *)sp = rmasks;
   1131 WRITE_MB();
   1132 			*(u_int32_t *)dp = rmaskd;
   1133 WRITE_MB();
   1134 
   1135 			sp = (sq += scanspan);
   1136 			dp = (dq += scanspan);
   1137 			width = w;
   1138 			height--;
   1139 		}
   1140 	}
   1141 	/* copy backward (right-to-left) */
   1142 	else {
   1143 		caddr_t sq, dq;
   1144 
   1145 		shift = alignd - aligns;
   1146 		if (shift > 0) {
   1147 			shift = shift - 8;
   1148 			w += 8;
   1149 		}
   1150 		width = w + aligns;
   1151 		lmasks = SFBCOPYALL1 << aligns;
   1152 		rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1153 		lmaskd = SFBCOPYALL1 << alignd;
   1154 		rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
   1155 
   1156 		if (w + alignd <= SFBCOPYBITS)
   1157 			goto singlewrite;
   1158 
   1159 		SFBPIXELSHIFT(sfb, shift);
   1160 		w = width;
   1161 		sq = (sp += width);
   1162 		dq = (dp += width);
   1163 		while (height > 0) {
   1164 			*(u_int32_t *)sp = rmasks;
   1165 WRITE_MB();
   1166 			*(u_int32_t *)dp = rmaskd;
   1167 WRITE_MB();
   1168 			width -= 2 * SFBCOPYBITS;
   1169 			while (width > 0) {
   1170 				sp -= SFBCOPYBYTESDONE;
   1171 				dp -= SFBCOPYBYTESDONE;
   1172 				*(u_int32_t *)sp = SFBCOPYALL1;
   1173 WRITE_MB();
   1174 				*(u_int32_t *)dp = SFBCOPYALL1;
   1175 WRITE_MB();
   1176 				width -= SFBCOPYBITS;
   1177 			}
   1178 			sp -= SFBCOPYBYTESDONE;
   1179 			dp -= SFBCOPYBYTESDONE;
   1180 			*(u_int32_t *)sp = lmasks;
   1181 WRITE_MB();
   1182 			*(u_int32_t *)dp = lmaskd;
   1183 WRITE_MB();
   1184 
   1185 			sp = (sq += scanspan);
   1186 			dp = (dq += scanspan);
   1187 			width = w;
   1188 			height--;
   1189 		}
   1190 	}
   1191 	SFBMODE(sfb, MODE_SIMPLE);
   1192 	SFBPIXELSHIFT(sfb, 0);
   1193 	return;
   1194 
   1195 singlewrite:
   1196 	SFBPIXELSHIFT(sfb, shift);
   1197 	lmasks = lmasks & rmasks;
   1198 	lmaskd = lmaskd & rmaskd;
   1199 	while (height > 0) {
   1200 		*(u_int32_t *)sp = lmasks;
   1201 WRITE_MB();
   1202 		*(u_int32_t *)dp = lmaskd;
   1203 WRITE_MB();
   1204 		sp += scanspan;
   1205 		dp += scanspan;
   1206 		height--;
   1207 	}
   1208 	SFBMODE(sfb, MODE_SIMPLE);
   1209 	SFBPIXELSHIFT(sfb, 0);
   1210 }
   1211 
   1212 /*
   1213  * Clear characters in a line.
   1214  */
   1215 static void
   1216 sfb_erasecols(id, row, startcol, ncols, attr)
   1217 	void *id;
   1218 	int row, startcol, ncols;
   1219 	long attr;
   1220 {
   1221 	struct rcons *rc = id;
   1222 	struct raster *rap = rc->rc_sp;
   1223 	caddr_t sfb, p;
   1224 	int scanspan, startx, height, width, align, w, y;
   1225 	u_int32_t lmask, rmask;
   1226 
   1227 	scanspan = rap->linelongs * 4;
   1228 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1229 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
   1230 	height = rc->rc_font->height;
   1231 	w = rc->rc_font->width * ncols;
   1232 
   1233 	p = (caddr_t)rap->pixels + y * scanspan + startx;
   1234 	align = (long)p & SFBALIGNMASK;
   1235 	p -= align;
   1236 	width = w + align;
   1237 	lmask = SFBSTIPPLEALL1 << align;
   1238 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1239 	sfb = rap->data;
   1240 
   1241 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1242 	SFBPLANEMASK(sfb, ~0);
   1243 	SFBFG(sfb, 0);				/* fill with bg color */
   1244 	if (width <= SFBSTIPPLEBITS) {
   1245 		lmask = lmask & rmask;
   1246 		while (height > 0) {
   1247 			SFBADDRESS(sfb, (long)p);
   1248 			SFBSTART(sfb, lmask);
   1249 			p += scanspan;
   1250 			height--;
   1251 		}
   1252 	}
   1253 	else {
   1254 		caddr_t q = p;
   1255 		while (height > 0) {
   1256 			*(u_int32_t *)p = lmask;
   1257 WRITE_MB();
   1258 			width -= 2 * SFBSTIPPLEBITS;
   1259 			while (width > 0) {
   1260 				p += SFBSTIPPLEBYTESDONE;
   1261 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1262 WRITE_MB();
   1263 				width -= SFBSTIPPLEBITS;
   1264 			}
   1265 			p += SFBSTIPPLEBYTESDONE;
   1266 			*(u_int32_t *)p = rmask;
   1267 WRITE_MB();
   1268 
   1269 			p = (q += scanspan);
   1270 			width = w + align;
   1271 			height--;
   1272 		}
   1273 	}
   1274 	SFBMODE(sfb, MODE_SIMPLE);
   1275 }
   1276 
   1277 /*
   1278  * Copy lines.
   1279  */
   1280 static void
   1281 sfb_copyrows(id, srcrow, dstrow, nrows)
   1282 	void *id;
   1283 	int srcrow, dstrow, nrows;
   1284 {
   1285 	struct rcons *rc = id;
   1286 	struct raster *rap = rc->rc_sp;
   1287 	caddr_t sfb, p;
   1288 	int scanspan, offset, srcy, height, width, align, w;
   1289 	u_int32_t lmask, rmask;
   1290 
   1291 	scanspan = rap->linelongs * 4;
   1292 	height = rc->rc_font->height * nrows;
   1293 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1294 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1295 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1296 		scanspan = -scanspan;
   1297 		srcy += height;
   1298 	}
   1299 
   1300 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1301 	align = (long)p & SFBALIGNMASK;
   1302 	p -= align;
   1303 	w = rc->rc_font->width * rc->rc_maxcol;
   1304 	width = w + align;
   1305 	lmask = SFBCOPYALL1 << align;
   1306 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1307 	sfb = rap->data;
   1308 
   1309 	SFBMODE(sfb, MODE_COPY);
   1310 	SFBPLANEMASK(sfb, ~0);
   1311 	SFBPIXELSHIFT(sfb, 0);
   1312 	if (width <= SFBCOPYBITS) {
   1313 		/* never happens */;
   1314 	}
   1315 	else {
   1316 		caddr_t q = p;
   1317 		while (height > 0) {
   1318 			*(u_int32_t *)p = lmask;
   1319 			*(u_int32_t *)(p + offset) = lmask;
   1320 			width -= 2 * SFBCOPYBITS;
   1321 			while (width > 0) {
   1322 				p += SFBCOPYBYTESDONE;
   1323 				*(u_int32_t *)p = SFBCOPYALL1;
   1324 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1325 				width -= SFBCOPYBITS;
   1326 			}
   1327 			p += SFBCOPYBYTESDONE;
   1328 			*(u_int32_t *)p = rmask;
   1329 			*(u_int32_t *)(p + offset) = rmask;
   1330 
   1331 			p = (q += scanspan);
   1332 			width = w + align;
   1333 			height--;
   1334 		}
   1335 	}
   1336 	SFBMODE(sfb, MODE_SIMPLE);
   1337 }
   1338 
   1339 /*
   1340  * Erase lines.
   1341  */
   1342 void
   1343 sfb_eraserows(id, startrow, nrows, attr)
   1344 	void *id;
   1345 	int startrow, nrows;
   1346 	long attr;
   1347 {
   1348 	struct rcons *rc = id;
   1349 	struct raster *rap = rc->rc_sp;
   1350 	caddr_t sfb, p;
   1351 	int scanspan, starty, height, width, align, w;
   1352 	u_int32_t lmask, rmask;
   1353 
   1354 	scanspan = rap->linelongs * 4;
   1355 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1356 	height = rc->rc_font->height * nrows;
   1357 
   1358 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1359 	align = (long)p & SFBALIGNMASK;
   1360 	p -= align;
   1361 	w = rc->rc_font->width * rc->rc_maxcol;
   1362 	width = w + align;
   1363 	lmask = SFBSTIPPLEALL1 << align;
   1364 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1365 	sfb = rap->data;
   1366 
   1367 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1368 	SFBPLANEMASK(sfb, ~0);
   1369 	SFBFG(sfb, 0);				/* fill with bg color */
   1370 	if (width <= SFBSTIPPLEBITS) {
   1371 		/* never happens */;
   1372 	}
   1373 	else {
   1374 		caddr_t q = p;
   1375 		while (height > 0) {
   1376 			*(u_int32_t *)p = lmask;
   1377 WRITE_MB();
   1378 			width -= 2 * SFBSTIPPLEBITS;
   1379 			while (width > 0) {
   1380 				p += SFBSTIPPLEBYTESDONE;
   1381 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1382 WRITE_MB();
   1383 				width -= SFBSTIPPLEBITS;
   1384 			}
   1385 			p += SFBSTIPPLEBYTESDONE;
   1386 			*(u_int32_t *)p = rmask;
   1387 WRITE_MB();
   1388 
   1389 			p = (q += scanspan);
   1390 			width = w + align;
   1391 			height--;
   1392 		}
   1393 	}
   1394 	SFBMODE(sfb, MODE_SIMPLE);
   1395 }
   1396 
   1397 static int
   1398 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1399 	void *id;
   1400 	int fg, bg, flags;
   1401 	long *attrp;
   1402 {
   1403 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1404 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1405 		return (EINVAL);
   1406 	if (flags & WSATTR_REVERSE)
   1407 		*attrp = 1;
   1408 	else
   1409 		*attrp = 0;
   1410 	return (0);
   1411 }
   1412