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