1 /* $OpenBSD: ifb.c,v 1.3 2008/12/27 14:33:55 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2008 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 /* 61 * Parts of the following hardware knowledge come from David S. Miller's 62 * XVR-500 Linux driver (drivers/video/sunxvr500.c). 63 */ 64 65 /* 66 * The Expert3D and Expert3d-Lite cards are built around the Wildcat 67 * 5110, 6210 and 7210 chips. 68 * 69 * The card exposes the following resources: 70 * - a 32MB aperture window in which views to the different frame buffer 71 * areas can be mapped, in the first BAR. 72 * - a 64KB PROM and registers area, in the second BAR, with the registers 73 * starting 32KB within this area. 74 * - a 8MB memory mapping, which purpose is unknown, in the third BAR. 75 * 76 * In the state the PROM leaves us in, the 8MB frame buffer windows map 77 * the video memory as interleaved stripes: 78 * - frame buffer #0 will map horizontal pixels 00-1f, 60-9f, e0-11f, etc. 79 * - frame buffer #1 will map horizontal pixels 20-5f, a0-df, 120-15f, etc. 80 * However the non-visible parts of each stripe can still be addressed 81 * (probably for fast screen switching). 82 * 83 * Unfortunately, since we do not know how to reconfigured the stripes 84 * to provide at least a linear frame buffer, we have to write to both 85 * windows and have them provide the complete image. This however leads 86 * to parasite overlays appearing sometimes in the screen... 87 */ 88 89 /* 90 * The Expert3D has an extra BAR that is not present on the -Lite 91 * version. This register contains bits that tell us how many BARs to 92 * skip before we get to the BARs that interest us. 93 */ 94 #define IFB_PCI_CFG 0x5c 95 #define IFB_PCI_CFG_BAR_OFFSET(x) ((x & 0x000000e0) >> 3) 96 97 #define IFB_REG_OFFSET 0x8000 98 99 /* 100 * 0040 component configuration 101 * This register controls which parts of the board will be addressed by 102 * writes to other configuration registers. 103 * Apparently the low two bytes control the frame buffer windows for the 104 * given head (starting at 1). 105 * The high two bytes are texture related. 106 */ 107 #define IFB_REG_COMPONENT_SELECT 0x0040 108 109 /* 110 * 0058 magnifying configuration 111 * This register apparently controls magnifying. 112 * bits 5-6 select the window width divider (00: by 2, 01: by 4, 10: by 8, 113 * 11: by 16) 114 * bits 7-8 select the zoom factor (00: disabled, 01: x2, 10: x4, 11: x8) 115 */ 116 #define IFB_REG_MAGNIFY 0x0058 117 #define IFB_REG_MAGNIFY_DISABLE 0x00000000 118 #define IFB_REG_MAGNIFY_X2 0x00000040 119 #define IFB_REG_MAGNIFY_X4 0x00000080 120 #define IFB_REG_MAGNIFY_X8 0x000000c0 121 #define IFB_REG_MAGNIFY_WINDIV2 0x00000000 122 #define IFB_REG_MAGNIFY_WINDIV4 0x00000010 123 #define IFB_REG_MAGNIFY_WINDIV8 0x00000020 124 #define IFB_REG_MAGNIFY_WINDIV16 0x00000030 125 126 /* 127 * 0070 display resolution 128 * Contains the size of the display, as ((height - 1) << 16) | (width - 1) 129 */ 130 #define IFB_REG_RESOLUTION 0x0070 131 /* 132 * 0074 configuration register 133 * Contains 0x1a000088 | ((Log2 stride) << 16) 134 */ 135 #define IFB_REG_CONFIG 0x0074 136 /* 137 * 0078 32bit frame buffer window #0 (8 to 9 MB) 138 * Contains the offset (relative to BAR0) of the 32 bit frame buffer window. 139 */ 140 #define IFB_REG_FB32_0 0x0078 141 /* 142 * 007c 32bit frame buffer window #1 (8 to 9 MB) 143 * Contains the offset (relative to BAR0) of the 32 bit frame buffer window. 144 */ 145 #define IFB_REG_FB32_1 0x007c 146 /* 147 * 0080 8bit frame buffer window #0 (2 to 2.2 MB) 148 * Contains the offset (relative to BAR0) of the 8 bit frame buffer window. 149 */ 150 #define IFB_REG_FB8_0 0x0080 151 /* 152 * 0084 8bit frame buffer window #1 (2 to 2.2 MB) 153 * Contains the offset (relative to BAR0) of the 8 bit frame buffer window. 154 */ 155 #define IFB_REG_FB8_1 0x0084 156 /* 157 * 0088 unknown window (as large as a 32 bit frame buffer) 158 */ 159 #define IFB_REG_FB_UNK0 0x0088 160 /* 161 * 008c unknown window (as large as a 8 bit frame buffer) 162 */ 163 #define IFB_REG_FB_UNK1 0x008c 164 /* 165 * 0090 unknown window (as large as a 8 bit frame buffer) 166 */ 167 #define IFB_REG_FB_UNK2 0x0090 168 169 /* 170 * 00bc RAMDAC palette index register 171 */ 172 #define IFB_REG_CMAP_INDEX 0x00bc 173 /* 174 * 00c0 RAMDAC palette data register 175 */ 176 #define IFB_REG_CMAP_DATA 0x00c0 177 178 /* 179 * 00e4 DPMS state register 180 * States ``off'' and ``suspend'' need chip reprogramming before video can 181 * be enabled again. 182 */ 183 #define IFB_REG_DPMS_STATE 0x00e4 184 #define IFB_REG_DPMS_OFF 0x00000000 185 #define IFB_REG_DPMS_SUSPEND 0x00000001 186 #define IFB_REG_DPMS_STANDBY 0x00000002 187 #define IFB_REG_DPMS_ON 0x00000003 188 189 struct ifb_softc { 190 struct sunfb sc_sunfb; 191 int sc_nscreens; 192 193 bus_space_tag_t sc_mem_t; 194 pcitag_t sc_pcitag; 195 196 bus_space_handle_t sc_mem_h; 197 bus_addr_t sc_membase; 198 bus_size_t sc_memlen; 199 vaddr_t sc_memvaddr, sc_fb8bank0_vaddr, sc_fb8bank1_vaddr; 200 bus_space_handle_t sc_reg_h; 201 202 struct wsdisplay_emulops sc_old_ops; 203 void (*sc_old_cursor)(struct rasops_info *); 204 205 int sc_console; 206 u_int8_t sc_cmap_red[256]; 207 u_int8_t sc_cmap_green[256]; 208 u_int8_t sc_cmap_blue[256]; 209 }; 210 211 int ifb_ioctl(void *, u_long, caddr_t, int, struct proc *); 212 paddr_t ifb_mmap(void *, off_t, int); 213 int ifb_alloc_screen(void *, const struct wsscreen_descr *, void **, 214 int *, int *, long *); 215 void ifb_free_screen(void *, void *); 216 int ifb_show_screen(void *, void *, int, 217 void (*cb)(void *, int, int), void *); 218 void ifb_burner(void *, u_int, u_int); 219 220 struct wsdisplay_accessops ifb_accessops = { 221 ifb_ioctl, 222 ifb_mmap, 223 ifb_alloc_screen, 224 ifb_free_screen, 225 ifb_show_screen, 226 NULL, 227 NULL, 228 NULL, 229 ifb_burner 230 }; 231 232 int ifbmatch(struct device *, void *, void *); 233 void ifbattach(struct device *, struct device *, void *); 234 235 struct cfattach ifb_ca = { 236 sizeof (struct ifb_softc), ifbmatch, ifbattach 237 }; 238 239 struct cfdriver ifb_cd = { 240 NULL, "ifb", DV_DULL 241 }; 242 243 int ifb_mapregs(struct ifb_softc *, struct pci_attach_args *); 244 int ifb_is_console(int); 245 int ifb_getcmap(struct ifb_softc *, struct wsdisplay_cmap *); 246 int ifb_putcmap(struct ifb_softc *, struct wsdisplay_cmap *); 247 void ifb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 248 249 void ifb_putchar(void *, int, int, u_int, long); 250 void ifb_copycols(void *, int, int, int, int); 251 void ifb_erasecols(void *, int, int, int, long); 252 void ifb_copyrows(void *, int, int, int); 253 void ifb_eraserows(void *, int, int, long); 254 void ifb_do_cursor(struct rasops_info *); 255 256 const struct pci_matchid ifb_devices[] = { 257 { PCI_VENDOR_INTERGRAPH, PCI_PRODUCT_INTERGRAPH_EXPERT3D }, 258 { PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_WILDCAT_6210 }, 259 { PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_WILDCAT_5110 },/* Sun XVR-500 */ 260 { PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_WILDCAT_7210 }, 261 }; 262 263 int 264 ifbmatch(struct device *parent, void *cf, void *aux) 265 { 266 struct pci_attach_args *paa = aux; 267 int node; 268 char *name; 269 270 if (pci_matchbyid(paa, ifb_devices, 271 sizeof(ifb_devices) / sizeof(ifb_devices[0])) != 0) 272 return 1; 273 274 node = PCITAG_NODE(paa->pa_tag); 275 name = getpropstring(node, "name"); 276 if (strcmp(name, "SUNW,Expert3D") == 0 || 277 strcmp(name, "SUNW,Expert3D-Lite") == 0) 278 return 1; 279 280 return 0; 281 } 282 283 void 284 ifbattach(struct device *parent, struct device *self, void *aux) 285 { 286 struct ifb_softc *sc = (struct ifb_softc *)self; 287 struct pci_attach_args *paa = aux; 288 struct rasops_info *ri; 289 int node; 290 291 sc->sc_mem_t = paa->pa_memt; 292 sc->sc_pcitag = paa->pa_tag; 293 294 printf("\n"); 295 296 if (ifb_mapregs(sc, paa)) 297 return; 298 299 sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h); 300 sc->sc_fb8bank0_vaddr = sc->sc_memvaddr + 301 bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 302 IFB_REG_OFFSET + IFB_REG_FB8_0) - sc->sc_membase; 303 sc->sc_fb8bank1_vaddr = sc->sc_memvaddr + 304 bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, 305 IFB_REG_OFFSET + IFB_REG_FB8_1) - sc->sc_membase; 306 307 node = PCITAG_NODE(paa->pa_tag); 308 sc->sc_console = ifb_is_console(node); 309 310 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 311 312 printf("%s: %dx%d\n", 313 self->dv_xname, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 314 315 #if 0 316 /* 317 * Make sure the frame buffer is configured to sane values. 318 * So much more is needed there... documentation permitting. 319 */ 320 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 321 IFB_REG_OFFSET + IFB_REG_COMPONENT_SELECT, 0x00000101); 322 delay(1000); 323 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 324 IFB_REG_OFFSET + IFB_REG_MAGNIFY, IFB_REG_MAGNIFY_DISABLE); 325 #endif 326 327 ri = &sc->sc_sunfb.sf_ro; 328 ri->ri_bits = NULL; 329 ri->ri_hw = sc; 330 331 /* do NOT pass RI_CLEAR yet */ 332 fbwscons_init(&sc->sc_sunfb, RI_BSWAP); 333 ri->ri_flg &= ~RI_FULLCLEAR; /* due to the way we handle updates */ 334 335 if (!sc->sc_console) { 336 bzero((void *)sc->sc_fb8bank0_vaddr, sc->sc_sunfb.sf_fbsize); 337 bzero((void *)sc->sc_fb8bank1_vaddr, sc->sc_sunfb.sf_fbsize); 338 } 339 340 /* pick centering delta */ 341 sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits; 342 sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits; 343 344 sc->sc_old_ops = ri->ri_ops; /* structure copy */ 345 sc->sc_old_cursor = ri->ri_do_cursor; 346 ri->ri_ops.copyrows = ifb_copyrows; 347 ri->ri_ops.copycols = ifb_copycols; 348 ri->ri_ops.eraserows = ifb_eraserows; 349 ri->ri_ops.erasecols = ifb_erasecols; 350 ri->ri_ops.putchar = ifb_putchar; 351 ri->ri_do_cursor = ifb_do_cursor; 352 353 fbwscons_setcolormap(&sc->sc_sunfb, ifb_setcolor); 354 if (sc->sc_console) 355 fbwscons_console_init(&sc->sc_sunfb, -1); 356 fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, sc->sc_console); 357 } 358 359 int 360 ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 361 { 362 struct ifb_softc *sc = v; 363 struct wsdisplay_fbinfo *wdf; 364 struct pcisel *sel; 365 366 switch (cmd) { 367 case WSDISPLAYIO_GTYPE: 368 *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; 369 break; 370 371 case WSDISPLAYIO_SMODE: 372 if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL) 373 fbwscons_setcolormap(&sc->sc_sunfb, ifb_setcolor); 374 break; 375 case WSDISPLAYIO_GINFO: 376 wdf = (void *)data; 377 wdf->height = sc->sc_sunfb.sf_height; 378 wdf->width = sc->sc_sunfb.sf_width; 379 wdf->depth = sc->sc_sunfb.sf_depth; 380 wdf->cmsize = 256; 381 break; 382 case WSDISPLAYIO_LINEBYTES: 383 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 384 break; 385 386 case WSDISPLAYIO_GETCMAP: 387 return ifb_getcmap(sc, (struct wsdisplay_cmap *)data); 388 case WSDISPLAYIO_PUTCMAP: 389 return ifb_putcmap(sc, (struct wsdisplay_cmap *)data); 390 391 case WSDISPLAYIO_GPCIID: 392 sel = (struct pcisel *)data; 393 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 394 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 395 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 396 break; 397 398 case WSDISPLAYIO_SVIDEO: 399 case WSDISPLAYIO_GVIDEO: 400 break; 401 402 case WSDISPLAYIO_GCURPOS: 403 case WSDISPLAYIO_SCURPOS: 404 case WSDISPLAYIO_GCURMAX: 405 case WSDISPLAYIO_GCURSOR: 406 case WSDISPLAYIO_SCURSOR: 407 default: 408 return -1; /* not supported yet */ 409 } 410 411 return 0; 412 } 413 414 int 415 ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm) 416 { 417 u_int index = cm->index; 418 u_int count = cm->count; 419 int error; 420 421 if (index >= 256 || count > 256 - index) 422 return EINVAL; 423 424 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 425 if (error) 426 return error; 427 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 428 if (error) 429 return error; 430 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 431 if (error) 432 return error; 433 return 0; 434 } 435 436 int 437 ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm) 438 { 439 u_int index = cm->index; 440 u_int count = cm->count; 441 u_int i; 442 int error; 443 u_char *r, *g, *b; 444 445 if (index >= 256 || count > 256 - index) 446 return EINVAL; 447 448 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 449 return error; 450 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 451 return error; 452 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 453 return error; 454 455 r = &sc->sc_cmap_red[index]; 456 g = &sc->sc_cmap_green[index]; 457 b = &sc->sc_cmap_blue[index]; 458 459 for (i = 0; i < count; i++) { 460 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 461 IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index); 462 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 463 IFB_REG_OFFSET + IFB_REG_CMAP_DATA, 464 (((u_int)*b) << 22) | (((u_int)*g) << 12) | (((u_int)*r) << 2)); 465 r++, g++, b++, index++; 466 } 467 return 0; 468 } 469 470 void 471 ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 472 { 473 struct ifb_softc *sc = v; 474 475 sc->sc_cmap_red[index] = r; 476 sc->sc_cmap_green[index] = g; 477 sc->sc_cmap_blue[index] = b; 478 479 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 480 IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index); 481 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 482 IFB_REG_OFFSET + IFB_REG_CMAP_DATA, 483 (((u_int)b) << 22) | (((u_int)g) << 12) | (((u_int)r) << 2)); 484 } 485 486 int 487 ifb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 488 int *curxp, int *curyp, long *attrp) 489 { 490 struct ifb_softc *sc = v; 491 492 if (sc->sc_nscreens > 0) 493 return ENOMEM; 494 495 *cookiep = &sc->sc_sunfb.sf_ro; 496 *curyp = 0; 497 *curxp = 0; 498 sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, 499 WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); 500 sc->sc_nscreens++; 501 return 0; 502 } 503 504 void 505 ifb_free_screen(void *v, void *cookie) 506 { 507 struct ifb_softc *sc = v; 508 509 sc->sc_nscreens--; 510 } 511 512 int 513 ifb_show_screen(void *v, void *cookie, int waitok, 514 void (*cb)(void *, int, int), void *cbarg) 515 { 516 return 0; 517 } 518 519 paddr_t 520 ifb_mmap(void *v, off_t off, int prot) 521 { 522 return -1; 523 } 524 525 void 526 ifb_burner(void *v, u_int on, u_int flags) 527 { 528 struct ifb_softc *sc = (struct ifb_softc *)v; 529 int s; 530 uint32_t dpms; 531 532 s = splhigh(); 533 if (on) 534 dpms = IFB_REG_DPMS_ON; 535 else { 536 #ifdef notyet 537 if (flags & WSDISPLAY_BURN_VBLANK) 538 dpms = IFB_REG_DPMS_SUSPEND; 539 else 540 #endif 541 dpms = IFB_REG_DPMS_STANDBY; 542 } 543 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, 544 IFB_REG_OFFSET + IFB_REG_DPMS_STATE, dpms); 545 splx(s); 546 } 547 548 int 549 ifb_is_console(int node) 550 { 551 extern int fbnode; 552 553 return fbnode == node; 554 } 555 556 int 557 ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa) 558 { 559 u_int32_t cf; 560 int bar, rc; 561 562 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, IFB_PCI_CFG); 563 bar = PCI_MAPREG_START + IFB_PCI_CFG_BAR_OFFSET(cf); 564 565 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); 566 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) 567 rc = EINVAL; 568 else { 569 rc = pci_mapreg_map(pa, bar, cf, 570 BUS_SPACE_MAP_LINEAR, NULL, &sc->sc_mem_h, 571 &sc->sc_membase, &sc->sc_memlen, 0); 572 } 573 if (rc != 0) { 574 printf("%s: can't map video memory\n", 575 sc->sc_sunfb.sf_dev.dv_xname); 576 return rc; 577 } 578 579 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar + 4); 580 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) 581 rc = EINVAL; 582 else { 583 rc = pci_mapreg_map(pa, bar + 4, cf, 584 0, NULL, &sc->sc_reg_h, NULL, NULL, 0x9000); 585 } 586 if (rc != 0) { 587 printf("%s: can't map register space\n", 588 sc->sc_sunfb.sf_dev.dv_xname); 589 return rc; 590 } 591 592 return 0; 593 } 594 595 void 596 ifb_putchar(void *cookie, int row, int col, u_int uc, long attr) 597 { 598 struct rasops_info *ri = cookie; 599 struct ifb_softc *sc = ri->ri_hw; 600 601 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 602 sc->sc_old_ops.putchar(cookie, row, col, uc, attr); 603 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 604 sc->sc_old_ops.putchar(cookie, row, col, uc, attr); 605 } 606 607 void 608 ifb_copycols(void *cookie, int row, int src, int dst, int num) 609 { 610 struct rasops_info *ri = cookie; 611 struct ifb_softc *sc = ri->ri_hw; 612 613 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 614 sc->sc_old_ops.copycols(cookie, row, src, dst, num); 615 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 616 sc->sc_old_ops.copycols(cookie, row, src, dst, num); 617 } 618 619 void 620 ifb_erasecols(void *cookie, int row, int col, int num, long attr) 621 { 622 struct rasops_info *ri = cookie; 623 struct ifb_softc *sc = ri->ri_hw; 624 625 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 626 sc->sc_old_ops.erasecols(cookie, row, col, num, attr); 627 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 628 sc->sc_old_ops.erasecols(cookie, row, col, num, attr); 629 } 630 631 void 632 ifb_copyrows(void *cookie, int src, int dst, int num) 633 { 634 struct rasops_info *ri = cookie; 635 struct ifb_softc *sc = ri->ri_hw; 636 637 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 638 sc->sc_old_ops.copyrows(cookie, src, dst, num); 639 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 640 sc->sc_old_ops.copyrows(cookie, src, dst, num); 641 } 642 643 void 644 ifb_eraserows(void *cookie, int row, int num, long attr) 645 { 646 struct rasops_info *ri = cookie; 647 struct ifb_softc *sc = ri->ri_hw; 648 649 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 650 sc->sc_old_ops.eraserows(cookie, row, num, attr); 651 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 652 sc->sc_old_ops.eraserows(cookie, row, num, attr); 653 } 654 655 void 656 ifb_do_cursor(struct rasops_info *ri) 657 { 658 struct ifb_softc *sc = ri->ri_hw; 659 660 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; 661 sc->sc_old_cursor(ri); 662 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; 663 sc->sc_old_cursor(ri); 664 } 665