1 /* $NetBSD: gsfb.c,v 1.21 2014/03/31 11:25:49 martin 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.21 2014/03/31 11:25:49 martin 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