1 /* $OpenBSD: gfxp.c,v 1.15 2021/10/24 17:05:03 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Mark Kettenis. 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 #include <sys/param.h> 20 #include <sys/device.h> 21 #include <sys/pciio.h> 22 #include <sys/systm.h> 23 24 #include <machine/autoconf.h> 25 #include <machine/bus.h> 26 #include <machine/openfirm.h> 27 28 #include <dev/pci/pcireg.h> 29 #include <dev/pci/pcivar.h> 30 #include <dev/pci/pcidevs.h> 31 32 #include <dev/wscons/wsconsio.h> 33 #include <dev/wscons/wsdisplayvar.h> 34 35 #include <dev/rasops/rasops.h> 36 37 #include <machine/fbvar.h> 38 39 /* 40 * The Permedia 2 provides two views into its 64k register file. The 41 * first view is little-endian, the second is big-endian and 42 * immediately follows the little-endian view. Since bus_space(9) 43 * already does the byte order conversion for us, we use the 44 * little-endian view. 45 * 46 * There are also little-endian and big-endian views into the 47 * framebuffer. These are made available through separate BARs. We 48 * use the big-endian view in this driver to avoid unnecessary byte 49 * swapping in rasops(9). 50 */ 51 #define PM2_PCI_MMIO 0x10 /* Registers */ 52 #define PM2_PCI_MEM_LE 0x14 /* Framebuffer (little-endian) */ 53 #define PM2_PCI_MEM_BE 0x18 /* Framebuffer (big-endian) */ 54 55 #define PM2_IN_FIFO_SPACE 0x0018 56 #define PM2_OUT_FIFO_SPACE 0x0020 57 #define PM2_DMA_COUNT 0x0030 58 59 #define PM2_OUT_FIFO 0x2000 60 #define PM2_SYNC_TAG 0x00000188 61 62 #define PM2_PALETTE_WRITE_ADDR 0x4000 63 #define PM2_PALETTE_DATA 0x4008 64 65 #define PM2V_INDEX_LOW 0x4020 66 #define PM2V_INDEX_HIGH 0x4028 67 #define PM2V_INDEX_DATA 0x4030 68 #define PM2V_CURSOR_MODE 0x0005 69 #define PM2V_CURSOR_PATTERN 0x0400 70 71 #define PM2_RENDER 0x8038 72 #define PM2_RENDER_FASTFILL 0x00000008 73 #define PM2_RENDER_RECT 0x000000c0 74 #define PM2_INCREASE_X 0x00200000 75 #define PM2_INCREASE_Y 0x00400000 76 #define PM2_RECT_ORIG 0x80d0 77 #define PM2_RECT_SIZE 0x80d8 78 79 #define PM2_FB_READ_MODE 0x8a80 80 #define PM2_FB_BLOCK_COLOR 0x8ac8 81 #define PM2_FB_READ_PIXEL 0x8ad0 82 83 #define PM2_FILTER_MODE 0x8c00 84 #define PM2_FM_PASS_SYNC_TAG 0x00000400 85 #define PM2_SYNC 0x8c40 86 87 #define PM2_FB_SRC_DELTA 0x8d88 88 #define PM2_CONFIG 0x8d90 89 #define PM2_CONFIG_FB_READ_SRC_EN 0x00000001 90 #define PM2_CONFIG_FB_WRITE_EN 0x00000008 91 92 #define PM2_COORDS(x, y) ((y) << 16 | (x)) 93 94 95 #ifdef APERTURE 96 extern int allowaperture; 97 #endif 98 99 struct gfxp_softc { 100 struct sunfb sc_sunfb; 101 102 bus_space_tag_t sc_memt; 103 bus_space_handle_t sc_memh; 104 bus_addr_t sc_membase_le; 105 bus_size_t sc_memsize_le; 106 bus_addr_t sc_membase_be; 107 bus_size_t sc_memsize_be; 108 109 bus_space_tag_t sc_mmiot; 110 bus_space_handle_t sc_mmioh; 111 bus_addr_t sc_mmiobase; 112 bus_size_t sc_mmiosize; 113 114 pcitag_t sc_pcitag; 115 116 int sc_mode; 117 u_int8_t sc_cmap_red[256]; 118 u_int8_t sc_cmap_green[256]; 119 u_int8_t sc_cmap_blue[256]; 120 121 /* Saved state to clean up after X11. */ 122 uint32_t sc_read_mode; 123 uint32_t sc_read_pixel; 124 }; 125 126 int gfxp_ioctl(void *, u_long, caddr_t, int, struct proc *); 127 paddr_t gfxp_mmap(void *, off_t, int); 128 129 struct wsdisplay_accessops gfxp_accessops = { 130 .ioctl = gfxp_ioctl, 131 .mmap = gfxp_mmap 132 }; 133 134 int gfxp_match(struct device *, void *, void *); 135 void gfxp_attach(struct device *, struct device *, void *); 136 137 const struct cfattach gfxp_ca = { 138 sizeof(struct gfxp_softc), gfxp_match, gfxp_attach 139 }; 140 141 struct cfdriver gfxp_cd = { 142 NULL, "gfxp", DV_DULL 143 }; 144 145 int gfxp_is_console(int); 146 int gfxp_getcmap(struct gfxp_softc *, struct wsdisplay_cmap *); 147 int gfxp_putcmap(struct gfxp_softc *, struct wsdisplay_cmap *); 148 void gfxp_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 149 150 int gfxp_copycols(void *, int, int, int, int); 151 int gfxp_erasecols(void *, int, int, int, uint32_t); 152 int gfxp_copyrows(void *, int, int, int); 153 int gfxp_eraserows(void *, int, int, uint32_t); 154 155 void gfxp_init(struct gfxp_softc *); 156 void gfxp_reinit(struct gfxp_softc *); 157 158 void gfxp_indexed_write(struct gfxp_softc *, bus_size_t, uint32_t); 159 int gfxp_wait(struct gfxp_softc *); 160 int gfxp_wait_fifo(struct gfxp_softc *, int); 161 void gfxp_copyrect(struct gfxp_softc *, int, int, int, int, int, int); 162 void gfxp_fillrect(struct gfxp_softc *, int, int, int, int, int); 163 164 int 165 gfxp_match(struct device *parent, void *cf, void *aux) 166 { 167 struct pci_attach_args *pa = aux; 168 int node; 169 char *name; 170 171 node = PCITAG_NODE(pa->pa_tag); 172 name = getpropstring(node, "name"); 173 if (strcmp(name, "TECH-SOURCE,gfxp") == 0 || 174 strcmp(name, "TSI,gfxp") == 0) 175 return (10); 176 177 return (0); 178 } 179 180 void 181 gfxp_attach(struct device *parent, struct device *self, void *aux) 182 { 183 struct gfxp_softc *sc = (struct gfxp_softc *)self; 184 struct pci_attach_args *pa = aux; 185 struct rasops_info *ri; 186 int node, console, flags; 187 char *model; 188 189 sc->sc_pcitag = pa->pa_tag; 190 191 node = PCITAG_NODE(pa->pa_tag); 192 console = gfxp_is_console(node); 193 194 printf("\n"); 195 196 model = getpropstring(node, "model"); 197 printf("%s: %s", self->dv_xname, model); 198 199 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PM2_PCI_MEM_LE, 200 PCI_MAPREG_TYPE_MEM, &sc->sc_membase_le, &sc->sc_memsize_le, NULL)) 201 sc->sc_memsize_le = 0; 202 203 if (pci_mapreg_map(pa, PM2_PCI_MEM_BE, PCI_MAPREG_TYPE_MEM, 204 BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, 205 &sc->sc_membase_be, &sc->sc_memsize_be, 0)) { 206 printf("\n%s: can't map video memory\n", self->dv_xname); 207 return; 208 } 209 210 if (pci_mapreg_map(pa, PM2_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0, 211 &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, 212 &sc->sc_mmiosize, 0)) { 213 bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize_be); 214 printf("\n%s: can't map mmio\n", self->dv_xname); 215 return; 216 } 217 218 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 219 220 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 221 222 ri = &sc->sc_sunfb.sf_ro; 223 ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); 224 ri->ri_hw = sc; 225 226 flags = RI_BSWAP; 227 if (sc->sc_sunfb.sf_depth == 32) { 228 ri->ri_rnum = 8; 229 ri->ri_rpos = 16; 230 ri->ri_gnum = 8; 231 ri->ri_gpos = 8; 232 ri->ri_bnum = 8; 233 ri->ri_bpos = 0; 234 flags &= ~RI_BSWAP; 235 } 236 237 fbwscons_init(&sc->sc_sunfb, flags, console); 238 fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor); 239 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 240 241 gfxp_init(sc); 242 ri->ri_ops.copyrows = gfxp_copyrows; 243 ri->ri_ops.copycols = gfxp_copycols; 244 ri->ri_ops.eraserows = gfxp_eraserows; 245 ri->ri_ops.erasecols = gfxp_erasecols; 246 247 if (console) 248 fbwscons_console_init(&sc->sc_sunfb, -1); 249 fbwscons_attach(&sc->sc_sunfb, &gfxp_accessops, console); 250 } 251 252 int 253 gfxp_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 254 { 255 struct gfxp_softc *sc = v; 256 struct wsdisplay_fbinfo *wdf; 257 struct pcisel *sel; 258 259 switch (cmd) { 260 case WSDISPLAYIO_GTYPE: 261 *(u_int *)data = WSDISPLAY_TYPE_GFXP; 262 break; 263 case WSDISPLAYIO_SMODE: 264 sc->sc_mode = *(u_int *)data; 265 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 266 fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor); 267 268 /* Clean up the mess left behind by X. */ 269 gfxp_reinit(sc); 270 } 271 break; 272 case WSDISPLAYIO_GINFO: 273 wdf = (void *)data; 274 wdf->height = sc->sc_sunfb.sf_height; 275 wdf->width = sc->sc_sunfb.sf_width; 276 wdf->depth = sc->sc_sunfb.sf_depth; 277 if (sc->sc_sunfb.sf_depth == 32) 278 wdf->cmsize = 0; 279 else 280 wdf->cmsize = 256; 281 break; 282 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 283 if (sc->sc_sunfb.sf_depth == 32) 284 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32; 285 else 286 return (-1); 287 break; 288 case WSDISPLAYIO_LINEBYTES: 289 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 290 break; 291 292 case WSDISPLAYIO_GETCMAP: 293 return gfxp_getcmap(sc, (struct wsdisplay_cmap *)data); 294 case WSDISPLAYIO_PUTCMAP: 295 return gfxp_putcmap(sc, (struct wsdisplay_cmap *)data); 296 297 case WSDISPLAYIO_GPCIID: 298 sel = (struct pcisel *)data; 299 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 300 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 301 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 302 break; 303 304 case WSDISPLAYIO_SVIDEO: 305 case WSDISPLAYIO_GVIDEO: 306 break; 307 308 case WSDISPLAYIO_GCURPOS: 309 case WSDISPLAYIO_SCURPOS: 310 case WSDISPLAYIO_GCURMAX: 311 case WSDISPLAYIO_GCURSOR: 312 case WSDISPLAYIO_SCURSOR: 313 default: 314 return -1; /* not supported yet */ 315 } 316 317 return (0); 318 } 319 320 paddr_t 321 gfxp_mmap(void *v, off_t off, int prot) 322 { 323 struct gfxp_softc *sc = v; 324 325 if (off & PGOFSET) 326 return (-1); 327 328 switch (sc->sc_mode) { 329 case WSDISPLAYIO_MODE_MAPPED: 330 #ifdef APERTURE 331 if (allowaperture == 0) 332 return (-1); 333 #endif 334 335 if (sc->sc_mmiosize == 0) 336 return (-1); 337 338 if (off >= sc->sc_membase_be && 339 off < (sc->sc_membase_be + sc->sc_memsize_be)) 340 return (bus_space_mmap(sc->sc_memt, 341 sc->sc_membase_be, off - sc->sc_membase_be, 342 prot, BUS_SPACE_MAP_LINEAR)); 343 344 if (off >= sc->sc_mmiobase && 345 off < (sc->sc_mmiobase + sc->sc_mmiosize)) 346 return (bus_space_mmap(sc->sc_mmiot, 347 sc->sc_mmiobase, off - sc->sc_mmiobase, 348 prot, BUS_SPACE_MAP_LINEAR)); 349 break; 350 351 case WSDISPLAYIO_MODE_DUMBFB: 352 if (off >= 0 && off < sc->sc_memsize_le) 353 return (bus_space_mmap(sc->sc_memt, sc->sc_membase_le, 354 off, prot, BUS_SPACE_MAP_LINEAR)); 355 break; 356 } 357 358 return (-1); 359 } 360 361 int 362 gfxp_is_console(int node) 363 { 364 extern int fbnode; 365 366 return (fbnode == node); 367 } 368 369 int 370 gfxp_getcmap(struct gfxp_softc *sc, struct wsdisplay_cmap *cm) 371 { 372 u_int index = cm->index; 373 u_int count = cm->count; 374 int error; 375 376 if (index >= 256 || count > 256 - index) 377 return (EINVAL); 378 379 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 380 if (error) 381 return (error); 382 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 383 if (error) 384 return (error); 385 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 386 if (error) 387 return (error); 388 return (0); 389 } 390 391 int 392 gfxp_putcmap(struct gfxp_softc *sc, struct wsdisplay_cmap *cm) 393 { 394 u_int index = cm->index; 395 u_int count = cm->count; 396 u_int i; 397 int error; 398 u_char *r, *g, *b; 399 400 if (index >= 256 || count > 256 - index) 401 return (EINVAL); 402 403 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 404 return (error); 405 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 406 return (error); 407 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 408 return (error); 409 410 r = &sc->sc_cmap_red[index]; 411 g = &sc->sc_cmap_green[index]; 412 b = &sc->sc_cmap_blue[index]; 413 414 gfxp_wait_fifo(sc, 1); 415 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 416 PM2_PALETTE_WRITE_ADDR, index); 417 for (i = 0; i < count; i++) { 418 gfxp_wait_fifo(sc, 3); 419 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 420 PM2_PALETTE_DATA, *r); 421 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 422 PM2_PALETTE_DATA, *g); 423 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 424 PM2_PALETTE_DATA, *b); 425 r++, g++, b++; 426 } 427 return (0); 428 } 429 430 void 431 gfxp_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 432 { 433 struct gfxp_softc *sc = v; 434 435 sc->sc_cmap_red[index] = r; 436 sc->sc_cmap_green[index] = g; 437 sc->sc_cmap_blue[index] = b; 438 439 gfxp_wait_fifo(sc, 4); 440 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 441 PM2_PALETTE_WRITE_ADDR, index); 442 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_PALETTE_DATA, r); 443 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_PALETTE_DATA, g); 444 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_PALETTE_DATA, b); 445 } 446 447 /* 448 * Accelerated routines. 449 */ 450 451 int 452 gfxp_copycols(void *cookie, int row, int src, int dst, int num) 453 { 454 struct rasops_info *ri = cookie; 455 struct gfxp_softc *sc = ri->ri_hw; 456 457 num *= ri->ri_font->fontwidth; 458 src *= ri->ri_font->fontwidth; 459 dst *= ri->ri_font->fontwidth; 460 row *= ri->ri_font->fontheight; 461 462 gfxp_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 463 ri->ri_xorigin + dst, ri->ri_yorigin + row, 464 num, ri->ri_font->fontheight); 465 466 return 0; 467 } 468 469 int 470 gfxp_erasecols(void *cookie, int row, int col, int num, uint32_t attr) 471 { 472 struct rasops_info *ri = cookie; 473 struct gfxp_softc *sc = ri->ri_hw; 474 int bg, fg; 475 476 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 477 478 row *= ri->ri_font->fontheight; 479 col *= ri->ri_font->fontwidth; 480 num *= ri->ri_font->fontwidth; 481 482 gfxp_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 483 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 484 485 return 0; 486 } 487 488 int 489 gfxp_copyrows(void *cookie, int src, int dst, int num) 490 { 491 struct rasops_info *ri = cookie; 492 struct gfxp_softc *sc = ri->ri_hw; 493 494 num *= ri->ri_font->fontheight; 495 src *= ri->ri_font->fontheight; 496 dst *= ri->ri_font->fontheight; 497 498 gfxp_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 499 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 500 501 return 0; 502 } 503 504 int 505 gfxp_eraserows(void *cookie, int row, int num, uint32_t attr) 506 { 507 struct rasops_info *ri = cookie; 508 struct gfxp_softc *sc = ri->ri_hw; 509 int bg, fg; 510 int x, y, w; 511 512 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 513 514 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 515 num = ri->ri_height; 516 x = y = 0; 517 w = ri->ri_width; 518 } else { 519 num *= ri->ri_font->fontheight; 520 x = ri->ri_xorigin; 521 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 522 w = ri->ri_emuwidth; 523 } 524 gfxp_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 525 526 return 0; 527 } 528 529 void 530 gfxp_init(struct gfxp_softc *sc) 531 { 532 /* XXX Save. */ 533 sc->sc_read_mode = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 534 PM2_FB_READ_MODE); 535 sc->sc_read_pixel = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 536 PM2_FB_READ_PIXEL); 537 } 538 539 void 540 gfxp_reinit(struct gfxp_softc *sc) 541 { 542 struct rasops_info *ri = &sc->sc_sunfb.sf_ro; 543 int i; 544 545 /* XXX Restore. */ 546 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 547 PM2_FB_READ_MODE, sc->sc_read_mode); 548 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 549 PM2_FB_READ_PIXEL, sc->sc_read_pixel); 550 551 /* Disable cursor. */ 552 gfxp_indexed_write(sc, PM2V_CURSOR_MODE, 0x10); 553 554 /* Clear cursor image. */ 555 for (i = 0; i < 1024; i++) 556 gfxp_indexed_write(sc, PM2V_CURSOR_PATTERN + i, 0x00); 557 558 /* Clear screen. */ 559 gfxp_fillrect(sc, 0, 0, ri->ri_width, ri->ri_height, 560 ri->ri_devcmap[WSCOL_WHITE]); 561 } 562 563 void 564 gfxp_indexed_write(struct gfxp_softc *sc, bus_size_t offset, uint32_t value) 565 { 566 gfxp_wait_fifo(sc, 3); 567 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 568 PM2V_INDEX_HIGH, offset >> 8); 569 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 570 PM2V_INDEX_LOW, offset & 0xff); 571 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2V_INDEX_DATA, value); 572 } 573 574 int 575 gfxp_wait_fifo(struct gfxp_softc *sc, int n) 576 { 577 int i; 578 579 for (i = 1000000; i != 0; i--) { 580 if (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 581 PM2_IN_FIFO_SPACE) >= n) 582 break; 583 DELAY(1); 584 } 585 586 return i; 587 } 588 589 int 590 gfxp_wait(struct gfxp_softc *sc) 591 { 592 int i; 593 594 for (i = 1000000; i != 0; i--) { 595 if (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 596 PM2_DMA_COUNT) == 0) 597 break; 598 DELAY(1); 599 } 600 601 /* 602 * Insert a sync into the FIFO... 603 */ 604 gfxp_wait_fifo(sc, 2); 605 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 606 PM2_FILTER_MODE, PM2_FM_PASS_SYNC_TAG); 607 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_SYNC, 0); 608 609 /* 610 * ...and wait for it to appear on the other end, indicating 611 * completion of the operations before it. 612 */ 613 for (i = 1000000; i != 0; i--) { 614 if (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 615 PM2_OUT_FIFO_SPACE) > 0 && 616 bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 617 PM2_OUT_FIFO) == PM2_SYNC_TAG) 618 break; 619 DELAY(1); 620 } 621 622 return i; 623 } 624 625 void 626 gfxp_copyrect(struct gfxp_softc *sc, int sx, int sy, int dx, int dy, 627 int w, int h) 628 { 629 int dir = 0; 630 631 if (sx > dx) 632 dir |= PM2_INCREASE_X; 633 if (sy > dy) 634 dir |= PM2_INCREASE_Y; 635 636 gfxp_wait_fifo(sc, 5); 637 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_CONFIG, 638 PM2_CONFIG_FB_WRITE_EN | PM2_CONFIG_FB_READ_SRC_EN); 639 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_FB_SRC_DELTA, 640 PM2_COORDS((sx - dx) & 0xffff, (sy - dy) & 0xffff)); 641 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_ORIG, 642 PM2_COORDS(dx, dy)); 643 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_SIZE, 644 PM2_COORDS(w, h)); 645 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RENDER, 646 PM2_RENDER_RECT | dir); 647 648 gfxp_wait(sc); 649 } 650 651 void 652 gfxp_fillrect(struct gfxp_softc *sc, int x, int y, int w, int h, int color) 653 { 654 gfxp_wait_fifo(sc, 5); 655 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_CONFIG, 656 PM2_CONFIG_FB_WRITE_EN); 657 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_ORIG, 658 PM2_COORDS(x, y)); 659 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_SIZE, 660 PM2_COORDS(w, h)); 661 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_FB_BLOCK_COLOR, 662 color); 663 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RENDER, 664 PM2_RENDER_RECT | PM2_RENDER_FASTFILL); 665 666 gfxp_wait(sc); 667 } 668