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