1 /* $NetBSD: newport.c,v 1.10 2007/03/04 06:00:39 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Ilpo Ruotsalainen 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 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: newport.c,v 1.10 2007/03/04 06:00:39 christos Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/device.h> 38 #include <sys/malloc.h> 39 40 #include <machine/sysconf.h> 41 42 #include <dev/wscons/wsconsio.h> 43 #include <dev/wscons/wsdisplayvar.h> 44 #include <dev/wsfont/wsfont.h> 45 46 #include <sgimips/gio/giovar.h> 47 #include <sgimips/gio/newportvar.h> 48 #include <sgimips/gio/newportreg.h> 49 50 struct newport_softc { 51 struct device sc_dev; 52 53 struct newport_devconfig *sc_dc; 54 }; 55 56 struct newport_devconfig { 57 uint32_t dc_addr; 58 59 bus_space_tag_t dc_st; 60 bus_space_handle_t dc_sh; 61 62 int dc_boardrev; 63 int dc_vc2rev; 64 int dc_cmaprev; 65 int dc_xmaprev; 66 int dc_rexrev; 67 int dc_xres; 68 int dc_yres; 69 int dc_depth; 70 71 int dc_font; 72 struct wsdisplay_font *dc_fontdata; 73 }; 74 75 static int newport_match(struct device *, struct cfdata *, void *); 76 static void newport_attach(struct device *, struct device *, void *); 77 78 CFATTACH_DECL(newport, sizeof(struct newport_softc), 79 newport_match, newport_attach, NULL, NULL); 80 81 /* textops */ 82 static void newport_cursor(void *, int, int, int); 83 static int newport_mapchar(void *, int, unsigned int *); 84 static void newport_putchar(void *, int, int, u_int, long); 85 static void newport_copycols(void *, int, int, int, int); 86 static void newport_erasecols(void *, int, int, int, long); 87 static void newport_copyrows(void *, int, int, int); 88 static void newport_eraserows(void *, int, int, long); 89 static int newport_allocattr(void *, int, int, int, long *); 90 91 /* accessops */ 92 static int newport_ioctl(void *, void *, u_long, void *, int, 93 struct lwp *); 94 static paddr_t newport_mmap(void *, void *, off_t, int); 95 static int newport_alloc_screen(void *, const struct wsscreen_descr *, 96 void **, int *, int *, long *); 97 static void newport_free_screen(void *, void *); 98 static int newport_show_screen(void *, void *, int, 99 void (*)(void *, int, int), void *); 100 101 static const struct wsdisplay_emulops newport_textops = { 102 .cursor = newport_cursor, 103 .mapchar = newport_mapchar, 104 .putchar = newport_putchar, 105 .copycols = newport_copycols, 106 .erasecols = newport_erasecols, 107 .copyrows = newport_copyrows, 108 .eraserows = newport_eraserows, 109 .allocattr = newport_allocattr 110 }; 111 112 static const struct wsdisplay_accessops newport_accessops = { 113 .ioctl = newport_ioctl, 114 .mmap = newport_mmap, 115 .alloc_screen = newport_alloc_screen, 116 .free_screen = newport_free_screen, 117 .show_screen = newport_show_screen, 118 }; 119 120 static const struct wsscreen_descr newport_screen_1024x768 = { 121 .name = "1024x768", 122 .ncols = 128, 123 .nrows = 48, 124 .textops = &newport_textops, 125 .fontwidth = 8, 126 .fontheight = 16, 127 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE 128 }; 129 130 static const struct wsscreen_descr newport_screen_1280x1024 = { 131 .name = "1280x1024", 132 .ncols = 160, 133 .nrows = 64, 134 .textops = &newport_textops, 135 .fontwidth = 8, 136 .fontheight = 16, 137 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE 138 }; 139 140 static const struct wsscreen_descr *_newport_screenlist[] = { 141 &newport_screen_1024x768, 142 &newport_screen_1280x1024 143 }; 144 145 static const struct wsscreen_list newport_screenlist = { 146 sizeof(_newport_screenlist) / sizeof(struct wsscreen_descr *), 147 _newport_screenlist 148 }; 149 150 static struct newport_devconfig newport_console_dc; 151 static int newport_is_console = 0; 152 153 #define NEWPORT_ATTR_ENCODE(fg,bg) (((fg) << 8) | (bg)) 154 #define NEWPORT_ATTR_BG(a) ((a) & 0xff) 155 #define NEWPORT_ATTR_FG(a) (((a) >> 8) & 0xff) 156 157 static const uint16_t newport_cursor_data[128] = { 158 /* Bit 0 */ 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 0xff00, 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 0x0000, 0x0000, 191 192 /* Bit 1 */ 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 0x0000, 0x0000, 225 }; 226 227 static const uint8_t newport_defcmap[16*3] = { 228 /* Normal colors */ 229 0x00, 0x00, 0x00, /* black */ 230 0x7f, 0x00, 0x00, /* red */ 231 0x00, 0x7f, 0x00, /* green */ 232 0x7f, 0x7f, 0x00, /* brown */ 233 0x00, 0x00, 0x7f, /* blue */ 234 0x7f, 0x00, 0x7f, /* magenta */ 235 0x00, 0x7f, 0x7f, /* cyan */ 236 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ 237 238 /* Hilite colors */ 239 0x7f, 0x7f, 0x7f, /* black */ 240 0xff, 0x00, 0x00, /* red */ 241 0x00, 0xff, 0x00, /* green */ 242 0xff, 0xff, 0x00, /* brown */ 243 0x00, 0x00, 0xff, /* blue */ 244 0xff, 0x00, 0xff, /* magenta */ 245 0x00, 0xff, 0xff, /* cyan */ 246 0xff, 0xff, 0xff, /* white */ 247 }; 248 249 /**** Low-level hardware register groveling functions ****/ 250 static void 251 rex3_write(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val) 252 { 253 bus_space_write_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET + rexreg, 254 val); 255 } 256 257 static void 258 rex3_write_go(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val) 259 { 260 rex3_write(dc, rexreg + REX3_REG_GO, val); 261 } 262 263 static uint32_t 264 rex3_read(struct newport_devconfig *dc, bus_size_t rexreg) 265 { 266 return bus_space_read_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET + 267 rexreg); 268 } 269 270 static void 271 rex3_wait_gfifo(struct newport_devconfig *dc) 272 { 273 while (rex3_read(dc, REX3_REG_STATUS) & REX3_STATUS_GFXBUSY) 274 ; 275 } 276 277 static void 278 vc2_write_ireg(struct newport_devconfig *dc, uint8_t ireg, uint16_t val) 279 { 280 rex3_write(dc, REX3_REG_DCBMODE, 281 REX3_DCBMODE_DW_3 | 282 REX3_DCBMODE_ENCRSINC | 283 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) | 284 (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) | 285 REX3_DCBMODE_ENASYNCACK | 286 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 287 288 rex3_write(dc, REX3_REG_DCBDATA0, (ireg << 24) | (val << 8)); 289 } 290 291 static uint16_t 292 vc2_read_ireg(struct newport_devconfig *dc, uint8_t ireg) 293 { 294 rex3_write(dc, REX3_REG_DCBMODE, 295 REX3_DCBMODE_DW_1 | 296 REX3_DCBMODE_ENCRSINC | 297 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) | 298 (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) | 299 REX3_DCBMODE_ENASYNCACK | 300 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 301 302 rex3_write(dc, REX3_REG_DCBDATA0, ireg << 24); 303 304 rex3_write(dc, REX3_REG_DCBMODE, 305 REX3_DCBMODE_DW_2 | 306 REX3_DCBMODE_ENCRSINC | 307 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) | 308 (VC2_DCBCRS_IREG << REX3_DCBMODE_DCBCRS_SHIFT) | 309 REX3_DCBMODE_ENASYNCACK | 310 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 311 312 return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16); 313 } 314 315 static uint16_t 316 vc2_read_ram(struct newport_devconfig *dc, uint16_t addr) 317 { 318 vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr); 319 320 rex3_write(dc, REX3_REG_DCBMODE, 321 REX3_DCBMODE_DW_2 | 322 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) | 323 (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) | 324 REX3_DCBMODE_ENASYNCACK | 325 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 326 327 return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16); 328 } 329 330 static void 331 vc2_write_ram(struct newport_devconfig *dc, uint16_t addr, uint16_t val) 332 { 333 vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr); 334 335 rex3_write(dc, REX3_REG_DCBMODE, 336 REX3_DCBMODE_DW_2 | 337 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) | 338 (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) | 339 REX3_DCBMODE_ENASYNCACK | 340 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 341 342 rex3_write(dc, REX3_REG_DCBDATA0, val << 16); 343 } 344 345 static u_int32_t 346 xmap9_read(struct newport_devconfig *dc, int crs) 347 { 348 rex3_write(dc, REX3_REG_DCBMODE, 349 REX3_DCBMODE_DW_1 | 350 (NEWPORT_DCBADDR_XMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) | 351 (crs << REX3_DCBMODE_DCBCRS_SHIFT) | 352 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) | 353 (2 << REX3_DCBMODE_CSHOLD_SHIFT) | 354 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 355 return rex3_read(dc, REX3_REG_DCBDATA0); 356 } 357 358 static void 359 xmap9_write(struct newport_devconfig *dc, int crs, uint8_t val) 360 { 361 rex3_write(dc, REX3_REG_DCBMODE, 362 REX3_DCBMODE_DW_1 | 363 (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) | 364 (crs << REX3_DCBMODE_DCBCRS_SHIFT) | 365 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) | 366 (2 << REX3_DCBMODE_CSHOLD_SHIFT) | 367 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 368 369 rex3_write(dc, REX3_REG_DCBDATA0, val << 24); 370 } 371 372 static void 373 xmap9_write_mode(struct newport_devconfig *dc, uint8_t index, uint32_t mode) 374 { 375 rex3_write(dc, REX3_REG_DCBMODE, 376 REX3_DCBMODE_DW_4 | 377 (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) | 378 (XMAP9_DCBCRS_MODE_SETUP << REX3_DCBMODE_DCBCRS_SHIFT) | 379 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) | 380 (2 << REX3_DCBMODE_CSHOLD_SHIFT) | 381 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 382 383 rex3_write(dc, REX3_REG_DCBDATA0, (index << 24) | mode); 384 } 385 386 /**** Helper functions ****/ 387 static void 388 newport_fill_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2, 389 int y2, uint8_t color) 390 { 391 rex3_wait_gfifo(dc); 392 393 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW | 394 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP | 395 REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY); 396 rex3_write(dc, REX3_REG_WRMASK, 0xffffffff); 397 rex3_write(dc, REX3_REG_COLORI, color); 398 rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1); 399 400 rex3_write_go(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2); 401 } 402 403 static void 404 newport_copy_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2, 405 int y2, int dx, int dy) 406 { 407 uint32_t tmp; 408 409 rex3_wait_gfifo(dc); 410 411 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_SCR2SCR | 412 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP | 413 REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY); 414 rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1); 415 rex3_write(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2); 416 417 tmp = (dy - y1) & 0xffff; 418 tmp |= (dx - x1) << REX3_XYMOVE_XSHIFT; 419 420 rex3_write_go(dc, REX3_REG_XYMOVE, tmp); 421 } 422 423 static void 424 newport_cmap_setrgb(struct newport_devconfig *dc, int index, uint8_t r, 425 uint8_t g, uint8_t b) 426 { 427 rex3_write(dc, REX3_REG_DCBMODE, 428 REX3_DCBMODE_DW_2 | 429 REX3_DCBMODE_ENCRSINC | 430 (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) | 431 (CMAP_DCBCRS_ADDRESS_LOW << REX3_DCBMODE_DCBCRS_SHIFT) | 432 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) | 433 (1 << REX3_DCBMODE_CSHOLD_SHIFT) | 434 (1 << REX3_DCBMODE_CSSETUP_SHIFT) | 435 REX3_DCBMODE_SWAPENDIAN); 436 437 rex3_write(dc, REX3_REG_DCBDATA0, index << 16); 438 439 rex3_write(dc, REX3_REG_DCBMODE, 440 REX3_DCBMODE_DW_3 | 441 (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) | 442 (CMAP_DCBCRS_PALETTE << REX3_DCBMODE_DCBCRS_SHIFT) | 443 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) | 444 (1 << REX3_DCBMODE_CSHOLD_SHIFT) | 445 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 446 447 rex3_write(dc, REX3_REG_DCBDATA0, (r << 24) + (g << 16) + (b << 8)); 448 } 449 450 static void 451 newport_get_resolution(struct newport_devconfig *dc) 452 { 453 uint16_t vep,lines; 454 uint16_t linep,cols; 455 uint16_t data; 456 457 vep = vc2_read_ireg(dc, VC2_IREG_VIDEO_ENTRY); 458 459 dc->dc_xres = 0; 460 dc->dc_yres = 0; 461 462 for (;;) { 463 /* Iterate over runs in video timing table */ 464 465 cols = 0; 466 467 linep = vc2_read_ram(dc, vep++); 468 lines = vc2_read_ram(dc, vep++); 469 470 if (lines == 0) 471 break; 472 473 do { 474 /* Iterate over state runs in line sequence table */ 475 476 data = vc2_read_ram(dc, linep++); 477 478 if ((data & 0x0001) == 0) 479 cols += (data >> 7) & 0xfe; 480 481 if ((data & 0x0080) == 0) 482 data = vc2_read_ram(dc, linep++); 483 } while ((data & 0x8000) == 0); 484 485 if (cols != 0) { 486 if (cols > dc->dc_xres) 487 dc->dc_xres = cols; 488 489 dc->dc_yres += lines; 490 } 491 } 492 } 493 494 static void 495 newport_setup_hw(struct newport_devconfig *dc) 496 { 497 uint16_t curp,tmp; 498 int i; 499 uint32_t scratch; 500 501 /* Get various revisions */ 502 rex3_write(dc, REX3_REG_DCBMODE, 503 REX3_DCBMODE_DW_1 | 504 (NEWPORT_DCBADDR_CMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) | 505 (CMAP_DCBCRS_REVISION << REX3_DCBMODE_DCBCRS_SHIFT) | 506 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) | 507 (1 << REX3_DCBMODE_CSHOLD_SHIFT) | 508 (1 << REX3_DCBMODE_CSSETUP_SHIFT)); 509 510 scratch = vc2_read_ireg(dc, VC2_IREG_CONFIG); 511 dc->dc_vc2rev = (scratch & VC2_IREG_CONFIG_REVISION) >> 5; 512 513 scratch = rex3_read(dc, REX3_REG_DCBDATA0); 514 515 dc->dc_boardrev = (scratch >> 28) & 0x07; 516 dc->dc_cmaprev = scratch & 0x07; 517 dc->dc_xmaprev = xmap9_read(dc, XMAP9_DCBCRS_REVISION) & 0x07; 518 dc->dc_depth = ( (dc->dc_boardrev > 1) && (scratch & 0x80)) ? 8 : 24; 519 520 /* Setup cursor glyph */ 521 curp = vc2_read_ireg(dc, VC2_IREG_CURSOR_ENTRY); 522 523 for (i=0; i<128; i++) 524 vc2_write_ram(dc, curp + i, newport_cursor_data[i]); 525 526 /* Setup VC2 to a known state */ 527 tmp = vc2_read_ireg(dc, VC2_IREG_CONTROL) & VC2_CONTROL_INTERLACE; 528 vc2_write_ireg(dc, VC2_IREG_CONTROL, tmp | 529 VC2_CONTROL_DISPLAY_ENABLE | 530 VC2_CONTROL_VTIMING_ENABLE | 531 VC2_CONTROL_DID_ENABLE | 532 VC2_CONTROL_CURSORFUNC_ENABLE | 533 VC2_CONTROL_CURSOR_ENABLE); 534 535 /* Setup XMAP9s */ 536 xmap9_write(dc, XMAP9_DCBCRS_CONFIG, 537 XMAP9_CONFIG_8BIT_SYSTEM | XMAP9_CONFIG_RGBMAP_CI); 538 539 xmap9_write(dc, XMAP9_DCBCRS_CURSOR_CMAP, 0); 540 541 xmap9_write_mode(dc, 0, 542 XMAP9_MODE_GAMMA_BYPASS | 543 XMAP9_MODE_PIXSIZE_8BPP); 544 xmap9_write(dc, XMAP9_DCBCRS_MODE_SELECT, 0); 545 546 /* Setup REX3 */ 547 rex3_write(dc, REX3_REG_DRAWMODE1, 548 REX3_DRAWMODE1_PLANES_CI | 549 REX3_DRAWMODE1_DD_DD8 | 550 REX3_DRAWMODE1_RWPACKED | 551 REX3_DRAWMODE1_HD_HD8 | 552 REX3_DRAWMODE1_COMPARE_LT | 553 REX3_DRAWMODE1_COMPARE_EQ | 554 REX3_DRAWMODE1_COMPARE_GT | 555 REX3_DRAWMODE1_LO_SRC); 556 rex3_write(dc, REX3_REG_XYWIN, (4096 << 16) | 4096); 557 rex3_write(dc, REX3_REG_TOPSCAN, 0x3ff); /* XXX Why? XXX */ 558 559 /* Setup CMAP */ 560 for (i=0; i<16; i++) 561 newport_cmap_setrgb(dc, i, newport_defcmap[i*3], 562 newport_defcmap[i*3 + 1], newport_defcmap[i*3 + 2]); 563 } 564 565 /**** Attach routines ****/ 566 static int 567 newport_match(struct device *parent, struct cfdata *self, void *aux) 568 { 569 struct gio_attach_args *ga = aux; 570 571 /* newport doesn't decode all addresses */ 572 if (ga->ga_addr != 0x1f000000 && ga->ga_addr != 0x1f400000 && 573 ga->ga_addr != 0x1f800000 && ga->ga_addr != 0x1fc00000) 574 return 0; 575 576 /* Don't do the destructive probe if we're already attached */ 577 if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr) 578 return 1; 579 580 if (platform.badaddr( 581 (void *)(ga->ga_ioh + NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI), 582 sizeof(uint32_t))) 583 return 0; 584 if (platform.badaddr( 585 (void *)(ga->ga_ioh + NEWPORT_REX3_OFFSET + REX3_REG_XSTART), 586 sizeof(uint32_t))) 587 return 0; 588 589 /* Ugly, this probe is destructive, blame SGI... */ 590 /* XXX Should be bus_space_peek/bus_space_poke XXX */ 591 bus_space_write_4(ga->ga_iot, ga->ga_ioh, 592 NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI, 0x12345678); 593 if (bus_space_read_4(ga->ga_iot, ga->ga_ioh, 594 NEWPORT_REX3_OFFSET + REX3_REG_XSTART) 595 != ((0x12345678 & 0xffff) << 11)) 596 return 0; 597 598 return 1; 599 } 600 601 static void 602 newport_attach_common(struct newport_devconfig *dc, struct gio_attach_args *ga) 603 { 604 dc->dc_addr = ga->ga_addr; 605 606 dc->dc_st = ga->ga_iot; 607 dc->dc_sh = ga->ga_ioh; 608 609 wsfont_init(); 610 611 dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R, 612 WSDISPLAY_FONTORDER_L2R); 613 if (dc->dc_font < 0) 614 panic("newport_attach_common: no suitable fonts"); 615 616 if (wsfont_lock(dc->dc_font, &dc->dc_fontdata)) 617 panic("newport_attach_common: unable to lock font data"); 618 619 newport_setup_hw(dc); 620 621 newport_get_resolution(dc); 622 623 newport_fill_rectangle(dc, 0, 0, dc->dc_xres, dc->dc_yres, 0); 624 } 625 626 static void 627 newport_attach(struct device *parent, struct device *self, void *aux) 628 { 629 struct gio_attach_args *ga = aux; 630 struct newport_softc *sc = (void *)self; 631 struct wsemuldisplaydev_attach_args wa; 632 633 if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr) { 634 wa.console = 1; 635 sc->sc_dc = &newport_console_dc; 636 } else { 637 wa.console = 0; 638 sc->sc_dc = malloc(sizeof(struct newport_devconfig), 639 M_DEVBUF, M_WAITOK | M_ZERO); 640 if (sc->sc_dc == NULL) 641 panic("newport_attach: out of memory"); 642 643 newport_attach_common(sc->sc_dc, ga); 644 } 645 646 aprint_naive(": Display adapter\n"); 647 648 aprint_normal(": SGI NG1 (board revision %d, cmap revision %d, xmap revision %d, vc2 revision %d), depth %d\n", 649 sc->sc_dc->dc_boardrev, sc->sc_dc->dc_cmaprev, 650 sc->sc_dc->dc_xmaprev, sc->sc_dc->dc_vc2rev, sc->sc_dc->dc_depth); 651 652 wa.scrdata = &newport_screenlist; 653 wa.accessops = &newport_accessops; 654 wa.accesscookie = sc->sc_dc; 655 656 config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint); 657 } 658 659 int 660 newport_cnattach(struct gio_attach_args *ga) 661 { 662 long defattr = NEWPORT_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK); 663 const struct wsscreen_descr *screen; 664 665 if (!newport_match(NULL, NULL, ga)) { 666 return ENXIO; 667 } 668 669 newport_attach_common(&newport_console_dc, ga); 670 671 if (newport_console_dc.dc_xres >= 1280 && 672 newport_console_dc.dc_yres >= 1024) 673 screen = &newport_screen_1280x1024; 674 else 675 screen = &newport_screen_1024x768; 676 677 wsdisplay_cnattach(screen, &newport_console_dc, 0, 0, defattr); 678 679 newport_is_console = 1; 680 681 return 0; 682 } 683 684 /**** wsdisplay textops ****/ 685 static void 686 newport_cursor(void *c, int on, int row, int col) 687 { 688 struct newport_devconfig *dc = (void *)c; 689 uint16_t control; 690 int x_offset; 691 692 control = vc2_read_ireg(dc, VC2_IREG_CONTROL); 693 694 if (!on) { 695 vc2_write_ireg(dc, VC2_IREG_CONTROL, 696 control & ~VC2_CONTROL_CURSOR_ENABLE); 697 } else { 698 /* Work around bug in some board revisions */ 699 if (dc->dc_boardrev < 6) 700 x_offset = 21; 701 else if (dc->dc_vc2rev == 0) 702 x_offset = 29; 703 else 704 x_offset = 31; 705 706 vc2_write_ireg(dc, VC2_IREG_CURSOR_X, 707 col * dc->dc_fontdata->fontwidth + x_offset); 708 vc2_write_ireg(dc, VC2_IREG_CURSOR_Y, 709 row * dc->dc_fontdata->fontheight + 31); 710 711 vc2_write_ireg(dc, VC2_IREG_CONTROL, 712 control | VC2_CONTROL_CURSOR_ENABLE); 713 } 714 } 715 716 static int 717 newport_mapchar(void *c, int ch, unsigned int *cp) 718 { 719 struct newport_devconfig *dc = (void *)c; 720 721 if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) { 722 ch = wsfont_map_unichar(dc->dc_fontdata, ch); 723 724 if (ch < 0) 725 goto fail; 726 } 727 728 if (ch < dc->dc_fontdata->firstchar || 729 ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars) 730 goto fail; 731 732 *cp = ch; 733 return 5; 734 735 fail: 736 *cp = ' '; 737 return 0; 738 } 739 740 static void 741 newport_putchar(void *c, int row, int col, u_int ch, long attr) 742 { 743 struct newport_devconfig *dc = (void *)c; 744 struct wsdisplay_font *font = dc->dc_fontdata; 745 uint8_t *bitmap = (u_int8_t *)font->data + (ch - font->firstchar) * 746 font->fontheight * font->stride; 747 uint32_t pattern; 748 int i; 749 int x = col * font->fontwidth; 750 int y = row * font->fontheight; 751 752 rex3_wait_gfifo(dc); 753 754 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW | 755 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_STOPONX | 756 REX3_DRAWMODE0_ENZPATTERN | REX3_DRAWMODE0_ZPOPAQUE); 757 758 rex3_write(dc, REX3_REG_XYSTARTI, (x << REX3_XYSTARTI_XSHIFT) | y); 759 rex3_write(dc, REX3_REG_XYENDI, 760 (x + font->fontwidth - 1) << REX3_XYENDI_XSHIFT); 761 762 rex3_write(dc, REX3_REG_COLORI, NEWPORT_ATTR_FG(attr)); 763 rex3_write(dc, REX3_REG_COLORBACK, NEWPORT_ATTR_BG(attr)); 764 765 rex3_write(dc, REX3_REG_WRMASK, 0xffffffff); 766 767 for (i=0; i<font->fontheight; i++) { 768 /* XXX Works only with font->fontwidth == 8 XXX */ 769 pattern = *bitmap << 24; 770 771 rex3_write_go(dc, REX3_REG_ZPATTERN, pattern); 772 773 bitmap += font->stride; 774 } 775 } 776 777 static void 778 newport_copycols(void *c, int row, int srccol, int dstcol, int ncols) 779 { 780 struct newport_devconfig *dc = (void *)c; 781 struct wsdisplay_font *font = dc->dc_fontdata; 782 783 newport_copy_rectangle(dc, 784 srccol * font->fontwidth, /* x1 */ 785 row * font->fontheight, /* y1 */ 786 (srccol + ncols + 1) * font->fontwidth - 1, /* x2 */ 787 (row + 1) * font->fontheight - 1, /* y2 */ 788 dstcol * font->fontheight, /* dx */ 789 row * font->fontheight); /* dy */ 790 } 791 792 static void 793 newport_erasecols(void *c, int row, int startcol, int ncols, 794 long attr) 795 { 796 struct newport_devconfig *dc = (void *)c; 797 struct wsdisplay_font *font = dc->dc_fontdata; 798 799 newport_fill_rectangle(dc, 800 startcol * font->fontwidth, /* x1 */ 801 row * font->fontheight, /* y1 */ 802 (startcol + ncols + 1) * font->fontwidth - 1, /* x2 */ 803 (row + 1) * font->fontheight - 1, /* y2 */ 804 NEWPORT_ATTR_BG(attr)); 805 } 806 807 static void 808 newport_copyrows(void *c, int srcrow, int dstrow, int nrows) 809 { 810 struct newport_devconfig *dc = (void *)c; 811 struct wsdisplay_font *font = dc->dc_fontdata; 812 813 newport_copy_rectangle(dc, 814 0, /* x1 */ 815 srcrow * font->fontheight, /* y1 */ 816 dc->dc_xres, /* x2 */ 817 (srcrow + nrows + 1) * font->fontheight - 1, /* y2 */ 818 0, /* dx */ 819 dstrow * font->fontheight); /* dy */ 820 } 821 822 static void 823 newport_eraserows(void *c, int startrow, int nrows, long attr) 824 { 825 struct newport_devconfig *dc = (void *)c; 826 struct wsdisplay_font *font = dc->dc_fontdata; 827 828 newport_fill_rectangle(dc, 829 0, /* x1 */ 830 startrow * font->fontheight, /* y1 */ 831 dc->dc_xres, /* x2 */ 832 (startrow + nrows + 1) * font->fontheight - 1, /* y2 */ 833 NEWPORT_ATTR_BG(attr)); 834 } 835 836 static int 837 newport_allocattr(void *c, int fg, int bg, int flags, long *attr) 838 { 839 if (flags & WSATTR_BLINK) 840 return EINVAL; 841 842 if ((flags & WSATTR_WSCOLORS) == 0) { 843 fg = WSCOL_WHITE; 844 bg = WSCOL_BLACK; 845 } 846 847 if (flags & WSATTR_HILIT) 848 fg += 8; 849 850 if (flags & WSATTR_REVERSE) { 851 int tmp = fg; 852 fg = bg; 853 bg = tmp; 854 } 855 856 *attr = NEWPORT_ATTR_ENCODE(fg, bg); 857 858 return 0; 859 } 860 861 /**** wsdisplay accessops ****/ 862 863 static int 864 newport_ioctl(void *c, void *vs, u_long cmd, void *data, int flag, 865 struct lwp *l) 866 { 867 struct newport_softc *sc = c; 868 869 #define FBINFO (*(struct wsdisplay_fbinfo*)data) 870 871 switch (cmd) { 872 case WSDISPLAYIO_GINFO: 873 FBINFO.width = sc->sc_dc->dc_xres; 874 FBINFO.height = sc->sc_dc->dc_yres; 875 FBINFO.depth = sc->sc_dc->dc_depth; 876 FBINFO.cmsize = 1 << FBINFO.depth; 877 return 0; 878 case WSDISPLAYIO_GTYPE: 879 *(u_int *)data = WSDISPLAY_TYPE_NEWPORT; 880 return 0; 881 } 882 return EPASSTHROUGH; 883 } 884 885 static paddr_t 886 newport_mmap(void *c, void *vs, off_t offset, int prot) 887 { 888 struct newport_devconfig *dc = c; 889 890 if ( offset >= 0xfffff) 891 return -1; 892 893 return mips_btop(dc->dc_addr + offset); 894 } 895 896 static int 897 newport_alloc_screen(void *c, const struct wsscreen_descr *type, void **cookiep, 898 int *cursxp, int *cursyp, long *attrp) 899 { 900 /* This won't get called for console screen and we don't support 901 * virtual screens */ 902 903 return ENOMEM; 904 } 905 906 static void 907 newport_free_screen(void *c, void *cookie) 908 { 909 panic("newport_free_screen"); 910 } 911 static int 912 newport_show_screen(void *c, void *cookie, int waitok, 913 void (*cb)(void *, int, int), void *cbarg) 914 { 915 return 0; 916 } 917