1 /* $OpenBSD: ifb.c,v 1.14 2009/01/04 00:05:52 miod Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2008, 2009 Miodrag Vallat. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Least-effort driver for the Sun Expert3D cards (based on the 21 * ``Wildcat'' chips). 22 * 23 * There is no public documentation for these chips available. 24 * Since they are no longer supported by 3DLabs (which got bought by 25 * Creative), and Sun does not want to publish even minimal information 26 * or source code, the best we can do is experiment. 27 * 28 * Quoting Alan Coopersmith in 29 * http://mail.opensolaris.org/pipermail/opensolaris-discuss/2005-December/011885.html 30 * ``Unfortunately, the lawyers have asked we not give details about why 31 * specific components are not being released.'' 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 #include <sys/errno.h> 38 #include <sys/ioctl.h> 39 #include <sys/malloc.h> 40 #include <sys/pciio.h> 41 42 #include <uvm/uvm_extern.h> 43 44 #include <machine/autoconf.h> 45 #include <machine/bus.h> 46 #include <machine/intr.h> 47 #include <machine/openfirm.h> 48 49 #include <dev/pci/pcireg.h> 50 #include <dev/pci/pcivar.h> 51 #include <dev/pci/pcidevs.h> 52 53 #include <dev/wscons/wsconsio.h> 54 #include <dev/wscons/wsdisplayvar.h> 55 56 #include <dev/rasops/rasops.h> 57 58 #include <machine/fbvar.h> 59 60 #ifdef APERTURE 61 extern int allowaperture; 62 #endif 63 64 /* 65 * Parts of the following hardware knowledge come from David S. Miller's 66 * XVR-500 Linux driver (drivers/video/sunxvr500.c). 67 */ 68 69 /* 70 * The Expert3D and Expert3d-Lite cards are built around the Wildcat 71 * 5110, 6210 and 7210 chips. 72 * 73 * The card exposes the following resources: 74 * - a 32MB aperture window in which views to the different frame buffer 75 * areas can be mapped, in the first BAR. 76 * - a 64KB PROM and registers area, in the second BAR, with the registers 77 * starting 32KB within this area. 78 * - a 8MB memory mapping, which purpose is unknown, in the third BAR. 79 * 80 * In the state the PROM leaves us in, the 8MB frame buffer windows map 81 * the video memory as interleaved stripes, of which the non-visible parts 82 * can still be addressed (probably for fast screen switching). 83 * 84 * Unfortunately, since we do not know how to reconfigure the stripes 85 * to provide at least a linear frame buffer, we have to write to both 86 * windows and have them provide the complete image. 87 * 88 * Moreover, high pixel values in the overlay planes (such as 0xff or 0xfe) 89 * seem to enable other planes with random contents, so we'll limit ourselves 90 * to 7bpp opration. 91 */ 92 93 /* 94 * The Expert3D has an extra BAR that is not present on the -Lite 95 * version. This register contains bits that tell us how many BARs to 96 * skip before we get to the BARs that interest us. 97 */ 98 #define IFB_PCI_CFG 0x5c 99 #define IFB_PCI_CFG_BAR_OFFSET(x) ((x & 0x000000e0) >> 3) 100 101 #define IFB_REG_OFFSET 0x8000 102 103 /* 104 * 0000 magic 105 * This register seems to be used to issue commands to the 106 * acceleration hardware. 107 * 108 */ 109 #define IFB_REG_MAGIC 0x0000 110 #define IFB_REG_MAGIC_DIR_BACKWARDS_Y (0x08 | 0x02) 111 #define IFB_REG_MAGIC_DIR_BACKWARDS_X (0x04 | 0x01) 112 113 /* 114 * 0040 component configuration 115 * This register controls which parts of the board will be addressed by 116 * writes to other configuration registers. 117 * Apparently the low two bytes control the frame buffer windows for the 118 * given head (starting at 1). 119 * The high two bytes are texture related. 120 */ 121 #define IFB_REG_COMPONENT_SELECT 0x0040 122 123 /* 124 * 0044 status 125 * This register has a bit that signals completion of commands issued 126 * to the acceleration hardware. 127 */ 128 #define IFB_REG_STATUS 0x0044 129 #define IFB_REG_STATUS_DONE 0x00000004 130 131 /* 132 * 0058 magnifying configuration 133 * This register apparently controls magnifying. 134 * bits 5-6 select the window width divider (00: by 2, 01: by 4, 10: by 8, 135 * 11: by 16) 136 * bits 7-8 select the zoom factor (00: disabled, 01: x2, 10: x4, 11: x8) 137 */ 138 #define IFB_REG_MAGNIFY 0x0058 139 #define IFB_REG_MAGNIFY_DISABLE 0x00000000 140 #define IFB_REG_MAGNIFY_X2 0x00000040 141 #define IFB_REG_MAGNIFY_X4 0x00000080 142 #define IFB_REG_MAGNIFY_X8 0x000000c0 143 #define IFB_REG_MAGNIFY_WINDIV2 0x00000000 144 #define IFB_REG_MAGNIFY_WINDIV4 0x00000010 145 #define IFB_REG_MAGNIFY_WINDIV8 0x00000020 146 #define IFB_REG_MAGNIFY_WINDIV16 0x00000030 147 148 /* 149 * 0070 display resolution 150 * Contains the size of the display, as ((height - 1) << 16) | (width - 1) 151 */ 152 #define IFB_REG_RESOLUTION 0x0070 153 /* 154 * 0074 configuration register 155 * Contains 0x1a000088 | ((Log2 stride) << 16) 156 */ 157 #define IFB_REG_CONFIG 0x0074 158 /* 159 * 0078 32bit frame buffer window #0 (8 to 9 MB) 160 * Contains the offset (relative to BAR0) of the 32 bit frame buffer window. 161 */ 162 #define IFB_REG_FB32_0 0x0078 163 /* 164 * 007c 32bit frame buffer window #1 (8 to 9 MB) 165 * Contains the offset (relative to BAR0) of the 32 bit frame buffer window. 166 */ 167 #define IFB_REG_FB32_1 0x007c 168 /* 169 * 0080 8bit frame buffer window #0 (2 to 2.2 MB) 170 * Contains the offset (relative to BAR0) of the 8 bit frame buffer window. 171 */ 172 #define IFB_REG_FB8_0 0x0080 173 /* 174 * 0084 8bit frame buffer window #1 (2 to 2.2 MB) 175 * Contains the offset (relative to BAR0) of the 8 bit frame buffer window. 176 */ 177 #define IFB_REG_FB8_1 0x0084 178 /* 179 * 0088 unknown window (as large as a 32 bit frame buffer) 180 */ 181 #define IFB_REG_FB_UNK0 0x0088 182 /* 183 * 008c unknown window (as large as a 8 bit frame buffer) 184 */ 185 #define IFB_REG_FB_UNK1 0x008c 186 /* 187 * 0090 unknown window (as large as a 8 bit frame buffer) 188 */ 189 #define IFB_REG_FB_UNK2 0x0090 190 191 /* 192 * 00bc RAMDAC palette index register 193 */ 194 #define IFB_REG_CMAP_INDEX 0x00bc 195 /* 196 * 00c0 RAMDAC palette data register 197 */ 198 #define IFB_REG_CMAP_DATA 0x00c0 199 200 /* 201 * 00e4 DPMS state register 202 * States ``off'' and ``suspend'' need chip reprogramming before video can 203 * be enabled again. 204 */ 205 #define IFB_REG_DPMS_STATE 0x00e4 206 #define IFB_REG_DPMS_OFF 0x00000000 207 #define IFB_REG_DPMS_SUSPEND 0x00000001 208 #define IFB_REG_DPMS_STANDBY 0x00000002 209 #define IFB_REG_DPMS_ON 0x00000003 210 211 /* 212 * (some) ROP codes 213 */ 214 215 #define IFB_ROP_CLEAR 0x00000000 /* clear bits in rop mask */ 216 #define IFB_ROP_SRC 0x00330000 /* copy src bits matching rop mask */ 217 #define IFB_ROP_XOR 0x00cc0000 /* xor src bits with rop mask */ 218 #define IFB_ROP_SET 0x00ff0000 /* set bits in rop mask */ 219 220 #define IFB_COORDS(x, y) ((x) | (y) << 16) 221 222 #define IFB_PIXELMASK 0x7f /* 7bpp */ 223 224 struct ifb_softc { 225 struct sunfb sc_sunfb; 226 227 bus_space_tag_t sc_mem_t; 228 pcitag_t sc_pcitag; 229 230 bus_space_handle_t sc_mem_h; 231 bus_addr_t sc_membase, sc_fb8bank0_base, sc_fb8bank1_base; 232 bus_size_t sc_memlen; 233 vaddr_t sc_memvaddr, sc_fb8bank0_vaddr, sc_fb8bank1_vaddr; 234 235 bus_space_handle_t sc_reg_h; 236 bus_addr_t sc_regbase; 237 bus_size_t sc_reglen; 238 239 u_int sc_mode; 240 241 void (*sc_old_putchar)(void *, int, int, u_int, long); 242 243 int sc_console; 244 u_int8_t sc_cmap_red[256]; 245 u_int8_t sc_cmap_green[256]; 246 u_int8_t sc_cmap_blue[256]; 247 }; 248 249 int ifb_ioctl(void *, u_long, caddr_t, int, struct proc *); 250 paddr_t ifb_mmap(void *, off_t, int); 251 void ifb_burner(void *, u_int, u_int); 252 253 struct wsdisplay_accessops ifb_accessops = { 254 ifb_ioctl, 255 ifb_mmap, 256 NULL, /* alloc_screen */ 257 NULL, /* free_screen */ 258 NULL, /* show_screen */ 259 NULL, /* load_font */ 260 NULL, /* scrollback */ 261 NULL, /* getchar */ 262 ifb_burner, 263 NULL /* pollc */ 264 }; 265 266 int ifbmatch(struct device *, void *, void *); 267 void ifbattach(struct device *, struct device *, void *); 268 269 struct cfattach ifb_ca = { 270 sizeof (struct ifb_softc), ifbmatch, ifbattach 271 }; 272 273 struct cfdriver ifb_cd = { 274 NULL, "ifb", DV_DULL 275 }; 276 277 int ifb_getcmap(struct ifb_softc *, struct wsdisplay_cmap *); 278 int ifb_is_console(int); 279 int ifb_mapregs(struct ifb_softc *, struct pci_attach_args *); 280 int ifb_putcmap(struct ifb_softc *, struct wsdisplay_cmap *); 281 void ifb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 282 void ifb_setcolormap(struct sunfb *, 283 void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)); 284 285 void ifb_copyrect(struct ifb_softc *, int, int, int, int, int, int); 286 void ifb_fillrect(struct ifb_softc *, int, int, int, int, int); 287 void ifb_rop(struct ifb_softc *, int, int, int, int, int, int, uint32_t, 288 int32_t); 289 void ifb_rop_wait(struct ifb_softc *); 290 291 void ifb_putchar(void *, int, int, u_int, long); 292 void ifb_copycols(void *, int, int, int, int); 293 void ifb_erasecols(void *, int, int, int, long); 294 void ifb_copyrows(void *, int, int, int); 295 void ifb_eraserows(void *, int, int, long); 296 void ifb_do_cursor(struct rasops_info *); 297 298 int 299 ifbmatch(struct device *parent, void *cf, void *aux) 300 { 301 return ifb_ident(aux); 302 } 303 304 void 305 ifbattach(struct device *parent, struct device *self, void *aux) 306 { 307 struct ifb_softc *sc = (struct ifb_softc *)self; 308 struct pci_attach_args *paa = aux; 309 struct rasops_info *ri; 310 int node; 311 312 sc->sc_mem_t = paa->pa_memt; 313 sc->sc_pcitag = paa->pa_tag; 314 315 printf("\n"); 316 317 if (ifb_mapregs(sc, paa)) 318 return; 319 320 sc->sc_fb8bank0_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 321 IFB_REG_OFFSET + IFB_REG_FB8_0); 322 sc->sc_fb8bank1_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 323 IFB_REG_OFFSET + IFB_REG_FB8_1); 324 325 sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h); 326 sc->sc_fb8bank0_vaddr = sc->sc_memvaddr + 327 sc->sc_fb8bank0_base - sc->sc_membase; 328 sc->sc_fb8bank1_vaddr = sc->sc_memvaddr + 329 sc->sc_fb8bank1_base - sc->sc_membase; 330 331 node = PCITAG_NODE(paa->pa_tag); 332 sc->sc_console = ifb_is_console(node); 333 334 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 335 336 printf("%s: %dx%d\n", 337 self->dv_xname, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 338 339 #if 0 340 /* 341 * Make sure the frame buffer is configured to sane values. 342 * So much more is needed there... documentation permitting. 343 */ 344 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 345 IFB_REG_OFFSET + IFB_REG_COMPONENT_SELECT, 0x00000101); 346 delay(1000); 347 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 348 IFB_REG_OFFSET + IFB_REG_MAGNIFY, IFB_REG_MAGNIFY_DISABLE); 349 #endif 350 351 ri = &sc->sc_sunfb.sf_ro; 352 ri->ri_bits = NULL; 353 ri->ri_hw = sc; 354 355 fbwscons_init(&sc->sc_sunfb, RI_BSWAP, sc->sc_console); 356 357 /* 358 * Clear the unwanted pixel planes: all if non console (thus 359 * white background), and all planes above 7bpp otherwise. 360 */ 361 ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height, 362 IFB_ROP_CLEAR, sc->sc_console ? ~IFB_PIXELMASK : ~0); 363 ifb_rop_wait(sc); 364 365 /* pick centering delta */ 366 sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits; 367 sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits; 368 369 sc->sc_old_putchar = ri->ri_ops.putchar; 370 ri->ri_ops.copyrows = ifb_copyrows; 371 ri->ri_ops.copycols = ifb_copycols; 372 ri->ri_ops.eraserows = ifb_eraserows; 373 ri->ri_ops.erasecols = ifb_erasecols; 374 ri->ri_ops.putchar = ifb_putchar; 375 ri->ri_do_cursor = ifb_do_cursor; 376 377 ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor); 378 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 379 380 if (sc->sc_console) 381 fbwscons_console_init(&sc->sc_sunfb, -1); 382 fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, sc->sc_console); 383 } 384 385 int 386 ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 387 { 388 struct ifb_softc *sc = v; 389 struct wsdisplay_fbinfo *wdf; 390 struct pcisel *sel; 391 int mode; 392 393 switch (cmd) { 394 case WSDISPLAYIO_GTYPE: 395 *(u_int *)data = WSDISPLAY_TYPE_IFB; 396 break; 397 398 case WSDISPLAYIO_SMODE: 399 mode = *(u_int *)data; 400 if (mode == WSDISPLAYIO_MODE_EMUL) 401 ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor); 402 sc->sc_mode = mode; 403 break; 404 case WSDISPLAYIO_GINFO: 405 wdf = (void *)data; 406 wdf->height = sc->sc_sunfb.sf_height; 407 wdf->width = sc->sc_sunfb.sf_width; 408 wdf->depth = sc->sc_sunfb.sf_depth; 409 wdf->cmsize = 256; 410 break; 411 case WSDISPLAYIO_LINEBYTES: 412 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 413 break; 414 415 case WSDISPLAYIO_GETCMAP: 416 return ifb_getcmap(sc, (struct wsdisplay_cmap *)data); 417 case WSDISPLAYIO_PUTCMAP: 418 return ifb_putcmap(sc, (struct wsdisplay_cmap *)data); 419 420 case WSDISPLAYIO_GPCIID: 421 sel = (struct pcisel *)data; 422 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 423 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 424 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 425 break; 426 427 case WSDISPLAYIO_SVIDEO: 428 case WSDISPLAYIO_GVIDEO: 429 break; 430 431 case WSDISPLAYIO_GCURPOS: 432 case WSDISPLAYIO_SCURPOS: 433 case WSDISPLAYIO_GCURMAX: 434 case WSDISPLAYIO_GCURSOR: 435 case WSDISPLAYIO_SCURSOR: 436 default: 437 return -1; /* not supported yet */ 438 } 439 440 return 0; 441 } 442 443 int 444 ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm) 445 { 446 u_int index = cm->index; 447 u_int count = cm->count; 448 int error; 449 450 if (index >= 256 || count > 256 - index) 451 return EINVAL; 452 453 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 454 if (error) 455 return error; 456 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 457 if (error) 458 return error; 459 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 460 if (error) 461 return error; 462 return 0; 463 } 464 465 int 466 ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm) 467 { 468 u_int index = cm->index; 469 u_int count = cm->count; 470 u_int i; 471 int error; 472 u_char *r, *g, *b; 473 474 if (index >= 256 || count > 256 - index) 475 return EINVAL; 476 477 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 478 return error; 479 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 480 return error; 481 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 482 return error; 483 484 r = &sc->sc_cmap_red[index]; 485 g = &sc->sc_cmap_green[index]; 486 b = &sc->sc_cmap_blue[index]; 487 488 for (i = 0; i < count; i++) { 489 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 490 IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index); 491 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 492 IFB_REG_OFFSET + IFB_REG_CMAP_DATA, 493 (((u_int)*b) << 22) | (((u_int)*g) << 12) | (((u_int)*r) << 2)); 494 r++, g++, b++, index++; 495 } 496 return 0; 497 } 498 499 void 500 ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 501 { 502 struct ifb_softc *sc = v; 503 504 sc->sc_cmap_red[index] = r; 505 sc->sc_cmap_green[index] = g; 506 sc->sc_cmap_blue[index] = b; 507 508 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 509 IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index); 510 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 511 IFB_REG_OFFSET + IFB_REG_CMAP_DATA, 512 (((u_int)b) << 22) | (((u_int)g) << 12) | (((u_int)r) << 2)); 513 } 514 515 /* similar in spirit to fbwscons_setcolormap() */ 516 void 517 ifb_setcolormap(struct sunfb *sf, 518 void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)) 519 { 520 struct rasops_info *ri = &sf->sf_ro; 521 int i; 522 const u_char *color; 523 524 /* 525 * Compensate for overlay plane limitations. Since we'll operate 526 * in 7bpp mode, our basic colors will use positions 00 to 0f, 527 * and the inverted colors will use positions 7f to 70. 528 */ 529 530 for (i = 0x00; i < 0x10; i++) { 531 color = &rasops_cmap[i * 3]; 532 setcolor(sf, i, color[0], color[1], color[2]); 533 } 534 for (i = 0x70; i < 0x80; i++) { 535 color = &rasops_cmap[(0xf0 | i) * 3]; 536 setcolor(sf, i, color[0], color[1], color[2]); 537 } 538 539 /* 540 * Proper operation apparently needs black to be 01, always. 541 * Replace black, red and white with white, black and red. 542 * Kind of ugly, but it works. 543 */ 544 ri->ri_devcmap[WSCOL_WHITE] = 0x00000000; 545 ri->ri_devcmap[WSCOL_BLACK] = 0x01010101; 546 ri->ri_devcmap[WSCOL_RED] = 0x07070707; 547 548 color = &rasops_cmap[(WSCOL_WHITE + 8) * 3]; /* real white */ 549 setcolor(sf, 0, color[0], color[1], color[2]); 550 setcolor(sf, IFB_PIXELMASK ^ 0, ~color[0], ~color[1], ~color[2]); 551 color = &rasops_cmap[WSCOL_BLACK * 3]; 552 setcolor(sf, 1, color[0], color[1], color[2]); 553 setcolor(sf, IFB_PIXELMASK ^ 1, ~color[0], ~color[1], ~color[2]); 554 color = &rasops_cmap[WSCOL_RED * 3]; 555 setcolor(sf, 7, color[0], color[1], color[2]); 556 setcolor(sf, IFB_PIXELMASK ^ 7, ~color[0], ~color[1], ~color[2]); 557 } 558 559 paddr_t 560 ifb_mmap(void *v, off_t off, int prot) 561 { 562 struct ifb_softc *sc = (struct ifb_softc *)v; 563 564 switch (sc->sc_mode) { 565 case WSDISPLAYIO_MODE_MAPPED: 566 /* 567 * In mapped mode, provide access to the two overlays, 568 * followed by the control registers, at the following 569 * addresses: 570 * 00000000 overlay 0, size up to 2MB (visible fb size) 571 * 01000000 overlay 1, size up to 2MB (visible fb size) 572 * 02000000 control registers 573 */ 574 off -= 0x00000000; 575 if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) { 576 return bus_space_mmap(sc->sc_mem_t, 577 sc->sc_fb8bank0_base, 578 off, prot, BUS_SPACE_MAP_LINEAR); 579 } 580 off -= 0x01000000; 581 if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) { 582 return bus_space_mmap(sc->sc_mem_t, 583 sc->sc_fb8bank1_base, 584 off, prot, BUS_SPACE_MAP_LINEAR); 585 } 586 #ifdef APERTURE 587 off -= 0x01000000; 588 if (allowaperture != 0) { 589 if (off >= 0 && off < round_page(sc->sc_reglen)) { 590 return bus_space_mmap(sc->sc_mem_t, 591 sc->sc_regbase, 592 off, prot, BUS_SPACE_MAP_LINEAR); 593 } 594 } 595 #endif 596 break; 597 } 598 599 return -1; 600 } 601 602 void 603 ifb_burner(void *v, u_int on, u_int flags) 604 { 605 struct ifb_softc *sc = (struct ifb_softc *)v; 606 int s; 607 uint32_t dpms; 608 609 s = splhigh(); 610 if (on) 611 dpms = IFB_REG_DPMS_ON; 612 else { 613 #ifdef notyet 614 if (flags & WSDISPLAY_BURN_VBLANK) 615 dpms = IFB_REG_DPMS_SUSPEND; 616 else 617 #endif 618 dpms = IFB_REG_DPMS_STANDBY; 619 } 620 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 621 IFB_REG_OFFSET + IFB_REG_DPMS_STATE, dpms); 622 splx(s); 623 } 624 625 int 626 ifb_is_console(int node) 627 { 628 extern int fbnode; 629 630 return fbnode == node; 631 } 632 633 int 634 ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa) 635 { 636 u_int32_t cf; 637 int bar, rc; 638 639 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, IFB_PCI_CFG); 640 bar = PCI_MAPREG_START + IFB_PCI_CFG_BAR_OFFSET(cf); 641 642 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); 643 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) 644 rc = EINVAL; 645 else { 646 rc = pci_mapreg_map(pa, bar, cf, 647 BUS_SPACE_MAP_LINEAR, NULL, &sc->sc_mem_h, 648 &sc->sc_membase, &sc->sc_memlen, 0); 649 } 650 if (rc != 0) { 651 printf("%s: can't map video memory\n", 652 sc->sc_sunfb.sf_dev.dv_xname); 653 return rc; 654 } 655 656 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar + 4); 657 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) 658 rc = EINVAL; 659 else { 660 rc = pci_mapreg_map(pa, bar + 4, cf, 661 0, NULL, &sc->sc_reg_h, 662 &sc->sc_regbase, &sc->sc_reglen, 0x9000); 663 } 664 if (rc != 0) { 665 printf("%s: can't map register space\n", 666 sc->sc_sunfb.sf_dev.dv_xname); 667 return rc; 668 } 669 670 return 0; 671 } 672 673 void 674 ifb_putchar(void *cookie, int row, int col, u_int uc, long attr) 675 { 676 struct rasops_info *ri = cookie; 677 struct ifb_softc *sc = ri->ri_hw; 678 679 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 680 sc->sc_old_putchar(cookie, row, col, uc, attr); 681 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 682 sc->sc_old_putchar(cookie, row, col, uc, attr); 683 } 684 685 void 686 ifb_copycols(void *cookie, int row, int src, int dst, int num) 687 { 688 struct rasops_info *ri = cookie; 689 struct ifb_softc *sc = ri->ri_hw; 690 691 num *= ri->ri_font->fontwidth; 692 src *= ri->ri_font->fontwidth; 693 dst *= ri->ri_font->fontwidth; 694 row *= ri->ri_font->fontheight; 695 696 ifb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 697 ri->ri_xorigin + dst, ri->ri_yorigin + row, 698 num, ri->ri_font->fontheight); 699 } 700 701 void 702 ifb_erasecols(void *cookie, int row, int col, int num, long attr) 703 { 704 struct rasops_info *ri = cookie; 705 struct ifb_softc *sc = ri->ri_hw; 706 int bg, fg; 707 708 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 709 710 row *= ri->ri_font->fontheight; 711 col *= ri->ri_font->fontwidth; 712 num *= ri->ri_font->fontwidth; 713 714 ifb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 715 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 716 } 717 718 void 719 ifb_copyrows(void *cookie, int src, int dst, int num) 720 { 721 struct rasops_info *ri = cookie; 722 struct ifb_softc *sc = ri->ri_hw; 723 724 num *= ri->ri_font->fontheight; 725 src *= ri->ri_font->fontheight; 726 dst *= ri->ri_font->fontheight; 727 728 ifb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 729 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 730 } 731 732 void 733 ifb_eraserows(void *cookie, int row, int num, long attr) 734 { 735 struct rasops_info *ri = cookie; 736 struct ifb_softc *sc = ri->ri_hw; 737 int bg, fg; 738 int x, y, w; 739 740 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 741 742 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 743 num = ri->ri_height; 744 x = y = 0; 745 w = ri->ri_width; 746 } else { 747 num *= ri->ri_font->fontheight; 748 x = ri->ri_xorigin; 749 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 750 w = ri->ri_emuwidth; 751 } 752 ifb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 753 } 754 755 void 756 ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) 757 { 758 ifb_rop(sc, sx, sy, dx, dy, w, h, IFB_ROP_SRC, IFB_PIXELMASK); 759 ifb_rop_wait(sc); 760 } 761 762 void 763 ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg) 764 { 765 int32_t mask; 766 767 /* pixels to set... */ 768 mask = IFB_PIXELMASK & bg; 769 if (mask != 0) { 770 ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_SET, mask); 771 ifb_rop_wait(sc); 772 } 773 774 /* pixels to clear... */ 775 mask = IFB_PIXELMASK & ~bg; 776 if (mask != 0) { 777 ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_CLEAR, mask); 778 ifb_rop_wait(sc); 779 } 780 } 781 782 /* 783 * Perform a raster operation on both overlay planes. 784 * Puzzled by all the magic numbers in there? So are we. Isn't a dire 785 * lack of documentation wonderful? 786 */ 787 void 788 ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h, 789 uint32_t rop, int32_t planemask) 790 { 791 int dir = 0; 792 793 /* 794 * Compute rop direction. This only really matters for 795 * screen-to-screen copies. 796 */ 797 if (sy < dy /* && sy + h > dy */) { 798 sy += h - 1; 799 dy += h; 800 dir |= IFB_REG_MAGIC_DIR_BACKWARDS_Y; 801 } 802 if (sx < dx /* && sx + w > dx */) { 803 sx += w - 1; 804 dx += w; 805 dir |= IFB_REG_MAGIC_DIR_BACKWARDS_X; 806 } 807 808 /* Which one of those below is your magic number for today? */ 809 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 810 IFB_REG_OFFSET + IFB_REG_MAGIC, 2); 811 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 812 IFB_REG_OFFSET + IFB_REG_MAGIC, 1); 813 /* the ``0101'' part is probably a component selection */ 814 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 815 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x540101ff); 816 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 817 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x61000001); 818 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 819 IFB_REG_OFFSET + IFB_REG_MAGIC, 0); 820 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 821 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x6301c080); 822 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 823 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x80000000); 824 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 825 IFB_REG_OFFSET + IFB_REG_MAGIC, rop); 826 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 827 IFB_REG_OFFSET + IFB_REG_MAGIC, planemask); 828 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 829 IFB_REG_OFFSET + IFB_REG_MAGIC, 0); 830 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 831 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x64000303); 832 /* 833 * This value is a pixel offset within the destination area. It is 834 * probably used to define complex polygon shapes, with the 835 * last pixel in the list being back to (0,0). 836 */ 837 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 838 IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(0, 0)); 839 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 840 IFB_REG_OFFSET + IFB_REG_MAGIC, 0); 841 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 842 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x00030000); 843 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 844 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x2200010d); 845 846 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 847 IFB_REG_OFFSET + IFB_REG_MAGIC, 0x33f01000 | dir); 848 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 849 IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(dx, dy)); 850 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 851 IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(w, h)); 852 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 853 IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(sx, sy)); 854 } 855 856 void 857 ifb_rop_wait(struct ifb_softc *sc) 858 { 859 int i; 860 861 for (i = 1000000; i > 0; i--) { 862 if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 863 IFB_REG_OFFSET + IFB_REG_STATUS) & IFB_REG_STATUS_DONE) 864 break; 865 DELAY(1); 866 } 867 } 868 869 void 870 ifb_do_cursor(struct rasops_info *ri) 871 { 872 struct ifb_softc *sc = ri->ri_hw; 873 int y, x; 874 875 y = ri->ri_yorigin + ri->ri_crow * ri->ri_font->fontheight; 876 x = ri->ri_xorigin + ri->ri_ccol * ri->ri_font->fontwidth; 877 878 ifb_rop(sc, x, y, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight, 879 IFB_ROP_XOR, IFB_PIXELMASK); 880 ifb_rop_wait(sc); 881 } 882