1 /* $OpenBSD: gfxp.c,v 1.11 2009/09/05 14:09:35 miod 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 gfxp_ioctl, 131 gfxp_mmap, 132 NULL, /* alloc_screen */ 133 NULL, /* free_screen */ 134 NULL, /* show_screen */ 135 NULL, /* load_font */ 136 NULL, /* scrollback */ 137 NULL, /* getchar */ 138 NULL, /* burner */ 139 NULL /* pollc */ 140 }; 141 142 int gfxp_match(struct device *, void *, void *); 143 void gfxp_attach(struct device *, struct device *, void *); 144 145 struct cfattach gfxp_ca = { 146 sizeof(struct gfxp_softc), gfxp_match, gfxp_attach 147 }; 148 149 struct cfdriver gfxp_cd = { 150 NULL, "gfxp", DV_DULL 151 }; 152 153 int gfxp_is_console(int); 154 int gfxp_getcmap(struct gfxp_softc *, struct wsdisplay_cmap *); 155 int gfxp_putcmap(struct gfxp_softc *, struct wsdisplay_cmap *); 156 void gfxp_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 157 158 int gfxp_copycols(void *, int, int, int, int); 159 int gfxp_erasecols(void *, int, int, int, long); 160 int gfxp_copyrows(void *, int, int, int); 161 int gfxp_eraserows(void *, int, int, long); 162 163 void gfxp_init(struct gfxp_softc *); 164 void gfxp_reinit(struct gfxp_softc *); 165 166 void gfxp_indexed_write(struct gfxp_softc *, bus_size_t, uint32_t); 167 int gfxp_wait(struct gfxp_softc *); 168 int gfxp_wait_fifo(struct gfxp_softc *, int); 169 void gfxp_copyrect(struct gfxp_softc *, int, int, int, int, int, int); 170 void gfxp_fillrect(struct gfxp_softc *, int, int, int, int, int); 171 172 int 173 gfxp_match(struct device *parent, void *cf, void *aux) 174 { 175 struct pci_attach_args *pa = aux; 176 int node; 177 char *name; 178 179 node = PCITAG_NODE(pa->pa_tag); 180 name = getpropstring(node, "name"); 181 if (strcmp(name, "TECH-SOURCE,gfxp") == 0 || 182 strcmp(name, "TSI,gfxp") == 0) 183 return (10); 184 185 return (0); 186 } 187 188 void 189 gfxp_attach(struct device *parent, struct device *self, void *aux) 190 { 191 struct gfxp_softc *sc = (struct gfxp_softc *)self; 192 struct pci_attach_args *pa = aux; 193 struct rasops_info *ri; 194 int node, console, flags; 195 char *model; 196 197 sc->sc_pcitag = pa->pa_tag; 198 199 node = PCITAG_NODE(pa->pa_tag); 200 console = gfxp_is_console(node); 201 202 printf("\n"); 203 204 model = getpropstring(node, "model"); 205 printf("%s: %s", self->dv_xname, model); 206 207 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PM2_PCI_MEM_LE, 208 PCI_MAPREG_TYPE_MEM, &sc->sc_membase_le, &sc->sc_memsize_le, NULL)) 209 sc->sc_memsize_le = 0; 210 211 if (pci_mapreg_map(pa, PM2_PCI_MEM_BE, PCI_MAPREG_TYPE_MEM, 212 BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, 213 &sc->sc_membase_be, &sc->sc_memsize_be, 0)) { 214 printf("\n%s: can't map video memory\n", self->dv_xname); 215 return; 216 } 217 218 if (pci_mapreg_map(pa, PM2_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0, 219 &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, 220 &sc->sc_mmiosize, 0)) { 221 bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize_be); 222 printf("\n%s: can't map mmio\n", self->dv_xname); 223 return; 224 } 225 226 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 227 228 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 229 230 ri = &sc->sc_sunfb.sf_ro; 231 ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); 232 ri->ri_hw = sc; 233 234 flags = RI_BSWAP; 235 if (sc->sc_sunfb.sf_depth == 32) { 236 ri->ri_rnum = 8; 237 ri->ri_rpos = 16; 238 ri->ri_gnum = 8; 239 ri->ri_gpos = 8; 240 ri->ri_bnum = 8; 241 ri->ri_bpos = 0; 242 flags &= ~RI_BSWAP; 243 } 244 245 fbwscons_init(&sc->sc_sunfb, flags, console); 246 fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor); 247 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 248 249 gfxp_init(sc); 250 ri->ri_ops.copyrows = gfxp_copyrows; 251 ri->ri_ops.copycols = gfxp_copycols; 252 ri->ri_ops.eraserows = gfxp_eraserows; 253 ri->ri_ops.erasecols = gfxp_erasecols; 254 255 if (console) 256 fbwscons_console_init(&sc->sc_sunfb, -1); 257 fbwscons_attach(&sc->sc_sunfb, &gfxp_accessops, console); 258 } 259 260 int 261 gfxp_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 262 { 263 struct gfxp_softc *sc = v; 264 struct wsdisplay_fbinfo *wdf; 265 struct pcisel *sel; 266 267 switch (cmd) { 268 case WSDISPLAYIO_GTYPE: 269 *(u_int *)data = WSDISPLAY_TYPE_GFXP; 270 break; 271 case WSDISPLAYIO_SMODE: 272 sc->sc_mode = *(u_int *)data; 273 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 274 fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor); 275 276 /* Clean up the mess left behind by X. */ 277 gfxp_reinit(sc); 278 } 279 break; 280 case WSDISPLAYIO_GINFO: 281 wdf = (void *)data; 282 wdf->height = sc->sc_sunfb.sf_height; 283 wdf->width = sc->sc_sunfb.sf_width; 284 wdf->depth = sc->sc_sunfb.sf_depth; 285 if (sc->sc_sunfb.sf_depth == 32) 286 wdf->cmsize = 0; 287 else 288 wdf->cmsize = 256; 289 break; 290 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 291 if (sc->sc_sunfb.sf_depth == 32) 292 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32; 293 else 294 return (-1); 295 break; 296 case WSDISPLAYIO_LINEBYTES: 297 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 298 break; 299 300 case WSDISPLAYIO_GETCMAP: 301 return gfxp_getcmap(sc, (struct wsdisplay_cmap *)data); 302 case WSDISPLAYIO_PUTCMAP: 303 return gfxp_putcmap(sc, (struct wsdisplay_cmap *)data); 304 305 case WSDISPLAYIO_GPCIID: 306 sel = (struct pcisel *)data; 307 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 308 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 309 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 310 break; 311 312 case WSDISPLAYIO_SVIDEO: 313 case WSDISPLAYIO_GVIDEO: 314 break; 315 316 case WSDISPLAYIO_GCURPOS: 317 case WSDISPLAYIO_SCURPOS: 318 case WSDISPLAYIO_GCURMAX: 319 case WSDISPLAYIO_GCURSOR: 320 case WSDISPLAYIO_SCURSOR: 321 default: 322 return -1; /* not supported yet */ 323 } 324 325 return (0); 326 } 327 328 paddr_t 329 gfxp_mmap(void *v, off_t off, int prot) 330 { 331 struct gfxp_softc *sc = v; 332 333 if (off & PGOFSET) 334 return (-1); 335 336 switch (sc->sc_mode) { 337 case WSDISPLAYIO_MODE_MAPPED: 338 #ifdef APERTURE 339 if (allowaperture == 0) 340 return (-1); 341 #endif 342 343 if (sc->sc_mmiosize == 0) 344 return (-1); 345 346 if (off >= sc->sc_membase_be && 347 off < (sc->sc_membase_be + sc->sc_memsize_be)) 348 return (bus_space_mmap(sc->sc_memt, 349 sc->sc_membase_be, off - sc->sc_membase_be, 350 prot, BUS_SPACE_MAP_LINEAR)); 351 352 if (off >= sc->sc_mmiobase && 353 off < (sc->sc_mmiobase + sc->sc_mmiosize)) 354 return (bus_space_mmap(sc->sc_mmiot, 355 sc->sc_mmiobase, off - sc->sc_mmiobase, 356 prot, BUS_SPACE_MAP_LINEAR)); 357 break; 358 359 case WSDISPLAYIO_MODE_DUMBFB: 360 if (off >= 0 && off < sc->sc_memsize_le) 361 return (bus_space_mmap(sc->sc_memt, sc->sc_membase_le, 362 off, prot, BUS_SPACE_MAP_LINEAR)); 363 break; 364 } 365 366 return (-1); 367 } 368 369 int 370 gfxp_is_console(int node) 371 { 372 extern int fbnode; 373 374 return (fbnode == node); 375 } 376 377 int 378 gfxp_getcmap(struct gfxp_softc *sc, struct wsdisplay_cmap *cm) 379 { 380 u_int index = cm->index; 381 u_int count = cm->count; 382 int error; 383 384 if (index >= 256 || count > 256 - index) 385 return (EINVAL); 386 387 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 388 if (error) 389 return (error); 390 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 391 if (error) 392 return (error); 393 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 394 if (error) 395 return (error); 396 return (0); 397 } 398 399 int 400 gfxp_putcmap(struct gfxp_softc *sc, struct wsdisplay_cmap *cm) 401 { 402 u_int index = cm->index; 403 u_int count = cm->count; 404 u_int i; 405 int error; 406 u_char *r, *g, *b; 407 408 if (index >= 256 || count > 256 - index) 409 return (EINVAL); 410 411 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 412 return (error); 413 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 414 return (error); 415 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 416 return (error); 417 418 r = &sc->sc_cmap_red[index]; 419 g = &sc->sc_cmap_green[index]; 420 b = &sc->sc_cmap_blue[index]; 421 422 gfxp_wait_fifo(sc, 1); 423 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 424 PM2_PALETTE_WRITE_ADDR, index); 425 for (i = 0; i < count; i++) { 426 gfxp_wait_fifo(sc, 3); 427 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 428 PM2_PALETTE_DATA, *r); 429 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 430 PM2_PALETTE_DATA, *g); 431 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 432 PM2_PALETTE_DATA, *b); 433 r++, g++, b++; 434 } 435 return (0); 436 } 437 438 void 439 gfxp_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 440 { 441 struct gfxp_softc *sc = v; 442 443 sc->sc_cmap_red[index] = r; 444 sc->sc_cmap_green[index] = g; 445 sc->sc_cmap_blue[index] = b; 446 447 gfxp_wait_fifo(sc, 4); 448 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 449 PM2_PALETTE_WRITE_ADDR, index); 450 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_PALETTE_DATA, r); 451 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_PALETTE_DATA, g); 452 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_PALETTE_DATA, b); 453 } 454 455 /* 456 * Accelerated routines. 457 */ 458 459 int 460 gfxp_copycols(void *cookie, int row, int src, int dst, int num) 461 { 462 struct rasops_info *ri = cookie; 463 struct gfxp_softc *sc = ri->ri_hw; 464 465 num *= ri->ri_font->fontwidth; 466 src *= ri->ri_font->fontwidth; 467 dst *= ri->ri_font->fontwidth; 468 row *= ri->ri_font->fontheight; 469 470 gfxp_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 471 ri->ri_xorigin + dst, ri->ri_yorigin + row, 472 num, ri->ri_font->fontheight); 473 474 return 0; 475 } 476 477 int 478 gfxp_erasecols(void *cookie, int row, int col, int num, long attr) 479 { 480 struct rasops_info *ri = cookie; 481 struct gfxp_softc *sc = ri->ri_hw; 482 int bg, fg; 483 484 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 485 486 row *= ri->ri_font->fontheight; 487 col *= ri->ri_font->fontwidth; 488 num *= ri->ri_font->fontwidth; 489 490 gfxp_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 491 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 492 493 return 0; 494 } 495 496 int 497 gfxp_copyrows(void *cookie, int src, int dst, int num) 498 { 499 struct rasops_info *ri = cookie; 500 struct gfxp_softc *sc = ri->ri_hw; 501 502 num *= ri->ri_font->fontheight; 503 src *= ri->ri_font->fontheight; 504 dst *= ri->ri_font->fontheight; 505 506 gfxp_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 507 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 508 509 return 0; 510 } 511 512 int 513 gfxp_eraserows(void *cookie, int row, int num, long attr) 514 { 515 struct rasops_info *ri = cookie; 516 struct gfxp_softc *sc = ri->ri_hw; 517 int bg, fg; 518 int x, y, w; 519 520 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 521 522 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 523 num = ri->ri_height; 524 x = y = 0; 525 w = ri->ri_width; 526 } else { 527 num *= ri->ri_font->fontheight; 528 x = ri->ri_xorigin; 529 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 530 w = ri->ri_emuwidth; 531 } 532 gfxp_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 533 534 return 0; 535 } 536 537 void 538 gfxp_init(struct gfxp_softc *sc) 539 { 540 /* XXX Save. */ 541 sc->sc_read_mode = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 542 PM2_FB_READ_MODE); 543 sc->sc_read_pixel = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 544 PM2_FB_READ_PIXEL); 545 } 546 547 void 548 gfxp_reinit(struct gfxp_softc *sc) 549 { 550 struct rasops_info *ri = &sc->sc_sunfb.sf_ro; 551 int i; 552 553 /* XXX Restore. */ 554 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 555 PM2_FB_READ_MODE, sc->sc_read_mode); 556 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 557 PM2_FB_READ_PIXEL, sc->sc_read_pixel); 558 559 /* Disable cursor. */ 560 gfxp_indexed_write(sc, PM2V_CURSOR_MODE, 0x10); 561 562 /* Clear cursor image. */ 563 for (i = 0; i < 1024; i++) 564 gfxp_indexed_write(sc, PM2V_CURSOR_PATTERN + i, 0x00); 565 566 /* Clear screen. */ 567 gfxp_fillrect(sc, 0, 0, ri->ri_width, ri->ri_height, 568 ri->ri_devcmap[WSCOL_WHITE]); 569 } 570 571 void 572 gfxp_indexed_write(struct gfxp_softc *sc, bus_size_t offset, uint32_t value) 573 { 574 gfxp_wait_fifo(sc, 3); 575 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 576 PM2V_INDEX_HIGH, offset >> 8); 577 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 578 PM2V_INDEX_LOW, offset & 0xff); 579 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2V_INDEX_DATA, value); 580 } 581 582 int 583 gfxp_wait_fifo(struct gfxp_softc *sc, int n) 584 { 585 int i; 586 587 for (i = 1000000; i != 0; i--) { 588 if (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 589 PM2_IN_FIFO_SPACE) >= n) 590 break; 591 DELAY(1); 592 } 593 594 return i; 595 } 596 597 int 598 gfxp_wait(struct gfxp_softc *sc) 599 { 600 int i; 601 602 for (i = 1000000; i != 0; i--) { 603 if (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 604 PM2_DMA_COUNT) == 0) 605 break; 606 DELAY(1); 607 } 608 609 /* 610 * Insert a sync into the FIFO... 611 */ 612 gfxp_wait_fifo(sc, 2); 613 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, 614 PM2_FILTER_MODE, PM2_FM_PASS_SYNC_TAG); 615 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_SYNC, 0); 616 617 /* 618 * ...and wait for it to appear on the other end, indicating 619 * completion of the operations before it. 620 */ 621 for (i = 1000000; i != 0; i--) { 622 if (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 623 PM2_OUT_FIFO_SPACE) > 0 && 624 bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, 625 PM2_OUT_FIFO) == PM2_SYNC_TAG) 626 break; 627 DELAY(1); 628 } 629 630 return i; 631 } 632 633 void 634 gfxp_copyrect(struct gfxp_softc *sc, int sx, int sy, int dx, int dy, 635 int w, int h) 636 { 637 int dir = 0; 638 639 if (sx > dx) 640 dir |= PM2_INCREASE_X; 641 if (sy > dy) 642 dir |= PM2_INCREASE_Y; 643 644 gfxp_wait_fifo(sc, 5); 645 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_CONFIG, 646 PM2_CONFIG_FB_WRITE_EN | PM2_CONFIG_FB_READ_SRC_EN); 647 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_FB_SRC_DELTA, 648 PM2_COORDS(sx - dx, sy - dy)); 649 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_ORIG, 650 PM2_COORDS(dx, dy)); 651 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_SIZE, 652 PM2_COORDS(w, h)); 653 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RENDER, 654 PM2_RENDER_RECT | dir); 655 656 gfxp_wait(sc); 657 } 658 659 void 660 gfxp_fillrect(struct gfxp_softc *sc, int x, int y, int w, int h, int color) 661 { 662 gfxp_wait_fifo(sc, 5); 663 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_CONFIG, 664 PM2_CONFIG_FB_WRITE_EN); 665 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_ORIG, 666 PM2_COORDS(x, y)); 667 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RECT_SIZE, 668 PM2_COORDS(w, h)); 669 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_FB_BLOCK_COLOR, 670 color); 671 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, PM2_RENDER, 672 PM2_RENDER_RECT | PM2_RENDER_FASTFILL); 673 674 gfxp_wait(sc); 675 } 676