summaryrefslogtreecommitdiff
path: root/sys/arch/sgi/xbow
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-03-07 21:26:25 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-03-07 21:26:25 +0000
commit620991ed7c96f5cb2d5aba33e5780c9feae911d8 (patch)
treee33eb7e3e5e14a1383c9f42033684daa5b952db9 /sys/arch/sgi/xbow
parent6132f545a66994e896da7919ab654a3a371d2fcd (diff)
Minimalistic driver for the ImpactSR (Mardigras) video option found on older
Octane systems, as well as some Onyxes. With special permission to change a systemwide .h file and add a manpage from deraadt@ Magic numbers and operation sequencing borrowed from Linux; tested on Octane + ESI. ok deraadt@
Diffstat (limited to 'sys/arch/sgi/xbow')
-rw-r--r--sys/arch/sgi/xbow/files.xbow6
-rw-r--r--sys/arch/sgi/xbow/impact.c842
-rw-r--r--sys/arch/sgi/xbow/impactreg.h118
-rw-r--r--sys/arch/sgi/xbow/impactvar.h20
4 files changed, 985 insertions, 1 deletions
diff --git a/sys/arch/sgi/xbow/files.xbow b/sys/arch/sgi/xbow/files.xbow
index fb6d8d13590..1dc26b43539 100644
--- a/sys/arch/sgi/xbow/files.xbow
+++ b/sys/arch/sgi/xbow/files.xbow
@@ -1,4 +1,4 @@
-# $OpenBSD: files.xbow,v 1.6 2010/03/04 14:50:35 jsing Exp $
+# $OpenBSD: files.xbow,v 1.7 2010/03/07 21:26:24 miod Exp $
# IP30 and IP27 planar XBow bus
define xbow {[widget = -1], [vendor = -1], [product = -1]}
@@ -23,3 +23,7 @@ device odyssey: wsemuldisplaydev, rasops8, rasops16, rasops32
attach odyssey at xbow
file arch/sgi/xbow/odyssey.c odyssey needs-flag
+# ImpactSR graphics
+device impact: wsemuldisplaydev, rasops32
+attach impact at xbow
+file arch/sgi/xbow/impact.c impact needs-flag
diff --git a/sys/arch/sgi/xbow/impact.c b/sys/arch/sgi/xbow/impact.c
new file mode 100644
index 00000000000..24ff69ba322
--- /dev/null
+++ b/sys/arch/sgi/xbow/impact.c
@@ -0,0 +1,842 @@
+/* $OpenBSD: impact.c,v 1.1 2010/03/07 21:26:24 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for the SGI ImpactSR graphics board.
+ */
+
+/*
+ * The details regarding the design and operation of this hardware, along with
+ * the necessary magic numbers, are only available thanks to the reverse
+ * engineering work undertaken by Stanislaw Skowronek <skylark@linux-mips.org>.
+ */
+
+/*
+ * This driver currently lacks support for the HQ4 DMA engine, which could be
+ * used to speed up rasops `copy' operations a lot by doing framebuffer to
+ * memory, then memory to framebuffer operations.
+ *
+ * Of course, in an ideal world, these operations would be done with
+ * framebuffer to framebuffer operations, but according to Skowronek, these
+ * operations are not reliable and IRIX' Xsgi X server does not even try to
+ * use them.
+ *
+ * Thus this driver currently implements rasops `copy' operations by repainting
+ * affected areas with PIO routines. This is unfortunately slower than DMA,
+ * but this will work until I have more time to spend on this. -- miod
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+
+#include <machine/autoconf.h>
+
+#include <mips64/arcbios.h>
+
+#include <sgi/xbow/impactreg.h>
+#include <sgi/xbow/impactvar.h>
+#include <sgi/xbow/widget.h>
+#include <sgi/xbow/xbow.h>
+#include <sgi/xbow/xbowdevs.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+
+#define IMPACT_WIDTH 1280
+#define IMPACT_HEIGHT 1024
+#define IMPACT_DEPTH 32
+
+struct impact_screen;
+
+struct impact_softc {
+ struct device sc_dev;
+ struct impact_screen *curscr;
+ int console;
+ int nscreens;
+};
+
+int impact_match(struct device *, void *, void *);
+void impact_attach(struct device *, struct device *, void *);
+
+const struct cfattach impact_ca = {
+ sizeof(struct impact_softc), impact_match, impact_attach,
+};
+
+struct cfdriver impact_cd = {
+ NULL, "impact", DV_DULL,
+};
+
+struct impact_screen {
+ struct rasops_info ri;
+ long defattr;
+ struct wsdisplay_charcell *bs;
+
+ struct impact_softc *sc;
+
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+
+ struct wsscreen_descr wsd;
+ struct wsscreen_list wsl;
+ struct wsscreen_descr *scrlist[1];
+
+ struct mips_bus_space iot_store;
+};
+
+int impact_is_console(struct xbow_attach_args *);
+
+static inline void
+ impact_cmd_fifo_write(struct impact_screen *, uint64_t, uint32_t, int);
+int impact_cmd_fifo_wait(struct impact_screen *);
+
+void impact_setup(struct impact_screen *);
+int impact_init_screen(struct impact_screen *);
+
+/*
+ * Hardware acceleration (sort of) for rasops.
+ */
+void impact_rop(struct impact_screen *, int, int, int, int, int, u_int);
+void impact_fillrect(struct impact_screen *, int, int, int, int, u_int);
+int impact_do_cursor(struct rasops_info *);
+int impact_putchar(void *, int, int, u_int, long);
+int impact_copycols(void *, int, int, int, int);
+int impact_erasecols(void *, int, int, int, long);
+int impact_copyrows(void *, int, int, int);
+int impact_eraserows(void *, int, int, long);
+
+/*
+ * Interfaces for wscons.
+ */
+int impact_ioctl(void *, u_long, caddr_t, int, struct proc *);
+paddr_t impact_mmap(void *, off_t, int);
+int impact_alloc_screen(void *, const struct wsscreen_descr *, void **,
+ int *, int *, long *);
+void impact_free_screen(void *, void *);
+int impact_show_screen(void *, void *, int, void (*)(void *, int, int),
+ void *);
+
+static struct impact_screen impact_cons;
+
+struct wsdisplay_accessops impact_accessops = {
+ impact_ioctl,
+ impact_mmap,
+ impact_alloc_screen,
+ impact_free_screen,
+ impact_show_screen,
+ NULL, /* load_font */
+ NULL, /* scrollback */
+ NULL, /* getchar */
+ NULL, /* burner */
+ NULL /* pollc */
+};
+
+int
+impact_match(struct device *parent, void *match, void *aux)
+{
+ struct xbow_attach_args *xaa = aux;
+
+ if (xaa->xaa_vendor == XBOW_VENDOR_SGI5 &&
+ xaa->xaa_product == XBOW_PRODUCT_SGI5_IMPACT)
+ return 1;
+
+ return 0;
+}
+
+void
+impact_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct xbow_attach_args *xaa = aux;
+ struct wsemuldisplaydev_attach_args waa;
+ struct impact_softc *sc = (void *)self;
+ struct impact_screen *scr;
+
+ if (strncmp(bios_graphics, "alive", 5) != 0) {
+ printf(" device has not been setup by firmware!\n");
+ return;
+ }
+
+ printf(" revision %d\n", xaa->xaa_revision);
+
+ if (impact_is_console(xaa)) {
+ /*
+ * Setup has already been done via impact_cnattach().
+ */
+ scr = &impact_cons;
+ scr->sc = sc;
+ sc->curscr = scr;
+ sc->console = 1;
+ } else {
+ /*
+ * Setup screen data.
+ */
+ scr = malloc(sizeof(struct impact_screen), M_DEVBUF,
+ M_NOWAIT);
+ if (scr == NULL) {
+ printf("failed to allocate screen memory!\n");
+ return;
+ }
+
+ /*
+ * Create a copy of the bus space tag.
+ */
+ bcopy(xaa->xaa_iot, &scr->iot_store,
+ sizeof(struct mips_bus_space));
+ scr->iot = &scr->iot_store;
+
+ /* Setup bus space mappings. */
+ if (bus_space_map(scr->iot, IMPACTSR_REG_OFFSET,
+ IMPACTSR_REG_SIZE, 0, &scr->ioh)) {
+ printf("failed to map registers\n");
+ free(scr, M_DEVBUF);
+ return;
+ }
+
+ scr->sc = sc;
+ sc->curscr = scr;
+
+ /* Setup hardware and clear screen. */
+ impact_setup(scr);
+ if (impact_init_screen(scr) != 0) {
+ printf("failed to allocate memory\n");
+ bus_space_unmap(scr->iot, scr->ioh, IMPACTSR_REG_SIZE);
+ free(scr, M_DEVBUF);
+ return;
+ }
+ }
+
+ scr->scrlist[0] = &scr->wsd;
+ scr->wsl.nscreens = 1;
+ scr->wsl.screens = (const struct wsscreen_descr **)scr->scrlist;
+
+ waa.console = sc->console;
+ waa.scrdata = &scr->wsl;
+ waa.accessops = &impact_accessops;
+ waa.accesscookie = scr;
+ waa.defaultscreens = 0;
+
+ config_found(self, &waa, wsemuldisplaydevprint);
+}
+
+int
+impact_init_screen(struct impact_screen *scr)
+{
+ struct rasops_info *ri = &scr->ri;
+ size_t bssize;
+
+ bzero(ri, sizeof(struct rasops_info));
+
+ ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
+ ri->ri_depth = IMPACT_DEPTH;
+ ri->ri_width = IMPACT_WIDTH;
+ ri->ri_height = IMPACT_HEIGHT;
+ ri->ri_stride = IMPACT_WIDTH * IMPACT_DEPTH / 8;
+
+ rasops_init(ri, 160, 160);
+
+ /*
+ * Allocate backing store to remember character cells, to
+ * be able to fulfill scrolling requests.
+ */
+ if (scr->bs == NULL) {
+ bssize = ri->ri_rows * ri->ri_cols *
+ sizeof(struct wsdisplay_charcell);
+ scr->bs = malloc(bssize, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (scr->bs == NULL)
+ return ENOMEM;
+ }
+
+ ri->ri_hw = scr;
+
+ ri->ri_ops.putchar = impact_putchar;
+ ri->ri_do_cursor = impact_do_cursor;
+ ri->ri_ops.copyrows = impact_copyrows;
+ ri->ri_ops.copycols = impact_copycols;
+ ri->ri_ops.eraserows = impact_eraserows;
+ ri->ri_ops.erasecols = impact_erasecols;
+
+ /* clear display */
+ impact_fillrect(scr, 0, 0, ri->ri_width, ri->ri_height,
+ ri->ri_devcmap[WSCOL_BLACK]);
+
+ strlcpy(scr->wsd.name, "std", sizeof(scr->wsd.name));
+ scr->wsd.ncols = ri->ri_cols;
+ scr->wsd.nrows = ri->ri_rows;
+ scr->wsd.textops = &ri->ri_ops;
+ scr->wsd.fontwidth = ri->ri_font->fontwidth;
+ scr->wsd.fontheight = ri->ri_font->fontheight;
+ scr->wsd.capabilities = ri->ri_caps;
+
+ return 0;
+}
+
+/*
+ * Hardware initialization.
+ */
+
+void
+impact_setup(struct impact_screen *scr)
+{
+ /* HQ4 initialization */
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_CFIFO_HW, 0x00000047);
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_CFIFO_LW, 0x00000014);
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_CFIFO_DELAY, 0x00000064);
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_DFIFO_HW, 0x00000040);
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_DFIFO_LW, 0x00000010);
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_DFIFO_DELAY, 0x00000000);
+
+ /* VC3 initialization: disable hardware cursor */
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_VC3_INDEXDATA,
+ 0x1d000100);
+
+ /* RSS initialization */
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_COLORMASKLSBSA, 0xffffff, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_COLORMASKLSBSB, 0xffffff, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_COLORMASKMSBS, 0, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRMASKLO, 0xffffff, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRMASKHI, 0xffffff, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_DRBPOINTERS, 0xc8240, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_CONFIG, 0xcac, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XYWIN,
+ IMPACTSR_YXCOORDS(0, 0x3ff), 0);
+
+ /* XMAP initialization */
+ bus_space_write_1(scr->iot, scr->ioh, IMPACTSR_XMAP_PP1SELECT, 0x01);
+ bus_space_write_1(scr->iot, scr->ioh, IMPACTSR_XMAP_INDEX, 0x00);
+ bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_XMAP_MAIN_MODE,
+ 0x000007a4);
+}
+
+/*
+ * Write to the command FIFO.
+ */
+static inline void
+impact_cmd_fifo_write(struct impact_screen *scr, uint64_t reg, uint32_t val,
+ int exec)
+{
+ uint64_t cmd;
+
+ cmd = IMPACTSR_CFIFO_WRITE | (reg << IMPACTSR_CFIFO_REG_SHIFT);
+ if (exec)
+ cmd |= IMPACTSR_CFIFO_EXEC;
+ bus_space_write_8(scr->iot, scr->ioh, IMPACTSR_CFIFO, cmd | val);
+}
+
+/*
+ * Wait until the command FIFO is empty.
+ */
+int
+impact_cmd_fifo_wait(struct impact_screen *scr)
+{
+ u_int32_t val, timeout = 1000000;
+ struct impact_softc *sc = scr->sc;
+
+ val = bus_space_read_4(scr->iot, scr->ioh, IMPACTSR_FIFOSTATUS);
+ while ((val & IMPACTSR_FIFO_MASK) != 0) {
+ delay(1);
+ if (--timeout == 0) {
+#ifdef DIAGNOSTIC
+ if (sc != NULL && sc->console == 0)
+ printf("%s: timeout waiting for command fifo\n",
+ sc != NULL ? sc->sc_dev.dv_xname :
+ impact_cd.cd_name);
+#endif
+ return ETIMEDOUT;
+ }
+ val = bus_space_read_4(scr->iot, scr->ioh, IMPACTSR_FIFOSTATUS);
+ }
+
+ return 0;
+}
+
+/*
+ * Interfaces for wscons.
+ */
+
+int
+impact_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
+{
+ struct impact_screen *scr = (struct impact_screen *)v;
+ struct rasops_info *ri;
+ struct wsdisplay_fbinfo *fb;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(u_int *)data = WSDISPLAY_TYPE_WSDISPLAY_TYPE_IMPACT;
+ break;
+ case WSDISPLAYIO_GINFO:
+ fb = (struct wsdisplay_fbinfo *)data;
+ ri = &scr->ri;
+ fb->height = ri->ri_height;
+ fb->width = ri->ri_width;
+ fb->depth = ri->ri_depth;
+ fb->cmsize = 0;
+ break;
+#if 0
+ case WSDISPLAYIO_LINEBYTES:
+ ri = &scr->ri;
+ *(u_int *)data = ri->ri_stride;
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+paddr_t
+impact_mmap(void *v, off_t offset, int prot)
+{
+ if (offset < 0 || (offset & PAGE_MASK) != 0)
+ return -1;
+
+ return -1;
+}
+
+int
+impact_alloc_screen(void *v, const struct wsscreen_descr *type,
+ void **cookiep, int *curxp, int *curyp, long *attrp)
+{
+ struct impact_screen *scr = (struct impact_screen *)v;
+ struct rasops_info *ri = &scr->ri;
+ struct impact_softc *sc = (struct impact_softc *)scr->sc;
+
+ /* We do not allow multiple consoles at the moment. */
+ if (sc->nscreens > 0)
+ return ENOMEM;
+
+ sc->nscreens++;
+
+ *cookiep = ri;
+ *curxp = 0;
+ *curyp = 0;
+ ri->ri_ops.alloc_attr(ri, 0, 0, 0, &scr->defattr);
+ *attrp = scr->defattr;
+
+ return 0;
+}
+
+void
+impact_free_screen(void *v, void *cookie)
+{
+ /* We do not allow multiple consoles at the moment. */
+}
+
+int
+impact_show_screen(void *v, void *cookie, int waitok,
+ void (*cb)(void *, int, int), void *cbarg)
+{
+ /* We do not allow multiple consoles at the moment. */
+ return 0;
+}
+
+/*
+ * Hardware accelerated functions.
+ */
+
+void
+impact_rop(struct impact_screen *scr, int x, int y, int w, int h, int op,
+ u_int c)
+{
+ impact_cmd_fifo_wait(scr);
+ if (op == OPENGL_LOGIC_OP_COPY)
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE,
+ IMPACTSR_PP1FILLMODE(0x6300, op), 0);
+ else
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE,
+ IMPACTSR_PP1FILLMODE(0x6304, op), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_FILLMODE, 0, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_PACKEDCOLOR, c & 0x00ffffff, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYSTARTI,
+ IMPACTSR_XYCOORDS(x, y), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYENDI,
+ IMPACTSR_XYCOORDS(x + w - 1, y + h - 1), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_IR_ALIAS, 0x18, 1);
+}
+
+void
+impact_fillrect(struct impact_screen *scr, int x, int y, int w, int h, u_int c)
+{
+ impact_rop(scr, x, y, w, h, OPENGL_LOGIC_OP_COPY, c);
+}
+
+int
+impact_do_cursor(struct rasops_info *ri)
+{
+ struct impact_screen *scr = ri->ri_hw;
+ int y, x, w, h, fg, bg;
+
+ w = ri->ri_font->fontwidth;
+ h = ri->ri_font->fontheight;
+ x = ri->ri_xorigin + ri->ri_ccol * w;
+ y = ri->ri_yorigin + ri->ri_crow * h;
+
+ ri->ri_ops.unpack_attr(ri, scr->defattr, &fg, &bg, NULL);
+
+ impact_rop(scr, x, y, w, h, OPENGL_LOGIC_OP_XOR, ri->ri_devcmap[fg]);
+ impact_cmd_fifo_wait(scr);
+
+ return 0;
+}
+
+int
+impact_putchar(void *cookie, int row, int col, u_int uc, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct impact_screen *scr = ri->ri_hw;
+ struct wsdisplay_font *font = ri->ri_font;
+ int x, y, w, h, bg, fg, ul;
+ u_int8_t *fontbitmap;
+ u_int chunk;
+ struct wsdisplay_charcell *cell;
+
+ /* Update backing store. */
+ cell = scr->bs + row * ri->ri_cols + col;
+ cell->uc = uc;
+ cell->attr = attr;
+
+ w = font->fontwidth;
+ h = font->fontheight;
+ x = ri->ri_xorigin + col * w;
+ y = ri->ri_yorigin + row * h;
+
+ ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul);
+
+ /* Handle spaces with a single fillrect. */
+ if ((uc == ' ' || uc == 0) && ul == 0) {
+ impact_fillrect(scr, x, y, w, h, ri->ri_devcmap[bg]);
+ return 0;
+ }
+
+ fontbitmap = (u_int8_t *)(font->data + (uc - font->firstchar) *
+ ri->ri_fontscale);
+
+ impact_cmd_fifo_wait(scr);
+ if (ri->ri_devcmap[bg] == 0) {
+ /*
+ * 1bpp pixel expansion; fast but background color ends up
+ * being incorrect (white renders as light green, and other
+ * colors end up slightly more greenish), which is why it is
+ * only done for black background.
+ */
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE,
+ IMPACTSR_PP1FILLMODE(0x6300, OPENGL_LOGIC_OP_COPY), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_FILLMODE,
+ 0x00400018, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_PACKEDCOLOR,
+ ri->ri_devcmap[fg], 0);
+#if 0
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BKGRD_RG,
+ (ri->ri_devcmap[bg] & 0x0000ffff) << 8, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BKGRD_BA,
+ (ri->ri_devcmap[bg] & 0x00ff0000) >> 8, 0);
+#else
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BKGRD_RG, 0, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BKGRD_BA, 0, 0);
+#endif
+
+ if (w <= 8) {
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYSTARTI,
+ IMPACTSR_XYCOORDS(x, y), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYENDI,
+ IMPACTSR_XYCOORDS(x + w - 1, y + h - 1), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_IR_ALIAS,
+ 0x18, 1);
+
+ for (; h != 0; h--) {
+ chunk = *fontbitmap;
+ fontbitmap += font->stride;
+
+ /* Handle underline. */
+ if (ul && h == 1)
+ chunk = 0xff;
+
+ impact_cmd_fifo_wait(scr);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_H,
+ chunk << 24, 1);
+ }
+ } else {
+ for (; h != 0; h--) {
+ chunk = *(u_int16_t *)fontbitmap;
+ fontbitmap += font->stride;
+
+ /* Handle underline. */
+ if (ul && h == 1)
+ chunk = 0xffff;
+
+ impact_cmd_fifo_write(scr,
+ IMPACTSR_CMD_BLOCKXYSTARTI,
+ IMPACTSR_XYCOORDS(x, y), 0);
+ impact_cmd_fifo_write(scr,
+ IMPACTSR_CMD_BLOCKXYENDI,
+ IMPACTSR_XYCOORDS(x + w - 1, y + 1 - 1), 0);
+ impact_cmd_fifo_write(scr,
+ IMPACTSR_CMD_IR_ALIAS, 0x18, 1);
+
+ impact_cmd_fifo_wait(scr);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_H,
+ chunk << 16, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_L,
+ chunk << 24, 1);
+
+ y++;
+ }
+ }
+ } else {
+ uint mask;
+ uint32_t data;
+ int i, flip;
+
+ /* slower 8bpp blt; hopefully gives us the correct colors */
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE,
+ IMPACTSR_PP1FILLMODE(0x6300, OPENGL_LOGIC_OP_COPY), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYSTARTI,
+ IMPACTSR_XYCOORDS(x, y), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYENDI,
+ IMPACTSR_XYCOORDS(x + w - 1, y + h - 1), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_FILLMODE,
+ 0x00c00000, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRMODE, 0x0080, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRSIZE,
+ IMPACTSR_YXCOORDS(w, h), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRCOUNTERS,
+ IMPACTSR_YXCOORDS(w, h), 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_GLINE_XSTARTF, 1, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_IR_ALIAS, 0x18, 1);
+ for (i = 0; i < 32 + 1; i++)
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_ALPHA, 0, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRCONTROL, 2, 0);
+
+ flip = 0;
+ for (; h != 0; h--) {
+ if (w > 8)
+ chunk = *(u_int16_t *)fontbitmap;
+ else
+ chunk = *fontbitmap;
+ fontbitmap += font->stride;
+
+ /* Handle underline. */
+ if (ul && h == 1)
+ chunk = 0xffff;
+
+ /* font data is packed towards most significant bit */
+ mask = w > 8 ? 0x8000 : 0x80;
+ for (i = w; i != 0; i--, mask >>= 1) {
+ data = ri->ri_devcmap[(chunk & mask) ? fg : bg];
+ impact_cmd_fifo_write(scr, flip ?
+ IMPACTSR_CMD_CHAR_L : IMPACTSR_CMD_CHAR_H,
+ data, flip);
+ flip ^= 1;
+ }
+ if (flip)
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_L,
+ 0, 1);
+ }
+
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_GLINE_XSTARTF, 0, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_RE_TOGGLECNTX, 0, 0);
+ impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRCOUNTERS,
+ IMPACTSR_YXCOORDS(0, 0), 0);
+ }
+
+ return 0;
+}
+
+int
+impact_copycols(void *cookie, int row, int src, int dst, int num)
+{
+ struct rasops_info *ri = cookie;
+ struct impact_screen *scr = ri->ri_hw;
+ struct wsdisplay_charcell *cell;
+
+ /* Copy columns in backing store. */
+ cell = scr->bs + row * ri->ri_cols;
+ ovbcopy(cell + src, cell + dst,
+ num * sizeof(struct wsdisplay_charcell));
+
+ /* Repaint affected area */
+ cell += dst;
+ for (; num != 0; num--, dst++, cell++)
+ impact_putchar(cookie, row, dst, cell->uc, cell->attr);
+
+ return 0;
+}
+
+int
+impact_erasecols(void *cookie, int row, int col, int num, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct impact_screen *scr = ri->ri_hw;
+ int bg, fg, i;
+ struct wsdisplay_charcell *cell;
+
+ /* Erase columns in backing store. */
+ cell = scr->bs + row * ri->ri_cols + col;
+ for (i = num; i != 0; i--, cell++) {
+ cell->uc = 0;
+ cell->attr = attr;
+ }
+
+ ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
+
+ row *= ri->ri_font->fontheight;
+ col *= ri->ri_font->fontwidth;
+ num *= ri->ri_font->fontwidth;
+
+ impact_fillrect(scr, ri->ri_xorigin + col, ri->ri_yorigin + row,
+ num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
+
+ return 0;
+}
+
+int
+impact_copyrows(void *cookie, int src, int dst, int num)
+{
+ struct rasops_info *ri = cookie;
+ struct impact_screen *scr = ri->ri_hw;
+ struct wsdisplay_charcell *cell;
+ int col;
+
+ /* Copy rows in backing store. */
+ cell = scr->bs + dst * ri->ri_cols;
+ ovbcopy(scr->bs + src * ri->ri_cols, cell,
+ num * ri->ri_cols * sizeof(struct wsdisplay_charcell));
+
+ /* Repaint affected area */
+ for (; num != 0; num--, dst++) {
+ for (col = 0; col < ri->ri_cols; col++, cell++)
+ impact_putchar(cookie, dst, col, cell->uc, cell->attr);
+ }
+
+ return 0;
+}
+
+int
+impact_eraserows(void *cookie, int row, int num, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct impact_screen *scr = ri->ri_hw;
+ int x, y, w, bg, fg;
+ struct wsdisplay_charcell *cell;
+
+ /* Erase rows in backing store. */
+ cell = scr->bs + row * ri->ri_cols;
+ for (x = ri->ri_cols; x != 0; x--, cell++) {
+ cell->uc = 0;
+ cell->attr = attr;
+ }
+ for (y = 1; y < num; y++)
+ ovbcopy(scr->bs + row * ri->ri_cols,
+ scr->bs + (row + y) * ri->ri_cols,
+ ri->ri_cols * sizeof(struct wsdisplay_charcell));
+
+ ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
+
+ if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
+ num = ri->ri_height;
+ x = y = 0;
+ w = ri->ri_width;
+ } else {
+ num *= ri->ri_font->fontheight;
+ x = ri->ri_xorigin;
+ y = ri->ri_yorigin + row * ri->ri_font->fontheight;
+ w = ri->ri_emuwidth;
+ }
+
+ impact_fillrect(scr, x, y, w, num, ri->ri_devcmap[bg]);
+ impact_cmd_fifo_wait(scr);
+
+ return 0;
+}
+
+/*
+ * Console support.
+ */
+
+static int16_t impact_console_nasid;
+static int impact_console_widget;
+
+/* console backing store, worst case font selection */
+static struct wsdisplay_charcell
+ impact_cons_bs[(IMPACT_WIDTH / 8) * (IMPACT_HEIGHT / 16)];
+
+int
+impact_cnprobe(int16_t nasid, int widget)
+{
+ u_int32_t wid, vendor, product;
+
+ if (xbow_widget_id(nasid, widget, &wid) != 0)
+ return 0;
+
+ vendor = (wid & WIDGET_ID_VENDOR_MASK) >> WIDGET_ID_VENDOR_SHIFT;
+ product = (wid & WIDGET_ID_PRODUCT_MASK) >> WIDGET_ID_PRODUCT_SHIFT;
+
+ if (vendor != XBOW_VENDOR_SGI5 || product != XBOW_PRODUCT_SGI5_IMPACT)
+ return 0;
+
+ if (strncmp(bios_graphics, "alive", 5) != 0)
+ return 0;
+
+ return 1;
+}
+
+int
+impact_cnattach(int16_t nasid, int widget)
+{
+ struct impact_screen *scr = &impact_cons;
+ struct rasops_info *ri = &scr->ri;
+ int rc;
+
+ /* Build bus space accessor. */
+ xbow_build_bus_space(&scr->iot_store, nasid, widget);
+ scr->iot = &scr->iot_store;
+
+ rc = bus_space_map(scr->iot, IMPACTSR_REG_OFFSET, IMPACTSR_REG_SIZE,
+ 0, &scr->ioh);
+ if (rc != 0)
+ return rc;
+
+ impact_setup(scr);
+ scr->bs = impact_cons_bs;
+ rc = impact_init_screen(scr);
+ if (rc != 0) {
+ bus_space_unmap(scr->iot, scr->ioh, IMPACTSR_REG_SIZE);
+ return rc;
+ }
+
+ ri->ri_ops.alloc_attr(ri, 0, 0, 0, &scr->defattr);
+ wsdisplay_cnattach(&scr->wsd, ri, 0, 0, scr->defattr);
+
+ impact_console_nasid = nasid;
+ impact_console_widget = widget;
+
+ return 0;
+}
+
+int
+impact_is_console(struct xbow_attach_args *xaa)
+{
+ return xaa->xaa_nasid == impact_console_nasid &&
+ xaa->xaa_widget == impact_console_widget;
+}
diff --git a/sys/arch/sgi/xbow/impactreg.h b/sys/arch/sgi/xbow/impactreg.h
new file mode 100644
index 00000000000..ad9cb4df0dd
--- /dev/null
+++ b/sys/arch/sgi/xbow/impactreg.h
@@ -0,0 +1,118 @@
+/* $OpenBSD: impactreg.h,v 1.1 2010/03/07 21:26:24 miod Exp $ */
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * ImpactSR registers
+ */
+
+#define IMPACTSR_REG_OFFSET 0x00000000
+#define IMPACTSR_REG_SIZE 0x00200000
+
+#define IMPACTSR_STATUS 0x020000
+#define IMPACTSR_FIFOSTATUS 0x020008
+#define IMPACTSR_FIFO_MASK 0x000000ff
+#define IMPACTSR_GIOSTATUS 0x020100
+#define IMPACTSR_DMABUSY 0x020200
+#define IMPACTSR_CFIFO 0x020400
+
+#define IMPACTSR_CFIFO_HW 0x040000
+#define IMPACTSR_CFIFO_LW 0x040008
+#define IMPACTSR_CFIFO_DELAY 0x040010
+#define IMPACTSR_DFIFO_HW 0x040020
+#define IMPACTSR_DFIFO_LW 0x040028
+#define IMPACTSR_DFIFO_DELAY 0x040030
+
+#define IMPACTSR_XMAP_PP1SELECT 0x071c08
+#define IMPACTSR_XMAP_INDEX 0x071c88
+#define IMPACTSR_XMAP_CONFIG 0x071d00
+#define IMPACTSR_XMAP_CONFIGB 0x071d08
+#define IMPACTSR_XMAP_BUF_SELECT 0x071d80
+#define IMPACTSR_XMAP_MAIN_MODE 0x071e00
+#define IMPACTSR_XMAP_OVERLAY_MODE 0x071e80
+#define IMPACTSR_XMAP_DIB 0x071f00
+#define IMPACTSR_XMAP_DIB_DW 0x071f40
+#define IMPACTSR_XMAP_RE_RAC 0x071f80
+
+#define IMPACTSR_VC3_INDEX 0x072008
+#define IMPACTSR_VC3_INDEXDATA 0x072038
+#define IMPACTSR_VC3_DATA 0x0720b0
+#define IMPACTSR_VC3_RAM 0x072190
+
+/*
+ * Command FIFO instruction encoding
+ */
+
+#define IMPACTSR_CFIFO_WRITE 0x0018000400000000UL
+#define IMPACTSR_CFIFO_EXEC 0x0004000000000000UL
+#define IMPACTSR_CFIFO_REG_SHIFT 40
+
+/*
+ * Command FIFO registers
+ */
+
+#define IMPACTSR_CMD_GLINE_XSTARTF 0x0c
+#define IMPACTSR_CMD_IR_ALIAS 0x45
+#define IMPACTSR_CMD_BLOCKXYSTARTI 0x46 /* XY coords */
+#define IMPACTSR_CMD_BLOCKXYENDI 0x47 /* XY coords */
+#define IMPACTSR_CMD_PACKEDCOLOR 0x5b
+#define IMPACTSR_CMD_ALPHA 0x5f
+#define IMPACTSR_CMD_CHAR_H 0x70
+#define IMPACTSR_CMD_CHAR_L 0x71
+#define IMPACTSR_CMD_XFRCONTROL 0x102
+#define IMPACTSR_CMD_FILLMODE 0x110
+#define IMPACTSR_CMD_CONFIG 0x112
+#define IMPACTSR_CMD_XYWIN 0x115 /* YX coords */
+#define IMPACTSR_CMD_BKGRD_RG 0x140
+#define IMPACTSR_CMD_BKGRD_BA 0x141
+#define IMPACTSR_CMD_XFRSIZE 0x153 /* YX coords */
+#define IMPACTSR_CMD_XFRMASKLO 0x156
+#define IMPACTSR_CMD_XFRMASKHI 0x157
+#define IMPACTSR_CMD_XFRCOUNTERS 0x158 /* YX coords */
+#define IMPACTSR_CMD_XFRMODE 0x159
+#define IMPACTSR_CMD_RE_TOGGLECNTX 0x15f
+#define IMPACTSR_CMD_PP1FILLMODE 0x161
+#define IMPACTSR_CMD_COLORMASKMSBS 0x162
+#define IMPACTSR_CMD_COLORMASKLSBSA 0x163
+#define IMPACTSR_CMD_COLORMASKLSBSB 0x164
+#define IMPACTSR_CMD_DRBPOINTERS 0x16d
+
+#define IMPACTSR_XYCOORDS(x,y) (((x) << 16) | (y))
+#define IMPACTSR_YXCOORDS(x,y) (((y) << 16) | (x))
+
+#define IMPACTSR_PP1FILLMODE(mode,op) ((mode) | ((op) << 26))
+
+/*
+ * Logic Operations
+ */
+
+#define OPENGL_LOGIC_OP_CLEAR 0
+#define OPENGL_LOGIC_OP_AND 1
+#define OPENGL_LOGIC_OP_AND_REVERSE 2
+#define OPENGL_LOGIC_OP_COPY 3
+#define OPENGL_LOGIC_OP_AND_INVERTED 4
+#define OPENGL_LOGIC_OP_NOOP 5
+#define OPENGL_LOGIC_OP_XOR 6
+#define OPENGL_LOGIC_OP_OR 7
+#define OPENGL_LOGIC_OP_NOR 8
+#define OPENGL_LOGIC_OP_EQUIV 9
+#define OPENGL_LOGIC_OP_INVERT 10
+#define OPENGL_LOGIC_OP_OR_REVERSE 11
+#define OPENGL_LOGIC_OP_COPY_INVERTED 12
+#define OPENGL_LOGIC_OP_OR_INVERTED 13
+#define OPENGL_LOGIC_OP_NAND 14
+#define OPENGL_LOGIC_OP_SET 15
diff --git a/sys/arch/sgi/xbow/impactvar.h b/sys/arch/sgi/xbow/impactvar.h
new file mode 100644
index 00000000000..59acddc3d39
--- /dev/null
+++ b/sys/arch/sgi/xbow/impactvar.h
@@ -0,0 +1,20 @@
+/* $OpenBSD: impactvar.h,v 1.1 2010/03/07 21:26:24 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+int impact_cnprobe(int16_t, int);
+int impact_cnattach(int16_t, int);