1 /* $OpenBSD: machfb.c,v 1.10 2014/07/28 15:00:27 jsg 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 .ioctl = machfb_ioctl, 198 .mmap = machfb_mmap 199 }; 200 201 int machfb_match(struct device *, void *, void *); 202 void machfb_attach(struct device *, struct device *, void *); 203 204 struct cfattach machfb_ca = { 205 sizeof(struct machfb_softc), machfb_match, machfb_attach 206 }; 207 208 struct cfdriver machfb_cd = { 209 NULL, "machfb", DV_DULL 210 }; 211 212 int machfb_is_console(int); 213 int machfb_getcmap(struct machfb_softc *, struct wsdisplay_cmap *); 214 int machfb_putcmap(struct machfb_softc *, struct wsdisplay_cmap *); 215 void machfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 216 217 int machfb_copycols(void *, int, int, int, int); 218 int machfb_erasecols(void *, int, int, int, long); 219 int machfb_copyrows(void *, int, int, int); 220 int machfb_eraserows(void *, int, int, long); 221 222 void machfb_init(struct machfb_softc *); 223 int machfb_wait_fifo(struct machfb_softc *, int); 224 int machfb_wait(struct machfb_softc *); 225 void machfb_copyrect(struct machfb_softc *, int, int, int, int, int, int); 226 void machfb_fillrect(struct machfb_softc *, int, int, int, int, int); 227 228 int 229 machfb_match(struct device *parent, void *cf, void *aux) 230 { 231 struct pci_attach_args *pa = aux; 232 char buf[32]; 233 int node; 234 235 node = PCITAG_NODE(pa->pa_tag); 236 OF_getprop(node, "name", buf, sizeof(buf)); 237 if (strcmp(buf, "SUNW,m64B") == 0) 238 return (10); 239 240 if (OF_getprop(node, "compatible", buf, sizeof(buf)) > 0 && 241 strcmp(buf, "SUNW,m64B") == 0) 242 return (10); 243 244 return (0); 245 } 246 247 void 248 machfb_attach(struct device *parent, struct device *self, void *aux) 249 { 250 struct machfb_softc *sc = (struct machfb_softc *)self; 251 struct pci_attach_args *pa = aux; 252 struct rasops_info *ri; 253 int node, console; 254 char *model; 255 256 sc->sc_pcitag = pa->pa_tag; 257 258 node = PCITAG_NODE(pa->pa_tag); 259 console = machfb_is_console(node); 260 261 printf("\n"); 262 263 model = getpropstring(node, "model"); 264 printf("%s: %s", self->dv_xname, model); 265 266 if (pci_mapreg_map(pa, M64_PCI_MEM, PCI_MAPREG_TYPE_MEM, 267 BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, 268 &sc->sc_membase, &sc->sc_memsize, 0)) { 269 printf("\n%s: can't map video memory\n", self->dv_xname); 270 return; 271 } 272 273 sc->sc_regt = sc->sc_memt; 274 if (bus_space_subregion(sc->sc_memt, sc->sc_memh, 275 M64_REG_OFF, M64_REG_SIZE, &sc->sc_regh)) { 276 printf("\n%s: can't map registers\n", self->dv_xname); 277 return; 278 } 279 280 if (pci_mapreg_map(pa, M64_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0, 281 &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, 282 &sc->sc_mmiosize, 0)) { 283 printf("\n%s: can't map registers\n", self->dv_xname); 284 return; 285 } 286 287 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); 288 if (sc->sc_sunfb.sf_depth == 24) { 289 sc->sc_sunfb.sf_depth = 32; 290 sc->sc_sunfb.sf_linebytes = 291 (sc->sc_sunfb.sf_depth / 8) * sc->sc_sunfb.sf_width; 292 sc->sc_sunfb.sf_fbsize = 293 sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes; 294 } 295 296 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 297 298 #ifdef RAMDISK_HOOKS 299 printf("%s: aperture needed\n", self->dv_xname); 300 #endif 301 302 ri = &sc->sc_sunfb.sf_ro; 303 ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); 304 ri->ri_hw = sc; 305 306 fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console); 307 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor); 308 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 309 310 machfb_init(sc); 311 ri->ri_ops.copyrows = machfb_copyrows; 312 ri->ri_ops.copycols = machfb_copycols; 313 ri->ri_ops.eraserows = machfb_eraserows; 314 ri->ri_ops.erasecols = machfb_erasecols; 315 316 if (console) 317 fbwscons_console_init(&sc->sc_sunfb, -1); 318 fbwscons_attach(&sc->sc_sunfb, &machfb_accessops, console); 319 } 320 321 int 322 machfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) 323 { 324 struct machfb_softc *sc = v; 325 struct wsdisplay_fbinfo *wdf; 326 struct pcisel *sel; 327 328 switch (cmd) { 329 case WSDISPLAYIO_GTYPE: 330 *(u_int *)data = WSDISPLAY_TYPE_MACHFB; 331 break; 332 case WSDISPLAYIO_SMODE: 333 sc->sc_mode = *(u_int *)data; 334 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 335 struct rasops_info *ri = &sc->sc_sunfb.sf_ro; 336 337 /* Restore colormap. */ 338 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor); 339 340 /* Clear screen. */ 341 machfb_fillrect(sc, 0, 0, ri->ri_width, ri->ri_height, 342 ri->ri_devcmap[WSCOL_WHITE]); 343 } 344 break; 345 case WSDISPLAYIO_GINFO: 346 wdf = (void *)data; 347 wdf->height = sc->sc_sunfb.sf_height; 348 wdf->width = sc->sc_sunfb.sf_width; 349 wdf->depth = sc->sc_sunfb.sf_depth; 350 wdf->cmsize = 256; 351 break; 352 case WSDISPLAYIO_LINEBYTES: 353 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 354 break; 355 356 case WSDISPLAYIO_GETCMAP: 357 return machfb_getcmap(sc, (struct wsdisplay_cmap *)data); 358 case WSDISPLAYIO_PUTCMAP: 359 return machfb_putcmap(sc, (struct wsdisplay_cmap *)data); 360 361 case WSDISPLAYIO_GPCIID: 362 sel = (struct pcisel *)data; 363 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 364 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 365 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 366 break; 367 368 case WSDISPLAYIO_SVIDEO: 369 case WSDISPLAYIO_GVIDEO: 370 break; 371 372 case WSDISPLAYIO_GCURPOS: 373 case WSDISPLAYIO_SCURPOS: 374 case WSDISPLAYIO_GCURMAX: 375 case WSDISPLAYIO_GCURSOR: 376 case WSDISPLAYIO_SCURSOR: 377 default: 378 return -1; /* not supported yet */ 379 } 380 381 return (0); 382 } 383 384 paddr_t 385 machfb_mmap(void *v, off_t off, int prot) 386 { 387 struct machfb_softc *sc = v; 388 389 if (off & PGOFSET) 390 return (-1); 391 392 switch (sc->sc_mode) { 393 case WSDISPLAYIO_MODE_MAPPED: 394 #ifdef APERTURE 395 if (allowaperture == 0) 396 return (-1); 397 #endif 398 399 if (sc->sc_mmiosize == 0) 400 return (-1); 401 402 if (off >= sc->sc_membase && 403 off < (sc->sc_membase + sc->sc_memsize)) 404 return (bus_space_mmap(sc->sc_memt, 405 sc->sc_membase, off - sc->sc_membase, 406 prot, BUS_SPACE_MAP_LINEAR)); 407 408 if (off >= sc->sc_mmiobase && 409 off < (sc->sc_mmiobase + sc->sc_mmiosize)) 410 return (bus_space_mmap(sc->sc_mmiot, 411 sc->sc_mmiobase, off - sc->sc_mmiobase, 412 prot, BUS_SPACE_MAP_LINEAR)); 413 break; 414 415 case WSDISPLAYIO_MODE_DUMBFB: 416 if (off >= 0 && off < sc->sc_memsize) 417 return (bus_space_mmap(sc->sc_memt, sc->sc_membase, 418 off, prot, BUS_SPACE_MAP_LINEAR)); 419 break; 420 } 421 422 return (-1); 423 } 424 425 int 426 machfb_is_console(int node) 427 { 428 extern int fbnode; 429 430 return (fbnode == node); 431 } 432 433 int 434 machfb_getcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm) 435 { 436 u_int index = cm->index; 437 u_int count = cm->count; 438 int error; 439 440 if (index >= 256 || count > 256 - index) 441 return (EINVAL); 442 443 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 444 if (error) 445 return (error); 446 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 447 if (error) 448 return (error); 449 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 450 if (error) 451 return (error); 452 return (0); 453 } 454 455 int 456 machfb_putcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm) 457 { 458 u_int index = cm->index; 459 u_int count = cm->count; 460 u_int i; 461 int error; 462 u_char *r, *g, *b; 463 464 if (index >= 256 || count > 256 - index) 465 return (EINVAL); 466 467 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 468 return (error); 469 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 470 return (error); 471 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 472 return (error); 473 474 r = &sc->sc_cmap_red[index]; 475 g = &sc->sc_cmap_green[index]; 476 b = &sc->sc_cmap_blue[index]; 477 478 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff); 479 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index); 480 for (i = 0; i < count; i++) { 481 bus_space_write_1(sc->sc_regt, sc->sc_regh, 482 M64_DAC_DATA, *r); 483 bus_space_write_1(sc->sc_regt, sc->sc_regh, 484 M64_DAC_DATA, *g); 485 bus_space_write_1(sc->sc_regt, sc->sc_regh, 486 M64_DAC_DATA, *b); 487 r++, g++, b++; 488 } 489 return (0); 490 } 491 492 void 493 machfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 494 { 495 struct machfb_softc *sc = v; 496 497 sc->sc_cmap_red[index] = r; 498 sc->sc_cmap_green[index] = g; 499 sc->sc_cmap_blue[index] = b; 500 501 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff); 502 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index); 503 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, r); 504 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, g); 505 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, b); 506 } 507 508 /* 509 * Accelerated routines. 510 */ 511 512 int 513 machfb_copycols(void *cookie, int row, int src, int dst, int num) 514 { 515 struct rasops_info *ri = cookie; 516 struct machfb_softc *sc = ri->ri_hw; 517 518 num *= ri->ri_font->fontwidth; 519 src *= ri->ri_font->fontwidth; 520 dst *= ri->ri_font->fontwidth; 521 row *= ri->ri_font->fontheight; 522 523 machfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 524 ri->ri_xorigin + dst, ri->ri_yorigin + row, 525 num, ri->ri_font->fontheight); 526 527 return 0; 528 } 529 530 int 531 machfb_erasecols(void *cookie, int row, int col, int num, long attr) 532 { 533 struct rasops_info *ri = cookie; 534 struct machfb_softc *sc = ri->ri_hw; 535 int bg, fg; 536 537 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 538 539 row *= ri->ri_font->fontheight; 540 col *= ri->ri_font->fontwidth; 541 num *= ri->ri_font->fontwidth; 542 543 machfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 544 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 545 546 return 0; 547 } 548 549 int 550 machfb_copyrows(void *cookie, int src, int dst, int num) 551 { 552 struct rasops_info *ri = cookie; 553 struct machfb_softc *sc = ri->ri_hw; 554 555 num *= ri->ri_font->fontheight; 556 src *= ri->ri_font->fontheight; 557 dst *= ri->ri_font->fontheight; 558 559 machfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 560 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 561 562 return 0; 563 } 564 565 int 566 machfb_eraserows(void *cookie, int row, int num, long attr) 567 { 568 struct rasops_info *ri = cookie; 569 struct machfb_softc *sc = ri->ri_hw; 570 int bg, fg; 571 int x, y, w; 572 573 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 574 575 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 576 num = ri->ri_height; 577 x = y = 0; 578 w = ri->ri_width; 579 } else { 580 num *= ri->ri_font->fontheight; 581 x = ri->ri_xorigin; 582 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 583 w = ri->ri_emuwidth; 584 } 585 machfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 586 587 return 0; 588 } 589 590 void 591 machfb_init(struct machfb_softc *sc) 592 { 593 uint32_t reg; 594 595 /* Reset engine. */ 596 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL); 597 reg &= ~M64_GEN_GUI_EN; 598 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg); 599 600 /* Enable engine. */ 601 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL); 602 reg &= M64_GEN_GUI_EN; 603 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg); 604 605 /* Clearing any FIFO or host errors. */ 606 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL); 607 reg |= M64_BUS_HOST_ERR_ACK | M64_BUS_FIFO_ERR_ACK; 608 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL, reg); 609 610 machfb_wait_fifo(sc, 14); 611 612 bus_space_write_4(sc->sc_regt, sc->sc_regh, 613 M64_CONTEXT_MASK, 0xffffffff); 614 615 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_OFF_PITCH, 616 (sc->sc_sunfb.sf_linebytes / 8) << 22); 617 618 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_Y_X, 0); 619 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_HEIGHT, 0); 620 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_ERR, 0); 621 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_INC, 0); 622 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_DEC, 0); 623 624 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, 625 M64_DST_LAST_PEL | M64_DST_X_LEFT_TO_RIGHT | 626 M64_DST_Y_TOP_TO_BOTTOM); 627 628 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_OFF_PITCH, 629 (sc->sc_sunfb.sf_linebytes / 8) << 22); 630 631 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X, 0); 632 bus_space_write_4(sc->sc_regt, sc->sc_regh, 633 M64_SRC_HEIGHT1_WIDTH1, 1); 634 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X_START, 0); 635 bus_space_write_4(sc->sc_regt, sc->sc_regh, 636 M64_SRC_HEIGHT2_WIDTH2, 1); 637 638 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_CNTL, 639 M64_SRC_LINE_X_LEFT_TO_RIGHT); 640 641 machfb_wait_fifo(sc, 13); 642 643 /* Host attributes. */ 644 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_HOST_CNTL, 0); 645 646 /* Pattern attributes. */ 647 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG0, 0); 648 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG1, 0); 649 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_CNTL, 0); 650 651 /* Scissors. */ 652 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_LEFT, 0); 653 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_TOP, 0); 654 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_BOTTOM, 655 sc->sc_sunfb.sf_height - 1); 656 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_RIGHT, 657 sc->sc_sunfb.sf_linebytes - 1); 658 659 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_BKGD_CLR, 0); 660 bus_space_write_4(sc->sc_regt, sc->sc_regh, 661 M64_DP_FRGD_CLR, 0xffffffff); 662 bus_space_write_4(sc->sc_regt, sc->sc_regh, 663 M64_DP_WRITE_MASK, 0xffffffff); 664 bus_space_write_4(sc->sc_regt, sc->sc_regh, 665 M64_DP_MIX, (M64_MIX_SRC << 16) | M64_MIX_DST); 666 667 bus_space_write_4(sc->sc_regt, sc->sc_regh, 668 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR); 669 670 machfb_wait_fifo(sc, 3); 671 672 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CLR, 0); 673 bus_space_write_4(sc->sc_regt, sc->sc_regh, 674 M64_CLR_CMP_MASK, 0xffffffff); 675 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 676 677 machfb_wait_fifo(sc, 3); 678 679 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_PIX_WIDTH, 680 M64_HOST_8BPP | M64_SRC_8BPP | M64_DST_8BPP); 681 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_CHAIN_MASK, 682 M64_DP_CHAIN_8BPP); 683 684 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GUI_TRAJ_CNTL, 685 M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM); 686 687 machfb_wait(sc); 688 } 689 690 int 691 machfb_wait_fifo(struct machfb_softc *sc, int v) 692 { 693 int i; 694 695 for (i = 1000000; i != 0; i--) { 696 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh, 697 M64_FIFO_STAT) & M64_FIFO_STAT_MASK) <= (0x8000 >> v)) 698 break; 699 DELAY(1); 700 } 701 702 return i; 703 } 704 705 int 706 machfb_wait(struct machfb_softc *sc) 707 { 708 int i; 709 710 machfb_wait_fifo(sc, 16); 711 for (i = 1000000; i != 0; i--) { 712 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh, 713 M64_GUI_STAT) & M64_GUI_ACTIVE) == 0) 714 break; 715 DELAY(1); 716 } 717 718 return i; 719 } 720 721 void 722 machfb_copyrect(struct machfb_softc *sc, int sx, int sy, int dx, int dy, 723 int w, int h) 724 { 725 uint32_t dest_ctl = 0; 726 727 machfb_wait_fifo(sc, 10); 728 729 bus_space_write_4(sc->sc_regt, sc->sc_regh, 730 M64_DP_WRITE_MASK, 0xff); 731 bus_space_write_4(sc->sc_regt, sc->sc_regh, 732 M64_DP_SRC, M64_FRGD_SRC_BLIT); 733 bus_space_write_4(sc->sc_regt, sc->sc_regh, 734 M64_DP_MIX, M64_MIX_SRC << 16); 735 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 736 if (dy < sy) { 737 dest_ctl = M64_DST_Y_TOP_TO_BOTTOM; 738 } else { 739 sy += h - 1; 740 dy += h - 1; 741 dest_ctl = M64_DST_Y_BOTTOM_TO_TOP; 742 } 743 if (dx < sx) { 744 dest_ctl |= M64_DST_X_LEFT_TO_RIGHT; 745 bus_space_write_4(sc->sc_regt, sc->sc_regh, 746 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT); 747 } else { 748 dest_ctl |= M64_DST_X_RIGHT_TO_LEFT; 749 sx += w - 1; 750 dx += w - 1; 751 bus_space_write_4(sc->sc_regt, sc->sc_regh, 752 M64_SRC_CNTL, M64_SRC_LINE_X_RIGHT_TO_LEFT); 753 } 754 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, dest_ctl); 755 756 bus_space_write_4(sc->sc_regt, sc->sc_regh, 757 M64_SRC_Y_X, M64_COORDS(sx, sy)); 758 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w); 759 bus_space_write_4(sc->sc_regt, sc->sc_regh, 760 M64_DST_Y_X, M64_COORDS(dx, dy)); 761 bus_space_write_4(sc->sc_regt, sc->sc_regh, 762 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h)); 763 764 machfb_wait(sc); 765 } 766 767 void 768 machfb_fillrect(struct machfb_softc *sc, int x, int y, int w, int h, int color) 769 { 770 machfb_wait_fifo(sc, 11); 771 772 bus_space_write_4(sc->sc_regt, sc->sc_regh, 773 M64_DP_WRITE_MASK, 0xff); 774 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_FRGD_CLR, color); 775 bus_space_write_4(sc->sc_regt, sc->sc_regh, 776 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR); 777 bus_space_write_4(sc->sc_regt, sc->sc_regh, 778 M64_DP_MIX, M64_MIX_SRC << 16); 779 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 780 bus_space_write_4(sc->sc_regt, sc->sc_regh, 781 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT); 782 bus_space_write_4(sc->sc_regt, sc->sc_regh, 783 M64_DST_CNTL, M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM); 784 785 bus_space_write_4(sc->sc_regt, sc->sc_regh, 786 M64_SRC_Y_X, M64_COORDS(x, y)); 787 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w); 788 bus_space_write_4(sc->sc_regt, sc->sc_regh, 789 M64_DST_Y_X, M64_COORDS(x, y)); 790 bus_space_write_4(sc->sc_regt, sc->sc_regh, 791 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h)); 792 793 machfb_wait(sc); 794 } 795