Annotation of sys/arch/sparc/dev/agten.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: agten.c,v 1.10 2006/06/02 20:00:54 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2002, 2003, Miodrag Vallat.
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 18: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 19: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 20: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 21: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 23: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 25: * POSSIBILITY OF SUCH DAMAGE.
! 26: *
! 27: */
! 28:
! 29: /*
! 30: * Fujitsu AG-10 framebuffer driver.
! 31: *
! 32: * The AG-10 is mostly made of:
! 33: * - a 3DLabs 300SX Glint chip, with two 6MB independent framebuffer spaces
! 34: * - a Number Nine Imagine 128 chip with its own 4MB framebuffer space
! 35: * - a Weitek P9100 with its own 2MB of framebuffer memory
! 36: * - an IBM PaletteDAC 561 ramdac
! 37: * - an Analog Devices ADSP-21062
! 38: *
! 39: * All of these chips (memory, registers, etc) are mapped in the SBus
! 40: * memory space associated to the board. What is unexpected, however, is
! 41: * that there are also PCI registers mappings for the first three chips!
! 42: *
! 43: * The three graphics chips act as overlays of each other, for the final
! 44: * video output.
! 45: *
! 46: * The PROM initialization will use the I128 framebuffer memory for output,
! 47: * which is ``above'' the P9100. The P9100 seems to only be there to provide
! 48: * a simple RAMDAC interface, but its frame buffer memory is accessible and
! 49: * will appear as an ``underlay'' plane.
! 50: */
! 51:
! 52: /*
! 53: * TODO
! 54: * - initialize the I128 in 32bit mode
! 55: * - use the i128 acceleration features
! 56: */
! 57:
! 58: #include <sys/param.h>
! 59: #include <sys/systm.h>
! 60: #include <sys/buf.h>
! 61: #include <sys/device.h>
! 62: #include <sys/ioctl.h>
! 63: #include <sys/malloc.h>
! 64: #include <sys/mman.h>
! 65: #include <sys/tty.h>
! 66: #include <sys/conf.h>
! 67:
! 68: #include <uvm/uvm_extern.h>
! 69:
! 70: #include <machine/autoconf.h>
! 71: #include <machine/pmap.h>
! 72: #include <machine/cpu.h>
! 73: #include <machine/conf.h>
! 74:
! 75: #include <dev/wscons/wsconsio.h>
! 76: #include <dev/wscons/wsdisplayvar.h>
! 77: #include <dev/rasops/rasops.h>
! 78: #include <machine/fbvar.h>
! 79:
! 80: #include <dev/ic/p9000.h>
! 81: #include <dev/ic/ibm561reg.h>
! 82:
! 83: #include <sparc/dev/sbusvar.h>
! 84:
! 85: struct agten_cmap {
! 86: u_int8_t cm_red[256];
! 87: u_int8_t cm_green[256];
! 88: u_int8_t cm_blue[256];
! 89: };
! 90:
! 91: /* per-display variables */
! 92: struct agten_softc {
! 93: struct sunfb sc_sunfb; /* common base part */
! 94:
! 95: struct rom_reg sc_phys; /* physical address and */
! 96: off_t sc_physoffset; /* offset for frame buffer */
! 97:
! 98: volatile u_int8_t *sc_p9100;
! 99: struct agten_cmap sc_cmap; /* shadow color map */
! 100:
! 101: volatile u_int32_t *sc_i128_fb;
! 102: };
! 103:
! 104: int agten_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 105: paddr_t agten_mmap(void *, off_t, int);
! 106: void agten_reset(struct agten_softc *);
! 107: void agten_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
! 108:
! 109: static __inline__
! 110: void ibm561_write(struct agten_softc *, u_int32_t, u_int32_t);
! 111: int agten_getcmap(struct agten_cmap *, struct wsdisplay_cmap *);
! 112: int agten_putcmap(struct agten_cmap *, struct wsdisplay_cmap *);
! 113: void agten_loadcmap(struct agten_softc *, u_int, u_int);
! 114:
! 115: struct wsdisplay_accessops agten_accessops = {
! 116: agten_ioctl,
! 117: agten_mmap,
! 118: NULL, /* alloc_screen */
! 119: NULL, /* free_screen */
! 120: NULL, /* show_screen */
! 121: NULL, /* load_font */
! 122: NULL, /* scrollback */
! 123: NULL, /* getchar */
! 124: NULL, /* burner */
! 125: NULL /* pollc */
! 126: };
! 127:
! 128: int agtenmatch(struct device *, void *, void *);
! 129: void agtenattach(struct device *, struct device *, void *);
! 130:
! 131: struct cfattach agten_ca = {
! 132: sizeof(struct agten_softc), agtenmatch, agtenattach
! 133: };
! 134:
! 135: struct cfdriver agten_cd = {
! 136: NULL, "agten", DV_DULL
! 137: };
! 138:
! 139: int
! 140: agtenmatch(struct device *parent, void *vcf, void *aux)
! 141: {
! 142: struct confargs *ca = aux;
! 143: struct romaux *ra = &ca->ca_ra;
! 144:
! 145: if (strcmp(ra->ra_name, "PFU,aga") != 0)
! 146: return (0);
! 147:
! 148: return (1);
! 149: }
! 150:
! 151: void
! 152: agtenattach(struct device *parent, struct device *self, void *args)
! 153: {
! 154: struct agten_softc *sc = (struct agten_softc *)self;
! 155: struct confargs *ca = args;
! 156: int node, isconsole;
! 157: char *nam;
! 158:
! 159: node = ca->ca_ra.ra_node;
! 160: nam = getpropstring(node, "model");
! 161: printf(": model %s", nam);
! 162:
! 163: isconsole = node == fbnode;
! 164:
! 165: sc->sc_phys = ca->ca_ra.ra_reg[0];
! 166:
! 167: /*
! 168: * Map the various beasts of this card we are interested in.
! 169: */
! 170:
! 171: sc->sc_physoffset =
! 172: (off_t)getpropint(node, "i128_fb_physaddr", 0x8000000);
! 173: sc->sc_i128_fb = mapiodev(ca->ca_ra.ra_reg, sc->sc_physoffset,
! 174: getpropint(node, "i128_fb_size", 0x400000));
! 175: sc->sc_p9100 = mapiodev(ca->ca_ra.ra_reg,
! 176: getpropint(node, "p9100_reg_physaddr", 0x10a0000),
! 177: 0x4000);
! 178:
! 179: /*
! 180: * For some reason the agten does not use the canonical name for
! 181: * properties, but uses an ffb_ prefix; and the linebytes property is
! 182: * missing.
! 183: * The following is a specific version of
! 184: * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, BUS_SBUS);
! 185: * using the correct property names.
! 186: */
! 187: #ifdef notyet
! 188: sc->sc_sunfb.sf_depth = 32;
! 189: #else
! 190: sc->sc_sunfb.sf_depth = getpropint(node, "ffb_depth", 8);
! 191: #endif
! 192: sc->sc_sunfb.sf_width = getpropint(node, "ffb_width", 1152);
! 193: sc->sc_sunfb.sf_height = getpropint(node, "ffb_height", 900);
! 194: sc->sc_sunfb.sf_linebytes =
! 195: roundup(sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_depth) *
! 196: sc->sc_sunfb.sf_depth / 8;
! 197: sc->sc_sunfb.sf_fbsize =
! 198: sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
! 199:
! 200: printf(", %dx%d, depth %d\n",
! 201: sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
! 202: sc->sc_sunfb.sf_depth);
! 203:
! 204: sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_i128_fb;
! 205:
! 206: sc->sc_sunfb.sf_ro.ri_hw = sc;
! 207: fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
! 208: fbwscons_setcolormap(&sc->sc_sunfb, agten_setcolor);
! 209:
! 210: if (isconsole) {
! 211: fbwscons_console_init(&sc->sc_sunfb, -1);
! 212: }
! 213:
! 214: fbwscons_attach(&sc->sc_sunfb, &agten_accessops, isconsole);
! 215: }
! 216:
! 217: int
! 218: agten_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
! 219: {
! 220: struct agten_softc *sc = dev;
! 221: struct wsdisplay_cmap *cm;
! 222: struct wsdisplay_fbinfo *wdf;
! 223: int error;
! 224:
! 225: switch (cmd) {
! 226: case WSDISPLAYIO_GTYPE:
! 227: *(u_int *)data = WSDISPLAY_TYPE_SUN24;
! 228: break;
! 229: case WSDISPLAYIO_GINFO:
! 230: wdf = (struct wsdisplay_fbinfo *)data;
! 231: wdf->height = sc->sc_sunfb.sf_height;
! 232: wdf->width = sc->sc_sunfb.sf_width;
! 233: wdf->depth = sc->sc_sunfb.sf_depth;
! 234: wdf->cmsize = (sc->sc_sunfb.sf_depth == 8) ? 256 : 0;
! 235: break;
! 236: case WSDISPLAYIO_LINEBYTES:
! 237: *(u_int *)data = sc->sc_sunfb.sf_linebytes;
! 238: break;
! 239:
! 240: case WSDISPLAYIO_GETCMAP:
! 241: if (sc->sc_sunfb.sf_depth == 8) {
! 242: cm = (struct wsdisplay_cmap *)data;
! 243: error = agten_getcmap(&sc->sc_cmap, cm);
! 244: if (error)
! 245: return (error);
! 246: }
! 247: break;
! 248: case WSDISPLAYIO_PUTCMAP:
! 249: if (sc->sc_sunfb.sf_depth == 8) {
! 250: cm = (struct wsdisplay_cmap *)data;
! 251: error = agten_putcmap(&sc->sc_cmap, cm);
! 252: if (error)
! 253: return (error);
! 254: agten_loadcmap(sc, 0, 256);
! 255: }
! 256: break;
! 257:
! 258: case WSDISPLAYIO_SVIDEO:
! 259: case WSDISPLAYIO_GVIDEO:
! 260: break;
! 261:
! 262: case WSDISPLAYIO_GCURPOS:
! 263: case WSDISPLAYIO_SCURPOS:
! 264: case WSDISPLAYIO_GCURMAX:
! 265: case WSDISPLAYIO_GCURSOR:
! 266: case WSDISPLAYIO_SCURSOR:
! 267: default:
! 268: return (-1); /* not supported yet */
! 269: }
! 270:
! 271: return (0);
! 272: }
! 273:
! 274: paddr_t
! 275: agten_mmap(void *v, off_t offset, int prot)
! 276: {
! 277: struct agten_softc *sc = v;
! 278:
! 279: if (offset & PGOFSET)
! 280: return (-1);
! 281:
! 282: /* Allow mapping as a dumb framebuffer from offset 0 */
! 283: if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
! 284: return (REG2PHYS(&sc->sc_phys, sc->sc_physoffset + offset) |
! 285: PMAP_NC);
! 286: }
! 287:
! 288: return (-1);
! 289: }
! 290:
! 291: void
! 292: agten_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
! 293: {
! 294: struct agten_softc *sc = v;
! 295:
! 296: sc->sc_cmap.cm_red[index] = r;
! 297: sc->sc_cmap.cm_green[index] = g;
! 298: sc->sc_cmap.cm_blue[index] = b;
! 299:
! 300: agten_loadcmap(sc, index, 1);
! 301: }
! 302:
! 303: int
! 304: agten_getcmap(struct agten_cmap *cm, struct wsdisplay_cmap *rcm)
! 305: {
! 306: u_int index = rcm->index, count = rcm->count;
! 307: int error;
! 308:
! 309: if (index >= 256 || count > 256 - index)
! 310: return (EINVAL);
! 311:
! 312: if ((error = copyout(&cm->cm_red[index], rcm->red, count)) != 0)
! 313: return (error);
! 314: if ((error = copyout(&cm->cm_green[index], rcm->green, count)) != 0)
! 315: return (error);
! 316: if ((error = copyout(&cm->cm_blue[index], rcm->blue, count)) != 0)
! 317: return (error);
! 318:
! 319: return (0);
! 320: }
! 321:
! 322: int
! 323: agten_putcmap(struct agten_cmap *cm, struct wsdisplay_cmap *rcm)
! 324: {
! 325: u_int index = rcm->index, count = rcm->count;
! 326: int error;
! 327:
! 328: if (index >= 256 || count > 256 - index)
! 329: return (EINVAL);
! 330:
! 331: if ((error = copyin(rcm->red, &cm->cm_red[index], count)) != 0)
! 332: return (error);
! 333: if ((error = copyin(rcm->green, &cm->cm_green[index], count)) != 0)
! 334: return (error);
! 335: if ((error = copyin(rcm->blue, &cm->cm_blue[index], count)) != 0)
! 336: return (error);
! 337:
! 338: return (0);
! 339: }
! 340:
! 341: static __inline__ void
! 342: ibm561_write(struct agten_softc *sc, u_int32_t reg, u_int32_t value)
! 343: {
! 344: /*
! 345: * For some design reason the IBM561 PaletteDac needs to be fed
! 346: * values shifted left by 16 bits. What happened to simplicity?
! 347: */
! 348: *(volatile u_int32_t *)(sc->sc_p9100 + P9100_RAMDAC_REGISTER(reg)) =
! 349: (value) << 16;
! 350: }
! 351:
! 352: void
! 353: agten_loadcmap(struct agten_softc *sc, u_int start, u_int ncolors)
! 354: {
! 355: int i;
! 356: u_int8_t *red, *green, *blue;
! 357:
! 358: ibm561_write(sc, IBM561_ADDR_LOW,
! 359: (IBM561_CMAP_TABLE + start) & 0xff);
! 360: ibm561_write(sc, IBM561_ADDR_HIGH,
! 361: ((IBM561_CMAP_TABLE + start) >> 8) & 0xff);
! 362:
! 363: red = sc->sc_cmap.cm_red;
! 364: green = sc->sc_cmap.cm_green;
! 365: blue = sc->sc_cmap.cm_blue;
! 366: for (i = start; i < start + ncolors; i++) {
! 367: ibm561_write(sc, IBM561_CMD_CMAP, *red++);
! 368: ibm561_write(sc, IBM561_CMD_CMAP, *green++);
! 369: ibm561_write(sc, IBM561_CMD_CMAP, *blue++);
! 370: }
! 371: }
CVSweb