xref: /netbsd/sys/arch/playstation2/ee/gsfb.c (revision beecddb6)
1 /*	$NetBSD: gsfb.c,v 1.24 2021/08/07 16:19:02 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
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: gsfb.c,v 1.24 2021/08/07 16:19:02 thorpej Exp $");
34 
35 #include "debug_playstation2.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 
40 #include <machine/autoconf.h>
41 
42 #include <dev/cons.h>
43 
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wscons/wsdisplayvar.h>
46 #include <dev/wscons/wscons_callbacks.h>
47 
48 #include <dev/wsfont/wsfont.h>
49 
50 #include <playstation2/ee/eevar.h>
51 #include <playstation2/ee/gsvar.h>
52 #include <playstation2/ee/gsreg.h>
53 #include <playstation2/ee/dmacvar.h>
54 #include <playstation2/ee/dmacreg.h>
55 
56 #ifdef DEBUG
57 #define STATIC
58 #else
59 #define STATIC	static
60 #endif
61 
62 struct gsfb_softc {
63 	device_t sc_dev;
64 	const struct wsscreen_descr *sc_screen;
65 	struct wsdisplay_font *sc_font;
66 	bool sc_is_console;
67 };
68 
69 static int gsfb_is_console;
70 static struct gsfb_softc gsfb_console_softc;
71 
72 STATIC void gsfb_dma_kick(paddr_t, size_t);
73 STATIC void gsfb_font_expand_psmct32(const struct wsdisplay_font *, u_int,
74     long, u_int32_t *);
75 STATIC inline void gsfb_set_cursor_pos(u_int32_t *, int, int, int, int);
76 
77 #define ATTR_FG_GET(a)	(((a )>> 24) & 0xf)
78 #define ATTR_BG_GET(a)	(((a )>> 16) & 0xf)
79 #define ATTR_FG_SET(x)	(((x) << 24) & 0x0f000000)
80 #define ATTR_BG_SET(x)	(((x) << 16) & 0x000f0000)
81 
82 STATIC const u_int32_t gsfb_ansi_psmct32[] = {
83 	0x80000000, /* black */
84 	0x800000aa, /* red */
85 	0x8000aa00, /* green */
86 	0x8000aaaa, /* brown */
87 	0x80aa0000, /* blue */
88 	0x80aa00aa, /* magenta */
89 	0x80aaaa00, /* cyan */
90 	0x80aaaaaa, /* white */
91 	0x80000000, /* black */
92 	0x800000ff, /* red */
93 	0x8000ff00, /* green */
94 	0x8000ffff, /* brown */
95 	0x80ff0000, /* blue */
96 	0x80ff00ff, /* magenta */
97 	0x80ffff00, /* cyan */
98 	0x80ffffff, /* black */
99 };
100 
101 #define TRXPOS_DXY(f, x, y)						\
102 ({									\
103 	f[9] = ((x) & 0x000007ff) | (((y) << 16) & 0x07ff0000);		\
104 })
105 
106 #define TRXPOS_SY_DY(f, sy, dy)						\
107 ({									\
108 	f[8] = (((sy) << 16) & 0x07ff0000);				\
109 	f[9] = (((dy) << 16) & 0x07ff0000);				\
110 })
111 
112 #define TRXPOS_DXY_SXY(f, dx, dy, sx, sy)				\
113 ({									\
114 	f[8] = ((((sy) << 16) & 0x07ff0000) | ((sx) & 0x000007ff));	\
115 	f[9] = ((((dy) << 16) & 0x07ff0000) | ((dx) & 0x000007ff));	\
116 })
117 
118 STATIC u_int32_t gsfb_scroll_cmd_640x16[] __attribute__((__aligned__(16))) = {
119         0x00008004, 0x10000000, 0x0000000e, 0x00000000,
120         0x000a0000, 0x000a0000, 0x00000050, 0x00000000,
121         0x07ff0000, 0x07ff0000, 0x00000051, 0x00000000,
122         0x00000280, 0x00000010, 0x00000052, 0x00000000,
123         0x00000002, 0x00000000, 0x00000053, 0x00000000,
124 };
125 
126 STATIC u_int32_t gsfb_cursor_cmd[] __attribute__((__aligned__(16))) = {
127 	0x00008007, 0x10000000, 0x0000000e, 0x00000000,
128 	0x00000001, 0x00000000, 0x0000001a, 0x00000000,
129         0x000000a4, 0x00000080, 0x00000042, 0x00000000,
130 	0x00000046, 0x00000000, 0x00000000, 0x00000000,
131 	0x80ffffff, 0x00000000, 0x00000001, 0x00000000,
132 	0x00000000, 0x00000000, 0x0000000d, 0x00000000,
133 	0x80ffffff, 0x00000000, 0x00000001, 0x00000000,
134 	0x00000000, 0x00000000, 0x00000005, 0x00000000,
135 };
136 
137 STATIC u_int32_t gsfb_copy_cmd_8x16[] __attribute__((__aligned__(16))) = {
138         0x00008004, 0x10000000, 0x0000000e, 0x00000000,
139         0x000a0000, 0x000a0000, 0x00000050, 0x00000000,
140         0x07ff07ff, 0x07ff07ff, 0x00000051, 0x00000000,
141         0x00000008, 0x00000010, 0x00000052, 0x00000000,
142         0x00000002, 0x00000000, 0x00000053, 0x00000000,
143 };
144 
145 STATIC u_int32_t gsfb_init_cmd_640x480[] __attribute__((__aligned__(16))) = {
146 	0x00008008, 0x10000000, 0x0000000e, 0x00000000,
147 	0x000a0000, 0x00000000, 0x0000004c, 0x00000000,
148 	0x00000096, 0x00000000, 0x0000004e, 0x00000000,
149 	0x02800000, 0x01e00000, 0x00000040, 0x00000000,
150 	0x00000006, 0x00000000, 0x00000000, 0x00000000,
151 	0x80000000, 0x00000000, 0x00000001, 0x00000000,
152 	0x00000000, 0x00000000, 0x0000000d, 0x00000000,
153 	0x80000000, 0x00000000, 0x00000001, 0x00000000,
154 	0x1e002800, 0x00000000, 0x00000005, 0x00000000,
155 };
156 
157 STATIC u_int32_t gsfb_load_cmd_8x16_psmct32[(6 + 32) * 4]
158 	__attribute__((__aligned__(16))) = {
159 	/* GIF tag + GS command */
160         0x00000004, 0x10000000, 0x0000000e, 0x00000000,
161         0x00000000, 0x000a0000, 0x00000050, 0x00000000,
162         0x00000000, 0x00000000, 0x00000051, 0x00000000,
163         0x00000008, 0x00000016, 0x00000052, 0x00000000,
164         0x00000000, 0x00000000, 0x00000053, 0x00000000,
165         0x00008020, 0x08000000, 0x00000000, 0x00000000,
166 	/* Load area */
167 #define FONT_SCRATCH_BASE	(6 * 4)
168 };
169 
170 #ifdef GSFB_DEBUG_MONITOR
171 #include <machine/stdarg.h>
172 STATIC const struct _gsfb_debug_window {
173 	int start, nrow, attr;
174 } _gsfb_debug_window[3] = {
175 	{ 24, 2 , ATTR_BG_SET(WSCOL_BROWN) | ATTR_FG_SET(WSCOL_BLUE) },
176 	{ 26, 2 , ATTR_BG_SET(WSCOL_CYAN) | ATTR_FG_SET(WSCOL_BLUE) },
177 	{ 28, 2 , ATTR_BG_SET(WSCOL_WHITE) | ATTR_FG_SET(WSCOL_BLUE) },
178 };
179 STATIC char _gsfb_debug_buf[80 * 2];
180 #endif /* GSFB_DEBUG_MONITOR */
181 
182 STATIC int gsfb_match(device_t, cfdata_t, void *);
183 STATIC void gsfb_attach(device_t, device_t, void *);
184 
185 CFATTACH_DECL_NEW(gsfb, sizeof(struct gsfb_softc),
186     gsfb_match, gsfb_attach, NULL, NULL);
187 
188 STATIC void gsfb_hwinit(void);
189 STATIC int gsfb_swinit(struct gsfb_softc*);
190 
191 /* console */
192 void gsfbcnprobe(struct consdev *);
193 void gsfbcninit(struct consdev *);
194 
195 /* emul ops */
196 STATIC void _gsfb_cursor(void *, int, int, int);
197 STATIC int _gsfb_mapchar(void *, int, unsigned int *);
198 STATIC void _gsfb_putchar(void *, int, int, u_int, long);
199 STATIC void _gsfb_copycols(void *, int, int, int, int);
200 STATIC void _gsfb_erasecols(void *, int, int, int, long);
201 STATIC void _gsfb_copyrows(void *, int, int, int);
202 STATIC void _gsfb_eraserows(void *, int, int, long);
203 STATIC int _gsfb_allocattr(void *, int, int, int, long *);
204 
205 /* access ops */
206 STATIC int _gsfb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
207 STATIC paddr_t _gsfb_mmap(void *, void *, off_t, int);
208 STATIC int _gsfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
209     int *, int *, long *);
210 STATIC void _gsfb_free_screen(void *, void *);
211 STATIC int _gsfb_show_screen(void *, void *, int, void (*)(void *, int, int),
212     void *);
213 STATIC void _gsfb_pollc(void *, int);
214 
215 /*
216  * wsdisplay attach args
217  *   std: screen size 640 x 480, font size 8 x 16
218  */
219 #define GSFB_STD_SCREEN_WIDTH		640
220 #define GSFB_STD_SCREEN_HEIGHT		480
221 #define GSFB_STD_FONT_WIDTH		8
222 #define GSFB_STD_FONT_HEIGHT		16
223 const struct wsdisplay_emulops _gsfb_emulops = {
224 	.cursor		= _gsfb_cursor,
225 	.mapchar	= _gsfb_mapchar,
226 	.putchar	= _gsfb_putchar,
227 	.copycols	= _gsfb_copycols,
228 	.erasecols	= _gsfb_erasecols,
229 	.copyrows	= _gsfb_copyrows,
230 	.eraserows	= _gsfb_eraserows,
231 	.allocattr	= _gsfb_allocattr
232 };
233 
234 const struct wsscreen_descr _gsfb_std_screen = {
235 	.name		= "std",
236 	.ncols		= 80,
237 #ifdef GSFB_DEBUG_MONITOR
238 	.nrows		= 24,
239 #else
240 	.nrows		= 30,
241 #endif
242 	.textops	= &_gsfb_emulops,
243 	.fontwidth	= 8,
244 	.fontheight	= 16,
245 	.capabilities	= WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
246 	WSSCREEN_WSCOLORS
247 };
248 
249 const struct wsscreen_descr *_gsfb_screen_table[] = {
250 	&_gsfb_std_screen,
251 };
252 
253 struct wsscreen_list _gsfb_screen_list = {
254 	.nscreens	= sizeof(_gsfb_screen_table) /
255 	sizeof(_gsfb_screen_table[0]),
256 	.screens	= _gsfb_screen_table
257 };
258 
259 struct wsdisplay_accessops _gsfb_accessops = {
260 	.ioctl		= _gsfb_ioctl,
261 	.mmap		= _gsfb_mmap,
262 	.alloc_screen	= _gsfb_alloc_screen,
263 	.free_screen	= _gsfb_free_screen,
264 	.show_screen	= _gsfb_show_screen,
265 	.load_font	= 0,
266 	.pollc		= _gsfb_pollc
267 };
268 
269 int
gsfb_match(device_t parent,cfdata_t cf,void * aux)270 gsfb_match(device_t parent, cfdata_t cf, void *aux)
271 {
272 	extern struct cfdriver gsfb_cd;
273 	struct mainbus_attach_args *ma = aux;
274 
275 	if (strcmp(ma->ma_name, gsfb_cd.cd_name) != 0)
276 		return (0);
277 
278 	return 1;
279 }
280 
281 void
gsfb_attach(device_t parent,device_t self,void * aux)282 gsfb_attach(device_t parent, device_t self, void *aux)
283 {
284 	struct wsemuldisplaydev_attach_args wa;
285 	struct gsfb_softc *sc = device_private(self);
286 
287 	if (gsfb_is_console) {
288 		memcpy(sc, &gsfb_console_softc, sizeof(gsfb_console_softc));
289 		sc->sc_is_console = true;
290 	}
291 	sc->sc_dev = self;
292 
293 	if (!sc->sc_is_console && !gsfb_swinit(sc) != 0)
294 		return;
295 
296 	printf("\n");
297 
298 	wa.console	= sc->sc_is_console;
299 	wa.scrdata	= &_gsfb_screen_list;
300 	wa.accessops	= &_gsfb_accessops;
301 	wa.accesscookie	= sc;
302 
303 	config_found(self, &wa, wsdisplaydevprint, CFARGS_NONE);
304 }
305 
306 /*
307  * console
308  */
309 void
gsfbcnprobe(struct consdev * cndev)310 gsfbcnprobe(struct consdev *cndev)
311 {
312 
313 	cndev->cn_pri = CN_INTERNAL;
314 }
315 
316 void
gsfbcninit(struct consdev * cndev)317 gsfbcninit(struct consdev *cndev)
318 {
319 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_init_cmd_640x480);
320 	u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
321 	long defattr =  ATTR_BG_SET(WS_DEFAULT_BG) | ATTR_FG_SET(WS_DEFAULT_FG);
322 
323 	gsfb_is_console = 1;
324 
325 	gsfb_hwinit();
326 	gsfb_swinit(&gsfb_console_softc);
327 
328 	/* Set the screen to the default background color at boot */
329 	buf[28] = gsfb_ansi_psmct32[ATTR_BG_GET(defattr)];
330 	gsfb_dma_kick(paddr, sizeof gsfb_init_cmd_640x480);
331 #ifdef GSFB_DEBUG_MONITOR
332 	{
333 		const struct _gsfb_debug_window *win;
334 		int i;
335 
336 		for (i = 0; i < 3; i++) {
337 			win = &_gsfb_debug_window[i];
338 			_gsfb_eraserows(0, win->start, win->nrow, win->attr);
339 		}
340 	}
341 #endif /* GSFB_DEBUG_MONITOR */
342 
343 	wsdisplay_cnattach(&_gsfb_std_screen, &gsfb_console_softc, 0, 0,
344 	    defattr);
345 }
346 
347 void
gsfb_hwinit(void)348 gsfb_hwinit(void)
349 {
350 	/*
351 	  gs_init(VESA_1A) hang up on SCPH-50000.
352 	  use bootloader's setting.
353 	  EN1 | CRTMOD | MMOD | AMOD | ALP(all 1.0)
354 	*/
355 	_reg_write_8(GS_S_PMODE_REG, 0xffa5);
356 
357 	dmac_init();
358 
359 	/* reset GIF channel DMA */
360 	_reg_write_4(D2_QWC_REG, 0);
361 	_reg_write_4(D2_MADR_REG, 0);
362 	_reg_write_4(D2_TADR_REG, 0);
363 	_reg_write_4(D2_CHCR_REG, 0);
364 }
365 
366 int
gsfb_swinit(struct gsfb_softc * sc)367 gsfb_swinit(struct gsfb_softc *sc)
368 {
369 	int font;
370 
371 	wsfont_init();
372 	font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
373 	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
374 	if (font < 0)
375 		return (1);
376 
377 	if (wsfont_lock(font, &sc->sc_font))
378 		return (1);
379 
380 	sc->sc_screen = &_gsfb_std_screen;
381 
382 	return (0);
383 }
384 
385 /*
386  * wsdisplay
387  */
388 void
_gsfb_cursor(void * cookie,int on,int row,int col)389 _gsfb_cursor(void *cookie, int on, int row, int col)
390 {
391 	struct gsfb_softc *sc = cookie;
392 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_cursor_cmd);
393 	u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
394 	struct wsdisplay_font *font = sc->sc_font;
395 
396 	gsfb_set_cursor_pos(buf, col, row, font->fontwidth, font->fontheight);
397 
398 	gsfb_dma_kick(paddr, sizeof gsfb_cursor_cmd);
399 }
400 
401 inline void
gsfb_set_cursor_pos(u_int32_t * p,int x,int y,int w,int h)402 gsfb_set_cursor_pos(u_int32_t *p, int x, int y, int w, int h)
403 {
404 
405 	x *= w;
406 	y *= h;
407 	p[20] = ((x << 4) & 0xffff) | ((y << 20) & 0xffff0000);
408 	p[28] = (((x + w) << 4) & 0xffff) | (((y + h) << 20) & 0xffff0000);
409 }
410 
411 int
_gsfb_mapchar(void * cookie,int c,unsigned int * cp)412 _gsfb_mapchar(void *cookie, int c, unsigned int *cp)
413 {
414 	struct gsfb_softc *sc = cookie;
415 	struct wsdisplay_font *font = sc->sc_font;
416 
417 	if (font->encoding != WSDISPLAY_FONTENC_ISO)
418 		if ((c = wsfont_map_unichar(font, c)) < 0)
419 			goto nomap;
420 
421 	if (c < font->firstchar || c >= font->firstchar + font->numchars)
422 			goto nomap;
423 
424 	*cp = c;
425 	return (5);
426 
427  nomap:
428 	*cp = ' ';
429 	return (0);
430 }
431 
432 void
_gsfb_putchar(void * cookie,int row,int col,u_int uc,long attr)433 _gsfb_putchar(void *cookie, int row, int col, u_int uc, long attr)
434 {
435 	struct gsfb_softc *sc = cookie;
436 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_load_cmd_8x16_psmct32);
437 	u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
438 	struct wsdisplay_font *font = sc->sc_font;
439 
440 	/* copy font data to DMA region */
441 	gsfb_font_expand_psmct32(font, uc, attr, &buf[FONT_SCRATCH_BASE]);
442 
443 	/* set destination position */
444 	TRXPOS_DXY(buf, col * font->fontwidth, row * font->fontheight);
445 
446 	/* kick to GIF */
447 	gsfb_dma_kick(paddr, sizeof gsfb_load_cmd_8x16_psmct32);
448 }
449 
450 void
_gsfb_copycols(void * cookie,int row,int srccol,int dstcol,int ncols)451 _gsfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
452 {
453 	struct gsfb_softc *sc = cookie;
454 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_copy_cmd_8x16);
455 	u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
456 	int y = sc->sc_font->fontheight * row;
457 	int w = sc->sc_font->fontwidth;
458 	int i;
459 
460 	if (dstcol > srccol) {
461 		for (i = ncols - 1; i >= 0; i--) {
462 			TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
463 			gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
464 		}
465 	} else {
466 		for (i = 0; i < ncols; i++) {
467 			TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
468 			gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
469 		}
470 	}
471 }
472 
473 void
_gsfb_erasecols(void * cookie,int row,int startcol,int ncols,long attr)474 _gsfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
475 {
476 	int i;
477 
478 	for (i = 0; i < ncols; i++)
479 		_gsfb_putchar(cookie, row, startcol + i, ' ', attr);
480 }
481 
482 void
_gsfb_copyrows(void * cookie,int src,int dst,int num)483 _gsfb_copyrows(void *cookie, int src, int dst, int num)
484 {
485 	struct gsfb_softc *sc = cookie;
486 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_scroll_cmd_640x16);
487 	u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
488 	int i;
489 	int h = sc->sc_font->fontheight;
490 
491 	if (dst > src) {
492 		for (i = num - 1; i >= 0; i--) {
493 			TRXPOS_SY_DY(cmd, (src + i) * h, (dst  + i) * h);
494 			gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
495 		}
496 	} else {
497 		for (i = 0; i < num; i++) {
498 			TRXPOS_SY_DY(cmd, (src + i) * h, (dst  + i) * h);
499 			gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
500 		}
501 	}
502 }
503 
504 void
_gsfb_eraserows(void * cookie,int row,int nrow,long attr)505 _gsfb_eraserows(void *cookie, int row, int nrow, long attr)
506 {
507 	struct gsfb_softc *sc = cookie;
508 	int i, j;
509 
510 	for (j = 0; j < nrow; j++)
511 		for (i = 0; i < sc->sc_screen->ncols; i++)
512 			_gsfb_putchar(cookie, row + j, i, ' ', attr);
513 }
514 
515 int
_gsfb_allocattr(void * cookie,int fg,int bg,int flags,long * attr)516 _gsfb_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
517 {
518 
519 	if ((flags & WSATTR_BLINK) != 0)
520 		return (EINVAL);
521 
522 	if ((flags & WSATTR_WSCOLORS) == 0) {
523 		fg = WS_DEFAULT_FG;
524 		bg = WS_DEFAULT_BG;
525 	}
526 
527 	if ((flags & WSATTR_HILIT) != 0)
528 		fg += 8;
529 
530 	flags = (flags & WSATTR_UNDERLINE) ? 1 : 0;
531 
532 
533 	*attr = ATTR_BG_SET(bg) | ATTR_FG_SET(fg) | flags;
534 
535 	return (0);
536 }
537 
538 int
_gsfb_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)539 _gsfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
540 	struct lwp *l)
541 {
542 
543 	return (EPASSTHROUGH); /* Inappropriate ioctl for device */
544 }
545 
546 paddr_t
_gsfb_mmap(void * v,void * vs,off_t offset,int prot)547 _gsfb_mmap(void *v, void *vs, off_t offset, int prot)
548 {
549 
550 	return (-1); /* can't mmap */
551 }
552 
553 int
_gsfb_alloc_screen(void * v,const struct wsscreen_descr * type,void ** cookiep,int * curxp,int * curyp,long * attrp)554 _gsfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
555     int *curxp, int *curyp, long *attrp)
556 {
557 
558 	*attrp = ATTR_BG_SET(WS_DEFAULT_BG) | ATTR_FG_SET(WS_DEFAULT_FG);
559 
560 	return (0);
561 }
562 
563 void
_gsfb_free_screen(void * v,void * cookie)564 _gsfb_free_screen(void *v, void *cookie)
565 {
566 }
567 
568 int
_gsfb_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)569 _gsfb_show_screen(void *v, void *cookie, int waitok,
570     void (*cb)(void *, int, int), void *cbarg)
571 {
572 
573 	return (0);
574 }
575 
576 void
_gsfb_pollc(void * v,int on)577 _gsfb_pollc(void *v, int on)
578 {
579 
580 }
581 
582 /*
583  * font expansion
584  *   PSMCT32 only
585  */
586 void
gsfb_font_expand_psmct32(const struct wsdisplay_font * font,u_int c,long attr,u_int32_t * buf)587 gsfb_font_expand_psmct32(const struct wsdisplay_font *font, u_int c, long attr,
588     u_int32_t *buf)
589 {
590 	u_int32_t fg, bg;
591 	u_int8_t *bitmap;
592 	int i, j;
593 
594 	KDASSERT(((u_int32_t)buf & 15) == 0);
595 
596 	fg = gsfb_ansi_psmct32[ATTR_FG_GET(attr)];
597 	bg = gsfb_ansi_psmct32[ATTR_BG_GET(attr)];
598 
599 	bitmap = (u_int8_t *)font->data + (c - font->firstchar) *
600 	    font->fontheight * font->stride;
601 	for (i = 0; i < font->fontheight; i++, bitmap++) {
602 		u_int32_t b = *bitmap;
603 		for (j = 0; j < font->fontwidth; j++, b <<= 1)
604 			*buf++ = (b & 0x80) ? fg : bg;
605 	}
606 }
607 
608 void
gsfb_dma_kick(paddr_t addr,size_t size)609 gsfb_dma_kick(paddr_t addr, size_t size)
610 {
611 	/* Wait for previous DMA request complete */
612 	while (_reg_read_4(D2_QWC_REG))
613 		;
614 
615 	/* Wait until GS FIFO empty */
616 	while ((_reg_read_8(GS_S_CSR_REG) & (3 << 14)) != (1 << 14))
617 		;
618 
619 	/* wait for DMA complete */
620 	dmac_bus_poll(D_CH2_GIF);
621 
622 	/* transfer addr */
623 	_reg_write_4(D2_MADR_REG, addr);
624 	/* transfer data size (unit qword) */
625 	_reg_write_4(D2_QWC_REG, bytetoqwc(size));
626 
627 	/* kick DMA (normal-mode) */
628 	dmac_chcr_write(D_CH2_GIF, D_CHCR_STR);
629 }
630 
631 #ifdef GSFB_DEBUG_MONITOR
632 void
__gsfb_print(int window,const char * fmt,...)633 __gsfb_print(int window, const char *fmt, ...)
634 {
635 	const struct _gsfb_debug_window *win;
636 	int i, s, x, y, n, a;
637 	u_int c;
638 	va_list ap;
639 
640 	if (!gsfb.initialized)
641 		return;
642 
643 	s = _intr_suspend();
644 	win = &_gsfb_debug_window[window];
645 	x = 0;
646 	y = win->start;
647 	n = win->nrow * 80;
648 	a = win->attr;
649 
650 	va_start(ap, fmt);
651 	vsnprintf(_gsfb_debug_buf, n, fmt, ap);
652 	va_end(ap);
653 
654 	_gsfb_eraserows(0, y, win->nrow, a);
655 
656 	for (i = 0; i < n &&
657 	    (c = (u_int)_gsfb_debug_buf[i] & 0x7f) != 0; i++) {
658 		if (c == '\n')
659 			x = 0, y++;
660 		else
661 			_gsfb_putchar(0, y, x++, c, a);
662 	}
663 
664 	_intr_resume(s);
665 }
666 
667 void
__gsfb_print_hex(int a0,int a1,int a2,int a3)668 __gsfb_print_hex(int a0, int a1, int a2, int a3)
669 {
670 	__gsfb_print(2, "a0=%08x a1=%08x a2=%08x a3=%08x",
671 	    a0, a1, a2, a3);
672 }
673 #endif /* GSFB_DEBUG_MONITOR */
674