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