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