1 /* $OpenBSD: machfb.c,v 1.4 2009/06/03 03:05:30 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 void machfb_copycols(void *, int, int, int, int); 226 void machfb_erasecols(void *, int, int, int, long); 227 void machfb_copyrows(void *, int, int, int); 228 void 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 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor); 340 break; 341 case WSDISPLAYIO_GINFO: 342 wdf = (void *)data; 343 wdf->height = sc->sc_sunfb.sf_height; 344 wdf->width = sc->sc_sunfb.sf_width; 345 wdf->depth = sc->sc_sunfb.sf_depth; 346 wdf->cmsize = 256; 347 break; 348 case WSDISPLAYIO_LINEBYTES: 349 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 350 break; 351 352 case WSDISPLAYIO_GETCMAP: 353 return machfb_getcmap(sc, (struct wsdisplay_cmap *)data); 354 case WSDISPLAYIO_PUTCMAP: 355 return machfb_putcmap(sc, (struct wsdisplay_cmap *)data); 356 357 case WSDISPLAYIO_GPCIID: 358 sel = (struct pcisel *)data; 359 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); 360 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); 361 sel->pc_func = PCITAG_FUN(sc->sc_pcitag); 362 break; 363 364 case WSDISPLAYIO_SVIDEO: 365 case WSDISPLAYIO_GVIDEO: 366 break; 367 368 case WSDISPLAYIO_GCURPOS: 369 case WSDISPLAYIO_SCURPOS: 370 case WSDISPLAYIO_GCURMAX: 371 case WSDISPLAYIO_GCURSOR: 372 case WSDISPLAYIO_SCURSOR: 373 default: 374 return -1; /* not supported yet */ 375 } 376 377 return (0); 378 } 379 380 paddr_t 381 machfb_mmap(void *v, off_t off, int prot) 382 { 383 struct machfb_softc *sc = v; 384 385 if (off & PGOFSET) 386 return (-1); 387 388 switch (sc->sc_mode) { 389 case WSDISPLAYIO_MODE_MAPPED: 390 #ifdef APERTURE 391 if (allowaperture == 0) 392 return (-1); 393 #endif 394 395 if (sc->sc_mmiosize == 0) 396 return (-1); 397 398 if (off >= sc->sc_membase && 399 off < (sc->sc_membase + sc->sc_memsize)) 400 return (bus_space_mmap(sc->sc_memt, 401 sc->sc_membase, off - sc->sc_membase, 402 prot, BUS_SPACE_MAP_LINEAR)); 403 404 if (off >= sc->sc_mmiobase && 405 off < (sc->sc_mmiobase + sc->sc_mmiosize)) 406 return (bus_space_mmap(sc->sc_mmiot, 407 sc->sc_mmiobase, off - sc->sc_mmiobase, 408 prot, BUS_SPACE_MAP_LINEAR)); 409 break; 410 411 case WSDISPLAYIO_MODE_DUMBFB: 412 if (off >= 0 && off < sc->sc_memsize) 413 return (bus_space_mmap(sc->sc_memt, sc->sc_membase, 414 off, prot, BUS_SPACE_MAP_LINEAR)); 415 break; 416 } 417 418 return (-1); 419 } 420 421 int 422 machfb_is_console(int node) 423 { 424 extern int fbnode; 425 426 return (fbnode == node); 427 } 428 429 int 430 machfb_getcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm) 431 { 432 u_int index = cm->index; 433 u_int count = cm->count; 434 int error; 435 436 if (index >= 256 || count > 256 - index) 437 return (EINVAL); 438 439 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 440 if (error) 441 return (error); 442 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 443 if (error) 444 return (error); 445 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 446 if (error) 447 return (error); 448 return (0); 449 } 450 451 int 452 machfb_putcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm) 453 { 454 u_int index = cm->index; 455 u_int count = cm->count; 456 u_int i; 457 int error; 458 u_char *r, *g, *b; 459 460 if (index >= 256 || count > 256 - index) 461 return (EINVAL); 462 463 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0) 464 return (error); 465 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0) 466 return (error); 467 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0) 468 return (error); 469 470 r = &sc->sc_cmap_red[index]; 471 g = &sc->sc_cmap_green[index]; 472 b = &sc->sc_cmap_blue[index]; 473 474 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff); 475 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index); 476 for (i = 0; i < count; i++) { 477 bus_space_write_1(sc->sc_regt, sc->sc_regh, 478 M64_DAC_DATA, *r); 479 bus_space_write_1(sc->sc_regt, sc->sc_regh, 480 M64_DAC_DATA, *g); 481 bus_space_write_1(sc->sc_regt, sc->sc_regh, 482 M64_DAC_DATA, *b); 483 r++, g++, b++; 484 } 485 return (0); 486 } 487 488 void 489 machfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 490 { 491 struct machfb_softc *sc = v; 492 493 sc->sc_cmap_red[index] = r; 494 sc->sc_cmap_green[index] = g; 495 sc->sc_cmap_blue[index] = b; 496 497 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff); 498 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index); 499 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, r); 500 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, g); 501 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, b); 502 } 503 504 /* 505 * Accelerated routines. 506 */ 507 508 void 509 machfb_copycols(void *cookie, int row, int src, int dst, int num) 510 { 511 struct rasops_info *ri = cookie; 512 struct machfb_softc *sc = ri->ri_hw; 513 514 num *= ri->ri_font->fontwidth; 515 src *= ri->ri_font->fontwidth; 516 dst *= ri->ri_font->fontwidth; 517 row *= ri->ri_font->fontheight; 518 519 machfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, 520 ri->ri_xorigin + dst, ri->ri_yorigin + row, 521 num, ri->ri_font->fontheight); 522 } 523 524 void 525 machfb_erasecols(void *cookie, int row, int col, int num, long attr) 526 { 527 struct rasops_info *ri = cookie; 528 struct machfb_softc *sc = ri->ri_hw; 529 int bg, fg; 530 531 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 532 533 row *= ri->ri_font->fontheight; 534 col *= ri->ri_font->fontwidth; 535 num *= ri->ri_font->fontwidth; 536 537 machfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, 538 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); 539 } 540 541 void 542 machfb_copyrows(void *cookie, int src, int dst, int num) 543 { 544 struct rasops_info *ri = cookie; 545 struct machfb_softc *sc = ri->ri_hw; 546 547 num *= ri->ri_font->fontheight; 548 src *= ri->ri_font->fontheight; 549 dst *= ri->ri_font->fontheight; 550 551 machfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, 552 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); 553 } 554 555 void 556 machfb_eraserows(void *cookie, int row, int num, long attr) 557 { 558 struct rasops_info *ri = cookie; 559 struct machfb_softc *sc = ri->ri_hw; 560 int bg, fg; 561 int x, y, w; 562 563 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 564 565 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { 566 num = ri->ri_height; 567 x = y = 0; 568 w = ri->ri_width; 569 } else { 570 num *= ri->ri_font->fontheight; 571 x = ri->ri_xorigin; 572 y = ri->ri_yorigin + row * ri->ri_font->fontheight; 573 w = ri->ri_emuwidth; 574 } 575 machfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); 576 } 577 578 void 579 machfb_init(struct machfb_softc *sc) 580 { 581 uint32_t reg; 582 583 /* Reset engine. */ 584 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL); 585 reg &= ~M64_GEN_GUI_EN; 586 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg); 587 588 /* Enable engine. */ 589 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL); 590 reg &= M64_GEN_GUI_EN; 591 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg); 592 593 /* Clearing any FIFO or host errors. */ 594 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL); 595 reg |= M64_BUS_HOST_ERR_ACK | M64_BUS_FIFO_ERR_ACK; 596 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL, reg); 597 598 machfb_wait_fifo(sc, 14); 599 600 bus_space_write_4(sc->sc_regt, sc->sc_regh, 601 M64_CONTEXT_MASK, 0xffffffff); 602 603 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_OFF_PITCH, 604 (sc->sc_sunfb.sf_linebytes / 8) << 22); 605 606 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_Y_X, 0); 607 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_HEIGHT, 0); 608 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_ERR, 0); 609 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_INC, 0); 610 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_DEC, 0); 611 612 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, 613 M64_DST_LAST_PEL | M64_DST_X_LEFT_TO_RIGHT | 614 M64_DST_Y_TOP_TO_BOTTOM); 615 616 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_OFF_PITCH, 617 (sc->sc_sunfb.sf_linebytes / 8) << 22); 618 619 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X, 0); 620 bus_space_write_4(sc->sc_regt, sc->sc_regh, 621 M64_SRC_HEIGHT1_WIDTH1, 1); 622 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X_START, 0); 623 bus_space_write_4(sc->sc_regt, sc->sc_regh, 624 M64_SRC_HEIGHT2_WIDTH2, 1); 625 626 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_CNTL, 627 M64_SRC_LINE_X_LEFT_TO_RIGHT); 628 629 machfb_wait_fifo(sc, 13); 630 631 /* Host attributes. */ 632 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_HOST_CNTL, 0); 633 634 /* Pattern attributes. */ 635 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG0, 0); 636 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG1, 0); 637 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_CNTL, 0); 638 639 /* Scissors. */ 640 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_LEFT, 0); 641 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_TOP, 0); 642 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_BOTTOM, 643 sc->sc_sunfb.sf_height - 1); 644 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_RIGHT, 645 sc->sc_sunfb.sf_linebytes - 1); 646 647 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_BKGD_CLR, 0); 648 bus_space_write_4(sc->sc_regt, sc->sc_regh, 649 M64_DP_FRGD_CLR, 0xffffffff); 650 bus_space_write_4(sc->sc_regt, sc->sc_regh, 651 M64_DP_WRITE_MASK, 0xffffffff); 652 bus_space_write_4(sc->sc_regt, sc->sc_regh, 653 M64_DP_MIX, (M64_MIX_SRC << 16) | M64_MIX_DST); 654 655 bus_space_write_4(sc->sc_regt, sc->sc_regh, 656 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR); 657 658 machfb_wait_fifo(sc, 3); 659 660 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CLR, 0); 661 bus_space_write_4(sc->sc_regt, sc->sc_regh, 662 M64_CLR_CMP_MASK, 0xffffffff); 663 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 664 665 machfb_wait_fifo(sc, 3); 666 667 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_PIX_WIDTH, 668 M64_HOST_8BPP | M64_SRC_8BPP | M64_DST_8BPP); 669 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_CHAIN_MASK, 670 M64_DP_CHAIN_8BPP); 671 672 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GUI_TRAJ_CNTL, 673 M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM); 674 675 machfb_wait(sc); 676 } 677 678 int 679 machfb_wait_fifo(struct machfb_softc *sc, int v) 680 { 681 int i; 682 683 for (i = 1000000; i != 0; i--) { 684 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh, 685 M64_FIFO_STAT) & M64_FIFO_STAT_MASK) <= (0x8000 >> v)) 686 break; 687 DELAY(1); 688 } 689 690 return i; 691 } 692 693 int 694 machfb_wait(struct machfb_softc *sc) 695 { 696 int i; 697 698 machfb_wait_fifo(sc, 16); 699 for (i = 1000000; i != 0; i--) { 700 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh, 701 M64_GUI_STAT) & M64_GUI_ACTIVE) == 0) 702 break; 703 DELAY(1); 704 } 705 706 return i; 707 } 708 709 void 710 machfb_copyrect(struct machfb_softc *sc, int sx, int sy, int dx, int dy, 711 int w, int h) 712 { 713 uint32_t dest_ctl = 0; 714 715 machfb_wait_fifo(sc, 10); 716 717 bus_space_write_4(sc->sc_regt, sc->sc_regh, 718 M64_DP_WRITE_MASK, 0xff); 719 bus_space_write_4(sc->sc_regt, sc->sc_regh, 720 M64_DP_SRC, M64_FRGD_SRC_BLIT); 721 bus_space_write_4(sc->sc_regt, sc->sc_regh, 722 M64_DP_MIX, M64_MIX_SRC << 16); 723 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 724 if (dy < sy) { 725 dest_ctl = M64_DST_Y_TOP_TO_BOTTOM; 726 } else { 727 sy += h - 1; 728 dy += h - 1; 729 dest_ctl = M64_DST_Y_BOTTOM_TO_TOP; 730 } 731 if (dx < sx) { 732 dest_ctl |= M64_DST_X_LEFT_TO_RIGHT; 733 bus_space_write_4(sc->sc_regt, sc->sc_regh, 734 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT); 735 } else { 736 dest_ctl |= M64_DST_X_RIGHT_TO_LEFT; 737 sx += w - 1; 738 dx += w - 1; 739 bus_space_write_4(sc->sc_regt, sc->sc_regh, 740 M64_SRC_CNTL, M64_SRC_LINE_X_RIGHT_TO_LEFT); 741 } 742 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, dest_ctl); 743 744 bus_space_write_4(sc->sc_regt, sc->sc_regh, 745 M64_SRC_Y_X, M64_COORDS(sx, sy)); 746 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w); 747 bus_space_write_4(sc->sc_regt, sc->sc_regh, 748 M64_DST_Y_X, M64_COORDS(dx, dy)); 749 bus_space_write_4(sc->sc_regt, sc->sc_regh, 750 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h)); 751 752 machfb_wait(sc); 753 } 754 755 void 756 machfb_fillrect(struct machfb_softc *sc, int x, int y, int w, int h, int color) 757 { 758 machfb_wait_fifo(sc, 11); 759 760 bus_space_write_4(sc->sc_regt, sc->sc_regh, 761 M64_DP_WRITE_MASK, 0xff); 762 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_FRGD_CLR, color); 763 bus_space_write_4(sc->sc_regt, sc->sc_regh, 764 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR); 765 bus_space_write_4(sc->sc_regt, sc->sc_regh, 766 M64_DP_MIX, M64_MIX_SRC << 16); 767 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0); 768 bus_space_write_4(sc->sc_regt, sc->sc_regh, 769 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT); 770 bus_space_write_4(sc->sc_regt, sc->sc_regh, 771 M64_DST_CNTL, M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM); 772 773 bus_space_write_4(sc->sc_regt, sc->sc_regh, 774 M64_SRC_Y_X, M64_COORDS(x, y)); 775 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w); 776 bus_space_write_4(sc->sc_regt, sc->sc_regh, 777 M64_DST_Y_X, M64_COORDS(x, y)); 778 bus_space_write_4(sc->sc_regt, sc->sc_regh, 779 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h)); 780 781 machfb_wait(sc); 782 } 783