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