1 /* $NetBSD: grtwo.c,v 1.1 2004/03/18 08:52:04 sekiya Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Christopher SEKIYA 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>> 30 */ 31 32 /* wscons driver for SGI GR2 family of framebuffers 33 * 34 * Heavily based on the newport wscons driver. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: grtwo.c,v 1.1 2004/03/18 08:52:04 sekiya Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 #include <sys/malloc.h> 44 45 #include <dev/wscons/wsconsio.h> 46 #include <dev/wscons/wsdisplayvar.h> 47 #include <dev/wsfont/wsfont.h> 48 49 #include <sgimips/gio/giovar.h> 50 #include <sgimips/gio/grtwovar.h> 51 #include <sgimips/gio/grtworeg.h> 52 53 #include <sgimips/dev/int2var.h> 54 55 struct grtwo_softc { 56 struct device sc_dev; 57 58 struct grtwo_devconfig *sc_dc; 59 }; 60 61 struct grtwo_devconfig { 62 u_int32_t dc_addr; 63 64 bus_space_tag_t iot; 65 bus_space_handle_t ioh; 66 67 u_int8_t boardrev; 68 u_int8_t backendrev; 69 int hq2rev; 70 int ge7rev; 71 int vc1rev; 72 int zbuffer; 73 int cmaprev; 74 int xmaprev; 75 int rexrev; 76 int xres; 77 int yres; 78 int depth; 79 int monitor; 80 81 int dc_font; 82 struct wsdisplay_font *dc_fontdata; 83 }; 84 85 static int grtwo_match(struct device *, struct cfdata *, void *); 86 static void grtwo_attach(struct device *, struct device *, void *); 87 88 CFATTACH_DECL(grtwo, sizeof(struct grtwo_softc), 89 grtwo_match, grtwo_attach, NULL, NULL); 90 91 /* textops */ 92 static void grtwo_cursor(void *, int, int, int); 93 static int grtwo_mapchar(void *, int, unsigned int *); 94 static void grtwo_putchar(void *, int, int, u_int, long); 95 static void grtwo_copycols(void *, int, int, int, int); 96 static void grtwo_erasecols(void *, int, int, int, long); 97 static void grtwo_copyrows(void *, int, int, int); 98 static void grtwo_eraserows(void *, int, int, long); 99 static int grtwo_allocattr(void *, int, int, int, long *); 100 101 /* accessops */ 102 static int grtwo_ioctl(void *, u_long, caddr_t, int, struct proc *); 103 static paddr_t grtwo_mmap(void *, off_t, int); 104 static int 105 grtwo_alloc_screen(void *, const struct wsscreen_descr *, 106 void **, int *, int *, long *); 107 static void grtwo_free_screen(void *, void *); 108 static int 109 grtwo_show_screen(void *, void *, int, void (*) (void *, int, int), void *); 110 111 static const struct wsdisplay_emulops grtwo_textops = { 112 .cursor = grtwo_cursor, 113 .mapchar = grtwo_mapchar, 114 .putchar = grtwo_putchar, 115 .copycols = grtwo_copycols, 116 .erasecols = grtwo_erasecols, 117 .copyrows = grtwo_copyrows, 118 .eraserows = grtwo_eraserows, 119 .allocattr = grtwo_allocattr 120 }; 121 122 static const struct wsdisplay_accessops grtwo_accessops = { 123 .ioctl = grtwo_ioctl, 124 .mmap = grtwo_mmap, 125 .alloc_screen = grtwo_alloc_screen, 126 .free_screen = grtwo_free_screen, 127 .show_screen = grtwo_show_screen, 128 }; 129 130 static const struct wsscreen_descr grtwo_screen = { 131 .name = "1280x1024", 132 .ncols = 160, 133 .nrows = 64, 134 .textops = &grtwo_textops, 135 .fontwidth = 8, 136 .fontheight = 16, 137 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE 138 }; 139 140 static const struct wsscreen_descr *_grtwo_screenlist[] = { 141 &grtwo_screen 142 }; 143 144 static const struct wsscreen_list grtwo_screenlist = { 145 sizeof(_grtwo_screenlist) / sizeof(struct wsscreen_descr *), 146 _grtwo_screenlist 147 }; 148 149 static struct grtwo_devconfig grtwo_console_dc; 150 static int grtwo_is_console = 0; 151 152 #define GR2_ATTR_ENCODE(fg,bg) (((fg) << 8) | (bg)) 153 #define GR2_ATTR_BG(a) ((a) & 0xff) 154 #define GR2_ATTR_FG(a) (((a) >> 8) & 0xff) 155 156 static const u_int16_t grtwo_cursor_data[128] = { 157 /* Bit 0 */ 158 0xff00, 0x0000, 159 0xff00, 0x0000, 160 0xff00, 0x0000, 161 0xff00, 0x0000, 162 0xff00, 0x0000, 163 0xff00, 0x0000, 164 0xff00, 0x0000, 165 0xff00, 0x0000, 166 0xff00, 0x0000, 167 0xff00, 0x0000, 168 0xff00, 0x0000, 169 0xff00, 0x0000, 170 0xff00, 0x0000, 171 0xff00, 0x0000, 172 0xff00, 0x0000, 173 0xff00, 0x0000, 174 0x0000, 0x0000, 175 0x0000, 0x0000, 176 0x0000, 0x0000, 177 0x0000, 0x0000, 178 0x0000, 0x0000, 179 0x0000, 0x0000, 180 0x0000, 0x0000, 181 0x0000, 0x0000, 182 0x0000, 0x0000, 183 0x0000, 0x0000, 184 0x0000, 0x0000, 185 0x0000, 0x0000, 186 0x0000, 0x0000, 187 0x0000, 0x0000, 188 0x0000, 0x0000, 189 0x0000, 0x0000, 190 191 /* Bit 1 */ 192 0x0000, 0x0000, 193 0x0000, 0x0000, 194 0x0000, 0x0000, 195 0x0000, 0x0000, 196 0x0000, 0x0000, 197 0x0000, 0x0000, 198 0x0000, 0x0000, 199 0x0000, 0x0000, 200 0x0000, 0x0000, 201 0x0000, 0x0000, 202 0x0000, 0x0000, 203 0x0000, 0x0000, 204 0x0000, 0x0000, 205 0x0000, 0x0000, 206 0x0000, 0x0000, 207 0x0000, 0x0000, 208 0x0000, 0x0000, 209 0x0000, 0x0000, 210 0x0000, 0x0000, 211 0x0000, 0x0000, 212 0x0000, 0x0000, 213 0x0000, 0x0000, 214 0x0000, 0x0000, 215 0x0000, 0x0000, 216 0x0000, 0x0000, 217 0x0000, 0x0000, 218 0x0000, 0x0000, 219 0x0000, 0x0000, 220 0x0000, 0x0000, 221 0x0000, 0x0000, 222 0x0000, 0x0000, 223 0x0000, 0x0000, 224 }; 225 226 static const u_int8_t grtwo_defcmap[8 * 3] = { 227 /* Normal colors */ 228 0x00, 0x00, 0x00, /* black */ 229 0x7f, 0x00, 0x00, /* red */ 230 0x00, 0x7f, 0x00, /* green */ 231 0x7f, 0x7f, 0x00, /* brown */ 232 0x00, 0x00, 0x7f, /* blue */ 233 0x7f, 0x00, 0x7f, /* magenta */ 234 0x00, 0x7f, 0x7f, /* cyan */ 235 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ 236 }; 237 238 static void 239 grtwo_wait_gfifo(struct grtwo_devconfig * dc) 240 { 241 int2_wait_fifo(1); 242 } 243 244 /* Helper functions */ 245 static void 246 grtwo_fill_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2, 247 int y2, u_int8_t color) 248 { 249 /* gr2 sees coordinate 0,0 as the lower left corner of the screen */ 250 y1 = dc->yres - y1; 251 y2 = dc->yres - y2; 252 253 grtwo_wait_gfifo(dc); 254 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_COLOR, color); 255 grtwo_wait_gfifo(dc); 256 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1); 257 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1); 258 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 259 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2); 260 } 261 262 static void 263 grtwo_copy_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2, 264 int y2, int dx, int dy) 265 { 266 int length = (dx + 3) >> 2; 267 int lines = 4864 / length; 268 int from_y; 269 int to_y; 270 int height; 271 272 y1 = dc->yres - y1 - dy; 273 y2 = dc->yres - y2 - dy; 274 275 if ((y2 <= y1) || (dy < lines)) { 276 grtwo_wait_gfifo(dc); 277 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length); 278 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines); 279 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1); 280 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1); 281 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dx); 282 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dy); 283 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 284 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2); 285 } else { 286 from_y = y1 + dy - lines; 287 to_y = y2 + dy - lines; 288 height = MIN(dy, lines); 289 290 while (height) { 291 grtwo_wait_gfifo(dc); 292 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length); 293 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines); 294 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1); 295 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y); 296 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dx); 297 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, height); 298 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 299 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, to_y); 300 dy -= height; 301 height = MIN(dy, lines); 302 from_y -= height; 303 to_y -= height; 304 } 305 } 306 } 307 308 static void 309 grtwo_cmap_setrgb(struct grtwo_devconfig * dc, int index, u_int8_t r, u_int8_t g, u_int8_t b) 310 { 311 /* index += 0x1000; */ 312 313 grtwo_wait_gfifo(dc); 314 bus_space_write_4(dc->iot, dc->ioh, XMAPALL_ADDRHI, 315 (index & 0x1f00) >> 8); 316 bus_space_write_4(dc->iot, dc->ioh, XMAPALL_ADDRLO, 317 (index & 0xff)); 318 bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, r); 319 bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, g); 320 bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, b); 321 } 322 323 static void 324 grtwo_setup_hw(struct grtwo_devconfig * dc) 325 { 326 int i = 0; 327 328 /* Get various revisions */ 329 dc->boardrev = (~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0))) & GR2_REVISION_RD0_VERSION_MASK; 330 331 /* 332 * boards prior to rev 4 have a pretty whacky config scheme. 333 * what is doubly weird is that i have a rev 2 board, but the rev 4 334 * probe routines work just fine. 335 * we'll trust SGI, though, and separate things a bit. it's only 336 * critical for the display depth calculation. 337 */ 338 339 if (dc->boardrev < 4) { 340 dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & GR2_REVISION_RD2_BACKEND_REV) >> 2; 341 if (dc->backendrev == 0) 342 return; 343 dc->zbuffer = !(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION_RD1_ZBUFFER); 344 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMA) != 3) 345 i++; 346 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMB) != 0x0c) 347 i++; 348 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMC) != 0x30) 349 i++; 350 dc->depth = 8 * i; 351 dc->monitor = 352 ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & 0x03) << 1) | 353 (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & 0x01); 354 } else { 355 dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1)) & 0x03; 356 if (dc->backendrev == 0) 357 return; 358 dc->zbuffer = bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_ZBUFFER; 359 dc->depth = ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_24BPP) >> 4) ? 24 : 8; 360 dc->monitor = (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0) & GR2_REVISION4_RD0_MONITOR_MASK) >> 4; 361 } 362 363 dc->hq2rev = (bus_space_read_4(dc->iot, dc->ioh, HQ2_VERSION) & HQ2_VERSION_MASK) >> HQ2_VERSION_SHIFT; 364 dc->ge7rev = (bus_space_read_4(dc->iot, dc->ioh, GE7_REVISION) & GE7_REVISION_MASK) >> 5; 365 /* dc->vc1rev = vc1_read_ireg(dc, 5) & 0x07; */ 366 367 /* gr2 supports 1280x1024 only */ 368 dc->xres = 1280; 369 dc->yres = 1024; 370 371 #if 0 372 /* Setup cursor glyph */ 373 374 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, 375 (VC1_SRAM_CURSOR0_BASE >> 8) & 0xff); 376 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, 377 VC1_SRAM_CURSOR0_BASE & 0xff); 378 for (i = 0; i < 128; i++) 379 bus_space_write_4(dc->iot, dc->ioh, VC1_SRAM, grtwo_cursor_data[i]); 380 381 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, 382 (VC1_CURSOR_EP >> 8) & 0xff); 383 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, 384 VC1_CURSOR_EP & 0xff); 385 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, VC1_SRAM_CURSOR0_BASE); 386 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0); 387 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0); 388 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0); 389 390 /* Turn on cursor function, display, DID */ 391 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL, 392 VC1_SYSCTL_VC1 | VC1_SYSCTL_DID | 393 VC1_SYSCTL_CURSOR | VC1_SYSCTL_CURSOR_DISPLAY); 394 #endif 395 396 /* Setup CMAP */ 397 for (i = 0; i < 8; i++) 398 grtwo_cmap_setrgb(dc, i, grtwo_defcmap[i * 3], 399 grtwo_defcmap[i * 3 + 1], grtwo_defcmap[i * 3 + 2]); 400 } 401 402 /* Attach routines */ 403 static int 404 grtwo_match(struct device * parent, struct cfdata * self, void *aux) 405 { 406 struct gio_attach_args *ga = aux; 407 408 /* 409 * grtwo doesn't have anything that even vaguely resembles a product 410 * ID. Instead, we determine presence by looking at the HQ2 "mystery" 411 * register, which contains a magic number. 412 */ 413 if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) ) 414 return 0; 415 416 if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef) 417 return 0; 418 419 return 1; 420 } 421 422 static void 423 grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga) 424 { 425 dc->dc_addr = ga->ga_addr; 426 427 dc->iot = ga->ga_iot; 428 dc->ioh = ga->ga_ioh; 429 430 wsfont_init(); 431 432 dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R, 433 WSDISPLAY_FONTORDER_L2R); 434 435 if (dc->dc_font < 0) 436 panic("grtwo_attach_common: no suitable fonts"); 437 438 if (wsfont_lock(dc->dc_font, &dc->dc_fontdata)) 439 panic("grtwo_attach_common: unable to lock font data"); 440 441 grtwo_setup_hw(dc); 442 443 grtwo_fill_rectangle(dc, 0, 0, dc->xres, dc->yres, 0); 444 } 445 446 static void 447 grtwo_attach(struct device * parent, struct device * self, void *aux) 448 { 449 struct gio_attach_args *ga = aux; 450 struct grtwo_softc *sc = (void *) self; 451 struct wsemuldisplaydev_attach_args wa; 452 453 if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) { 454 wa.console = 1; 455 sc->sc_dc = &grtwo_console_dc; 456 } else { 457 wa.console = 0; 458 sc->sc_dc = malloc(sizeof(struct grtwo_devconfig), 459 M_DEVBUF, M_WAITOK | M_ZERO); 460 if (sc->sc_dc == NULL) 461 panic("grtwo_attach: out of memory"); 462 463 grtwo_attach_common(sc->sc_dc, ga); 464 } 465 466 aprint_naive(": Display adapter\n"); 467 468 aprint_normal(": SGI GR2 (board rev %x, monitor %d, depth %d)\n", 469 sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth); 470 471 wa.scrdata = &grtwo_screenlist; 472 wa.accessops = &grtwo_accessops; 473 wa.accesscookie = sc->sc_dc; 474 475 config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint); 476 } 477 478 int 479 grtwo_cnattach(struct gio_attach_args * ga) 480 { 481 long defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK); 482 const struct wsscreen_descr *screen; 483 484 if (!grtwo_match(NULL, NULL, ga)) { 485 return ENXIO; 486 } 487 488 grtwo_attach_common(&grtwo_console_dc, ga); 489 490 screen = &grtwo_screen; 491 492 wsdisplay_cnattach(screen, &grtwo_console_dc, 0, 0, defattr); 493 494 grtwo_is_console = 1; 495 496 return 0; 497 } 498 499 /* wsdisplay textops */ 500 static void 501 grtwo_cursor(void *c, int on, int row, int col) 502 { 503 struct grtwo_devconfig *dc = (void *) c; 504 u_int32_t control; 505 control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL); 506 507 if (!on) { 508 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL, 509 control & ~VC1_SYSCTL_CURSOR_DISPLAY); 510 } else { 511 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8 512 ); 513 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff); 514 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 515 col * dc->dc_fontdata->fontwidth); 516 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 517 row * dc->dc_fontdata->fontheight); 518 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL, 519 control | VC1_SYSCTL_CURSOR_DISPLAY); 520 } 521 } 522 523 static int 524 grtwo_mapchar(void *c, int ch, unsigned int *cp) 525 { 526 struct grtwo_devconfig *dc = (void *) c; 527 528 if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) { 529 ch = wsfont_map_unichar(dc->dc_fontdata, ch); 530 531 if (ch < 0) 532 goto fail; 533 } 534 if (ch < dc->dc_fontdata->firstchar || 535 ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars) 536 goto fail; 537 538 *cp = ch; 539 return 5; 540 541 fail: 542 *cp = ' '; 543 return 0; 544 } 545 546 static void 547 grtwo_putchar(void *c, int row, int col, u_int ch, long attr) 548 { 549 struct grtwo_devconfig *dc = (void *) c; 550 struct wsdisplay_font *font = dc->dc_fontdata; 551 u_int8_t *bitmap = (u_int8_t *) font->data + (ch - font->firstchar) * font->fontheight * font->stride; 552 u_int32_t pattern; 553 int i; 554 int x = col * font->fontwidth; 555 int y = dc->yres - ( (row + 1) * font->fontheight); 556 557 /* Set the drawing color */ 558 grtwo_wait_gfifo(dc); 559 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_COLOR, attr); 560 561 /* Set drawing coordinates */ 562 grtwo_wait_gfifo(dc); 563 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x); 564 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y); 565 566 grtwo_wait_gfifo(dc); 567 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth); 568 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight); 569 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 1); 570 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */ 571 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */ 572 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); 573 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); 574 575 for (i = 0; i < font->fontheight; i++) { 576 /* It appears that writes have to be 16 bits. An "I tell you 577 two times" sort of thing? Thanks, SGI */ 578 pattern = *bitmap | (*bitmap << 8); 579 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern); 580 bitmap += font->stride; 581 } 582 583 /* pad up to 18 */ 584 for (i = font->fontheight; i < 18; i++) 585 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000); 586 } 587 588 static void 589 grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols) 590 { 591 struct grtwo_devconfig *dc = (void *) c; 592 struct wsdisplay_font *font = dc->dc_fontdata; 593 594 grtwo_copy_rectangle(dc, 595 srccol * font->fontwidth, /* x1 */ 596 row * font->fontheight, /* y1 */ 597 (srccol + ncols + 1) * font->fontwidth - 1, /* x2 */ 598 (row + 1) * font->fontheight - 1, /* y2 */ 599 dstcol * font->fontheight, /* dx */ 600 row * font->fontheight); /* dy */ 601 } 602 603 static void 604 grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr) 605 { 606 struct grtwo_devconfig *dc = (void *) c; 607 struct wsdisplay_font *font = dc->dc_fontdata; 608 609 grtwo_fill_rectangle(dc, 610 startcol * font->fontwidth, /* x1 */ 611 row * font->fontheight, /* y1 */ 612 (startcol + ncols + 1) * font->fontwidth - 1, /* x2 */ 613 (row + 1) * font->fontheight - 1, /* y2 */ 614 GR2_ATTR_BG(attr)); 615 } 616 617 static void 618 grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows) 619 { 620 struct grtwo_devconfig *dc = (void *) c; 621 struct wsdisplay_font *font = dc->dc_fontdata; 622 623 grtwo_copy_rectangle(dc, 624 0, /* x1 */ 625 srcrow * font->fontheight, /* y1 */ 626 dc->xres, /* x2 */ 627 (srcrow + nrows + 1) * font->fontheight - 1, /* y2 */ 628 0, /* dx */ 629 dstrow * font->fontheight); /* dy */ 630 } 631 632 static void 633 grtwo_eraserows(void *c, int startrow, int nrows, long attr) 634 { 635 struct grtwo_devconfig *dc = (void *) c; 636 struct wsdisplay_font *font = dc->dc_fontdata; 637 638 grtwo_fill_rectangle(dc, 639 0, /* x1 */ 640 startrow * font->fontheight, /* y1 */ 641 dc->xres, /* x2 */ 642 (startrow + nrows + 1) * font->fontheight - 1, /* y2 */ 643 GR2_ATTR_BG(attr)); 644 } 645 646 static int 647 grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr) 648 { 649 if (flags & WSATTR_BLINK) 650 return EINVAL; 651 652 if ((flags & WSATTR_WSCOLORS) == 0) { 653 fg = WSCOL_WHITE; 654 bg = WSCOL_BLACK; 655 } 656 if (flags & WSATTR_HILIT) 657 fg += 8; 658 659 if (flags & WSATTR_REVERSE) { 660 int tmp = fg; 661 fg = bg; 662 bg = tmp; 663 } 664 *attr = GR2_ATTR_ENCODE(fg, bg); 665 666 return 0; 667 } 668 669 /* wsdisplay accessops */ 670 671 static int 672 grtwo_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc * p) 673 { 674 struct grtwo_softc *sc = c; 675 676 #define FBINFO (*(struct wsdisplay_fbinfo*)data) 677 678 switch (cmd) { 679 case WSDISPLAYIO_GINFO: 680 FBINFO.width = sc->sc_dc->xres; 681 FBINFO.height = sc->sc_dc->yres; 682 FBINFO.depth = sc->sc_dc->depth; 683 FBINFO.cmsize = 1 << FBINFO.depth; 684 return 0; 685 case WSDISPLAYIO_GTYPE: 686 *(u_int *) data = WSDISPLAY_TYPE_GR2; 687 return 0; 688 } 689 return EPASSTHROUGH; 690 } 691 692 static paddr_t 693 grtwo_mmap(void *c, off_t offset, int prot) 694 { 695 struct grtwo_devconfig *dc = c; 696 697 if (offset >= 0xfffff) 698 return -1; 699 700 return mips_btop(dc->dc_addr + offset); 701 } 702 703 static int 704 grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep, 705 int *cursxp, int *cursyp, long *attrp) 706 { 707 /* 708 * This won't get called for console screen and we don't support 709 * virtual screens 710 */ 711 712 return ENOMEM; 713 } 714 715 static void 716 grtwo_free_screen(void *c, void *cookie) 717 { 718 panic("grtwo_free_screen"); 719 } 720 static int 721 grtwo_show_screen(void *c, void *cookie, int waitok, 722 void (*cb) (void *, int, int), void *cbarg) 723 { 724 return 0; 725 } 726