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