Home | History | Annotate | Line # | Download | only in tc
sfb.c revision 1.24
      1 /* $NetBSD: sfb.c,v 1.24 1999/10/27 04:32:35 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.24 1999/10/27 04:32:35 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, align, shift, w, y;
   1080 	u_int32_t lmask, rmask;
   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 	dp = basex + rc->rc_font->width * dstcol;
   1089 	sp = basex + rc->rc_font->width * srccol;
   1090 
   1091 	align = shift = (long)sp & SFBALIGNMASK;
   1092 	sp -= align;
   1093 	width = w + align;
   1094 	align = (long)dp & SFBALIGNMASK;
   1095 	dp -= align;
   1096 	shift = align - shift;
   1097 #if 1
   1098 	if (shift < 0) {
   1099 		align += 8;
   1100 		dp -= 8;
   1101 	}
   1102 #endif
   1103 	lmask = SFBCOPYALL1 << align;
   1104 	rmask = SFBCOPYALL1 >> (-(w + align) & SFBCOPYBITMASK);
   1105 	sfb = rap->data;
   1106 
   1107 	SFBMODE(sfb, MODE_COPY);
   1108 	SFBPLANEMASK(sfb, ~0);
   1109 	SFBPIXELSHIFT(sfb, shift);
   1110 	if (width <= SFBCOPYBITS) {
   1111 		lmask = lmask & rmask;
   1112 		while (height > 0) {
   1113 			*(u_int32_t *)sp = SFBCOPYALL1;
   1114 WRITE_MB();
   1115 			*(u_int32_t *)dp = lmask;
   1116 WRITE_MB();
   1117 			sp += scanspan;
   1118 			dp += scanspan;
   1119 			height--;
   1120 		}
   1121 	}
   1122 	/* copy forward (left-to-right) */
   1123 	else if (dstcol < srccol || srccol + ncols < dstcol) {
   1124 		caddr_t sq = sp, dq = dp;
   1125 
   1126 		w = width;
   1127 		while (height > 0) {
   1128 			*(u_int32_t *)sp = SFBCOPYALL1;
   1129 WRITE_MB();
   1130 			*(u_int32_t *)dp = lmask;
   1131 WRITE_MB();
   1132 			width -= 2 * SFBCOPYBITS;
   1133 			while (width > 0) {
   1134 				sp += SFBCOPYBYTESDONE;
   1135 				dp += SFBCOPYBYTESDONE;
   1136 				*(u_int32_t *)sp = SFBCOPYALL1;
   1137 WRITE_MB();
   1138 				*(u_int32_t *)dp = SFBCOPYALL1;
   1139 WRITE_MB();
   1140 				width -= SFBCOPYBITS;
   1141 			}
   1142 			sp += SFBCOPYBYTESDONE;
   1143 			dp += SFBCOPYBYTESDONE;
   1144 			*(u_int32_t *)sp = SFBCOPYALL1;
   1145 WRITE_MB();
   1146 			*(u_int32_t *)dp = rmask;
   1147 WRITE_MB();
   1148 
   1149 			sp = (sq += scanspan);
   1150 			dp = (dq += scanspan);
   1151 			width = w;
   1152 			height--;
   1153 		}
   1154 	}
   1155 	/* copy backward (right-to-left) */
   1156 	else {
   1157 		caddr_t sq = (sp += width), dq = (dp += width);
   1158 
   1159 		w = width;
   1160 		while (height > 0) {
   1161 			*(u_int32_t *)sp = SFBCOPYALL1;
   1162 WRITE_MB();
   1163 			*(u_int32_t *)dp = rmask;
   1164 WRITE_MB();
   1165 			width -= 2 * SFBCOPYBITS;
   1166 			while (width > 0) {
   1167 				sp -= SFBCOPYBYTESDONE;
   1168 				dp -= SFBCOPYBYTESDONE;
   1169 				*(u_int32_t *)sp = SFBCOPYALL1;
   1170 WRITE_MB();
   1171 				*(u_int32_t *)dp = SFBCOPYALL1;
   1172 WRITE_MB();
   1173 				width -= SFBCOPYBITS;
   1174 			}
   1175 			sp -= SFBCOPYBYTESDONE;
   1176 			dp -= SFBCOPYBYTESDONE;
   1177 			*(u_int32_t *)sp = SFBCOPYALL1;
   1178 WRITE_MB();
   1179 			*(u_int32_t *)dp = lmask;
   1180 WRITE_MB();
   1181 
   1182 			sp = (sq += scanspan);
   1183 			dp = (dq += scanspan);
   1184 			width = w;
   1185 			height--;
   1186 		}
   1187 	}
   1188 	SFBMODE(sfb, MODE_SIMPLE);
   1189 }
   1190 
   1191 /*
   1192  * Clear characters in a line.
   1193  */
   1194 void
   1195 sfb_erasecols(id, row, startcol, ncols, attr)
   1196 	void *id;
   1197 	int row, startcol, ncols;
   1198 	long attr;
   1199 {
   1200 	struct rcons *rc = id;
   1201 	struct raster *rap = rc->rc_sp;
   1202 	caddr_t sfb, p;
   1203 	int scanspan, startx, height, width, align, w, y;
   1204 	u_int32_t lmask, rmask;
   1205 
   1206 	scanspan = rap->linelongs * 4;
   1207 	y = rc->rc_yorigin + rc->rc_font->height * row;
   1208 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
   1209 	height = rc->rc_font->height;
   1210 	w = rc->rc_font->width * ncols;
   1211 
   1212 	p = (caddr_t)rap->pixels + y * scanspan + startx;
   1213 	align = (long)p & SFBALIGNMASK;
   1214 	p -= align;
   1215 	width = w + align;
   1216 	lmask = SFBSTIPPLEALL1 << align;
   1217 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1218 	sfb = rap->data;
   1219 
   1220 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1221 	SFBPLANEMASK(sfb, ~0);
   1222 	SFBFG(sfb, 0);				/* fill with bg color */
   1223 	if (width <= SFBSTIPPLEBITS) {
   1224 		lmask = lmask & rmask;
   1225 		while (height > 0) {
   1226 			SFBADDRESS(sfb, (long)p);
   1227 			SFBSTART(sfb, lmask);
   1228 			p += scanspan;
   1229 			height--;
   1230 		}
   1231 	}
   1232 	else {
   1233 		caddr_t q = p;
   1234 		while (height > 0) {
   1235 			*(u_int32_t *)p = lmask;
   1236 WRITE_MB();
   1237 			width -= 2 * SFBSTIPPLEBITS;
   1238 			while (width > 0) {
   1239 				p += SFBSTIPPLEBYTESDONE;
   1240 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1241 WRITE_MB();
   1242 				width -= SFBSTIPPLEBITS;
   1243 			}
   1244 			p += SFBSTIPPLEBYTESDONE;
   1245 			*(u_int32_t *)p = rmask;
   1246 WRITE_MB();
   1247 
   1248 			p = (q += scanspan);
   1249 			width = w + align;
   1250 			height--;
   1251 		}
   1252 	}
   1253 	SFBMODE(sfb, MODE_SIMPLE);
   1254 }
   1255 
   1256 /*
   1257  * Copy lines.
   1258  */
   1259 void
   1260 sfb_copyrows(id, srcrow, dstrow, nrows)
   1261 	void *id;
   1262 	int srcrow, dstrow, nrows;
   1263 {
   1264 	struct rcons *rc = id;
   1265 	struct raster *rap = rc->rc_sp;
   1266 	caddr_t sfb, p;
   1267 	int scanspan, offset, srcy, height, width, align, w;
   1268 	u_int32_t lmask, rmask;
   1269 
   1270 	scanspan = rap->linelongs * 4;
   1271 	height = rc->rc_font->height * nrows;
   1272 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
   1273 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
   1274 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
   1275 		scanspan = -scanspan;
   1276 		srcy += height;
   1277 	}
   1278 
   1279 	p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
   1280 	align = (long)p & SFBALIGNMASK;
   1281 	p -= align;
   1282 	w = rc->rc_font->width * rc->rc_maxcol;
   1283 	width = w + align;
   1284 	lmask = SFBCOPYALL1 << align;
   1285 	rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
   1286 	sfb = rap->data;
   1287 
   1288 	SFBMODE(sfb, MODE_COPY);
   1289 	SFBPLANEMASK(sfb, ~0);
   1290 	SFBPIXELSHIFT(sfb, 0);
   1291 	if (width <= SFBCOPYBITS) {
   1292 		/* never happens */;
   1293 	}
   1294 	else {
   1295 		caddr_t q = p;
   1296 		while (height > 0) {
   1297 			*(u_int32_t *)p = lmask;
   1298 			*(u_int32_t *)(p + offset) = lmask;
   1299 			width -= 2 * SFBCOPYBITS;
   1300 			while (width > 0) {
   1301 				p += SFBCOPYBYTESDONE;
   1302 				*(u_int32_t *)p = SFBCOPYALL1;
   1303 				*(u_int32_t *)(p + offset) = SFBCOPYALL1;
   1304 				width -= SFBCOPYBITS;
   1305 			}
   1306 			p += SFBCOPYBYTESDONE;
   1307 			*(u_int32_t *)p = rmask;
   1308 			*(u_int32_t *)(p + offset) = rmask;
   1309 
   1310 			p = (q += scanspan);
   1311 			width = w + align;
   1312 			height--;
   1313 		}
   1314 	}
   1315 	SFBMODE(sfb, MODE_SIMPLE);
   1316 }
   1317 
   1318 /*
   1319  * Erase lines.
   1320  */
   1321 void
   1322 sfb_eraserows(id, startrow, nrows, attr)
   1323 	void *id;
   1324 	int startrow, nrows;
   1325 	long attr;
   1326 {
   1327 	struct rcons *rc = id;
   1328 	struct raster *rap = rc->rc_sp;
   1329 	caddr_t sfb, p;
   1330 	int scanspan, starty, height, width, align, w;
   1331 	u_int32_t lmask, rmask;
   1332 
   1333 	scanspan = rap->linelongs * 4;
   1334 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
   1335 	height = rc->rc_font->height * nrows;
   1336 
   1337 	p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
   1338 	align = (long)p & SFBALIGNMASK;
   1339 	p -= align;
   1340 	w = rc->rc_font->width * rc->rc_maxcol;
   1341 	width = w + align;
   1342 	lmask = SFBSTIPPLEALL1 << align;
   1343 	rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
   1344 	sfb = rap->data;
   1345 
   1346 	SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
   1347 	SFBPLANEMASK(sfb, ~0);
   1348 	SFBFG(sfb, 0);				/* fill with bg color */
   1349 	if (width <= SFBSTIPPLEBITS) {
   1350 		/* never happens */;
   1351 	}
   1352 	else {
   1353 		caddr_t q = p;
   1354 		while (height > 0) {
   1355 			*(u_int32_t *)p = lmask;
   1356 WRITE_MB();
   1357 			width -= 2 * SFBSTIPPLEBITS;
   1358 			while (width > 0) {
   1359 				p += SFBSTIPPLEBYTESDONE;
   1360 				*(u_int32_t *)p = SFBSTIPPLEALL1;
   1361 WRITE_MB();
   1362 				width -= SFBSTIPPLEBITS;
   1363 			}
   1364 			p += SFBSTIPPLEBYTESDONE;
   1365 			*(u_int32_t *)p = rmask;
   1366 WRITE_MB();
   1367 
   1368 			p = (q += scanspan);
   1369 			width = w + align;
   1370 			height--;
   1371 		}
   1372 	}
   1373 	SFBMODE(sfb, MODE_SIMPLE);
   1374 }
   1375 
   1376 int
   1377 sfb_alloc_attr(id, fg, bg, flags, attrp)
   1378 	void *id;
   1379 	int fg, bg, flags;
   1380 	long *attrp;
   1381 {
   1382 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
   1383 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
   1384 		return (EINVAL);
   1385 	if (flags & WSATTR_REVERSE)
   1386 		*attrp = 1;
   1387 	else
   1388 		*attrp = 0;
   1389 	return (0);
   1390 }
   1391