gsfb.c revision 1.6 1 /* $NetBSD: gsfb.c,v 1.6 2002/10/02 04:17:22 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 * 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 CFATTACH_DECL(gsfb, sizeof(struct device),
188 gsfb_match, gsfb_attach, NULL, NULL);
189
190 STATIC void gsfb_hwinit(void);
191 STATIC int gsfb_swinit(void);
192
193 /* console */
194 void gsfbcnprobe(struct consdev *);
195 void gsfbcninit(struct consdev *);
196
197 /* emul ops */
198 STATIC void _gsfb_cursor(void *, int, int, int);
199 STATIC int _gsfb_mapchar(void *, int, unsigned int *);
200 STATIC void _gsfb_putchar(void *, int, int, u_int, long);
201 STATIC void _gsfb_copycols(void *, int, int, int, int);
202 STATIC void _gsfb_erasecols(void *, int, int, int, long);
203 STATIC void _gsfb_copyrows(void *, int, int, int);
204 STATIC void _gsfb_eraserows(void *, int, int, long);
205 STATIC int _gsfb_allocattr(void *, int, int, int, long *);
206
207 /* access ops */
208 STATIC int _gsfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
209 STATIC paddr_t _gsfb_mmap(void *, off_t, int);
210 STATIC int _gsfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
211 int *, int *, long *);
212 STATIC void _gsfb_free_screen(void *, void *);
213 STATIC int _gsfb_show_screen(void *, void *, int, void (*)(void *, int, int),
214 void *);
215 STATIC void _gsfb_pollc(void *, int);
216
217 /*
218 * wsdisplay attach args
219 * std: screen size 640 x 480, font size 8 x 16
220 */
221 #define GSFB_STD_SCREEN_WIDTH 640
222 #define GSFB_STD_SCREEN_HEIGHT 480
223 #define GSFB_STD_FONT_WIDTH 8
224 #define GSFB_STD_FONT_HEIGHT 16
225 const struct wsdisplay_emulops _gsfb_emulops = {
226 .cursor = _gsfb_cursor,
227 .mapchar = _gsfb_mapchar,
228 .putchar = _gsfb_putchar,
229 .copycols = _gsfb_copycols,
230 .erasecols = _gsfb_erasecols,
231 .copyrows = _gsfb_copyrows,
232 .eraserows = _gsfb_eraserows,
233 .allocattr = _gsfb_allocattr
234 };
235
236 const struct wsscreen_descr _gsfb_std_screen = {
237 .name = "std",
238 .ncols = 80,
239 #ifdef GSFB_DEBUG_MONITOR
240 .nrows = 24,
241 #else
242 .nrows = 30,
243 #endif
244 .textops = &_gsfb_emulops,
245 .fontwidth = 8,
246 .fontheight = 16,
247 .capabilities = WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
248 WSSCREEN_WSCOLORS
249 };
250
251 const struct wsscreen_descr *_gsfb_screen_table[] = {
252 &_gsfb_std_screen,
253 };
254
255 struct wsscreen_list _gsfb_screen_list = {
256 .nscreens = sizeof(_gsfb_screen_table) /
257 sizeof(_gsfb_screen_table[0]),
258 .screens = _gsfb_screen_table
259 };
260
261 struct wsdisplay_accessops _gsfb_accessops = {
262 .ioctl = _gsfb_ioctl,
263 .mmap = _gsfb_mmap,
264 .alloc_screen = _gsfb_alloc_screen,
265 .free_screen = _gsfb_free_screen,
266 .show_screen = _gsfb_show_screen,
267 .load_font = 0,
268 .pollc = _gsfb_pollc
269 };
270
271 int
272 gsfb_match(struct device *parent, struct cfdata *cf, void *aux)
273 {
274 extern struct cfdriver gsfb_cd;
275 struct mainbus_attach_args *ma = aux;
276
277 if (strcmp(ma->ma_name, gsfb_cd.cd_name) != 0)
278 return (0);
279
280 return (!gsfb.attached);
281 }
282
283 void
284 gsfb_attach(struct device *parent, struct device *self, void *aux)
285 {
286 struct wsemuldisplaydev_attach_args wa;
287
288 gsfb.attached = 1;
289 if (!gsfb.is_console && gsfb_swinit() != 0)
290 return;
291
292 printf("\n");
293
294 wa.console = gsfb.is_console;
295 wa.scrdata = &_gsfb_screen_list;
296 wa.accessops = &_gsfb_accessops;
297 wa.accesscookie = &gsfb;
298
299 config_found(self, &wa, wsdisplaydevprint);
300 }
301
302 /*
303 * console
304 */
305 void
306 gsfbcnprobe(struct consdev *cndev)
307 {
308
309 cndev->cn_pri = CN_INTERNAL;
310 }
311
312 void
313 gsfbcninit(struct consdev *cndev)
314 {
315 paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_init_cmd_640x480);
316 long defattr = ATTR_BG_SET(WSCOL_BLACK) | ATTR_FG_SET(WSCOL_WHITE);
317
318 gsfb.is_console = 1;
319
320 gsfb_hwinit();
321 gsfb_swinit();
322
323 gsfb_dma_kick(paddr, sizeof gsfb_init_cmd_640x480);
324 #ifdef GSFB_DEBUG_MONITOR
325 {
326 const struct _gsfb_debug_window *win;
327 int i;
328
329 for (i = 0; i < 3; i++) {
330 win = &_gsfb_debug_window[i];
331 _gsfb_eraserows(0, win->start, win->nrow, win->attr);
332 }
333 }
334 #endif /* GSFB_DEBUG_MONITOR */
335
336 wsdisplay_cnattach(&_gsfb_std_screen, &gsfb, 0, 0, defattr);
337 }
338
339 void
340 gsfb_hwinit()
341 {
342 gs_init(VESA_1A);
343 dmac_init();
344
345 /* reset GIF channel DMA */
346 _reg_write_4(D2_QWC_REG, 0);
347 _reg_write_4(D2_MADR_REG, 0);
348 _reg_write_4(D2_TADR_REG, 0);
349 _reg_write_4(D2_CHCR_REG, 0);
350 }
351
352 int
353 gsfb_swinit()
354 {
355 int font;
356
357 wsfont_init();
358 font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
359 WSDISPLAY_FONTORDER_L2R);
360 if (font < 0)
361 return (1);
362
363 if (wsfont_lock(font, &gsfb.font))
364 return (1);
365
366 gsfb.screen = &_gsfb_std_screen;
367 gsfb.initialized = 1;
368
369 return (0);
370 }
371
372 /*
373 * wsdisplay
374 */
375 void
376 _gsfb_cursor(void *cookie, int on, int row, int col)
377 {
378 paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_cursor_cmd);
379 u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
380 struct wsdisplay_font *font = gsfb.font;
381
382 gsfb_set_cursor_pos(buf, col, row, font->fontwidth, font->fontheight);
383
384 gsfb_dma_kick(paddr, sizeof gsfb_cursor_cmd);
385 }
386
387 __inline__ void
388 gsfb_set_cursor_pos(u_int32_t *p, int x, int y, int w, int h)
389 {
390
391 x *= w;
392 y *= h;
393 p[20] = ((x << 4) & 0xffff) | ((y << 20) & 0xffff0000);
394 p[28] = (((x + w - 1) << 4) & 0xffff) |
395 (((y + h - 1) << 20) & 0xffff0000);
396 }
397
398 int
399 _gsfb_mapchar(void *cookie, int c, unsigned int *cp)
400 {
401 struct wsdisplay_font *font = gsfb.font;
402
403 if (font->encoding != WSDISPLAY_FONTENC_ISO)
404 if ((c = wsfont_map_unichar(font, c)) < 0)
405 goto nomap;
406
407 if (c < font->firstchar || c >= font->firstchar + font->numchars)
408 goto nomap;
409
410 *cp = c;
411 return (5);
412
413 nomap:
414 *cp = ' ';
415 return (0);
416 }
417
418 void
419 _gsfb_putchar(void *cookie, int row, int col, u_int uc, long attr)
420 {
421 paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_load_cmd_8x16_psmct32);
422 u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
423 struct wsdisplay_font *font = gsfb.font;
424
425 /* copy font data to DMA region */
426 gsfb_font_expand_psmct32(font, uc, attr, &buf[FONT_SCRATCH_BASE]);
427
428 /* set destination position */
429 TRXPOS_DXY(buf, col * font->fontwidth, row * font->fontheight);
430
431 /* kick to GIF */
432 gsfb_dma_kick(paddr, sizeof gsfb_load_cmd_8x16_psmct32);
433 }
434
435 void
436 _gsfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
437 {
438 paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_copy_cmd_8x16);
439 u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
440 int y = gsfb.font->fontheight * row;
441 int w = gsfb.font->fontwidth;
442 int i;
443
444 if (dstcol > srccol) {
445 for (i = ncols - 1; i >= 0; i--) {
446 TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
447 gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
448 }
449 } else {
450 for (i = 0; i < ncols; i++) {
451 TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
452 gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
453 }
454 }
455 }
456
457 void
458 _gsfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
459 {
460 int i;
461
462 for (i = 0; i < ncols; i++)
463 _gsfb_putchar(cookie, row, startcol + i, ' ', attr);
464 }
465
466 void
467 _gsfb_copyrows(void *cookie, int src, int dst, int num)
468 {
469 paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_scroll_cmd_640x16);
470 u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
471 int i;
472 int h = gsfb.font->fontheight;
473
474 if (dst > src) {
475 for (i = num - 1; i >= 0; i--) {
476 TRXPOS_SY_DY(cmd, (src + i) * h, (dst + i) * h);
477 gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
478 }
479 } else {
480 for (i = 0; i < num; i++) {
481 TRXPOS_SY_DY(cmd, (src + i) * h, (dst + i) * h);
482 gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
483 }
484 }
485 }
486
487 void
488 _gsfb_eraserows(void *cookie, int row, int nrow, long attr)
489 {
490 int i, j;
491
492 for (j = 0; j < nrow; j++)
493 for (i = 0; i < gsfb.screen->ncols; i++)
494 _gsfb_putchar(cookie, row + j, i, ' ', attr);
495 }
496
497 int
498 _gsfb_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
499 {
500
501 if ((flags & WSATTR_BLINK) != 0)
502 return (EINVAL);
503
504 if ((flags & WSATTR_WSCOLORS) == 0) {
505 fg = WSCOL_WHITE;
506 bg = WSCOL_BLACK;
507 }
508
509 if ((flags & WSATTR_HILIT) != 0)
510 fg += 8;
511
512 flags = (flags & WSATTR_UNDERLINE) ? 1 : 0;
513
514
515 *attr = ATTR_BG_SET(bg) | ATTR_FG_SET(fg) | flags;
516
517 return (0);
518 }
519
520 int
521 _gsfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
522 {
523
524 return (EPASSTHROUGH); /* Inappropriate ioctl for device */
525 }
526
527 paddr_t
528 _gsfb_mmap(void *v, off_t offset, int prot)
529 {
530
531 return (NULL); /* can't mmap */
532 }
533
534 int
535 _gsfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
536 int *curxp, int *curyp, long *attrp)
537 {
538
539 *attrp = ATTR_BG_SET(WSCOL_BLACK) | ATTR_FG_SET(WSCOL_WHITE);
540
541 return (0);
542 }
543
544 void
545 _gsfb_free_screen(void *v, void *cookie)
546 {
547 }
548
549 int
550 _gsfb_show_screen(void *v, void *cookie, int waitok,
551 void (*cb)(void *, int, int), void *cbarg)
552 {
553
554 return (0);
555 }
556
557 void
558 _gsfb_pollc(void *v, int on)
559 {
560
561 }
562
563 /*
564 * font expansion
565 * PSMCT32 only
566 */
567 void
568 gsfb_font_expand_psmct32(const struct wsdisplay_font *font, u_int c, long attr,
569 u_int32_t *buf)
570 {
571 u_int32_t fg, bg;
572 u_int8_t *bitmap;
573 int i, j;
574
575 KDASSERT(((u_int32_t)buf & 15) == 0);
576
577 fg = gsfb_ansi_psmct32[ATTR_FG_GET(attr)];
578 bg = gsfb_ansi_psmct32[ATTR_BG_GET(attr)];
579
580 bitmap = (u_int8_t *)font->data + (c - font->firstchar) *
581 font->fontheight * font->stride;
582 for (i = 0; i < font->fontheight; i++, bitmap++) {
583 u_int32_t b = *bitmap;
584 for (j = 0; j < font->fontwidth; j++, b <<= 1)
585 *buf++ = (b & 0x80) ? fg : bg;
586 }
587 }
588
589 void
590 gsfb_dma_kick(paddr_t addr, size_t size)
591 {
592 /* Wait for previous DMA request complete */
593 while (_reg_read_4(D2_QWC_REG))
594 ;
595
596 /* Wait until GS FIFO empty */
597 while ((_reg_read_8(GS_S_CSR_REG) & (3 << 14)) != (1 << 14))
598 ;
599
600 /* wait for DMA complete */
601 dmac_bus_poll(D_CH2_GIF);
602
603 /* transfer addr */
604 _reg_write_4(D2_MADR_REG, addr);
605 /* transfer data size (unit qword) */
606 _reg_write_4(D2_QWC_REG, bytetoqwc(size));
607
608 /* kick DMA (normal-mode) */
609 dmac_chcr_write(D_CH2_GIF, D_CHCR_STR);
610 }
611
612 #ifdef GSFB_DEBUG_MONITOR
613 void
614 __gsfb_print(int window, const char *fmt, ...)
615 {
616 const struct _gsfb_debug_window *win;
617 int i, s, x, y, n, a;
618 u_int c;
619 va_list ap;
620
621 if (!gsfb.initialized)
622 return;
623
624 s = _intr_suspend();
625 win = &_gsfb_debug_window[window];
626 x = 0;
627 y = win->start;
628 n = win->nrow * 80;
629 a = win->attr;
630
631 va_start(ap, fmt);
632 vsnprintf(_gsfb_debug_buf, n, fmt, ap);
633 va_end(ap);
634
635 _gsfb_eraserows(0, y, win->nrow, a);
636
637 for (i = 0; i < n &&
638 (c = (u_int)_gsfb_debug_buf[i] & 0x7f) != 0; i++) {
639 if (c == '\n')
640 x = 0, y++;
641 else
642 _gsfb_putchar(0, y, x++, c, a);
643 }
644
645 _intr_resume(s);
646 }
647
648 void
649 __gsfb_print_hex(int a0, int a1, int a2, int a3)
650 {
651 __gsfb_print(2, "a0=%08x a1=%08x a2=%08x a3=%08x",
652 a0, a1, a2, a3);
653 }
654 #endif /* GSFB_DEBUG_MONITOR */
655