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