1 /* $NetBSD: tcx.c,v 1.12 2002/10/02 16:52:45 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996,1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * color display (TCX) driver. 41 * 42 * Does not handle interrupts, even though they can occur. 43 * 44 * XXX should defer colormap updates to vertical retrace interrupts 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.12 2002/10/02 16:52:45 thorpej Exp $"); 49 50 /* 51 * define for cg8 emulation on S24 (24-bit version of tcx) for the SS5; 52 * it is bypassed on the 8-bit version (onboard framebuffer for SS4) 53 */ 54 #undef TCX_CG8 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/buf.h> 59 #include <sys/device.h> 60 #include <sys/ioctl.h> 61 #include <sys/malloc.h> 62 #include <sys/mman.h> 63 #include <sys/tty.h> 64 #include <sys/conf.h> 65 66 #ifdef DEBUG 67 #include <sys/proc.h> 68 #include <sys/syslog.h> 69 #endif 70 71 #include <machine/bus.h> 72 #include <machine/autoconf.h> 73 74 #include <dev/sun/fbio.h> 75 #include <dev/sun/fbvar.h> 76 #include <dev/sun/btreg.h> 77 #include <dev/sun/btvar.h> 78 79 #include <dev/sbus/sbusvar.h> 80 #include <dev/sbus/tcxreg.h> 81 82 /* per-display variables */ 83 struct tcx_softc { 84 struct device sc_dev; /* base device */ 85 struct sbusdev sc_sd; /* sbus device */ 86 struct fbdevice sc_fb; /* frame buffer device */ 87 bus_space_tag_t sc_bustag; 88 struct openprom_addr sc_physadr[TCX_NREG];/* phys addr of h/w */ 89 90 volatile struct bt_regs *sc_bt; /* Brooktree registers */ 91 volatile struct tcx_thc *sc_thc;/* THC registers */ 92 #ifdef TCX_CG8 93 volatile ulong *sc_cplane; /* framebuffer with control planes */ 94 #endif 95 short sc_8bit; /* true if 8-bit hardware */ 96 short sc_blanked; /* true if blanked */ 97 union bt_cmap sc_cmap; /* Brooktree color map */ 98 }; 99 100 /* 101 * The S24 provides the framebuffer RAM mapped in three ways: 102 * 26 bits per pixel, in 32-bit words; the low-order 24 bits are 103 * blue, green, and red values, and the other two bits select the 104 * display modes, per pixel); 105 * 24 bits per pixel, in 32-bit words; the high-order byte reads as 106 * zero, and is ignored on writes (so the mode bits cannot be altered); 107 * 8 bits per pixel, unpadded; writes to this space do not modify the 108 * other 18 bits. 109 */ 110 #define TCX_CTL_8_MAPPED 0x00000000 /* 8 bits, uses color map */ 111 #define TCX_CTL_24_MAPPED 0x01000000 /* 24 bits, uses color map */ 112 #define TCX_CTL_24_LEVEL 0x03000000 /* 24 bits, ignores color map */ 113 #define TCX_CTL_PIXELMASK 0x00FFFFFF /* mask for index/level */ 114 115 /* autoconfiguration driver */ 116 static void tcxattach __P((struct device *, struct device *, void *)); 117 static int tcxmatch __P((struct device *, struct cfdata *, void *)); 118 static void tcx_unblank __P((struct device *)); 119 120 CFATTACH_DECL(tcx, sizeof(struct tcx_softc), 121 tcxmatch, tcxattach, NULL, NULL); 122 123 extern struct cfdriver tcx_cd; 124 125 dev_type_open(tcxopen); 126 dev_type_close(tcxclose); 127 dev_type_ioctl(tcxioctl); 128 dev_type_mmap(tcxmmap); 129 130 const struct cdevsw tcx_cdevsw = { 131 tcxopen, tcxclose, noread, nowrite, tcxioctl, 132 nostop, notty, nopoll, tcxmmap, 133 }; 134 135 /* frame buffer generic driver */ 136 static struct fbdriver tcx_fbdriver = { 137 tcx_unblank, tcxopen, tcxclose, tcxioctl, nopoll, tcxmmap 138 }; 139 140 static void tcx_reset __P((struct tcx_softc *)); 141 static void tcx_loadcmap __P((struct tcx_softc *, int, int)); 142 143 #define OBPNAME "SUNW,tcx" 144 145 #ifdef TCX_CG8 146 /* 147 * For CG8 emulation, we map the 32-bit-deep framebuffer at an offset of 148 * 256K; the cg8 space begins with a mono overlay plane and an overlay 149 * enable plane (128K bytes each, 1 bit per pixel), immediately followed 150 * by the color planes, 32 bits per pixel. We also map just the 32-bit 151 * framebuffer at 0x04000000 (TCX_USER_RAM_COMPAT), for compatibility 152 * with the cg8 driver. 153 */ 154 #define TCX_CG8OVERLAY (256 * 1024) 155 #define TCX_SIZE_DFB32 (1152 * 900 * 4) /* max size of the framebuffer */ 156 #endif 157 158 /* 159 * Match a tcx. 160 */ 161 int 162 tcxmatch(parent, cf, aux) 163 struct device *parent; 164 struct cfdata *cf; 165 void *aux; 166 { 167 struct sbus_attach_args *sa = aux; 168 169 return (strcmp(sa->sa_name, OBPNAME) == 0); 170 } 171 172 /* 173 * Attach a display. 174 */ 175 void 176 tcxattach(parent, self, args) 177 struct device *parent, *self; 178 void *args; 179 { 180 struct tcx_softc *sc = (struct tcx_softc *)self; 181 struct sbus_attach_args *sa = args; 182 int node, ramsize; 183 volatile struct bt_regs *bt; 184 struct fbdevice *fb = &sc->sc_fb; 185 bus_space_handle_t bh; 186 int isconsole; 187 188 sc->sc_bustag = sa->sa_bustag; 189 node = sa->sa_node; 190 191 fb->fb_driver = &tcx_fbdriver; 192 fb->fb_device = &sc->sc_dev; 193 /* Mask out invalid flags from the user. */ 194 fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags & FB_USERMASK; 195 /* 196 * The onboard framebuffer on the SS4 supports only 8-bit mode; 197 * it can be distinguished from the S24 card for the SS5 by the 198 * presence of the "tcx-8-bit" attribute on the SS4 version. 199 */ 200 sc->sc_8bit = node_has_property(node, "tcx-8-bit"); 201 #ifdef TCX_CG8 202 if (sc->sc_8bit) { 203 #endif 204 /* 205 * cg8 emulation is either not compiled in or not supported 206 * on this hardware. Report values for the 8-bit framebuffer 207 * so cg3 emulation works. (If this hardware supports 208 * 24-bit mode, the 24-bit framebuffer will also be available) 209 */ 210 fb->fb_type.fb_depth = 8; 211 fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node); 212 213 ramsize = fb->fb_type.fb_height * fb->fb_linebytes; 214 #ifdef TCX_CG8 215 } else { 216 /* 217 * for cg8 emulation, unconditionally report the depth as 218 * 32 bits, but use the height and width reported by the 219 * boot prom. cg8 users want to see the full size of 220 * overlay planes plus color planes included in the 221 * reported framebuffer size. 222 */ 223 fb->fb_type.fb_depth = 32; 224 fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node); 225 fb->fb_linebytes = 226 (fb->fb_type.fb_width * fb->fb_type.fb_depth) / 8; 227 ramsize = TCX_CG8OVERLAY + 228 (fb->fb_type.fb_height * fb->fb_linebytes); 229 } 230 #endif 231 fb->fb_type.fb_cmsize = 256; 232 fb->fb_type.fb_size = ramsize; 233 printf(": %s, %d x %d", OBPNAME, 234 fb->fb_type.fb_width, 235 fb->fb_type.fb_height); 236 #ifdef TCX_CG8 237 /* 238 * if cg8 emulation is enabled, say so; but if hardware can't 239 * emulate cg8, explain that instead 240 */ 241 printf( (sc->sc_8bit)? 242 " (8-bit only)" : 243 " (emulating cg8)"); 244 #endif 245 246 /* 247 * XXX - should be set to FBTYPE_TCX. 248 * XXX For CG3 emulation to work in current (96/6) X11 servers, 249 * XXX `fbtype' must point to an "unregocnised" entry. 250 */ 251 #ifdef TCX_CG8 252 if (sc->sc_8bit) { 253 fb->fb_type.fb_type = FBTYPE_RESERVED3; 254 } else { 255 fb->fb_type.fb_type = FBTYPE_MEMCOLOR; 256 } 257 #else 258 fb->fb_type.fb_type = FBTYPE_RESERVED3; 259 #endif 260 261 262 if (sa->sa_nreg != TCX_NREG) { 263 printf("%s: only %d register sets\n", 264 self->dv_xname, sa->sa_nreg); 265 return; 266 } 267 bcopy(sa->sa_reg, sc->sc_physadr, 268 sa->sa_nreg * sizeof(struct openprom_addr)); 269 270 /* XXX - fix THC and TEC offsets */ 271 sc->sc_physadr[TCX_REG_TEC].oa_base += 0x1000; 272 sc->sc_physadr[TCX_REG_THC].oa_base += 0x1000; 273 274 /* Map the register banks we care about */ 275 if (sbus_bus_map(sa->sa_bustag, 276 sc->sc_physadr[TCX_REG_THC].oa_space, 277 sc->sc_physadr[TCX_REG_THC].oa_base, 278 sizeof (struct tcx_thc), 279 BUS_SPACE_MAP_LINEAR, &bh) != 0) { 280 printf("tcxattach: cannot map thc registers\n"); 281 return; 282 } 283 sc->sc_thc = (volatile struct tcx_thc *) 284 bus_space_vaddr(sa->sa_bustag, bh); 285 286 if (sbus_bus_map(sa->sa_bustag, 287 sc->sc_physadr[TCX_REG_CMAP].oa_space, 288 sc->sc_physadr[TCX_REG_CMAP].oa_base, 289 sizeof (struct bt_regs), 290 BUS_SPACE_MAP_LINEAR, &bh) != 0) { 291 printf("tcxattach: cannot map bt registers\n"); 292 return; 293 } 294 sc->sc_bt = bt = (volatile struct bt_regs *) 295 bus_space_vaddr(sa->sa_bustag, bh); 296 297 #ifdef TCX_CG8 298 if (!sc->sc_8bit) { 299 if (sbus_bus_map(sa->sa_bustag, 300 (bus_type_t)sc->sc_physadr[TCX_REG_RDFB32].oa_space, 301 (bus_addr_t)sc->sc_physadr[TCX_REG_RDFB32].oa_base, 302 TCX_SIZE_DFB32, 303 BUS_SPACE_MAP_LINEAR, 304 0, &bh) != 0) { 305 printf("tcxattach: cannot map control planes\n"); 306 return; 307 } 308 sc->sc_cplane = (volatile ulong *)bh; 309 } 310 #endif 311 312 isconsole = fb_is_console(node); 313 314 printf(", id %d, rev %d, sense %d", 315 (sc->sc_thc->thc_config & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, 316 (sc->sc_thc->thc_config & THC_CFG_REV) >> THC_CFG_REV_SHIFT, 317 (sc->sc_thc->thc_config & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT 318 ); 319 320 /* reset cursor & frame buffer controls */ 321 tcx_reset(sc); 322 323 /* Initialize the default color map. */ 324 bt_initcmap(&sc->sc_cmap, 256); 325 tcx_loadcmap(sc, 0, 256); 326 327 /* enable video */ 328 sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; 329 330 if (isconsole) { 331 printf(" (console)\n"); 332 } else 333 printf("\n"); 334 335 sbus_establish(&sc->sc_sd, &sc->sc_dev); 336 fb_attach(&sc->sc_fb, isconsole); 337 } 338 339 #ifdef TCX_CG8 340 /* 341 * keep track of the number of opens, so we can switch to 24-bit mode 342 * when the device is first opened, and return to 8-bit mode on the 343 * last close. (stolen from cgfourteen driver...) There can only be 344 * one TCX per system, so we only need one flag. 345 */ 346 static int tcx_opens = 0; 347 #endif 348 349 int 350 tcxopen(dev, flags, mode, p) 351 dev_t dev; 352 int flags, mode; 353 struct proc *p; 354 { 355 int unit = minor(dev); 356 #ifdef TCX_CG8 357 struct tcx_softc *sc; 358 int i, s, oldopens; 359 volatile ulong *cptr; 360 struct fbdevice *fb; 361 #endif 362 363 if (unit >= tcx_cd.cd_ndevs || tcx_cd.cd_devs[unit] == NULL) 364 return (ENXIO); 365 #ifdef TCX_CG8 366 sc = tcx_cd.cd_devs[unit]; 367 if (!sc->sc_8bit) { 368 s = splhigh(); 369 oldopens = tcx_opens++; 370 splx(s); 371 if (oldopens == 0) { 372 /* 373 * rewrite the control planes to select 24-bit mode 374 * and clear the screen 375 */ 376 fb = &sc->sc_fb; 377 i = fb->fb_type.fb_height * fb->fb_type.fb_width; 378 cptr = sc->sc_cplane; 379 while (--i >= 0) 380 *cptr++ = TCX_CTL_24_LEVEL; 381 } 382 } 383 #endif 384 return (0); 385 } 386 387 int 388 tcxclose(dev, flags, mode, p) 389 dev_t dev; 390 int flags, mode; 391 struct proc *p; 392 { 393 struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; 394 #ifdef TCX_CG8 395 int i, s, opens; 396 volatile ulong *cptr; 397 struct fbdevice *fb; 398 #endif 399 400 tcx_reset(sc); 401 #ifdef TCX_CG8 402 if (!sc->sc_8bit) { 403 s = splhigh(); 404 opens = --tcx_opens; 405 if (tcx_opens <= 0) 406 opens = tcx_opens = 0; 407 splx(s); 408 if (opens == 0) { 409 /* 410 * rewrite the control planes to select 8-bit mode, 411 * preserving the contents of the screen. 412 * (or we could just bzero the whole thing...) 413 */ 414 fb = &sc->sc_fb; 415 i = fb->fb_type.fb_height * fb->fb_type.fb_width; 416 cptr = sc->sc_cplane; 417 while (--i >= 0) 418 *cptr++ &= TCX_CTL_PIXELMASK; 419 } 420 } 421 #endif 422 return (0); 423 } 424 425 int 426 tcxioctl(dev, cmd, data, flags, p) 427 dev_t dev; 428 u_long cmd; 429 caddr_t data; 430 int flags; 431 struct proc *p; 432 { 433 struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; 434 int error; 435 436 switch (cmd) { 437 438 case FBIOGTYPE: 439 *(struct fbtype *)data = sc->sc_fb.fb_type; 440 break; 441 442 case FBIOGATTR: 443 #define fba ((struct fbgattr *)data) 444 fba->real_type = sc->sc_fb.fb_type.fb_type; 445 fba->owner = 0; /* XXX ??? */ 446 fba->fbtype = sc->sc_fb.fb_type; 447 fba->sattr.flags = 0; 448 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 449 fba->sattr.dev_specific[0] = -1; 450 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 451 fba->emu_types[1] = FBTYPE_SUN3COLOR; 452 fba->emu_types[2] = -1; 453 #undef fba 454 break; 455 456 case FBIOGETCMAP: 457 #define p ((struct fbcmap *)data) 458 return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 459 460 case FBIOPUTCMAP: 461 /* copy to software map */ 462 #ifdef TCX_CG8 463 if (!sc->sc_8bit) { 464 /* 465 * cg8 has extra bits in high-order byte of the index 466 * that bt_putcmap doesn't recognize 467 */ 468 p->index &= 0xffffff; 469 } 470 #endif 471 error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 472 if (error) 473 return (error); 474 /* now blast them into the chip */ 475 /* XXX should use retrace interrupt */ 476 tcx_loadcmap(sc, p->index, p->count); 477 #undef p 478 break; 479 480 case FBIOGVIDEO: 481 *(int *)data = sc->sc_blanked; 482 break; 483 484 case FBIOSVIDEO: 485 if (*(int *)data) 486 tcx_unblank(&sc->sc_dev); 487 else if (!sc->sc_blanked) { 488 sc->sc_blanked = 1; 489 sc->sc_thc->thc_hcmisc &= ~THC_MISC_VIDEN; 490 /* Put monitor in `power-saving mode' */ 491 sc->sc_thc->thc_hcmisc |= THC_MISC_VSYNC_DISABLE; 492 sc->sc_thc->thc_hcmisc |= THC_MISC_HSYNC_DISABLE; 493 } 494 break; 495 496 default: 497 #ifdef DEBUG 498 log(LOG_NOTICE, "tcxioctl(0x%lx) (%s[%d])\n", cmd, 499 p->p_comm, p->p_pid); 500 #endif 501 return (ENOTTY); 502 } 503 return (0); 504 } 505 506 /* 507 * Clean up hardware state (e.g., after bootup or after X crashes). 508 */ 509 static void 510 tcx_reset(sc) 511 struct tcx_softc *sc; 512 { 513 volatile struct bt_regs *bt; 514 515 /* Enable cursor in Brooktree DAC. */ 516 bt = sc->sc_bt; 517 bt->bt_addr = 0x06 << 24; 518 bt->bt_ctrl |= 0x03 << 24; 519 } 520 521 /* 522 * Load a subset of the current (new) colormap into the color DAC. 523 */ 524 static void 525 tcx_loadcmap(sc, start, ncolors) 526 struct tcx_softc *sc; 527 int start, ncolors; 528 { 529 volatile struct bt_regs *bt; 530 u_int *ip, i; 531 int count; 532 533 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ 534 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; 535 bt = sc->sc_bt; 536 bt->bt_addr = BT_D4M4(start) << 24; 537 while (--count >= 0) { 538 i = *ip++; 539 /* hardware that makes one want to pound boards with hammers */ 540 bt->bt_cmap = i; 541 bt->bt_cmap = i << 8; 542 bt->bt_cmap = i << 16; 543 bt->bt_cmap = i << 24; 544 } 545 } 546 547 static void 548 tcx_unblank(dev) 549 struct device *dev; 550 { 551 struct tcx_softc *sc = (struct tcx_softc *)dev; 552 553 if (sc->sc_blanked) { 554 sc->sc_blanked = 0; 555 sc->sc_thc->thc_hcmisc &= ~THC_MISC_VSYNC_DISABLE; 556 sc->sc_thc->thc_hcmisc &= ~THC_MISC_HSYNC_DISABLE; 557 sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; 558 } 559 } 560 561 /* 562 * Base addresses at which users can mmap() the various pieces of a tcx. 563 */ 564 #define TCX_USER_RAM 0x00000000 565 #define TCX_USER_RAM24 0x01000000 566 #define TCX_USER_RAM_COMPAT 0x04000000 /* cg3 emulation */ 567 #define TCX_USER_STIP 0x10000000 568 #define TCX_USER_BLIT 0x20000000 569 #define TCX_USER_RDFB32 0x28000000 570 #define TCX_USER_RSTIP 0x30000000 571 #define TCX_USER_RBLIT 0x38000000 572 #define TCX_USER_TEC 0x70001000 573 #define TCX_USER_BTREGS 0x70002000 574 #define TCX_USER_THC 0x70004000 575 #define TCX_USER_DHC 0x70008000 576 #define TCX_USER_ALT 0x7000a000 577 #define TCX_USER_UART 0x7000c000 578 #define TCX_USER_VRT 0x7000e000 579 #define TCX_USER_ROM 0x70010000 580 581 struct mmo { 582 u_int mo_uaddr; /* user (virtual) address */ 583 u_int mo_size; /* size, or 0 for video ram size */ 584 u_int mo_bank; /* register bank number */ 585 }; 586 587 /* 588 * Return the address that would map the given device at the given 589 * offset, allowing for the given protection, or return -1 for error. 590 * 591 * XXX needs testing against `demanding' applications (e.g., aviator) 592 */ 593 paddr_t 594 tcxmmap(dev, off, prot) 595 dev_t dev; 596 off_t off; 597 int prot; 598 { 599 struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; 600 struct openprom_addr *rr = sc->sc_physadr; 601 struct mmo *mo, *mo_end; 602 u_int u, sz; 603 static struct mmo mmo[] = { 604 { TCX_USER_RAM, 0, TCX_REG_DFB8 }, 605 { TCX_USER_RAM24, 0, TCX_REG_DFB24 }, 606 { TCX_USER_RAM_COMPAT, 0, TCX_REG_DFB8 }, 607 608 { TCX_USER_STIP, 1, TCX_REG_STIP }, 609 { TCX_USER_BLIT, 1, TCX_REG_BLIT }, 610 { TCX_USER_RDFB32, 0, TCX_REG_RDFB32 }, 611 { TCX_USER_RSTIP, 1, TCX_REG_RSTIP }, 612 { TCX_USER_RBLIT, 1, TCX_REG_RBLIT }, 613 { TCX_USER_TEC, 1, TCX_REG_TEC }, 614 { TCX_USER_BTREGS, 8192 /* XXX */, TCX_REG_CMAP }, 615 { TCX_USER_THC, sizeof(struct tcx_thc), TCX_REG_THC }, 616 { TCX_USER_DHC, 1, TCX_REG_DHC }, 617 { TCX_USER_ALT, 1, TCX_REG_ALT }, 618 { TCX_USER_ROM, 65536, TCX_REG_ROM }, 619 }; 620 #define NMMO (sizeof mmo / sizeof *mmo) 621 #ifdef TCX_CG8 622 /* 623 * alternate mapping for CG8 emulation: 624 * map part of the 8-bit-deep framebuffer into the cg8 overlay 625 * space, just so there's something there, and map the 32-bit-deep 626 * framebuffer where cg8 users expect to find it. 627 */ 628 static struct mmo mmo_cg8[] = { 629 { TCX_USER_RAM, TCX_CG8OVERLAY, TCX_REG_DFB8 }, 630 { TCX_CG8OVERLAY, TCX_SIZE_DFB32, TCX_REG_DFB24 }, 631 { TCX_USER_RAM_COMPAT, TCX_SIZE_DFB32, TCX_REG_DFB24 } 632 }; 633 #define NMMO_CG8 (sizeof mmo_cg8 / sizeof *mmo_cg8) 634 #endif 635 636 if (off & PGOFSET) 637 panic("tcxmmap"); 638 639 /* 640 * Entries with size 0 map video RAM (i.e., the size in fb data). 641 * Entries that map 32-bit deep regions are adjusted for their 642 * depth (fb_size gives the size of the 8-bit-deep region). 643 * 644 * Since we work in pages, the fact that the map offset table's 645 * sizes are sometimes bizarre (e.g., 1) is effectively ignored: 646 * one byte is as good as one page. 647 */ 648 #ifdef TCX_CG8 649 if (sc->sc_8bit) { 650 mo = mmo; 651 mo_end = &mmo[NMMO]; 652 } else { 653 mo = mmo_cg8; 654 mo_end = &mmo_cg8[NMMO_CG8]; 655 } 656 #else 657 mo = mmo; 658 mo_end = &mmo[NMMO]; 659 #endif 660 for (; mo < mo_end; mo++) { 661 if ((u_int)off < mo->mo_uaddr) 662 continue; 663 u = off - mo->mo_uaddr; 664 sz = mo->mo_size; 665 if (sz == 0) { 666 sz = sc->sc_fb.fb_type.fb_size; 667 /* 668 * check for the 32-bit-deep regions and adjust 669 * accordingly 670 */ 671 if (mo->mo_uaddr == TCX_USER_RAM24 || 672 mo->mo_uaddr == TCX_USER_RDFB32) { 673 if (sc->sc_8bit) { 674 /* 675 * not present on 8-bit hardware 676 */ 677 continue; 678 } 679 sz *= 4; 680 } 681 } 682 if (u < sz) { 683 return (bus_space_mmap(sc->sc_bustag, 684 BUS_ADDR(rr[mo->mo_bank].oa_space, 685 rr[mo->mo_bank].oa_base), 686 u, 687 prot, 688 BUS_SPACE_MAP_LINEAR)); 689 } 690 } 691 return (-1); 692 } 693