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