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