1 /* $NetBSD: grtwo.c,v 1.5 2004/09/29 05:13:39 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.5 2004/09/29 05:13:39 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 int grtwo_intr0(void *); 112 static int grtwo_intr6(void *); 113 114 static const struct wsdisplay_emulops grtwo_textops = { 115 .cursor = grtwo_cursor, 116 .mapchar = grtwo_mapchar, 117 .putchar = grtwo_putchar, 118 .copycols = grtwo_copycols, 119 .erasecols = grtwo_erasecols, 120 .copyrows = grtwo_copyrows, 121 .eraserows = grtwo_eraserows, 122 .allocattr = grtwo_allocattr 123 }; 124 125 static const struct wsdisplay_accessops grtwo_accessops = { 126 .ioctl = grtwo_ioctl, 127 .mmap = grtwo_mmap, 128 .alloc_screen = grtwo_alloc_screen, 129 .free_screen = grtwo_free_screen, 130 .show_screen = grtwo_show_screen, 131 }; 132 133 static const struct wsscreen_descr grtwo_screen = { 134 .name = "1280x1024", 135 .ncols = 160, 136 .nrows = 64, /* 40 */ 137 .textops = &grtwo_textops, 138 .fontwidth = 8, 139 .fontheight = 16, 140 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE 141 }; 142 143 static const struct wsscreen_descr *_grtwo_screenlist[] = { 144 &grtwo_screen 145 }; 146 147 static const struct wsscreen_list grtwo_screenlist = { 148 sizeof(_grtwo_screenlist) / sizeof(struct wsscreen_descr *), 149 _grtwo_screenlist 150 }; 151 152 static struct grtwo_devconfig grtwo_console_dc; 153 static int grtwo_is_console = 0; 154 155 #define GR2_ATTR_ENCODE(fg,bg) (((fg) << 8) | (bg)) 156 #define GR2_ATTR_BG(a) ((a) & 0xff) 157 #define GR2_ATTR_FG(a) (((a) >> 8) & 0xff) 158 159 static const u_int16_t grtwo_cursor_data[128] = { 160 /* Bit 0 */ 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 0xff00, 0x0000, 175 0xff00, 0x0000, 176 0xff00, 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 0x0000, 0x0000, 191 0x0000, 0x0000, 192 0x0000, 0x0000, 193 194 /* Bit 1 */ 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 0x0000, 0x0000, 225 0x0000, 0x0000, 226 0x0000, 0x0000, 227 }; 228 229 static const u_int8_t grtwo_defcmap[8 * 3] = { 230 /* Normal colors */ 231 0x00, 0x00, 0x00, /* black */ 232 0x7f, 0x00, 0x00, /* red */ 233 0x00, 0x7f, 0x00, /* green */ 234 0x7f, 0x7f, 0x00, /* brown */ 235 0x00, 0x00, 0x7f, /* blue */ 236 0x7f, 0x00, 0x7f, /* magenta */ 237 0x00, 0x7f, 0x7f, /* cyan */ 238 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ 239 }; 240 241 static void 242 grtwo_wait_gfifo(struct grtwo_devconfig * dc) 243 { 244 int2_wait_fifo(1); 245 } 246 247 static inline void 248 grtwo_set_color(bus_space_tag_t iot, bus_space_handle_t ioh, int color) 249 { 250 bus_space_write_4(iot, ioh, GR2_FIFO_COLOR, color); 251 } 252 253 /* Helper functions */ 254 static void 255 grtwo_fill_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2, 256 int y2, u_int8_t color) 257 { 258 int remaining; 259 int from_y; 260 int to_y; 261 262 /* gr2 sees coordinate 0,0 as the lower left corner, and 1279,1023 263 as the upper right. To keep things consistent, we shall flip the 264 y axis. */ 265 266 /* There appears to be a limit to the number of vertical lines that we 267 can run through the the graphics engine at one go. This probably has 268 something to do with vertical refresh. Single-row fills are okay, 269 multiple-row screw up the board in exciting ways. The copy_rectangle 270 workaround doesn't work for fills. */ 271 272 /* Coordinates, not length. Remember that! */ 273 274 to_y = min(dc->yres - 1 - y1, dc->yres - 1 - y2); 275 from_y = max(dc->yres - 1 - y1, dc->yres - 1 - y2); 276 277 remaining = to_y - from_y; 278 279 grtwo_wait_gfifo(dc); 280 grtwo_set_color(dc->iot, dc->ioh, color); 281 282 while (remaining) { 283 if (remaining <= 32) 284 { 285 delay(10000); 286 grtwo_wait_gfifo(dc); 287 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1); 288 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y); 289 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 290 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y + remaining); 291 break; 292 } else { 293 delay(100000); 294 grtwo_wait_gfifo(dc); 295 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1); 296 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y); 297 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 298 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y + remaining); 299 from_y += 32; 300 remaining -=32; 301 } 302 } 303 } 304 305 static void 306 grtwo_copy_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2, 307 int y2, int width, int height) 308 { 309 int length = (width + 3) >> 2; 310 int lines = 4864 / length; 311 int from_y; 312 int to_y; 313 int temp_height; 314 315 if ((y2 <= y1) || (height < lines)) { 316 grtwo_wait_gfifo(dc); 317 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length); 318 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines); 319 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1); 320 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1); 321 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, width); 322 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, height); 323 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 324 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2); 325 } else { 326 from_y = y1 + height - lines; 327 to_y = y2 + height - lines; 328 temp_height = MIN(height, lines); 329 330 while (temp_height) { 331 grtwo_wait_gfifo(dc); 332 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length); 333 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines); 334 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1); 335 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y); 336 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, width); 337 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, temp_height); 338 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2); 339 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, to_y); 340 height -= temp_height; 341 height = MIN(height, lines); 342 from_y -= temp_height; 343 to_y -= temp_height; 344 } 345 } 346 } 347 348 static void 349 grtwo_cmap_setrgb(struct grtwo_devconfig * dc, int index, u_int8_t r, u_int8_t g, u_int8_t b) 350 { 351 grtwo_wait_gfifo(dc); 352 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_ADDRHI, 353 ((index & 0x1f00) >> 8) ); 354 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_ADDRLO, 355 (index & 0xff)); 356 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, r); 357 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, g); 358 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, b); 359 } 360 361 static void 362 grtwo_setup_hw(struct grtwo_devconfig * dc) 363 { 364 int i = 0; 365 366 /* Get various revisions */ 367 dc->boardrev = (~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0))) & GR2_REVISION_RD0_VERSION_MASK; 368 369 /* 370 * boards prior to rev 4 have a pretty whacky config scheme. 371 * what is doubly weird is that i have a rev 2 board, but the rev 4 372 * probe routines work just fine. 373 * we'll trust SGI, though, and separate things a bit. it's only 374 * critical for the display depth calculation. 375 */ 376 377 if (dc->boardrev < 4) { 378 dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & GR2_REVISION_RD2_BACKEND_REV) >> 2; 379 if (dc->backendrev == 0) 380 return; 381 dc->zbuffer = !(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION_RD1_ZBUFFER); 382 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMA) != 3) 383 i++; 384 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMB) != 0x0c) 385 i++; 386 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMC) != 0x30) 387 i++; 388 dc->depth = 8 * i; 389 dc->monitor = 390 ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & 0x03) << 1) | 391 (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & 0x01); 392 } else { 393 dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1)) & 0x03; 394 if (dc->backendrev == 0) 395 return; 396 dc->zbuffer = bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_ZBUFFER; 397 dc->depth = ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_24BPP) >> 4) ? 24 : 8; 398 dc->monitor = (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0) & GR2_REVISION4_RD0_MONITOR_MASK) >> 4; 399 } 400 401 dc->hq2rev = (bus_space_read_4(dc->iot, dc->ioh, HQ2_VERSION) & HQ2_VERSION_MASK) >> HQ2_VERSION_SHIFT; 402 dc->ge7rev = (bus_space_read_4(dc->iot, dc->ioh, GE7_REVISION) & GE7_REVISION_MASK) >> 5; 403 /* dc->vc1rev = vc1_read_ireg(dc, 5) & 0x07; */ 404 405 /* gr2 supports 1280x1024 only */ 406 dc->xres = 1280; 407 dc->yres = 1024; 408 409 #if 0 410 /* Setup cursor glyph */ 411 412 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, 413 (VC1_SRAM_CURSOR0_BASE >> 8) & 0xff); 414 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, 415 VC1_SRAM_CURSOR0_BASE & 0xff); 416 for (i = 0; i < 128; i++) 417 bus_space_write_4(dc->iot, dc->ioh, VC1_SRAM, grtwo_cursor_data[i]); 418 419 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, 420 (VC1_CURSOR_EP >> 8) & 0xff); 421 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, 422 VC1_CURSOR_EP & 0xff); 423 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, VC1_SRAM_CURSOR0_BASE); 424 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0); 425 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0); 426 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0); 427 428 /* Turn on cursor function, display, DID */ 429 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL, 430 VC1_SYSCTL_VC1 | VC1_SYSCTL_DID | 431 VC1_SYSCTL_CURSOR | VC1_SYSCTL_CURSOR_DISPLAY); 432 #endif 433 434 /* Setup CMAP */ 435 for (i = 0; i < 8; i++) 436 grtwo_cmap_setrgb(dc, i, grtwo_defcmap[i * 3], 437 grtwo_defcmap[i * 3 + 1], grtwo_defcmap[i * 3 + 2]); 438 } 439 440 /* Attach routines */ 441 static int 442 grtwo_match(struct device * parent, struct cfdata * self, void *aux) 443 { 444 struct gio_attach_args *ga = aux; 445 446 /* 447 * grtwo doesn't have anything that even vaguely resembles a product 448 * ID. Instead, we determine presence by looking at the HQ2 "mystery" 449 * register, which contains a magic number. 450 */ 451 if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) ) 452 return 0; 453 454 if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef) 455 return 0; 456 457 return 1; 458 } 459 460 static void 461 grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga) 462 { 463 dc->dc_addr = ga->ga_addr; 464 465 dc->iot = ga->ga_iot; 466 dc->ioh = ga->ga_ioh; 467 int i = 0; 468 469 wsfont_init(); 470 471 dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R, 472 WSDISPLAY_FONTORDER_L2R); 473 474 if (dc->dc_font < 0) 475 panic("grtwo_attach_common: no suitable fonts"); 476 477 if (wsfont_lock(dc->dc_font, &dc->dc_fontdata)) 478 panic("grtwo_attach_common: unable to lock font data"); 479 480 grtwo_setup_hw(dc); 481 482 /* Large fills are broken. For now, clear the screen line-by-line. */ 483 for (i = 0; i < 64; i++) 484 grtwo_eraserows(dc, i, 1, 0); 485 486 /* If large fills worked, we'd do this instead: 487 grtwo_fill_rectangle(dc, 0, 0, dc->xres - 1, dc->yres - 1, 0); 488 */ 489 } 490 491 static void 492 grtwo_attach(struct device * parent, struct device * self, void *aux) 493 { 494 struct gio_attach_args *ga = aux; 495 struct grtwo_softc *sc = (void *) self; 496 struct wsemuldisplaydev_attach_args wa; 497 498 if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) { 499 wa.console = 1; 500 sc->sc_dc = &grtwo_console_dc; 501 } else { 502 wa.console = 0; 503 sc->sc_dc = malloc(sizeof(struct grtwo_devconfig), 504 M_DEVBUF, M_WAITOK | M_ZERO); 505 if (sc->sc_dc == NULL) 506 panic("grtwo_attach: out of memory"); 507 508 grtwo_attach_common(sc->sc_dc, ga); 509 } 510 511 aprint_naive(": Display adapter\n"); 512 513 aprint_normal(": GR2 (board rev %x, monitor %d, depth %d)\n", 514 sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth); 515 516 wa.scrdata = &grtwo_screenlist; 517 wa.accessops = &grtwo_accessops; 518 wa.accesscookie = sc->sc_dc; 519 520 if ((cpu_intr_establish(0, IPL_TTY, grtwo_intr0, sc)) == NULL) 521 printf(": unable to establish interrupt!\n"); 522 523 if ((cpu_intr_establish(6, IPL_TTY, grtwo_intr6, sc)) == NULL) 524 printf(": unable to establish interrupt!\n"); 525 526 config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint); 527 } 528 529 int 530 grtwo_cnattach(struct gio_attach_args * ga) 531 { 532 long defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK); 533 534 if (!grtwo_match(NULL, NULL, ga)) { 535 return ENXIO; 536 } 537 538 grtwo_attach_common(&grtwo_console_dc, ga); 539 wsdisplay_cnattach(&grtwo_screen, &grtwo_console_dc, 0, 0, defattr); 540 541 grtwo_is_console = 1; 542 543 return 0; 544 } 545 546 /* wsdisplay textops */ 547 static void 548 grtwo_cursor(void *c, int on, int row, int col) 549 { 550 struct grtwo_devconfig *dc = (void *) c; 551 u_int32_t control; 552 control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL); 553 554 if (!on) { 555 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL, 556 control & ~VC1_SYSCTL_CURSOR_DISPLAY); 557 } else { 558 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8 559 ); 560 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff); 561 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 562 col * dc->dc_fontdata->fontwidth); 563 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 564 row * dc->dc_fontdata->fontheight); 565 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL, 566 control | VC1_SYSCTL_CURSOR_DISPLAY); 567 } 568 } 569 570 static int 571 grtwo_mapchar(void *c, int ch, unsigned int *cp) 572 { 573 struct grtwo_devconfig *dc = (void *) c; 574 575 if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) { 576 ch = wsfont_map_unichar(dc->dc_fontdata, ch); 577 578 if (ch < 0) 579 goto fail; 580 } 581 if (ch < dc->dc_fontdata->firstchar || 582 ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars) 583 goto fail; 584 585 *cp = ch; 586 return 5; 587 588 fail: 589 *cp = ' '; 590 return 0; 591 } 592 593 static void 594 grtwo_putchar(void *c, int row, int col, u_int ch, long attr) 595 { 596 struct grtwo_devconfig *dc = (void *) c; 597 struct wsdisplay_font *font = dc->dc_fontdata; 598 u_int8_t *bitmap = (u_int8_t *) font->data + (ch - font->firstchar + 1) * font->fontheight * font->stride; 599 u_int32_t pattern; 600 int i; 601 int x = col * font->fontwidth; 602 int y = dc->yres - ( (row + 1) * font->fontheight); 603 604 /* Set the drawing color */ 605 grtwo_wait_gfifo(dc); 606 grtwo_set_color(dc->iot, dc->ioh, (((attr) >> 8) & 0xff)); 607 grtwo_wait_gfifo(dc); 608 609 /* Set drawing coordinates */ 610 grtwo_wait_gfifo(dc); 611 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x); 612 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y); 613 614 /* This works for font sizes < 18 */ 615 grtwo_wait_gfifo(dc); 616 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth); 617 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight); 618 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 2); 619 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */ 620 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */ 621 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); 622 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); 623 624 for (i = 0; i < font->fontheight; i++) { 625 /* It appears that writes have to be 16 bits. An "I tell you 626 two times" sort of thing? Thanks, SGI */ 627 pattern = *bitmap | (*bitmap << 8); 628 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern); 629 bitmap -= font->stride; 630 } 631 632 /* pad up to 18 */ 633 for (i = font->fontheight; i < 18; i++) 634 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000); 635 } 636 637 static void 638 grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols) 639 { 640 #if 1 641 printf("grtwo_copycols: %i %i %i %i\n", row, srccol, dstcol, ncols); 642 #else 643 struct grtwo_devconfig *dc = (void *) c; 644 struct wsdisplay_font *font = dc->dc_fontdata; 645 grtwo_copy_rectangle(dc, 646 srccol * font->fontwidth, /* x1 */ 647 0, /* y1 */ 648 dstcol * font->fontwidth, /* x2 */ 649 0, /* y2 */ 650 ncols * font->fontwidth, /* dx */ 651 dc->yres ); /* dy */ 652 #endif 653 } 654 655 static void 656 grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr) 657 { 658 struct grtwo_devconfig *dc = (void *) c; 659 struct wsdisplay_font *font = dc->dc_fontdata; 660 661 grtwo_fill_rectangle(dc, 662 startcol * font->fontwidth, /* x1 */ 663 0, /* y1 */ 664 (startcol * font->fontwidth) + ncols * font->fontwidth, /* x2 */ 665 dc->yres, /* y2 */ 666 GR2_ATTR_BG(attr)); 667 } 668 669 static void 670 grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows) 671 { 672 struct grtwo_devconfig *dc = (void *) c; 673 struct wsdisplay_font *font = dc->dc_fontdata; 674 675 grtwo_copy_rectangle(dc, 676 0, /* x1 */ 677 srcrow * font->fontheight, /* y1 */ 678 0, /* x2 */ 679 dstrow * font->fontheight, /* y2 */ 680 dc->xres, /* dx */ 681 nrows * font->fontheight); 682 } 683 684 static void 685 grtwo_eraserows(void *c, int startrow, int nrows, long attr) 686 { 687 struct grtwo_devconfig *dc = (void *) c; 688 struct wsdisplay_font *font = dc->dc_fontdata; 689 grtwo_fill_rectangle(dc, 690 0, /* x1 */ 691 startrow * font->fontheight, /* y1 */ 692 dc->xres, /* x2 */ 693 (startrow * font->fontheight) + nrows * font->fontheight, /* y2 */ 694 GR2_ATTR_BG(attr)); 695 } 696 697 static int 698 grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr) 699 { 700 if (flags & WSATTR_BLINK) 701 return EINVAL; 702 703 if ((flags & WSATTR_WSCOLORS) == 0) { 704 fg = WSCOL_WHITE; 705 bg = WSCOL_BLACK; 706 } 707 if (flags & WSATTR_HILIT) 708 fg += 8; 709 710 if (flags & WSATTR_REVERSE) { 711 int tmp = fg; 712 fg = bg; 713 bg = tmp; 714 } 715 *attr = GR2_ATTR_ENCODE(fg, bg); 716 717 return 0; 718 } 719 720 /* wsdisplay accessops */ 721 722 static int 723 grtwo_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc * p) 724 { 725 struct grtwo_softc *sc = c; 726 727 #define FBINFO (*(struct wsdisplay_fbinfo*)data) 728 729 switch (cmd) { 730 case WSDISPLAYIO_GINFO: 731 FBINFO.width = sc->sc_dc->xres; 732 FBINFO.height = sc->sc_dc->yres; 733 FBINFO.depth = sc->sc_dc->depth; 734 FBINFO.cmsize = 1 << FBINFO.depth; 735 return 0; 736 case WSDISPLAYIO_GTYPE: 737 *(u_int *) data = WSDISPLAY_TYPE_GR2; 738 return 0; 739 } 740 return EPASSTHROUGH; 741 } 742 743 static paddr_t 744 grtwo_mmap(void *c, off_t offset, int prot) 745 { 746 struct grtwo_devconfig *dc = c; 747 748 if (offset >= 0xfffff) 749 return -1; 750 751 return mips_btop(dc->dc_addr + offset); 752 } 753 754 static int 755 grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep, 756 int *cursxp, int *cursyp, long *attrp) 757 { 758 /* 759 * This won't get called for console screen and we don't support 760 * virtual screens 761 */ 762 763 return ENOMEM; 764 } 765 766 static void 767 grtwo_free_screen(void *c, void *cookie) 768 { 769 panic("grtwo_free_screen"); 770 } 771 static int 772 grtwo_show_screen(void *c, void *cookie, int waitok, 773 void (*cb) (void *, int, int), void *cbarg) 774 { 775 return 0; 776 } 777 778 static int 779 grtwo_intr0(void *arg) 780 { 781 /* struct grtwo_devconfig *dc = arg; */ 782 return 1; 783 } 784 785 786 static int 787 grtwo_intr6(void *arg) 788 { 789 /* struct grtwo_devconfig *dc = arg; */ 790 return 1; 791 } 792 793