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