1 /* $NetBSD: ffb.c,v 1.2 2003/06/11 22:50:12 petrov Exp $ */ 2 /* $OpenBSD: creator.c,v 1.20 2002/07/30 19:48:15 jason Exp $ */ 3 4 /* 5 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Jason L. Wright 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/device.h> 40 #include <sys/conf.h> 41 42 #include <machine/bus.h> 43 #include <machine/autoconf.h> 44 #include <machine/openfirm.h> 45 46 #include <dev/wscons/wsconsio.h> 47 #include <dev/wscons/wsdisplayvar.h> 48 #include <dev/wscons/wscons_raster.h> 49 #include <dev/rasops/rasops.h> 50 51 #include <sparc64/dev/ffbreg.h> 52 #include <sparc64/dev/ffbvar.h> 53 54 struct wsscreen_descr ffb_stdscreen = { 55 "std", 56 0, 0, /* will be filled in -- XXX shouldn't, it's global. */ 57 0, 58 0, 0, 59 WSSCREEN_REVERSE | WSSCREEN_WSCOLORS 60 }; 61 62 const struct wsscreen_descr *ffb_scrlist[] = { 63 &ffb_stdscreen, 64 /* XXX other formats? */ 65 }; 66 67 struct wsscreen_list ffb_screenlist = { 68 sizeof(ffb_scrlist) / sizeof(struct wsscreen_descr *), 69 ffb_scrlist 70 }; 71 72 int ffb_ioctl(void *, u_long, caddr_t, int, struct proc *); 73 int ffb_alloc_screen(void *, const struct wsscreen_descr *, void **, 74 int *, int *, long *); 75 void ffb_free_screen(void *, void *); 76 int ffb_show_screen(void *, void *, int, void (*cb)(void *, int, int), 77 void *); 78 paddr_t ffb_mmap(void *, off_t, int); 79 static int a2int(char *, int); 80 void ffb_ras_fifo_wait(struct ffb_softc *, int); 81 void ffb_ras_wait(struct ffb_softc *); 82 void ffb_ras_init(struct ffb_softc *); 83 void ffb_ras_copyrows(void *, int, int, int); 84 void ffb_ras_erasecols(void *, int, int, int, long int); 85 void ffb_ras_eraserows(void *, int, int, long int); 86 void ffb_ras_do_cursor(struct rasops_info *); 87 void ffb_ras_fill(struct ffb_softc *); 88 void ffb_ras_setfg(struct ffb_softc *, int32_t); 89 90 struct wsdisplay_accessops ffb_accessops = { 91 ffb_ioctl, 92 ffb_mmap, 93 ffb_alloc_screen, 94 ffb_free_screen, 95 ffb_show_screen, 96 NULL, /* load font */ 97 NULL, /* scrollback */ 98 NULL, /* getchar */ 99 NULL, /* burner */ 100 }; 101 102 void 103 ffb_attach(struct ffb_softc *sc) 104 { 105 struct wsemuldisplaydev_attach_args waa; 106 char *model; 107 int btype; 108 109 printf(":"); 110 111 if (sc->sc_type == FFB_CREATOR) { 112 btype = PROM_getpropint(sc->sc_node, "board_type", 0); 113 if ((btype & 7) == 3) 114 printf(" Creator3D"); 115 else 116 printf(" Creator"); 117 } else 118 printf(" Elite3D"); 119 120 model = PROM_getpropstring(sc->sc_node, "model"); 121 if (model == NULL || strlen(model) == 0) 122 model = "unknown"; 123 124 printf(", model %s\n", model); 125 126 sc->sc_depth = 24; 127 sc->sc_linebytes = 8192; 128 sc->sc_height = PROM_getpropint(sc->sc_node, "height", 0); 129 sc->sc_width = PROM_getpropint(sc->sc_node, "width", 0); 130 131 sc->sc_rasops.ri_depth = 32; 132 sc->sc_rasops.ri_stride = sc->sc_linebytes; 133 sc->sc_rasops.ri_flg = RI_CENTER; 134 sc->sc_rasops.ri_bits = (void *)bus_space_vaddr(sc->sc_bt, 135 sc->sc_pixel_h); 136 137 sc->sc_rasops.ri_width = sc->sc_width; 138 sc->sc_rasops.ri_height = sc->sc_height; 139 sc->sc_rasops.ri_hw = sc; 140 141 rasops_init(&sc->sc_rasops, 142 a2int(PROM_getpropstring(optionsnode, "screen-#rows"), 34), 143 a2int(PROM_getpropstring(optionsnode, "screen-#columns"), 80)); 144 145 if ((sc->sc_dv.dv_cfdata->cf_flags & FFB_CFFLAG_NOACCEL) == 0) { 146 sc->sc_rasops.ri_hw = sc; 147 sc->sc_rasops.ri_ops.eraserows = ffb_ras_eraserows; 148 sc->sc_rasops.ri_ops.erasecols = ffb_ras_erasecols; 149 sc->sc_rasops.ri_ops.copyrows = ffb_ras_copyrows; 150 ffb_ras_init(sc); 151 } 152 153 ffb_stdscreen.nrows = sc->sc_rasops.ri_rows; 154 ffb_stdscreen.ncols = sc->sc_rasops.ri_cols; 155 ffb_stdscreen.textops = &sc->sc_rasops.ri_ops; 156 157 if (sc->sc_console) { 158 int *ccolp, *crowp; 159 long defattr; 160 161 if (romgetcursoraddr(&crowp, &ccolp)) 162 ccolp = crowp = NULL; 163 if (ccolp != NULL) 164 sc->sc_rasops.ri_ccol = *ccolp; 165 if (crowp != NULL) 166 sc->sc_rasops.ri_crow = *crowp; 167 168 sc->sc_rasops.ri_ops.allocattr(&sc->sc_rasops, 169 0, 0, 0, &defattr); 170 171 wsdisplay_cnattach(&ffb_stdscreen, &sc->sc_rasops, 172 sc->sc_rasops.ri_ccol, sc->sc_rasops.ri_crow, defattr); 173 } 174 175 waa.console = sc->sc_console; 176 waa.scrdata = &ffb_screenlist; 177 waa.accessops = &ffb_accessops; 178 waa.accesscookie = sc; 179 config_found(&sc->sc_dv, &waa, wsemuldisplaydevprint); 180 } 181 182 int 183 ffb_ioctl(v, cmd, data, flags, p) 184 void *v; 185 u_long cmd; 186 caddr_t data; 187 int flags; 188 struct proc *p; 189 { 190 struct ffb_softc *sc = v; 191 struct wsdisplay_fbinfo *wdf; 192 193 #ifdef FFBDEBUG 194 printf("ffb_ioctl: %s cmd _IO%s%s('%c', %lu)\n", 195 sc->sc_dv.dv_xname, 196 (cmd & IOC_IN) ? "W" : "", (cmd & IOC_OUT) ? "R" : "", 197 (char)IOCGROUP(cmd), cmd & 0xff); 198 #endif 199 200 switch (cmd) { 201 case WSDISPLAYIO_GTYPE: 202 *(u_int *)data = WSDISPLAY_TYPE_SUN24; 203 break; 204 case WSDISPLAYIO_SMODE: 205 sc->sc_mode = *(u_int *)data; 206 break; 207 case WSDISPLAYIO_GINFO: 208 wdf = (void *)data; 209 wdf->height = sc->sc_height; 210 wdf->width = sc->sc_width; 211 wdf->depth = 32; 212 wdf->cmsize = 256; /* XXX */ 213 break; 214 #ifdef WSDISPLAYIO_LINEBYTES 215 case WSDISPLAYIO_LINEBYTES: 216 *(u_int *)data = sc->sc_linebytes; 217 break; 218 #endif 219 case WSDISPLAYIO_GETCMAP: 220 break;/* XXX */ 221 222 case WSDISPLAYIO_PUTCMAP: 223 break;/* XXX */ 224 225 case WSDISPLAYIO_SVIDEO: 226 case WSDISPLAYIO_GVIDEO: 227 case WSDISPLAYIO_GCURPOS: 228 case WSDISPLAYIO_SCURPOS: 229 case WSDISPLAYIO_GCURMAX: 230 case WSDISPLAYIO_GCURSOR: 231 case WSDISPLAYIO_SCURSOR: 232 default: 233 return -1; /* not supported yet */ 234 } 235 236 return (0); 237 } 238 239 int 240 ffb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 241 void *v; 242 const struct wsscreen_descr *type; 243 void **cookiep; 244 int *curxp, *curyp; 245 long *attrp; 246 { 247 struct ffb_softc *sc = v; 248 249 if (sc->sc_nscreens > 0) 250 return (ENOMEM); 251 252 *cookiep = &sc->sc_rasops; 253 *curyp = 0; 254 *curxp = 0; 255 256 sc->sc_rasops.ri_ops.allocattr(&sc->sc_rasops, 0, 0, 0, attrp); 257 258 sc->sc_nscreens++; 259 return (0); 260 } 261 262 void 263 ffb_free_screen(v, cookie) 264 void *v; 265 void *cookie; 266 { 267 struct ffb_softc *sc = v; 268 269 sc->sc_nscreens--; 270 } 271 272 int 273 ffb_show_screen(v, cookie, waitok, cb, cbarg) 274 void *v; 275 void *cookie; 276 int waitok; 277 void (*cb)(void *, int, int); 278 void *cbarg; 279 { 280 return (0); 281 } 282 283 paddr_t 284 ffb_mmap(vsc, off, prot) 285 void *vsc; 286 off_t off; 287 int prot; 288 { 289 struct ffb_softc *sc = vsc; 290 int i; 291 292 switch (sc->sc_mode) { 293 case WSDISPLAYIO_MODE_MAPPED: 294 for (i = 0; i < sc->sc_nreg; i++) { 295 /* Before this set? */ 296 if (off < sc->sc_addrs[i]) 297 continue; 298 /* After this set? */ 299 if (off >= (sc->sc_addrs[i] + sc->sc_sizes[i])) 300 continue; 301 302 return (bus_space_mmap(sc->sc_bt, sc->sc_addrs[i], 303 off - sc->sc_addrs[i], prot, BUS_SPACE_MAP_LINEAR)); 304 } 305 break; 306 #ifdef WSDISPLAYIO_MODE_DUMBFB 307 case WSDISPLAYIO_MODE_DUMBFB: 308 if (sc->sc_nreg < FFB_REG_DFB24) 309 break; 310 if (off >= 0 && off < sc->sc_sizes[FFB_REG_DFB24]) 311 return (bus_space_mmap(sc->sc_bt, 312 sc->sc_addrs[FFB_REG_DFB24], off, prot, 313 BUS_SPACE_MAP_LINEAR)); 314 break; 315 #endif 316 } 317 318 return (-1); 319 } 320 321 static int 322 a2int(char *cp, int deflt) 323 { 324 int i = 0; 325 326 if (*cp == '\0') 327 return (deflt); 328 while (*cp != '\0') 329 i = i * 10 + *cp++ - '0'; 330 return (i); 331 } 332 333 void 334 ffb_ras_fifo_wait(sc, n) 335 struct ffb_softc *sc; 336 int n; 337 { 338 int32_t cache = sc->sc_fifo_cache; 339 340 if (cache < n) { 341 do { 342 cache = FBC_READ(sc, FFB_FBC_UCSR); 343 cache = (cache & FBC_UCSR_FIFO_MASK) - 8; 344 } while (cache < n); 345 } 346 sc->sc_fifo_cache = cache - n; 347 } 348 349 void 350 ffb_ras_wait(sc) 351 struct ffb_softc *sc; 352 { 353 u_int32_t ucsr, r; 354 355 while (1) { 356 ucsr = FBC_READ(sc, FFB_FBC_UCSR); 357 if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0) 358 break; 359 r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL); 360 if (r != 0) 361 FBC_WRITE(sc, FFB_FBC_UCSR, r); 362 } 363 } 364 365 void 366 ffb_ras_init(sc) 367 struct ffb_softc *sc; 368 { 369 ffb_ras_fifo_wait(sc, 7); 370 FBC_WRITE(sc, FFB_FBC_PPC, 371 FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE | 372 FBC_PPC_APE_DIS | FBC_PPC_CS_CONST); 373 FBC_WRITE(sc, FFB_FBC_FBC, 374 FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH | 375 FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK); 376 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); 377 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); 378 FBC_WRITE(sc, FFB_FBC_PMASK, 0xffffffff); 379 FBC_WRITE(sc, FFB_FBC_FONTINC, 0x10000); 380 sc->sc_fg_cache = 0; 381 FBC_WRITE(sc, FFB_FBC_FG, sc->sc_fg_cache); 382 ffb_ras_wait(sc); 383 } 384 385 void 386 ffb_ras_eraserows(cookie, row, n, attr) 387 void *cookie; 388 int row, n; 389 long int attr; 390 { 391 struct rasops_info *ri = cookie; 392 struct ffb_softc *sc = ri->ri_hw; 393 394 if (row < 0) { 395 n += row; 396 row = 0; 397 } 398 if (row + n > ri->ri_rows) 399 n = ri->ri_rows - row; 400 if (n <= 0) 401 return; 402 403 ffb_ras_fill(sc); 404 ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]); 405 ffb_ras_fifo_wait(sc, 4); 406 if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { 407 FBC_WRITE(sc, FFB_FBC_BY, 0); 408 FBC_WRITE(sc, FFB_FBC_BX, 0); 409 FBC_WRITE(sc, FFB_FBC_BH, ri->ri_height); 410 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_width); 411 } else { 412 row *= ri->ri_font->fontheight; 413 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); 414 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); 415 FBC_WRITE(sc, FFB_FBC_BH, n * ri->ri_font->fontheight); 416 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); 417 } 418 ffb_ras_wait(sc); 419 } 420 421 void 422 ffb_ras_erasecols(cookie, row, col, n, attr) 423 void *cookie; 424 int row, col, n; 425 long int attr; 426 { 427 struct rasops_info *ri = cookie; 428 struct ffb_softc *sc = ri->ri_hw; 429 430 if ((row < 0) || (row >= ri->ri_rows)) 431 return; 432 if (col < 0) { 433 n += col; 434 col = 0; 435 } 436 if (col + n > ri->ri_cols) 437 n = ri->ri_cols - col; 438 if (n <= 0) 439 return; 440 n *= ri->ri_font->fontwidth; 441 col *= ri->ri_font->fontwidth; 442 row *= ri->ri_font->fontheight; 443 444 ffb_ras_fill(sc); 445 ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]); 446 ffb_ras_fifo_wait(sc, 4); 447 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row); 448 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin + col); 449 FBC_WRITE(sc, FFB_FBC_BH, ri->ri_font->fontheight); 450 FBC_WRITE(sc, FFB_FBC_BW, n - 1); 451 ffb_ras_wait(sc); 452 } 453 454 void 455 ffb_ras_fill(sc) 456 struct ffb_softc *sc; 457 { 458 ffb_ras_fifo_wait(sc, 2); 459 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW); 460 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); 461 ffb_ras_wait(sc); 462 } 463 464 void 465 ffb_ras_copyrows(cookie, src, dst, n) 466 void *cookie; 467 int src, dst, n; 468 { 469 struct rasops_info *ri = cookie; 470 struct ffb_softc *sc = ri->ri_hw; 471 472 if (dst == src) 473 return; 474 if (src < 0) { 475 n += src; 476 src = 0; 477 } 478 if ((src + n) > ri->ri_rows) 479 n = ri->ri_rows - src; 480 if (dst < 0) { 481 n += dst; 482 dst = 0; 483 } 484 if ((dst + n) > ri->ri_rows) 485 n = ri->ri_rows - dst; 486 if (n <= 0) 487 return; 488 n *= ri->ri_font->fontheight; 489 src *= ri->ri_font->fontheight; 490 dst *= ri->ri_font->fontheight; 491 492 ffb_ras_fifo_wait(sc, 8); 493 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_OLD | (FBC_ROP_OLD << 8)); 494 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_VSCROLL); 495 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + src); 496 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin); 497 FBC_WRITE(sc, FFB_FBC_DY, ri->ri_yorigin + dst); 498 FBC_WRITE(sc, FFB_FBC_DX, ri->ri_xorigin); 499 FBC_WRITE(sc, FFB_FBC_BH, n); 500 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth); 501 ffb_ras_wait(sc); 502 } 503 504 void 505 ffb_ras_setfg(sc, fg) 506 struct ffb_softc *sc; 507 int32_t fg; 508 { 509 ffb_ras_fifo_wait(sc, 1); 510 if (fg == sc->sc_fg_cache) 511 return; 512 sc->sc_fg_cache = fg; 513 FBC_WRITE(sc, FFB_FBC_FG, fg); 514 ffb_ras_wait(sc); 515 } 516