Annotation of sys/dev/pci/tga.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: tga.c,v 1.29 2006/12/17 22:18:16 miod Exp $ */
! 2: /* $NetBSD: tga.c,v 1.40 2002/03/13 15:05:18 ad Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995, 1996 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Author: Chris G. Demetriou
! 9: *
! 10: * Permission to use, copy, modify and distribute this software and
! 11: * its documentation is hereby granted, provided that both the copyright
! 12: * notice and this permission notice appear in all copies of the
! 13: * software, derivative works or modified versions, and any portions
! 14: * thereof, and that both notices appear in supporting documentation.
! 15: *
! 16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 19: *
! 20: * Carnegie Mellon requests users of this software to return to
! 21: *
! 22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 23: * School of Computer Science
! 24: * Carnegie Mellon University
! 25: * Pittsburgh PA 15213-3890
! 26: *
! 27: * any improvements or extensions that they make and grant Carnegie the
! 28: * rights to redistribute these changes.
! 29: */
! 30:
! 31: #include <sys/param.h>
! 32: #include <sys/systm.h>
! 33: #include <sys/kernel.h>
! 34: #include <sys/device.h>
! 35: #include <sys/conf.h>
! 36: #include <sys/malloc.h>
! 37: #include <sys/buf.h>
! 38: #include <sys/ioctl.h>
! 39:
! 40: #include <machine/bus.h>
! 41: #include <machine/intr.h>
! 42:
! 43: #include <dev/pci/pcireg.h>
! 44: #include <dev/pci/pcivar.h>
! 45: #include <dev/pci/pcidevs.h>
! 46: #include <dev/pci/tgareg.h>
! 47: #include <dev/pci/tgavar.h>
! 48: #include <dev/ic/bt485reg.h>
! 49: #include <dev/ic/bt485var.h>
! 50: #include <dev/ic/bt463reg.h>
! 51: #include <dev/ic/bt463var.h>
! 52: #include <dev/ic/ibm561var.h>
! 53:
! 54: #include <dev/wscons/wsconsio.h>
! 55: #include <dev/rasops/rasops.h>
! 56: #include <dev/wsfont/wsfont.h>
! 57:
! 58: #if defined(__alpha__) || defined(__mips__)
! 59: #include <uvm/uvm_extern.h>
! 60: #endif
! 61:
! 62: #ifdef __alpha__
! 63: #include <machine/pte.h>
! 64: #endif
! 65: #ifdef __mips__
! 66: #include <mips/pte.h>
! 67: #endif
! 68:
! 69: int tgamatch(struct device *, struct cfdata *, void *);
! 70: void tgaattach(struct device *, struct device *, void *);
! 71: int tgaprint(void *, const char *);
! 72:
! 73: struct cfdriver tga_cd = {
! 74: NULL, "tga", DV_DULL
! 75: };
! 76:
! 77: struct cfattach tga_ca = {
! 78: sizeof(struct tga_softc), (cfmatch_t)tgamatch, tgaattach,
! 79: };
! 80:
! 81: int tga_identify(struct tga_devconfig *);
! 82: const struct tga_conf *tga_getconf(int);
! 83: void tga_getdevconfig(bus_space_tag_t memt, pci_chipset_tag_t pc,
! 84: pcitag_t tag, struct tga_devconfig *dc);
! 85: unsigned tga_getdotclock(struct tga_devconfig *dc);
! 86:
! 87: struct tga_devconfig tga_console_dc;
! 88:
! 89: int tga_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 90: paddr_t tga_mmap(void *, off_t, int);
! 91: void tga_copyrows(void *, int, int, int);
! 92: void tga_copycols(void *, int, int, int, int);
! 93: int tga_alloc_screen(void *, const struct wsscreen_descr *,
! 94: void **, int *, int *, long *);
! 95: void tga_free_screen(void *, void *);
! 96: int tga_show_screen(void *, void *, int,
! 97: void (*) (void *, int, int), void *);
! 98: void tga_burner(void *, u_int, u_int);
! 99: int tga_rop(struct rasops_info *, int, int, int, int,
! 100: struct rasops_info *, int, int);
! 101: int tga_rop_vtov(struct rasops_info *, int, int, int,
! 102: int, struct rasops_info *, int, int );
! 103: void tga_putchar(void *c, int row, int col, u_int uc, long attr);
! 104: void tga_eraserows(void *, int, int, long);
! 105: void tga_erasecols(void *, int, int, int, long);
! 106: void tga2_init(struct tga_devconfig *);
! 107:
! 108: void tga_config_interrupts(struct device *);
! 109:
! 110: /* RAMDAC interface functions */
! 111: int tga_sched_update(void *, void (*)(void *));
! 112: void tga_ramdac_wr(void *, u_int, u_int8_t);
! 113: u_int8_t tga_ramdac_rd(void *, u_int);
! 114: void tga_bt463_wr(void *, u_int, u_int8_t);
! 115: u_int8_t tga_bt463_rd(void *, u_int);
! 116: void tga2_ramdac_wr(void *, u_int, u_int8_t);
! 117: u_int8_t tga2_ramdac_rd(void *, u_int);
! 118:
! 119: /* Interrupt handler */
! 120: int tga_intr(void *);
! 121:
! 122: /* The NULL entries will get filled in by rasops_init().
! 123: * XXX and the non-NULL ones will be overwritten; reset after calling it.
! 124: */
! 125: struct wsdisplay_emulops tga_emulops = {
! 126: NULL,
! 127: NULL,
! 128: tga_putchar,
! 129: tga_copycols,
! 130: tga_erasecols,
! 131: tga_copyrows,
! 132: tga_eraserows,
! 133: NULL,
! 134: NULL
! 135: };
! 136:
! 137: struct wsscreen_descr tga_stdscreen = {
! 138: "std",
! 139: 0, 0, /* will be filled in -- XXX shouldn't, it's global */
! 140: &tga_emulops,
! 141: 0, 0,
! 142: WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
! 143: WSSCREEN_WSCOLORS | WSSCREEN_REVERSE
! 144: };
! 145:
! 146: const struct wsscreen_descr *_tga_scrlist[] = {
! 147: &tga_stdscreen,
! 148: /* XXX other formats, graphics screen? */
! 149: };
! 150:
! 151: struct wsscreen_list tga_screenlist = {
! 152: sizeof(_tga_scrlist) / sizeof(struct wsscreen_descr *), _tga_scrlist
! 153: };
! 154:
! 155: struct wsdisplay_accessops tga_accessops = {
! 156: tga_ioctl,
! 157: tga_mmap,
! 158: tga_alloc_screen,
! 159: tga_free_screen,
! 160: tga_show_screen,
! 161: NULL, /* load_font */
! 162: NULL, /* scrollback */
! 163: NULL, /* getchar */
! 164: tga_burner,
! 165: };
! 166:
! 167: void tga_blank(struct tga_devconfig *);
! 168: void tga_unblank(struct tga_devconfig *);
! 169:
! 170: #ifdef TGA_DEBUG
! 171: #define DPRINTF(...) printf (__VA_ARGS__)
! 172: #define DPRINTFN(n, ...) if (tgadebug > (n)) printf (__VA_ARGS__)
! 173: int tgadebug = 0;
! 174: #else
! 175: #define DPRINTF(...)
! 176: #define DPRINTFN(n,...)
! 177: #endif
! 178:
! 179: const struct pci_matchid tga_devices[] = {
! 180: { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21030 },
! 181: { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_PBXGB },
! 182: };
! 183:
! 184: int
! 185: tgamatch(parent, match, aux)
! 186: struct device *parent;
! 187: struct cfdata *match;
! 188: void *aux;
! 189: {
! 190: if (pci_matchbyid((struct pci_attach_args *)aux, tga_devices,
! 191: sizeof(tga_devices) / sizeof(tga_devices[0])))
! 192: return (10); /* need to return more than vga_pci here! */
! 193:
! 194: return (0);
! 195: }
! 196:
! 197: void
! 198: tga_getdevconfig(memt, pc, tag, dc)
! 199: bus_space_tag_t memt;
! 200: pci_chipset_tag_t pc;
! 201: pcitag_t tag;
! 202: struct tga_devconfig *dc;
! 203: {
! 204: const struct tga_conf *tgac;
! 205: struct rasops_info *rip;
! 206: int cookie;
! 207: bus_size_t pcisize;
! 208: int i;
! 209:
! 210: dc->dc_memt = memt;
! 211:
! 212: dc->dc_pcitag = tag;
! 213:
! 214: DPRINTF("tga_getdevconfig: Getting map info\n");
! 215: /* XXX magic number */
! 216: if (pci_mapreg_info(pc, tag, 0x10,
! 217: PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
! 218: &dc->dc_pcipaddr, &pcisize, NULL))
! 219: return;
! 220:
! 221: DPRINTF("tga_getdevconfig: preparing to map\n");
! 222: #ifdef __OpenBSD__
! 223: if (bus_space_map(memt, dc->dc_pcipaddr, pcisize, 1, &dc->dc_memh))
! 224: return;
! 225: dc->dc_vaddr = dc->dc_memh;
! 226: #else
! 227: if (bus_space_map(memt, dc->dc_pcipaddr, pcisize,
! 228: BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR, &dc->dc_memh))
! 229: return;
! 230: dc->dc_vaddr = (vaddr_t) bus_space_vaddr(memt, dc->dc_memh);
! 231: #endif
! 232: DPRINTF("tga_getdevconfig: mapped\n");
! 233:
! 234: #ifdef __alpha__
! 235: dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */
! 236: #endif
! 237: #ifdef arc
! 238: bus_space_paddr(memt, dc->dc_memh, &dc->dc_paddr);
! 239: #endif
! 240: DPRINTF("tga_getdevconfig: allocating subregion\n");
! 241: bus_space_subregion(dc->dc_memt, dc->dc_memh,
! 242: TGA_MEM_CREGS, TGA_CREGS_SIZE,
! 243: &dc->dc_regs);
! 244:
! 245: DPRINTF("tga_getdevconfig: going to identify\n");
! 246: dc->dc_tga_type = tga_identify(dc);
! 247:
! 248: DPRINTF("tga_getdevconfig: preparing to get config\n");
! 249: tgac = dc->dc_tgaconf = tga_getconf(dc->dc_tga_type);
! 250: if (tgac == NULL)
! 251: return;
! 252:
! 253: #if 0
! 254: /* XXX on the Alpha, pcisize = 4 * cspace_size. */
! 255: if (tgac->tgac_cspace_size != pcisize) /* sanity */
! 256: panic("tga_getdevconfig: memory size mismatch?");
! 257: #endif
! 258:
! 259: DPRINTF("tga_getdevconfig: get revno\n");
! 260: switch (TGARREG(dc, TGA_REG_GREV) & 0xff) {
! 261: case 0x01:
! 262: case 0x02:
! 263: case 0x03:
! 264: case 0x04:
! 265: dc->dc_tga2 = 0;
! 266: break;
! 267: case 0x20:
! 268: case 0x21:
! 269: case 0x22:
! 270: dc->dc_tga2 = 1;
! 271: break;
! 272: default:
! 273: panic("tga_getdevconfig: TGA Revision not recognized");
! 274: }
! 275:
! 276: if (dc->dc_tga2) {
! 277: tga2_init(dc);
! 278: }
! 279:
! 280: i = TGARREG(dc, TGA_REG_VHCR) & 0x1ff;
! 281: DPRINTF("tga_getdevconfig: TGA_REG_VHCR & 0x1ff = %d\n", i);
! 282: switch (i) { /* XXX */
! 283: case 0:
! 284: dc->dc_wid = 8192;
! 285: break;
! 286:
! 287: case 1:
! 288: dc->dc_wid = 8196;
! 289: break;
! 290:
! 291: default:
! 292: dc->dc_wid = (TGARREG(dc, TGA_REG_VHCR) & 0x1ff) * 4; /* XXX */
! 293: break;
! 294: }
! 295:
! 296: DPRINTF("tga_getdevconfig: dc->dc_wid = %d\n", dc->dc_wid);
! 297: /*
! 298: * XXX XXX Turning off "odd" shouldn't be necessary,
! 299: * XXX XXX but I can't make X work with the weird size.
! 300: */
! 301: DPRINTF("tga_getdevconfig: beginning magic incantation\n");
! 302: if ((TGARREG(dc, TGA_REG_VHCR) & 0x00000001) != 0 && /* XXX */
! 303: (TGARREG(dc, TGA_REG_VHCR) & 0x80000000) != 0) { /* XXX */
! 304: TGAWREG(dc, TGA_REG_VHCR,
! 305: (TGARREG(dc, TGA_REG_VHCR) & ~0x80000001));
! 306: dc->dc_wid -= 4;
! 307: }
! 308:
! 309: dc->dc_rowbytes = dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8);
! 310: dc->dc_ht = (TGARREG(dc, TGA_REG_VVCR) & 0x7ff); /* XXX */
! 311: DPRINTF("tga_getdevconfig: rowbytes = %d, tgac_phys_depth = %d\n"
! 312: " dc_wid = %d, dc_ht = %d\n",
! 313: dc->dc_rowbytes, dc->dc_tgaconf->tgac_phys_depth,
! 314: dc->dc_wid, dc->dc_ht);
! 315:
! 316: /* XXX this seems to be what DEC does */
! 317: DPRINTF("tga_getdevconfig: more magic\n");
! 318: TGAWREG(dc, TGA_REG_CCBR, 0);
! 319: TGAWREG(dc, TGA_REG_VVBR, 1);
! 320: dc->dc_videobase = dc->dc_vaddr + tgac->tgac_dbuf[0] +
! 321: 1 * tgac->tgac_vvbr_units;
! 322: dc->dc_blanked = 1;
! 323: tga_unblank(dc);
! 324:
! 325: DPRINTF("tga_getdevconfig: dc_videobase = 0x%016llx\n"
! 326: " dc_vaddr = 0x%016llx\n"
! 327: " tgac_dbuf[0] = %d\n"
! 328: " tgac_vvbr_units = %d\n",
! 329: dc->dc_videobase, dc->dc_vaddr, tgac->tgac_dbuf[0],
! 330: tgac->tgac_vvbr_units);
! 331:
! 332: /*
! 333: * Set all bits in the pixel mask, to enable writes to all pixels.
! 334: * It seems that the console firmware clears some of them
! 335: * under some circumstances, which causes cute vertical stripes.
! 336: */
! 337: DPRINTF("tga_getdevconfig: set pixel mask\n");
! 338: TGAWREG(dc, TGA_REG_GPXR_P, 0xffffffff);
! 339:
! 340: /* clear the screen */
! 341: DPRINTF("tga_getdevconfig: clear screen\n");
! 342: for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
! 343: *(u_int32_t *)(dc->dc_videobase + i) = 0;
! 344:
! 345: DPRINTF("tga_getdevconfig: raster ops\n");
! 346: /* Initialize rasops descriptor */
! 347: rip = &dc->dc_rinfo;
! 348: rip->ri_flg = RI_CENTER;
! 349: rip->ri_depth = tgac->tgac_phys_depth;
! 350: rip->ri_bits = (void *)dc->dc_videobase;
! 351: rip->ri_width = dc->dc_wid;
! 352: rip->ri_height = dc->dc_ht;
! 353: rip->ri_stride = dc->dc_rowbytes;
! 354: rip->ri_hw = dc;
! 355:
! 356: if (tgac->tgac_phys_depth == 32) {
! 357: rip->ri_rnum = 8;
! 358: rip->ri_gnum = 8;
! 359: rip->ri_bnum = 8;
! 360: rip->ri_rpos = 16;
! 361: rip->ri_gpos = 8;
! 362: rip->ri_bpos = 0;
! 363: }
! 364:
! 365: DPRINTF("tga_getdevconfig: wsfont_init\n");
! 366: wsfont_init();
! 367: if (rip->ri_width > 80*12)
! 368: /* High res screen, choose a big font */
! 369: cookie = wsfont_find(NULL, 12, 0, 0);
! 370: else
! 371: /* lower res, choose a 8 pixel wide font */
! 372: cookie = wsfont_find(NULL, 8, 0, 0);
! 373: if (cookie <= 0)
! 374: cookie = wsfont_find(NULL, 0, 0, 0);
! 375: if (cookie <= 0) {
! 376: printf("tga: no appropriate fonts.\n");
! 377: return;
! 378: }
! 379:
! 380: /* the accelerated tga_putchar() needs LSbit left */
! 381: if (wsfont_lock(cookie, &rip->ri_font,
! 382: WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
! 383: printf("tga: couldn't lock font\n");
! 384: return;
! 385: }
! 386: rip->ri_wsfcookie = cookie;
! 387: /* fill screen size */
! 388: rasops_init(rip, rip->ri_height / rip->ri_font->fontheight,
! 389: rip->ri_width / rip->ri_font->fontwidth);
! 390:
! 391: /* add our accelerated functions */
! 392: /* XXX shouldn't have to do this; rasops should leave non-NULL
! 393: * XXX entries alone.
! 394: */
! 395: rip->ri_ops.copyrows = tga_copyrows;
! 396: rip->ri_ops.eraserows = tga_eraserows;
! 397: rip->ri_ops.erasecols = tga_erasecols;
! 398: rip->ri_ops.copycols = tga_copycols;
! 399: rip->ri_ops.putchar = tga_putchar;
! 400:
! 401: tga_stdscreen.nrows = rip->ri_rows;
! 402: tga_stdscreen.ncols = rip->ri_cols;
! 403: tga_stdscreen.textops = &rip->ri_ops;
! 404: tga_stdscreen.capabilities = rip->ri_caps;
! 405:
! 406: dc->dc_intrenabled = 0;
! 407: }
! 408:
! 409: void
! 410: tgaattach(parent, self, aux)
! 411: struct device *parent, *self;
! 412: void *aux;
! 413: {
! 414: struct pci_attach_args *pa = aux;
! 415: struct tga_softc *sc = (struct tga_softc *)self;
! 416: struct wsemuldisplaydev_attach_args aa;
! 417: pci_intr_handle_t intrh;
! 418: const char *intrstr;
! 419: u_int8_t rev;
! 420: int console;
! 421:
! 422: #if defined(__alpha__) || defined(arc)
! 423: console = (pa->pa_tag == tga_console_dc.dc_pcitag);
! 424: #else
! 425: console = 0;
! 426: #endif
! 427: if (console) {
! 428: sc->sc_dc = &tga_console_dc;
! 429: sc->nscreens = 1;
! 430: } else {
! 431: sc->sc_dc = (struct tga_devconfig *)
! 432: malloc(sizeof(struct tga_devconfig), M_DEVBUF, M_NOWAIT);
! 433: if (sc->sc_dc == NULL)
! 434: return;
! 435: bzero(sc->sc_dc, sizeof(struct tga_devconfig));
! 436: tga_getdevconfig(pa->pa_memt, pa->pa_pc, pa->pa_tag,
! 437: sc->sc_dc);
! 438: }
! 439: if (sc->sc_dc->dc_vaddr == NULL) {
! 440: printf(": couldn't map memory space; punt!\n");
! 441: return;
! 442: }
! 443:
! 444: /* XXX say what's going on. */
! 445: intrstr = NULL;
! 446: if (pci_intr_map(pa, &intrh)) {
! 447: printf(": couldn't map interrupt");
! 448: return;
! 449: }
! 450: intrstr = pci_intr_string(pa->pa_pc, intrh);
! 451: sc->sc_intr = pci_intr_establish(pa->pa_pc, intrh, IPL_TTY, tga_intr,
! 452: sc->sc_dc, sc->sc_dev.dv_xname);
! 453: if (sc->sc_intr == NULL) {
! 454: printf(": couldn't establish interrupt");
! 455: if (intrstr != NULL)
! 456: printf("at %s", intrstr);
! 457: printf("\n");
! 458: return;
! 459: }
! 460:
! 461: rev = PCI_REVISION(pa->pa_class);
! 462: switch (rev) {
! 463: case 0x1:
! 464: case 0x2:
! 465: case 0x3:
! 466: printf(": DC21030 step %c", 'A' + rev - 1);
! 467: break;
! 468: case 0x20:
! 469: printf(": TGA2 abstract software model");
! 470: break;
! 471: case 0x21:
! 472: case 0x22:
! 473: printf(": TGA2 pass %d", rev - 0x20);
! 474: break;
! 475:
! 476: default:
! 477: printf("unknown stepping (0x%x)", rev);
! 478: break;
! 479: }
! 480: printf(", ");
! 481:
! 482: /*
! 483: * Get RAMDAC function vectors and call the RAMDAC functions
! 484: * to allocate its private storage and pass that back to us.
! 485: */
! 486:
! 487: DPRINTF("tgaattach: Get RAMDAC functions\n");
! 488: sc->sc_dc->dc_ramdac_funcs = sc->sc_dc->dc_tgaconf->ramdac_funcs();
! 489: if (!sc->sc_dc->dc_tga2) {
! 490: DPRINTF("tgaattach: !sc->sc_dc->dc_tga2\n");
! 491: DPRINTF("tgaattach: sc->sc_dc->dc_tgaconf->ramdac_funcs %s "
! 492: "bt485_funcs\n",
! 493: (sc->sc_dc->dc_tgaconf->ramdac_funcs == bt485_funcs)
! 494: ? "==" : "!=");
! 495: if (sc->sc_dc->dc_tgaconf->ramdac_funcs == bt485_funcs)
! 496: sc->sc_dc->dc_ramdac_cookie =
! 497: sc->sc_dc->dc_ramdac_funcs->ramdac_register(sc->sc_dc,
! 498: tga_sched_update, tga_ramdac_wr, tga_ramdac_rd);
! 499: else
! 500: sc->sc_dc->dc_ramdac_cookie =
! 501: sc->sc_dc->dc_ramdac_funcs->ramdac_register(sc->sc_dc,
! 502: tga_sched_update, tga_bt463_wr, tga_bt463_rd);
! 503: } else {
! 504: DPRINTF("tgaattach: sc->sc_dc->dc_tga2\n");
! 505: sc->sc_dc->dc_ramdac_cookie =
! 506: sc->sc_dc->dc_ramdac_funcs->ramdac_register(sc->sc_dc,
! 507: tga_sched_update, tga2_ramdac_wr, tga2_ramdac_rd);
! 508:
! 509: /* XXX this is a bit of a hack, setting the dotclock here */
! 510: if (sc->sc_dc->dc_tgaconf->ramdac_funcs != bt485_funcs)
! 511: (*sc->sc_dc->dc_ramdac_funcs->ramdac_set_dotclock)
! 512: (sc->sc_dc->dc_ramdac_cookie,
! 513: tga_getdotclock(sc->sc_dc));
! 514: }
! 515: DPRINTF("tgaattach: sc->sc_dc->dc_ramdac_cookie = 0x%016llx\n",
! 516: sc->sc_dc->dc_ramdac_cookie);
! 517: /*
! 518: * Initialize the RAMDAC. Initialization includes disabling
! 519: * cursor, setting a sane colormap, etc.
! 520: */
! 521: DPRINTF("tgaattach: Initializing RAMDAC.\n");
! 522: (*sc->sc_dc->dc_ramdac_funcs->ramdac_init)(sc->sc_dc->dc_ramdac_cookie);
! 523: TGAWREG(sc->sc_dc, TGA_REG_SISR, 0x00000001); /* XXX */
! 524:
! 525: if (sc->sc_dc->dc_tgaconf == NULL) {
! 526: printf("unknown board configuration\n");
! 527: return;
! 528: }
! 529: printf("board type %s\n", sc->sc_dc->dc_tgaconf->tgac_name);
! 530: printf("%s: %d x %d, %dbpp, %s RAMDAC\n", sc->sc_dev.dv_xname,
! 531: sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
! 532: sc->sc_dc->dc_tgaconf->tgac_phys_depth,
! 533: sc->sc_dc->dc_ramdac_funcs->ramdac_name);
! 534:
! 535: if (intrstr != NULL)
! 536: printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname,
! 537: intrstr);
! 538:
! 539: aa.console = console;
! 540: aa.scrdata = &tga_screenlist;
! 541: aa.accessops = &tga_accessops;
! 542: aa.accesscookie = sc;
! 543: aa.defaultscreens = 0;
! 544:
! 545: config_found(self, &aa, wsemuldisplaydevprint);
! 546:
! 547: #ifdef __NetBSD__
! 548: config_interrupts(self, tga_config_interrupts);
! 549: #else
! 550: tga_config_interrupts(self);
! 551: #endif
! 552: }
! 553:
! 554: void
! 555: tga_config_interrupts (d)
! 556: struct device *d;
! 557: {
! 558: struct tga_softc *sc = (struct tga_softc *)d;
! 559: sc->sc_dc->dc_intrenabled = 1;
! 560: }
! 561:
! 562:
! 563: int
! 564: tga_ioctl(v, cmd, data, flag, p)
! 565: void *v;
! 566: u_long cmd;
! 567: caddr_t data;
! 568: int flag;
! 569: struct proc *p;
! 570: {
! 571: struct tga_softc *sc = v;
! 572: struct tga_devconfig *dc = sc->sc_dc;
! 573: struct ramdac_funcs *dcrf = dc->dc_ramdac_funcs;
! 574: struct ramdac_cookie *dcrc = dc->dc_ramdac_cookie;
! 575:
! 576: switch (cmd) {
! 577: case WSDISPLAYIO_GTYPE:
! 578: *(u_int *)data = WSDISPLAY_TYPE_TGA;
! 579: break;
! 580:
! 581: case WSDISPLAYIO_SMODE:
! 582: sc->sc_mode = *(u_int *)data;
! 583: switch (sc->sc_mode) {
! 584: case WSDISPLAYIO_MODE_DUMBFB:
! 585: /* in dump fb mode start the framebuffer at 0 */
! 586: TGAWREG(dc, TGA_REG_VVBR, 0);
! 587: break;
! 588: default:
! 589: /* XXX it this useful, except for not breaking Xtga? */
! 590: TGAWREG(dc, TGA_REG_VVBR, 1);
! 591: break;
! 592: }
! 593: break;
! 594:
! 595: case WSDISPLAYIO_GINFO:
! 596: #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
! 597: wsd_fbip->height = sc->sc_dc->dc_ht;
! 598: wsd_fbip->width = sc->sc_dc->dc_wid;
! 599: wsd_fbip->depth = sc->sc_dc->dc_tgaconf->tgac_phys_depth;
! 600: wsd_fbip->cmsize = 1024; /* XXX ??? */
! 601: #undef wsd_fbip
! 602: break;
! 603:
! 604: case WSDISPLAYIO_LINEBYTES:
! 605: *(u_int *)data = sc->sc_dc->dc_rowbytes;
! 606: break;
! 607:
! 608: case WSDISPLAYIO_GETCMAP:
! 609: return (*dcrf->ramdac_get_cmap)(dcrc,
! 610: (struct wsdisplay_cmap *)data);
! 611: case WSDISPLAYIO_PUTCMAP:
! 612: return (*dcrf->ramdac_set_cmap)(dcrc,
! 613: (struct wsdisplay_cmap *)data);
! 614:
! 615: case WSDISPLAYIO_SVIDEO:
! 616: case WSDISPLAYIO_GVIDEO:
! 617: break;
! 618:
! 619: case WSDISPLAYIO_GCURPOS:
! 620: return (*dcrf->ramdac_get_curpos)(dcrc,
! 621: (struct wsdisplay_curpos *)data);
! 622:
! 623: case WSDISPLAYIO_SCURPOS:
! 624: return (*dcrf->ramdac_set_curpos)(dcrc,
! 625: (struct wsdisplay_curpos *)data);
! 626:
! 627: case WSDISPLAYIO_GCURMAX:
! 628: return (*dcrf->ramdac_get_curmax)(dcrc,
! 629: (struct wsdisplay_curpos *)data);
! 630:
! 631: case WSDISPLAYIO_GCURSOR:
! 632: return (*dcrf->ramdac_get_cursor)(dcrc,
! 633: (struct wsdisplay_cursor *)data);
! 634:
! 635: case WSDISPLAYIO_SCURSOR:
! 636: return (*dcrf->ramdac_set_cursor)(dcrc,
! 637: (struct wsdisplay_cursor *)data);
! 638:
! 639: default:
! 640: return (-1);
! 641: }
! 642:
! 643: return (0);
! 644: }
! 645:
! 646: int
! 647: tga_sched_update(v, f)
! 648: void *v;
! 649: void (*f)(void *);
! 650: {
! 651: struct tga_devconfig *dc = v;
! 652:
! 653: if (dc->dc_intrenabled) {
! 654: /* Arrange for f to be called at the next end-of-frame interrupt */
! 655: dc->dc_ramdac_intr = f;
! 656: TGAWREG(dc, TGA_REG_SISR, 0x00010000);
! 657: } else {
! 658: /* Spin until the end-of-frame, then call f */
! 659: TGAWREG(dc, TGA_REG_SISR, 0x00010001);
! 660: TGAREGWB(dc, TGA_REG_SISR, 1);
! 661: while ((TGARREG(dc, TGA_REG_SISR) & 0x00000001) == 0)
! 662: ;
! 663: f(dc->dc_ramdac_cookie);
! 664: TGAWREG(dc, TGA_REG_SISR, 0x00000001);
! 665: TGAREGWB(dc, TGA_REG_SISR, 1);
! 666: }
! 667:
! 668: return 0;
! 669: }
! 670:
! 671: int
! 672: tga_intr(v)
! 673: void *v;
! 674: {
! 675: struct tga_devconfig *dc = v;
! 676: struct ramdac_cookie *dcrc= dc->dc_ramdac_cookie;
! 677:
! 678: u_int32_t reg;
! 679:
! 680: reg = TGARREG(dc, TGA_REG_SISR);
! 681: if (( reg & 0x00010001) != 0x00010001) {
! 682: /* Odd. We never set any of the other interrupt enables. */
! 683: if ((reg & 0x1f) != 0) {
! 684: /* Clear the mysterious pending interrupts. */
! 685: TGAWREG(dc, TGA_REG_SISR, (reg & 0x1f));
! 686: TGAREGWB(dc, TGA_REG_SISR, 1);
! 687: /* This was our interrupt, even if we're puzzled as to why
! 688: * we got it. Don't make the interrupt handler think it
! 689: * was a stray.
! 690: */
! 691: return -1;
! 692: } else {
! 693: return 0;
! 694: }
! 695: }
! 696: /* if we have something to do, do it */
! 697: if (dc->dc_ramdac_intr) {
! 698: dc->dc_ramdac_intr(dcrc);
! 699: dc->dc_ramdac_intr = NULL;
! 700: }
! 701: TGAWREG(dc, TGA_REG_SISR, 0x00000001);
! 702: TGAREGWB(dc, TGA_REG_SISR, 1);
! 703: return (1);
! 704: }
! 705:
! 706: paddr_t
! 707: tga_mmap(v, offset, prot)
! 708: void *v;
! 709: off_t offset;
! 710: int prot;
! 711: {
! 712: struct tga_softc *sc = v;
! 713: struct tga_devconfig *dc = sc->sc_dc;
! 714:
! 715: if (offset >= dc->dc_tgaconf->tgac_cspace_size || offset < 0)
! 716: return -1;
! 717:
! 718: if (sc->sc_mode == WSDISPLAYIO_MODE_DUMBFB) {
! 719: /*
! 720: * The framebuffer starts at the upper half of tga mem
! 721: */
! 722: offset += dc->dc_tgaconf->tgac_cspace_size / 2;
! 723: }
! 724: #if defined(__alpha__) || defined(__mips__)
! 725: return atop(sc->sc_dc->dc_paddr + offset);
! 726: #else
! 727: return (-1);
! 728: #endif
! 729: }
! 730:
! 731: int
! 732: tga_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
! 733: void *v;
! 734: const struct wsscreen_descr *type;
! 735: void **cookiep;
! 736: int *curxp, *curyp;
! 737: long *attrp;
! 738: {
! 739: struct tga_softc *sc = v;
! 740: long defattr;
! 741:
! 742: if (sc->nscreens > 0)
! 743: return (ENOMEM);
! 744:
! 745: *cookiep = &sc->sc_dc->dc_rinfo; /* one and only for now */
! 746: *curxp = 0;
! 747: *curyp = 0;
! 748: sc->sc_dc->dc_rinfo.ri_ops.alloc_attr(&sc->sc_dc->dc_rinfo,
! 749: 0, 0, 0, &defattr);
! 750: *attrp = defattr;
! 751: sc->nscreens++;
! 752: return (0);
! 753: }
! 754:
! 755: void
! 756: tga_free_screen(v, cookie)
! 757: void *v;
! 758: void *cookie;
! 759: {
! 760: struct tga_softc *sc = v;
! 761:
! 762: if (sc->sc_dc == &tga_console_dc)
! 763: panic("tga_free_screen: console");
! 764:
! 765: sc->nscreens--;
! 766: }
! 767:
! 768: int
! 769: tga_show_screen(v, cookie, waitok, cb, cbarg)
! 770: void *v;
! 771: void *cookie;
! 772: int waitok;
! 773: void (*cb)(void *, int, int);
! 774: void *cbarg;
! 775: {
! 776:
! 777: return (0);
! 778: }
! 779:
! 780: int
! 781: tga_cnattach(iot, memt, pc, bus, device, function)
! 782: bus_space_tag_t iot, memt;
! 783: pci_chipset_tag_t pc;
! 784: int bus, device, function;
! 785: {
! 786: struct tga_devconfig *dcp = &tga_console_dc;
! 787: long defattr;
! 788:
! 789: tga_getdevconfig(memt, pc,
! 790: pci_make_tag(pc, bus, device, function), dcp);
! 791:
! 792: /* sanity checks */
! 793: if (dcp->dc_vaddr == NULL)
! 794: panic("tga_console(%d, %d): couldn't map memory space",
! 795: device, function);
! 796: if (dcp->dc_tgaconf == NULL)
! 797: panic("tga_console(%d, %d): unknown board configuration",
! 798: device, function);
! 799:
! 800: /*
! 801: * Initialize the RAMDAC but DO NOT allocate any private storage.
! 802: * Initialization includes disabling cursor, setting a sane
! 803: * colormap, etc. It will be reinitialized in tgaattach().
! 804: */
! 805: if (dcp->dc_tga2) {
! 806: if (dcp->dc_tgaconf->ramdac_funcs == bt485_funcs)
! 807: bt485_cninit(dcp, tga_sched_update, tga2_ramdac_wr,
! 808: tga2_ramdac_rd);
! 809: else
! 810: ibm561_cninit(dcp, tga_sched_update, tga2_ramdac_wr,
! 811: tga2_ramdac_rd, tga_getdotclock(dcp));
! 812: } else {
! 813: if (dcp->dc_tgaconf->ramdac_funcs == bt485_funcs)
! 814: bt485_cninit(dcp, tga_sched_update, tga_ramdac_wr,
! 815: tga_ramdac_rd);
! 816: else {
! 817: bt463_cninit(dcp, tga_sched_update, tga_bt463_wr,
! 818: tga_bt463_rd);
! 819: }
! 820: }
! 821: dcp->dc_rinfo.ri_ops.alloc_attr(&dcp->dc_rinfo, 0, 0, 0, &defattr);
! 822: wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rinfo, 0, 0, defattr);
! 823:
! 824: return(0);
! 825: }
! 826:
! 827: /*
! 828: * Functions to blank and unblank the display.
! 829: */
! 830: void
! 831: tga_burner(v, on, flags)
! 832: void *v;
! 833: u_int on, flags;
! 834: {
! 835: struct tga_softc *sc = v;
! 836:
! 837: if (on) {
! 838: tga_unblank(sc->sc_dc);
! 839: } else {
! 840: tga_blank(sc->sc_dc);
! 841: }
! 842: }
! 843:
! 844: void
! 845: tga_blank(dc)
! 846: struct tga_devconfig *dc;
! 847: {
! 848:
! 849: if (!dc->dc_blanked) {
! 850: dc->dc_blanked = 1;
! 851: /* XXX */
! 852: TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) | VVR_BLANK);
! 853: }
! 854: }
! 855:
! 856: void
! 857: tga_unblank(dc)
! 858: struct tga_devconfig *dc;
! 859: {
! 860:
! 861: if (dc->dc_blanked) {
! 862: dc->dc_blanked = 0;
! 863: /* XXX */
! 864: TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) & ~VVR_BLANK);
! 865: }
! 866: }
! 867:
! 868: /*
! 869: * Functions to manipulate the built-in cursor handing hardware.
! 870: */
! 871: int
! 872: tga_builtin_set_cursor(dc, cursorp)
! 873: struct tga_devconfig *dc;
! 874: struct wsdisplay_cursor *cursorp;
! 875: {
! 876: struct ramdac_funcs *dcrf = dc->dc_ramdac_funcs;
! 877: struct ramdac_cookie *dcrc = dc->dc_ramdac_cookie;
! 878: u_int count, v;
! 879: int error;
! 880:
! 881: v = cursorp->which;
! 882: if (v & WSDISPLAY_CURSOR_DOCMAP) {
! 883: error = dcrf->ramdac_check_curcmap(dcrc, cursorp);
! 884: if (error)
! 885: return (error);
! 886: }
! 887: if (v & WSDISPLAY_CURSOR_DOSHAPE) {
! 888: if ((u_int)cursorp->size.x != 64 ||
! 889: (u_int)cursorp->size.y > 64)
! 890: return (EINVAL);
! 891: }
! 892: if (v & WSDISPLAY_CURSOR_DOHOT) /* not supported */
! 893: return EINVAL;
! 894:
! 895: /* parameters are OK; do it */
! 896: if (v & WSDISPLAY_CURSOR_DOCUR) {
! 897: if (cursorp->enable)
! 898: /* XXX */
! 899: TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) | 0x04);
! 900: else
! 901: /* XXX */
! 902: TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) & ~0x04);
! 903: }
! 904: if (v & WSDISPLAY_CURSOR_DOPOS) {
! 905: TGAWREG(dc, TGA_REG_CXYR,
! 906: ((cursorp->pos.y & 0xfff) << 12) | (cursorp->pos.x & 0xfff));
! 907: }
! 908: if (v & WSDISPLAY_CURSOR_DOCMAP) {
! 909: /* can't fail. */
! 910: dcrf->ramdac_set_curcmap(dcrc, cursorp);
! 911: }
! 912: if (v & WSDISPLAY_CURSOR_DOSHAPE) {
! 913: /* The cursor is 2 bits deep, and there is no mask */
! 914: count = (cursorp->size.y * 64 * 2) / NBBY;
! 915: TGAWREG(dc, TGA_REG_CCBR,
! 916: (TGARREG(dc, TGA_REG_CCBR) & ~0xfc00) | (cursorp->size.y << 10));
! 917: if ((error = copyin(cursorp->image,(char *)(dc->dc_vaddr +
! 918: (TGARREG(dc, TGA_REG_CCBR) & 0x3ff)), count)) != 0)
! 919: return (error);
! 920: }
! 921: return (0);
! 922: }
! 923:
! 924: int
! 925: tga_builtin_get_cursor(dc, cursorp)
! 926: struct tga_devconfig *dc;
! 927: struct wsdisplay_cursor *cursorp;
! 928: {
! 929: struct ramdac_funcs *dcrf = dc->dc_ramdac_funcs;
! 930: struct ramdac_cookie *dcrc = dc->dc_ramdac_cookie;
! 931: int error;
! 932: u_int count;
! 933:
! 934: cursorp->which = WSDISPLAY_CURSOR_DOALL &
! 935: ~(WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOCMAP);
! 936: cursorp->enable = (TGARREG(dc, TGA_REG_VVVR) & 0x04) != 0;
! 937: cursorp->pos.x = TGARREG(dc, TGA_REG_CXYR) & 0xfff;
! 938: cursorp->pos.y = (TGARREG(dc, TGA_REG_CXYR) >> 12) & 0xfff;
! 939: cursorp->size.x = 64;
! 940: cursorp->size.y = (TGARREG(dc, TGA_REG_CCBR) >> 10) & 0x3f;
! 941:
! 942: if (cursorp->image != NULL) {
! 943: count = (cursorp->size.y * 64 * 2) / NBBY;
! 944: error = copyout((char *)(dc->dc_vaddr +
! 945: (TGARREG(dc, TGA_REG_CCBR) & 0x3ff)),
! 946: cursorp->image, count);
! 947: if (error)
! 948: return (error);
! 949: /* No mask */
! 950: }
! 951: error = dcrf->ramdac_get_curcmap(dcrc, cursorp);
! 952: return (error);
! 953: }
! 954:
! 955: int
! 956: tga_builtin_set_curpos(dc, curposp)
! 957: struct tga_devconfig *dc;
! 958: struct wsdisplay_curpos *curposp;
! 959: {
! 960:
! 961: TGAWREG(dc, TGA_REG_CXYR,
! 962: ((curposp->y & 0xfff) << 12) | (curposp->x & 0xfff));
! 963: return (0);
! 964: }
! 965:
! 966: int
! 967: tga_builtin_get_curpos(dc, curposp)
! 968: struct tga_devconfig *dc;
! 969: struct wsdisplay_curpos *curposp;
! 970: {
! 971:
! 972: curposp->x = TGARREG(dc, TGA_REG_CXYR) & 0xfff;
! 973: curposp->y = (TGARREG(dc, TGA_REG_CXYR) >> 12) & 0xfff;
! 974: return (0);
! 975: }
! 976:
! 977: int
! 978: tga_builtin_get_curmax(dc, curposp)
! 979: struct tga_devconfig *dc;
! 980: struct wsdisplay_curpos *curposp;
! 981: {
! 982:
! 983: curposp->x = curposp->y = 64;
! 984: return (0);
! 985: }
! 986:
! 987: /*
! 988: * Copy columns (characters) in a row (line).
! 989: */
! 990: void
! 991: tga_copycols(id, row, srccol, dstcol, ncols)
! 992: void *id;
! 993: int row, srccol, dstcol, ncols;
! 994: {
! 995: struct rasops_info *ri = id;
! 996: int y, srcx, dstx, nx;
! 997:
! 998: y = ri->ri_font->fontheight * row;
! 999: srcx = ri->ri_font->fontwidth * srccol;
! 1000: dstx = ri->ri_font->fontwidth * dstcol;
! 1001: nx = ri->ri_font->fontwidth * ncols;
! 1002:
! 1003: tga_rop(ri, dstx, y, nx, ri->ri_font->fontheight, ri, srcx, y);
! 1004: }
! 1005:
! 1006: /*
! 1007: * Copy rows (lines).
! 1008: */
! 1009: void
! 1010: tga_copyrows(id, srcrow, dstrow, nrows)
! 1011: void *id;
! 1012: int srcrow, dstrow, nrows;
! 1013: {
! 1014: struct rasops_info *ri = id;
! 1015: int srcy, dsty, ny;
! 1016:
! 1017: srcy = ri->ri_font->fontheight * srcrow;
! 1018: dsty = ri->ri_font->fontheight * dstrow;
! 1019: ny = ri->ri_font->fontheight * nrows;
! 1020:
! 1021: tga_rop(ri, 0, dsty, ri->ri_emuwidth, ny, ri, 0, srcy);
! 1022: }
! 1023:
! 1024: /*
! 1025: * Generic TGA raster op.
! 1026: * This covers all possible raster ops, and
! 1027: * clips the sizes and all of that.
! 1028: */
! 1029: int
! 1030: tga_rop(dst, dx, dy, w, h, src, sx, sy)
! 1031: struct rasops_info *dst;
! 1032: int dx, dy, w, h;
! 1033: struct rasops_info *src;
! 1034: int sx, sy;
! 1035: {
! 1036: if (dst == NULL || src == NULL)
! 1037: return -1;
! 1038:
! 1039: /* Clip against src */
! 1040: if (sx < 0) {
! 1041: w += sx;
! 1042: sx = 0;
! 1043: }
! 1044: if (sy < 0) {
! 1045: h += sy;
! 1046: sy = 0;
! 1047: }
! 1048: if (sx + w > src->ri_emuwidth)
! 1049: w = src->ri_emuwidth - sx;
! 1050: if (sy + h > src->ri_emuheight)
! 1051: h = src->ri_emuheight - sy;
! 1052:
! 1053: /* Clip against dst. We modify src regardless of using it,
! 1054: * since it really doesn't matter.
! 1055: */
! 1056: if (dx < 0) {
! 1057: w += dx;
! 1058: sx -= dx;
! 1059: dx = 0;
! 1060: }
! 1061: if (dy < 0) {
! 1062: h += dy;
! 1063: sy -= dy;
! 1064: dy = 0;
! 1065: }
! 1066: if (dx + w > dst->ri_emuwidth)
! 1067: w = dst->ri_emuwidth - dx;
! 1068: if (dy + h > dst->ri_emuheight)
! 1069: h = dst->ri_emuheight - dy;
! 1070: if (w <= 0 || h <= 0)
! 1071: return 0; /* Vacuously true; */
! 1072:
! 1073: return tga_rop_vtov(dst, dx, dy, w, h, src, sx, sy);
! 1074: }
! 1075:
! 1076:
! 1077:
! 1078: /*
! 1079: * Video to Video raster ops.
! 1080: * This function deals with all raster ops that have a src and dst
! 1081: * that are on the card.
! 1082: */
! 1083: int
! 1084: tga_rop_vtov(dst, dx, dy, w, h, src, sx, sy)
! 1085: struct rasops_info *dst;
! 1086: int dx, dy, w, h;
! 1087: struct rasops_info *src;
! 1088: int sx, sy;
! 1089: {
! 1090: struct tga_devconfig *dc = (struct tga_devconfig *)dst->ri_hw;
! 1091: int srcb, dstb, tga_srcb, tga_dstb;
! 1092: int x, y, wb;
! 1093: int xstart, xend, xdir;
! 1094: int ystart, yend, ydir, yinc;
! 1095: int xleft, lastx, lastleft;
! 1096: int offset = 1 * dc->dc_tgaconf->tgac_vvbr_units;
! 1097:
! 1098: /*
! 1099: * I don't yet want to deal with unaligned guys, really. And we don't
! 1100: * deal with copies from one card to another.
! 1101: */
! 1102: if (dx % 8 != 0 || sx % 8 != 0 || src != dst) {
! 1103: /* XXX Punt! */
! 1104: /* XXX should never happen, since it's only being used to
! 1105: * XXX copy 8-pixel-wide characters.
! 1106: */
! 1107: return -1;
! 1108: }
! 1109:
! 1110: wb = w * (dst->ri_depth / 8);
! 1111: if (sy >= dy) {
! 1112: ystart = 0;
! 1113: yend = h;
! 1114: ydir = 1;
! 1115: } else {
! 1116: ystart = h;
! 1117: yend = 0;
! 1118: ydir = -1;
! 1119: }
! 1120: if (sx >= dx) { /* moving to the left */
! 1121: xstart = 0;
! 1122: xend = w * (dst->ri_depth / 8) - 4;
! 1123: xdir = 1;
! 1124: } else { /* moving to the right */
! 1125: xstart = wb - ( wb >= 4*64 ? 4*64 : wb >= 64 ? 64 : 4 );
! 1126: xend = 0;
! 1127: xdir = -1;
! 1128: }
! 1129: #define XINC4 4
! 1130: #define XINC64 64
! 1131: #define XINC256 (64*4)
! 1132: yinc = ydir * dst->ri_stride;
! 1133: ystart *= dst->ri_stride;
! 1134: yend *= dst->ri_stride;
! 1135:
! 1136: srcb = sy * src->ri_stride + sx * (src->ri_depth/8);
! 1137: dstb = dy * dst->ri_stride + dx * (dst->ri_depth/8);
! 1138: tga_srcb = offset + (sy + src->ri_yorigin) * src->ri_stride +
! 1139: (sx + src->ri_xorigin) * (src->ri_depth/8);
! 1140: tga_dstb = offset + (dy + dst->ri_yorigin) * dst->ri_stride +
! 1141: (dx + dst->ri_xorigin) * (dst->ri_depth/8);
! 1142:
! 1143: TGAWALREG(dc, TGA_REG_GMOR, 3, 0x0007); /* Copy mode */
! 1144: TGAWALREG(dc, TGA_REG_GOPR, 3, 0x0003); /* SRC */
! 1145:
! 1146: /*
! 1147: * we have 3 sizes of pixels to move in X direction:
! 1148: * 4 * 64 (unrolled TGA ops)
! 1149: * 64 (single TGA op)
! 1150: * 4 (CPU, using long word)
! 1151: */
! 1152:
! 1153: if (xdir == 1) { /* move to the left */
! 1154:
! 1155: for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
! 1156:
! 1157: /* 4*64 byte chunks */
! 1158: for (xleft = wb, x = xstart;
! 1159: x <= xend && xleft >= 4*64;
! 1160: x += XINC256, xleft -= XINC256) {
! 1161:
! 1162: /* XXX XXX Eight writes to different addresses should fill
! 1163: * XXX XXX up the write buffers on 21064 and 21164 chips,
! 1164: * XXX XXX but later CPUs might have larger write buffers which
! 1165: * XXX XXX require further unrolling of this loop, or the
! 1166: * XXX XXX insertion of memory barriers.
! 1167: */
! 1168: TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 0 * 64);
! 1169: TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 0 * 64);
! 1170: TGAWALREG(dc, TGA_REG_GCSR, 1, tga_srcb + y + x + 1 * 64);
! 1171: TGAWALREG(dc, TGA_REG_GCDR, 1, tga_dstb + y + x + 1 * 64);
! 1172: TGAWALREG(dc, TGA_REG_GCSR, 2, tga_srcb + y + x + 2 * 64);
! 1173: TGAWALREG(dc, TGA_REG_GCDR, 2, tga_dstb + y + x + 2 * 64);
! 1174: TGAWALREG(dc, TGA_REG_GCSR, 3, tga_srcb + y + x + 3 * 64);
! 1175: TGAWALREG(dc, TGA_REG_GCDR, 3, tga_dstb + y + x + 3 * 64);
! 1176: }
! 1177:
! 1178: /* 64 byte chunks */
! 1179: for ( ; x <= xend && xleft >= 64;
! 1180: x += XINC64, xleft -= XINC64) {
! 1181: TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 0 * 64);
! 1182: TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 0 * 64);
! 1183: }
! 1184: lastx = x; lastleft = xleft; /* remember for CPU loop */
! 1185:
! 1186: }
! 1187: TGAWALREG(dc, TGA_REG_GOPR, 0, 0x0003); /* op -> dst = src */
! 1188: TGAWALREG(dc, TGA_REG_GMOR, 0, 0x0000); /* Simple mode */
! 1189:
! 1190: for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
! 1191: /* 4 byte granularity */
! 1192: for (x = lastx, xleft = lastleft;
! 1193: x <= xend && xleft >= 4;
! 1194: x += XINC4, xleft -= XINC4) {
! 1195: *(uint32_t *)(dst->ri_bits + dstb + y + x) =
! 1196: *(uint32_t *)(dst->ri_bits + srcb + y + x);
! 1197: }
! 1198: }
! 1199: }
! 1200: else { /* above move to the left, below move to the right */
! 1201:
! 1202: for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
! 1203:
! 1204: /* 4*64 byte chunks */
! 1205: for (xleft = wb, x = xstart;
! 1206: x >= xend && xleft >= 4*64;
! 1207: x -= XINC256, xleft -= XINC256) {
! 1208:
! 1209: /* XXX XXX Eight writes to different addresses should fill
! 1210: * XXX XXX up the write buffers on 21064 and 21164 chips,
! 1211: * XXX XXX but later CPUs might have larger write buffers which
! 1212: * XXX XXX require further unrolling of this loop, or the
! 1213: * XXX XXX insertion of memory barriers.
! 1214: */
! 1215: TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 3 * 64);
! 1216: TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 3 * 64);
! 1217: TGAWALREG(dc, TGA_REG_GCSR, 1, tga_srcb + y + x + 2 * 64);
! 1218: TGAWALREG(dc, TGA_REG_GCDR, 1, tga_dstb + y + x + 2 * 64);
! 1219: TGAWALREG(dc, TGA_REG_GCSR, 2, tga_srcb + y + x + 1 * 64);
! 1220: TGAWALREG(dc, TGA_REG_GCDR, 2, tga_dstb + y + x + 1 * 64);
! 1221: TGAWALREG(dc, TGA_REG_GCSR, 3, tga_srcb + y + x + 0 * 64);
! 1222: TGAWALREG(dc, TGA_REG_GCDR, 3, tga_dstb + y + x + 0 * 64);
! 1223: }
! 1224:
! 1225: if (xleft) x += XINC256 - XINC64;
! 1226:
! 1227: /* 64 byte chunks */
! 1228: for ( ; x >= xend && xleft >= 64;
! 1229: x -= XINC64, xleft -= XINC64) {
! 1230: TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 0 * 64);
! 1231: TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 0 * 64);
! 1232: }
! 1233: if (xleft) x += XINC64 - XINC4;
! 1234: lastx = x; lastleft = xleft; /* remember for CPU loop */
! 1235: }
! 1236: TGAWALREG(dc, TGA_REG_GOPR, 0, 0x0003); /* op -> dst = src */
! 1237: TGAWALREG(dc, TGA_REG_GMOR, 0, 0x0000); /* Simple mode */
! 1238:
! 1239: for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
! 1240: /* 4 byte granularity */
! 1241: for (x = lastx, xleft = lastleft;
! 1242: x >= xend && xleft >= 4;
! 1243: x -= XINC4, xleft -= XINC4) {
! 1244: *(uint32_t *)(dst->ri_bits + dstb + y + x) =
! 1245: *(uint32_t *)(dst->ri_bits + srcb + y + x);
! 1246: }
! 1247: }
! 1248: }
! 1249: return 0;
! 1250: }
! 1251:
! 1252:
! 1253: void
! 1254: tga_putchar(c, row, col, uc, attr)
! 1255: void *c;
! 1256: int row, col;
! 1257: u_int uc;
! 1258: long attr;
! 1259: {
! 1260: struct rasops_info *ri = c;
! 1261: struct tga_devconfig *dc = ri->ri_hw;
! 1262: int fs, height, width;
! 1263: int fg, bg, ul;
! 1264: u_char *fr;
! 1265: int32_t *rp;
! 1266:
! 1267: rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
! 1268:
! 1269: height = ri->ri_font->fontheight;
! 1270: width = ri->ri_font->fontwidth;
! 1271:
! 1272: uc -= ri->ri_font->firstchar;
! 1273: fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
! 1274: fs = ri->ri_font->stride;
! 1275:
! 1276: /* Set foreground and background color. XXX memoize this somehow?
! 1277: * The rasops code has already expanded the color entry to 32 bits
! 1278: * for us, even for 8-bit displays, so we don't have to do anything.
! 1279: */
! 1280: ri->ri_ops.unpack_attr(c, attr, &fg, &bg, &ul);
! 1281: TGAWREG(dc, TGA_REG_GFGR, ri->ri_devcmap[fg]);
! 1282: TGAWREG(dc, TGA_REG_GBGR, ri->ri_devcmap[bg]);
! 1283:
! 1284: /* Set raster operation to "copy"... */
! 1285: if (ri->ri_depth == 8)
! 1286: TGAWREG(dc, TGA_REG_GOPR, 0x3);
! 1287: else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
! 1288: TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
! 1289:
! 1290: /* Set which pixels we're drawing (of a possible 32). */
! 1291: TGAWREG(dc, TGA_REG_GPXR_P, (1 << width) - 1);
! 1292:
! 1293: /* Set drawing mode to opaque stipple. */
! 1294: TGAWREG(dc, TGA_REG_GMOR, 0x1);
! 1295:
! 1296: /* Insert write barrier before actually sending data */
! 1297: /* XXX Abuses the fact that there is only one write barrier on Alphas */
! 1298: TGAREGWB(dc, TGA_REG_GMOR, 1);
! 1299:
! 1300: while (height--) {
! 1301: /* The actual stipple write */
! 1302: *rp = fr[0] | (fr[1] << 8) | (fr[2] << 16) | (fr[3] << 24);
! 1303:
! 1304: fr += fs;
! 1305: rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
! 1306: }
! 1307:
! 1308: /* Do underline */
! 1309: if (ul) {
! 1310: rp = (int32_t *)((caddr_t)rp - (ri->ri_stride << 1));
! 1311: *rp = 0xffffffff;
! 1312: }
! 1313:
! 1314: /* Set grapics mode back to normal. */
! 1315: TGAWREG(dc, TGA_REG_GMOR, 0);
! 1316: TGAWREG(dc, TGA_REG_GPXR_P, 0xffffffff);
! 1317: }
! 1318:
! 1319: void
! 1320: tga_eraserows(c, row, num, attr)
! 1321: void *c;
! 1322: int row, num;
! 1323: long attr;
! 1324: {
! 1325: struct rasops_info *ri = c;
! 1326: struct tga_devconfig *dc = ri->ri_hw;
! 1327: int32_t color, lines, pixels;
! 1328: int fg, bg;
! 1329: int32_t *rp;
! 1330:
! 1331: ri->ri_ops.unpack_attr(c, attr, &fg, &bg, NULL);
! 1332: color = ri->ri_devcmap[bg];
! 1333: rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale);
! 1334: lines = num * ri->ri_font->fontheight;
! 1335: pixels = ri->ri_emuwidth - 1;
! 1336:
! 1337: /* Set fill color in block-color registers */
! 1338: TGAWREG(dc, TGA_REG_GBCR0, color);
! 1339: TGAWREG(dc, TGA_REG_GBCR1, color);
! 1340: if (ri->ri_depth != 8) {
! 1341: TGAWREG(dc, TGA_REG_GBCR2, color);
! 1342: TGAWREG(dc, TGA_REG_GBCR3, color);
! 1343: TGAWREG(dc, TGA_REG_GBCR4, color);
! 1344: TGAWREG(dc, TGA_REG_GBCR5, color);
! 1345: TGAWREG(dc, TGA_REG_GBCR6, color);
! 1346: TGAWREG(dc, TGA_REG_GBCR7, color);
! 1347: }
! 1348:
! 1349: /* Set raster operation to "copy"... */
! 1350: if (ri->ri_depth == 8)
! 1351: TGAWREG(dc, TGA_REG_GOPR, 0x3);
! 1352: else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
! 1353: TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
! 1354:
! 1355: /* Set which pixels we're drawing (of a possible 32). */
! 1356: TGAWREG(dc, TGA_REG_GDAR, 0xffffffff);
! 1357:
! 1358: /* Set drawing mode to block fill. */
! 1359: TGAWREG(dc, TGA_REG_GMOR, 0x2d);
! 1360:
! 1361: /* Insert write barrier before actually sending data */
! 1362: /* XXX Abuses the fact that there is only one write barrier on Alphas */
! 1363: TGAREGWB(dc, TGA_REG_GMOR, 1);
! 1364:
! 1365: while (lines--) {
! 1366: *rp = pixels;
! 1367: rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
! 1368: }
! 1369:
! 1370: /* Set grapics mode back to normal. */
! 1371: TGAWREG(dc, TGA_REG_GMOR, 0);
! 1372:
! 1373: }
! 1374:
! 1375: void
! 1376: tga_erasecols (c, row, col, num, attr)
! 1377: void *c;
! 1378: int row, col, num;
! 1379: long attr;
! 1380: {
! 1381: struct rasops_info *ri = c;
! 1382: struct tga_devconfig *dc = ri->ri_hw;
! 1383: int32_t color, lines, pixels;
! 1384: int fg, bg;
! 1385: int32_t *rp;
! 1386:
! 1387: ri->ri_ops.unpack_attr(c, attr, &fg, &bg, NULL);
! 1388: color = ri->ri_devcmap[bg];
! 1389: rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
! 1390: lines = ri->ri_font->fontheight;
! 1391: pixels = (num * ri->ri_font->fontwidth) - 1;
! 1392:
! 1393: /* Set fill color in block-color registers */
! 1394: TGAWREG(dc, TGA_REG_GBCR0, color);
! 1395: TGAWREG(dc, TGA_REG_GBCR1, color);
! 1396: if (ri->ri_depth != 8) {
! 1397: TGAWREG(dc, TGA_REG_GBCR2, color);
! 1398: TGAWREG(dc, TGA_REG_GBCR3, color);
! 1399: TGAWREG(dc, TGA_REG_GBCR4, color);
! 1400: TGAWREG(dc, TGA_REG_GBCR5, color);
! 1401: TGAWREG(dc, TGA_REG_GBCR6, color);
! 1402: TGAWREG(dc, TGA_REG_GBCR7, color);
! 1403: }
! 1404:
! 1405: /* Set raster operation to "copy"... */
! 1406: if (ri->ri_depth == 8)
! 1407: TGAWREG(dc, TGA_REG_GOPR, 0x3);
! 1408: else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
! 1409: TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
! 1410:
! 1411: /* Set which pixels we're drawing (of a possible 32). */
! 1412: TGAWREG(dc, TGA_REG_GDAR, 0xffffffff);
! 1413:
! 1414: /* Set drawing mode to block fill. */
! 1415: TGAWREG(dc, TGA_REG_GMOR, 0x2d);
! 1416:
! 1417: /* Insert write barrier before actually sending data */
! 1418: /* XXX Abuses the fact that there is only one write barrier on Alphas */
! 1419: TGAREGWB(dc, TGA_REG_GMOR, 1);
! 1420:
! 1421: while (lines--) {
! 1422: *rp = pixels;
! 1423: rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
! 1424: }
! 1425:
! 1426: /* Set grapics mode back to normal. */
! 1427: TGAWREG(dc, TGA_REG_GMOR, 0);
! 1428: }
! 1429:
! 1430:
! 1431: void
! 1432: tga_ramdac_wr(v, btreg, val)
! 1433: void *v;
! 1434: u_int btreg;
! 1435: u_int8_t val;
! 1436: {
! 1437: struct tga_devconfig *dc = v;
! 1438:
! 1439: if (btreg > BT485_REG_MAX)
! 1440: panic("tga_ramdac_wr: reg %d out of range", btreg);
! 1441:
! 1442: TGAWREG(dc, TGA_REG_EPDR, (btreg << 9) | (0 << 8 ) | val); /* XXX */
! 1443: TGAREGWB(dc, TGA_REG_EPDR, 1);
! 1444: }
! 1445:
! 1446: void
! 1447: tga2_ramdac_wr(v, btreg, val)
! 1448: void *v;
! 1449: u_int btreg;
! 1450: u_int8_t val;
! 1451: {
! 1452: struct tga_devconfig *dc = v;
! 1453: bus_space_handle_t ramdac;
! 1454:
! 1455: if (btreg > BT485_REG_MAX)
! 1456: panic("tga_ramdac_wr: reg %d out of range", btreg);
! 1457:
! 1458: bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_RAMDAC +
! 1459: (0xe << 12) + (btreg << 8), 4, &ramdac);
! 1460: bus_space_write_4(dc->dc_memt, ramdac, 0, val & 0xff);
! 1461: bus_space_barrier(dc->dc_memt, ramdac, 0, 4, BUS_SPACE_BARRIER_WRITE);
! 1462: }
! 1463:
! 1464: u_int8_t
! 1465: tga_bt463_rd(v, btreg)
! 1466: void *v;
! 1467: u_int btreg;
! 1468: {
! 1469: struct tga_devconfig *dc = v;
! 1470: tga_reg_t rdval;
! 1471:
! 1472: /*
! 1473: * Strobe CE# (high->low->high) since status and data are latched on
! 1474: * the falling and rising edges (repsectively) of this active-low signal.
! 1475: */
! 1476:
! 1477: TGAREGWB(dc, TGA_REG_EPSR, 1);
! 1478: TGAWREG(dc, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
! 1479: TGAREGWB(dc, TGA_REG_EPSR, 1);
! 1480: TGAWREG(dc, TGA_REG_EPSR, (btreg << 2) | 2 | 0);
! 1481:
! 1482: TGAREGRB(dc, TGA_REG_EPSR, 1);
! 1483:
! 1484: rdval = TGARREG(dc, TGA_REG_EPDR);
! 1485: TGAREGWB(dc, TGA_REG_EPSR, 1);
! 1486: TGAWREG(dc, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
! 1487:
! 1488: return (rdval >> 16) & 0xff;
! 1489: }
! 1490:
! 1491: void
! 1492: tga_bt463_wr(v, btreg, val)
! 1493: void *v;
! 1494: u_int btreg;
! 1495: u_int8_t val;
! 1496: {
! 1497: struct tga_devconfig *dc = v;
! 1498:
! 1499: /*
! 1500: * In spite of the 21030 documentation, to set the MPU bus bits for
! 1501: * a write, you set them in the upper bits of EPDR, not EPSR.
! 1502: */
! 1503:
! 1504: /*
! 1505: * Strobe CE# (high->low->high) since status and data are latched on
! 1506: * the falling and rising edges of this active-low signal.
! 1507: */
! 1508:
! 1509: TGAREGWB(dc, TGA_REG_EPDR, 1);
! 1510: TGAWREG(dc, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
! 1511: TGAREGWB(dc, TGA_REG_EPDR, 1);
! 1512: TGAWREG(dc, TGA_REG_EPDR, (btreg << 10) | 0x000 | val);
! 1513: TGAREGWB(dc, TGA_REG_EPDR, 1);
! 1514: TGAWREG(dc, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
! 1515:
! 1516: }
! 1517:
! 1518: u_int8_t
! 1519: tga_ramdac_rd(v, btreg)
! 1520: void *v;
! 1521: u_int btreg;
! 1522: {
! 1523: struct tga_devconfig *dc = v;
! 1524: tga_reg_t rdval;
! 1525:
! 1526: if (btreg > BT485_REG_MAX)
! 1527: panic("tga_ramdac_rd: reg %d out of range", btreg);
! 1528:
! 1529: TGAWREG(dc, TGA_REG_EPSR, (btreg << 1) | 0x1); /* XXX */
! 1530: TGAREGWB(dc, TGA_REG_EPSR, 1);
! 1531:
! 1532: rdval = TGARREG(dc, TGA_REG_EPDR);
! 1533: return (rdval >> 16) & 0xff; /* XXX */
! 1534: }
! 1535:
! 1536: u_int8_t
! 1537: tga2_ramdac_rd(v, btreg)
! 1538: void *v;
! 1539: u_int btreg;
! 1540: {
! 1541: struct tga_devconfig *dc = v;
! 1542: bus_space_handle_t ramdac;
! 1543: u_int8_t retval;
! 1544:
! 1545: if (btreg > BT485_REG_MAX)
! 1546: panic("tga_ramdac_rd: reg %d out of range", btreg);
! 1547:
! 1548: bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_RAMDAC +
! 1549: (0xe << 12) + (btreg << 8), 4, &ramdac);
! 1550: retval = bus_space_read_4(dc->dc_memt, ramdac, 0) & 0xff;
! 1551: bus_space_barrier(dc->dc_memt, ramdac, 0, 4, BUS_SPACE_BARRIER_READ);
! 1552: return retval;
! 1553: }
! 1554:
! 1555: #include <dev/ic/decmonitors.c>
! 1556: void tga2_ics9110_wr(
! 1557: struct tga_devconfig *dc,
! 1558: int dotclock
! 1559: );
! 1560:
! 1561: struct monitor *tga_getmonitor(struct tga_devconfig *dc);
! 1562:
! 1563: void
! 1564: tga2_init(dc)
! 1565: struct tga_devconfig *dc;
! 1566: {
! 1567: struct monitor *m = tga_getmonitor(dc);
! 1568:
! 1569:
! 1570: /* Deal with the dot clocks.
! 1571: */
! 1572: if (dc->dc_tga_type == TGA_TYPE_POWERSTORM_4D20) {
! 1573: /* Set this up as a reference clock for the
! 1574: * ibm561's PLL.
! 1575: */
! 1576: tga2_ics9110_wr(dc, 14300000);
! 1577: /* XXX Can't set up the dotclock properly, until such time
! 1578: * as the RAMDAC is configured.
! 1579: */
! 1580: } else {
! 1581: /* otherwise the ics9110 is our clock. */
! 1582: tga2_ics9110_wr(dc, m->dotclock);
! 1583: }
! 1584: #if 0
! 1585: TGAWREG(dc, TGA_REG_VHCR,
! 1586: ((m->hbp / 4) << 21) |
! 1587: ((m->hsync / 4) << 14) |
! 1588: (((m->hfp - 4) / 4) << 9) |
! 1589: ((m->cols + 4) / 4));
! 1590: #else
! 1591: TGAWREG(dc, TGA_REG_VHCR,
! 1592: ((m->hbp / 4) << 21) |
! 1593: ((m->hsync / 4) << 14) |
! 1594: (((m->hfp) / 4) << 9) |
! 1595: ((m->cols) / 4));
! 1596: #endif
! 1597: TGAWREG(dc, TGA_REG_VVCR,
! 1598: (m->vbp << 22) |
! 1599: (m->vsync << 16) |
! 1600: (m->vfp << 11) |
! 1601: (m->rows));
! 1602: TGAWREG(dc, TGA_REG_VVBR, 1);
! 1603: TGAREGRWB(dc, TGA_REG_VHCR, 3);
! 1604: TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) | 1);
! 1605: TGAREGRWB(dc, TGA_REG_VVVR, 1);
! 1606: TGAWREG(dc, TGA_REG_GPMR, 0xffffffff);
! 1607: TGAREGRWB(dc, TGA_REG_GPMR, 1);
! 1608: }
! 1609:
! 1610: void
! 1611: tga2_ics9110_wr(dc, dotclock)
! 1612: struct tga_devconfig *dc;
! 1613: int dotclock;
! 1614: {
! 1615: bus_space_handle_t clock;
! 1616: u_int32_t valU;
! 1617: int N, M, R, V, X;
! 1618: int i;
! 1619:
! 1620: switch (dotclock) {
! 1621: case 130808000:
! 1622: N = 0x40; M = 0x7; V = 0x0; X = 0x1; R = 0x1; break;
! 1623: case 119840000:
! 1624: N = 0x2d; M = 0x2b; V = 0x1; X = 0x1; R = 0x1; break;
! 1625: case 108180000:
! 1626: N = 0x11; M = 0x9; V = 0x1; X = 0x1; R = 0x2; break;
! 1627: case 103994000:
! 1628: N = 0x6d; M = 0xf; V = 0x0; X = 0x1; R = 0x1; break;
! 1629: case 175000000:
! 1630: N = 0x5F; M = 0x3E; V = 0x1; X = 0x1; R = 0x1; break;
! 1631: case 75000000:
! 1632: N = 0x6e; M = 0x15; V = 0x0; X = 0x1; R = 0x1; break;
! 1633: case 74000000:
! 1634: N = 0x2a; M = 0x41; V = 0x1; X = 0x1; R = 0x1; break;
! 1635: case 69000000:
! 1636: N = 0x35; M = 0xb; V = 0x0; X = 0x1; R = 0x1; break;
! 1637: case 65000000:
! 1638: N = 0x6d; M = 0x0c; V = 0x0; X = 0x1; R = 0x2; break;
! 1639: case 50000000:
! 1640: N = 0x37; M = 0x3f; V = 0x1; X = 0x1; R = 0x2; break;
! 1641: case 40000000:
! 1642: N = 0x5f; M = 0x11; V = 0x0; X = 0x1; R = 0x2; break;
! 1643: case 31500000:
! 1644: N = 0x16; M = 0x05; V = 0x0; X = 0x1; R = 0x2; break;
! 1645: case 25175000:
! 1646: N = 0x66; M = 0x1d; V = 0x0; X = 0x1; R = 0x2; break;
! 1647: case 135000000:
! 1648: N = 0x42; M = 0x07; V = 0x0; X = 0x1; R = 0x1; break;
! 1649: case 110000000:
! 1650: N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
! 1651: case 202500000:
! 1652: N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
! 1653: case 14300000: /* this one is just a ref clock */
! 1654: N = 0x03; M = 0x03; V = 0x1; X = 0x1; R = 0x3; break;
! 1655: default:
! 1656: panic("unrecognized clock rate %d", dotclock);
! 1657: }
! 1658:
! 1659: /* XXX -- hard coded, bad */
! 1660: valU = N | ( M << 7 ) | (V << 14);
! 1661: valU |= (X << 15) | (R << 17);
! 1662: valU |= 0x17 << 19;
! 1663:
! 1664: bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_EXTDEV +
! 1665: TGA2_MEM_CLOCK + (0xe << 12), 4, &clock); /* XXX */
! 1666:
! 1667: for (i = 24; i > 0; i--) {
! 1668: u_int32_t writeval;
! 1669:
! 1670: writeval = valU & 0x1;
! 1671: if (i == 1)
! 1672: writeval |= 0x2;
! 1673: valU >>= 1;
! 1674: bus_space_write_4(dc->dc_memt, clock, 0, writeval);
! 1675: bus_space_barrier(dc->dc_memt, clock, 0, 4, BUS_SPACE_BARRIER_WRITE);
! 1676: }
! 1677: bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_EXTDEV +
! 1678: TGA2_MEM_CLOCK + (0xe << 12) + (0x1 << 11) + (0x1 << 11), 4,
! 1679: &clock); /* XXX */
! 1680: bus_space_write_4(dc->dc_memt, clock, 0, 0x0);
! 1681: bus_space_barrier(dc->dc_memt, clock, 0, 0, BUS_SPACE_BARRIER_WRITE);
! 1682: }
! 1683:
! 1684: struct monitor *
! 1685: tga_getmonitor(dc)
! 1686: struct tga_devconfig *dc;
! 1687: {
! 1688: return &decmonitors[(~TGARREG(dc, TGA_REG_GREV) >> 16) & 0x0f];
! 1689: }
! 1690:
! 1691: unsigned
! 1692: tga_getdotclock(dc)
! 1693: struct tga_devconfig *dc;
! 1694: {
! 1695: return tga_getmonitor(dc)->dotclock;
! 1696: }
CVSweb