Annotation of sys/arch/sparc64/dev/creator.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb