Annotation of sys/arch/vax/vsa/lcg.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: lcg.c,v 1.10 2006/11/29 12:13:54 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2006 Miodrag Vallat.
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice, this permission notice, and the disclaimer below
! 8: * appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18: /*
! 19: * Copyright (c) 2003, 2004 Blaz Antonic
! 20: * All rights reserved.
! 21: *
! 22: * Redistribution and use in source and binary forms, with or without
! 23: * modification, are permitted provided that the following conditions
! 24: * are met:
! 25: * 1. Redistributions of source code must retain the above copyright
! 26: * notice, this list of conditions and the following disclaimer.
! 27: * 2. Redistributions in binary form must reproduce the above copyright
! 28: * notice, this list of conditions and the following disclaimer in the
! 29: * documentation and/or other materials provided with the distribution.
! 30: * 3. All advertising materials mentioning features or use of this software
! 31: * must display the abovementioned copyrights
! 32: * 4. The name of the author may not be used to endorse or promote products
! 33: * derived from this software without specific prior written permission
! 34: *
! 35: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 36: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 37: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 38: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 39: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 40: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 41: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 42: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 43: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 44: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 45: */
! 46:
! 47: #include <sys/param.h>
! 48: #include <sys/device.h>
! 49: #include <sys/systm.h>
! 50: #include <sys/malloc.h>
! 51: #include <sys/conf.h>
! 52: #include <sys/kernel.h>
! 53:
! 54: #include <machine/vsbus.h>
! 55: #include <machine/scb.h>
! 56: #include <machine/sid.h>
! 57: #include <machine/cpu.h>
! 58:
! 59: #include <uvm/uvm_extern.h>
! 60:
! 61: #include <dev/cons.h>
! 62:
! 63: #include <dev/wscons/wsconsio.h>
! 64: #include <dev/wscons/wsdisplayvar.h>
! 65: #include <dev/rasops/rasops.h>
! 66:
! 67: #include <vax/vsa/lcgreg.h>
! 68:
! 69: #define LCG_CONFIG_ADDR 0x200f0010 /* configuration register */
! 70: #define LCG_REG_ADDR 0x20100000 /* registers */
! 71: #define LCG_REG_SIZE 0x4000
! 72: #define LCG_LUT_ADDR 0x21800000 /* colormap */
! 73: #define LCG_LUT_OFFSET 0x0800
! 74: #define LCG_LUT_SIZE 0x0800
! 75: #define LCG_FB_ADDR 0x21801000 /* frame buffer */
! 76:
! 77: int lcg_match(struct device *, void *, void *);
! 78: void lcg_attach(struct device *, struct device *, void *);
! 79:
! 80: struct lcg_screen {
! 81: struct rasops_info ss_ri;
! 82: u_int32_t ss_cfg;
! 83: u_int ss_width, ss_height, ss_depth;
! 84: u_int ss_fbsize; /* visible part only */
! 85: caddr_t ss_addr; /* frame buffer address */
! 86: vaddr_t ss_reg;
! 87: volatile u_int8_t *ss_lut;
! 88: u_int8_t ss_cmap[256 * 3];
! 89: };
! 90:
! 91: /* for console */
! 92: struct lcg_screen lcg_consscr;
! 93:
! 94: struct lcg_softc {
! 95: struct device sc_dev;
! 96: struct lcg_screen *sc_scr;
! 97: int sc_nscreens;
! 98: };
! 99:
! 100: struct cfattach lcg_ca = {
! 101: sizeof(struct lcg_softc), lcg_match, lcg_attach,
! 102: };
! 103:
! 104: struct cfdriver lcg_cd = {
! 105: NULL, "lcg", DV_DULL
! 106: };
! 107:
! 108: struct wsscreen_descr lcg_stdscreen = {
! 109: "std",
! 110: };
! 111:
! 112: const struct wsscreen_descr *_lcg_scrlist[] = {
! 113: &lcg_stdscreen,
! 114: };
! 115:
! 116: const struct wsscreen_list lcg_screenlist = {
! 117: sizeof(_lcg_scrlist) / sizeof(struct wsscreen_descr *),
! 118: _lcg_scrlist,
! 119: };
! 120:
! 121: int lcg_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 122: paddr_t lcg_mmap(void *, off_t, int);
! 123: int lcg_alloc_screen(void *, const struct wsscreen_descr *,
! 124: void **, int *, int *, long *);
! 125: void lcg_free_screen(void *, void *);
! 126: int lcg_show_screen(void *, void *, int,
! 127: void (*) (void *, int, int), void *);
! 128: void lcg_burner(void *, u_int, u_int);
! 129:
! 130: const struct wsdisplay_accessops lcg_accessops = {
! 131: lcg_ioctl,
! 132: lcg_mmap,
! 133: lcg_alloc_screen,
! 134: lcg_free_screen,
! 135: lcg_show_screen,
! 136: NULL, /* load_font */
! 137: NULL, /* scrollback */
! 138: NULL, /* getchar */
! 139: lcg_burner
! 140: };
! 141:
! 142: int lcg_alloc_attr(void *, int, int, int, long *);
! 143: int lcg_getcmap(struct lcg_screen *, struct wsdisplay_cmap *);
! 144: void lcg_loadcmap(struct lcg_screen *, int, int);
! 145: int lcg_probe_screen(u_int32_t, u_int *, u_int *);
! 146: int lcg_putcmap(struct lcg_screen *, struct wsdisplay_cmap *);
! 147: void lcg_resetcmap(struct lcg_screen *);
! 148: int lcg_setup_screen(struct lcg_screen *);
! 149:
! 150: #define lcg_read_reg(ss, regno) \
! 151: *(volatile u_int32_t *)((ss)->ss_reg + (regno))
! 152: #define lcg_write_reg(ss, regno, val) \
! 153: *(volatile u_int32_t *)((ss)->ss_reg + (regno)) = (val)
! 154:
! 155: int
! 156: lcg_match(struct device *parent, void *vcf, void *aux)
! 157: {
! 158: struct vsbus_softc *sc = (void *)parent;
! 159: struct vsbus_attach_args *va = aux;
! 160: vaddr_t cfgreg;
! 161: int depth, missing;
! 162: volatile u_int8_t *ch;
! 163:
! 164: switch (vax_boardtype) {
! 165: default:
! 166: return (0);
! 167:
! 168: case VAX_BTYP_46:
! 169: case VAX_BTYP_48:
! 170: if (va->va_paddr != LCG_REG_ADDR)
! 171: return (0);
! 172:
! 173: break;
! 174: }
! 175:
! 176: /*
! 177: * Check the configuration register.
! 178: * This is done to sort out empty frame buffer slots, since the video
! 179: * memory test sometimes passes!
! 180: */
! 181: cfgreg = vax_map_physmem(LCG_CONFIG_ADDR, 1);
! 182: depth = lcg_probe_screen(*(volatile u_int32_t *)cfgreg, NULL, NULL);
! 183: vax_unmap_physmem(cfgreg, 1);
! 184: if (depth < 0) /* no frame buffer */
! 185: return (0);
! 186:
! 187: /*
! 188: * Check for video memory.
! 189: * We can not use badaddr() on these models.
! 190: */
! 191: missing = 0;
! 192: ch = (volatile u_int8_t *)vax_map_physmem(LCG_FB_ADDR, 1);
! 193: *ch = 0x01;
! 194: if ((*ch & 0x01) == 0)
! 195: missing = 1;
! 196: else {
! 197: *ch = 0x00;
! 198: if ((*ch & 0x01) != 0)
! 199: missing = 1;
! 200: }
! 201: vax_unmap_physmem((vaddr_t)ch, 1);
! 202: if (missing != 0)
! 203: return (0);
! 204:
! 205: sc->sc_mask = 0x04; /* XXX - should be generated */
! 206: scb_fake(0x120, 0x15);
! 207: return (20);
! 208: }
! 209:
! 210: void
! 211: lcg_attach(struct device *parent, struct device *self, void *aux)
! 212: {
! 213: struct lcg_softc *sc = (struct lcg_softc *)self;
! 214: struct lcg_screen *ss;
! 215: struct wsemuldisplaydev_attach_args aa;
! 216: vaddr_t tmp;
! 217: u_int32_t cfg;
! 218: int console;
! 219: extern struct consdev wsdisplay_cons;
! 220:
! 221: console = (vax_confdata & 0x100) == 0 && cn_tab == &wsdisplay_cons;
! 222:
! 223: /*
! 224: * Check for a recognized configuration register.
! 225: * If we do not recognize it, print it and do not attach - so that
! 226: * this gets noticed...
! 227: */
! 228: if (!console) {
! 229: tmp = vax_map_physmem(LCG_CONFIG_ADDR, 1);
! 230: if (tmp == NULL) {
! 231: printf("\n%s: can not map configuration register\n",
! 232: self->dv_xname);
! 233: return;
! 234: }
! 235: cfg = *(volatile u_int32_t *)tmp;
! 236: vax_unmap_physmem(tmp, 1);
! 237:
! 238: if (lcg_probe_screen(cfg, NULL, NULL) <= 0) {
! 239: printf("\n%s:"
! 240: " unrecognized configuration register %08x\n",
! 241: self->dv_xname, cfg);
! 242: return;
! 243: }
! 244: }
! 245:
! 246: if (console) {
! 247: ss = &lcg_consscr;
! 248: sc->sc_nscreens = 1;
! 249: } else {
! 250: ss = malloc(sizeof(struct lcg_screen), M_DEVBUF, M_NOWAIT);
! 251: if (ss == NULL) {
! 252: printf(": can not allocate memory\n");
! 253: return;
! 254: }
! 255: bzero(ss, sizeof(struct lcg_screen));
! 256:
! 257: ss->ss_cfg = cfg;
! 258: ss->ss_depth = lcg_probe_screen(ss->ss_cfg,
! 259: &ss->ss_width, &ss->ss_height);
! 260: ss->ss_fbsize =
! 261: roundup(ss->ss_width * ss->ss_height, PAGE_SIZE);
! 262:
! 263: ss->ss_addr = (caddr_t)vax_map_physmem(LCG_FB_ADDR,
! 264: ss->ss_fbsize / VAX_NBPG);
! 265: if (ss->ss_addr == NULL) {
! 266: printf(": can not map frame buffer\n");
! 267: goto fail1;
! 268: }
! 269:
! 270: ss->ss_reg = vax_map_physmem(LCG_REG_ADDR,
! 271: LCG_REG_SIZE / VAX_NBPG);
! 272: if (ss->ss_reg == 0L) {
! 273: printf(": can not map registers\n");
! 274: goto fail2;
! 275: }
! 276:
! 277: ss->ss_lut = (volatile u_int8_t *)vax_map_physmem(LCG_LUT_ADDR +
! 278: LCG_LUT_OFFSET, LCG_LUT_SIZE / VAX_NBPG);
! 279: if (ss->ss_lut == NULL) {
! 280: printf(": can not map color LUT\n");
! 281: goto fail3;
! 282: }
! 283:
! 284: if (lcg_setup_screen(ss) != 0) {
! 285: printf(": initialization failed\n");
! 286: goto fail4;
! 287: }
! 288: }
! 289: sc->sc_scr = ss;
! 290:
! 291: printf(": %dx%dx%d frame buffer\n",
! 292: ss->ss_width, ss->ss_height, ss->ss_depth);
! 293:
! 294: aa.console = console;
! 295: aa.scrdata = &lcg_screenlist;
! 296: aa.accessops = &lcg_accessops;
! 297: aa.accesscookie = sc;
! 298: aa.defaultscreens = 0;
! 299:
! 300: config_found(self, &aa, wsemuldisplaydevprint);
! 301: return;
! 302:
! 303: fail4:
! 304: vax_unmap_physmem((vaddr_t)ss->ss_lut, LCG_LUT_SIZE / VAX_NBPG);
! 305: fail3:
! 306: vax_unmap_physmem(ss->ss_reg, LCG_REG_SIZE / VAX_NBPG);
! 307: fail2:
! 308: vax_unmap_physmem((vaddr_t)ss->ss_addr, ss->ss_fbsize / VAX_NBPG);
! 309: fail1:
! 310: free(ss, M_DEVBUF);
! 311: }
! 312:
! 313: /*
! 314: * Determine if we have a recognized frame buffer, its resolution and
! 315: * color depth.
! 316: */
! 317: int
! 318: lcg_probe_screen(u_int32_t cfg, u_int *width, u_int *height)
! 319: {
! 320: u_int w, h, d = 8;
! 321:
! 322: switch (vax_boardtype) {
! 323: case VAX_BTYP_46:
! 324: switch (cfg & 0xf0) {
! 325: case 0x00:
! 326: return (-1); /* no hardware */
! 327: case 0x20:
! 328: case 0x60:
! 329: w = 1024; h = 864;
! 330: break;
! 331: case 0x40:
! 332: w = 1024; h = 768;
! 333: break;
! 334: case 0x80:
! 335: d = 4;
! 336: /* FALLTHROUGH */
! 337: case 0x90:
! 338: case 0xb0:
! 339: w = 1280; h = 1024;
! 340: break;
! 341: default:
! 342: return (0); /* unknown configuration, please help */
! 343: }
! 344: break;
! 345: case VAX_BTYP_48:
! 346: switch (cfg & 0x07) {
! 347: case 0x00:
! 348: return (-1); /* no hardware */
! 349: case 0x05:
! 350: w = 1280; h = 1024;
! 351: break;
! 352: case 0x06:
! 353: if (vax_confdata & 0x80) {
! 354: w = 1024; h = 768;
! 355: } else {
! 356: w = 640; h = 480;
! 357: }
! 358: break;
! 359: case 0x07:
! 360: if (vax_confdata & 0x80) {
! 361: w = 1024; h = 864;
! 362: } else {
! 363: w = 1024; h = 768;
! 364: }
! 365: break;
! 366: default:
! 367: return (0); /* unknown configuration, please help */
! 368: }
! 369: break;
! 370: }
! 371:
! 372: if (width != NULL)
! 373: *width = w;
! 374: if (height != NULL)
! 375: *height = h;
! 376:
! 377: return (d);
! 378: }
! 379:
! 380: /*
! 381: * Initialize anything necessary for an emulating wsdisplay to work (i.e.
! 382: * pick a font, initialize a rasops structure, setup the accessops callbacks.)
! 383: */
! 384: int
! 385: lcg_setup_screen(struct lcg_screen *ss)
! 386: {
! 387: struct rasops_info *ri = &ss->ss_ri;
! 388:
! 389: bzero(ri, sizeof(*ri));
! 390: /*
! 391: * Since the frame buffer memory is byte addressed, even in low-bpp
! 392: * mode, initialize a 8bpp rasops engine. We will report a shorter
! 393: * colormap if necessary, which will allow X to do TRT.
! 394: */
! 395: ri->ri_depth = 8;
! 396: ri->ri_width = ss->ss_width;
! 397: ri->ri_height = ss->ss_height;
! 398: ri->ri_stride = ss->ss_width;
! 399: ri->ri_flg = RI_CLEAR | RI_CENTER;
! 400: ri->ri_bits = (void *)ss->ss_addr;
! 401: ri->ri_hw = ss;
! 402:
! 403: /*
! 404: * Ask for an unholy big display, rasops will trim this to more
! 405: * reasonable values.
! 406: */
! 407: if (rasops_init(ri, 160, 160) != 0)
! 408: return (-1);
! 409:
! 410: if (ss->ss_depth < 8) {
! 411: ri->ri_ops.alloc_attr = lcg_alloc_attr;
! 412: ri->ri_caps &= ~WSSCREEN_HILIT;
! 413: }
! 414:
! 415: lcg_stdscreen.ncols = ri->ri_cols;
! 416: lcg_stdscreen.nrows = ri->ri_rows;
! 417: lcg_stdscreen.textops = &ri->ri_ops;
! 418: lcg_stdscreen.fontwidth = ri->ri_font->fontwidth;
! 419: lcg_stdscreen.fontheight = ri->ri_font->fontheight;
! 420: lcg_stdscreen.capabilities = ri->ri_caps;
! 421:
! 422: lcg_resetcmap(ss);
! 423:
! 424: return (0);
! 425: }
! 426:
! 427: int
! 428: lcg_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
! 429: {
! 430: struct lcg_softc *sc = v;
! 431: struct lcg_screen *ss = sc->sc_scr;
! 432: struct wsdisplay_fbinfo *wdf;
! 433: struct wsdisplay_cmap *cm;
! 434: int error;
! 435:
! 436: switch (cmd) {
! 437: case WSDISPLAYIO_GTYPE:
! 438: *(u_int *)data = WSDISPLAY_TYPE_LCG;
! 439: break;
! 440:
! 441: case WSDISPLAYIO_GINFO:
! 442: wdf = (struct wsdisplay_fbinfo *)data;
! 443: wdf->height = ss->ss_height;
! 444: wdf->width = ss->ss_width;
! 445: wdf->depth = 8;
! 446: wdf->cmsize = 1 << ss->ss_depth;
! 447: break;
! 448:
! 449: case WSDISPLAYIO_LINEBYTES:
! 450: *(u_int *)data = ss->ss_ri.ri_stride;
! 451: break;
! 452:
! 453: case WSDISPLAYIO_GETCMAP:
! 454: cm = (struct wsdisplay_cmap *)data;
! 455: error = lcg_getcmap(ss, cm);
! 456: if (error != 0)
! 457: return (error);
! 458: break;
! 459: case WSDISPLAYIO_PUTCMAP:
! 460: cm = (struct wsdisplay_cmap *)data;
! 461: error = lcg_putcmap(ss, cm);
! 462: if (error != 0)
! 463: return (error);
! 464: lcg_loadcmap(ss, cm->index, cm->count);
! 465: break;
! 466:
! 467: case WSDISPLAYIO_GVIDEO:
! 468: case WSDISPLAYIO_SVIDEO:
! 469: break;
! 470:
! 471: default:
! 472: return (-1);
! 473: }
! 474:
! 475: return (0);
! 476: }
! 477:
! 478: paddr_t
! 479: lcg_mmap(void *v, off_t offset, int prot)
! 480: {
! 481: struct lcg_softc *sc = v;
! 482: struct lcg_screen *ss = sc->sc_scr;
! 483:
! 484: if (offset >= ss->ss_fbsize || offset < 0)
! 485: return (-1);
! 486:
! 487: return (LCG_FB_ADDR + offset) >> PGSHIFT;
! 488: }
! 489:
! 490: int
! 491: lcg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
! 492: int *curxp, int *curyp, long *defattrp)
! 493: {
! 494: struct lcg_softc *sc = v;
! 495: struct lcg_screen *ss = sc->sc_scr;
! 496: struct rasops_info *ri = &ss->ss_ri;
! 497:
! 498: if (sc->sc_nscreens > 0)
! 499: return (ENOMEM);
! 500:
! 501: *cookiep = ri;
! 502: *curxp = *curyp = 0;
! 503: ri->ri_ops.alloc_attr(ri, 0, 0, 0, defattrp);
! 504: sc->sc_nscreens++;
! 505:
! 506: return (0);
! 507: }
! 508:
! 509: void
! 510: lcg_free_screen(void *v, void *cookie)
! 511: {
! 512: struct lcg_softc *sc = v;
! 513:
! 514: sc->sc_nscreens--;
! 515: }
! 516:
! 517: int
! 518: lcg_show_screen(void *v, void *cookie, int waitok,
! 519: void (*cb)(void *, int, int), void *cbarg)
! 520: {
! 521: return (0);
! 522: }
! 523:
! 524: void
! 525: lcg_burner(void *v, u_int on, u_int flags)
! 526: {
! 527: struct lcg_softc *sc = v;
! 528: struct lcg_screen *ss = sc->sc_scr;
! 529: u_int32_t vidcfg;
! 530:
! 531: vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG);
! 532: if (on)
! 533: vidcfg |= VIDEO_ENABLE_VIDEO | VIDEO_SYNC_ENABLE;
! 534: else {
! 535: vidcfg &= ~VIDEO_ENABLE_VIDEO;
! 536: if (flags & WSDISPLAY_BURN_VBLANK)
! 537: vidcfg &= ~VIDEO_SYNC_ENABLE;
! 538: }
! 539: lcg_write_reg(ss, LCG_REG_VIDEO_CONFIG, vidcfg);
! 540: }
! 541:
! 542: /*
! 543: * Attribute allocator for 4bpp frame buffers.
! 544: * In such modes, highlighting is not available.
! 545: */
! 546: int
! 547: lcg_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
! 548: {
! 549: extern int rasops_alloc_cattr(void *, int, int, int, long *);
! 550:
! 551: if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
! 552: return (EINVAL);
! 553:
! 554: return (rasops_alloc_cattr(cookie, fg, bg, flg, attr));
! 555: }
! 556:
! 557: /*
! 558: * Colormap handling routines
! 559: */
! 560:
! 561: int
! 562: lcg_getcmap(struct lcg_screen *ss, struct wsdisplay_cmap *cm)
! 563: {
! 564: u_int index = cm->index, count = cm->count, i;
! 565: u_int colcount = 1 << ss->ss_depth;
! 566: int error;
! 567: u_int8_t ramp[256], *c, *r;
! 568:
! 569: if (index >= colcount || count > colcount - index)
! 570: return (EINVAL);
! 571:
! 572: /* extract reds */
! 573: c = ss->ss_cmap + 0 + index * 3;
! 574: for (i = count, r = ramp; i != 0; i--)
! 575: *r++ = *c, c += 3;
! 576: if ((error = copyout(ramp, cm->red, count)) != 0)
! 577: return (error);
! 578:
! 579: /* extract greens */
! 580: c = ss->ss_cmap + 1 + index * 3;
! 581: for (i = count, r = ramp; i != 0; i--)
! 582: *r++ = *c, c += 3;
! 583: if ((error = copyout(ramp, cm->green, count)) != 0)
! 584: return (error);
! 585:
! 586: /* extract blues */
! 587: c = ss->ss_cmap + 2 + index * 3;
! 588: for (i = count, r = ramp; i != 0; i--)
! 589: *r++ = *c, c += 3;
! 590: if ((error = copyout(ramp, cm->blue, count)) != 0)
! 591: return (error);
! 592:
! 593: return (0);
! 594: }
! 595:
! 596: int
! 597: lcg_putcmap(struct lcg_screen *ss, struct wsdisplay_cmap *cm)
! 598: {
! 599: u_int index = cm->index, count = cm->count;
! 600: u_int colcount = 1 << ss->ss_depth;
! 601: int i, error;
! 602: u_int8_t r[256], g[256], b[256], *nr, *ng, *nb, *c;
! 603:
! 604: if (index >= colcount || count > colcount - index)
! 605: return (EINVAL);
! 606:
! 607: if ((error = copyin(cm->red, r, count)) != 0)
! 608: return (error);
! 609: if ((error = copyin(cm->green, g, count)) != 0)
! 610: return (error);
! 611: if ((error = copyin(cm->blue, b, count)) != 0)
! 612: return (error);
! 613:
! 614: nr = r, ng = g, nb = b;
! 615: c = ss->ss_cmap + index * 3;
! 616: for (i = count; i != 0; i--) {
! 617: *c++ = *nr++;
! 618: *c++ = *ng++;
! 619: *c++ = *nb++;
! 620: }
! 621:
! 622: return (0);
! 623: }
! 624:
! 625: /* Fill the given colormap (LUT) entry. */
! 626: #define lcg_set_lut_entry(lutptr, cmap, idx, shift) \
! 627: do { \
! 628: *(lutptr)++ = LUT_ADRS_REG; \
! 629: *(lutptr)++ = (idx); \
! 630: *(lutptr)++ = LUT_COLOR_AUTOINC; \
! 631: *(lutptr)++ = (*(cmap)++) >> (shift); \
! 632: *(lutptr)++ = LUT_COLOR_AUTOINC; \
! 633: *(lutptr)++ = (*(cmap)++) >> (shift); \
! 634: *(lutptr)++ = LUT_COLOR_AUTOINC; \
! 635: *(lutptr)++ = (*(cmap)++) >> (shift); \
! 636: } while (0)
! 637:
! 638: void
! 639: lcg_loadcmap(struct lcg_screen *ss, int from, int count)
! 640: {
! 641: const u_int8_t *cmap;
! 642: u_int i;
! 643: volatile u_int8_t *lutptr;
! 644: u_int32_t vidcfg;
! 645:
! 646: /* partial updates ignored for now */
! 647: cmap = ss->ss_cmap;
! 648: lutptr = ss->ss_lut;
! 649: if (ss->ss_depth == 8) {
! 650: for (i = 0; i < 256; i++) {
! 651: lcg_set_lut_entry(lutptr, cmap, i, 0);
! 652: }
! 653: } else {
! 654: for (i = 0; i < 16; i++) {
! 655: lcg_set_lut_entry(lutptr, cmap, i, 4);
! 656: }
! 657: }
! 658:
! 659: /*
! 660: * Wait for retrace
! 661: */
! 662: while (((vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG)) &
! 663: VIDEO_VSTATE) != VIDEO_VSYNC)
! 664: DELAY(1);
! 665:
! 666: vidcfg &= ~(VIDEO_SHIFT_SEL | VIDEO_MEM_REFRESH_SEL_MASK |
! 667: VIDEO_LUT_SHIFT_SEL);
! 668: /* Do full loads if width is 1024 or 2048, split loads otherwise. */
! 669: if (ss->ss_width == 1024 || ss->ss_width == 2048)
! 670: vidcfg |= VIDEO_SHIFT_SEL | (1 << VIDEO_MEM_REFRESH_SEL_SHIFT) |
! 671: VIDEO_LUT_SHIFT_SEL;
! 672: else
! 673: vidcfg |= (2 << VIDEO_MEM_REFRESH_SEL_SHIFT);
! 674: vidcfg |= VIDEO_LUT_LOAD_SIZE; /* 2KB lut */
! 675: lcg_write_reg(ss, LCG_REG_VIDEO_CONFIG, vidcfg);
! 676: lcg_write_reg(ss, LCG_REG_LUT_CONSOLE_SEL, LUT_SEL_COLOR);
! 677: lcg_write_reg(ss, LCG_REG_LUT_COLOR_BASE_W, LCG_LUT_OFFSET);
! 678: /* Wait for end of retrace */
! 679: while (((vidcfg = lcg_read_reg(ss, LCG_REG_VIDEO_CONFIG)) &
! 680: VIDEO_VSTATE) == VIDEO_VSYNC)
! 681: DELAY(1);
! 682: lcg_write_reg(ss, LCG_REG_LUT_CONSOLE_SEL, LUT_SEL_CONSOLE);
! 683: }
! 684:
! 685: void
! 686: lcg_resetcmap(struct lcg_screen *ss)
! 687: {
! 688: if (ss->ss_depth == 8)
! 689: bcopy(rasops_cmap, ss->ss_cmap, sizeof(ss->ss_cmap));
! 690: else {
! 691: bcopy(rasops_cmap, ss->ss_cmap, 8 * 3);
! 692: bcopy(rasops_cmap + 0xf8 * 3, ss->ss_cmap + 8 * 3, 8 * 3);
! 693: }
! 694: lcg_loadcmap(ss, 0, 1 << ss->ss_depth);
! 695: }
! 696:
! 697: /*
! 698: * Console support code
! 699: */
! 700:
! 701: int lcgcnprobe(void);
! 702: void lcgcninit(void);
! 703:
! 704: int
! 705: lcgcnprobe()
! 706: {
! 707: extern vaddr_t virtual_avail;
! 708: u_int32_t cfg;
! 709: vaddr_t tmp;
! 710: volatile u_int8_t *ch;
! 711:
! 712: switch (vax_boardtype) {
! 713: case VAX_BTYP_46:
! 714: case VAX_BTYP_48:
! 715: if ((vax_confdata & 0x100) != 0)
! 716: break; /* doesn't use graphics console */
! 717:
! 718: tmp = virtual_avail;
! 719: ioaccess(tmp, vax_trunc_page(LCG_CONFIG_ADDR), 1);
! 720: cfg = *(volatile u_int32_t *)
! 721: (tmp + (LCG_CONFIG_ADDR & VAX_PGOFSET));
! 722:
! 723: if (lcg_probe_screen(cfg, NULL, NULL) <= 0)
! 724: break; /* unsupported configuration */
! 725:
! 726: /*
! 727: * Check for video memory.
! 728: * We can not use badaddr() on these models.
! 729: */
! 730: ioaccess(tmp, LCG_FB_ADDR, 1);
! 731: ch = (volatile u_int8_t *)tmp;
! 732: *ch = 0x01;
! 733: if ((*ch & 0x01) == 0)
! 734: break;
! 735: *ch = 0x00;
! 736: if ((*ch & 0x01) != 0)
! 737: break;
! 738:
! 739: return (1);
! 740:
! 741: default:
! 742: break;
! 743: }
! 744:
! 745: return (0);
! 746: }
! 747:
! 748: /*
! 749: * Called very early to setup the glass tty as console.
! 750: * Because it's called before the VM system is initialized, virtual memory
! 751: * for the framebuffer can be stolen directly without disturbing anything.
! 752: */
! 753: void
! 754: lcgcninit()
! 755: {
! 756: struct lcg_screen *ss = &lcg_consscr;
! 757: extern vaddr_t virtual_avail;
! 758: vaddr_t tmp;
! 759: long defattr;
! 760: struct rasops_info *ri;
! 761:
! 762: tmp = virtual_avail;
! 763: ioaccess(tmp, vax_trunc_page(LCG_CONFIG_ADDR), 1);
! 764: ss->ss_cfg = *(volatile u_int32_t *)
! 765: (tmp + (LCG_CONFIG_ADDR & VAX_PGOFSET));
! 766:
! 767: ss->ss_depth = lcg_probe_screen(ss->ss_cfg,
! 768: &ss->ss_width, &ss->ss_height);
! 769:
! 770: ss->ss_fbsize = roundup(ss->ss_width * ss->ss_height, PAGE_SIZE);
! 771:
! 772: ss->ss_addr = (caddr_t)virtual_avail;
! 773: virtual_avail += ss->ss_fbsize;
! 774: ioaccess((vaddr_t)ss->ss_addr, LCG_FB_ADDR, ss->ss_fbsize / VAX_NBPG);
! 775:
! 776: ss->ss_reg = virtual_avail;
! 777: virtual_avail += LCG_REG_SIZE;
! 778: ioaccess(ss->ss_reg, LCG_REG_ADDR, LCG_REG_SIZE / VAX_NBPG);
! 779:
! 780: ss->ss_lut = (volatile u_int8_t *)virtual_avail;
! 781: virtual_avail += LCG_LUT_SIZE;
! 782: ioaccess((vaddr_t)ss->ss_lut, LCG_LUT_ADDR + LCG_LUT_OFFSET,
! 783: LCG_LUT_SIZE / VAX_NBPG);
! 784:
! 785: virtual_avail = round_page(virtual_avail);
! 786:
! 787: /* this had better not fail as we can't recover there */
! 788: if (lcg_setup_screen(ss) != 0)
! 789: panic(__func__);
! 790:
! 791: ri = &ss->ss_ri;
! 792: ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
! 793: wsdisplay_cnattach(&lcg_stdscreen, ri, 0, 0, defattr);
! 794: }
CVSweb