1 /* $OpenBSD: ifb.c,v 1.16 2009/01/21 17:01:31 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 or 128KB PROM and registers area, in the second BAR. 77 * - a 8MB ``direct burst'' memory mapping, in the third BAR. 78 * 79 * The location of this BAR range is pointed to by a board-specific PCI 80 * configuration register. 81 * 82 * In the state the PROM leaves us in, the 8MB frame buffer windows map 83 * the video memory as interleaved stripes, of which the non-visible parts 84 * can still be addressed (probably for fast screen switching). 85 * 86 * Unfortunately, since we do not know how to reconfigure the stripes 87 * to provide at least a linear frame buffer, we have to write to both 88 * windows and have them provide the complete image. 89 * 90 * Moreover, high pixel values in the overlay planes (such as 0xff or 0xfe) 91 * seem to enable other planes with random contents, so we'll limit ourselves 92 * to 7bpp opration. 93 */ 94 95 /* 96 * The Fcode driver sets up a communication structure, allowing third-party 97 * code to reprogram the video mode while still allowing the Fcode routines 98 * to access the overlay planes. 99 * 100 * We'll use this information as well, although so far it's unlikely 101 * any code will do so, as long as the only documentation for this 102 * hardware amounts to zilch. 103 */ 104 105 /* probably some form of signature */ 106 #define IFB_SHARED_SIGNATURE 0x00 107 #define SIG_IFB 0x09209911 108 #define SIG_JFB 0x05140213 109 #define IFB_SHARED_MONITOR_MODE 0x10 110 #define IFB_SHARED_WIDTH 0x14 111 #define IFB_SHARED_HEIGHT 0x18 112 #define IFB_SHARED_V_FREQ 0x1c 113 #define IFB_SHARED_TIMING_H_FP 0x20 114 #define IFB_SHARED_TIMING_H_SYNC 0x24 115 #define IFB_SHARED_TIMING_H_BP 0x28 116 #define IFB_SHARED_TIMING_V_FP 0x2c 117 #define IFB_SHARED_TIMING_V_SYNC 0x30 118 #define IFB_SHARED_TIMING_V_BP 0x34 119 #define IFB_SHARED_TIMING_FLAGS 0x38 120 #define IFB_SHARED_CMAP_DIRTY 0x3c 121 #define IFB_SHARED_TERM8_GSR 0x4c 122 #define IFB_SHARED_TERM8_SPR 0x50 123 #define IFB_SHARED_TERM8_SPLR 0x54 124 125 /* 126 * The Expert3D has an extra BAR that is not present on the -Lite 127 * version. This register contains bits that tell us how many BARs to 128 * skip before we get to the BARs that interest us. 129 */ 130 #define IFB_PCI_CFG 0x5c 131 #define IFB_PCI_CFG_BAR_OFFSET(x) ((x & 0x000000e0) >> 3) 132 133 /* 134 * 6000 (jfb) / 8000 (ifb) engine command 135 * This register is used to issue (some) commands sequences to the 136 * acceleration hardware. 137 */ 138 #define JFB_REG_ENGINE 0x6000 139 #define IFB_REG_ENGINE 0x8000 140 141 /* 142 * 8040 component configuration 143 * This register controls which parts of the board will be addressed by 144 * writes to other configuration registers. 145 * Apparently the low two bytes control the frame buffer windows for the 146 * given head (starting at 1). 147 * The high two bytes are texture related. 148 */ 149 #define IFB_REG_COMPONENT_SELECT 0x8040 150 151 /* 152 * 8044 status 153 * This register has a bit that signals completion of commands issued 154 * to the acceleration hardware. 155 */ 156 #define IFB_REG_STATUS 0x8044 157 #define IFB_REG_STATUS_DONE 0x00000004 158 159 /* 160 * 8058 magnifying configuration 161 * This register apparently controls magnifying. 162 * bits 5-6 select the window width divider (00: by 2, 01: by 4, 10: by 8, 163 * 11: by 16) 164 * bits 7-8 select the zoom factor (00: disabled, 01: x2, 10: x4, 11: x8) 165 */ 166 #define IFB_REG_MAGNIFY 0x8058 167 #define IFB_REG_MAGNIFY_DISABLE 0x00000000 168 #define IFB_REG_MAGNIFY_X2 0x00000040 169 #define IFB_REG_MAGNIFY_X4 0x00000080 170 #define IFB_REG_MAGNIFY_X8 0x000000c0 171 #define IFB_REG_MAGNIFY_WINDIV2 0x00000000 172 #define IFB_REG_MAGNIFY_WINDIV4 0x00000010 173 #define IFB_REG_MAGNIFY_WINDIV8 0x00000020 174 #define IFB_REG_MAGNIFY_WINDIV16 0x00000030 175 176 /* 177 * 8070 display resolution 178 * Contains the size of the display, as ((height - 1) << 16) | (width - 1) 179 */ 180 #define IFB_REG_RESOLUTION 0x8070 181 /* 182 * 8074 configuration register 183 * Contains 0x1a000088 | ((Log2 stride) << 16) 184 */ 185 #define IFB_REG_CONFIG 0x8074 186 /* 187 * 8078 32bit frame buffer window #0 (8 to 9 MB) 188 * Contains the offset (relative to BAR0) of the 32 bit frame buffer window. 189 */ 190 #define IFB_REG_FB32_0 0x8078 191 /* 192 * 807c 32bit frame buffer window #1 (8 to 9 MB) 193 * Contains the offset (relative to BAR0) of the 32 bit frame buffer window. 194 */ 195 #define IFB_REG_FB32_1 0x807c 196 /* 197 * 8080 8bit frame buffer window #0 (2 to 2.2 MB) 198 * Contains the offset (relative to BAR0) of the 8 bit frame buffer window. 199 */ 200 #define IFB_REG_FB8_0 0x8080 201 /* 202 * 8084 8bit frame buffer window #1 (2 to 2.2 MB) 203 * Contains the offset (relative to BAR0) of the 8 bit frame buffer window. 204 */ 205 #define IFB_REG_FB8_1 0x8084 206 /* 207 * 8088 unknown window (as large as a 32 bit frame buffer) 208 */ 209 #define IFB_REG_FB_UNK0 0x8088 210 /* 211 * 808c unknown window (as large as a 8 bit frame buffer) 212 */ 213 #define IFB_REG_FB_UNK1 0x808c 214 /* 215 * 8090 unknown window (as large as a 8 bit frame buffer) 216 */ 217 #define IFB_REG_FB_UNK2 0x8090 218 219 /* 220 * 80bc RAMDAC palette index register 221 */ 222 #define IFB_REG_CMAP_INDEX 0x80bc 223 /* 224 * 80c0 RAMDAC palette data register 225 */ 226 #define IFB_REG_CMAP_DATA 0x80c0 227 228 /* 229 * 80e4 DPMS state register 230 * States ``off'' and ``suspend'' need chip reprogramming before video can 231 * be enabled again. 232 */ 233 #define IFB_REG_DPMS_STATE 0x80e4 234 #define IFB_REG_DPMS_OFF 0x00000000 235 #define IFB_REG_DPMS_SUSPEND 0x00000001 236 #define IFB_REG_DPMS_STANDBY 0x00000002 237 #define IFB_REG_DPMS_ON 0x00000003 238 239 /* 240 * (some) ROP codes 241 */ 242 243 #define IFB_ROP_CLEAR 0x00000000 /* clear bits in rop mask */ 244 #define IFB_ROP_SRC 0x00330000 /* copy src bits matching rop mask */ 245 #define IFB_ROP_XOR 0x00cc0000 /* xor src bits with rop mask */ 246 #define IFB_ROP_SET 0x00ff0000 /* set bits in rop mask */ 247 248 #define IFB_COORDS(x, y) ((x) | (y) << 16) 249 250 /* blitter directions */ 251 #define IFB_BLT_DIR_BACKWARDS_Y (0x08 | 0x02) 252 #define IFB_BLT_DIR_BACKWARDS_X (0x04 | 0x01) 253 254 #define IFB_PIXELMASK 0x7f /* 7bpp */ 255 256 struct ifb_softc { 257 struct sunfb sc_sunfb; 258 259 bus_space_tag_t sc_mem_t; 260 pcitag_t sc_pcitag; 261 262 /* overlays mappings */ 263 bus_space_handle_t sc_mem_h; 264 bus_addr_t sc_membase, sc_fb8bank0_base, sc_fb8bank1_base; 265 bus_size_t sc_memlen; 266 vaddr_t sc_memvaddr, sc_fb8bank0_vaddr, sc_fb8bank1_vaddr; 267 268 /* registers mapping */ 269 bus_space_handle_t sc_reg_h; 270 bus_addr_t sc_regbase; 271 bus_size_t sc_reglen; 272 273 /* communication area */ 274 volatile uint32_t *sc_comm; 275 276 /* acceleration information */ 277 u_int sc_acceltype; 278 #define IFB_ACCEL_NONE 0 279 #define IFB_ACCEL_IFB 1 /* Expert3D style */ 280 #define IFB_ACCEL_JFB 2 /* XVR-500 style */ 281 void (*sc_rop)(void *, int, int, int, int, int, int, uint32_t, int32_t); 282 283 /* wsdisplay related goo */ 284 u_int sc_mode; 285 struct wsdisplay_emulops sc_old_ops; 286 u_int8_t sc_cmap_red[256]; 287 u_int8_t sc_cmap_green[256]; 288 u_int8_t sc_cmap_blue[256]; 289 }; 290 291 int ifb_ioctl(void *, u_long, caddr_t, int, struct proc *); 292 paddr_t ifb_mmap(void *, off_t, int); 293 void ifb_burner(void *, u_int, u_int); 294 295 struct wsdisplay_accessops ifb_accessops = { 296 ifb_ioctl, 297 ifb_mmap, 298 NULL, /* alloc_screen */ 299 NULL, /* free_screen */ 300 NULL, /* show_screen */ 301 NULL, /* load_font */ 302 NULL, /* scrollback */ 303 NULL, /* getchar */ 304 ifb_burner, 305 NULL /* pollc */ 306 }; 307 308 int ifbmatch(struct device *, void *, void *); 309 void ifbattach(struct device *, struct device *, void *); 310 311 struct cfattach ifb_ca = { 312 sizeof (struct ifb_softc), ifbmatch, ifbattach 313 }; 314 315 struct cfdriver ifb_cd = { 316 NULL, "ifb", DV_DULL 317 }; 318 319 int ifb_accel_identify(struct pci_attach_args *); 320 static inline 321 u_int ifb_dac_value(u_int, u_int, u_int); 322 int ifb_getcmap(struct ifb_softc *, struct wsdisplay_cmap *); 323 static inline 324 int ifb_is_console(int); 325 int ifb_mapregs(struct ifb_softc *, struct pci_attach_args *); 326 int ifb_putcmap(struct ifb_softc *, struct wsdisplay_cmap *); 327 void ifb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 328 void ifb_setcolormap(struct sunfb *, 329 void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)); 330 331 void ifb_copyrect(struct ifb_softc *, int, int, int, int, int, int); 332 void ifb_fillrect(struct ifb_softc *, int, int, int, int, int); 333 static inline 334 void ifb_rop(struct ifb_softc *, int, int, int, int, int, int, uint32_t, 335 int32_t); 336 void ifb_rop_common(struct ifb_softc *, bus_addr_t, int, int, int, int, 337 int, int, uint32_t, int32_t); 338 void ifb_rop_ifb(void *, int, int, int, int, int, int, uint32_t, int32_t); 339 void ifb_rop_jfb(void *, int, int, int, int, int, int, uint32_t, int32_t); 340 int ifb_rop_wait(struct ifb_softc *); 341 342 void ifb_putchar_dumb(void *, int, int, u_int, long); 343 void ifb_copycols_dumb(void *, int, int, int, int); 344 void ifb_erasecols_dumb(void *, int, int, int, long); 345 void ifb_copyrows_dumb(void *, int, int, int); 346 void ifb_eraserows_dumb(void *, int, int, long); 347 void ifb_do_cursor_dumb(struct rasops_info *); 348 349 void ifb_putchar(void *, int, int, u_int, long); 350 void ifb_copycols(void *, int, int, int, int); 351 void ifb_erasecols(void *, int, int, int, long); 352 void ifb_copyrows(void *, int, int, int); 353 void ifb_eraserows(void *, int, int, long); 354 void ifb_do_cursor(struct rasops_info *); 355 356 int 357 ifbmatch(struct device *parent, void *cf, void *aux) 358 { 359 return ifb_ident(aux); 360 } 361 362 void 363 ifbattach(struct device *parent, struct device *self, void *aux) 364 { 365 struct ifb_softc *sc = (struct ifb_softc *)self; 366 struct pci_attach_args *paa = aux; 367 struct rasops_info *ri; 368 uint32_t dev_comm; 369 int node, console; 370 char *text; 371 372 sc->sc_mem_t = paa->pa_memt; 373 sc->sc_pcitag = paa->pa_tag; 374 375 node = PCITAG_NODE(paa->pa_tag); 376 console = ifb_is_console(node); 377 378 printf("\n"); 379 380 /* 381 * Multiple heads appear as PCI subfunctions. 382 * However, the ofw node for it lacks most properties, 383 * and its BAR only give access to registers, not 384 * frame buffer memory. 385 */ 386 if (!node_has_property(node, "device_type")) { 387 printf("%s: secondary output not supported yet\n", 388 self->dv_xname); 389 return; 390 } 391 392 /* 393 * Describe the beast. 394 */ 395 396 text = getpropstring(node, "name"); 397 if (strncmp(text, "SUNW,", 5) == 0) 398 text += 5; 399 printf("%s: %s", self->dv_xname, text); 400 text = getpropstring(node, "model"); 401 if (*text != '\0') 402 printf(" (%s)", text); 403 404 if (ifb_mapregs(sc, paa)) 405 return; 406 407 sc->sc_fb8bank0_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 408 IFB_REG_FB8_0); 409 sc->sc_fb8bank1_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 410 IFB_REG_FB8_1); 411 412 sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h); 413 sc->sc_fb8bank0_vaddr = sc->sc_memvaddr + 414 sc->sc_fb8bank0_base - sc->sc_membase; 415 sc->sc_fb8bank1_vaddr = sc->sc_memvaddr + 416 sc->sc_fb8bank1_base - sc->sc_membase; 417 418 /* 419 * The values stored into the node properties might have been 420 * modified since the Fcode was last run. Pick the geometry 421 * information from the configuration registers instead. 422 * This replaces 423 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 424 */ 425 426 sc->sc_sunfb.sf_width = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 427 IFB_REG_RESOLUTION) & 0xffff) + 1; 428 sc->sc_sunfb.sf_height = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 429 IFB_REG_RESOLUTION) >> 16) + 1; 430 sc->sc_sunfb.sf_depth = 8; 431 sc->sc_sunfb.sf_linebytes = 1 << (bus_space_read_4(sc->sc_mem_t, 432 sc->sc_reg_h, IFB_REG_CONFIG) >> 16); 433 sc->sc_sunfb.sf_fbsize = 434 sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes; 435 436 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 437 438 ri = &sc->sc_sunfb.sf_ro; 439 ri->ri_bits = NULL; 440 ri->ri_hw = sc; 441 442 fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console); 443 444 /* 445 * Find out what flavour of ifb we are... 446 */ 447 448 sc->sc_acceltype = ifb_accel_identify(paa); 449 450 switch (sc->sc_acceltype) { 451 case IFB_ACCEL_IFB: 452 sc->sc_rop = ifb_rop_ifb; 453 break; 454 case IFB_ACCEL_JFB: 455 /* 456 * Remember the address of the communication area 457 */ 458 if (OF_getprop(node, "dev-comm", &dev_comm, 459 sizeof dev_comm) != -1) { 460 sc->sc_comm = (volatile uint32_t *)(vaddr_t)dev_comm; 461 } 462 sc->sc_rop = ifb_rop_jfb; 463 break; 464 } 465 466 /* 467 * Clear the unwanted pixel planes: all if non console (thus 468 * white background), and all planes above 7bpp otherwise. 469 * This also allows to check whether the accelerated code works, 470 * or not. 471 */ 472 473 if (sc->sc_acceltype != IFB_ACCEL_NONE) { 474 ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width, 475 sc->sc_sunfb.sf_height, IFB_ROP_CLEAR, 476 console ? ~IFB_PIXELMASK : ~0); 477 if (ifb_rop_wait(sc) == 0) { 478 /* fall back to dumb software operation */ 479 sc->sc_acceltype = IFB_ACCEL_NONE; 480 } 481 } 482 483 if (sc->sc_acceltype == IFB_ACCEL_NONE) { 484 /* due to the way we will handle updates */ 485 ri->ri_flg &= ~RI_FULLCLEAR; 486 487 if (!console) { 488 bzero((void *)sc->sc_fb8bank0_vaddr, 489 sc->sc_sunfb.sf_fbsize); 490 bzero((void *)sc->sc_fb8bank1_vaddr, 491 sc->sc_sunfb.sf_fbsize); 492 } 493 } 494 495 /* pick centering delta */ 496 sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits; 497 sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits; 498 499 sc->sc_old_ops = ri->ri_ops; /* structure copy */ 500 501 if (sc->sc_acceltype != IFB_ACCEL_NONE) { 502 ri->ri_ops.copyrows = ifb_copyrows; 503 ri->ri_ops.copycols = ifb_copycols; 504 ri->ri_ops.eraserows = ifb_eraserows; 505 ri->ri_ops.erasecols = ifb_erasecols; 506 ri->ri_ops.putchar = ifb_putchar_dumb; 507 ri->ri_do_cursor = ifb_do_cursor; 508 } else { 509 ri->ri_ops.copyrows = ifb_copyrows_dumb; 510 ri->ri_ops.copycols = ifb_copycols_dumb; 511 ri->ri_ops.eraserows = ifb_eraserows_dumb; 512 ri->ri_ops.erasecols = ifb_erasecols_dumb; 513 ri->ri_ops.putchar = ifb_putchar_dumb; 514 ri->ri_do_cursor = ifb_do_cursor_dumb; 515 } 516 517 ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor); 518 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 519 520 if (console) 521 fbwscons_console_init(&sc->sc_sunfb, -1); 522 fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, console); 523 } 524 525 /* 526 * Attempt to identify what kind of ifb we are talking to, so as to setup 527 * proper acceleration information. 528 */ 529 int 530 ifb_accel_identify(struct pci_attach_args *pa) 531 { 532 uint32_t subid; 533 534 subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 535 536 /* 537 * If we have an exact Expert3D match, or the subsystem id 538 * matches Expert3D or Expert3D-Lite, we have an IFB. 539 */ 540 541 if (pa->pa_id == 542 PCI_ID_CODE(PCI_VENDOR_INTERGRAPH, PCI_PRODUCT_INTERGRAPH_EXPERT3D)) 543 return IFB_ACCEL_IFB; 544 if (subid == PCI_ID_CODE(PCI_VENDOR_INTERGRAPH, 0x108) || 545 subid == PCI_ID_CODE(PCI_VENDOR_INTERGRAPH, 0x140)) 546 return IFB_ACCEL_IFB; 547 548 /* 549 * If we have an exact 5110 match, or the subsystem id matches 550 * another set of magic values, we have a JFB. 551 */ 552 553 if (pa->pa_id == 554 PCI_ID_CODE(PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_WILDCAT_5110)) 555 return IFB_ACCEL_JFB; 556 if (subid == PCI_ID_CODE(PCI_VENDOR_3DLABS, 0x1044) || 557 subid == PCI_ID_CODE(PCI_VENDOR_3DLABS, 0x1047)) 558 return IFB_ACCEL_JFB; 559 560 return IFB_ACCEL_NONE; 561 } 562 563 int 564 ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 565 { 566 struct ifb_softc *sc = v; 567 struct wsdisplay_fbinfo *wdf; 568 struct pcisel *sel; 569 int mode; 570 571 switch (cmd) { 572 case WSDISPLAYIO_GTYPE: 573 *(u_int *)data = WSDISPLAY_TYPE_IFB; 574 break; 575 576 case WSDISPLAYIO_SMODE: 577 mode = *(u_int *)data; 578 if (mode == WSDISPLAYIO_MODE_EMUL) 579 ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor); 580 sc->sc_mode = mode; 581 break; 582 case WSDISPLAYIO_GINFO: 583 wdf = (void *)data; 584 wdf->height = sc->sc_sunfb.sf_height; 585 wdf->width = sc->sc_sunfb.sf_width; 586 wdf->depth = sc->sc_sunfb.sf_depth; 587 wdf->cmsize = 256; 588 break; 589 case WSDISPLAYIO_LINEBYTES: 590 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 591 break; 592 593 case WSDISPLAYIO_GETCMAP: 594 return ifb_getcmap(sc, (struct wsdisplay_cmap *)data); 595 case WSDISPLAYIO_PUTCMAP: 596 return ifb_putcmap(sc, (struct wsdisplay_cmap *)data); 597 598 case WSDISPLAYIO_GPCIID: 599 sel = (struct pcisel *)data; 600 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 601 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 602 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 603 break; 604 605 case WSDISPLAYIO_SVIDEO: 606 case WSDISPLAYIO_GVIDEO: 607 break; 608 609 case WSDISPLAYIO_GCURPOS: 610 case WSDISPLAYIO_SCURPOS: 611 case WSDISPLAYIO_GCURMAX: 612 case WSDISPLAYIO_GCURSOR: 613 case WSDISPLAYIO_SCURSOR: 614 default: 615 return -1; /* not supported yet */ 616 } 617 618 return 0; 619 } 620 621 static inline 622 u_int 623 ifb_dac_value(u_int r, u_int g, u_int b) 624 { 625 /* 626 * Convert 8 bit values to 10 bit scale, by shifting and inserting 627 * the former high bits in the low two bits. 628 * Simply shifting is sligthly too dull. 629 */ 630 r = (r << 2) | (r >> 6); 631 g = (g << 2) | (g >> 6); 632 b = (b << 2) | (b >> 6); 633 634 return (b << 20) | (g << 10) | r; 635 } 636 637 int 638 ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm) 639 { 640 u_int index = cm->index; 641 u_int count = cm->count; 642 int error; 643 644 if (index >= 256 || count > 256 - index) 645 return EINVAL; 646 647 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 648 if (error) 649 return error; 650 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 651 if (error) 652 return error; 653 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 654 if (error) 655 return error; 656 return 0; 657 } 658 659 int 660 ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm) 661 { 662 u_int index = cm->index; 663 u_int count = cm->count; 664 u_int i; 665 int error; 666 u_char *r, *g, *b; 667 668 if (index >= 256 || count > 256 - index) 669 return EINVAL; 670 671 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 672 return error; 673 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 674 return error; 675 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 676 return error; 677 678 r = &sc->sc_cmap_red[index]; 679 g = &sc->sc_cmap_green[index]; 680 b = &sc->sc_cmap_blue[index]; 681 682 for (i = 0; i < count; i++) { 683 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 684 IFB_REG_CMAP_INDEX, index); 685 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA, 686 ifb_dac_value(*r, *g, *b)); 687 r++, g++, b++, index++; 688 } 689 return 0; 690 } 691 692 void 693 ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 694 { 695 struct ifb_softc *sc = v; 696 697 sc->sc_cmap_red[index] = r; 698 sc->sc_cmap_green[index] = g; 699 sc->sc_cmap_blue[index] = b; 700 701 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_INDEX, 702 index); 703 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA, 704 ifb_dac_value(r, g, b)); 705 } 706 707 /* similar in spirit to fbwscons_setcolormap() */ 708 void 709 ifb_setcolormap(struct sunfb *sf, 710 void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)) 711 { 712 struct rasops_info *ri = &sf->sf_ro; 713 int i; 714 const u_char *color; 715 716 /* 717 * Compensate for overlay plane limitations. Since we'll operate 718 * in 7bpp mode, our basic colors will use positions 00 to 0f, 719 * and the inverted colors will use positions 7f to 70. 720 */ 721 722 for (i = 0x00; i < 0x10; i++) { 723 color = &rasops_cmap[i * 3]; 724 setcolor(sf, i, color[0], color[1], color[2]); 725 } 726 for (i = 0x70; i < 0x80; i++) { 727 color = &rasops_cmap[(0xf0 | i) * 3]; 728 setcolor(sf, i, color[0], color[1], color[2]); 729 } 730 731 /* 732 * Proper operation apparently needs black to be 01, always. 733 * Replace black, red and white with white, black and red. 734 * Kind of ugly, but it works. 735 */ 736 ri->ri_devcmap[WSCOL_WHITE] = 0x00000000; 737 ri->ri_devcmap[WSCOL_BLACK] = 0x01010101; 738 ri->ri_devcmap[WSCOL_RED] = 0x07070707; 739 740 color = &rasops_cmap[(WSCOL_WHITE + 8) * 3]; /* real white */ 741 setcolor(sf, 0, color[0], color[1], color[2]); 742 setcolor(sf, IFB_PIXELMASK ^ 0, ~color[0], ~color[1], ~color[2]); 743 color = &rasops_cmap[WSCOL_BLACK * 3]; 744 setcolor(sf, 1, color[0], color[1], color[2]); 745 setcolor(sf, IFB_PIXELMASK ^ 1, ~color[0], ~color[1], ~color[2]); 746 color = &rasops_cmap[WSCOL_RED * 3]; 747 setcolor(sf, 7, color[0], color[1], color[2]); 748 setcolor(sf, IFB_PIXELMASK ^ 7, ~color[0], ~color[1], ~color[2]); 749 } 750 751 paddr_t 752 ifb_mmap(void *v, off_t off, int prot) 753 { 754 struct ifb_softc *sc = (struct ifb_softc *)v; 755 756 switch (sc->sc_mode) { 757 case WSDISPLAYIO_MODE_MAPPED: 758 /* 759 * In mapped mode, provide access to the two overlays, 760 * followed by the control registers, at the following 761 * addresses: 762 * 00000000 overlay 0, size up to 2MB (visible fb size) 763 * 01000000 overlay 1, size up to 2MB (visible fb size) 764 * 02000000 control registers 765 */ 766 off -= 0x00000000; 767 if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) { 768 return bus_space_mmap(sc->sc_mem_t, 769 sc->sc_fb8bank0_base, 770 off, prot, BUS_SPACE_MAP_LINEAR); 771 } 772 off -= 0x01000000; 773 if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) { 774 return bus_space_mmap(sc->sc_mem_t, 775 sc->sc_fb8bank1_base, 776 off, prot, BUS_SPACE_MAP_LINEAR); 777 } 778 #ifdef APERTURE 779 off -= 0x01000000; 780 if (allowaperture != 0 && sc->sc_acceltype != IFB_ACCEL_NONE) { 781 if (off >= 0 && off < round_page(sc->sc_reglen)) { 782 return bus_space_mmap(sc->sc_mem_t, 783 sc->sc_regbase, 784 off, prot, BUS_SPACE_MAP_LINEAR); 785 } 786 } 787 #endif 788 break; 789 } 790 791 return -1; 792 } 793 794 void 795 ifb_burner(void *v, u_int on, u_int flags) 796 { 797 struct ifb_softc *sc = (struct ifb_softc *)v; 798 int s; 799 uint32_t dpms; 800 801 s = splhigh(); 802 if (on) 803 dpms = IFB_REG_DPMS_ON; 804 else { 805 #ifdef notyet 806 if (flags & WSDISPLAY_BURN_VBLANK) 807 dpms = IFB_REG_DPMS_SUSPEND; 808 else 809 #endif 810 dpms = IFB_REG_DPMS_STANDBY; 811 } 812 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_DPMS_STATE, dpms); 813 splx(s); 814 } 815 816 static inline int 817 ifb_is_console(int node) 818 { 819 extern int fbnode; 820 821 return fbnode == node; 822 } 823 824 int 825 ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa) 826 { 827 u_int32_t cf; 828 int bar, rc; 829 830 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, IFB_PCI_CFG); 831 bar = PCI_MAPREG_START + IFB_PCI_CFG_BAR_OFFSET(cf); 832 833 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); 834 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) 835 rc = EINVAL; 836 else { 837 rc = pci_mapreg_map(pa, bar, cf, 838 BUS_SPACE_MAP_LINEAR, NULL, &sc->sc_mem_h, 839 &sc->sc_membase, &sc->sc_memlen, 0); 840 } 841 if (rc != 0) { 842 printf("\n%s: can't map video memory\n", 843 sc->sc_sunfb.sf_dev.dv_xname); 844 return rc; 845 } 846 847 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar + 4); 848 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) 849 rc = EINVAL; 850 else { 851 rc = pci_mapreg_map(pa, bar + 4, cf, 852 0, NULL, &sc->sc_reg_h, 853 &sc->sc_regbase, &sc->sc_reglen, 0x9000); 854 } 855 if (rc != 0) { 856 printf("\n%s: can't map register space\n", 857 sc->sc_sunfb.sf_dev.dv_xname); 858 return rc; 859 } 860 861 return 0; 862 } 863 864 /* 865 * Non accelerated routines. 866 */ 867 868 void 869 ifb_putchar_dumb(void *cookie, int row, int col, u_int uc, long attr) 870 { 871 struct rasops_info *ri = cookie; 872 struct ifb_softc *sc = ri->ri_hw; 873 874 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 875 sc->sc_old_ops.putchar(cookie, row, col, uc, attr); 876 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 877 sc->sc_old_ops.putchar(cookie, row, col, uc, attr); 878 } 879 880 void 881 ifb_copycols_dumb(void *cookie, int row, int src, int dst, int num) 882 { 883 struct rasops_info *ri = cookie; 884 struct ifb_softc *sc = ri->ri_hw; 885 886 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 887 sc->sc_old_ops.copycols(cookie, row, src, dst, num); 888 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 889 sc->sc_old_ops.copycols(cookie, row, src, dst, num); 890 } 891 892 void 893 ifb_erasecols_dumb(void *cookie, int row, int col, int num, long attr) 894 { 895 struct rasops_info *ri = cookie; 896 struct ifb_softc *sc = ri->ri_hw; 897 898 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 899 sc->sc_old_ops.erasecols(cookie, row, col, num, attr); 900 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 901 sc->sc_old_ops.erasecols(cookie, row, col, num, attr); 902 } 903 904 void 905 ifb_copyrows_dumb(void *cookie, int src, int dst, int num) 906 { 907 struct rasops_info *ri = cookie; 908 struct ifb_softc *sc = ri->ri_hw; 909 910 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 911 sc->sc_old_ops.copyrows(cookie, src, dst, num); 912 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 913 sc->sc_old_ops.copyrows(cookie, src, dst, num); 914 } 915 916 void 917 ifb_eraserows_dumb(void *cookie, int row, int num, long attr) 918 { 919 struct rasops_info *ri = cookie; 920 struct ifb_softc *sc = ri->ri_hw; 921 922 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 923 sc->sc_old_ops.eraserows(cookie, row, num, attr); 924 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 925 sc->sc_old_ops.eraserows(cookie, row, num, attr); 926 } 927 928 /* Similar to rasops_do_cursor(), but using a 7bit pixel mask. */ 929 930 #define CURSOR_MASK 0x7f7f7f7f 931 932 void 933 ifb_do_cursor_dumb(struct rasops_info *ri) 934 { 935 struct ifb_softc *sc = ri->ri_hw; 936 int full1, height, cnt, slop1, slop2, row, col; 937 int ovl_offset = sc->sc_fb8bank1_vaddr - sc->sc_fb8bank0_vaddr; 938 u_char *dp0, *dp1, *rp; 939 940 row = ri->ri_crow; 941 col = ri->ri_ccol; 942 943 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 944 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 945 height = ri->ri_font->fontheight; 946 slop1 = (4 - ((long)rp & 3)) & 3; 947 948 if (slop1 > ri->ri_xscale) 949 slop1 = ri->ri_xscale; 950 951 slop2 = (ri->ri_xscale - slop1) & 3; 952 full1 = (ri->ri_xscale - slop1 - slop2) >> 2; 953 954 if ((slop1 | slop2) == 0) { 955 /* A common case */ 956 while (height--) { 957 dp0 = rp; 958 dp1 = dp0 + ovl_offset; 959 rp += ri->ri_stride; 960 961 for (cnt = full1; cnt; cnt--) { 962 *(int32_t *)dp0 ^= CURSOR_MASK; 963 *(int32_t *)dp1 ^= CURSOR_MASK; 964 dp0 += 4; 965 dp1 += 4; 966 } 967 } 968 } else { 969 /* XXX this is stupid.. use masks instead */ 970 while (height--) { 971 dp0 = rp; 972 dp1 = dp0 + ovl_offset; 973 rp += ri->ri_stride; 974 975 if (slop1 & 1) { 976 *dp0++ ^= (u_char)CURSOR_MASK; 977 *dp1++ ^= (u_char)CURSOR_MASK; 978 } 979 980 if (slop1 & 2) { 981 *(int16_t *)dp0 ^= (int16_t)CURSOR_MASK; 982 *(int16_t *)dp1 ^= (int16_t)CURSOR_MASK; 983 dp0 += 2; 984 dp1 += 2; 985 } 986 987 for (cnt = full1; cnt; cnt--) { 988 *(int32_t *)dp0 ^= CURSOR_MASK; 989 *(int32_t *)dp1 ^= CURSOR_MASK; 990 dp0 += 4; 991 dp1 += 4; 992 } 993 994 if (slop2 & 1) { 995 *dp0++ ^= (u_char)CURSOR_MASK; 996 *dp1++ ^= (u_char)CURSOR_MASK; 997 } 998 999 if (slop2 & 2) { 1000 *(int16_t *)dp0 ^= (int16_t)CURSOR_MASK; 1001 *(int16_t *)dp1 ^= (int16_t)CURSOR_MASK; 1002 } 1003 } 1004 } 1005 } 1006 1007 /* 1008 * Accelerated routines. 1009 */ 1010 1011 void 1012 ifb_copycols(void *cookie, int row, int src, int dst, int num) 1013 { 1014 struct rasops_info *ri = cookie; 1015 struct ifb_softc *sc = ri->ri_hw; 1016 1017 num *= ri->ri_font->fontwidth; 1018 src *= ri->ri_font->fontwidth; 1019 dst *= ri->ri_font->fontwidth; 1020 row *= ri->ri_font->fontheight; 1021 1022 ifb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 1023 ri->ri_xorigin + dst, ri->ri_yorigin + row, 1024 num, ri->ri_font->fontheight); 1025 } 1026 1027 void 1028 ifb_erasecols(void *cookie, int row, int col, int num, long attr) 1029 { 1030 struct rasops_info *ri = cookie; 1031 struct ifb_softc *sc = ri->ri_hw; 1032 int bg, fg; 1033 1034 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 1035 1036 row *= ri->ri_font->fontheight; 1037 col *= ri->ri_font->fontwidth; 1038 num *= ri->ri_font->fontwidth; 1039 1040 ifb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 1041 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 1042 } 1043 1044 void 1045 ifb_copyrows(void *cookie, int src, int dst, int num) 1046 { 1047 struct rasops_info *ri = cookie; 1048 struct ifb_softc *sc = ri->ri_hw; 1049 1050 num *= ri->ri_font->fontheight; 1051 src *= ri->ri_font->fontheight; 1052 dst *= ri->ri_font->fontheight; 1053 1054 ifb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 1055 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 1056 } 1057 1058 void 1059 ifb_eraserows(void *cookie, int row, int num, long attr) 1060 { 1061 struct rasops_info *ri = cookie; 1062 struct ifb_softc *sc = ri->ri_hw; 1063 int bg, fg; 1064 int x, y, w; 1065 1066 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 1067 1068 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 1069 num = ri->ri_height; 1070 x = y = 0; 1071 w = ri->ri_width; 1072 } else { 1073 num *= ri->ri_font->fontheight; 1074 x = ri->ri_xorigin; 1075 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 1076 w = ri->ri_emuwidth; 1077 } 1078 ifb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 1079 } 1080 1081 void 1082 ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) 1083 { 1084 ifb_rop(sc, sx, sy, dx, dy, w, h, IFB_ROP_SRC, IFB_PIXELMASK); 1085 ifb_rop_wait(sc); 1086 } 1087 1088 void 1089 ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg) 1090 { 1091 int32_t mask; 1092 1093 /* pixels to set... */ 1094 mask = IFB_PIXELMASK & bg; 1095 if (mask != 0) { 1096 ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_SET, mask); 1097 ifb_rop_wait(sc); 1098 } 1099 1100 /* pixels to clear... */ 1101 mask = IFB_PIXELMASK & ~bg; 1102 if (mask != 0) { 1103 ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_CLEAR, mask); 1104 ifb_rop_wait(sc); 1105 } 1106 } 1107 1108 /* 1109 * Perform a raster operation on both overlay planes. 1110 * Puzzled by all the magic numbers in there? So are we. Isn't a dire 1111 * lack of documentation wonderful? 1112 */ 1113 1114 static inline void 1115 ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h, 1116 uint32_t rop, int32_t planemask) 1117 { 1118 (*sc->sc_rop)(sc, sx, sy, dx, dy, w, h, rop, planemask); 1119 } 1120 1121 void 1122 ifb_rop_common(struct ifb_softc *sc, bus_addr_t reg, int sx, int sy, 1123 int dx, int dy, int w, int h, uint32_t rop, int32_t planemask) 1124 { 1125 int dir = 0; 1126 1127 /* 1128 * Compute rop direction. This only really matters for 1129 * screen-to-screen copies. 1130 */ 1131 if (sy < dy /* && sy + h > dy */) { 1132 sy += h - 1; 1133 dy += h; 1134 dir |= IFB_BLT_DIR_BACKWARDS_Y; 1135 } 1136 if (sx < dx /* && sx + w > dx */) { 1137 sx += w - 1; 1138 dx += w; 1139 dir |= IFB_BLT_DIR_BACKWARDS_X; 1140 } 1141 1142 /* Which one of those below is your magic number for today? */ 1143 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x61000001); 1144 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0); 1145 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x6301c080); 1146 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x80000000); 1147 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, rop); 1148 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, planemask); 1149 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0); 1150 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x64000303); 1151 /* 1152 * This value is a pixel offset within the destination area. It is 1153 * probably used to define complex polygon shapes, with the 1154 * last pixel in the list being back to (0,0). 1155 */ 1156 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(0, 0)); 1157 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0); 1158 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00030000); 1159 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x2200010d); 1160 1161 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x33f01000 | dir); 1162 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(dx, dy)); 1163 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(w, h)); 1164 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(sx, sy)); 1165 } 1166 1167 void 1168 ifb_rop_ifb(void *v, int sx, int sy, int dx, int dy, int w, int h, 1169 uint32_t rop, int32_t planemask) 1170 { 1171 struct ifb_softc *sc = (struct ifb_softc *)v; 1172 bus_addr_t reg = IFB_REG_ENGINE; 1173 1174 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 2); 1175 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 1); 1176 /* the ``0101'' part is probably a component selection */ 1177 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x540101ff); 1178 1179 ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask); 1180 } 1181 1182 void 1183 ifb_rop_jfb(void *v, int sx, int sy, int dx, int dy, int w, int h, 1184 uint32_t rop, int32_t planemask) 1185 { 1186 struct ifb_softc *sc = (struct ifb_softc *)v; 1187 bus_addr_t reg = JFB_REG_ENGINE; 1188 uint32_t spr, splr; 1189 1190 /* 1191 * Pick the current spr and splr values from the communication 1192 * area if possible. 1193 */ 1194 if (sc->sc_comm != NULL) { 1195 spr = sc->sc_comm[IFB_SHARED_TERM8_SPR >> 2]; 1196 splr = sc->sc_comm[IFB_SHARED_TERM8_SPLR >> 2]; 1197 } else { 1198 /* supposedly sane defaults */ 1199 spr = 0x54ff0303; 1200 splr = 0x5c0000ff; 1201 } 1202 1203 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00400016); 1204 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000002); 1205 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000000); 1206 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, spr); 1207 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, splr); 1208 1209 ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask); 1210 1211 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000001); 1212 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000001); 1213 } 1214 1215 int 1216 ifb_rop_wait(struct ifb_softc *sc) 1217 { 1218 int i; 1219 1220 for (i = 1000000; i != 0; i--) { 1221 if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 1222 IFB_REG_STATUS) & IFB_REG_STATUS_DONE) 1223 break; 1224 DELAY(1); 1225 } 1226 1227 return i; 1228 } 1229 1230 void 1231 ifb_do_cursor(struct rasops_info *ri) 1232 { 1233 struct ifb_softc *sc = ri->ri_hw; 1234 int y, x; 1235 1236 y = ri->ri_yorigin + ri->ri_crow * ri->ri_font->fontheight; 1237 x = ri->ri_xorigin + ri->ri_ccol * ri->ri_font->fontwidth; 1238 1239 ifb_rop(sc, x, y, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight, 1240 IFB_ROP_XOR, IFB_PIXELMASK); 1241 ifb_rop_wait(sc); 1242 } 1243