summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-03-09 01:46:38 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-03-09 01:46:38 +0000
commitd80eef4b19766fb10d730452512b5704669a9ef3 (patch)
treeb54ddf46fbedd0d71abe1882799c56b75bc5d644 /sys
parent8cf7a45e373025e4cbd2f25cb83fe987f5bf1667 (diff)
A work-in-progress driver for the Sun ZX (aka Leo) accelerated frame buffers,
from NetBSD. This was initially written for Linux, then each iteration attempted to replace more 0x12345 magic numbers with meaningful constants. The lack of documentation for the hardware still makes some areas a guess orgy. No doc, no kernel configuration file entries, and X11 is disabled on purpose at the moment. This will be coming soon.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc/dev/zx.c752
-rw-r--r--sys/arch/sparc/dev/zxreg.h274
2 files changed, 1026 insertions, 0 deletions
diff --git a/sys/arch/sparc/dev/zx.c b/sys/arch/sparc/dev/zx.c
new file mode 100644
index 00000000000..8b183d65b0c
--- /dev/null
+++ b/sys/arch/sparc/dev/zx.c
@@ -0,0 +1,752 @@
+/* $OpenBSD: zx.c,v 1.1 2003/03/09 01:46:37 miod Exp $ */
+/* $NetBSD: zx.c,v 1.5 2002/10/02 16:52:46 thorpej Exp $ */
+
+/*
+ * Copyright (c) 2003, 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.
+ *
+ * Derived from NetBSD syssrc/sys/dev/sbus/zx.c under the following licence
+ * terms:
+ *
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 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
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/*
+ * Driver for the Sun ZX display adapter. This would be called 'leo', but
+ * NetBSD/amiga already has a driver by that name. The XFree86 and Linux
+ * drivers were used as "living documentation" when writing this; thanks
+ * to the authors.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/autoconf.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/zxreg.h>
+#include <sparc/dev/sbusvar.h>
+
+#define ZX_WID_SHARED_8 0
+#define ZX_WID_SHARED_24 1
+#define ZX_WID_DBL_8 2
+#define ZX_WID_DBL_24 3
+
+/*
+ * Per-instance data.
+ */
+
+struct zx_cmap {
+ u_int8_t cm_red[256];
+ u_int8_t cm_green[256];
+ u_int8_t cm_blue[256];
+};
+
+struct zx_softc {
+ struct sunfb sc_sunfb;
+ struct sbusdev sc_sd;
+ struct rom_reg sc_phys;
+
+ struct zx_cmap sc_cmap; /* shadow color map for overlay plane */
+
+ volatile struct zx_command *sc_zc;
+ volatile struct zx_cross *sc_zx;
+ volatile struct zx_draw *sc_zd_ss0;
+ volatile struct zx_draw_ss1 *sc_zd_ss1;
+ volatile struct zx_cursor *sc_zcu;
+
+ int sc_nscreens;
+};
+
+struct wsscreen_descr zx_stdscreen = {
+ "std"
+};
+
+const struct wsscreen_descr *zx_scrlist[] = {
+ &zx_stdscreen
+};
+
+struct wsscreen_list zx_screenlist = {
+ sizeof(zx_scrlist) / sizeof(struct wsscreen_descr *),
+ zx_scrlist
+};
+
+int zx_ioctl(void *, u_long, caddr_t, int, struct proc *);
+int zx_alloc_screen(void *, const struct wsscreen_descr *, void **,
+ int *, int *, long *);
+void zx_free_screen(void *, void *);
+int zx_show_screen(void *, void *, int, void (*)(void *, int, int), void *);
+paddr_t zx_mmap(void *, off_t, int);
+void zx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
+void zx_reset(struct zx_softc *);
+void zx_burner(void *, u_int, u_int);
+
+struct wsdisplay_accessops zx_accessops = {
+ zx_ioctl,
+ zx_mmap,
+ zx_alloc_screen,
+ zx_free_screen,
+ zx_show_screen,
+ NULL, /* load_font */
+ NULL, /* scrollback */
+ NULL, /* getchar */
+ zx_burner
+};
+
+/* Force 32-bit writes. */
+#define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v))
+
+#define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
+ ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
+
+#define ZX_BWIDTH 13
+#define ZX_WWIDTH 11 /* word width */
+
+void zx_attach(struct device *, struct device *, void *);
+int zx_match(struct device *, void *, void *);
+
+int zx_putcmap(struct zx_softc *);
+void zx_copyrect(struct rasops_info *, int, int, int, int, int, int);
+int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int);
+int zx_cross_wait(struct zx_softc *);
+void zx_fillrect(struct rasops_info *, int, int, int, int, long, int);
+int zx_intr(void *);
+void zx_prom(void *);
+
+void zx_cursor(void *, int, int, int);
+void zx_putchar(void *, int, int, u_int, long);
+void zx_copycols(void *, int, int, int, int);
+void zx_erasecols(void *, int, int, int, long);
+void zx_copyrows(void *, int, int, int);
+void zx_eraserows(void *, int, int, long);
+void zx_do_cursor(struct rasops_info *);
+
+struct cfattach zx_ca = {
+ sizeof(struct zx_softc), zx_match, zx_attach
+};
+
+struct cfdriver zx_cd = {
+ NULL, "zx", DV_DULL
+};
+
+int
+zx_match(struct device *parent, void *vcf, void *aux)
+{
+ struct cfdata *cf = vcf;
+ struct confargs *ca = aux;
+ struct romaux *ra = &ca->ca_ra;
+
+ /*
+ * Mask out invalid flags from the user.
+ */
+ cf->cf_flags &= FB_USERMASK;
+
+ if (strcmp(ra->ra_name, "SUNW,leo") == 0)
+ return (1);
+
+ return (0);
+}
+
+void
+zx_attach(struct device *parent, struct device *self, void *args)
+{
+ struct zx_softc *sc = (struct zx_softc *)self;
+ struct confargs *ca = args;
+ struct rasops_info *ri;
+ struct wsemuldisplaydev_attach_args waa;
+ int node, isconsole = 0;
+ const char *nam;
+
+ sc->sc_sunfb.sf_flags = self->dv_cfdata->cf_flags;
+ ri = &sc->sc_sunfb.sf_ro;
+ node = ca->ca_ra.ra_node;
+
+ /*
+ * Map the various parts of the card.
+ */
+ sc->sc_phys = ca->ca_ra.ra_reg[0];
+
+ sc->sc_zc = (struct zx_command *)
+ mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LC_SS0_USR,
+ sizeof(struct zx_command));
+ sc->sc_zd_ss0 = (struct zx_draw *)
+ mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LD_SS0,
+ sizeof(struct zx_draw));
+ sc->sc_zd_ss1 = (struct zx_draw_ss1 *)
+ mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LD_SS1,
+ sizeof(struct zx_draw_ss1));
+ sc->sc_zx = (struct zx_cross *)
+ mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LX_CROSS,
+ sizeof(struct zx_cross));
+ sc->sc_zcu = (struct zx_cursor *)
+ mapiodev(ca->ca_ra.ra_reg, ZX_OFF_LX_CURSOR,
+ sizeof(struct zx_cursor));
+
+ nam = getpropstring(node, "model");
+ if (*nam == '\0')
+ nam = ca->ca_ra.ra_name;
+ printf(": %s", nam);
+
+ isconsole = node == fbnode;
+
+ /*
+ * The console is using the 8-bit overlay plane, while the prom
+ * will correctly report 32 bit depth.
+ * The following is an equivalent for
+ * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
+ * forcing the depth value not to be overwritten.
+ * Furthermore, the linebytes value is in fact 8192 bytes.
+ */
+ sc->sc_sunfb.sf_depth = 8;
+ sc->sc_sunfb.sf_width = getpropint(node, "width", 1152);
+ sc->sc_sunfb.sf_height = getpropint(node, "height", 900);
+ sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH;
+ sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH;
+
+ printf(", %d x %d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
+
+ ri->ri_bits = mapiodev(ca->ca_ra.ra_reg,
+ ZX_OFF_SS0, round_page(sc->sc_sunfb.sf_fbsize));
+ ri->ri_hw = sc;
+
+ /*
+ * Watch out! rasops_init() invoked via fbwscons_init() would
+ * not compute ri_bits correctly, if it had been tricked with the
+ * low depth value. So masquerade as 32 bits for the call. This
+ * will invoke rasops32_init() instead of rasops8_init(), but this
+ * doesn't matter as we will override all the rasops functions
+ * below.
+ */
+ sc->sc_sunfb.sf_depth = 32;
+ fbwscons_init(&sc->sc_sunfb, isconsole);
+ sc->sc_sunfb.sf_depth = ri->ri_depth = 8;
+
+ ri->ri_ops.copyrows = zx_copyrows;
+ ri->ri_ops.copycols = zx_copycols;
+ ri->ri_ops.eraserows = zx_eraserows;
+ ri->ri_ops.erasecols = zx_erasecols;
+ ri->ri_ops.putchar = zx_putchar;
+ ri->ri_do_cursor = zx_do_cursor;
+
+ zx_stdscreen.capabilities = ri->ri_caps;
+ zx_stdscreen.nrows = ri->ri_rows;
+ zx_stdscreen.ncols = ri->ri_cols;
+ zx_stdscreen.textops = &ri->ri_ops;
+
+ if (isconsole) {
+ /* zx_reset() below will clear screen, so restart at 1st row */
+ fbwscons_console_init(&sc->sc_sunfb, &zx_stdscreen, 0,
+ zx_burner);
+ }
+
+ /* reset cursor & frame buffer controls */
+ zx_reset(sc);
+
+ /* enable video */
+ zx_burner(sc, 1, 0);
+
+ sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev);
+
+ waa.console = isconsole;
+ waa.scrdata = &zx_screenlist;
+ waa.accessops = &zx_accessops;
+ waa.accesscookie = sc;
+ config_found(self, &waa, wsemuldisplaydevprint);
+}
+
+int
+zx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
+{
+ struct zx_softc *sc = dev;
+ struct wsdisplay_fbinfo *wdf;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN;
+ break;
+ 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 = 0;
+ break;
+ case WSDISPLAYIO_LINEBYTES:
+#if 0
+ *(u_int *)data = sc->sc_sunfb.sf_linebytes;
+ break;
+#else
+ /* Prevent X11 from starting, on purpose */
+ return (-1);
+#endif
+
+ case WSDISPLAYIO_GETCMAP:
+ case WSDISPLAYIO_PUTCMAP:
+ break;
+
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+zx_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
+ int *curxp, int *curyp, long *attrp)
+{
+ struct zx_softc *sc = v;
+
+ if (sc->sc_nscreens > 0)
+ return (ENOMEM);
+
+ *cookiep = &sc->sc_sunfb.sf_ro;
+ *curyp = 0;
+ *curxp = 0;
+ sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
+ WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
+ sc->sc_nscreens++;
+ return (0);
+}
+
+void
+zx_free_screen(void *v, void *cookie)
+{
+ struct zx_softc *sc = v;
+
+ sc->sc_nscreens--;
+}
+
+int
+zx_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
+ void *cbarg)
+{
+ return (0);
+}
+
+/*
+ * Return the address that would map the given device at the given
+ * offset, allowing for the given protection, or return -1 for error.
+ */
+paddr_t
+zx_mmap(void *v, off_t offset, int prot)
+{
+ struct zx_softc *sc = v;
+
+ if (offset & PGOFSET)
+ return (-1);
+
+ /* Allow mapping as a dumb framebuffer from offset 0 */
+ if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
+ return (REG2PHYS(&sc->sc_phys, ZX_OFF_SS0 + offset) | PMAP_NC);
+ }
+
+ return (-1);
+}
+
+void
+zx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
+{
+ struct zx_softc *sc = v;
+
+ sc->sc_cmap.cm_red[index] = r;
+ sc->sc_cmap.cm_green[index] = g;
+ sc->sc_cmap.cm_blue[index] = b;
+}
+
+void
+zx_reset(struct zx_softc *sc)
+{
+ volatile struct zx_draw *zd;
+ volatile struct zx_command *zc;
+ u_int32_t i;
+ const u_char *color;
+ u_int8_t *r, *g, *b;
+
+ zd = sc->sc_zd_ss0;
+ zc = sc->sc_zc;
+
+ zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0);
+ zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30);
+ zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20);
+ zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30);
+
+ i = sc->sc_zd_ss1->zd_misc;
+ i |= ZX_SS1_MISC_ENABLE;
+ SETREG(sc->sc_zd_ss1->zd_misc, i);
+
+ /*
+ * XXX
+ * If zc_fill is not set to that value, there will be black bars
+ * left in the margins. But then with this value, the screen gets
+ * cleared. Go figure.
+ */
+ SETREG(zd->zd_wid, 0xffffffff);
+ SETREG(zd->zd_wmask, 0xffff);
+ SETREG(zd->zd_vclipmin, 0);
+ SETREG(zd->zd_vclipmax,
+ (sc->sc_sunfb.sf_width - 1) | ((sc->sc_sunfb.sf_height - 1) << 16));
+ SETREG(zd->zd_fg, 0);
+ SETREG(zd->zd_planemask, 0xff000000);
+ SETREG(zd->zd_rop, ZX_STD_ROP | ZX_ATTR_WRITEZ_ENABLE);
+ SETREG(zd->zd_widclip, 0);
+
+ SETREG(zc->zc_extent, (sc->sc_sunfb.sf_width - 1) |
+ ((sc->sc_sunfb.sf_height - 1) << ZX_WWIDTH));
+ SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR);
+ SETREG(zc->zc_fill, 0x80000000);
+ SETREG(zc->zc_fontt, 0);
+
+ while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
+ ;
+
+ /*
+ * Initialize the 8-bit colormap
+ */
+ r = sc->sc_cmap.cm_red;
+ g = sc->sc_cmap.cm_green;
+ b = sc->sc_cmap.cm_blue;
+ color = rasops_cmap;
+ for (i = 0; i < 256; i++) {
+ *r++ = *color++;
+ *g++ = *color++;
+ *b++ = *color++;
+ }
+ fbwscons_setcolormap(&sc->sc_sunfb, zx_setcolor);
+ zx_putcmap(sc);
+}
+
+int
+zx_cross_wait(struct zx_softc *sc)
+{
+ volatile struct zx_cross *zx;
+ int i;
+
+ zx = sc->sc_zx;
+
+ for (i = 300000; i != 0; i--) {
+ if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0)
+ break;
+ DELAY(1);
+ }
+
+ if (i == 0)
+ printf("%s: zx_cross_wait: timed out\n",
+ sc->sc_sunfb.sf_dev.dv_xname);
+
+ return (i);
+}
+
+int
+zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value)
+{
+ volatile struct zx_cross *zx;
+ u_int tmp;
+
+ zx = sc->sc_zx;
+ SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
+
+ if (!zx_cross_wait(sc))
+ return (1);
+
+ if (type == ZX_WID_DBL_8)
+ tmp = (index & 0x0f) + 0x40;
+ else if (type == ZX_WID_DBL_24)
+ tmp = index & 0x3f;
+
+ SETREG(zx->zx_type, 0x5800 + tmp);
+ SETREG(zx->zx_value, value);
+ SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
+ SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2);
+
+ return (0);
+}
+
+int
+zx_putcmap(struct zx_softc *sc)
+{
+ volatile struct zx_cross *zx;
+ u_int32_t i;
+ u_int8_t *r, *g, *b;
+
+ zx = sc->sc_zx;
+
+ SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
+ if (!zx_cross_wait(sc))
+ return (1);
+
+ SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA);
+
+ r = sc->sc_cmap.cm_red;
+ g = sc->sc_cmap.cm_green;
+ b = sc->sc_cmap.cm_blue;
+ for (i = 0; i < 256; i++) {
+ SETREG(zx->zx_value, *r++ | (*g++ << 8) | (*b++ << 16));
+ }
+
+ SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
+ i = zx->zx_csr;
+ i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2;
+ SETREG(zx->zx_csr, i);
+ return (0);
+}
+
+void
+zx_burner(void *v, u_int on, u_int flags)
+{
+ struct zx_softc *sc = v;
+ volatile struct zx_cross *zx;
+ u_int32_t i;
+
+ zx = sc->sc_zx;
+
+ SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO);
+ i = zx->zx_csr;
+ if (on) {
+ i |= ZX_CROSS_CSR_ENABLE;
+ } else {
+ i &= ~ZX_CROSS_CSR_ENABLE;
+ }
+ SETREG(zx->zx_csr, i);
+}
+
+void
+zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, long attr,
+ int rop)
+{
+ struct zx_softc *sc;
+ volatile struct zx_command *zc;
+ volatile struct zx_draw *zd;
+ int fg, bg;
+
+ sc = ri->ri_hw;
+ zc = sc->sc_zc;
+ zd = sc->sc_zd_ss0;
+
+ rasops_unpack_attr(attr, &fg, &bg, NULL);
+ x = x * ri->ri_font->fontwidth + ri->ri_xorigin;
+ y = y * ri->ri_font->fontheight + ri->ri_yorigin;
+ w = ri->ri_font->fontwidth * w - 1;
+ h = ri->ri_font->fontheight * h - 1;
+
+ while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
+ ;
+
+ SETREG(zd->zd_rop, rop);
+ SETREG(zd->zd_fg, bg << 24);
+ SETREG(zc->zc_extent, w | (h << ZX_WWIDTH));
+ SETREG(zc->zc_fill, x | (y << ZX_WWIDTH) | 0x80000000);
+}
+
+void
+zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w,
+ int h)
+{
+ struct zx_softc *sc;
+ volatile struct zx_command *zc;
+ volatile struct zx_draw *zd;
+ int dir;
+
+ sc = ri->ri_hw;
+ zc = sc->sc_zc;
+ zd = sc->sc_zd_ss0;
+
+ sx = sx * ri->ri_font->fontwidth + ri->ri_xorigin;
+ sy = sy * ri->ri_font->fontheight + ri->ri_yorigin;
+ dx = dx * ri->ri_font->fontwidth + ri->ri_xorigin;
+ dy = dy * ri->ri_font->fontheight + ri->ri_yorigin;
+ w = w * ri->ri_font->fontwidth - 1;
+ h = h * ri->ri_font->fontheight - 1;
+
+ if (sy < dy || sx < dx) {
+ dir = ZX_EXTENT_DIR_BACKWARDS;
+ sx += w;
+ sy += h;
+ dx += w;
+ dy += h;
+ } else
+ dir = ZX_EXTENT_DIR_FORWARDS;
+
+ while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
+ ;
+
+ SETREG(zd->zd_rop, ZX_STD_ROP);
+ SETREG(zc->zc_extent, w | (h << ZX_WWIDTH) | dir);
+ SETREG(zc->zc_src, sx | (sy << ZX_WWIDTH));
+ SETREG(zc->zc_copy, dx | (dy << ZX_WWIDTH));
+}
+
+void
+zx_do_cursor(struct rasops_info *ri)
+{
+
+ zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, WSCOL_BLACK << 16,
+ ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
+ ZX_ATTR_FORCE_WID);
+}
+
+void
+zx_erasecols(void *cookie, int row, int col, int num, long attr)
+{
+ struct rasops_info *ri;
+
+ ri = (struct rasops_info *)cookie;
+
+ zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP);
+}
+
+void
+zx_eraserows(void *cookie, int row, int num, long attr)
+{
+ struct rasops_info *ri;
+
+ ri = (struct rasops_info *)cookie;
+
+ zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP);
+}
+
+void
+zx_copyrows(void *cookie, int src, int dst, int num)
+{
+ struct rasops_info *ri;
+
+ ri = (struct rasops_info *)cookie;
+
+ zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num);
+}
+
+void
+zx_copycols(void *cookie, int row, int src, int dst, int num)
+{
+ struct rasops_info *ri;
+
+ ri = (struct rasops_info *)cookie;
+
+ zx_copyrect(ri, src, row, dst, row, num, 1);
+}
+
+void
+zx_putchar(void *cookie, int row, int col, u_int uc, long attr)
+{
+ struct rasops_info *ri;
+ struct zx_softc *sc;
+ struct wsdisplay_font *font;
+ volatile struct zx_command *zc;
+ volatile struct zx_draw *zd;
+ volatile u_int32_t *dp;
+ u_int8_t *fb;
+ int fs, i, fg, bg, ul;
+
+ ri = (struct rasops_info *)cookie;
+
+ if (uc == ' ') {
+ zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP);
+ return;
+ }
+
+ sc = ri->ri_hw;
+ zc = sc->sc_zc;
+ zd = sc->sc_zd_ss0;
+ font = ri->ri_font;
+
+ dp = (volatile u_int32_t *)ri->ri_bits +
+ ((row * font->fontheight) << ZX_WWIDTH) + col * font->fontwidth;
+ fb = (u_int8_t *)font->data + (uc - font->firstchar) *
+ ri->ri_fontscale;
+ fs = font->stride;
+ rasops_unpack_attr(attr, &fg, &bg, &ul);
+
+ while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
+ ;
+
+ SETREG(zd->zd_rop, ZX_STD_ROP);
+ SETREG(zd->zd_fg, fg << 24);
+ SETREG(zd->zd_bg, bg << 24);
+ SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
+
+ if (font->fontwidth <= 8) {
+ for (i = font->fontheight; i != 0; i--, dp += 1 << ZX_WWIDTH) {
+ *dp = *fb << 24;
+ fb += fs;
+ }
+ } else {
+ for (i = font->fontheight; i != 0; i--, dp += 1 << ZX_WWIDTH) {
+ *dp = *((u_int16_t *)fb) << 16;
+ fb += fs;
+ }
+ }
+
+ /* underline XXX does this really work??? */
+ if (ul) {
+ dp -= 2 << ZX_WWIDTH;
+ *dp = 0xffffffff;
+ }
+}
diff --git a/sys/arch/sparc/dev/zxreg.h b/sys/arch/sparc/dev/zxreg.h
new file mode 100644
index 00000000000..5ea0eece861
--- /dev/null
+++ b/sys/arch/sparc/dev/zxreg.h
@@ -0,0 +1,274 @@
+/* $OpenBSD: zxreg.h,v 1.1 2003/03/09 01:46:37 miod Exp $ */
+/* $NetBSD: zxreg.h,v 1.1 2002/09/13 14:03:53 ad Exp $ */
+
+/*
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 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
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * 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) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _DEV_SBUS_ZXREG_H_
+#define _DEV_SBUS_ZXREG_H_
+
+/* Hardware offsets. */
+#define ZX_OFF_UNK2 0x00000000
+#define ZX_OFF_LC_SS0_KRN 0x00200000
+#define ZX_OFF_LC_SS0_USR 0x00201000
+#define ZX_OFF_LD_SS0 0x00400000
+#define ZX_OFF_LD_GBL 0x00401000
+#define ZX_OFF_LX_CROSS 0x00600000
+#define ZX_OFF_LX_CURSOR 0x00601000
+#define ZX_OFF_UNK 0x00602000
+#define ZX_OFF_SS0 0x00800000
+#define ZX_OFF_LC_SS1_KRN 0x01200000
+#define ZX_OFF_LC_SS1_USR 0x01201000
+#define ZX_OFF_LD_SS1 0x01400000
+#define ZX_OFF_SS1 0x01800000
+
+/* ROP register */
+#define ZX_ATTR_PICK_DISABLE 0x00000000
+#define ZX_ATTR_PICK_2D 0x80000000
+#define ZX_ATTR_PICK_3D 0xa0000000
+#define ZX_ATTR_PICK_2D_REND 0xc0000000
+#define ZX_ATTR_PICK_3D_REND 0xe0000000
+
+#define ZX_ATTR_DCE_DISABLE 0x00000000
+#define ZX_ATTR_DCE_ENABLE 0x10000000
+
+#define ZX_ATTR_APE_DISABLE 0x00000000
+#define ZX_ATTR_APE_ENABLE 0x08000000
+
+#define ZX_ATTR_COLOR_VAR 0x00000000
+#define ZX_ATTR_COLOR_CONST 0x04000000
+
+#define ZX_ATTR_AA_DISABLE 0x02000000
+#define ZX_ATTR_AA_ENABLE 0x01000000
+
+#define ZX_ATTR_ABE_BG 0x00000000 /* dst + alpha * (src - bg) */
+#define ZX_ATTR_ABE_FB 0x00800000 /* dst + alpha * (src - dst) */
+
+#define ZX_ATTR_ABE_DISABLE 0x00000000
+#define ZX_ATTR_ABE_ENABLE 0x00400000
+
+#define ZX_ATTR_BLTSRC_A 0x00000000
+#define ZX_ATTR_BLTSRC_B 0x00200000
+
+#define ZX_ROP_ZERO (0x0 << 18)
+#define ZX_ROP_NEW_AND_OLD (0x8 << 18)
+#define ZX_ROP_NEW_AND_NOLD (0x4 << 18)
+#define ZX_ROP_NEW (0xc << 18)
+#define ZX_ROP_NNEW_AND_OLD (0x2 << 18)
+#define ZX_ROP_OLD (0xa << 18)
+#define ZX_ROP_NEW_XOR_OLD (0x6 << 18)
+#define ZX_ROP_NEW_OR_OLD (0xe << 18)
+#define ZX_ROP_NNEW_AND_NOLD (0x1 << 18)
+#define ZX_ROP_NNEW_XOR_NOLD (0x9 << 18)
+#define ZX_ROP_NOLD (0x5 << 18)
+#define ZX_ROP_NEW_OR_NOLD (0xd << 18)
+#define ZX_ROP_NNEW (0x3 << 18)
+#define ZX_ROP_NNEW_OR_OLD (0xb << 18)
+#define ZX_ROP_NNEW_OR_NOLD (0x7 << 18)
+#define ZX_ROP_ONES (0xf << 18)
+
+#define ZX_ATTR_HSR_DISABLE 0x00000000
+#define ZX_ATTR_HSR_ENABLE 0x00020000
+
+#define ZX_ATTR_WRITEZ_DISABLE 0x00000000
+#define ZX_ATTR_WRITEZ_ENABLE 0x00010000
+
+#define ZX_ATTR_Z_VAR 0x00000000
+#define ZX_ATTR_Z_CONST 0x00008000
+
+#define ZX_ATTR_WCLIP_DISABLE 0x00000000
+#define ZX_ATTR_WCLIP_ENABLE 0x00004000
+
+#define ZX_ATTR_MONO 0x00000000
+#define ZX_ATTR_STEREO_LEFT 0x00001000
+#define ZX_ATTR_STEREO_RIGHT 0x00003000
+
+#define ZX_ATTR_WE_DISABLE 0x00000000
+#define ZX_ATTR_WE_ENABLE 0x00000800
+
+#define ZX_ATTR_FCE_DISABLE 0x00000000
+#define ZX_ATTR_FCE_ENABLE 0x00000400
+
+#define ZX_ATTR_RE_DISABLE 0x00000000
+#define ZX_ATTR_RE_ENABLE 0x00000200
+
+#define ZX_ATTR_GE_DISABLE 0x00000000
+#define ZX_ATTR_GE_ENABLE 0x00000100
+
+#define ZX_ATTR_BE_DISABLE 0x00000000
+#define ZX_ATTR_BE_ENABLE 0x00000080
+
+#define ZX_ATTR_RGBE_DISABLE 0x00000000
+#define ZX_ATTR_RGBE_ENABLE 0x00000380
+
+#define ZX_ATTR_OE_DISABLE 0x00000000
+#define ZX_ATTR_OE_ENABLE 0x00000040
+
+#define ZX_ATTR_ZE_DISABLE 0x00000000
+#define ZX_ATTR_ZE_ENABLE 0x00000020
+
+#define ZX_ATTR_FORCE_WID 0x00000010
+
+#define ZX_ATTR_FC_PLANE_MASK 0x0000000e
+
+#define ZX_ATTR_BUFFER_A 0x00000000
+#define ZX_ATTR_BUFFER_B 0x00000001
+
+/* CSR */
+#define ZX_CSR_BLT_BUSY 0x20000000
+
+struct zx_draw {
+ u_int32_t zd_pad0[896];
+ u_int32_t zd_csr;
+ u_int32_t zd_wid;
+ u_int32_t zd_wmask;
+ u_int32_t zd_widclip;
+ u_int32_t zd_vclipmin;
+ u_int32_t zd_vclipmax;
+ u_int32_t zd_pickmin; /* SS1 only */
+ u_int32_t zd_pickmax; /* SS1 only */
+ u_int32_t zd_fg;
+ u_int32_t zd_bg;
+ u_int32_t zd_src; /* Copy/Scroll (SS0 only) */
+ u_int32_t zd_dst; /* Copy/Scroll/Fill (SS0 only) */
+ u_int32_t zd_extent; /* Copy/Scroll/Fill size (SS0 only) */
+ u_int32_t zd_pad1[3];
+ u_int32_t zd_setsem; /* SS1 only */
+ u_int32_t zd_clrsem; /* SS1 only */
+ u_int32_t zd_clrpick; /* SS1 only */
+ u_int32_t zd_clrdat; /* SS1 only */
+ u_int32_t zd_alpha; /* SS1 only */
+ u_int32_t zd_pad2[11];
+ u_int32_t zd_winbg;
+ u_int32_t zd_planemask;
+ u_int32_t zd_rop;
+ u_int32_t zd_z;
+ u_int32_t zd_dczf; /* SS1 only */
+ u_int32_t zd_dczb; /* SS1 only */
+ u_int32_t zd_dcs; /* SS1 only */
+ u_int32_t zd_dczs; /* SS1 only */
+ u_int32_t zd_pickfb; /* SS1 only */
+ u_int32_t zd_pickbb; /* SS1 only */
+ u_int32_t zd_dcfc; /* SS1 only */
+ u_int32_t zd_forcecol; /* SS1 only */
+ u_int32_t zd_door[8]; /* SS1 only */
+ u_int32_t zd_pick[5]; /* SS1 only */
+};
+
+/* EXTENT */
+#define ZX_EXTENT_DIR_FORWARDS 0x00000000
+#define ZX_EXTENT_DIR_BACKWARDS 0x80000000
+
+struct zx_draw_ss1 {
+ u_int32_t zd_pad0[957];
+ u_int32_t zd_misc;
+};
+#define ZX_SS1_MISC_ENABLE 0x00000001
+#define ZX_SS1_MISC_STEREO 0x00000002
+
+#define ZX_ADDRSPC_OBGR 0x00
+#define ZX_ADDRSPC_Z 0x01
+#define ZX_ADDRSPC_W 0x02
+#define ZX_ADDRSPC_FONT_OBGR 0x04
+#define ZX_ADDRSPC_FONT_Z 0x05
+#define ZX_ADDRSPC_FONT_W 0x06
+#define ZX_ADDRSPC_O 0x08
+#define ZX_ADDRSPC_B 0x09
+#define ZX_ADDRSPC_G 0x0a
+#define ZX_ADDRSPC_R 0x0b
+
+struct zx_command {
+ u_int32_t zc_csr;
+ u_int32_t zc_addrspace;
+ u_int32_t zc_fontmsk;
+ u_int32_t zc_fontt;
+ u_int32_t zc_extent;
+ u_int32_t zc_src;
+ u_int32_t zc_dst;
+ u_int32_t zc_copy;
+ u_int32_t zc_fill;
+};
+
+#define ZX_CROSS_TYPE_CLUT0 0x00001000
+#define ZX_CROSS_TYPE_CLUT1 0x00001001
+#define ZX_CROSS_TYPE_CLUT2 0x00001002
+#define ZX_CROSS_TYPE_WID 0x00001003
+#define ZX_CROSS_TYPE_UNK 0x00001006
+#define ZX_CROSS_TYPE_VIDEO 0x00002003
+#define ZX_CROSS_TYPE_CLUTDATA 0x00004000
+
+#define ZX_CROSS_CSR_ENABLE 0x00000008
+#define ZX_CROSS_CSR_PROGRESS 0x00000004
+#define ZX_CROSS_CSR_UNK 0x00000002
+#define ZX_CROSS_CSR_UNK2 0x00000001
+
+struct zx_cross {
+ u_int32_t zx_type;
+ u_int32_t zx_csr;
+ u_int32_t zx_value;
+};
+
+struct zx_cursor {
+ u_int32_t zcu_pad0[4];
+ u_int32_t zcu_type;
+ u_int32_t zcu_misc;
+ u_int32_t zcu_sxy;
+ u_int32_t zcu_data;
+};
+
+#endif /* !_DEV_SBUS_ZXREG_H_ */