summaryrefslogtreecommitdiffstats
path: root/sys/arch/sparc/dev/tcx.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc/dev/tcx.c')
-rw-r--r--sys/arch/sparc/dev/tcx.c697
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);
+}