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