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