Annotation of sys/arch/luna88k/dev/lunafb.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: lunafb.c,v 1.8 2006/11/29 12:13:54 miod Exp $ */
! 2: /* $NetBSD: lunafb.c,v 1.7.6.1 2002/08/07 01:48:34 lukem Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2000 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Tohru Nishimura.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: #include <sys/param.h>
! 41: #include <sys/systm.h>
! 42: #include <sys/conf.h>
! 43: #include <sys/device.h>
! 44: #include <sys/ioctl.h>
! 45: #include <sys/malloc.h>
! 46: #include <sys/mman.h>
! 47: #include <sys/proc.h>
! 48: #include <sys/tty.h>
! 49: #include <sys/errno.h>
! 50: #include <sys/buf.h>
! 51:
! 52: #include <uvm/uvm_extern.h>
! 53:
! 54: #include <dev/wscons/wsconsio.h>
! 55: #include <dev/wscons/wsdisplayvar.h>
! 56: #include <dev/rasops/rasops.h>
! 57:
! 58: #include <machine/cpu.h>
! 59: #include <machine/autoconf.h>
! 60:
! 61: struct bt454 {
! 62: u_int8_t bt_addr; /* map address register */
! 63: u_int8_t bt_cmap; /* colormap data register */
! 64: };
! 65:
! 66: struct bt458 {
! 67: u_int8_t bt_addr; /* map address register */
! 68: unsigned :24;
! 69: u_int8_t bt_cmap; /* colormap data register */
! 70: unsigned :24;
! 71: u_int8_t bt_ctrl; /* control register */
! 72: unsigned :24;
! 73: u_int8_t bt_omap; /* overlay (cursor) map register */
! 74: unsigned :24;
! 75: };
! 76:
! 77: #define OMFB_RFCNT 0xB1000000 /* video h-origin/v-origin */
! 78: #define OMFB_PLANEMASK 0xB1040000 /* planemask register */
! 79: #define OMFB_FB_WADDR 0xB1080008 /* common plane */
! 80: #define OMFB_FB_RADDR 0xB10C0008 /* plane #0 */
! 81: #define OMFB_ROPFUNC 0xB12C0000 /* ROP function code */
! 82: #define OMFB_RAMDAC 0xC1100000 /* Bt454/Bt458 RAMDAC */
! 83: #define OMFB_SIZE (0xB1300000 - 0xB1080000 + NBPG)
! 84:
! 85: struct om_hwdevconfig {
! 86: int dc_wid; /* width of frame buffer */
! 87: int dc_ht; /* height of frame buffer */
! 88: int dc_depth; /* depth, bits per pixel */
! 89: int dc_rowbytes; /* bytes in a FB scan line */
! 90: int dc_cmsize; /* colormap size */
! 91: vaddr_t dc_videobase; /* base of flat frame buffer */
! 92: struct rasops_info dc_ri; /* raster blitter variables */
! 93: };
! 94:
! 95: struct hwcmap {
! 96: #define CMAP_SIZE 256
! 97: u_int8_t r[CMAP_SIZE];
! 98: u_int8_t g[CMAP_SIZE];
! 99: u_int8_t b[CMAP_SIZE];
! 100: };
! 101:
! 102: struct omfb_softc {
! 103: struct device sc_dev; /* base device */
! 104: struct om_hwdevconfig *sc_dc; /* device configuration */
! 105: struct hwcmap sc_cmap; /* software copy of colormap */
! 106: int nscreens;
! 107: };
! 108:
! 109: int omgetcmap(struct omfb_softc *, struct wsdisplay_cmap *);
! 110: int omsetcmap(struct omfb_softc *, struct wsdisplay_cmap *);
! 111:
! 112: struct om_hwdevconfig omfb_console_dc;
! 113: void omfb_getdevconfig(paddr_t, struct om_hwdevconfig *);
! 114:
! 115: /* in omrasops.c */
! 116: void om_cursor(void *, int, int, int);
! 117: void om_putchar(void *, int, int, u_int, long);
! 118: void om_copycols(void *, int, int, int, int);
! 119: void om_copyrows(void *, int, int, int num);
! 120: void om_erasecols(void *, int, int, int, long);
! 121: void om_eraserows(void *, int, int, long);
! 122:
! 123: struct wsscreen_descr omfb_stdscreen = {
! 124: "std"
! 125: };
! 126:
! 127: const struct wsscreen_descr *_omfb_scrlist[] = {
! 128: &omfb_stdscreen,
! 129: };
! 130:
! 131: const struct wsscreen_list omfb_screenlist = {
! 132: sizeof(_omfb_scrlist) / sizeof(struct wsscreen_descr *), _omfb_scrlist
! 133: };
! 134:
! 135: int omfbioctl(void *, u_long, caddr_t, int, struct proc *);
! 136: paddr_t omfbmmap(void *, off_t, int);
! 137: int omfb_alloc_screen(void *, const struct wsscreen_descr *,
! 138: void **, int *, int *, long *);
! 139: void omfb_free_screen(void *, void *);
! 140: int omfb_show_screen(void *, void *, int,
! 141: void (*) (void *, int, int), void *);
! 142:
! 143: const struct wsdisplay_accessops omfb_accessops = {
! 144: omfbioctl,
! 145: omfbmmap,
! 146: omfb_alloc_screen,
! 147: omfb_free_screen,
! 148: omfb_show_screen,
! 149: NULL, /* load_font */
! 150: NULL, /* scrollback */
! 151: NULL, /* getchar */
! 152: NULL /* burner */
! 153: };
! 154:
! 155: int omfbmatch(struct device *, void *, void *);
! 156: void omfbattach(struct device *, struct device *, void *);
! 157:
! 158: const struct cfattach fb_ca = {
! 159: sizeof(struct omfb_softc), omfbmatch, omfbattach
! 160: };
! 161:
! 162: struct cfdriver fb_cd = {
! 163: NULL, "fb", DV_DULL
! 164: };
! 165:
! 166: extern int hwplanebits; /* hardware plane bits; retrieved at boot */
! 167:
! 168: int omfb_console;
! 169: int omfb_cnattach(void);
! 170:
! 171: int
! 172: omfbmatch(parent, cf, aux)
! 173: struct device *parent;
! 174: void *cf, *aux;
! 175: {
! 176: struct mainbus_attach_args *ma = aux;
! 177:
! 178: if (strcmp(ma->ma_name, fb_cd.cd_name))
! 179: return (0);
! 180: #if 0 /* XXX badaddr() bombs if no framebuffer is installed */
! 181: if (badaddr((caddr_t)ma->ma_addr, 4))
! 182: return (0);
! 183: #else
! 184: if (hwplanebits == 0)
! 185: return (0);
! 186: #endif
! 187: return (1);
! 188: }
! 189:
! 190: void
! 191: omfbattach(parent, self, args)
! 192: struct device *parent, *self;
! 193: void *args;
! 194: {
! 195: struct omfb_softc *sc = (struct omfb_softc *)self;
! 196: struct wsemuldisplaydev_attach_args waa;
! 197:
! 198: if (omfb_console) {
! 199: sc->sc_dc = &omfb_console_dc;
! 200: sc->nscreens = 1;
! 201: }
! 202: else {
! 203: sc->sc_dc = (struct om_hwdevconfig *)
! 204: malloc(sizeof(struct om_hwdevconfig), M_DEVBUF, M_WAITOK);
! 205: omfb_getdevconfig(OMFB_FB_WADDR, sc->sc_dc);
! 206: }
! 207: printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
! 208: sc->sc_dc->dc_depth);
! 209:
! 210: #if 0 /* WHITE on BLACK */
! 211: cm = &sc->sc_cmap;
! 212: memset(cm, 255, sizeof(struct hwcmap));
! 213: cm->r[0] = cm->g[0] = cm->b[0] = 0;
! 214: #endif
! 215: waa.console = omfb_console;
! 216: waa.scrdata = &omfb_screenlist;
! 217: waa.accessops = &omfb_accessops;
! 218: waa.accesscookie = sc;
! 219: waa.defaultscreens = 0;
! 220:
! 221: config_found(self, &waa, wsemuldisplaydevprint);
! 222: }
! 223:
! 224: /* EXPORT */ int
! 225: omfb_cnattach()
! 226: {
! 227: struct om_hwdevconfig *dc = &omfb_console_dc;
! 228: struct rasops_info *ri = &dc->dc_ri;
! 229: long defattr;
! 230:
! 231: omfb_getdevconfig(OMFB_FB_WADDR, dc);
! 232: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
! 233: wsdisplay_cnattach(&omfb_stdscreen, ri, 0, 0, defattr);
! 234: omfb_console = 1;
! 235: return (0);
! 236: }
! 237:
! 238: int
! 239: omfbioctl(v, cmd, data, flag, p)
! 240: void *v;
! 241: u_long cmd;
! 242: caddr_t data;
! 243: int flag;
! 244: struct proc *p;
! 245: {
! 246: struct omfb_softc *sc = v;
! 247: struct om_hwdevconfig *dc = sc->sc_dc;
! 248:
! 249: switch (cmd) {
! 250: case WSDISPLAYIO_GTYPE:
! 251: *(u_int *)data = WSDISPLAY_TYPE_LUNA;
! 252: break;
! 253:
! 254: case WSDISPLAYIO_GINFO:
! 255: #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
! 256: wsd_fbip->height = dc->dc_ht;
! 257: wsd_fbip->width = dc->dc_wid;
! 258: wsd_fbip->depth = dc->dc_depth;
! 259: wsd_fbip->cmsize = dc->dc_cmsize;
! 260: #undef fbt
! 261: break;
! 262:
! 263: case WSDISPLAYIO_GETCMAP:
! 264: return omgetcmap(sc, (struct wsdisplay_cmap *)data);
! 265:
! 266: case WSDISPLAYIO_PUTCMAP:
! 267: return omsetcmap(sc, (struct wsdisplay_cmap *)data);
! 268:
! 269: case WSDISPLAYIO_SVIDEO:
! 270: case WSDISPLAYIO_GVIDEO:
! 271: break;
! 272:
! 273: case WSDISPLAYIO_GCURPOS:
! 274: case WSDISPLAYIO_SCURPOS:
! 275: case WSDISPLAYIO_GCURMAX:
! 276: case WSDISPLAYIO_GCURSOR:
! 277: case WSDISPLAYIO_SCURSOR:
! 278: default:
! 279: return (-1);
! 280: }
! 281:
! 282: return (0);
! 283: }
! 284:
! 285: /*
! 286: * Return the address that would map the given device at the given
! 287: * offset, allowing for the given protection, or return -1 for error.
! 288: */
! 289:
! 290: paddr_t
! 291: omfbmmap(v, offset, prot)
! 292: void *v;
! 293: off_t offset;
! 294: int prot;
! 295: {
! 296: struct omfb_softc *sc = v;
! 297:
! 298: if (offset & PGOFSET)
! 299: return (-1);
! 300: if (offset >= OMFB_SIZE || offset < 0)
! 301: return (-1);
! 302:
! 303: return atop(trunc_page(sc->sc_dc->dc_videobase) + offset);
! 304: }
! 305:
! 306: int
! 307: omgetcmap(sc, p)
! 308: struct omfb_softc *sc;
! 309: struct wsdisplay_cmap *p;
! 310: {
! 311: u_int index = p->index, count = p->count;
! 312: unsigned int cmsize;
! 313: int error;
! 314:
! 315: cmsize = sc->sc_dc->dc_cmsize;
! 316: if (index >= cmsize || count > cmsize - index)
! 317: return (EINVAL);
! 318:
! 319: error = copyout(&sc->sc_cmap.r[index], p->red, count);
! 320: if (error != 0)
! 321: return (error);
! 322: error = copyout(&sc->sc_cmap.g[index], p->green, count);
! 323: if (error != 0)
! 324: return (error);
! 325: error = copyout(&sc->sc_cmap.b[index], p->blue, count);
! 326: if (error != 0)
! 327: return (error);
! 328:
! 329: return (0);
! 330: }
! 331:
! 332: int
! 333: omsetcmap(sc, p)
! 334: struct omfb_softc *sc;
! 335: struct wsdisplay_cmap *p;
! 336: {
! 337: u_int index = p->index, count = p->count;
! 338: unsigned int cmsize, i;
! 339: int error;
! 340:
! 341: cmsize = sc->sc_dc->dc_cmsize;
! 342: if (index >= cmsize || count > cmsize - index)
! 343: return (EINVAL);
! 344:
! 345: error = copyin(p->red, &sc->sc_cmap.r[index], count);
! 346: if (error != 0)
! 347: return (error);
! 348: error = copyin(p->green, &sc->sc_cmap.g[index], count);
! 349: if (error != 0)
! 350: return (error);
! 351: error = copyin(p->blue, &sc->sc_cmap.b[index], count);
! 352: if (error != 0)
! 353: return (error);
! 354:
! 355: if (hwplanebits == 4) {
! 356: struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
! 357: odac->bt_addr = index;
! 358: for (i = index; i < count; i++) {
! 359: odac->bt_cmap = sc->sc_cmap.r[i];
! 360: odac->bt_cmap = sc->sc_cmap.g[i];
! 361: odac->bt_cmap = sc->sc_cmap.b[i];
! 362: }
! 363: }
! 364: else if (hwplanebits == 8) {
! 365: struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
! 366: ndac->bt_addr = index;
! 367: for (i = index; i < count; i++) {
! 368: ndac->bt_cmap = sc->sc_cmap.r[i];
! 369: ndac->bt_cmap = sc->sc_cmap.g[i];
! 370: ndac->bt_cmap = sc->sc_cmap.b[i];
! 371: }
! 372: }
! 373: return (0);
! 374: }
! 375:
! 376: void
! 377: omfb_getdevconfig(paddr, dc)
! 378: paddr_t paddr;
! 379: struct om_hwdevconfig *dc;
! 380: {
! 381: int bpp, i;
! 382: struct rasops_info *ri;
! 383: union {
! 384: struct { short h, v; } p;
! 385: u_int32_t u;
! 386: } rfcnt;
! 387:
! 388: switch (hwplanebits) {
! 389: case 8:
! 390: bpp = 8; /* XXX check monochrome bit in DIPSW */
! 391: break;
! 392: default:
! 393: case 4:
! 394: bpp = 4; /* XXX check monochrome bit in DIPSW */
! 395: break;
! 396: case 1:
! 397: bpp = 1;
! 398: break;
! 399: }
! 400: dc->dc_wid = 1280;
! 401: dc->dc_ht = 1024;
! 402: dc->dc_depth = bpp;
! 403: dc->dc_rowbytes = 2048 / 8;
! 404: dc->dc_cmsize = (bpp == 1) ? 0 : 1 << bpp;
! 405: dc->dc_videobase = paddr;
! 406:
! 407: #if 0 /* WHITE on BLACK XXX experiment resulted in WHITE on SKYBLUE... */
! 408: if (hwplanebits == 4) {
! 409: /* XXX Need Bt454 initialization */
! 410: struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
! 411: odac->bt_addr = 0;
! 412: odac->bt_cmap = 0;
! 413: odac->bt_cmap = 0;
! 414: odac->bt_cmap = 0;
! 415: for (i = 1; i < 16; i++) {
! 416: odac->bt_cmap = 255;
! 417: odac->bt_cmap = 255;
! 418: odac->bt_cmap = 255;
! 419: }
! 420: }
! 421: else if (hwplanebits == 8) {
! 422: struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
! 423:
! 424: ndac->bt_addr = 0x04;
! 425: ndac->bt_ctrl = 0xff; /* all planes will be read */
! 426: ndac->bt_ctrl = 0x00; /* all planes have non-blink */
! 427: ndac->bt_ctrl = 0x43; /* pallete enabled, ovly plane */
! 428: ndac->bt_ctrl = 0x00; /* no test mode */
! 429: ndac->bt_addr = 0;
! 430: ndac->bt_cmap = 0;
! 431: ndac->bt_cmap = 0;
! 432: ndac->bt_cmap = 0;
! 433: for (i = 1; i < 256; i++) {
! 434: ndac->bt_cmap = 255;
! 435: ndac->bt_cmap = 255;
! 436: ndac->bt_cmap = 255;
! 437: }
! 438: }
! 439: #endif
! 440:
! 441: /* adjust h/v origin on screen */
! 442: rfcnt.p.h = 7;
! 443: rfcnt.p.v = -27;
! 444: *(u_int32_t *)OMFB_RFCNT = rfcnt.u; /* single write of 0x007ffe6 */
! 445:
! 446: /* clear the screen */
! 447: *(u_int32_t *)OMFB_PLANEMASK = 0xff;
! 448: ((u_int32_t *)OMFB_ROPFUNC)[5] = ~0; /* ROP copy */
! 449: for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++)
! 450: *((u_int32_t *)dc->dc_videobase + i) = 0;
! 451: *(u_int32_t *)OMFB_PLANEMASK = 0x01;
! 452:
! 453: /* initialize the raster */
! 454: ri = &dc->dc_ri;
! 455: ri->ri_width = dc->dc_wid;
! 456: ri->ri_height = dc->dc_ht;
! 457: ri->ri_depth = 1; /* since planes are independently addressed */
! 458: ri->ri_stride = dc->dc_rowbytes;
! 459: ri->ri_bits = (void *)dc->dc_videobase;
! 460: ri->ri_flg = RI_CENTER;
! 461: ri->ri_hw = dc;
! 462:
! 463: rasops_init(ri, 35, 80);
! 464:
! 465: omfb_stdscreen.ncols = ri->ri_cols;
! 466: omfb_stdscreen.nrows = ri->ri_rows;
! 467: ri->ri_ops.cursor = om_cursor;
! 468: ri->ri_ops.putchar = om_putchar;
! 469: ri->ri_ops.copycols = om_copycols;
! 470: ri->ri_ops.erasecols = om_erasecols;
! 471: ri->ri_ops.copyrows = om_copyrows;
! 472: ri->ri_ops.eraserows = om_eraserows;
! 473: omfb_stdscreen.textops = &ri->ri_ops;
! 474: omfb_stdscreen.fontwidth = ri->ri_font->fontwidth;
! 475: omfb_stdscreen.fontheight = ri->ri_font->fontheight;
! 476: omfb_stdscreen.capabilities = ri->ri_caps & ~WSSCREEN_UNDERLINE;
! 477: }
! 478:
! 479: int
! 480: omfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
! 481: void *v;
! 482: const struct wsscreen_descr *type;
! 483: void **cookiep;
! 484: int *curxp, *curyp;
! 485: long *attrp;
! 486: {
! 487: struct omfb_softc *sc = v;
! 488: struct rasops_info *ri = &sc->sc_dc->dc_ri;
! 489:
! 490: if (sc->nscreens > 0)
! 491: return (ENOMEM);
! 492:
! 493: *cookiep = ri;
! 494: *curxp = 0;
! 495: *curyp = 0;
! 496: ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
! 497: sc->nscreens++;
! 498: return (0);
! 499: }
! 500:
! 501: void
! 502: omfb_free_screen(v, cookie)
! 503: void *v;
! 504: void *cookie;
! 505: {
! 506: struct omfb_softc *sc = v;
! 507:
! 508: sc->nscreens--;
! 509: }
! 510:
! 511: int
! 512: omfb_show_screen(v, cookie, waitok, cb, cbarg)
! 513: void *v;
! 514: void *cookie;
! 515: int waitok;
! 516: void (*cb)(void *, int, int);
! 517: void *cbarg;
! 518: {
! 519: return 0;
! 520: }
CVSweb