1 /* $OpenBSD: creator.c,v 1.39 2007/03/06 23:10:26 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/device.h> 34 #include <sys/conf.h> 35 #include <sys/timeout.h> 36 37 #include <machine/bus.h> 38 #include <machine/autoconf.h> 39 #include <machine/openfirm.h> 40 41 #include <dev/wscons/wsconsio.h> 42 #include <dev/wscons/wsdisplayvar.h> 43 #include <dev/rasops/rasops.h> 44 #include <machine/fbvar.h> 45 46 #include <sparc64/dev/creatorreg.h> 47 #include <sparc64/dev/creatorvar.h> 48 49 int creator_match(struct device *, void *, void *); 50 void creator_attach(struct device *, struct device *, void *); 51 int creator_ioctl(void *, u_long, caddr_t, int, struct proc *); 52 int creator_alloc_screen(void *, const struct wsscreen_descr *, void **, 53 int *, int *, long *); 54 void creator_free_screen(void *, void *); 55 int creator_show_screen(void *, void *, int, void (*cb)(void *, int, int), 56 void *); 57 paddr_t creator_mmap(void *, off_t, int); 58 void creator_ras_fifo_wait(struct creator_softc *, int); 59 void creator_ras_wait(struct creator_softc *); 60 void creator_ras_init(struct creator_softc *); 61 void creator_ras_copyrows(void *, int, int, int); 62 void creator_ras_erasecols(void *, int, int, int, long int); 63 void creator_ras_eraserows(void *, int, int, long int); 64 void creator_ras_fill(struct creator_softc *); 65 void creator_ras_setfg(struct creator_softc *, int32_t); 66 int creator_setcursor(struct creator_softc *, struct wsdisplay_cursor *); 67 int creator_updatecursor(struct creator_softc *, u_int); 68 void creator_curs_enable(struct creator_softc *, u_int); 69 70 struct wsdisplay_accessops creator_accessops = { 71 creator_ioctl, 72 creator_mmap, 73 creator_alloc_screen, 74 creator_free_screen, 75 creator_show_screen, 76 NULL, /* load font */ 77 NULL, /* scrollback */ 78 NULL, /* getchar */ 79 NULL, /* burner */ 80 }; 81 82 struct cfdriver creator_cd = { 83 NULL, "creator", DV_DULL 84 }; 85 86 struct cfattach creator_ca = { 87 sizeof(struct creator_softc), creator_match, creator_attach 88 }; 89 90 int 91 creator_match(parent, match, aux) 92 struct device *parent; 93 void *match, *aux; 94 { 95 struct mainbus_attach_args *ma = aux; 96 97 if (strcmp(ma->ma_name, "SUNW,ffb") == 0 || 98 strcmp(ma->ma_name, "SUNW,afb") == 0) 99 return (1); 100 return (0); 101 } 102 103 void 104 creator_attach(parent, self, aux) 105 struct device *parent, *self; 106 void *aux; 107 { 108 struct creator_softc *sc = (struct creator_softc *)self; 109 struct mainbus_attach_args *ma = aux; 110 extern int fbnode; 111 int i, nregs; 112 char *model; 113 int btype; 114 115 sc->sc_bt = ma->ma_bustag; 116 117 nregs = min(ma->ma_nreg, FFB_NREGS); 118 119 if (nregs <= FFB_REG_DFB24) { 120 printf(": no dfb24 regs found\n"); 121 return; 122 } 123 124 if (bus_space_map(sc->sc_bt, ma->ma_reg[FFB_REG_DFB24].ur_paddr, 125 ma->ma_reg[FFB_REG_DFB24].ur_len, BUS_SPACE_MAP_LINEAR, 126 &sc->sc_pixel_h)) { 127 printf(": failed to map dfb24\n"); 128 return; 129 } 130 131 if (bus_space_map(sc->sc_bt, ma->ma_reg[FFB_REG_FBC].ur_paddr, 132 ma->ma_reg[FFB_REG_FBC].ur_len, 0, &sc->sc_fbc_h)) { 133 printf(": failed to map fbc\n"); 134 goto unmap_dfb24; 135 } 136 137 if (bus_space_map(sc->sc_bt, ma->ma_reg[FFB_REG_DAC].ur_paddr, 138 ma->ma_reg[FFB_REG_DAC].ur_len, 0, &sc->sc_dac_h)) { 139 printf(": failed to map dac\n"); 140 goto unmap_fbc; 141 } 142 143 for (i = 0; i < nregs; i++) { 144 sc->sc_addrs[i] = ma->ma_reg[i].ur_paddr; 145 sc->sc_sizes[i] = ma->ma_reg[i].ur_len; 146 } 147 sc->sc_nreg = nregs; 148 149 sc->sc_console = (fbnode == ma->ma_node); 150 sc->sc_node = ma->ma_node; 151 152 if (strcmp(ma->ma_name, "SUNW,afb") == 0) 153 sc->sc_type = FFB_AFB; 154 155 /* 156 * Prom reports only the length of the fcode header, we need 157 * the whole thing. 158 */ 159 sc->sc_sizes[0] = 0x00400000; 160 161 if (sc->sc_type == FFB_CREATOR) { 162 btype = getpropint(sc->sc_node, "board_type", 0); 163 if ((btype & 7) == 3) 164 printf(": Creator3D"); 165 else 166 printf(": Creator"); 167 } else 168 printf(": Elite3D"); 169 170 model = getpropstring(sc->sc_node, "model"); 171 if (model == NULL || strlen(model) == 0) 172 model = "unknown"; 173 174 DAC_WRITE(sc, FFB_DAC_TYPE, DAC_TYPE_GETREV); 175 sc->sc_dacrev = DAC_READ(sc, FFB_DAC_VALUE) >> 28; 176 177 printf(", model %s, dac %u\n", model, sc->sc_dacrev); 178 179 if (sc->sc_type == FFB_AFB) 180 sc->sc_dacrev = 10; 181 182 fb_setsize(&sc->sc_sunfb, 32, 1152, 900, sc->sc_node, 0); 183 /* linesize has a fixed value, compensate */ 184 sc->sc_sunfb.sf_linebytes = 8192; 185 sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * 8192; 186 187 sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bt, 188 sc->sc_pixel_h); 189 sc->sc_sunfb.sf_ro.ri_hw = sc; 190 fbwscons_init(&sc->sc_sunfb, sc->sc_console ? 0 : RI_CLEAR); 191 192 if ((sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags & CREATOR_CFFLAG_NOACCEL) 193 == 0) { 194 sc->sc_sunfb.sf_ro.ri_ops.eraserows = creator_ras_eraserows; 195 sc->sc_sunfb.sf_ro.ri_ops.erasecols = creator_ras_erasecols; 196 sc->sc_sunfb.sf_ro.ri_ops.copyrows = creator_ras_copyrows; 197 creator_ras_init(sc); 198 } 199 200 if (sc->sc_console) { 201 fbwscons_console_init(&sc->sc_sunfb, -1); 202 } 203 204 fbwscons_attach(&sc->sc_sunfb, &creator_accessops, sc->sc_console); 205 return; 206 207 unmap_fbc: 208 bus_space_unmap(sc->sc_bt, sc->sc_fbc_h, 209 ma->ma_reg[FFB_REG_FBC].ur_len); 210 unmap_dfb24: 211 bus_space_unmap(sc->sc_bt, sc->sc_pixel_h, 212 ma->ma_reg[FFB_REG_DFB24].ur_len); 213 } 214 215 int 216 creator_ioctl(v, cmd, data, flags, p) 217 void *v; 218 u_long cmd; 219 caddr_t data; 220 int flags; 221 struct proc *p; 222 { 223 struct creator_softc *sc = v; 224 struct wsdisplay_cursor *curs; 225 struct wsdisplay_fbinfo *wdf; 226 struct wsdisplay_curpos *pos; 227 u_char r[2], g[2], b[2]; 228 int error; 229 230 switch (cmd) { 231 case WSDISPLAYIO_GTYPE: 232 *(u_int *)data = WSDISPLAY_TYPE_SUNFFB; 233 break; 234 case WSDISPLAYIO_SMODE: 235 sc->sc_mode = *(u_int *)data; 236 break; 237 case WSDISPLAYIO_GINFO: 238 wdf = (void *)data; 239 wdf->height = sc->sc_sunfb.sf_height; 240 wdf->width = sc->sc_sunfb.sf_width; 241 wdf->depth = 32; 242 wdf->cmsize = 0; 243 break; 244 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 245 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32; 246 break; 247 case WSDISPLAYIO_LINEBYTES: 248 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 249 break; 250 case WSDISPLAYIO_GCURSOR: 251 curs = (struct wsdisplay_cursor *)data; 252 if (curs->which & WSDISPLAY_CURSOR_DOCUR) 253 curs->enable = sc->sc_curs_enabled; 254 if (curs->which & WSDISPLAY_CURSOR_DOPOS) { 255 curs->pos.x = sc->sc_curs_pos.x; 256 curs->pos.y = sc->sc_curs_pos.y; 257 } 258 if (curs->which & WSDISPLAY_CURSOR_DOHOT) { 259 curs->hot.x = sc->sc_curs_hot.x; 260 curs->hot.y = sc->sc_curs_hot.y; 261 } 262 if (curs->which & WSDISPLAY_CURSOR_DOCMAP) { 263 curs->cmap.index = 0; 264 curs->cmap.count = 2; 265 r[0] = sc->sc_curs_fg >> 0; 266 g[0] = sc->sc_curs_fg >> 8; 267 b[0] = sc->sc_curs_fg >> 16; 268 r[1] = sc->sc_curs_bg >> 0; 269 g[1] = sc->sc_curs_bg >> 8; 270 b[1] = sc->sc_curs_bg >> 16; 271 error = copyout(r, curs->cmap.red, sizeof(r)); 272 if (error) 273 return (error); 274 error = copyout(g, curs->cmap.green, sizeof(g)); 275 if (error) 276 return (error); 277 error = copyout(b, curs->cmap.blue, sizeof(b)); 278 if (error) 279 return (error); 280 } 281 if (curs->which & WSDISPLAY_CURSOR_DOSHAPE) { 282 size_t l; 283 284 curs->size.x = sc->sc_curs_size.x; 285 curs->size.y = sc->sc_curs_size.y; 286 l = (sc->sc_curs_size.x * sc->sc_curs_size.y) / NBBY; 287 error = copyout(sc->sc_curs_image, curs->image, l); 288 if (error) 289 return (error); 290 error = copyout(sc->sc_curs_mask, curs->mask, l); 291 if (error) 292 return (error); 293 } 294 break; 295 case WSDISPLAYIO_SCURPOS: 296 pos = (struct wsdisplay_curpos *)data; 297 sc->sc_curs_pos.x = pos->x; 298 sc->sc_curs_pos.y = pos->y; 299 creator_updatecursor(sc, WSDISPLAY_CURSOR_DOPOS); 300 break; 301 case WSDISPLAYIO_GCURPOS: 302 pos = (struct wsdisplay_curpos *)data; 303 pos->x = sc->sc_curs_pos.x; 304 pos->y = sc->sc_curs_pos.y; 305 break; 306 case WSDISPLAYIO_SCURSOR: 307 curs = (struct wsdisplay_cursor *)data; 308 return (creator_setcursor(sc, curs)); 309 case WSDISPLAYIO_GCURMAX: 310 pos = (struct wsdisplay_curpos *)data; 311 pos->x = CREATOR_CURS_MAX; 312 pos->y = CREATOR_CURS_MAX; 313 break; 314 case WSDISPLAYIO_SVIDEO: 315 case WSDISPLAYIO_GVIDEO: 316 break; 317 318 case WSDISPLAYIO_GETCMAP: 319 case WSDISPLAYIO_PUTCMAP: 320 default: 321 return -1; /* not supported yet */ 322 } 323 324 return (0); 325 } 326 327 int 328 creator_setcursor(struct creator_softc *sc, struct wsdisplay_cursor *curs) 329 { 330 u_int8_t r[2], g[2], b[2], image[128], mask[128]; 331 int error; 332 size_t imcount; 333 334 /* 335 * Do stuff that can generate errors first, then we'll blast it 336 * all at once. 337 */ 338 if (curs->which & WSDISPLAY_CURSOR_DOCMAP) { 339 if (curs->cmap.count < 2) 340 return (EINVAL); 341 error = copyin(curs->cmap.red, r, sizeof(r)); 342 if (error) 343 return (error); 344 error = copyin(curs->cmap.green, g, sizeof(g)); 345 if (error) 346 return (error); 347 error = copyin(curs->cmap.blue, b, sizeof(b)); 348 if (error) 349 return (error); 350 } 351 352 if (curs->which & WSDISPLAY_CURSOR_DOSHAPE) { 353 if (curs->size.x > CREATOR_CURS_MAX || 354 curs->size.y > CREATOR_CURS_MAX) 355 return (EINVAL); 356 imcount = (curs->size.x * curs->size.y) / NBBY; 357 error = copyin(curs->image, image, imcount); 358 if (error) 359 return (error); 360 error = copyin(curs->mask, mask, imcount); 361 if (error) 362 return (error); 363 } 364 365 /* 366 * Ok, everything is in kernel space and sane, update state. 367 */ 368 369 if (curs->which & WSDISPLAY_CURSOR_DOCUR) 370 sc->sc_curs_enabled = curs->enable; 371 if (curs->which & WSDISPLAY_CURSOR_DOPOS) { 372 sc->sc_curs_pos.x = curs->pos.x; 373 sc->sc_curs_pos.y = curs->pos.y; 374 } 375 if (curs->which & WSDISPLAY_CURSOR_DOHOT) { 376 sc->sc_curs_hot.x = curs->hot.x; 377 sc->sc_curs_hot.y = curs->hot.y; 378 } 379 if (curs->which & WSDISPLAY_CURSOR_DOCMAP) { 380 sc->sc_curs_fg = ((r[0] << 0) | (g[0] << 8) | (b[0] << 16)); 381 sc->sc_curs_bg = ((r[1] << 0) | (g[1] << 8) | (b[1] << 16)); 382 } 383 if (curs->which & WSDISPLAY_CURSOR_DOSHAPE) { 384 sc->sc_curs_size.x = curs->size.x; 385 sc->sc_curs_size.y = curs->size.y; 386 bcopy(image, sc->sc_curs_image, imcount); 387 bcopy(mask, sc->sc_curs_mask, imcount); 388 } 389 390 creator_updatecursor(sc, curs->which); 391 392 return (0); 393 } 394 395 void 396 creator_curs_enable(struct creator_softc *sc, u_int ena) 397 { 398 u_int32_t v; 399 400 DAC_WRITE(sc, FFB_DAC_TYPE2, DAC_TYPE2_CURSENAB); 401 if (sc->sc_dacrev <= 2) 402 v = ena ? 3 : 0; 403 else 404 v = ena ? 0 : 3; 405 DAC_WRITE(sc, FFB_DAC_VALUE2, v); 406 } 407 408 int 409 creator_updatecursor(struct creator_softc *sc, u_int which) 410 { 411 creator_curs_enable(sc, 0); 412 413 if (which & WSDISPLAY_CURSOR_DOCMAP) { 414 DAC_WRITE(sc, FFB_DAC_TYPE2, DAC_TYPE2_CURSCMAP); 415 DAC_WRITE(sc, FFB_DAC_VALUE2, sc->sc_curs_fg); 416 DAC_WRITE(sc, FFB_DAC_VALUE2, sc->sc_curs_bg); 417 } 418 419 if (which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 420 u_int32_t x, y; 421 422 x = sc->sc_curs_pos.x + CREATOR_CURS_MAX - sc->sc_curs_hot.x; 423 y = sc->sc_curs_pos.y + CREATOR_CURS_MAX - sc->sc_curs_hot.y; 424 DAC_WRITE(sc, FFB_DAC_TYPE2, DAC_TYPE2_CURSPOS); 425 DAC_WRITE(sc, FFB_DAC_VALUE2, 426 ((x & 0xffff) << 16) | (y & 0xffff)); 427 } 428 429 if (which & WSDISPLAY_CURSOR_DOCUR) 430 creator_curs_enable(sc, sc->sc_curs_enabled); 431 432 return (0); 433 } 434 435 int 436 creator_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 437 void *v; 438 const struct wsscreen_descr *type; 439 void **cookiep; 440 int *curxp, *curyp; 441 long *attrp; 442 { 443 struct creator_softc *sc = v; 444 445 if (sc->sc_nscreens > 0) 446 return (ENOMEM); 447 448 *cookiep = &sc->sc_sunfb.sf_ro; 449 *curyp = 0; 450 *curxp = 0; 451 sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, 452 WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); 453 sc->sc_nscreens++; 454 return (0); 455 } 456 457 void 458 creator_free_screen(v, cookie) 459 void *v; 460 void *cookie; 461 { 462 struct creator_softc *sc = v; 463 464 sc->sc_nscreens--; 465 } 466 467 int 468 creator_show_screen(v, cookie, waitok, cb, cbarg) 469 void *v; 470 void *cookie; 471 int waitok; 472 void (*cb)(void *, int, int); 473 void *cbarg; 474 { 475 return (0); 476 } 477 478 const struct creator_mappings { 479 bus_addr_t uoff; 480 bus_addr_t poff; 481 bus_size_t ulen; 482 } creator_map[] = { 483 { FFB_VOFF_SFB8R, FFB_POFF_SFB8R, FFB_VLEN_SFB8R }, 484 { FFB_VOFF_SFB8G, FFB_POFF_SFB8G, FFB_VLEN_SFB8G }, 485 { FFB_VOFF_SFB8B, FFB_POFF_SFB8B, FFB_VLEN_SFB8B }, 486 { FFB_VOFF_SFB8X, FFB_POFF_SFB8X, FFB_VLEN_SFB8X }, 487 { FFB_VOFF_SFB32, FFB_POFF_SFB32, FFB_VLEN_SFB32 }, 488 { FFB_VOFF_SFB64, FFB_POFF_SFB64, FFB_VLEN_SFB64 }, 489 { FFB_VOFF_FBC_REGS, FFB_POFF_FBC_REGS, FFB_VLEN_FBC_REGS }, 490 { FFB_VOFF_BM_FBC_REGS, FFB_POFF_BM_FBC_REGS, FFB_VLEN_BM_FBC_REGS }, 491 { FFB_VOFF_DFB8R, FFB_POFF_DFB8R, FFB_VLEN_DFB8R }, 492 { FFB_VOFF_DFB8G, FFB_POFF_DFB8G, FFB_VLEN_DFB8G }, 493 { FFB_VOFF_DFB8B, FFB_POFF_DFB8B, FFB_VLEN_DFB8B }, 494 { FFB_VOFF_DFB8X, FFB_POFF_DFB8X, FFB_VLEN_DFB8X }, 495 { FFB_VOFF_DFB24, FFB_POFF_DFB24, FFB_VLEN_DFB24 }, 496 { FFB_VOFF_DFB32, FFB_POFF_DFB32, FFB_VLEN_DFB32 }, 497 { FFB_VOFF_DFB422A, FFB_POFF_DFB422A, FFB_VLEN_DFB422A }, 498 { FFB_VOFF_DFB422AD, FFB_POFF_DFB422AD, FFB_VLEN_DFB422AD }, 499 { FFB_VOFF_DFB24B, FFB_POFF_DFB24B, FFB_VLEN_DFB24B }, 500 { FFB_VOFF_DFB422B, FFB_POFF_DFB422B, FFB_VLEN_DFB422B }, 501 { FFB_VOFF_DFB422BD, FFB_POFF_DFB422BD, FFB_VLEN_DFB422BD }, 502 { FFB_VOFF_SFB16Z, FFB_POFF_SFB16Z, FFB_VLEN_SFB16Z }, 503 { FFB_VOFF_SFB8Z, FFB_POFF_SFB8Z, FFB_VLEN_SFB8Z }, 504 { FFB_VOFF_SFB422, FFB_POFF_SFB422, FFB_VLEN_SFB422 }, 505 { FFB_VOFF_SFB422D, FFB_POFF_SFB422D, FFB_VLEN_SFB422D }, 506 { FFB_VOFF_FBC_KREGS, FFB_POFF_FBC_KREGS, FFB_VLEN_FBC_KREGS }, 507 { FFB_VOFF_DAC, FFB_POFF_DAC, FFB_VLEN_DAC }, 508 { FFB_VOFF_PROM, FFB_POFF_PROM, FFB_VLEN_PROM }, 509 { FFB_VOFF_EXP, FFB_POFF_EXP, FFB_VLEN_EXP }, 510 }; 511 #define CREATOR_NMAPPINGS (sizeof(creator_map)/sizeof(creator_map[0])) 512 513 paddr_t 514 creator_mmap(vsc, off, prot) 515 void *vsc; 516 off_t off; 517 int prot; 518 { 519 paddr_t x; 520 struct creator_softc *sc = vsc; 521 int i; 522 523 switch (sc->sc_mode) { 524 case WSDISPLAYIO_MODE_MAPPED: 525 /* Turn virtual offset into physical offset */ 526 for (i = 0; i < CREATOR_NMAPPINGS; i++) { 527 if (off >= creator_map[i].uoff && 528 off < (creator_map[i].uoff + creator_map[i].ulen)) 529 break; 530 } 531 if (i == CREATOR_NMAPPINGS) 532 break; 533 534 off -= creator_map[i].uoff; 535 off += creator_map[i].poff; 536 off += sc->sc_addrs[0]; 537 538 /* Map based on physical offset */ 539 for (i = 0; i < sc->sc_nreg; i++) { 540 /* Before this set? */ 541 if (off < sc->sc_addrs[i]) 542 continue; 543 /* After this set? */ 544 if (off >= (sc->sc_addrs[i] + sc->sc_sizes[i])) 545 continue; 546 547 x = bus_space_mmap(sc->sc_bt, 0, off, prot, 548 BUS_SPACE_MAP_LINEAR); 549 return (x); 550 } 551 break; 552 case WSDISPLAYIO_MODE_DUMBFB: 553 if (sc->sc_nreg <= FFB_REG_DFB24) 554 break; 555 if (off >= 0 && off < sc->sc_sizes[FFB_REG_DFB24]) 556 return (bus_space_mmap(sc->sc_bt, 557 sc->sc_addrs[FFB_REG_DFB24], off, prot, 558 BUS_SPACE_MAP_LINEAR)); 559 break; 560 } 561 562 return (-1); 563 } 564 565 void 566 creator_ras_fifo_wait(sc, n) 567 struct creator_softc *sc; 568 int n; 569 { 570 int32_t cache = sc->sc_fifo_cache; 571 572 if (cache < n) { 573 do { 574 cache = FBC_READ(sc, FFB_FBC_UCSR); 575 cache = (cache & FBC_UCSR_FIFO_MASK) - 8; 576 } while (cache < n); 577 } 578 sc->sc_fifo_cache = cache - n; 579 } 580 581 void 582 creator_ras_wait(sc) 583 struct creator_softc *sc; 584 { 585 u_int32_t ucsr, r; 586 587 while (1) { 588 ucsr = FBC_READ(sc, FFB_FBC_UCSR); 589 if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0) 590 break; 591 r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL); 592 if (r != 0) 593 FBC_WRITE(sc, FFB_FBC_UCSR, r); 594 } 595 } 596 597 void 598 creator_ras_init(sc) 599 struct creator_softc *sc; 600 { 601 creator_ras_fifo_wait(sc, 7); 602 FBC_WRITE(sc, FFB_FBC_PPC, 603 FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | 604 FBC_PPC_APE_DIS | FBC_PPC_CS_CONST); 605 FBC_WRITE(sc, FFB_FBC_FBC, 606 FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH | 607 FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK); 608 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); 609 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); 610 FBC_WRITE(sc, FFB_FBC_PMASK, 0xffffffff); 611 FBC_WRITE(sc, FFB_FBC_FONTINC, 0x10000); 612 sc->sc_fg_cache = 0; 613 FBC_WRITE(sc, FFB_FBC_FG, sc->sc_fg_cache); 614 creator_ras_wait(sc); 615 } 616 617 void 618 creator_ras_eraserows(cookie, row, n, attr) 619 void *cookie; 620 int row, n; 621 long int attr; 622 { 623 struct rasops_info *ri = cookie; 624 struct creator_softc *sc = ri->ri_hw; 625 int bg, fg; 626 627 if (row < 0) { 628 n += row; 629 row = 0; 630 } 631 if (row + n > ri->ri_rows) 632 n = ri->ri_rows - row; 633 if (n <= 0) 634 return; 635 636 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 637 creator_ras_fill(sc); 638 creator_ras_setfg(sc, ri->ri_devcmap[bg]); 639 creator_ras_fifo_wait(sc, 4); 640 if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { 641 FBC_WRITE(sc, FFB_FBC_BY, 0); 642 FBC_WRITE(sc, FFB_FBC_BX, 0); 643 FBC_WRITE(sc, FFB_FBC_BH, ri->ri_height); 644 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_width); 645 } else { 646 row *= ri->ri_font->fontheight; 647 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); 648 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); 649 FBC_WRITE(sc, FFB_FBC_BH, n * ri->ri_font->fontheight); 650 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); 651 } 652 creator_ras_wait(sc); 653 } 654 655 void 656 creator_ras_erasecols(cookie, row, col, n, attr) 657 void *cookie; 658 int row, col, n; 659 long int attr; 660 { 661 struct rasops_info *ri = cookie; 662 struct creator_softc *sc = ri->ri_hw; 663 int fg, bg; 664 665 if ((row < 0) || (row >= ri->ri_rows)) 666 return; 667 if (col < 0) { 668 n += col; 669 col = 0; 670 } 671 if (col + n > ri->ri_cols) 672 n = ri->ri_cols - col; 673 if (n <= 0) 674 return; 675 n *= ri->ri_font->fontwidth; 676 col *= ri->ri_font->fontwidth; 677 row *= ri->ri_font->fontheight; 678 679 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 680 creator_ras_fill(sc); 681 creator_ras_setfg(sc, ri->ri_devcmap[bg]); 682 creator_ras_fifo_wait(sc, 4); 683 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); 684 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin + col); 685 FBC_WRITE(sc, FFB_FBC_BH, ri->ri_font->fontheight); 686 FBC_WRITE(sc, FFB_FBC_BW, n - 1); 687 creator_ras_wait(sc); 688 } 689 690 void 691 creator_ras_fill(sc) 692 struct creator_softc *sc; 693 { 694 creator_ras_fifo_wait(sc, 2); 695 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); 696 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); 697 creator_ras_wait(sc); 698 } 699 700 void 701 creator_ras_copyrows(cookie, src, dst, n) 702 void *cookie; 703 int src, dst, n; 704 { 705 struct rasops_info *ri = cookie; 706 struct creator_softc *sc = ri->ri_hw; 707 708 if (dst == src) 709 return; 710 if (src < 0) { 711 n += src; 712 src = 0; 713 } 714 if ((src + n) > ri->ri_rows) 715 n = ri->ri_rows - src; 716 if (dst < 0) { 717 n += dst; 718 dst = 0; 719 } 720 if ((dst + n) > ri->ri_rows) 721 n = ri->ri_rows - dst; 722 if (n <= 0) 723 return; 724 n *= ri->ri_font->fontheight; 725 src *= ri->ri_font->fontheight; 726 dst *= ri->ri_font->fontheight; 727 728 creator_ras_fifo_wait(sc, 8); 729 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_OLD | (FBC_ROP_OLD << 8)); 730 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_VSCROLL); 731 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + src); 732 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); 733 FBC_WRITE(sc, FFB_FBC_DY, ri->ri_yorigin + dst); 734 FBC_WRITE(sc, FFB_FBC_DX, ri->ri_xorigin); 735 FBC_WRITE(sc, FFB_FBC_BH, n); 736 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); 737 creator_ras_wait(sc); 738 } 739 740 void 741 creator_ras_setfg(sc, fg) 742 struct creator_softc *sc; 743 int32_t fg; 744 { 745 creator_ras_fifo_wait(sc, 1); 746 if (fg == sc->sc_fg_cache) 747 return; 748 sc->sc_fg_cache = fg; 749 FBC_WRITE(sc, FFB_FBC_FG, fg); 750 creator_ras_wait(sc); 751 } 752