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