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