Annotation of sys/arch/sparc/dev/fb.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: fb.c,v 1.43 2006/12/03 22:10:30 miod Exp $ */
! 2: /* $NetBSD: fb.c,v 1.23 1997/07/07 23:30:22 pk Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2002, 2004 Miodrag Vallat.
! 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: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 19: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 20: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 21: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 22: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 23: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 25: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 26: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 27: * POSSIBILITY OF SUCH DAMAGE.
! 28: *
! 29: *
! 30: * Copyright (c) 1992, 1993
! 31: * The Regents of the University of California. All rights reserved.
! 32: *
! 33: * This software was developed by the Computer Systems Engineering group
! 34: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 35: * contributed to Berkeley.
! 36: *
! 37: * All advertising materials mentioning features or use of this software
! 38: * must display the following acknowledgement:
! 39: * This product includes software developed by the University of
! 40: * California, Lawrence Berkeley Laboratory.
! 41: *
! 42: * Redistribution and use in source and binary forms, with or without
! 43: * modification, are permitted provided that the following conditions
! 44: * are met:
! 45: * 1. Redistributions of source code must retain the above copyright
! 46: * notice, this list of conditions and the following disclaimer.
! 47: * 2. Redistributions in binary form must reproduce the above copyright
! 48: * notice, this list of conditions and the following disclaimer in the
! 49: * documentation and/or other materials provided with the distribution.
! 50: * 3. Neither the name of the University nor the names of its contributors
! 51: * may be used to endorse or promote products derived from this software
! 52: * without specific prior written permission.
! 53: *
! 54: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 55: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 56: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 57: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 58: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 59: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 60: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 61: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 62: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 63: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 64: * SUCH DAMAGE.
! 65: *
! 66: * @(#)fb.c 8.1 (Berkeley) 6/11/93
! 67: */
! 68:
! 69: /*
! 70: * Common wsdisplay framebuffer drivers helpers.
! 71: */
! 72:
! 73: #include <sys/param.h>
! 74: #include <sys/systm.h>
! 75: #include <sys/device.h>
! 76: #include <sys/proc.h>
! 77: #include <sys/conf.h>
! 78:
! 79: #include <machine/autoconf.h>
! 80: #include <machine/conf.h>
! 81: #if defined(SUN4)
! 82: #include <machine/eeprom.h>
! 83: #include <sparc/dev/pfourreg.h>
! 84: #endif
! 85:
! 86: #include <dev/wscons/wsdisplayvar.h>
! 87: #include <dev/rasops/rasops.h>
! 88: #include <machine/fbvar.h>
! 89:
! 90: #include "wsdisplay.h"
! 91:
! 92: /*
! 93: * Sun specific color indexes.
! 94: * Black is not really 7, but rather ~0; to fit within the 8 ANSI color
! 95: * palette we are using on console, we pick (~0) & 0x07 instead.
! 96: * This essentially swaps WSCOL_BLACK and WSCOL_WHITE.
! 97: */
! 98: #define WSCOL_SUN_WHITE 0
! 99: #define WSCOL_SUN_BLACK 7
! 100:
! 101: /*
! 102: * emergency unblank code
! 103: * XXX should be somewhat moved to wscons MI code
! 104: */
! 105:
! 106: void (*fb_burner)(void *, u_int, u_int);
! 107: void *fb_cookie;
! 108:
! 109: void
! 110: fb_unblank()
! 111: {
! 112: if (fb_burner != NULL)
! 113: (*fb_burner)(fb_cookie, 1, 0);
! 114: }
! 115:
! 116: #if NWSDISPLAY > 0
! 117:
! 118: #if defined(SUN4C) || defined(SUN4M)
! 119: static int a2int(char *, int);
! 120: #endif
! 121: static void fb_initwsd(struct sunfb *);
! 122: static void fb_updatecursor(struct rasops_info *);
! 123: int fb_alloc_screen(void *, const struct wsscreen_descr *, void **,
! 124: int *, int *, long *);
! 125: void fb_free_screen(void *, void *);
! 126: int fb_show_screen(void *, void *, int, void (*)(void *, int, int),
! 127: void *);
! 128:
! 129: void
! 130: fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height,
! 131: int node, int bustype)
! 132: {
! 133: int def_linebytes;
! 134:
! 135: switch (bustype) {
! 136: case BUS_VME16:
! 137: case BUS_VME32:
! 138: case BUS_OBIO:
! 139: #if defined(SUN4M)
! 140: /* 4m may have SBus-like framebuffer on obio */
! 141: if (CPU_ISSUN4M) {
! 142: goto obpsize;
! 143: }
! 144: #endif
! 145: /* Set up some defaults. */
! 146: sf->sf_width = def_width;
! 147: sf->sf_height = def_height;
! 148: sf->sf_depth = def_depth;
! 149:
! 150: #if defined(SUN4)
! 151: /*
! 152: * This is not particularly useful on Sun 4 VME framebuffers.
! 153: * The EEPROM only contains info about the built-in.
! 154: */
! 155: if (CPU_ISSUN4 && bustype == BUS_OBIO) {
! 156: struct eeprom *eep = (struct eeprom *)eeprom_va;
! 157:
! 158: if (ISSET(sf->sf_flags, FB_PFOUR)) {
! 159: volatile u_int32_t pfour;
! 160: u_int size;
! 161:
! 162: pfour = *sf->sf_pfour;
! 163:
! 164: /*
! 165: * Use the pfour register to determine
! 166: * the size. Note that the cgsix and
! 167: * cgeight don't use this size encoding.
! 168: * In this case, we have to settle
! 169: * for the defaults we were provided
! 170: * with.
! 171: */
! 172: if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) ||
! 173: (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR))
! 174: size = 0x00; /* invalid */
! 175: else
! 176: size = PFOUR_SIZE(pfour);
! 177:
! 178: switch (size) {
! 179: case PFOUR_SIZE_1152X900:
! 180: sf->sf_width = 1152;
! 181: sf->sf_height = 900;
! 182: break;
! 183: case PFOUR_SIZE_1024X1024:
! 184: sf->sf_width = 1024;
! 185: sf->sf_height = 1024;
! 186: break;
! 187: case PFOUR_SIZE_1280X1024:
! 188: sf->sf_width = 1280;
! 189: sf->sf_height = 1024;
! 190: break;
! 191: case PFOUR_SIZE_1600X1280:
! 192: sf->sf_width = 1600;
! 193: sf->sf_height = 1280;
! 194: break;
! 195: case PFOUR_SIZE_1440X1440:
! 196: sf->sf_width = 1440;
! 197: sf->sf_height = 1440;
! 198: break;
! 199: case PFOUR_SIZE_640X480:
! 200: sf->sf_width = 640;
! 201: sf->sf_height = 480;
! 202: break;
! 203: }
! 204: } else if (eep != NULL) {
! 205: switch (eep->eeScreenSize) {
! 206: case EE_SCR_1152X900:
! 207: sf->sf_width = 1152;
! 208: sf->sf_height = 900;
! 209: break;
! 210: case EE_SCR_1024X1024:
! 211: sf->sf_width = 1024;
! 212: sf->sf_height = 1024;
! 213: break;
! 214: case EE_SCR_1600X1280:
! 215: sf->sf_width = 1600;
! 216: sf->sf_height = 1280;
! 217: break;
! 218: case EE_SCR_1440X1440:
! 219: sf->sf_width = 1440;
! 220: sf->sf_height = 1440;
! 221: break;
! 222: }
! 223: }
! 224: }
! 225: #endif /* SUN4 */
! 226: #if defined(SUN4M)
! 227: if (CPU_ISSUN4M) {
! 228: /* XXX: need code to find 4/600 vme screen size */
! 229: }
! 230: #endif /* SUN4M */
! 231:
! 232: sf->sf_linebytes = (sf->sf_width * sf->sf_depth) / 8;
! 233: break;
! 234:
! 235: case BUS_SBUS:
! 236: #if defined(SUN4M)
! 237: obpsize:
! 238: #endif
! 239: sf->sf_depth = getpropint(node, "depth", def_depth);
! 240: sf->sf_width = getpropint(node, "width", def_width);
! 241: sf->sf_height = getpropint(node, "height", def_height);
! 242:
! 243: def_linebytes =
! 244: roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8;
! 245: sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes);
! 246:
! 247: /*
! 248: * XXX If we are configuring a board in a wider depth level
! 249: * than the mode it is currently operating in, the PROM will
! 250: * return a linebytes property tied to the current depth value,
! 251: * which is NOT what we are relying upon!
! 252: */
! 253: if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8)
! 254: sf->sf_linebytes = def_linebytes;
! 255:
! 256: break;
! 257: }
! 258:
! 259: sf->sf_fbsize = sf->sf_height * sf->sf_linebytes;
! 260: }
! 261:
! 262: #if defined(SUN4C) || defined(SUN4M)
! 263: static int
! 264: a2int(char *cp, int deflt)
! 265: {
! 266: int i = 0;
! 267:
! 268: if (*cp == '\0')
! 269: return (deflt);
! 270: while (*cp != '\0')
! 271: i = i * 10 + *cp++ - '0';
! 272: return (i);
! 273: }
! 274: #endif
! 275:
! 276: /* setup the embedded wsscreen_descr structure from rasops settings */
! 277: static void
! 278: fb_initwsd(struct sunfb *sf)
! 279: {
! 280: strlcpy(sf->sf_wsd.name, "std", sizeof(sf->sf_wsd.name));
! 281: sf->sf_wsd.capabilities = sf->sf_ro.ri_caps;
! 282: sf->sf_wsd.nrows = sf->sf_ro.ri_rows;
! 283: sf->sf_wsd.ncols = sf->sf_ro.ri_cols;
! 284: sf->sf_wsd.textops = &sf->sf_ro.ri_ops;
! 285: }
! 286:
! 287: static void
! 288: fb_updatecursor(struct rasops_info *ri)
! 289: {
! 290: struct sunfb *sf = (struct sunfb *)ri->ri_hw;
! 291:
! 292: if (sf->sf_crowp != NULL)
! 293: *sf->sf_crowp = ri->ri_crow;
! 294: if (sf->sf_ccolp != NULL)
! 295: *sf->sf_ccolp = ri->ri_ccol;
! 296: }
! 297:
! 298: void
! 299: fbwscons_init(struct sunfb *sf, int flags)
! 300: {
! 301: struct rasops_info *ri = &sf->sf_ro;
! 302: int cols, rows;
! 303:
! 304: /* ri_hw and ri_bits must have already been setup by caller */
! 305: ri->ri_flg = RI_CENTER | RI_FULLCLEAR | flags;
! 306: ri->ri_depth = sf->sf_depth;
! 307: ri->ri_stride = sf->sf_linebytes;
! 308: ri->ri_width = sf->sf_width;
! 309: ri->ri_height = sf->sf_height;
! 310:
! 311: #if defined(SUN4C) || defined(SUN4M)
! 312: if (CPU_ISSUN4COR4M) {
! 313: rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34);
! 314: cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80);
! 315: }
! 316: #endif
! 317: #if defined(SUN4)
! 318: if (CPU_ISSUN4) {
! 319: struct eeprom *ep = (struct eeprom *)eeprom_va;
! 320:
! 321: if (ep != NULL) {
! 322: rows = (u_short)ep->eeTtyRows;
! 323: cols = (u_short)ep->eeTtyCols;
! 324: /* deal with broken nvram contents... */
! 325: if (rows <= 0)
! 326: rows = 34;
! 327: if (cols <= 0)
! 328: cols = 80;
! 329: } else {
! 330: rows = 34;
! 331: cols = 80;
! 332: }
! 333: }
! 334: #endif
! 335:
! 336: rasops_init(ri, rows, cols);
! 337:
! 338: if (sf->sf_depth == 8) {
! 339: /*
! 340: * If we are running with an indexed palette, compensate
! 341: * the swap of black and white through ri_devcmap.
! 342: */
! 343: ri->ri_devcmap[WSCOL_SUN_BLACK] = 0;
! 344: ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff;
! 345: } else if (sf->sf_depth > 8) {
! 346: /*
! 347: * If we are running on a direct color frame buffer,
! 348: * make the ``normal'' white the same as the hilighted
! 349: * white.
! 350: */
! 351: ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8];
! 352: }
! 353: }
! 354:
! 355: void
! 356: fbwscons_console_init(struct sunfb *sf, int row)
! 357: {
! 358: struct rasops_info *ri = &sf->sf_ro;
! 359: long defattr;
! 360:
! 361: if (CPU_ISSUN4 || romgetcursoraddr(&sf->sf_crowp, &sf->sf_ccolp))
! 362: sf->sf_ccolp = sf->sf_crowp = NULL;
! 363: if (sf->sf_ccolp != NULL)
! 364: ri->ri_ccol = *sf->sf_ccolp;
! 365:
! 366: if (row < 0) {
! 367: if (sf->sf_crowp != NULL)
! 368: ri->ri_crow = *sf->sf_crowp;
! 369: else
! 370: /* assume last row */
! 371: ri->ri_crow = ri->ri_rows - 1;
! 372: } else {
! 373: /*
! 374: * If we force the display row, this is because the screen
! 375: * has been cleared or the font has been changed.
! 376: * In this case, choose not to keep pointers to the PROM
! 377: * cursor position, as the values are likely to be inaccurate
! 378: * upon shutdown...
! 379: */
! 380: sf->sf_crowp = sf->sf_ccolp = NULL;
! 381: ri->ri_crow = row;
! 382: }
! 383:
! 384: /*
! 385: * Scale back rows and columns if the font would not otherwise
! 386: * fit on this display. Without this we would panic later.
! 387: */
! 388: if (ri->ri_crow >= ri->ri_rows)
! 389: ri->ri_crow = ri->ri_rows - 1;
! 390: if (ri->ri_ccol >= ri->ri_cols)
! 391: ri->ri_ccol = ri->ri_cols - 1;
! 392:
! 393: /*
! 394: * Take care of updating the PROM cursor position as well if we can.
! 395: */
! 396: if (ri->ri_updatecursor == NULL &&
! 397: (sf->sf_ccolp != NULL || sf->sf_crowp != NULL))
! 398: ri->ri_updatecursor = fb_updatecursor;
! 399:
! 400: if (ISSET(ri->ri_caps, WSSCREEN_WSCOLORS))
! 401: ri->ri_ops.alloc_attr(ri,
! 402: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, &defattr);
! 403: else
! 404: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
! 405:
! 406: fb_initwsd(sf);
! 407: wsdisplay_cnattach(&sf->sf_wsd, ri,
! 408: ri->ri_ccol, ri->ri_crow, defattr);
! 409: }
! 410:
! 411: void
! 412: fbwscons_setcolormap(struct sunfb *sf,
! 413: void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t))
! 414: {
! 415: int i;
! 416: const u_char *color;
! 417:
! 418: if (sf->sf_depth <= 8 && setcolor != NULL) {
! 419: for (i = 0; i < 16; i++) {
! 420: color = &rasops_cmap[i * 3];
! 421: setcolor(sf, i, color[0], color[1], color[2]);
! 422: }
! 423: for (i = 240; i < 256; i++) {
! 424: color = &rasops_cmap[i * 3];
! 425: setcolor(sf, i, color[0], color[1], color[2]);
! 426: }
! 427: /*
! 428: * Compensate for BoW default hardware palette: existing
! 429: * output (which we do not want to affect) is black on
! 430: * white with color index 0 being white and 0xff being
! 431: * black.
! 432: */
! 433: setcolor(sf, WSCOL_SUN_WHITE, 0xff, 0xff, 0xff);
! 434: setcolor(sf, 0xff ^ WSCOL_SUN_WHITE, 0, 0, 0);
! 435: setcolor(sf, WSCOL_SUN_BLACK, 0, 0, 0);
! 436: setcolor(sf, 0xff ^ (WSCOL_SUN_BLACK), 0xff, 0xff, 0xff);
! 437: }
! 438: }
! 439:
! 440: void
! 441: fbwscons_attach(struct sunfb *sf, struct wsdisplay_accessops *op, int isconsole)
! 442: {
! 443: struct wsemuldisplaydev_attach_args waa;
! 444:
! 445: if (isconsole == 0) {
! 446: /* done in wsdisplay_cnattach() earlier if console */
! 447: fb_initwsd(sf);
! 448: } else {
! 449: /* remember screen burner routine */
! 450: fb_burner = op->burn_screen;
! 451: fb_cookie = sf;
! 452: }
! 453:
! 454: /* plug common wsdisplay_accessops if necessary */
! 455: if (op->alloc_screen == NULL) {
! 456: op->alloc_screen = fb_alloc_screen;
! 457: op->free_screen = fb_free_screen;
! 458: op->show_screen = fb_show_screen;
! 459: }
! 460:
! 461: sf->sf_scrlist[0] = &sf->sf_wsd;
! 462: sf->sf_wsl.nscreens = 1;
! 463: sf->sf_wsl.screens = (const struct wsscreen_descr **)sf->sf_scrlist;
! 464:
! 465: waa.console = isconsole;
! 466: waa.scrdata = &sf->sf_wsl;
! 467: waa.accessops = op;
! 468: waa.accesscookie = sf;
! 469: waa.defaultscreens = 0;
! 470: config_found(&sf->sf_dev, &waa, wsemuldisplaydevprint);
! 471: }
! 472:
! 473: /*
! 474: * Common wsdisplay_accessops routines.
! 475: */
! 476: int
! 477: fb_alloc_screen(void *v, const struct wsscreen_descr *type,
! 478: void **cookiep, int *curxp, int *curyp, long *attrp)
! 479: {
! 480: struct sunfb *sf = v;
! 481: struct rasops_info *ri = &sf->sf_ro;
! 482:
! 483: if (sf->sf_nscreens > 0)
! 484: return (ENOMEM);
! 485:
! 486: *cookiep = ri;
! 487: *curyp = 0;
! 488: *curxp = 0;
! 489: if (ISSET(ri->ri_caps, WSSCREEN_WSCOLORS))
! 490: ri->ri_ops.alloc_attr(ri,
! 491: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
! 492: else
! 493: ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
! 494: sf->sf_nscreens++;
! 495: return (0);
! 496: }
! 497:
! 498: void
! 499: fb_free_screen(void *v, void *cookie)
! 500: {
! 501: struct sunfb *sf = v;
! 502:
! 503: sf->sf_nscreens--;
! 504: }
! 505:
! 506: int
! 507: fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
! 508: void *cbarg)
! 509: {
! 510: return (0);
! 511: }
! 512:
! 513: #if defined(SUN4)
! 514:
! 515: /*
! 516: * Support routines for P4 framebuffers.
! 517: */
! 518:
! 519: /*
! 520: * Probe for a P4 framebuffer. Return values:
! 521: * PFOUR_NOTPFOUR framebuffer is not a P4 framebuffer
! 522: * otherwise returns P4 ID
! 523: */
! 524: int
! 525: fb_pfour_id(void *va)
! 526: {
! 527: volatile u_int32_t val, save, *pfour = va;
! 528:
! 529: /* Read the pfour register. */
! 530: save = *pfour;
! 531:
! 532: /*
! 533: * Try to modify the type code. If it changes, put the
! 534: * original value back, and notify the caller that it's
! 535: * not a pfour framebuffer.
! 536: */
! 537: val = save & ~PFOUR_REG_RESET;
! 538: *pfour = (val ^ PFOUR_FBTYPE_MASK);
! 539: if ((*pfour ^ val) & PFOUR_FBTYPE_MASK) {
! 540: *pfour = save;
! 541: return (PFOUR_NOTPFOUR);
! 542: }
! 543:
! 544: return (PFOUR_ID(val));
! 545: }
! 546:
! 547: /*
! 548: * Screen burner routine for P4
! 549: */
! 550: void
! 551: fb_pfour_burner(void *v, u_int enable, u_int flags)
! 552: {
! 553: struct sunfb *sf = (struct sunfb *)v;
! 554: volatile u_int32_t pfour;
! 555:
! 556: pfour = *sf->sf_pfour & ~(PFOUR_REG_INTCLR | PFOUR_REG_VIDEO);
! 557: *sf->sf_pfour = pfour | (enable ? PFOUR_REG_VIDEO : 0);
! 558: }
! 559:
! 560: #endif /* SUN4 */
! 561:
! 562: #endif /* NWSDISPLAY */
CVSweb