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