diff options
Diffstat (limited to 'sys/arch/sparc/dev/tcx.c')
| -rw-r--r-- | sys/arch/sparc/dev/tcx.c | 697 |
1 files changed, 401 insertions, 296 deletions
diff --git a/sys/arch/sparc/dev/tcx.c b/sys/arch/sparc/dev/tcx.c index ef8f0b120ce..a3eb138a941 100644 --- a/sys/arch/sparc/dev/tcx.c +++ b/sys/arch/sparc/dev/tcx.c @@ -1,13 +1,37 @@ -/* $OpenBSD: tcx.c,v 1.6 2002/03/14 01:26:43 millert Exp $ */ +/* $OpenBSD: tcx.c,v 1.7 2002/08/12 10:44:04 miod Exp $ */ /* $NetBSD: tcx.c,v 1.8 1997/07/29 09:58:14 fair Exp $ */ -/* +/* + * Copyright (c) 2002 Miodrag Vallat. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * * Copyright (c) 1996 The NetBSD Foundation, Inc. * All rights reserved. - * + * * This code is derived from software contributed to The NetBSD Foundation * by Paul Kranenburg. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,7 +47,7 @@ * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -35,78 +59,108 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - */ + */ /* * color display (TCX) driver. - * - * Does not handle interrupts, even though they can occur. - * - * XXX should defer colormap updates to vertical retrace interrupts */ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/device.h> -#include <machine/fbio.h> #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/mman.h> #include <sys/tty.h> #include <sys/conf.h> -#ifdef DEBUG -#include <sys/proc.h> -#include <sys/syslog.h> -#endif - #include <uvm/uvm_extern.h> #include <machine/autoconf.h> #include <machine/pmap.h> -#include <machine/fbvar.h> #include <machine/cpu.h> #include <machine/conf.h> +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/wscons/wscons_raster.h> +#include <dev/rasops/rasops.h> +#include <machine/fbvar.h> + #include <sparc/dev/btreg.h> #include <sparc/dev/btvar.h> #include <sparc/dev/tcxreg.h> #include <sparc/dev/sbusvar.h> -#if 0 -union cursor_cmap { /* colormap, like bt_cmap, but tiny */ - u_char cm_map[2][3]; /* 2 R/G/B entries */ - u_int cm_chip[2]; /* 2 chip equivalents */ -}; +#include <dev/cons.h> /* for prom console hook */ -struct tcx_cursor { /* tcx hardware cursor status */ - short cc_enable; /* cursor is enabled */ - struct fbcurpos cc_pos; /* position */ - struct fbcurpos cc_hot; /* hot-spot */ - struct fbcurpos cc_size; /* size of mask & image fields */ - u_int cc_bits[2][32]; /* space for mask & image bits */ - union cursor_cmap cc_color; /* cursor colormap */ -}; +/* + * Define TCX_LOWDEPTH to only use the 8 bit color mode of the S24, for faster + * console output. + */ +#ifdef SMALL_KERNEL +#define TCX_LOWDEPTH #endif /* per-display variables */ struct tcx_softc { - struct device sc_dev; /* base device */ - struct sbusdev sc_sd; /* sbus device */ - struct fbdevice sc_fb; /* frame buffer device */ - struct rom_reg sc_physadr[TCX_NREG]; /* phys addr of h/w */ - int sc_bustype; /* type of bus we live on */ + struct sunfb sc_sunfb; /* common base part */ + struct sbusdev sc_sd; /* sbus device */ + struct rom_reg sc_phys[TCX_NREG]; /* phys addr of h/w */ volatile struct bt_regs *sc_bt; /* Brooktree registers */ volatile struct tcx_thc *sc_thc; /* THC registers */ - short sc_blanked; /* true if blanked */ - union bt_cmap sc_cmap; /* Brooktree color map */ + volatile u_int32_t *sc_cplane; /* S24 control plane */ + union bt_cmap sc_cmap; /* Brooktree color map */ + struct intrhand sc_ih; + int sc_nscreens; }; -/* autoconfiguration driver */ -static void tcxattach(struct device *, struct device *, void *); -static int tcxmatch(struct device *, void *, void *); -static void tcx_unblank(struct device *); +struct wsscreen_descr tcx_stdscreen = { + "std", + 0, 0, /* will be filled in */ + 0, + 0, 0, + WSSCREEN_REVERSE | WSSCREEN_WSCOLORS +}; + +const struct wsscreen_descr *tcx_scrlist[] = { + &tcx_stdscreen, + /* XXX other formats? */ +}; + +struct wsscreen_list tcx_screenlist = { + sizeof(tcx_scrlist) / sizeof(struct wsscreen_descr *), tcx_scrlist +}; + +int tcx_ioctl(void *, u_long, caddr_t, int, struct proc *); +int tcx_alloc_screen(void *, const struct wsscreen_descr *, void **, + int *, int *, long *); +void tcx_free_screen(void *, void *); +int tcx_show_screen(void *, void *, int, void (*cb)(void *, int, int), + void *); +paddr_t tcx_mmap(void *, off_t, int); +void tcx_reset(struct tcx_softc *); +void tcx_burner(void *, u_int, u_int); +void tcx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); +static __inline__ void tcx_loadcmap_deferred(struct tcx_softc *, u_int, u_int); +int tcx_intr(void *); +void tcx_prom(void *); + +struct wsdisplay_accessops tcx_accessops = { + tcx_ioctl, + tcx_mmap, + tcx_alloc_screen, + tcx_free_screen, + tcx_show_screen, + NULL, /* load_font */ + NULL, /* scrollback */ + NULL, /* getchar */ + tcx_burner, +}; + +int tcxmatch(struct device *, void *, void *); +void tcxattach(struct device *, struct device *, void *); struct cfattach tcx_ca = { sizeof(struct tcx_softc), tcxmatch, tcxattach @@ -116,17 +170,24 @@ struct cfdriver tcx_cd = { NULL, "tcx", DV_DULL }; -/* frame buffer generic driver */ -static struct fbdriver tcx_fbdriver = { - tcx_unblank, tcxopen, tcxclose, tcxioctl, tcxmmap -}; - -extern int fbnode; - -static void tcx_reset(struct tcx_softc *); -static void tcx_loadcmap(struct tcx_softc *, int, int); +/* + * There are three ways to access the framebuffer memory of the S24: + * - 26 bits per pixel, in 32-bit words; the low-order 24 bits are blue, + * green and red values, and the other two bits select the display modes, + * per pixel. + * - 24 bits per pixel, in 32-bit words; the high-order byte reads as zero, + * and is ignored on writes (so the mode bits can not be altered). + * - 8 bits per pixel, unpadded; writes to this space do not modify the + * other 18 bits, which are hidden. + * + * The entry-level tcx found on the SPARCstation 4 can only provide the 8-bit + * mode. + */ +#define TCX_CTL_8_MAPPED 0x00000000 /* 8 bits, uses colormap */ +#define TCX_CTL_24_MAPPED 0x01000000 /* 24 bits, uses colormap */ +#define TCX_CTL_24_LEVEL 0x03000000 /* 24 bits, true color */ +#define TCX_CTL_PIXELMASK 0x00ffffff /* mask for index/level */ -#define OBPNAME "SUNW,tcx" /* * Match a tcx. */ @@ -139,14 +200,14 @@ tcxmatch(parent, vcf, aux) struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; - if (strcmp(ra->ra_name, OBPNAME)) - return (0); - /* * Mask out invalid flags from the user. */ cf->cf_flags &= FB_USERMASK; + if (strcmp(ra->ra_name, "SUNW,tcx")) + return (0); + if (ca->ca_bustype == BUS_SBUS) return (1); @@ -161,337 +222,381 @@ tcxattach(parent, self, args) struct device *parent, *self; void *args; { - register struct tcx_softc *sc = (struct tcx_softc *)self; - register struct confargs *ca = args; - register int node = 0, ramsize, i; - register volatile struct bt_regs *bt; - struct fbdevice *fb = &sc->sc_fb; - int isconsole = 0, sbus = 1; - extern struct tty *fbconstty; - - fb->fb_driver = &tcx_fbdriver; - fb->fb_device = &sc->sc_dev; - fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags; + struct tcx_softc *sc = (struct tcx_softc *)self; + struct confargs *ca = args; + struct wsemuldisplaydev_attach_args waa; + int node = 0, i; + volatile struct bt_regs *bt; + int isconsole = 0; + char *nam = NULL; - /* - * XXX - should be set to FBTYPE_TCX. - * XXX For CG3 emulation to work in current (96/6) X11 servers, - * XXX `fbtype' must point to an "unregocnised" entry. - */ - fb->fb_type.fb_type = FBTYPE_RESERVED3; + sc->sc_sunfb.sf_flags = self->dv_cfdata->cf_flags; - if (ca->ca_ra.ra_nreg != TCX_NREG) - panic("tcx: oops"); + if (ca->ca_ra.ra_nreg < TCX_NREG) + panic("\ntcx: expected %d registers, got %d", TCX_NREG, + ca->ca_ra.ra_nreg); /* Copy register address spaces */ for (i = 0; i < TCX_NREG; i++) - sc->sc_physadr[i] = ca->ca_ra.ra_reg[i]; - - /* XXX - fix THC and TEC offsets */ - sc->sc_physadr[TCX_REG_TEC].rr_paddr += 0x1000; - sc->sc_physadr[TCX_REG_THC].rr_paddr += 0x1000; + sc->sc_phys[i] = ca->ca_ra.ra_reg[i]; sc->sc_bt = bt = (volatile struct bt_regs *) - mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt); + mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt); sc->sc_thc = (volatile struct tcx_thc *) - mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC], 0, sizeof *sc->sc_thc); + mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC], + 0x1000, sizeof *sc->sc_thc); switch (ca->ca_bustype) { case BUS_SBUS: node = ca->ca_ra.ra_node; + nam = getpropstring(node, "model"); break; - case BUS_OBIO: default: printf("TCX on bus 0x%x?\n", ca->ca_bustype); return; } - fb->fb_type.fb_depth = node_has_property(node, "tcx-24-bit") - ? 24 - : (node_has_property(node, "tcx-8-bit") - ? 8 - : 8); - - fb_setsize(fb, fb->fb_type.fb_depth, 1152, 900, - node, ca->ca_bustype); + printf(": %s\n", nam); - ramsize = fb->fb_type.fb_height * fb->fb_linebytes; - fb->fb_type.fb_cmsize = 256; - fb->fb_type.fb_size = ramsize; - printf(": %s, %d x %d", OBPNAME, - fb->fb_type.fb_width, - fb->fb_type.fb_height); + isconsole = node == fbnode; - isconsole = node == fbnode && fbconstty != NULL; +#ifdef TCX_LOWDEPTH + fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); +#else + fb_setsize(&sc->sc_sunfb, node_has_property(node, "tcx-8-bit") ? + 8 : 32, 1152, 900, node, ca->ca_bustype); +#endif - printf(", id %d, rev %d, sense %d", - (sc->sc_thc->thc_config & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, - (sc->sc_thc->thc_config & THC_CFG_REV) >> THC_CFG_REV_SHIFT, - (sc->sc_thc->thc_config & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT - ); + sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&ca->ca_ra.ra_reg[ + sc->sc_sunfb.sf_depth == 8 ? TCX_REG_DFB8 : TCX_REG_DFB24], + 0, round_page(sc->sc_sunfb.sf_fbsize)); + + /* map the control plane for S24 framebuffers */ + if (sc->sc_sunfb.sf_depth != 8) { + sc->sc_cplane = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_RDFB32], + 0, round_page(sc->sc_sunfb.sf_fbsize)); + } /* reset cursor & frame buffer controls */ tcx_reset(sc); - /* grab initial (current) color map (DOES THIS WORK?) */ + /* grab initial (current) color map */ bt->bt_addr = 0; for (i = 0; i < 256 * 3; i++) ((char *)&sc->sc_cmap)[i] = bt->bt_cmap >> 24; /* enable video */ - sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; + tcx_burner(sc, 1, 0); - if (isconsole) { - printf(" (console)\n"); - } else - printf("\n"); - - if (sbus) - sbus_establish(&sc->sc_sd, &sc->sc_dev); - if (node == fbnode) - fb_attach(&sc->sc_fb, isconsole); -} + sc->sc_sunfb.sf_ro.ri_hw = sc; + fbwscons_init(&sc->sc_sunfb, isconsole); -int -tcxopen(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; -{ - int unit = minor(dev); + tcx_stdscreen.nrows = sc->sc_sunfb.sf_ro.ri_rows; + tcx_stdscreen.ncols = sc->sc_sunfb.sf_ro.ri_cols; + tcx_stdscreen.textops = &sc->sc_sunfb.sf_ro.ri_ops; - if (unit >= tcx_cd.cd_ndevs || tcx_cd.cd_devs[unit] == NULL) - return (ENXIO); - return (0); -} + sc->sc_ih.ih_fun = tcx_intr; + sc->sc_ih.ih_arg = sc; + intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_FB); -int -tcxclose(dev, flags, mode, p) - dev_t dev; - int flags, mode; - struct proc *p; -{ - struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; + if (isconsole) { + fbwscons_console_init(&sc->sc_sunfb, &tcx_stdscreen, -1, + tcx_setcolor, tcx_burner); + } - tcx_reset(sc); - return (0); + sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev); + + printf("%s: %dx%d, depth %d, id %d, rev %d, sense %d\n", + self->dv_xname, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height, + sc->sc_sunfb.sf_depth, + (sc->sc_thc->thc_config & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, + (sc->sc_thc->thc_config & THC_CFG_REV) >> THC_CFG_REV_SHIFT, + (sc->sc_thc->thc_config & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT + ); + + waa.console = isconsole; + waa.scrdata = &tcx_screenlist; + waa.accessops = &tcx_accessops; + waa.accesscookie = sc; + config_found(self, &waa, wsemuldisplaydevprint); } int -tcxioctl(dev, cmd, data, flags, p) - dev_t dev; +tcx_ioctl(dev, cmd, data, flags, p) + void *dev; u_long cmd; - register caddr_t data; + caddr_t data; int flags; struct proc *p; { - register struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; + struct tcx_softc *sc = dev; + struct wsdisplay_cmap *cm; + struct wsdisplay_fbinfo *wdf; int error; switch (cmd) { - - case FBIOGTYPE: - *(struct fbtype *)data = sc->sc_fb.fb_type; + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_SUN24; break; - - case FBIOGATTR: -#define fba ((struct fbgattr *)data) - fba->real_type = sc->sc_fb.fb_type.fb_type; - fba->owner = 0; /* XXX ??? */ - fba->fbtype = sc->sc_fb.fb_type; - fba->sattr.flags = 0; - fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; - fba->sattr.dev_specific[0] = -1; - fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; - fba->emu_types[1] = FBTYPE_SUN3COLOR; - fba->emu_types[2] = -1; -#undef fba + case WSDISPLAYIO_GINFO: + wdf = (struct wsdisplay_fbinfo *)data; + wdf->height = sc->sc_sunfb.sf_height; + wdf->width = sc->sc_sunfb.sf_width; + wdf->depth = sc->sc_sunfb.sf_depth; + wdf->cmsize = (sc->sc_sunfb.sf_depth == 8) ? 256 : 0; break; - - case FBIOGETCMAP: - return (bt_getcmap((struct fbcmap *)data, &sc->sc_cmap, 256)); - - case FBIOPUTCMAP: - /* copy to software map */ -#define p ((struct fbcmap *)data) - error = bt_putcmap(p, &sc->sc_cmap, 256); - if (error) - return (error); - /* now blast them into the chip */ - /* XXX should use retrace interrupt */ - tcx_loadcmap(sc, p->index, p->count); -#undef p + case WSDISPLAYIO_LINEBYTES: + *(u_int *)data = sc->sc_sunfb.sf_linebytes; break; - case FBIOGVIDEO: - *(int *)data = sc->sc_blanked; + case WSDISPLAYIO_GETCMAP: + if (sc->sc_sunfb.sf_depth == 8) { + cm = (struct wsdisplay_cmap *)data; + error = bt_getcmap(&sc->sc_cmap, cm); + if (error) + return (error); + } break; - - case FBIOSVIDEO: - if (*(int *)data) - tcx_unblank(&sc->sc_dev); - else if (!sc->sc_blanked) { - sc->sc_blanked = 1; - sc->sc_thc->thc_hcmisc &= ~THC_MISC_VIDEN; - /* Put monitor in `power-saving mode' */ - sc->sc_thc->thc_hcmisc |= THC_MISC_VSYNC_DISABLE; - sc->sc_thc->thc_hcmisc |= THC_MISC_HSYNC_DISABLE; + case WSDISPLAYIO_PUTCMAP: + if (sc->sc_sunfb.sf_depth == 8) { + cm = (struct wsdisplay_cmap *)data; + error = bt_putcmap(&sc->sc_cmap, cm); + if (error) + return (error); + tcx_loadcmap_deferred(sc, cm->index, cm->count); } break; + case WSDISPLAYIO_SVIDEO: + case WSDISPLAYIO_GVIDEO: + case WSDISPLAYIO_GCURPOS: + case WSDISPLAYIO_SCURPOS: + case WSDISPLAYIO_GCURMAX: + case WSDISPLAYIO_GCURSOR: + case WSDISPLAYIO_SCURSOR: default: -#ifdef DEBUG - log(LOG_NOTICE, "tcxioctl(0x%lx) (%s[%d])\n", cmd, - p->p_comm, p->p_pid); -#endif - return (ENOTTY); + return (-1); /* not supported yet */ } + return (0); } /* * Clean up hardware state (e.g., after bootup or after X crashes). */ -static void +void tcx_reset(sc) - register struct tcx_softc *sc; + struct tcx_softc *sc; { - register volatile struct bt_regs *bt; + volatile struct bt_regs *bt; + + /* Hide the cursor, just in case */ + sc->sc_thc->thc_cursoraddr = THC_CURSOFF; /* Enable cursor in Brooktree DAC. */ bt = sc->sc_bt; bt->bt_addr = 0x06 << 24; bt->bt_ctrl |= 0x03 << 24; -} -/* - * Load a subset of the current (new) colormap into the color DAC. - */ -static void -tcx_loadcmap(sc, start, ncolors) - register struct tcx_softc *sc; - register int start, ncolors; -{ - register volatile struct bt_regs *bt; - register u_int *ip, i; - register int count; + /* + * Select 24-bit mode if appropriate. + */ + if (sc->sc_sunfb.sf_depth != 8) { + volatile u_int32_t *cptr; + u_int32_t pixel; + int ramsize; + + ramsize = sc->sc_sunfb.sf_fbsize / sizeof(u_int32_t); + cptr = sc->sc_cplane; + + /* + * Since the prom output so far has only been white (0) + * or black (255), we can promote the 8 bit plane contents + * to full color. + * Of course, the 24 bit plane uses 0 for black, so a + * reversal is necessary. Blame Sun. + */ + while (ramsize-- != 0) { + pixel = 255 - ((*cptr & TCX_CTL_PIXELMASK) & 0xff); + pixel = (pixel << 16) | (pixel << 8) | pixel; + *cptr++ = pixel | TCX_CTL_24_LEVEL; + } - ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ - count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; - bt = sc->sc_bt; - bt->bt_addr = BT_D4M4(start) << 24; - while (--count >= 0) { - i = *ip++; - /* hardware that makes one want to pound boards with hammers */ - bt->bt_cmap = i; - bt->bt_cmap = i << 8; - bt->bt_cmap = i << 16; - bt->bt_cmap = i << 24; + shutdownhook_establish(tcx_prom, sc); } } -static void -tcx_unblank(dev) - struct device *dev; +void +tcx_prom(v) + void *v; { - struct tcx_softc *sc = (struct tcx_softc *)dev; + struct tcx_softc *sc = v; + extern struct consdev consdev_prom; + + /* + * Select 8-bit mode. + */ + if (sc->sc_sunfb.sf_depth != 8) { + volatile u_int32_t *cptr; + u_int32_t pixel; + int ramsize; + + ramsize = sc->sc_sunfb.sf_fbsize / sizeof(u_int32_t); + cptr = sc->sc_cplane; - if (sc->sc_blanked) { - sc->sc_blanked = 0; - sc->sc_thc->thc_hcmisc &= ~THC_MISC_VSYNC_DISABLE; - sc->sc_thc->thc_hcmisc &= ~THC_MISC_HSYNC_DISABLE; - sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; + while (ramsize-- != 0) { + pixel = (*cptr & TCX_CTL_PIXELMASK); + *cptr++ = pixel | TCX_CTL_8_MAPPED; + } } + + /* + * Go back to prom output for the last few messages, so they + * will be displayed correctly. + */ + cn_tab = &consdev_prom; } -/* - * Base addresses at which users can mmap() the various pieces of a tcx. - */ -#define TCX_USER_RAM 0x00000000 -#define TCX_USER_RAM24 0x01000000 -#define TCX_USER_RAM_COMPAT 0x04000000 /* cg3 emulation */ -#define TCX_USER_STIP 0x10000000 -#define TCX_USER_BLIT 0x20000000 -#define TCX_USER_RDFB32 0x28000000 -#define TCX_USER_RSTIP 0x30000000 -#define TCX_USER_RBLIT 0x38000000 -#define TCX_USER_TEC 0x70001000 -#define TCX_USER_BTREGS 0x70002000 -#define TCX_USER_THC 0x70004000 -#define TCX_USER_DHC 0x70008000 -#define TCX_USER_ALT 0x7000a000 -#define TCX_USER_UART 0x7000c000 -#define TCX_USER_VRT 0x7000e000 -#define TCX_USER_ROM 0x70010000 - -struct mmo { - u_int mo_uaddr; /* user (virtual) address */ - u_int mo_size; /* size, or 0 for video ram size */ - u_int mo_bank; /* register bank number */ -}; +void +tcx_burner(v, on, flags) + void *v; + u_int on, flags; +{ + struct tcx_softc *sc = v; + int s; + u_int32_t thcm; + + s = splhigh(); + thcm = sc->sc_thc->thc_hcmisc; + if (on) { + thcm |= THC_MISC_VIDEN; + thcm &= ~(THC_MISC_VSYNC_DISABLE | THC_MISC_HSYNC_DISABLE); + } else { + thcm &= ~THC_MISC_VIDEN; + if (flags & WSDISPLAY_BURN_VBLANK) + thcm |= THC_MISC_VSYNC_DISABLE | THC_MISC_HSYNC_DISABLE; + } + sc->sc_thc->thc_hcmisc = thcm; + splx(s); +} /* * Return the address that would map the given device at the given * offset, allowing for the given protection, or return -1 for error. - * - * XXX needs testing against `demanding' applications (e.g., aviator) */ paddr_t -tcxmmap(dev, off, prot) - dev_t dev; - off_t off; +tcx_mmap(v, offset, prot) + void *v; + off_t offset; int prot; { - register struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; - register struct mmo *mo; - register u_int u, sz; - static struct mmo mmo[] = { - { TCX_USER_RAM, 0, TCX_REG_DFB8 }, - { TCX_USER_RAM24, 0, TCX_REG_DFB24 }, - { TCX_USER_RAM_COMPAT, 0, TCX_REG_DFB8 }, - - { TCX_USER_STIP, 1, TCX_REG_STIP }, - { TCX_USER_BLIT, 1, TCX_REG_BLIT }, - { TCX_USER_RDFB32, 1, TCX_REG_RDFB32 }, - { TCX_USER_RSTIP, 1, TCX_REG_RSTIP }, - { TCX_USER_RBLIT, 1, TCX_REG_RBLIT }, - { TCX_USER_TEC, 1, TCX_REG_TEC }, - { TCX_USER_BTREGS, 8192 /* XXX */, TCX_REG_CMAP }, - { TCX_USER_THC, sizeof(struct tcx_thc), TCX_REG_THC }, - { TCX_USER_DHC, 1, TCX_REG_DHC }, - { TCX_USER_ALT, 1, TCX_REG_ALT }, - { TCX_USER_ROM, 65536, TCX_REG_ROM }, - }; -#define NMMO (sizeof mmo / sizeof *mmo) - - if (off & PGOFSET) - panic("tcxmmap"); - - if (off < 0) + struct tcx_softc *sc = v; + int reg; + + if (offset & PGOFSET) return (-1); - /* - * Entries with size 0 map video RAM (i.e., the size in fb data). - * - * Since we work in pages, the fact that the map offset table's - * sizes are sometimes bizarre (e.g., 1) is effectively ignored: - * one byte is as good as one page. - */ - for (mo = mmo; mo < &mmo[NMMO]; mo++) { - if ((u_int)off < mo->mo_uaddr) - continue; - u = off - mo->mo_uaddr; - sz = mo->mo_size ? mo->mo_size : sc->sc_fb.fb_type.fb_size; - if (u < sz) - return (REG2PHYS(&sc->sc_physadr[mo->mo_bank], u) | - PMAP_NC); + /* Allow mapping as a dumb framebuffer from offset 0 */ + if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { + reg = (sc->sc_sunfb.sf_depth == 8) ? + TCX_REG_DFB8 : TCX_REG_DFB24; + return (REG2PHYS(&sc->sc_phys[reg], offset) | PMAP_NC); } -#ifdef DEBUG - { - register struct proc *p = curproc; /* XXX */ - log(LOG_NOTICE, "tcxmmap(0x%x) (%s[%d])\n", off, p->p_comm, p->p_pid); - } -#endif + return (-1); /* not a user-map offset */ } + +void +tcx_setcolor(v, index, r, g, b) + void *v; + u_int index; + u_int8_t r, g, b; +{ + struct tcx_softc *sc = v; + + bt_setcolor(&sc->sc_cmap, sc->sc_bt, index, r, g, b, 1); +} + +int +tcx_alloc_screen(v, type, cookiep, curxp, curyp, attrp) + void *v; + const struct wsscreen_descr *type; + void **cookiep; + int *curxp, *curyp; + long *attrp; +{ + struct tcx_softc *sc = v; + + if (sc->sc_nscreens > 0) + return (ENOMEM); + + *cookiep = &sc->sc_sunfb.sf_ro; + *curyp = 0; + *curxp = 0; + if (sc->sc_sunfb.sf_depth == 8) { + sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, + WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); + } else { + sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, + 0, 0, 0, attrp); + } + sc->sc_nscreens++; + return (0); +} + +void +tcx_free_screen(v, cookie) + void *v; + void *cookie; +{ + struct tcx_softc *sc = v; + + sc->sc_nscreens--; +} + +int +tcx_show_screen(v, cookie, waitok, cb, cbarg) + void *v; + void *cookie; + int waitok; + void (*cb)(void *, int, int); + void *cbarg; +{ + return (0); +} + +static __inline__ void +tcx_loadcmap_deferred(struct tcx_softc *sc, u_int start, u_int ncolors) +{ + u_int32_t thcm; + + thcm = sc->sc_thc->thc_hcmisc; + thcm &= ~THC_MISC_RESET; + thcm |= THC_MISC_INTEN; + sc->sc_thc->thc_hcmisc = thcm; +} + +int +tcx_intr(v) + void *v; +{ + struct tcx_softc *sc = v; + u_int32_t thcm; + + thcm = sc->sc_thc->thc_hcmisc; + if ((thcm & (THC_MISC_INTEN | THC_MISC_INTR)) != + (THC_MISC_INTEN | THC_MISC_INTR)) { + /* Not expecting an interrupt, it's not for us. */ + return (0); + } + + /* Acknowledge the interrupt and disable it. */ + thcm &= ~(THC_MISC_RESET | THC_MISC_INTEN); + thcm |= THC_MISC_INTR; + sc->sc_thc->thc_hcmisc = thcm; + + bt_loadcmap(&sc->sc_cmap, sc->sc_bt, 0, 256, 1); + + return (1); +} |
