1 /* $OpenBSD: machfb.c,v 1.7 2011/02/21 07:55:27 kettenis 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 #define M64_PCI_MEM 0x10 40 #define M64_PCI_MMIO 0x18 41 42 #define M64_REG_OFF 0x007ffc00 43 #define M64_REG_SIZE 0x0400 44 45 #define M64_CRTC_INT_CNTL 0x0018 46 47 #define M64_BUS_CNTL 0x00a0 48 #define M64_BUS_FIFO_ERR_ACK 0x00200000 49 #define M64_BUS_HOST_ERR_ACK 0x00800000 50 #define M64_BUS_APER_REG_DIS 0x00000010 51 52 #define M64_DAC_WINDEX 0x00c0 53 #define M64_DAC_DATA 0x00c1 54 #define M64_DAC_MASK 0x00c2 55 #define M64_DAC_RINDEX 0x00c3 56 #define M64_DAC_CNTL 0x00c4 57 #define M64_DAC_8BIT_EN 0x00000100 58 59 #define M64_GEN_TEST_CNTL 0x00d0 60 #define M64_GEN_GUI_EN 0x00000100 61 62 #define M64_DST_OFF_PITCH 0x0100 63 #define M64_DST_X 0x0104 64 #define M64_DST_Y 0x0108 65 #define M64_DST_Y_X 0x010c 66 #define M64_DST_WIDTH 0x0110 67 #define M64_DST_HEIGHT 0x0114 68 #define M64_DST_HEIGHT_WIDTH 0x0118 69 #define M64_DST_X_WIDTH 0x011c 70 #define M64_DST_BRES_LNTH 0x0120 71 #define M64_DST_BRES_ERR 0x0124 72 #define M64_DST_BRES_INC 0x0128 73 #define M64_DST_BRES_DEC 0x012c 74 #define M64_DST_CNTL 0x0130 75 #define M64_DST_X_RIGHT_TO_LEFT 0x00000000 76 #define M64_DST_X_LEFT_TO_RIGHT 0x00000001 77 #define M64_DST_Y_BOTTOM_TO_TOP 0x00000000 78 #define M64_DST_Y_TOP_TO_BOTTOM 0x00000002 79 #define M64_DST_X_MAJOR 0x00000000 80 #define M64_DST_Y_MAJOR 0x00000004 81 #define M64_DST_X_TILE 0x00000008 82 #define M64_DST_Y_TILE 0x00000010 83 #define M64_DST_LAST_PEL 0x00000020 84 #define M64_DST_POLYGON_EN 0x00000040 85 #define M64_DST_24_ROT_EN 0x00000080 86 87 #define M64_SRC_OFF_PITCH 0x0180 88 #define M64_SRC_X 0x0184 89 #define M64_SRC_Y 0x0188 90 #define M64_SRC_Y_X 0x018c 91 #define M64_SRC_WIDTH1 0x0190 92 #define M64_SRC_HEIGHT1 0x0194 93 #define M64_SRC_HEIGHT1_WIDTH1 0x0198 94 #define M64_SRC_X_START 0x019c 95 #define M64_SRC_Y_START 0x01a0 96 #define M64_SRC_Y_X_START 0x01a4 97 #define M64_SRC_WIDTH2 0x01a8 98 #define M64_SRC_HEIGHT2 0x01ac 99 #define M64_SRC_HEIGHT2_WIDTH2 0x01b0 100 #define M64_SRC_CNTL 0x01b4 101 #define M64_SRC_PATT_EN 0x00000001 102 #define M64_SRC_PATT_ROT_EN 0x00000002 103 #define M64_SRC_LINEAR_EN 0x00000004 104 #define M64_SRC_BYTE_ALIGN 0x00000008 105 #define M64_SRC_LINE_X_RIGHT_TO_LEFT 0x00000000 106 #define M64_SRC_LINE_X_LEFT_TO_RIGHT 0x00000010 107 108 #define M64_HOST_CNTL 0x0240 109 110 #define M64_PAT_REG0 0x0280 111 #define M64_PAT_REG1 0x0284 112 #define M64_PAT_CNTL 0x0288 113 114 #define M64_SC_LEFT 0x02a0 115 #define M64_SC_RIGHT 0x02a4 116 #define M64_SC_LEFT_RIGHT 0x02a8 117 #define M64_SC_TOP 0x02ac 118 #define M64_SC_BOTTOM 0x02b0 119 #define M64_SC_TOP_BOTTOM 0x02b4 120 121 #define M64_DP_BKGD_CLR 0x02c0 122 #define M64_DP_FRGD_CLR 0x02c4 123 #define M64_DP_WRITE_MASK 0x02c8 124 125 #define M64_DP_CHAIN_MASK 0x02cc 126 #define M64_DP_CHAIN_8BPP 0x00008080 127 #define M64_DP_PIX_WIDTH 0x02d0 128 #define M64_DST_8BPP 0x00000002 129 #define M64_SRC_8BPP 0x00000200 130 #define M64_HOST_8BPP 0x00020000 131 #define M64_DP_MIX 0x02d4 132 #define M64_MIX_DST 0x00000003 133 #define M64_MIX_SRC 0x00000007 134 #define M64_DP_SRC 0x02d8 135 #define M64_BKGD_SRC_BKGD_CLR 0x00000000 136 #define M64_BKGD_SRC_FRGD_CLR 0x00000001 137 #define M64_BKGD_SRC_HOST 0x00000002 138 #define M64_BKGD_SRC_BLIT 0x00000003 139 #define M64_BKGD_SRC_PATTERN 0x00000004 140 #define M64_FRGD_SRC_BKGD_CLR 0x00000000 141 #define M64_FRGD_SRC_FRGD_CLR 0x00000100 142 #define M64_FRGD_SRC_HOST 0x00000200 143 #define M64_FRGD_SRC_BLIT 0x00000300 144 #define M64_FRGD_SRC_PATTERN 0x00000400 145 #define M64_MONO_SRC_ONE 0x00000000 146 #define M64_MONO_SRC_PATTERN 0x00010000 147 #define M64_MONO_SRC_HOST 0x00020000 148 #define M64_MONO_SRC_BLIT 0x00030000 149 150 #define M64_CLR_CMP_CLR 0x0300 151 #define M64_CLR_CMP_MASK 0x0304 152 #define M64_CLR_CMP_CNTL 0x0308 153 154 #define M64_FIFO_STAT 0x0310 155 #define M64_FIFO_STAT_MASK 0x0000ffff 156 157 #define M64_CONTEXT_MASK 0x0320 158 159 #define M64_GUI_TRAJ_CNTL 0x0330 160 #define M64_GUI_STAT 0x0338 161 #define M64_GUI_ACTIVE 0x00000001 162 163 #define M64_COORDS(x, y) ((x << 16) | (y)) 164 165 #ifdef APERTURE 166 extern int allowaperture; 167 #endif 168 169 struct machfb_softc { 170 struct sunfb sc_sunfb; 171 172 bus_space_tag_t sc_memt; 173 bus_space_handle_t sc_memh; 174 bus_addr_t sc_membase; 175 bus_size_t sc_memsize; 176 177 bus_space_tag_t sc_regt; 178 bus_space_handle_t sc_regh; 179 180 bus_space_tag_t sc_mmiot; 181 bus_space_handle_t sc_mmioh; 182 bus_addr_t sc_mmiobase; 183 bus_size_t sc_mmiosize; 184 185 pcitag_t sc_pcitag; 186 187 int sc_mode; 188 u_int8_t sc_cmap_red[256]; 189 u_int8_t sc_cmap_green[256]; 190 u_int8_t sc_cmap_blue[256]; 191 }; 192 193 int machfb_ioctl(void *, u_long, caddr_t, int, struct proc *); 194 paddr_t machfb_mmap(void *, off_t, int); 195 196 struct wsdisplay_accessops machfb_accessops = { 197 machfb_ioctl, 198 machfb_mmap, 199 NULL, /* alloc_screen */ 200 NULL, /* free_screen */ 201 NULL, /* show_screen */ 202 NULL, /* load_font */ 203 NULL, /* scrollback */ 204 NULL, /* getchar */ 205 NULL, /* burner */ 206 NULL /* pollc */ 207 }; 208 209 int machfb_match(struct device *, void *, void *); 210 void machfb_attach(struct device *, struct device *, void *); 211 212 struct cfattach machfb_ca = { 213 sizeof(struct machfb_softc), machfb_match, machfb_attach 214 }; 215 216 struct cfdriver machfb_cd = { 217 NULL, "machfb", DV_DULL 218 }; 219 220 int machfb_is_console(int); 221 int machfb_getcmap(struct machfb_softc *, struct wsdisplay_cmap *); 222 int machfb_putcmap(struct machfb_softc *, struct wsdisplay_cmap *); 223 void machfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 224 225 int machfb_copycols(void *, int, int, int, int); 226 int machfb_erasecols(void *, int, int, int, long); 227 int machfb_copyrows(void *, int, int, int); 228 int machfb_eraserows(void *, int, int, long); 229 230 void machfb_init(struct machfb_softc *); 231 int machfb_wait_fifo(struct machfb_softc *, int); 232 int machfb_wait(struct machfb_softc *); 233 void machfb_copyrect(struct machfb_softc *, int, int, int, int, int, int); 234 void machfb_fillrect(struct machfb_softc *, int, int, int, int, int); 235 236 int 237 machfb_match(struct device *parent, void *cf, void *aux) 238 { 239 struct pci_attach_args *pa = aux; 240 char buf[32]; 241 int node; 242 243 node = PCITAG_NODE(pa->pa_tag); 244 OF_getprop(node, "name", buf, sizeof(buf)); 245 if (strcmp(buf, "SUNW,m64B") == 0) 246 return (10); 247 248 if (OF_getprop(node, "compatible", buf, sizeof(buf)) > 0 && 249 strcmp(buf, "SUNW,m64B") == 0) 250 return (10); 251 252 return (0); 253 } 254 255 void 256 machfb_attach(struct device *parent, struct device *self, void *aux) 257 { 258 struct machfb_softc *sc = (struct machfb_softc *)self; 259 struct pci_attach_args *pa = aux; 260 struct rasops_info *ri; 261 int node, console; 262 char *model; 263 264 sc->sc_pcitag = pa->pa_tag; 265 266 node = PCITAG_NODE(pa->pa_tag); 267 console = machfb_is_console(node); 268 269 printf("\n"); 270 271 model = getpropstring(node, "model"); 272 printf("%s: %s", self->dv_xname, model); 273 274 if (pci_mapreg_map(pa, M64_PCI_MEM, PCI_MAPREG_TYPE_MEM, 275 BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, 276 &sc->sc_membase, &sc->sc_memsize, 0)) { 277 printf("\n%s: can't map video memory\n", self->dv_xname); 278 return; 279 } 280 281 sc->sc_regt = sc->sc_memt; 282 if (bus_space_subregion(sc->sc_memt, sc->sc_memh, 283 M64_REG_OFF, M64_REG_SIZE, &sc->sc_regh)) { 284 printf("\n%s: can't map registers\n", self->dv_xname); 285 return; 286 } 287 288 if (pci_mapreg_map(pa, M64_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0, 289 &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, 290 &sc->sc_mmiosize, 0)) { 291 printf("\n%s: can't map registers\n", self->dv_xname); 292 return; 293 } 294 295 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 296 if (sc->sc_sunfb.sf_depth == 24) { 297 sc->sc_sunfb.sf_depth = 32; 298 sc->sc_sunfb.sf_linebytes = 299 (sc->sc_sunfb.sf_depth / 8) * sc->sc_sunfb.sf_width; 300 sc->sc_sunfb.sf_fbsize = 301 sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes; 302 } 303 304 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 305 306 ri = &sc->sc_sunfb.sf_ro; 307 ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); 308 ri->ri_hw = sc; 309 310 fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console); 311 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor); 312 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 313 314 machfb_init(sc); 315 ri->ri_ops.copyrows = machfb_copyrows; 316 ri->ri_ops.copycols = machfb_copycols; 317 ri->ri_ops.eraserows = machfb_eraserows; 318 ri->ri_ops.erasecols = machfb_erasecols; 319 320 if (console) 321 fbwscons_console_init(&sc->sc_sunfb, -1); 322 fbwscons_attach(&sc->sc_sunfb, &machfb_accessops, console); 323 } 324 325 int 326 machfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 327 { 328 struct machfb_softc *sc = v; 329 struct wsdisplay_fbinfo *wdf; 330 struct pcisel *sel; 331 332 switch (cmd) { 333 case WSDISPLAYIO_GTYPE: 334 *(u_int *)data = WSDISPLAY_TYPE_MACHFB; 335 break; 336 case WSDISPLAYIO_SMODE: 337 sc->sc_mode = *(u_int *)data; 338 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 339 struct rasops_info *ri = &sc->sc_sunfb.sf_ro; 340 341 /* Restore colormap. */ 342 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor); 343 344 /* Clear screen. */ 345 machfb_fillrect(sc, 0, 0, ri->ri_width, ri->ri_height, 346 ri->ri_devcmap[WSCOL_WHITE]); 347 } 348 break; 349 case WSDISPLAYIO_GINFO: 350 wdf = (void *)data; 351 wdf->height = sc->sc_sunfb.sf_height; 352 wdf->width = sc->sc_sunfb.sf_width; 353 wdf->depth = sc->sc_sunfb.sf_depth; 354 wdf->cmsize = 256; 355 break; 356 case WSDISPLAYIO_LINEBYTES: 357 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 358 break; 359 360 case WSDISPLAYIO_GETCMAP: 361 return machfb_getcmap(sc, (struct wsdisplay_cmap *)data); 362 case WSDISPLAYIO_PUTCMAP: 363 return machfb_putcmap(sc, (struct wsdisplay_cmap *)data); 364 365 case WSDISPLAYIO_GPCIID: 366 sel = (struct pcisel *)data; 367 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 368 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 369 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 370 break; 371 372 case WSDISPLAYIO_SVIDEO: 373 case WSDISPLAYIO_GVIDEO: 374 break; 375 376 case WSDISPLAYIO_GCURPOS: 377 case WSDISPLAYIO_SCURPOS: 378 case WSDISPLAYIO_GCURMAX: 379 case WSDISPLAYIO_GCURSOR: 380 case WSDISPLAYIO_SCURSOR: 381 default: 382 return -1; /* not supported yet */ 383 } 384 385 return (0); 386 } 387 388 paddr_t 389 machfb_mmap(void *v, off_t off, int prot) 390 { 391 struct machfb_softc *sc = v; 392 393 if (off & PGOFSET) 394 return (-1); 395 396 switch (sc->sc_mode) { 397 case WSDISPLAYIO_MODE_MAPPED: 398 #ifdef APERTURE 399 if (allowaperture == 0) 400 return (-1); 401 #endif 402 403 if (sc->sc_mmiosize == 0) 404 return (-1); 405 406 if (off >= sc->sc_membase && 407 off < (sc->sc_membase + sc->sc_memsize)) 408 return (bus_space_mmap(sc->sc_memt, 409 sc->sc_membase, off - sc->sc_membase, 410 prot, BUS_SPACE_MAP_LINEAR)); 411 412 if (off >= sc->sc_mmiobase && 413 off < (sc->sc_mmiobase + sc->sc_mmiosize)) 414 return (bus_space_mmap(sc->sc_mmiot, 415 sc->sc_mmiobase, off - sc->sc_mmiobase, 416 prot, BUS_SPACE_MAP_LINEAR)); 417 break; 418 419 case WSDISPLAYIO_MODE_DUMBFB: 420 if (off >= 0 && off < sc->sc_memsize) 421 return (bus_space_mmap(sc->sc_memt, sc->sc_membase, 422 off, prot, BUS_SPACE_MAP_LINEAR)); 423 break; 424 } 425 426 return (-1); 427 } 428 429 int 430 machfb_is_console(int node) 431 { 432 extern int fbnode; 433 434 return (fbnode == node); 435 } 436 437 int 438 machfb_getcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm) 439 { 440 u_int index = cm->index; 441 u_int count = cm->count; 442 int error; 443 444 if (index >= 256 || count > 256 - index) 445 return (EINVAL); 446 447 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 448 if (error) 449 return (error); 450 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 451 if (error) 452 return (error); 453 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 454 if (error) 455 return (error); 456 return (0); 457 } 458 459 int 460 machfb_putcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm) 461 { 462 u_int index = cm->index; 463 u_int count = cm->count; 464 u_int i; 465 int error; 466 u_char *r, *g, *b; 467 468 if (index >= 256 || count > 256 - index) 469 return (EINVAL); 470 471 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 472 return (error); 473 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 474 return (error); 475 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 476 return (error); 477 478 r = &sc->sc_cmap_red[index]; 479 g = &sc->sc_cmap_green[index]; 480 b = &sc->sc_cmap_blue[index]; 481 482 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff); 483 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index); 484 for (i = 0; i < count; i++) { 485 bus_space_write_1(sc->sc_regt, sc->sc_regh, 486 M64_DAC_DATA, *r); 487 bus_space_write_1(sc->sc_regt, sc->sc_regh, 488 M64_DAC_DATA, *g); 489 bus_space_write_1(sc->sc_regt, sc->sc_regh, 490 M64_DAC_DATA, *b); 491 r++, g++, b++; 492 } 493 return (0); 494 } 495 496 void 497 machfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 498 { 499 struct machfb_softc *sc = v; 500 501 sc->sc_cmap_red[index] = r; 502 sc->sc_cmap_green[index] = g; 503 sc->sc_cmap_blue[index] = b; 504 505 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff); 506 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index); 507 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, r); 508 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, g); 509 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, b); 510 } 511 512 /* 513 * Accelerated routines. 514 */ 515 516 int 517 machfb_copycols(void *cookie, int row, int src, int dst, int num) 518 { 519 struct rasops_info *ri = cookie; 520 struct machfb_softc *sc = ri->ri_hw; 521 522 num *= ri->ri_font->fontwidth; 523 src *= ri->ri_font->fontwidth; 524 dst *= ri->ri_font->fontwidth; 525 row *= ri->ri_font->fontheight; 526 527 machfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 528 ri->ri_xorigin + dst, ri->ri_yorigin + row, 529 num, ri->ri_font->fontheight); 530 531 return 0; 532 } 533 534 int 535 machfb_erasecols(void *cookie, int row, int col, int num, long attr) 536 { 537 struct rasops_info *ri = cookie; 538 struct machfb_softc *sc = ri->ri_hw; 539 int bg, fg; 540 541 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 542 543 row *= ri->ri_font->fontheight; 544 col *= ri->ri_font->fontwidth; 545 num *= ri->ri_font->fontwidth; 546 547 machfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 548 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 549 550 return 0; 551 } 552 553 int 554 machfb_copyrows(void *cookie, int src, int dst, int num) 555 { 556 struct rasops_info *ri = cookie; 557 struct machfb_softc *sc = ri->ri_hw; 558 559 num *= ri->ri_font->fontheight; 560 src *= ri->ri_font->fontheight; 561 dst *= ri->ri_font->fontheight; 562 563 machfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 564 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 565 566 return 0; 567 } 568 569 int 570 machfb_eraserows(void *cookie, int row, int num, long attr) 571 { 572 struct rasops_info *ri = cookie; 573 struct machfb_softc *sc = ri->ri_hw; 574 int bg, fg; 575 int x, y, w; 576 577 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 578 579 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 580 num = ri->ri_height; 581 x = y = 0; 582 w = ri->ri_width; 583 } else { 584 num *= ri->ri_font->fontheight; 585 x = ri->ri_xorigin; 586 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 587 w = ri->ri_emuwidth; 588 } 589 machfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 590 591 return 0; 592 } 593 594 void 595 machfb_init(struct machfb_softc *sc) 596 { 597 uint32_t reg; 598 599 /* Reset engine. */ 600 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL); 601 reg &= ~M64_GEN_GUI_EN; 602 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg); 603 604 /* Enable engine. */ 605 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL); 606 reg &= M64_GEN_GUI_EN; 607 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg); 608 609 /* Clearing any FIFO or host errors. */ 610 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL); 611 reg |= M64_BUS_HOST_ERR_ACK | M64_BUS_FIFO_ERR_ACK; 612 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL, reg); 613 614 machfb_wait_fifo(sc, 14); 615 616 bus_space_write_4(sc->sc_regt, sc->sc_regh, 617 M64_CONTEXT_MASK, 0xffffffff); 618 619 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_OFF_PITCH, 620 (sc->sc_sunfb.sf_linebytes / 8) << 22); 621 622 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_Y_X, 0); 623 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_HEIGHT, 0); 624 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_ERR, 0); 625 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_INC, 0); 626 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_DEC, 0); 627 628 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, 629 M64_DST_LAST_PEL | M64_DST_X_LEFT_TO_RIGHT | 630 M64_DST_Y_TOP_TO_BOTTOM); 631 632 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_OFF_PITCH, 633 (sc->sc_sunfb.sf_linebytes / 8) << 22); 634 635 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X, 0); 636 bus_space_write_4(sc->sc_regt, sc->sc_regh, 637 M64_SRC_HEIGHT1_WIDTH1, 1); 638 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X_START, 0); 639 bus_space_write_4(sc->sc_regt, sc->sc_regh, 640 M64_SRC_HEIGHT2_WIDTH2, 1); 641 642 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_CNTL, 643 M64_SRC_LINE_X_LEFT_TO_RIGHT); 644 645 machfb_wait_fifo(sc, 13); 646 647 /* Host attributes. */ 648 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_HOST_CNTL, 0); 649 650 /* Pattern attributes. */ 651 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG0, 0); 652 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG1, 0); 653 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_CNTL, 0); 654 655 /* Scissors. */ 656 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_LEFT, 0); 657 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_TOP, 0); 658 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_BOTTOM, 659 sc->sc_sunfb.sf_height - 1); 660 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_RIGHT, 661 sc->sc_sunfb.sf_linebytes - 1); 662 663 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_BKGD_CLR, 0); 664 bus_space_write_4(sc->sc_regt, sc->sc_regh, 665 M64_DP_FRGD_CLR, 0xffffffff); 666 bus_space_write_4(sc->sc_regt, sc->sc_regh, 667 M64_DP_WRITE_MASK, 0xffffffff); 668 bus_space_write_4(sc->sc_regt, sc->sc_regh, 669 M64_DP_MIX, (M64_MIX_SRC << 16) | M64_MIX_DST); 670 671 bus_space_write_4(sc->sc_regt, sc->sc_regh, 672 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR); 673 674 machfb_wait_fifo(sc, 3); 675 676 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CLR, 0); 677 bus_space_write_4(sc->sc_regt, sc->sc_regh, 678 M64_CLR_CMP_MASK, 0xffffffff); 679 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 680 681 machfb_wait_fifo(sc, 3); 682 683 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_PIX_WIDTH, 684 M64_HOST_8BPP | M64_SRC_8BPP | M64_DST_8BPP); 685 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_CHAIN_MASK, 686 M64_DP_CHAIN_8BPP); 687 688 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GUI_TRAJ_CNTL, 689 M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM); 690 691 machfb_wait(sc); 692 } 693 694 int 695 machfb_wait_fifo(struct machfb_softc *sc, int v) 696 { 697 int i; 698 699 for (i = 1000000; i != 0; i--) { 700 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh, 701 M64_FIFO_STAT) & M64_FIFO_STAT_MASK) <= (0x8000 >> v)) 702 break; 703 DELAY(1); 704 } 705 706 return i; 707 } 708 709 int 710 machfb_wait(struct machfb_softc *sc) 711 { 712 int i; 713 714 machfb_wait_fifo(sc, 16); 715 for (i = 1000000; i != 0; i--) { 716 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh, 717 M64_GUI_STAT) & M64_GUI_ACTIVE) == 0) 718 break; 719 DELAY(1); 720 } 721 722 return i; 723 } 724 725 void 726 machfb_copyrect(struct machfb_softc *sc, int sx, int sy, int dx, int dy, 727 int w, int h) 728 { 729 uint32_t dest_ctl = 0; 730 731 machfb_wait_fifo(sc, 10); 732 733 bus_space_write_4(sc->sc_regt, sc->sc_regh, 734 M64_DP_WRITE_MASK, 0xff); 735 bus_space_write_4(sc->sc_regt, sc->sc_regh, 736 M64_DP_SRC, M64_FRGD_SRC_BLIT); 737 bus_space_write_4(sc->sc_regt, sc->sc_regh, 738 M64_DP_MIX, M64_MIX_SRC << 16); 739 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 740 if (dy < sy) { 741 dest_ctl = M64_DST_Y_TOP_TO_BOTTOM; 742 } else { 743 sy += h - 1; 744 dy += h - 1; 745 dest_ctl = M64_DST_Y_BOTTOM_TO_TOP; 746 } 747 if (dx < sx) { 748 dest_ctl |= M64_DST_X_LEFT_TO_RIGHT; 749 bus_space_write_4(sc->sc_regt, sc->sc_regh, 750 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT); 751 } else { 752 dest_ctl |= M64_DST_X_RIGHT_TO_LEFT; 753 sx += w - 1; 754 dx += w - 1; 755 bus_space_write_4(sc->sc_regt, sc->sc_regh, 756 M64_SRC_CNTL, M64_SRC_LINE_X_RIGHT_TO_LEFT); 757 } 758 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, dest_ctl); 759 760 bus_space_write_4(sc->sc_regt, sc->sc_regh, 761 M64_SRC_Y_X, M64_COORDS(sx, sy)); 762 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w); 763 bus_space_write_4(sc->sc_regt, sc->sc_regh, 764 M64_DST_Y_X, M64_COORDS(dx, dy)); 765 bus_space_write_4(sc->sc_regt, sc->sc_regh, 766 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h)); 767 768 machfb_wait(sc); 769 } 770 771 void 772 machfb_fillrect(struct machfb_softc *sc, int x, int y, int w, int h, int color) 773 { 774 machfb_wait_fifo(sc, 11); 775 776 bus_space_write_4(sc->sc_regt, sc->sc_regh, 777 M64_DP_WRITE_MASK, 0xff); 778 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_FRGD_CLR, color); 779 bus_space_write_4(sc->sc_regt, sc->sc_regh, 780 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR); 781 bus_space_write_4(sc->sc_regt, sc->sc_regh, 782 M64_DP_MIX, M64_MIX_SRC << 16); 783 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 784 bus_space_write_4(sc->sc_regt, sc->sc_regh, 785 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT); 786 bus_space_write_4(sc->sc_regt, sc->sc_regh, 787 M64_DST_CNTL, M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM); 788 789 bus_space_write_4(sc->sc_regt, sc->sc_regh, 790 M64_SRC_Y_X, M64_COORDS(x, y)); 791 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w); 792 bus_space_write_4(sc->sc_regt, sc->sc_regh, 793 M64_DST_Y_X, M64_COORDS(x, y)); 794 bus_space_write_4(sc->sc_regt, sc->sc_regh, 795 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h)); 796 797 machfb_wait(sc); 798 } 799