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