Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.25
      1 /* $NetBSD: sfb.c,v 1.25 1999/11/05 03:28:40 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.25 1999/11/05 03:28:40 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 1
    281 	if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0
    282 	    && strncmp("PMAGD", ta->ta_modname, 5))
    283 		return (0);
    284 #else
    285 	if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
    286 		return (0);
    287 #endif
    288 	return (1);
    289 }
    290 
    291 void
    292 sfb_getdevconfig(dense_addr, dc)
    293 	tc_addr_t dense_addr;
    294 	struct fb_devconfig *dc;
    295 {
    296 	struct raster *rap;
    297 	struct rcons *rcp;
    298 	caddr_t sfbasic;
    299 	int i, hsetup, vsetup, vbase;
    300 
    301 	dc->dc_vaddr = dense_addr;
    302 	dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
    303 
    304 	sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    305 	hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
    306 	vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
    307 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
    308 
    309 	dc->dc_wid = (hsetup & 0x1ff) << 2;
    310 	dc->dc_ht = (vsetup & 0x7ff);
    311 	dc->dc_depth = 8;
    312 	dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
    313 	dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
    314 	dc->dc_blanked = 0;
    315 
    316 	/* initialize colormap and cursor resource */
    317 	sfbinit(dc);
    318 
    319 	/* clear the screen */
    320 	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
    321 		*(u_int32_t *)(dc->dc_videobase + i) = 0x0;
    322 
    323 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
    324 
    325 	/* initialize the raster */
    326 	rap = &dc->dc_raster;
    327 	rap->width = dc->dc_wid;
    328 	rap->height = dc->dc_ht;
    329 	rap->depth = dc->dc_depth;
    330 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
    331 	rap->pixels = (u_int32_t *)dc->dc_videobase;
    332 	rap->data = sfbasic;
    333 
    334 	/* initialize the raster console blitter */
    335 	rcp = &dc->dc_rcons;
    336 	rcp->rc_sp = rap;
    337 	rcp->rc_crow = rcp->rc_ccol = -1;
    338 	rcp->rc_crowp = &rcp->rc_crow;
    339 	rcp->rc_ccolp = &rcp->rc_ccol;
    340 	rcons_init(rcp, 34, 80);
    341 
    342 	sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
    343 	sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
    344 }
    345 
    346 void
    347 sfbattach(parent, self, aux)
    348 	struct device *parent, *self;
    349 	void *aux;
    350 {
    351 	struct sfb_softc *sc = (struct sfb_softc *)self;
    352 	struct tc_attach_args *ta = aux;
    353 	struct wsemuldisplaydev_attach_args waa;
    354 	struct hwcmap256 *cm;
    355 	caddr_t sfbasic;
    356 	int console;
    357 
    358 	console = (ta->ta_addr == sfb_consaddr);
    359 	if (console) {
    360 		sc->sc_dc = &sfb_console_dc;
    361 		sc->nscreens = 1;
    362 	}
    363 	else {
    364 		sc->sc_dc = (struct fb_devconfig *)
    365 		    malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
    366 		sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
    367 	}
    368 	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
    369 	    sc->sc_dc->dc_depth);
    370 
    371 	cm = &sc->sc_cmap;
    372 	memset(cm, 255, sizeof(struct hwcmap256));	/* XXX */
    373 	cm->r[0] = cm->g[0] = cm->b[0] = 0;		/* XXX */
    374 
    375 	sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
    376 	sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
    377 
    378         tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
    379 
    380 	sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
    381 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    382 	*(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
    383 
    384 	waa.console = console;
    385 	waa.scrdata = &sfb_screenlist;
    386 	waa.accessops = &sfb_accessops;
    387 	waa.accesscookie = sc;
    388 
    389 	config_found(self, &waa, wsemuldisplaydevprint);
    390 }
    391 
    392 int
    393 sfbioctl(v, cmd, data, flag, p)
    394 	void *v;
    395 	u_long cmd;
    396 	caddr_t data;
    397 	int flag;
    398 	struct proc *p;
    399 {
    400 	struct sfb_softc *sc = v;
    401 	struct fb_devconfig *dc = sc->sc_dc;
    402 	int turnoff;
    403 
    404 	switch (cmd) {
    405 	case WSDISPLAYIO_GTYPE:
    406 		*(u_int *)data = WSDISPLAY_TYPE_SFB;
    407 		return (0);
    408 
    409 	case WSDISPLAYIO_GINFO:
    410 #define	wsd_fbip ((struct wsdisplay_fbinfo *)data)
    411 		wsd_fbip->height = sc->sc_dc->dc_ht;
    412 		wsd_fbip->width = sc->sc_dc->dc_wid;
    413 		wsd_fbip->depth = sc->sc_dc->dc_depth;
    414 		wsd_fbip->cmsize = CMAP_SIZE;
    415 #undef fbt
    416 		return (0);
    417 
    418 	case WSDISPLAYIO_GETCMAP:
    419 		return get_cmap(sc, (struct wsdisplay_cmap *)data);
    420 
    421 	case WSDISPLAYIO_PUTCMAP:
    422 		return set_cmap(sc, (struct wsdisplay_cmap *)data);
    423 
    424 	case WSDISPLAYIO_SVIDEO:
    425 		turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
    426 		if ((dc->dc_blanked == 0) ^ turnoff) {
    427 			dc->dc_blanked = turnoff;
    428 #if 0 /* XXX later XXX */
    429 		To turn off, assign value 0 in ASIC_VIDEO_VALID register.
    430 #endif	/* XXX XXX XXX */
    431 		}
    432 		return (0);
    433 
    434 	case WSDISPLAYIO_GVIDEO:
    435 		*(u_int *)data = dc->dc_blanked ?
    436 		    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
    437 		return (0);
    438 
    439 	case WSDISPLAYIO_GCURPOS:
    440 		*(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
    441 		return (0);
    442 
    443 	case WSDISPLAYIO_SCURPOS:
    444 		set_curpos(sc, (struct wsdisplay_curpos *)data);
    445 		bt459_set_curpos(sc);
    446 		return (0);
    447 
    448 	case WSDISPLAYIO_GCURMAX:
    449 		((struct wsdisplay_curpos *)data)->x =
    450 		((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
    451 		return (0);
    452 
    453 	case WSDISPLAYIO_GCURSOR:
    454 		return get_cursor(sc, (struct wsdisplay_cursor *)data);
    455 
    456 	case WSDISPLAYIO_SCURSOR:
    457 		return set_cursor(sc, (struct wsdisplay_cursor *)data);
    458 	}
    459 	return ENOTTY;
    460 }
    461 
    462 int
    463 sfbmmap(v, offset, prot)
    464 	void *v;
    465 	off_t offset;
    466 	int prot;
    467 {
    468 	struct sfb_softc *sc = v;
    469 
    470 	if (offset >= SFB_SIZE || offset < 0)
    471 		return (-1);
    472 	return machine_btop(sc->sc_dc->dc_paddr + offset);
    473 }
    474 
    475 int
    476 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
    477 	void *v;
    478 	const struct wsscreen_descr *type;
    479 	void **cookiep;
    480 	int *curxp, *curyp;
    481 	long *attrp;
    482 {
    483 	struct sfb_softc *sc = v;
    484 	long defattr;
    485 
    486 	if (sc->nscreens > 0)
    487 		return (ENOMEM);
    488 
    489 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
    490 	*curxp = 0;
    491 	*curyp = 0;
    492 	sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
    493 	*attrp = defattr;
    494 	sc->nscreens++;
    495 	return (0);
    496 }
    497 
    498 void
    499 sfb_free_screen(v, cookie)
    500 	void *v;
    501 	void *cookie;
    502 {
    503 	struct sfb_softc *sc = v;
    504 
    505 	if (sc->sc_dc == &sfb_console_dc)
    506 		panic("sfb_free_screen: console");
    507 
    508 	sc->nscreens--;
    509 }
    510 
    511 void
    512 sfb_show_screen(v, cookie)
    513 	void *v;
    514 	void *cookie;
    515 {
    516 }
    517 
    518 int
    519 sfb_cnattach(addr)
    520         tc_addr_t addr;
    521 {
    522         struct fb_devconfig *dcp = &sfb_console_dc;
    523         long defattr;
    524 
    525         sfb_getdevconfig(addr, dcp);
    526 
    527         sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
    528 
    529         wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
    530                            0, 0, defattr);
    531         sfb_consaddr = addr;
    532         return(0);
    533 }
    534 
    535 int
    536 sfbintr(arg)
    537 	void *arg;
    538 {
    539 	struct sfb_softc *sc = arg;
    540 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    541 	caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
    542 	caddr_t vdac;
    543 	int v;
    544 
    545 	*(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
    546 	/* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
    547 
    548 	if (sc->sc_changed == 0)
    549 		return (1);
    550 
    551 	vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    552 	v = sc->sc_changed;
    553 	sc->sc_changed = 0;
    554 
    555 	if (v & DATA_ENB_CHANGED) {
    556 		SELECT(vdac, BT459_REG_CCR);
    557 		REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
    558 	}
    559 	if (v & DATA_CURCMAP_CHANGED) {
    560 		u_int8_t *cp = sc->sc_cursor.cc_color;
    561 
    562 		SELECT(vdac, BT459_REG_CCOLOR_2);
    563 		REG(vdac, bt_reg) = cp[1];	tc_wmb();
    564 		REG(vdac, bt_reg) = cp[3];	tc_wmb();
    565 		REG(vdac, bt_reg) = cp[5];	tc_wmb();
    566 
    567 		REG(vdac, bt_reg) = cp[0];	tc_wmb();
    568 		REG(vdac, bt_reg) = cp[2];	tc_wmb();
    569 		REG(vdac, bt_reg) = cp[4];	tc_wmb();
    570 	}
    571 	if (v & DATA_CURSHAPE_CHANGED) {
    572 		u_int8_t *ip, *mp, img, msk;
    573 		u_int8_t u;
    574 		int bcnt;
    575 
    576 		ip = (u_int8_t *)sc->sc_cursor.cc_image;
    577 		mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
    578 
    579 		bcnt = 0;
    580 		SELECT(vdac, BT459_REG_CRAM_BASE+0);
    581 		/* 64 pixel scan line is consisted with 16 byte cursor ram */
    582 		while (bcnt < sc->sc_cursor.cc_size.y * 16) {
    583 			/* pad right half 32 pixel when smaller than 33 */
    584 			if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
    585 				REG(vdac, bt_reg) = 0; tc_wmb();
    586 				REG(vdac, bt_reg) = 0; tc_wmb();
    587 			}
    588 			else {
    589 				img = *ip++;
    590 				msk = *mp++;
    591 				img &= msk;	/* cookie off image */
    592 				u = (msk & 0x0f) << 4 | (img & 0x0f);
    593 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    594 				u = (msk & 0xf0) | (img & 0xf0) >> 4;
    595 				REG(vdac, bt_reg) = shuffle[u];	tc_wmb();
    596 			}
    597 			bcnt += 2;
    598 		}
    599 		/* pad unoccupied scan lines */
    600 		while (bcnt < CURSOR_MAX_SIZE * 16) {
    601 			REG(vdac, bt_reg) = 0; tc_wmb();
    602 			REG(vdac, bt_reg) = 0; tc_wmb();
    603 			bcnt += 2;
    604 		}
    605 	}
    606 	if (v & DATA_CMAP_CHANGED) {
    607 		struct hwcmap256 *cm = &sc->sc_cmap;
    608 		int index;
    609 
    610 		SELECT(vdac, 0);
    611 		for (index = 0; index < CMAP_SIZE; index++) {
    612 			REG(vdac, bt_cmap) = cm->r[index];	tc_wmb();
    613 			REG(vdac, bt_cmap) = cm->g[index];	tc_wmb();
    614 			REG(vdac, bt_cmap) = cm->b[index];	tc_wmb();
    615 		}
    616 	}
    617 	return (1);
    618 }
    619 
    620 void
    621 sfbinit(dc)
    622 	struct fb_devconfig *dc;
    623 {
    624 	caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
    625 	caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
    626 	int i;
    627 
    628 	*(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 0;
    629 	*(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
    630 	*(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
    631 	*(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
    632 	*(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;  /* ROP_COPY */
    633 
    634 	*(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
    635 
    636 	SELECT(vdac, BT459_REG_COMMAND_0);
    637 	REG(vdac, bt_reg) = 0x40; /* CMD0 */	tc_wmb();
    638 	REG(vdac, bt_reg) = 0x0;  /* CMD1 */	tc_wmb();
    639 	REG(vdac, bt_reg) = 0xc0; /* CMD2 */	tc_wmb();
    640 	REG(vdac, bt_reg) = 0xff; /* PRM */	tc_wmb();
    641 	REG(vdac, bt_reg) = 0;    /* 205 */	tc_wmb();
    642 	REG(vdac, bt_reg) = 0x0;  /* PBM */	tc_wmb();
    643 	REG(vdac, bt_reg) = 0;    /* 207 */	tc_wmb();
    644 	REG(vdac, bt_reg) = 0x0;  /* ORM */	tc_wmb();
    645 	REG(vdac, bt_reg) = 0x0;  /* OBM */	tc_wmb();
    646 	REG(vdac, bt_reg) = 0x0;  /* ILV */	tc_wmb();
    647 	REG(vdac, bt_reg) = 0x0;  /* TEST */	tc_wmb();
    648 
    649 	SELECT(vdac, BT459_REG_CCR);
    650 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    651 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    652 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    653 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    654 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    655 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    656 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    657 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    658 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    659 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    660 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    661 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    662 	REG(vdac, bt_reg) = 0x0;	tc_wmb();
    663 
    664 	/* build sane colormap */
    665 	SELECT(vdac, 0);
    666 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    667 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    668 	REG(vdac, bt_cmap) = 0;	tc_wmb();
    669 	for (i = 1; i < CMAP_SIZE; i++) {
    670 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    671 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    672 		REG(vdac, bt_cmap) = 0xff;	tc_wmb();
    673 	}
    674 
    675 	/* clear out cursor image */
    676 	SELECT(vdac, BT459_REG_CRAM_BASE);
    677 	for (i = 0; i < 1024; i++)
    678 		REG(vdac, bt_reg) = 0xff;	tc_wmb();
    679 
    680 	/*
    681 	 * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
    682 	 * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
    683 	 * image color.  CCOLOR_1 will be never used.
    684 	 */
    685 	SELECT(vdac, BT459_REG_CCOLOR_1);
    686 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    687 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    688 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    689 
    690 	REG(vdac, bt_reg) = 0;		tc_wmb();
    691 	REG(vdac, bt_reg) = 0;		tc_wmb();
    692 	REG(vdac, bt_reg) = 0;		tc_wmb();
    693 
    694 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    695 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    696 	REG(vdac, bt_reg) = 0xff;	tc_wmb();
    697 }
    698 
    699 static int
    700 get_cmap(sc, p)
    701 	struct sfb_softc *sc;
    702 	struct wsdisplay_cmap *p;
    703 {
    704 	u_int index = p->index, count = p->count;
    705 
    706 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    707 		return (EINVAL);
    708 
    709 	if (!uvm_useracc(p->red, count, B_WRITE) ||
    710 	    !uvm_useracc(p->green, count, B_WRITE) ||
    711 	    !uvm_useracc(p->blue, count, B_WRITE))
    712 		return (EFAULT);
    713 
    714 	copyout(&sc->sc_cmap.r[index], p->red, count);
    715 	copyout(&sc->sc_cmap.g[index], p->green, count);
    716 	copyout(&sc->sc_cmap.b[index], p->blue, count);
    717 
    718 	return (0);
    719 }
    720 
    721 static int
    722 set_cmap(sc, p)
    723 	struct sfb_softc *sc;
    724 	struct wsdisplay_cmap *p;
    725 {
    726 	u_int index = p->index, count = p->count;
    727 
    728 	if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
    729 		return (EINVAL);
    730 
    731 	if (!uvm_useracc(p->red, count, B_READ) ||
    732 	    !uvm_useracc(p->green, count, B_READ) ||
    733 	    !uvm_useracc(p->blue, count, B_READ))
    734 		return (EFAULT);
    735 
    736 	copyin(p->red, &sc->sc_cmap.r[index], count);
    737 	copyin(p->green, &sc->sc_cmap.g[index], count);
    738 	copyin(p->blue, &sc->sc_cmap.b[index], count);
    739 
    740 	sc->sc_changed |= DATA_CMAP_CHANGED;
    741 
    742 	return (0);
    743 }
    744 
    745 
    746 static int
    747 set_cursor(sc, p)
    748 	struct sfb_softc *sc;
    749 	struct wsdisplay_cursor *p;
    750 {
    751 #define	cc (&sc->sc_cursor)
    752 	int v, index, count, icount;
    753 
    754 	v = p->which;
    755 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    756 		index = p->cmap.index;
    757 		count = p->cmap.count;
    758 		if (index >= 2 || (index + count) > 2)
    759 			return (EINVAL);
    760 		if (!uvm_useracc(p->cmap.red, count, B_READ) ||
    761 		    !uvm_useracc(p->cmap.green, count, B_READ) ||
    762 		    !uvm_useracc(p->cmap.blue, count, B_READ))
    763 			return (EFAULT);
    764 	}
    765 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    766 		if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
    767 			return (EINVAL);
    768 		icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
    769 		if (!uvm_useracc(p->image, icount, B_READ) ||
    770 		    !uvm_useracc(p->mask, icount, B_READ))
    771 			return (EFAULT);
    772 	}
    773 	if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
    774 		if (v & WSDISPLAY_CURSOR_DOCUR)
    775 			cc->cc_hot = p->hot;
    776 		if (v & WSDISPLAY_CURSOR_DOPOS)
    777 			set_curpos(sc, &p->pos);
    778 		bt459_set_curpos(sc);
    779 	}
    780 
    781 	sc->sc_changed = 0;
    782 	if (v & WSDISPLAY_CURSOR_DOCUR) {
    783 		sc->sc_curenb = p->enable;
    784 		sc->sc_changed |= DATA_ENB_CHANGED;
    785 	}
    786 	if (v & WSDISPLAY_CURSOR_DOCMAP) {
    787 		copyin(p->cmap.red, &cc->cc_color[index], count);
    788 		copyin(p->cmap.green, &cc->cc_color[index + 2], count);
    789 		copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
    790 		sc->sc_changed |= DATA_CURCMAP_CHANGED;
    791 	}
    792 	if (v & WSDISPLAY_CURSOR_DOSHAPE) {
    793 		cc->cc_size = p->size;
    794 		memset(cc->cc_image, 0, sizeof cc->cc_image);
    795 		copyin(p->image, cc->cc_image, icount);
    796 		copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
    797 		sc->sc_changed |= DATA_CURSHAPE_CHANGED;
    798 	}
    799 
    800 	return (0);
    801 #undef cc
    802 }
    803 
    804 static int
    805 get_cursor(sc, p)
    806 	struct sfb_softc *sc;
    807 	struct wsdisplay_cursor *p;
    808 {
    809 	return (ENOTTY); /* XXX */
    810 }
    811 
    812 static void
    813 set_curpos(sc, curpos)
    814 	struct sfb_softc *sc;
    815 	struct wsdisplay_curpos *curpos;
    816 {
    817 	struct fb_devconfig *dc = sc->sc_dc;
    818 	int x = curpos->x, y = curpos->y;
    819 
    820 	if (y < 0)
    821 		y = 0;
    822 	else if (y > dc->dc_ht)
    823 		y = dc->dc_ht;
    824 	if (x < 0)
    825 		x = 0;
    826 	else if (x > dc->dc_wid)
    827 		x = dc->dc_wid;
    828 	sc->sc_cursor.cc_pos.x = x;
    829 	sc->sc_cursor.cc_pos.y = y;
    830 }
    831 
    832 static void
    833 bt459_set_curpos(sc)
    834 	struct sfb_softc *sc;
    835 {
    836 	caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
    837 	caddr_t vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
    838 	int x, y, s;
    839 
    840 	x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
    841 	y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
    842 
    843 	x += sc->sc_cursor.cc_magic.x;
    844 	y += sc->sc_cursor.cc_magic.y;
    845 
    846 	s = spltty();
    847 
    848 	SELECT(vdac, BT459_REG_CURSOR_X_LOW);
    849 	REG(vdac, bt_reg) = x;		tc_wmb();
    850 	REG(vdac, bt_reg) = x >> 8;	tc_wmb();
    851 	REG(vdac, bt_reg) = y;		tc_wmb();
    852 	REG(vdac, bt_reg) = y >> 8;	tc_wmb();
    853 
    854 	splx(s);
    855 }
    856 
    857 #define	MODE_SIMPLE		0
    858 #define	MODE_OPAQUESTIPPLE	1
    859 #define	MODE_OPAQUELINE		2
    860 #define	MODE_TRANSPARENTSTIPPLE	5
    861 #define	MODE_TRANSPARENTLINE	6
    862 #define	MODE_COPY		7
    863 
    864 /* parameters for 8bpp configuration */
    865 #define	SFBALIGNMASK		0x7
    866 #define	SFBSTIPPLEALL1		0xffffffff
    867 #define	SFBSTIPPLEBITS		32
    868 #define	SFBSTIPPLEBITMASK	0x1f
    869 #define	SFBSTIPPLEBYTESDONE	32
    870 #define	SFBCOPYALL1		0xffffffff
    871 #define	SFBCOPYBITS		32
    872 #define	SFBCOPYBITMASK		0x1f
    873 #define	SFBCOPYBYTESDONE	32
    874 
    875 #ifdef pmax
    876 #define	WRITE_MB()
    877 #define	BUMP(p) (p)
    878 #endif
    879 
    880 #ifdef alpha
    881 #define	WRITE_MB() tc_wmb()
    882 #define	BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
    883 #endif
    884 
    885 #define	SFBMODE(p, v) \
    886 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
    887 #define	SFBROP(p, v) \
    888 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
    889 #define	SFBPLANEMASK(p, v) \
    890 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
    891 #define	SFBPIXELMASK(p, v) \
    892 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
    893 #define	SFBADDRESS(p, v) \
    894 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
    895 #define	SFBSTART(p, v) \
    896 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
    897 #define	SFBPIXELSHIFT(p, v) \
    898 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
    899 #define	SFBFG(p, v) \
    900 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
    901 #define	SFBBG(p, v) \
    902 		(*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
    903 
    904 
    905 /*
    906  * Paint (or unpaint) the cursor.
    907  */
    908 void
    909 sfb_cursor(id, on, row, col)
    910 	void *id;
    911 	int on, row, col;
    912 {
    913 	struct rcons *rc = id;
    914 	struct raster *rap = rc->rc_sp;
    915 	caddr_t sfb, p;
    916 	int scanspan, height, width, align, x, y;
    917 	u_int32_t lmask, rmask;
    918 
    919 	/* turn the cursor off */
    920 	if (!on) {
    921 		/* make sure it's on */
    922 		if ((rc->rc_bits & RC_CURSOR) == 0)
    923 			return;
    924 
    925 		row = *rc->rc_crowp;
    926 		col = *rc->rc_ccolp;
    927 	} else {
    928 		/* unpaint the old copy. */
    929 		*rc->rc_crowp = row;
    930 		*rc->rc_ccolp = col;
    931 	}
    932 
    933 	x = col * rc->rc_font->width + rc->rc_xorigin;
    934 	y = row * rc->rc_font->height + rc->rc_yorigin;
    935 	scanspan = rap->linelongs * 4;
    936 	height = rc->rc_font->height;
    937 
    938 	p = (caddr_t)rap->pixels + y * scanspan + x;
    939 	align = (long)p & SFBALIGNMASK;
    940 	p -= align;
    941 	width = rc->rc_font->width + align;
    942 	lmask = SFBSTIPPLEALL1 << align;
    943 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
    944 	sfb = rap->data;
    945 
    946 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
    947 	SFBPLANEMASK(sfb, ~0);
    948 	SFBROP(sfb, 6);			/* ROP_XOR */
    949 	SFBFG(sfb, 0x01010101);		/* (fg ^ bg) to swap fg/bg */
    950 	if (width <= SFBSTIPPLEBITS) {
    951 		lmask = lmask & rmask;
    952 		while (height > 0) {
    953 			SFBADDRESS(sfb, (long)p);
    954 			SFBSTART(sfb, lmask);
    955 			p += scanspan;
    956 			height--;
    957 		}
    958 	}
    959 	else {
    960 		caddr_t q = p;
    961 		while (height > 0) {
    962 			*(u_int32_t *)p = lmask;
    963 WRITE_MB();
    964 			p += SFBSTIPPLEBYTESDONE;
    965 			*(u_int32_t *)p = rmask;
    966 WRITE_MB();
    967 
    968 			p = (q += scanspan);
    969 			height--;
    970 		}
    971 	}
    972 	SFBMODE(sfb, MODE_SIMPLE);
    973 	SFBROP(sfb, 3);			/* ROP_COPY */
    974 
    975 	rc->rc_bits ^= RC_CURSOR;
    976 }
    977 
    978 /*
    979  * Actually write a string to the frame buffer.
    980  */
    981 int
    982 sfb_mapchar(id, uni, index)
    983 	void *id;
    984 	int uni;
    985 	unsigned int *index;
    986 {
    987 	if (uni < 128) {
    988 		*index = uni;
    989 		return (5);
    990 	}
    991 	*index = ' ';
    992 	return (0);
    993 }
    994 
    995 /*
    996  * Actually write a string to the frame buffer.
    997  */
    998 void
    999 sfb_putchar(id, row, col, uc, attr)
   1000 	void *id;
   1001 	int row, col;
   1002 	u_int uc;
   1003 	long attr;
   1004 {
   1005 	struct rcons *rc = id;
   1006 	struct raster *rap = rc->rc_sp;
   1007 	caddr_t sfb, p;
   1008 	int scanspan, height, width, align, x, y;
   1009 	u_int32_t lmask, rmask, glyph;
   1010 	u_int32_t *g;
   1011 
   1012 if (uc < 0x20 || uc >= 127) return; /* XXX why \033 is creaping in !? XXX */
   1013 
   1014 	x = col * rc->rc_font->width + rc->rc_xorigin;
   1015 	y = row * rc->rc_font->height + rc->rc_yorigin;
   1016 	scanspan = rap->linelongs * 4;
   1017 	height = rc->rc_font->height;
   1018 	g = rc->rc_font->chars[uc].r->pixels;
   1019 
   1020 	p = (caddr_t)rap->pixels + y * scanspan + x;
   1021 	align = (long)p & SFBALIGNMASK;
   1022 	p -= align;
   1023 	width = rc->rc_font->width + align;
   1024 	lmask = SFBSTIPPLEALL1 << align;
   1025 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1026 	sfb = rap->data;
   1027 	attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
   1028 
   1029 	SFBMODE(sfb, MODE_OPAQUESTIPPLE);
   1030 	SFBPLANEMASK(sfb, ~0);
   1031 	SFBFG(sfb, (attr == 0) ? 0x01010101 : 0);
   1032 	SFBBG(sfb, (attr == 0) ? 0 : 0x01010101);
   1033 	if (width <= SFBSTIPPLEBITS) {
   1034 		lmask = lmask & rmask;
   1035 		while (height > 0) {
   1036 			glyph = *g;
   1037 			SFBPIXELMASK(sfb, lmask);
   1038 			SFBADDRESS(sfb, (long)p);
   1039 			SFBSTART(sfb, glyph << align);
   1040 			p += scanspan;
   1041 			g += 1;
   1042 			height--;
   1043 		}
   1044 	}
   1045 	else {
   1046 		caddr_t q = p;
   1047 		while (height > 0) {
   1048 			glyph = *g;
   1049 			SFBPIXELMASK(sfb, lmask);
   1050 WRITE_MB();
   1051 			*(u_int32_t *)p = glyph << align;
   1052 WRITE_MB();
   1053 			p += SFBSTIPPLEBYTESDONE;
   1054 			SFBPIXELMASK(sfb, rmask);
   1055 WRITE_MB();
   1056 			*(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
   1057 WRITE_MB();
   1058 
   1059 			p = (q += scanspan);
   1060 			g += 1;
   1061 			height--;
   1062 		}
   1063 	}
   1064 	SFBMODE(sfb, MODE_SIMPLE);
   1065 	SFBPIXELMASK(sfb, ~0);		/* entire pixel */
   1066 }
   1067 
   1068 /*
   1069  * Copy characters in a line.
   1070  */
   1071 void
   1072 sfb_copycols(id, row, srccol, dstcol, ncols)
   1073 	void *id;
   1074 	int row, srccol, dstcol, ncols;
   1075 {
   1076 	struct rcons *rc = id;
   1077 	struct raster *rap = rc->rc_sp;
   1078 	caddr_t sp, dp, basex, sfb;
   1079 	int scanspan, height, width, aligns, alignd, shift, w, y;
   1080 	u_int32_t lmasks, rmasks, lmaskd, rmaskd;
   1081 
   1082 	scanspan = rap->linelongs * 4;
   1083 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1084 	basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
   1085 	height = rc->rc_font->height;
   1086 	w = rc->rc_font->width * ncols;
   1087 
   1088 	sp = basex + rc->rc_font->width * srccol;
   1089 	aligns = (long)sp & SFBALIGNMASK;
   1090 	dp = basex + rc->rc_font->width * dstcol;
   1091 	alignd = (long)dp & SFBALIGNMASK;
   1092 
   1093 	shift = alignd - aligns;
   1094 	/* right shift; prime left edge compensating width */
   1095 	if (shift < 0) {
   1096 		dp -= 8;
   1097 		alignd += 8;
   1098 		w += 8;
   1099 	}
   1100 	/* left shift; increase width to drain right edge */
   1101 	else if (shift > 0) {
   1102 		w += 8;
   1103 	}
   1104 	width = w + aligns;
   1105 	lmasks = SFBSTIPPLEALL1 << aligns;
   1106 	rmasks = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1107 	lmaskd = SFBSTIPPLEALL1 << alignd;
   1108 	rmaskd = SFBSTIPPLEALL1 >> (-(w + alignd) & SFBSTIPPLEBITMASK);
   1109 	sfb = rap->data;
   1110 
   1111 	SFBMODE(sfb, MODE_COPY);
   1112 	SFBPLANEMASK(sfb, ~0);
   1113 	SFBPIXELSHIFT(sfb, shift);
   1114 	if (width <= SFBCOPYBITS) {
   1115 		lmasks = lmasks & rmasks;
   1116 		lmaskd = lmaskd & rmaskd;
   1117 		while (height > 0) {
   1118 			*(u_int32_t *)sp = lmasks;
   1119 WRITE_MB();
   1120 			*(u_int32_t *)dp = lmaskd;
   1121 WRITE_MB();
   1122 			sp += scanspan;
   1123 			dp += scanspan;
   1124 			height--;
   1125 		}
   1126 	}
   1127 	/* copy forward (left-to-right) */
   1128 	else if (dstcol < srccol || srccol + ncols < dstcol) {
   1129 		caddr_t sq = sp, dq = dp;
   1130 
   1131 		w = width;
   1132 		while (height > 0) {
   1133 			*(u_int32_t *)sp = lmasks;
   1134 WRITE_MB();
   1135 			*(u_int32_t *)dp = lmaskd;
   1136 WRITE_MB();
   1137 			width -= 2 * SFBCOPYBITS;
   1138 			while (width > 0) {
   1139 				sp += SFBCOPYBYTESDONE;
   1140 				dp += SFBCOPYBYTESDONE;
   1141 				*(u_int32_t *)sp = SFBCOPYALL1;
   1142 WRITE_MB();
   1143 				*(u_int32_t *)dp = SFBCOPYALL1;
   1144 WRITE_MB();
   1145 				width -= SFBCOPYBITS;
   1146 			}
   1147 			sp += SFBCOPYBYTESDONE;
   1148 			dp += SFBCOPYBYTESDONE;
   1149 			*(u_int32_t *)sp = rmasks;
   1150 WRITE_MB();
   1151 			*(u_int32_t *)dp = rmaskd;
   1152 WRITE_MB();
   1153 
   1154 			sp = (sq += scanspan);
   1155 			dp = (dq += scanspan);
   1156 			width = w;
   1157 			height--;
   1158 		}
   1159 	}
   1160 	/* copy backward (right-to-left) */
   1161 	else {
   1162 		caddr_t sq = (sp += width), dq = (dp += width);
   1163 
   1164 		w = width;
   1165 		while (height > 0) {
   1166 			*(u_int32_t *)sp = rmasks;
   1167 WRITE_MB();
   1168 			*(u_int32_t *)dp = rmaskd;
   1169 WRITE_MB();
   1170 			width -= 2 * SFBCOPYBITS;
   1171 			while (width > 0) {
   1172 				sp -= SFBCOPYBYTESDONE;
   1173 				dp -= SFBCOPYBYTESDONE;
   1174 				*(u_int32_t *)sp = SFBCOPYALL1;
   1175 WRITE_MB();
   1176 				*(u_int32_t *)dp = SFBCOPYALL1;
   1177 WRITE_MB();
   1178 				width -= SFBCOPYBITS;
   1179 			}
   1180 			sp -= SFBCOPYBYTESDONE;
   1181 			dp -= SFBCOPYBYTESDONE;
   1182 			*(u_int32_t *)sp = lmasks;
   1183 WRITE_MB();
   1184 			*(u_int32_t *)dp = lmaskd;
   1185 WRITE_MB();
   1186 
   1187 			sp = (sq += scanspan);
   1188 			dp = (dq += scanspan);
   1189 			width = w;
   1190 			height--;
   1191 		}
   1192 	}
   1193 	SFBMODE(sfb, MODE_SIMPLE);
   1194 }
   1195 
   1196 /*
   1197  * Clear characters in a line.
   1198  */
   1199 void
   1200 sfb_erasecols(id, row, startcol, ncols, attr)
   1201 	void *id;
   1202 	int row, startcol, ncols;
   1203 	long attr;
   1204 {
   1205 	struct rcons *rc = id;
   1206 	struct raster *rap = rc->rc_sp;
   1207 	caddr_t sfb, p;
   1208 	int scanspan, startx, height, width, align, w, y;
   1209 	u_int32_t lmask, rmask;
   1210 
   1211 	scanspan = rap->linelongs * 4;
   1212 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1213 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
   1214 	height = rc->rc_font->height;
   1215 	w = rc->rc_font->width * ncols;
   1216 
   1217 	p = (caddr_t)rap->pixels + y * scanspan + startx;
   1218 	align = (long)p & SFBALIGNMASK;
   1219 	p -= align;
   1220 	width = w + align;
   1221 	lmask = SFBSTIPPLEALL1 << align;
   1222 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1223 	sfb = rap->data;
   1224 
   1225 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1226 	SFBPLANEMASK(sfb, ~0);
   1227 	SFBFG(sfb, 0);				/* fill with bg color */
   1228 	if (width <= SFBSTIPPLEBITS) {
   1229 		lmask = lmask & rmask;
   1230 		while (height > 0) {
   1231 			SFBADDRESS(sfb, (long)p);
   1232 			SFBSTART(sfb, lmask);
   1233 			p += scanspan;
   1234 			height--;
   1235 		}
   1236 	}
   1237 	else {
   1238 		caddr_t q = p;
   1239 		while (height > 0) {
   1240 			*(u_int32_t *)p = lmask;
   1241 WRITE_MB();
   1242 			width -= 2 * SFBSTIPPLEBITS;
   1243 			while (width > 0) {
   1244 				p += SFBSTIPPLEBYTESDONE;
   1245 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1246 WRITE_MB();
   1247 				width -= SFBSTIPPLEBITS;
   1248 			}
   1249 			p += SFBSTIPPLEBYTESDONE;
   1250 			*(u_int32_t *)p = rmask;
   1251 WRITE_MB();
   1252 
   1253 			p = (q += scanspan);
   1254 			width = w + align;
   1255 			height--;
   1256 		}
   1257 	}
   1258 	SFBMODE(sfb, MODE_SIMPLE);
   1259 }
   1260 
   1261 /*
   1262  * Copy lines.
   1263  */
   1264 void
   1265 sfb_copyrows(id, srcrow, dstrow, nrows)
   1266 	void *id;
   1267 	int srcrow, dstrow, nrows;
   1268 {
   1269 	struct rcons *rc = id;
   1270 	struct raster *rap = rc->rc_sp;
   1271 	caddr_t sfb, p;
   1272 	int scanspan, offset, srcy, height, width, align, w;
   1273 	u_int32_t lmask, rmask;
   1274 
   1275 	scanspan = rap->linelongs * 4;
   1276 	height = rc->rc_font->height * nrows;
   1277 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1278 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1279 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1280 		scanspan = -scanspan;
   1281 		srcy += height;
   1282 	}
   1283 
   1284 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1285 	align = (long)p & SFBALIGNMASK;
   1286 	p -= align;
   1287 	w = rc->rc_font->width * rc->rc_maxcol;
   1288 	width = w + align;
   1289 	lmask = SFBCOPYALL1 << align;
   1290 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1291 	sfb = rap->data;
   1292 
   1293 	SFBMODE(sfb, MODE_COPY);
   1294 	SFBPLANEMASK(sfb, ~0);
   1295 	SFBPIXELSHIFT(sfb, 0);
   1296 	if (width <= SFBCOPYBITS) {
   1297 		/* never happens */;
   1298 	}
   1299 	else {
   1300 		caddr_t q = p;
   1301 		while (height > 0) {
   1302 			*(u_int32_t *)p = lmask;
   1303 			*(u_int32_t *)(p + offset) = lmask;
   1304 			width -= 2 * SFBCOPYBITS;
   1305 			while (width > 0) {
   1306 				p += SFBCOPYBYTESDONE;
   1307 				*(u_int32_t *)p = SFBCOPYALL1;
   1308 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1309 				width -= SFBCOPYBITS;
   1310 			}
   1311 			p += SFBCOPYBYTESDONE;
   1312 			*(u_int32_t *)p = rmask;
   1313 			*(u_int32_t *)(p + offset) = rmask;
   1314 
   1315 			p = (q += scanspan);
   1316 			width = w + align;
   1317 			height--;
   1318 		}
   1319 	}
   1320 	SFBMODE(sfb, MODE_SIMPLE);
   1321 }
   1322 
   1323 /*
   1324  * Erase lines.
   1325  */
   1326 void
   1327 sfb_eraserows(id, startrow, nrows, attr)
   1328 	void *id;
   1329 	int startrow, nrows;
   1330 	long attr;
   1331 {
   1332 	struct rcons *rc = id;
   1333 	struct raster *rap = rc->rc_sp;
   1334 	caddr_t sfb, p;
   1335 	int scanspan, starty, height, width, align, w;
   1336 	u_int32_t lmask, rmask;
   1337 
   1338 	scanspan = rap->linelongs * 4;
   1339 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1340 	height = rc->rc_font->height * nrows;
   1341 
   1342 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1343 	align = (long)p & SFBALIGNMASK;
   1344 	p -= align;
   1345 	w = rc->rc_font->width * rc->rc_maxcol;
   1346 	width = w + align;
   1347 	lmask = SFBSTIPPLEALL1 << align;
   1348 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1349 	sfb = rap->data;
   1350 
   1351 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1352 	SFBPLANEMASK(sfb, ~0);
   1353 	SFBFG(sfb, 0);				/* fill with bg color */
   1354 	if (width <= SFBSTIPPLEBITS) {
   1355 		/* never happens */;
   1356 	}
   1357 	else {
   1358 		caddr_t q = p;
   1359 		while (height > 0) {
   1360 			*(u_int32_t *)p = lmask;
   1361 WRITE_MB();
   1362 			width -= 2 * SFBSTIPPLEBITS;
   1363 			while (width > 0) {
   1364 				p += SFBSTIPPLEBYTESDONE;
   1365 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1366 WRITE_MB();
   1367 				width -= SFBSTIPPLEBITS;
   1368 			}
   1369 			p += SFBSTIPPLEBYTESDONE;
   1370 			*(u_int32_t *)p = rmask;
   1371 WRITE_MB();
   1372 
   1373 			p = (q += scanspan);
   1374 			width = w + align;
   1375 			height--;
   1376 		}
   1377 	}
   1378 	SFBMODE(sfb, MODE_SIMPLE);
   1379 }
   1380 
   1381 int
   1382 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1383 	void *id;
   1384 	int fg, bg, flags;
   1385 	long *attrp;
   1386 {
   1387 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1388 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1389 		return (EINVAL);
   1390 	if (flags & WSATTR_REVERSE)
   1391 		*attrp = 1;
   1392 	else
   1393 		*attrp = 0;
   1394 	return (0);
   1395 }
   1396