summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/vax/conf/GENERIC17
-rw-r--r--sys/arch/vax/conf/RAMDISK15
-rw-r--r--sys/arch/vax/conf/files.vax6
-rw-r--r--sys/arch/vax/dec/files.dec6
-rw-r--r--sys/arch/vax/dec/sii.c1798
-rw-r--r--sys/arch/vax/dec/siireg.h235
-rw-r--r--sys/arch/vax/dec/siivar.h71
-rw-r--r--sys/arch/vax/include/clock.h5
-rw-r--r--sys/arch/vax/include/nexus.h3
-rw-r--r--sys/arch/vax/include/rpb.h3
-rw-r--r--sys/arch/vax/include/scb.h11
-rw-r--r--sys/arch/vax/mbus/dz_fwio.c215
-rw-r--r--sys/arch/vax/mbus/files.mbus29
-rw-r--r--sys/arch/vax/mbus/fwio.c111
-rw-r--r--sys/arch/vax/mbus/fwioreg.h45
-rw-r--r--sys/arch/vax/mbus/fwiovar.h28
-rw-r--r--sys/arch/vax/mbus/if_le_fwio.c272
-rw-r--r--sys/arch/vax/mbus/mbus.c441
-rw-r--r--sys/arch/vax/mbus/mbusreg.h251
-rw-r--r--sys/arch/vax/mbus/mbusvar.h33
-rw-r--r--sys/arch/vax/mbus/sii_fwio.c163
-rw-r--r--sys/arch/vax/mbus/uba_mbus.c174
-rw-r--r--sys/arch/vax/uba/ubareg.h6
-rw-r--r--sys/arch/vax/vax/autoconf.c27
-rw-r--r--sys/arch/vax/vax/clock.c5
-rw-r--r--sys/arch/vax/vax/conf.c4
-rw-r--r--sys/arch/vax/vax/findcpu.c7
-rw-r--r--sys/arch/vax/vax/ka60.c358
-rw-r--r--sys/arch/vax/vax/locore.c40
-rw-r--r--sys/arch/vax/vax/machdep.c18
-rw-r--r--sys/arch/vax/vax/pmap.c11
-rw-r--r--sys/arch/vax/vax/scb.c6
-rw-r--r--sys/arch/vax/vax/vm_machdep.c6
33 files changed, 4360 insertions, 60 deletions
diff --git a/sys/arch/vax/conf/GENERIC b/sys/arch/vax/conf/GENERIC
index 67c30fa724b..aed634833eb 100644
--- a/sys/arch/vax/conf/GENERIC
+++ b/sys/arch/vax/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.48 2006/11/06 20:28:20 miod Exp $
+# $OpenBSD: GENERIC,v 1.49 2008/08/18 23:19:21 miod Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -30,6 +30,7 @@ option VAX46 # VS 4000/60
option VAX48 # VS 4000 VLC
option VAX49 # VS 4000/90
option VAX53 # VAX 4000 10X, MicroVAX 3100m9X
+option VAX60 # VS 3[58][24]0
option VXT # VXT2000 and VXT2000+
# Old compat stuff; needed to run 4.3BSD Reno programs.
@@ -50,10 +51,11 @@ mainbus0 at root
#sbi0 at mainbus0 # SBI, master bus on 11/780.
#cmi0 at mainbus0 # 11/750 internal bus.
#bi0 at mainbus0 # VAX 8200
-vsbus0 at mainbus0 # All VAXstations
+vsbus0 at mainbus0 # All VAXstations but 3[58][24]0
ibus0 at mainbus0 # All Microvax
#nbi0 at mainbus0 # VAX 8800
#xmi0 at mainbus0 # VAX 6000
+mbus0 at mainbus0 # VS 3[58][24]0
vxtbus0 at mainbus0 # VXT2000
# Vsbus, the virtual VAXstation bus, and possible devices.
@@ -80,6 +82,16 @@ ze0 at ibus0 # SGEC on-board ethernet
le0 at ibus0 # LANCE ethernet (MV3400)
#shac0 at ibus0 # DSSI controller
+# M-bus found on VS 3[58][24]0
+fwio* at mbus0 mid ? # I/O module
+uba0 at mbus0 mid 0
+
+dz0 at fwio? # DZ-11 like serial ports
+dz* at fwio? # DZ-11 (on additional fwio)
+le0 at fwio? # LANCE ethernet
+le* at fwio? # LANCE (on additional fwio)
+sii* at fwio? # SII SCSI
+
# VXT2000 devices
ze0 at vxtbus0 # SGEC on-board ethernet
qsc0 at vxtbus0 # serial ports
@@ -133,6 +145,7 @@ mt* at mscpbus? drive? # MSCP tape
# SCSI devices
scsibus* at asc?
scsibus* at ncr?
+scsibus* at sii?
sd* at scsibus?
st* at scsibus?
diff --git a/sys/arch/vax/conf/RAMDISK b/sys/arch/vax/conf/RAMDISK
index bffd1545fef..ec7e7f96b5d 100644
--- a/sys/arch/vax/conf/RAMDISK
+++ b/sys/arch/vax/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.29 2008/06/08 20:37:39 deraadt Exp $
+# $OpenBSD: RAMDISK,v 1.30 2008/08/18 23:19:21 miod Exp $
machine vax # machine type
@@ -22,6 +22,7 @@ option VAX46 # VS 4000/60
option VAX48 # VS 4000 VLC
option VAX49 # VS 4000/90
option VAX53 # VAX 4000/10{0,5,6}
+option VAX60 # VS 3[58][24]0
option VXT # VXT2000 and VXT2000+
maxusers 8 # estimated number of users
@@ -61,6 +62,7 @@ vsbus0 at mainbus0 # All VAXstations
ibus0 at mainbus0 # All Microvax
#nbi0 at mainbus0 # VAX 8800
#xmi0 at mainbus0 # VAX 6000
+mbus0 at mainbus0 # VS 3[58][24]0
vxtbus0 at mainbus0 # VXT2000
# Vsbus, the virtual VAXstation bus, and possible devices.
@@ -87,6 +89,16 @@ ze0 at ibus0 # SGEC on-board ethernet
le0 at ibus0 # LANCE ethernet
#shac0 at ibus0 # DSSI controller
+# M-bus found on VS 3[58][24]0
+fwio* at mbus0 mid ? # I/O module
+uba0 at mbus0 mid 0
+
+dz0 at fwio? # DZ-11 like serial ports
+dz* at fwio? # DZ-11 (on additional fwio)
+le0 at fwio? # LANCE ethernet
+le* at fwio? # LANCE (on additional fwio)
+sii* at fwio? # SII SCSI
+
# VXT2000 devices
ze0 at vxtbus0 # SGEC on-board ethernet
qsc0 at vxtbus0 # serial ports
@@ -140,6 +152,7 @@ mt* at mscpbus? drive? # MSCP tape
# SCSI devices
scsibus* at asc?
scsibus* at ncr?
+scsibus* at sii?
sd* at scsibus?
st* at scsibus?
diff --git a/sys/arch/vax/conf/files.vax b/sys/arch/vax/conf/files.vax
index 11ae4b2987d..0c34f42ef43 100644
--- a/sys/arch/vax/conf/files.vax
+++ b/sys/arch/vax/conf/files.vax
@@ -1,4 +1,4 @@
-# $OpenBSD: files.vax,v 1.47 2008/08/18 23:07:22 miod Exp $
+# $OpenBSD: files.vax,v 1.48 2008/08/18 23:19:21 miod Exp $
# $NetBSD: files.vax,v 1.60 1999/08/27 20:04:32 ragge Exp $
#
# new style config file for vax architecture
@@ -340,6 +340,9 @@ device dh # XXX?
attach dh at uba
file arch/vax/uba/dh.c dh needs-flag
+# M-bus on VS 3[58][24]0
+include "arch/vax/mbus/files.mbus"
+
# Blinkenlichten
device led
attach led at mainbus
@@ -362,6 +365,7 @@ file arch/vax/vax/ka46.c vax46
file arch/vax/vax/ka48.c vax48
file arch/vax/vax/ka49.c vax49
file arch/vax/vax/ka53.c vax53
+file arch/vax/vax/ka60.c vax60
file arch/vax/vax/emulate.s insn_emulate
file arch/vax/vax/unimpl_emul.s insn_emulate
file arch/vax/vax/ka650.c vax650
diff --git a/sys/arch/vax/dec/files.dec b/sys/arch/vax/dec/files.dec
index fe2848d1163..1f81a9f177a 100644
--- a/sys/arch/vax/dec/files.dec
+++ b/sys/arch/vax/dec/files.dec
@@ -1,4 +1,4 @@
-# $OpenBSD: files.dec,v 1.5 2008/08/18 23:04:28 miod Exp $
+# $OpenBSD: files.dec,v 1.6 2008/08/18 23:19:22 miod Exp $
# $NetBSD: files.dec,v 1.4 1999/08/04 07:17:51 nisimura Exp $
#
# Config file and device description for machine-independent
@@ -14,3 +14,7 @@ file arch/vax/dec/wskbdmap_lk201.c lkkbd
# VSxxx mouse
file arch/vax/dec/vsms_ws.c lkms
+
+# DC7061 SII DSSI/SCSI controller
+device sii: scsi
+file arch/vax/dec/sii.c sii
diff --git a/sys/arch/vax/dec/sii.c b/sys/arch/vax/dec/sii.c
new file mode 100644
index 00000000000..0a677fa557e
--- /dev/null
+++ b/sys/arch/vax/dec/sii.c
@@ -0,0 +1,1798 @@
+/* $OpenBSD: sii.c,v 1.1 2008/08/18 23:19:22 miod Exp $ */
+/* $NetBSD: sii.c,v 1.42 2000/06/02 20:20:29 mhitch Exp $ */
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)sii.c 8.2 (Berkeley) 11/30/93
+ *
+ * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devSII.c,
+ * v 9.2 89/09/14 13:37:41 jhh Exp $ SPRITE (DECWRL)";
+ */
+
+/*
+ * SCSI interface driver
+ */
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_message.h>
+#ifdef DEBUG
+#include <scsi/scsi_disk.h>
+#endif
+
+#include <vax/dec/siireg.h> /* device registers */
+#include <vax/dec/siivar.h> /* softc and prototypes */
+
+/* XXX not in scsi/scsi_message.h */
+#define MSG_EXT_MODIFY_DATA_PTR 0x00
+
+struct cfdriver sii_cd = {
+ NULL, "sii", DV_DULL
+};
+
+/*
+ * MACROS for timing out spin loops.
+ *
+ * Wait until expression is true.
+ *
+ * Control register bits can change at any time so when the CPU
+ * reads a register, the bits might change and
+ * invalidate the setup and hold times for the CPU.
+ * This macro reads the register twice to be sure the value is stable.
+ *
+ * args: var - variable to save control register contents
+ * reg - control register to read
+ * expr - expression to spin on
+ * spincount - maximum number of times through the loop
+ * cntr - variable for number of tries
+ */
+#define SII_WAIT_UNTIL(var, reg, expr, spincount, cntr) { \
+ u_int tmp = reg; \
+ for (cntr = 0; cntr < spincount; cntr++) { \
+ while (tmp != (var = reg)) \
+ tmp = var; \
+ if (expr) \
+ break; \
+ if (cntr >= 100) \
+ DELAY(100); \
+ } \
+ }
+
+#ifdef DEBUG
+int sii_debug = 1;
+int sii_debug_cmd;
+int sii_debug_bn;
+int sii_debug_sz;
+#define NLOG 16
+struct sii_log {
+ u_short cstat;
+ u_short dstat;
+ u_short comm;
+ u_short msg;
+ int rlen;
+ int dlen;
+ int target;
+} sii_log[NLOG], *sii_logp = sii_log;
+#endif
+
+#define NORESET 0
+#define RESET 1
+#define NOWAIT 0
+#define WAIT 1
+
+#if 0
+/*
+ * XXX That hardcoded 7 below implies SII_NCMD <= 7, which is not the case...
+ * XXX Thankfully all uses of SII_BUF_ADDR are in #if 0 sections (and this
+ * XXX should be reasonably safe as long as we use 7 as the host id).
+ */
+/*
+ * Define a safe address in the SCSI buffer for doing status & message DMA
+ * XXX why not add another field to softc?
+ */
+#define SII_BUF_ADDR(sc) (SII_MAX_DMA_XFER_LENGTH * 7 * 2)
+#endif
+
+/*
+ * Forward references
+ */
+
+void sii_Reset(struct sii_softc *sc, int resetbus);
+void sii_StartCmd(struct sii_softc *sc, int target);
+void sii_CmdDone(struct sii_softc *sc, int target, int error);
+void sii_DoIntr(struct sii_softc *sc, u_int dstat);
+void sii_StateChg(struct sii_softc *sc, u_int cstat);
+int sii_GetByte(SIIRegs *regs, int phase, int ack);
+void sii_DoSync(struct sii_softc *, State *);
+void sii_StartDMA(SIIRegs *regs, int phase, u_int dmaAddr, int size);
+int sii_scsi_cmd(struct scsi_xfer *);
+#ifdef DEBUG
+void sii_DumpLog(void);
+#endif
+
+struct scsi_adapter sii_scsiswitch = {
+ sii_scsi_cmd,
+ minphys,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct scsi_device sii_scsidev = {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+void
+sii_attach(sc)
+ struct sii_softc *sc;
+{
+ struct scsibus_attach_args saa;
+ int i;
+
+ sc->sc_target = -1; /* no command active */
+
+ /*
+ * Give each target its own DMA buffer region.
+ * Make it big enough for 2 max transfers so we can ping pong buffers
+ * while we copy the data.
+ */
+ for (i = 0; i < SII_NCMD; i++) {
+ sc->sc_st[i].dmaAddr[0] =
+ SII_MAX_DMA_XFER_LENGTH * 2 * i;
+ sc->sc_st[i].dmaAddr[1] = sc->sc_st[i].dmaAddr[0] +
+ SII_MAX_DMA_XFER_LENGTH;
+ }
+
+ sii_Reset(sc, RESET);
+ printf("\n");
+
+ /*
+ * fill in the prototype scsi_link.
+ */
+ sc->sc_link.adapter = &sii_scsiswitch;
+ sc->sc_link.adapter_buswidth = 8;
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_regs->id & SII_IDMSK;
+ sc->sc_link.device = &sii_scsidev;
+ sc->sc_link.openings = 1; /* driver can't queue requests yet */
+
+ /*
+ * Now try to attach all the sub-devices
+ */
+ bzero(&saa, sizeof(saa));
+ saa.saa_sc_link = &sc->sc_link;
+ config_found(&sc->sc_dev, &saa, scsiprint);
+}
+
+/*
+ * Start activity on a SCSI device.
+ * We maintain information on each device separately since devices can
+ * connect/disconnect during an operation.
+ */
+
+int
+sii_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ int target = xs->sc_link->target;
+ struct sii_softc *sc = xs->sc_link->adapter_softc;
+ int s;
+ int count;
+
+ s = splbio();
+ if (sc->sc_cmd[target]) {
+ splx(s);
+#ifdef DEBUG
+ printf("[busy at start]\n");
+#endif
+ return (TRY_AGAIN_LATER);
+ }
+ /*
+ * Build a ScsiCmd for this command and start it.
+ */
+ sc->sc_xs[target] = xs;
+ sc->sc_cmd[target] = &sc->sc_cmd_fake[target]; /* XXX */
+ sc->sc_cmd[target]->unit = 0;
+ sc->sc_cmd[target]->flags = 0;
+ sc->sc_cmd[target]->buflen = xs->datalen;
+ sc->sc_cmd[target]->buf = xs->data;
+ sc->sc_cmd[target]->cmdlen = xs->cmdlen;
+ sc->sc_cmd[target]->cmd = (u_char *)xs->cmd;
+ sc->sc_cmd[target]->lun = xs->sc_link->lun;
+ sii_StartCmd(sc, target);
+ splx(s);
+
+ if ((xs->flags & ITSDONE) != 0)
+ return (COMPLETE);
+ if ((xs->flags & SCSI_POLL) == 0)
+ return (SUCCESSFULLY_QUEUED);
+ count = xs->timeout;
+ while (count) {
+ s = splbio();
+#if 0
+ (void)sii_intr(sc);
+#else
+{
+ u_int dstat;
+
+ /*
+ * Find which controller caused the interrupt.
+ */
+ dstat = sc->sc_regs->dstat;
+ if (dstat & (SII_CI | SII_DI))
+ sii_DoIntr(sc, dstat);
+}
+#endif
+ splx(s);
+ if ((xs->flags & ITSDONE) != 0)
+ break;
+ /* XXX schedule another command? */
+ DELAY(1000);
+ --count;
+ }
+ if ((xs->flags & ITSDONE) != 0)
+ return (COMPLETE);
+ xs->error = XS_TIMEOUT;
+ xs->flags |= ITSDONE;
+ s = splbio();
+ scsi_done(xs);
+ splx(s);
+ return (COMPLETE);
+}
+
+/*
+ * Check to see if any SII chips have pending interrupts
+ * and process as appropriate.
+ */
+int
+sii_intr(xxxsc)
+ void *xxxsc;
+{
+ struct sii_softc *sc = xxxsc;
+ u_int dstat;
+
+ /*
+ * Find which controller caused the interrupt.
+ */
+ dstat = sc->sc_regs->dstat;
+ if (dstat & (SII_CI | SII_DI)) {
+ sii_DoIntr(sc, dstat);
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Reset the SII chip and do a SCSI reset if 'reset' is true.
+ * NOTE: if !cold && reset, should probably probe for devices
+ * since a SCSI bus reset will set UNIT_ATTENTION.
+ */
+void
+sii_Reset(sc, reset)
+ struct sii_softc* sc;
+ int reset; /* TRUE => reset SCSI bus */
+{
+ SIIRegs *regs = sc->sc_regs;
+
+#ifdef DEBUG
+ if (sii_debug > 1)
+ printf("sii: RESET\n");
+#endif
+ /*
+ * Reset the SII chip.
+ */
+ regs->comm = SII_CHRESET;
+ /*
+ * Set arbitrated bus mode.
+ */
+ regs->csr = SII_HPM;
+ /*
+ * Set host adapter ID.
+ */
+ regs->id = SII_ID_IO | sc->sc_hostid;
+ /*
+ * Enable SII to drive the SCSI bus.
+ */
+ regs->dictrl = SII_PRE;
+ regs->dmctrl = 0;
+
+ if (reset) {
+ int i;
+
+ /*
+ * Assert SCSI bus reset for at least 25 Usec to clear the
+ * world. SII_DO_RST is self clearing.
+ * Delay 250 ms before doing any commands.
+ */
+ regs->comm = SII_DO_RST;
+ DELAY(250000);
+
+ /* rearbitrate synchronous offset */
+ for (i = 0; i < SII_NCMD; i++)
+ sc->sc_st[i].dmaReqAck = 0;
+ }
+
+ /*
+ * Clear any pending interrupts from the reset.
+ */
+ regs->cstat = regs->cstat;
+ regs->dstat = regs->dstat;
+ /*
+ * Set up SII for arbitrated bus mode, SCSI parity checking,
+ * Reselect Enable, and Interrupt Enable.
+ */
+ regs->csr = SII_HPM | SII_RSE | SII_PCE | SII_IE;
+}
+
+/*
+ * Start a SCSI command by sending the cmd data
+ * to a SCSI controller via the SII.
+ * Call the device done procedure if it can't be started.
+ * NOTE: we should be called with interrupts disabled.
+ */
+void
+sii_StartCmd(sc, target)
+ struct sii_softc *sc; /* which SII to use */
+ int target; /* which command to start */
+{
+ SIIRegs *regs;
+ ScsiCmd *scsicmd;
+ State *state;
+ u_int status;
+ int error, retval;
+
+ splassert(IPL_BIO);
+
+ /* if another command is currently in progress, just wait */
+ if (sc->sc_target >= 0)
+ return;
+
+ /* initialize state information for this command */
+ scsicmd = sc->sc_cmd[target];
+ state = &sc->sc_st[target];
+ state->flags = FIRST_DMA;
+ state->prevComm = 0;
+ state->dmalen = 0;
+ state->dmaCurPhase = -1;
+ state->dmaPrevPhase = -1;
+ state->dmaBufIndex = 0;
+ state->cmd = scsicmd->cmd;
+ state->cmdlen = scsicmd->cmdlen;
+ if ((state->buflen = scsicmd->buflen) == 0) {
+ state->dmaDataPhase = -1; /* illegal phase. shouldn't happen */
+ state->buf = (char *)0;
+ } else {
+ state->buf = scsicmd->buf;
+ }
+
+#ifdef DEBUG
+ if (sii_debug > 1) {
+ printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n",
+ sc->sc_dev.dv_xname,
+ target, scsicmd->cmd[0], scsicmd->buf, scsicmd->buflen,
+ state->dmaDataPhase);
+ }
+ sii_debug_cmd = scsicmd->cmd[0];
+ if (scsicmd->cmd[0] == READ_BIG ||
+ scsicmd->cmd[0] == WRITE_BIG) {
+ sii_debug_bn = (scsicmd->cmd[2] << 24) |
+ (scsicmd->cmd[3] << 16) |
+ (scsicmd->cmd[4] << 8) |
+ scsicmd->cmd[5];
+ sii_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
+ } else {
+ sii_debug_bn = 0;
+ sii_debug_sz = 0;
+ }
+#endif
+
+ /* try to select the target */
+ regs = sc->sc_regs;
+
+ /*
+ * Another device may have selected us; in which case,
+ * this command will be restarted later.
+ */
+ if ((status = regs->dstat) & (SII_CI | SII_DI)) {
+ sii_DoIntr(sc, status);
+ return;
+ }
+
+ sc->sc_target = target;
+#if 0
+ /* seem to have problems with synchronous transfers */
+ if (scsicmd->flags & SCSICMD_USE_SYNC) {
+ printf("sii_StartCmd: doing extended msg\n"); /* XXX */
+ /*
+ * Setup to send both the identify message and the synchronous
+ * data transfer request.
+ */
+ sc->sc_buf[0] = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG;
+ sc->sc_buf[1] = MSG_EXTENDED;
+ sc->sc_buf[2] = MSG_EXT_SDTR_LEN;
+ sc->sc_buf[3] = MSG_EXT_SDTR;
+ sc->sc_buf[4] = 0;
+ sc->sc_buf[5] = 3; /* maximum SII chip supports */
+
+ state->dmaCurPhase = SII_MSG_OUT_PHASE,
+ state->dmalen = 6;
+ sc->sii_copytobuf(sc, sc->sc_buf, SII_BUF_ADDR(sc), 6);
+ regs->slcsr = target;
+ regs->dmctrl = state->dmaReqAck;
+ regs->dmaddrl = SII_BUF_ADDR(sc);
+ regs->dmaddrh = SII_BUF_ADDR(sc) >> 16;
+ regs->dmlotc = 6;
+ regs->comm = SII_DMA | SII_INXFER | SII_SELECT | SII_ATN |
+ SII_CON | SII_MSG_OUT_PHASE;
+ } else
+#endif
+ {
+ /* do a chained, select with ATN and programmed I/O command */
+ regs->data = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG |
+ scsicmd->lun;
+ regs->slcsr = target;
+ regs->dmctrl = state->dmaReqAck;
+ regs->comm = SII_INXFER | SII_SELECT | SII_ATN | SII_CON |
+ SII_MSG_OUT_PHASE;
+ }
+
+ /*
+ * Wait for something to happen
+ * (should happen soon or we would use interrupts).
+ */
+ SII_WAIT_UNTIL(status, regs->cstat, status & (SII_CI | SII_DI),
+ SII_WAIT_COUNT/4, retval);
+
+ /* check to see if we are connected OK */
+ if ((status & (SII_RST | SII_SCH | SII_STATE_MSK)) ==
+ (SII_SCH | SII_CON)) {
+ regs->cstat = status;
+
+#ifdef DEBUG
+ sii_logp->target = target;
+ sii_logp->cstat = status;
+ sii_logp->dstat = 0;
+ sii_logp->comm = regs->comm;
+ sii_logp->msg = -1;
+ sii_logp->rlen = state->buflen;
+ sii_logp->dlen = state->dmalen;
+ if (++sii_logp >= &sii_log[NLOG])
+ sii_logp = sii_log;
+#endif
+
+ /* wait a short time for command phase */
+ SII_WAIT_UNTIL(status, regs->dstat, status & SII_MIS,
+ SII_WAIT_COUNT, retval);
+#ifdef DEBUG
+ if (sii_debug > 2)
+ printf("sii_StartCmd: ds %x cnt %d\n", status, retval);
+#endif
+ if ((status & (SII_CI | SII_MIS | SII_PHASE_MSK)) !=
+ (SII_MIS | SII_CMD_PHASE)) {
+ printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n",
+ regs->cstat, status, retval); /* XXX */
+ /* process interrupt or continue until it happens */
+ if (status & (SII_CI | SII_DI))
+ sii_DoIntr(sc, status);
+ return;
+ }
+ regs->dstat = SII_DNE; /* clear Msg Out DMA done */
+
+ /* send command data */
+ sc->sii_copytobuf(sc, state->cmd, state->dmaAddr[0],
+ state->cmdlen);
+ sii_StartDMA(regs, state->dmaCurPhase = SII_CMD_PHASE,
+ state->dmaAddr[0], state->dmalen = scsicmd->cmdlen);
+
+ /* wait a little while for DMA to finish */
+ SII_WAIT_UNTIL(status, regs->dstat, status & (SII_CI | SII_DI),
+ SII_WAIT_COUNT, retval);
+#ifdef DEBUG
+ if (sii_debug > 2)
+ printf("sii_StartCmd: ds %x, cnt %d\n", status, retval);
+#endif
+ if (status & (SII_CI | SII_DI))
+ sii_DoIntr(sc, status);
+#ifdef DEBUG
+ if (sii_debug > 2)
+ printf("sii_StartCmd: DONE ds %x\n", regs->dstat);
+#endif
+ return;
+ }
+
+ /*
+ * Another device may have selected us; in which case,
+ * this command will be restarted later.
+ */
+ if (status & (SII_CI | SII_DI)) {
+ sii_DoIntr(sc, regs->dstat);
+ return;
+ }
+
+ /*
+ * Disconnect if selection command still in progress.
+ */
+ if (status & SII_SIP) {
+ error = XS_SELTIMEOUT; /* device didn't respond */
+ regs->comm = SII_DISCON;
+ SII_WAIT_UNTIL(status, regs->cstat,
+ !(status & (SII_CON | SII_SIP)),
+ SII_WAIT_COUNT, retval);
+ } else
+ error = XS_BUSY; /* couldn't get the bus */
+#ifdef DEBUG
+ if (sii_debug > 1)
+ printf("sii_StartCmd: Couldn't select target %d error %d\n",
+ target, error);
+#endif
+ sc->sc_target = -1;
+ regs->cstat = 0xffff;
+ regs->dstat = 0xffff;
+ regs->comm = 0;
+ sii_CmdDone(sc, target, error);
+}
+
+/*
+ * Process interrupt conditions.
+ */
+void
+sii_DoIntr(sc, dstat)
+ struct sii_softc *sc;
+ u_int dstat;
+{
+ SIIRegs *regs = sc->sc_regs;
+ State *state;
+ u_int cstat;
+ int i, msg;
+ u_int comm;
+
+again:
+ comm = regs->comm;
+
+#ifdef DEBUG
+ if (sii_debug > 3)
+ printf("sii_DoIntr: cs %x, ds %x cm %x ",
+ regs->cstat, dstat, comm);
+ sii_logp->target = sc->sc_target;
+ sii_logp->cstat = regs->cstat;
+ sii_logp->dstat = dstat;
+ sii_logp->comm = comm;
+ sii_logp->msg = -1;
+ if (sc->sc_target >= 0) {
+ sii_logp->rlen = sc->sc_st[sc->sc_target].buflen;
+ sii_logp->dlen = sc->sc_st[sc->sc_target].dmalen;
+ } else {
+ sii_logp->rlen = 0;
+ sii_logp->dlen = 0;
+ }
+ if (++sii_logp >= &sii_log[NLOG])
+ sii_logp = sii_log;
+#endif
+
+ regs->dstat = dstat; /* acknowledge everything */
+
+ if (dstat & SII_CI) {
+ /* deglitch cstat register */
+ msg = regs->cstat;
+ while (msg != (cstat = regs->cstat))
+ msg = cstat;
+ regs->cstat = cstat; /* acknowledge everything */
+#ifdef DEBUG
+ if (sii_logp > sii_log)
+ sii_logp[-1].cstat = cstat;
+ else
+ sii_log[NLOG - 1].cstat = cstat;
+#endif
+
+ /* check for a BUS RESET */
+ if (cstat & SII_RST) {
+ printf("%s: SCSI bus reset\n", sc->sc_dev.dv_xname);
+ /* need to flush disconnected commands */
+ for (i = 0; i < SII_NCMD; i++) {
+ if (!sc->sc_cmd[i])
+ continue;
+ sii_CmdDone(sc, i, XS_DRIVER_STUFFUP /* EIO */);
+ }
+ /* rearbitrate synchronous offset */
+ for (i = 0; i < SII_NCMD; i++)
+ sc->sc_st[i].dmaReqAck = 0;
+ sc->sc_target = -1;
+ return;
+ }
+
+#ifdef notdef
+ /*
+ * Check for a BUS ERROR.
+ * According to DEC, this feature doesn't really work
+ * and to just clear the bit if it's set.
+ */
+ if (cstat & SII_BER) {
+ regs->cstat = SII_BER;
+ }
+#endif
+
+ /* check for state change */
+ if (cstat & SII_SCH) {
+ sii_StateChg(sc, cstat);
+ comm = regs->comm;
+ }
+ }
+
+ /* check for DMA completion */
+ if (dstat & SII_DNE) {
+ u_int dma;
+ char *buf;
+
+ /*
+ * There is a race condition with SII_SCH. There is a short
+ * window between the time a SII_SCH is seen after a disconnect
+ * and when the SII_SCH is cleared. A reselect can happen
+ * in this window and we will clear the SII_SCH without
+ * processing the reconnect.
+ */
+ if (sc->sc_target < 0) {
+ cstat = regs->cstat;
+ printf("%s: target %d DNE?? dev %d,%d cs %x\n",
+ sc->sc_dev.dv_xname, sc->sc_target,
+ regs->slcsr, regs->destat,
+ cstat); /* XXX */
+ if (cstat & SII_DST) {
+ sc->sc_target = regs->destat;
+ state = &sc->sc_st[sc->sc_target];
+ state->prevComm = 0;
+ } else
+ panic("sc_target 1");
+ }
+ state = &sc->sc_st[sc->sc_target];
+ /* check for a PARITY ERROR */
+ if (dstat & SII_IPE) {
+ state->flags |= PARITY_ERR;
+ printf("%s: Parity error\n", sc->sc_dev.dv_xname);
+ goto abort;
+ }
+ /* dmalen = amount left to transfer, i = amount transfered */
+ i = state->dmalen;
+ state->dmalen = 0;
+ state->dmaCurPhase = -1;
+#ifdef DEBUG
+ if (sii_debug > 4) {
+ printf("DNE: amt %d ", i);
+ if (!(dstat & SII_TCZ))
+ printf("no TCZ?? (%d) ", regs->dmlotc);
+ } else if (!(dstat & SII_TCZ)) {
+ printf("%s: device %d: no TCZ?? (%d)\n",
+ sc->sc_dev.dv_xname, sc->sc_target, regs->dmlotc);
+ sii_DumpLog(); /* XXX */
+ }
+#endif
+ switch (comm & SII_PHASE_MSK) {
+ case SII_CMD_PHASE:
+ state->cmdlen -= i;
+ break;
+
+ case SII_DATA_IN_PHASE:
+ /* check for more data for the same phase */
+ dma = state->dmaAddr[state->dmaBufIndex];
+ buf = state->buf;
+ state->buf += i;
+ state->buflen -= i;
+ if (state->buflen > 0 && !(dstat & SII_MIS)) {
+ int len;
+
+ /* start reading next chunk */
+ len = state->buflen;
+ if (len > SII_MAX_DMA_XFER_LENGTH)
+ len = SII_MAX_DMA_XFER_LENGTH;
+ state->dmaBufIndex = !state->dmaBufIndex;
+ sii_StartDMA(regs,
+ state->dmaCurPhase = SII_DATA_IN_PHASE,
+ state->dmaAddr[state->dmaBufIndex],
+ state->dmaCnt = state->dmalen = len);
+ dstat &= ~(SII_IBF | SII_TBE);
+ }
+ /* copy in the data */
+ sc->sii_copyfrombuf(sc, dma, buf, i);
+ break;
+
+ case SII_DATA_OUT_PHASE:
+ state->dmaBufIndex = !state->dmaBufIndex;
+ state->buf += i;
+ state->buflen -= i;
+
+ /* check for more data for the same phase */
+ if (state->buflen <= 0 || (dstat & SII_MIS))
+ break;
+
+ /* start next chunk */
+ i = state->buflen;
+ if (i > SII_MAX_DMA_XFER_LENGTH) {
+ sii_StartDMA(regs, state->dmaCurPhase =
+ SII_DATA_OUT_PHASE,
+ state->dmaAddr[state->dmaBufIndex],
+ state->dmaCnt = state->dmalen =
+ SII_MAX_DMA_XFER_LENGTH);
+ /* prepare for next chunk */
+ i -= SII_MAX_DMA_XFER_LENGTH;
+ if (i > SII_MAX_DMA_XFER_LENGTH)
+ i = SII_MAX_DMA_XFER_LENGTH;
+ sc->sii_copytobuf(sc, (u_char *)(state->buf +
+ SII_MAX_DMA_XFER_LENGTH),
+ state->dmaAddr[!state->dmaBufIndex], i);
+ } else {
+ sii_StartDMA(regs, state->dmaCurPhase =
+ SII_DATA_OUT_PHASE,
+ state->dmaAddr[state->dmaBufIndex],
+ state->dmaCnt = state->dmalen = i);
+ }
+ dstat &= ~(SII_IBF | SII_TBE);
+ }
+ }
+
+ /* check for phase change or another MsgIn/Out */
+ if (dstat & (SII_MIS | SII_IBF | SII_TBE)) {
+ /*
+ * There is a race condition with SII_SCH. There is a short
+ * window between the time a SII_SCH is seen after a disconnect
+ * and when the SII_SCH is cleared. A reselect can happen
+ * in this window and we will clear the SII_SCH without
+ * processing the reconnect.
+ */
+ if (sc->sc_target < 0) {
+ cstat = regs->cstat;
+ printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n",
+ sc->sc_dev.dv_xname, sc->sc_target,
+ regs->slcsr, regs->destat,
+ cstat, dstat); /* XXX */
+ if (cstat & SII_DST) {
+ sc->sc_target = regs->destat;
+ state = &sc->sc_st[sc->sc_target];
+ state->prevComm = 0;
+ } else {
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ panic("sc_target 2");
+ }
+ }
+ state = &sc->sc_st[sc->sc_target];
+ switch (dstat & SII_PHASE_MSK) {
+ case SII_CMD_PHASE:
+ if (state->dmaPrevPhase >= 0) {
+ /* restart DMA after disconnect/reconnect */
+ if (state->dmaPrevPhase != SII_CMD_PHASE) {
+ printf("%s: device %d: DMA reselect phase doesn't match\n",
+ sc->sc_dev.dv_xname, sc->sc_target);
+ goto abort;
+ }
+ state->dmaCurPhase = SII_CMD_PHASE;
+ state->dmaPrevPhase = -1;
+ regs->dmaddrl = state->dmaAddrL;
+ regs->dmaddrh = state->dmaAddrH;
+ regs->dmlotc = state->dmaCnt;
+ if (state->dmaCnt & 1)
+ regs->dmabyte = state->dmaByte;
+ regs->comm = SII_DMA | SII_INXFER |
+ (comm & SII_STATE_MSK) | SII_CMD_PHASE;
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("Cmd dcnt %d dadr %x ",
+ state->dmaCnt,
+ (state->dmaAddrH << 16) |
+ state->dmaAddrL);
+#endif
+ } else {
+ /* send command data */
+ i = state->cmdlen;
+ if (i == 0) {
+ printf("%s: device %d: cmd count exceeded\n",
+ sc->sc_dev.dv_xname, sc->sc_target);
+ goto abort;
+ }
+ sc->sii_copytobuf(sc, state->cmd,
+ state->dmaAddr[0], i);
+ sii_StartDMA(regs, state->dmaCurPhase =
+ SII_CMD_PHASE, state->dmaAddr[0],
+ state->dmaCnt = state->dmalen = i);
+ }
+ /* wait a short time for XFER complete */
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
+ if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cnt %d\n", i);
+ else if (sii_debug > 0)
+ printf("sii_DoIntr: cmd wait ds %x cnt %d\n",
+ dstat, i);
+#endif
+ goto again;
+ }
+ break;
+
+ case SII_DATA_IN_PHASE:
+ case SII_DATA_OUT_PHASE:
+ if (state->cmdlen > 0) {
+ printf("%s: device %d: cmd 0x%x: command data not all sent (%d) 1\n",
+ sc->sc_dev.dv_xname, sc->sc_target,
+ sc->sc_cmd[sc->sc_target]->cmd[0],
+ state->cmdlen);
+ state->cmdlen = 0;
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ }
+ if (state->dmaPrevPhase >= 0) {
+ /* restart DMA after disconnect/reconnect */
+ if (state->dmaPrevPhase !=
+ (dstat & SII_PHASE_MSK)) {
+ printf("%s: device %d: DMA reselect phase doesn't match\n",
+ sc->sc_dev.dv_xname, sc->sc_target);
+ goto abort;
+ }
+ state->dmaCurPhase = state->dmaPrevPhase;
+ state->dmaPrevPhase = -1;
+ regs->dmaddrl = state->dmaAddrL;
+ regs->dmaddrh = state->dmaAddrH;
+ regs->dmlotc = state->dmaCnt;
+ if (state->dmaCnt & 1)
+ regs->dmabyte = state->dmaByte;
+ regs->comm = SII_DMA | SII_INXFER |
+ (comm & SII_STATE_MSK) |
+ state->dmaCurPhase;
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("Data %d dcnt %d dadr %x ",
+ state->dmaDataPhase,
+ state->dmaCnt,
+ (state->dmaAddrH << 16) |
+ state->dmaAddrL);
+#endif
+ break;
+ }
+#ifdef DEBUG
+ if (sii_debug > 4) {
+ printf("Data %d ", state->dmaDataPhase);
+ if (sii_debug > 5)
+ printf("\n");
+ }
+#endif
+ i = state->buflen;
+ if (i == 0) {
+ printf("%s: device %d: data count exceeded\n",
+ sc->sc_dev.dv_xname, sc->sc_target);
+ goto abort;
+ }
+ if (i > SII_MAX_DMA_XFER_LENGTH)
+ i = SII_MAX_DMA_XFER_LENGTH;
+ if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) {
+ sii_StartDMA(regs,
+ state->dmaCurPhase = SII_DATA_IN_PHASE,
+ state->dmaAddr[state->dmaBufIndex],
+ state->dmaCnt = state->dmalen = i);
+ break;
+ }
+ /* start first chunk */
+ if (state->flags & FIRST_DMA) {
+ state->flags &= ~FIRST_DMA;
+ sc->sii_copytobuf(sc, (u_char *)state->buf,
+ state->dmaAddr[state->dmaBufIndex], i);
+ }
+ sii_StartDMA(regs,
+ state->dmaCurPhase = SII_DATA_OUT_PHASE,
+ state->dmaAddr[state->dmaBufIndex],
+ state->dmaCnt = state->dmalen = i);
+ i = state->buflen - SII_MAX_DMA_XFER_LENGTH;
+ if (i > 0) {
+ /* prepare for next chunk */
+ if (i > SII_MAX_DMA_XFER_LENGTH)
+ i = SII_MAX_DMA_XFER_LENGTH;
+ sc->sii_copytobuf(sc, (u_char *)(state->buf +
+ SII_MAX_DMA_XFER_LENGTH),
+ state->dmaAddr[!state->dmaBufIndex], i);
+ }
+ break;
+
+ case SII_STATUS_PHASE:
+ if (state->cmdlen > 0) {
+ printf("%s: device %d: cmd 0x%x: command data not all sent (%d) 2\n",
+ sc->sc_dev.dv_xname, sc->sc_target,
+ sc->sc_cmd[sc->sc_target]->cmd[0],
+ state->cmdlen);
+ state->cmdlen = 0;
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ }
+
+ /* read amount transfered if DMA didn't finish */
+ if (state->dmalen > 0) {
+ i = state->dmalen - regs->dmlotc;
+ state->dmalen = 0;
+ state->dmaCurPhase = -1;
+ regs->dmlotc = 0;
+ regs->comm = comm &
+ (SII_STATE_MSK | SII_PHASE_MSK);
+ regs->dstat = SII_DNE;
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("DMA amt %d ", i);
+#endif
+ switch (comm & SII_PHASE_MSK) {
+ case SII_DATA_IN_PHASE:
+ /* copy in the data */
+ sc->sii_copyfrombuf(sc,
+ state->dmaAddr[state->dmaBufIndex],
+ state->buf, i);
+
+ case SII_CMD_PHASE:
+ case SII_DATA_OUT_PHASE:
+ state->buflen -= i;
+ }
+ }
+
+ /* read a one byte status message */
+ state->statusByte = msg =
+ sii_GetByte(regs, SII_STATUS_PHASE, 1);
+ if (msg < 0) {
+ dstat = regs->dstat;
+ goto again;
+ }
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("Status %x ", msg);
+ if (sii_logp > sii_log)
+ sii_logp[-1].msg = msg;
+ else
+ sii_log[NLOG - 1].msg = msg;
+#endif
+
+ /* do a quick wait for COMMAND_COMPLETE */
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
+ if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cnt2 %d\n", i);
+#endif
+ goto again;
+ }
+ break;
+
+ case SII_MSG_IN_PHASE:
+ /*
+ * Save DMA state if DMA didn't finish.
+ * Be careful not to save state again after reconnect
+ * and see RESTORE_POINTER message.
+ * Note that the SII DMA address is not incremented
+ * as DMA proceeds.
+ */
+ if (state->dmaCurPhase >= 0) {
+ /* save DMA registers */
+ state->dmaPrevPhase = state->dmaCurPhase;
+ state->dmaCurPhase = -1;
+ if (dstat & SII_OBB)
+ state->dmaByte = regs->dmabyte;
+ i = regs->dmlotc;
+ if (i != 0)
+ i = state->dmaCnt - i;
+ /* note: no carry from dmaddrl to dmaddrh */
+ state->dmaAddrL = regs->dmaddrl + i;
+ state->dmaAddrH = regs->dmaddrh;
+ state->dmaCnt = regs->dmlotc;
+ if (state->dmaCnt == 0)
+ state->dmaCnt = SII_MAX_DMA_XFER_LENGTH;
+ regs->comm = comm &
+ (SII_STATE_MSK | SII_PHASE_MSK);
+ regs->dstat = SII_DNE;
+#ifdef DEBUG
+ if (sii_debug > 4) {
+ printf("SavP dcnt %d dadr %x ",
+ state->dmaCnt,
+ (state->dmaAddrH << 16) |
+ state->dmaAddrL);
+ if (((dstat & SII_OBB) != 0) ^
+ (state->dmaCnt & 1))
+ printf("OBB??? ");
+ } else if (sii_debug > 0) {
+ if (((dstat & SII_OBB) != 0) ^
+ (state->dmaCnt & 1)) {
+ printf("sii_DoIntr: OBB??? ds %x cnt %d\n",
+ dstat, state->dmaCnt);
+ sii_DumpLog();
+ }
+ }
+#endif
+ }
+
+ /* read a one byte message */
+ msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0);
+ if (msg < 0) {
+ dstat = regs->dstat;
+ goto again;
+ }
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("MsgIn %x ", msg);
+ if (sii_logp > sii_log)
+ sii_logp[-1].msg = msg;
+ else
+ sii_log[NLOG - 1].msg = msg;
+#endif
+
+ /* process message */
+ switch (msg) {
+ case MSG_CMDCOMPLETE:
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE, SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ msg = sc->sc_target;
+ sc->sc_target = -1;
+ /*
+ * Wait a short time for disconnect.
+ * Don't be fooled if SII_BER happens first.
+ * Note: a reselect may happen here.
+ */
+ SII_WAIT_UNTIL(cstat, regs->cstat,
+ cstat & (SII_RST | SII_SCH),
+ SII_WAIT_COUNT, i);
+ if ((cstat & (SII_RST | SII_SCH |
+ SII_STATE_MSK)) == SII_SCH) {
+ regs->cstat = SII_SCH | SII_BER;
+ regs->comm = 0;
+ /*
+ * Double check that we didn't miss a
+ * state change between seeing it and
+ * clearing the SII_SCH bit.
+ */
+ i = regs->cstat;
+ if (!(i & SII_SCH) &&
+ (i & SII_STATE_MSK) !=
+ (cstat & SII_STATE_MSK))
+ sii_StateChg(sc, i);
+ }
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cs %x\n", cstat);
+#endif
+ sii_CmdDone(sc, msg, XS_NOERROR);
+ break;
+
+ case MSG_EXTENDED:
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE, SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ /* read the message length */
+ msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1);
+ if (msg < 0) {
+ dstat = regs->dstat;
+ goto again;
+ }
+ sc->sc_buf[1] = msg; /* message length */
+ if (msg == 0)
+ msg = 256;
+ /*
+ * We read and acknowlege all the bytes
+ * except the last so we can assert ATN
+ * if needed before acknowledging the last.
+ */
+ for (i = 0; i < msg; i++) {
+ dstat = sii_GetByte(regs,
+ SII_MSG_IN_PHASE, i < msg - 1);
+ if ((int)dstat < 0) {
+ dstat = regs->dstat;
+ goto again;
+ }
+ sc->sc_buf[i + 2] = dstat;
+ }
+
+ switch (sc->sc_buf[2]) {
+ case MSG_EXT_MODIFY_DATA_PTR:
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER |
+ SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ i = (sc->sc_buf[3] << 24) |
+ (sc->sc_buf[4] << 16) |
+ (sc->sc_buf[5] << 8) |
+ sc->sc_buf[6];
+ if (state->dmaPrevPhase >= 0) {
+ state->dmaAddrL += i;
+ state->dmaCnt -= i;
+ }
+ break;
+
+ case MSG_EXT_SDTR_LEN:
+ /*
+ * Acknowledge last byte and
+ * signal a request for MSG_OUT.
+ */
+ regs->comm = SII_INXFER | SII_ATN |
+ SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ sii_DoSync(sc, state);
+ break;
+
+ default:
+ reject:
+ /*
+ * Acknowledge last byte and
+ * signal a request for MSG_OUT.
+ */
+ regs->comm = SII_INXFER | SII_ATN |
+ SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+
+ /* wait for MSG_OUT phase */
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_TBE,
+ SII_WAIT_COUNT, i);
+
+ /* send a reject message */
+ regs->data = MSG_MESSAGE_REJECT;
+ regs->comm = SII_INXFER |
+ (regs->cstat & SII_STATE_MSK) |
+ SII_MSG_OUT_PHASE;
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ }
+ break;
+
+ case MSG_SAVEDATAPOINTER:
+ case MSG_RESTOREPOINTERS:
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE, SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ /* wait a short time for another msg */
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & (SII_CI | SII_DI),
+ SII_WAIT_COUNT, i);
+ if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cnt %d\n", i);
+#endif
+ goto again;
+ }
+ break;
+
+ case MSG_DISCONNECT:
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE, SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ state->prevComm = comm;
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("disconn %d ", sc->sc_target);
+#endif
+ /*
+ * Wait a short time for disconnect.
+ * Don't be fooled if SII_BER happens first.
+ * Note: a reselect may happen here.
+ */
+ SII_WAIT_UNTIL(cstat, regs->cstat,
+ cstat & (SII_RST | SII_SCH),
+ SII_WAIT_COUNT, i);
+ if ((cstat & (SII_RST | SII_SCH |
+ SII_STATE_MSK)) != SII_SCH) {
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cnt %d\n", i);
+#endif
+ dstat = regs->dstat;
+ goto again;
+ }
+ regs->cstat = SII_SCH | SII_BER;
+ regs->comm = 0;
+ sc->sc_target = -1;
+ /*
+ * Double check that we didn't miss a state
+ * change between seeing it and clearing
+ * the SII_SCH bit.
+ */
+ i = regs->cstat;
+ if (!(i & SII_SCH) && (i & SII_STATE_MSK) !=
+ (cstat & SII_STATE_MSK))
+ sii_StateChg(sc, i);
+ break;
+
+ case MSG_MESSAGE_REJECT:
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE, SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ printf("%s: device %d: message reject.\n",
+ sc->sc_dev.dv_xname, sc->sc_target);
+ break;
+
+ default:
+ if (!(msg & MSG_IDENTIFYFLAG)) {
+ printf("%s: device %d: couldn't handle "
+ "message 0x%x... rejecting.\n",
+ sc->sc_dev.dv_xname, sc->sc_target,
+ msg);
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ goto reject;
+ }
+ /* acknowledge last byte */
+ regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+ (comm & SII_STATE_MSK);
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & SII_DNE, SII_WAIT_COUNT, i);
+ regs->dstat = SII_DNE;
+ /* may want to check LUN some day */
+ /* wait a short time for another msg */
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ dstat & (SII_CI | SII_DI),
+ SII_WAIT_COUNT, i);
+ if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cnt %d\n", i);
+#endif
+ goto again;
+ }
+ }
+ break;
+
+ case SII_MSG_OUT_PHASE:
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("MsgOut\n");
+#endif
+ printf("MsgOut %x\n", state->flags); /* XXX */
+
+ /*
+ * Check for parity error.
+ * Hardware will automatically set ATN
+ * to request the device for a MSG_OUT phase.
+ */
+ if (state->flags & PARITY_ERR) {
+ state->flags &= ~PARITY_ERR;
+ regs->data = MSG_PARITY_ERROR;
+ } else
+ regs->data = MSG_NOOP;
+ regs->comm = SII_INXFER | (comm & SII_STATE_MSK) |
+ SII_MSG_OUT_PHASE;
+
+ /* wait a short time for XFER complete */
+ SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("ds %x i %d\n", dstat, i);
+#endif
+ /* just clear the DNE bit and check errors later */
+ if (dstat & SII_DNE) {
+ regs->dstat = SII_DNE;
+ }
+ break;
+
+ default:
+ printf("%s: Couldn't handle phase %d... ignoring.\n",
+ sc->sc_dev.dv_xname, dstat & SII_PHASE_MSK);
+ }
+ }
+
+#ifdef DEBUG
+ if (sii_debug > 3)
+ printf("\n");
+#endif
+ /*
+ * Check to make sure we won't be interrupted again.
+ * Deglitch dstat register.
+ */
+ msg = regs->dstat;
+ while (msg != (dstat = regs->dstat))
+ msg = dstat;
+ if (dstat & (SII_CI | SII_DI))
+ goto again;
+
+ if (sc->sc_target < 0) {
+ /* look for another device that is ready */
+ for (i = 0; i < SII_NCMD; i++) {
+ /* don't restart a disconnected command */
+ if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
+ continue;
+ sii_StartCmd(sc, i);
+ break;
+ }
+ }
+ return;
+
+abort:
+ /* jump here to abort the current command */
+ printf("%s: device %d: current command terminated\n",
+ sc->sc_dev.dv_xname, sc->sc_target);
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+
+ if ((cstat = regs->cstat) & SII_CON) {
+ /* try to send an abort msg for awhile */
+ regs->dstat = SII_DNE;
+ regs->data = MSG_ABORT;
+ regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) |
+ SII_MSG_OUT_PHASE;
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ (dstat & (SII_DNE | SII_PHASE_MSK)) ==
+ (SII_DNE | SII_MSG_OUT_PHASE),
+ 2 * SII_WAIT_COUNT, i);
+#ifdef DEBUG
+ if (sii_debug > 0)
+ printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i);
+#endif
+ if ((dstat & (SII_DNE | SII_PHASE_MSK)) ==
+ (SII_DNE | SII_MSG_OUT_PHASE)) {
+ /* disconnect if command in progress */
+ regs->comm = SII_DISCON;
+ SII_WAIT_UNTIL(cstat, regs->cstat,
+ !(cstat & SII_CON), SII_WAIT_COUNT, i);
+ }
+ } else {
+#ifdef DEBUG
+ if (sii_debug > 0)
+ printf("Abort: cs %x\n", cstat);
+#endif
+ }
+ regs->cstat = 0xffff;
+ regs->dstat = 0xffff;
+ regs->comm = 0;
+
+ i = sc->sc_target;
+ sc->sc_target = -1;
+ sii_CmdDone(sc, i, XS_DRIVER_STUFFUP /* EIO */);
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target);
+#endif
+}
+
+void
+sii_StateChg(sc, cstat)
+ struct sii_softc *sc;
+ u_int cstat;
+{
+ SIIRegs *regs = sc->sc_regs;
+ State *state;
+ int i;
+
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("SCH: ");
+#endif
+
+ switch (cstat & SII_STATE_MSK) {
+ case 0:
+ /* disconnect */
+ i = sc->sc_target;
+ sc->sc_target = -1;
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("disconn %d ", i);
+#endif
+ if (i >= 0 && !sc->sc_st[i].prevComm) {
+ printf("%s: device %d: spurrious disconnect (%d)\n",
+ sc->sc_dev.dv_xname, i, regs->slcsr);
+ sc->sc_st[i].prevComm = 0;
+ }
+ break;
+
+ case SII_CON:
+ /* connected as initiator */
+ i = regs->slcsr;
+ if (sc->sc_target == i)
+ break;
+ printf("%s: device %d: connect to device %d??\n",
+ sc->sc_dev.dv_xname, sc->sc_target, i);
+ sc->sc_target = i;
+ break;
+
+ case SII_DST:
+ /*
+ * Wait for CON to become valid,
+ * chip is slow sometimes.
+ */
+ SII_WAIT_UNTIL(cstat, regs->cstat,
+ cstat & SII_CON, SII_WAIT_COUNT, i);
+ if (!(cstat & SII_CON))
+ panic("sii resel");
+ /* FALLTHROUGH */
+
+ case SII_CON | SII_DST:
+ /*
+ * Its a reselection. Save the ID and wait for
+ * interrupts to tell us what to do next
+ * (should be MSG_IN of IDENTIFY).
+ * NOTE: sc_target may be >= 0 if we were in
+ * the process of trying to start a command
+ * and were reselected before the select
+ * command finished.
+ */
+ sc->sc_target = i = regs->destat;
+ state = &sc->sc_st[i];
+ regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE;
+ regs->dmctrl = state->dmaReqAck;
+ if (!state->prevComm) {
+ printf("%s: device %d: spurious reselection\n",
+ sc->sc_dev.dv_xname, i);
+ break;
+ }
+ state->prevComm = 0;
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("resel %d ", sc->sc_target);
+#endif
+ break;
+
+#ifdef notyet
+ case SII_DST | SII_TGT:
+ case SII_CON | SII_DST | SII_TGT:
+ /* connected as target */
+ printf("%s: Selected by device %d as target!!\n",
+ sc->sc_dev.dv_xname, regs->destat);
+ regs->comm = SII_DISCON;
+ SII_WAIT_UNTIL(!(regs->cstat & SII_CON),
+ SII_WAIT_COUNT, i);
+ regs->cstat = 0xffff;
+ regs->dstat = 0xffff;
+ regs->comm = 0;
+ break;
+#endif
+
+ default:
+ printf("%s: Unknown state change (cs %x)!!\n",
+ sc->sc_dev.dv_xname, cstat);
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ }
+}
+
+/*
+ * Read one byte of data.
+ * If 'ack' is true, acknowledge the byte.
+ */
+int
+sii_GetByte(regs, phase, ack)
+ SIIRegs *regs;
+ int phase, ack;
+{
+ u_int dstat;
+ u_int state;
+ int i;
+ int data;
+
+ dstat = regs->dstat;
+ state = regs->cstat & SII_STATE_MSK;
+ i = -1;
+ if (!(dstat & SII_IBF) || (dstat & SII_MIS)) {
+ regs->comm = state | phase;
+ /* wait a short time for IBF */
+ SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF,
+ SII_WAIT_COUNT, i);
+#ifdef DEBUG
+ if (!(dstat & SII_IBF))
+ printf("status no IBF\n");
+#endif
+ }
+ if (dstat & SII_DNE) { /* XXX */
+ printf("sii_GetByte: DNE set 5\n");
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ regs->dstat = SII_DNE;
+ }
+ data = regs->data;
+ /* check for parity error */
+ if (dstat & SII_IPE) {
+#ifdef DEBUG
+ if (sii_debug > 4)
+ printf("cnt0 %d\n", i);
+#endif
+ printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n",
+ data, dstat, regs->comm, i); /* XXX */
+ data = -1;
+ ack = 1;
+ }
+
+ if (ack) {
+ regs->comm = SII_INXFER | state | phase;
+
+ /* wait a short time for XFER complete */
+ SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+
+ /* clear the DNE */
+ if (dstat & SII_DNE) {
+ regs->dstat = SII_DNE;
+ }
+ }
+
+ return (data);
+}
+
+/*
+ * Exchange messages to initiate synchronous data transfers.
+ */
+void
+sii_DoSync(sc, state)
+ struct sii_softc *sc;
+ State *state;
+{
+ SIIRegs *regs = sc->sc_regs;
+ u_int dstat, comm;
+ int i, j;
+ u_int len;
+
+#ifdef DEBUG
+ if (sii_debug)
+ printf("sii_DoSync: len %d per %d req/ack %d\n",
+ sc->sc_buf[1], sc->sc_buf[3], sc->sc_buf[4]);
+#endif
+
+ /* SII chip can only handle a minimum transfer period of ??? */
+ if (sc->sc_buf[3] < 64)
+ sc->sc_buf[3] = 64;
+ /* SII chip can only handle a maximum REQ/ACK offset of 3 */
+ len = sc->sc_buf[4];
+ if (len > 3)
+ len = 3;
+
+ sc->sc_buf[0] = MSG_EXTENDED;
+ sc->sc_buf[1] = MSG_EXT_SDTR_LEN;
+ sc->sc_buf[2] = MSG_EXT_SDTR;
+ sc->sc_buf[4] = len;
+#if 1
+ comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE |
+ (regs->cstat & SII_STATE_MSK);
+ regs->comm = comm & ~SII_INXFER;
+ for (j = 0; j < 5; j++) {
+ /* wait for target to request the next byte */
+ SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE,
+ SII_WAIT_COUNT, i);
+ if (!(dstat & SII_TBE) ||
+ (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) {
+ printf("sii_DoSync: TBE? ds %x cm %x i %d\n",
+ dstat, comm, i); /* XXX */
+ return;
+ }
+
+ /* the last message byte should have ATN off */
+ if (j == 4)
+ comm &= ~SII_ATN;
+
+ regs->data = sc->sc_buf[j];
+ regs->comm = comm;
+
+ /* wait a short time for XFER complete */
+ SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
+ SII_WAIT_COUNT, i);
+
+ if (!(dstat & SII_DNE)) {
+ printf("sii_DoSync: DNE? ds %x cm %x i %d\n",
+ dstat, comm, i); /* XXX */
+ return;
+ }
+
+ /* clear the DNE, other errors handled later */
+ regs->dstat = SII_DNE;
+ }
+#else /* 0 */
+ sc->sii_copytobuf(sc, sc->sc_buf, SII_BUF_ADDR(sc), 5);
+ printf("sii_DoSync: %x %x %x ds %x\n",
+ ((u_short *)sc->sc_buf)[0], ((u_short *)sc->sc_buf)[1],
+ ((u_short *)sc->sc_buf)[2], regs->dstat); /* XXX */
+ regs->dmaddrl = SII_BUF_ADDR(sc);
+ regs->dmaddrh = SII_BUF_ADDR(sc) >> 16;
+ regs->dmlotc = 5;
+ regs->comm = SII_DMA | SII_INXFER | SII_ATN |
+ (regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE;
+
+ /* wait a short time for XFER complete */
+ SII_WAIT_UNTIL(dstat, regs->dstat,
+ (dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ),
+ SII_WAIT_COUNT, i);
+
+ if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) {
+ printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
+ dstat, regs->comm, i, regs->dmlotc); /* XXX */
+ sii_DumpLog(); /* XXX */
+ return;
+ }
+ /* clear the DNE, other errors handled later */
+ regs->dstat = SII_DNE;
+#endif /* 0 */
+
+#if 0
+ SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI),
+ SII_WAIT_COUNT, i);
+ printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
+ dstat, regs->comm, i, regs->dmlotc); /* XXX */
+#endif
+
+ state->dmaReqAck = len;
+}
+
+/*
+ * Issue the sequence of commands to the controller to start DMA.
+ * NOTE: the data buffer should be word-aligned for DMA out.
+ */
+void
+sii_StartDMA(regs, phase, dmaAddr, size)
+ SIIRegs *regs; /* which SII to use */
+ int phase; /* phase to send/receive data */
+ u_int dmaAddr; /* DMA buffer offset */
+ int size; /* # of bytes to transfer */
+{
+
+ if (regs->dstat & SII_DNE) { /* XXX */
+ regs->dstat = SII_DNE;
+ printf("sii_StartDMA: DNE set\n");
+#ifdef DEBUG
+ sii_DumpLog();
+#endif
+ }
+ regs->dmaddrl = dmaAddr;
+ regs->dmaddrh = dmaAddr >> 16;
+ regs->dmlotc = size;
+ regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) |
+ phase;
+
+#ifdef DEBUG
+ if (sii_debug > 5) {
+ printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n",
+ regs->cstat, regs->dstat, regs->comm, size);
+ }
+#endif
+}
+
+/*
+ * Call the device driver's 'done' routine to let it know the command is done.
+ * The 'done' routine may try to start another command.
+ * To be fair, we should start pending commands for other devices
+ * before allowing the same device to start another command.
+ */
+void
+sii_CmdDone(sc, target, error)
+ struct sii_softc *sc; /* which SII to use */
+ int target; /* which device is done */
+ int error; /* error code if any errors */
+{
+ ScsiCmd *scsicmd;
+ struct scsi_xfer *xs;
+ int i;
+
+ splassert(IPL_BIO);
+
+ scsicmd = sc->sc_cmd[target];
+#ifdef DIAGNOSTIC
+ if (target < 0 || !scsicmd)
+ panic("sii_CmdDone");
+#endif
+ sc->sc_cmd[target] = NULL;
+#ifdef DEBUG
+ if (sii_debug > 1) {
+ printf("sii_CmdDone: %s target %d cmd 0x%x err %d resid %d\n",
+ sc->sc_dev.dv_xname,
+ target, scsicmd->cmd[0], error, sc->sc_st[target].buflen);
+ }
+#endif
+
+ /* look for another device that is ready */
+ for (i = 0; i < SII_NCMD; i++) {
+ /* don't restart a disconnected command */
+ if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
+ continue;
+ sii_StartCmd(sc, i);
+ break;
+ }
+
+ xs = sc->sc_xs[target];
+ xs->status = sc->sc_st[target].statusByte;
+ xs->error = error;
+ xs->resid = sc->sc_st[target].buflen;
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+}
+
+#ifdef DEBUG
+void
+sii_DumpLog()
+{
+ struct sii_log *lp;
+
+ printf("sii: cmd 0x%x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn,
+ sii_debug_sz);
+ lp = sii_logp;
+ do {
+ printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n",
+ lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg,
+ lp->rlen, lp->dlen);
+ if (++lp >= &sii_log[NLOG])
+ lp = sii_log;
+ } while (lp != sii_logp);
+}
+#endif
diff --git a/sys/arch/vax/dec/siireg.h b/sys/arch/vax/dec/siireg.h
new file mode 100644
index 00000000000..c83f0df9e37
--- /dev/null
+++ b/sys/arch/vax/dec/siireg.h
@@ -0,0 +1,235 @@
+/* $OpenBSD: siireg.h,v 1.1 2008/08/18 23:19:22 miod Exp $ */
+/* $NetBSD: siireg.h,v 1.2 2006/07/29 19:10:57 ad Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)siireg.h 8.1 (Berkeley) 6/10/93
+ *
+ * sii.h --
+ *
+ * SII registers.
+ *
+ * Copyright (C) 1989 Digital Equipment Corporation.
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies.
+ * Digital Equipment Corporation makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/sii.h,
+ * v 1.2 89/08/15 19:53:04 rab Exp SPRITE (DECWRL)
+ */
+
+#ifndef _SII
+#define _SII
+
+/*
+ * SII hardware registers
+ */
+typedef volatile struct {
+ u_short sdb; /* SCSI Data Bus and Parity */
+ u_short pad0;
+ u_short sc1; /* SCSI Control Signals One */
+ u_short pad1;
+ u_short sc2; /* SCSI Control Signals Two */
+ u_short pad2;
+ u_short csr; /* Control/Status register */
+ u_short pad3;
+ u_short id; /* Bus ID register */
+ u_short pad4;
+ u_short slcsr; /* Select Control and Status Register */
+ u_short pad5;
+ u_short destat; /* Selection Detector Status Register */
+ u_short pad6;
+ u_short dstmo; /* DSSI Timeout Register */
+ u_short pad7;
+ u_short data; /* Data Register */
+ u_short pad8;
+ u_short dmctrl; /* DMA Control Register */
+ u_short pad9;
+ u_short dmlotc; /* DMA Length of Transfer Counter */
+ u_short pad10;
+ u_short dmaddrl; /* DMA Address Register Low */
+ u_short pad11;
+ u_short dmaddrh; /* DMA Address Register High */
+ u_short pad12;
+ u_short dmabyte; /* DMA Initial Byte Register */
+ u_short pad13;
+ u_short stlp; /* DSSI Short Target List Pointer */
+ u_short pad14;
+ u_short ltlp; /* DSSI Long Target List Pointer */
+ u_short pad15;
+ u_short ilp; /* DSSI Initiator List Pointer */
+ u_short pad16;
+ u_short dsctrl; /* DSSI Control Register */
+ u_short pad17;
+ u_short cstat; /* Connection Status Register */
+ u_short pad18;
+ u_short dstat; /* Data Transfer Status Register */
+ u_short pad19;
+ u_short comm; /* Command Register */
+ u_short pad20;
+ u_short dictrl; /* Diagnostic Control Register */
+ u_short pad21;
+ u_short clock; /* Diagnostic Clock Register */
+ u_short pad22;
+ u_short bhdiag; /* Bus Handler Diagnostic Register */
+ u_short pad23;
+ u_short sidiag; /* SCSI IO Diagnostic Register */
+ u_short pad24;
+ u_short dmdiag; /* Data Mover Diagnostic Register */
+ u_short pad25;
+ u_short mcdiag; /* Main Control Diagnostic Register */
+ u_short pad26;
+} SIIRegs;
+
+/*
+ * SC1 - SCSI Control Signals One
+ */
+#define SII_SC1_MSK 0x1ff /* All possible signals on the bus */
+#define SII_SC1_SEL 0x80 /* SCSI SEL signal active on bus */
+#define SII_SC1_ATN 0x08 /* SCSI ATN signal active on bus */
+
+/*
+ * SC2 - SCSI Control Signals Two
+ */
+#define SII_SC2_IGS 0x8 /* SCSI drivers for initiator mode */
+
+/*
+ * CSR - Control/Status Register
+ */
+#define SII_HPM 0x10 /* SII in on an arbitrated SCSI bus */
+#define SII_RSE 0x08 /* 1 = respond to reselections */
+#define SII_SLE 0x04 /* 1 = respond to selections */
+#define SII_PCE 0x02 /* 1 = report parity errors */
+#define SII_IE 0x01 /* 1 = enable interrupts */
+
+/*
+ * ID - Bus ID Register
+ */
+#define SII_ID_IO 0x8000 /* I/O */
+
+/*
+ * DESTAT - Selection Detector Status Register
+ */
+#define SII_IDMSK 0x7 /* ID of target reselected the SII */
+
+/*
+ * DMCTRL - DMA Control Register
+ */
+#define SII_ASYNC 0x00 /* REQ/ACK Offset for async mode */
+#define SII_SYNC 0x03 /* REQ/ACK Offset for sync mode */
+
+/*
+ * DMLOTC - DMA Length Of Transfer Counter
+ */
+#define SII_TCMSK 0x1fff /* transfer count mask */
+
+/*
+ * CSTAT - Connection Status Register
+ */
+#define SII_CI 0x8000 /* composite interrupt bit for CSTAT */
+#define SII_DI 0x4000 /* composite interrupt bit for DSTAT */
+#define SII_RST 0x2000 /* 1 if reset is asserted on SCSI bus */
+#define SII_BER 0x1000 /* Bus error */
+#define SII_OBC 0x0800 /* Out_en Bit Cleared (DSSI mode) */
+#define SII_TZ 0x0400 /* Target pointer Zero (STLP or LTLP is zero) */
+#define SII_BUF 0x0200 /* Buffer service - outbound pkt to non-DSSI */
+#define SII_LDN 0x0100 /* List element Done */
+#define SII_SCH 0x0080 /* State Change */
+#define SII_CON 0x0040 /* SII is Connected to another device */
+#define SII_DST 0x0020 /* SII was Destination of current transfer */
+#define SII_TGT 0x0010 /* SII is operating as a Target */
+#define SII_STATE_MSK 0x0070 /* State Mask */
+#define SII_SWA 0x0008 /* Selected With Attention */
+#define SII_SIP 0x0004 /* Selection In Progress */
+#define SII_LST 0x0002 /* Lost arbitration */
+
+/*
+ * DSTAT - Data Transfer Status Register
+ */
+#define SII_DNE 0x2000 /* DMA transfer Done */
+#define SII_TCZ 0x1000 /* Transfer Count register is Zero */
+#define SII_TBE 0x0800 /* Transmit Buffer Empty */
+#define SII_IBF 0x0400 /* Input Buffer Full */
+#define SII_IPE 0x0200 /* Incoming Parity Error */
+#define SII_OBB 0x0100 /* Odd Byte Boundry */
+#define SII_MIS 0x0010 /* Phase Mismatch */
+#define SII_ATN 0x0008 /* ATN set by initiator if in Target mode */
+#define SII_MSG 0x0004 /* current bus state of MSG */
+#define SII_CD 0x0002 /* current bus state of C/D */
+#define SII_IO 0x0001 /* current bus state of I/O */
+#define SII_PHASE_MSK 0x0007 /* Phase Mask */
+
+/*
+ * The different phases.
+ */
+#define SII_MSG_IN_PHASE 0x7
+#define SII_MSG_OUT_PHASE 0x6
+#define SII_STATUS_PHASE 0x3
+#define SII_CMD_PHASE 0x2
+#define SII_DATA_IN_PHASE 0x1
+#define SII_DATA_OUT_PHASE 0x0
+
+/*
+ * COMM - Command Register
+ */
+#define SII_DMA 0x8000 /* DMA mode */
+#define SII_DO_RST 0x4000 /* Assert reset on SCSI bus for 25 usecs */
+#define SII_RSL 0x1000 /* 0 = select, 1 = reselect desired device */
+
+/* Commands: I - Initiator, T - Target, D - Disconnected */
+#define SII_INXFER 0x0800 /* Information Transfer command (I,T) */
+#define SII_SELECT 0x0400 /* Select command (D) */
+#define SII_REQDATA 0x0200 /* Request Data command (T) */
+#define SII_DISCON 0x0100 /* Disconnect command (I,T,D) */
+#define SII_CHRESET 0x0080 /* Chip Reset command (I,T,D) */
+
+/* Command state bits same as connection status register */
+/* Command phase bits same as data transfer status register */
+
+/*
+ * DICTRL - Diagnostic Control Register
+ */
+#define SII_PRE 0x4 /* Enable the SII to drive the SCSI bus */
+
+#define SII_WAIT_COUNT 10000 /* Delay count used for the SII chip */
+/*
+ * Max DMA transfer length for SII
+ * The SII chip only has a 13 bit counter. If 8192 is used as the max count,
+ * you can't tell the difference between a count of zero and 8192.
+ * 8190 is used instead of 8191 so the count is even.
+ */
+#define SII_MAX_DMA_XFER_LENGTH 8192
+
+#endif /* _SII */
diff --git a/sys/arch/vax/dec/siivar.h b/sys/arch/vax/dec/siivar.h
new file mode 100644
index 00000000000..82a92518d19
--- /dev/null
+++ b/sys/arch/vax/dec/siivar.h
@@ -0,0 +1,71 @@
+/* $OpenBSD: siivar.h,v 1.1 2008/08/18 23:19:22 miod Exp $ */
+/* $NetBSD: siivar.h,v 1.6 2000/06/02 20:16:51 mhitch Exp $ */
+
+#ifndef _SIIVAR_H
+#define _SIIVAR_H
+
+/*
+ * This structure contains information that a SCSI interface controller
+ * needs to execute a SCSI command.
+ */
+typedef struct ScsiCmd {
+ int unit; /* unit number passed to device done routine */
+ int flags; /* control flags for this command (see below) */
+ int buflen; /* length of the data buffer in bytes */
+ char *buf; /* pointer to data buffer for this command */
+ int cmdlen; /* length of data in cmdbuf */
+ u_char *cmd; /* buffer for the SCSI command */
+ int error; /* compatibility hack for new scsi */
+ int lun; /* LUN for MI SCSI */
+} ScsiCmd;
+
+typedef struct scsi_state {
+ int statusByte; /* status byte returned during STATUS_PHASE */
+ int dmaDataPhase; /* which data phase to expect */
+ int dmaCurPhase; /* SCSI phase if DMA is in progress */
+ int dmaPrevPhase; /* SCSI phase of DMA suspended by disconnect */
+ u_int dmaAddr[2]; /* DMA buffer memory offsets */
+ int dmaBufIndex; /* which of the above is currently in use */
+ int dmalen; /* amount to transfer in this chunk */
+ int cmdlen; /* total remaining amount of cmd to transfer */
+ u_char *cmd; /* current pointer within scsicmd->cmd */
+ int buflen; /* total remaining amount of data to transfer */
+ char *buf; /* current pointer within scsicmd->buf */
+ u_short flags; /* see below */
+ u_short prevComm; /* command reg before disconnect */
+ u_short dmaCtrl; /* DMA control register if disconnect */
+ u_short dmaAddrL; /* DMA address register if disconnect */
+ u_short dmaAddrH; /* DMA address register if disconnect */
+ u_short dmaCnt; /* DMA count if disconnect */
+ u_short dmaByte; /* DMA byte if disconnect on odd boundary */
+ u_short dmaReqAck; /* DMA synchronous xfer offset or 0 if async */
+} State;
+
+/* state flags */
+#define FIRST_DMA 0x01 /* true if no data DMA started yet */
+#define PARITY_ERR 0x02 /* true if parity error seen */
+
+#define SII_NCMD 8
+struct sii_softc {
+ struct device sc_dev; /* us as a device */
+ struct scsi_link sc_link; /* scsi link struct */
+ ScsiCmd sc_cmd_fake[SII_NCMD]; /* XXX - hack!!! */
+ struct scsi_xfer *sc_xs[SII_NCMD]; /* XXX - hack!!! */
+ SIIRegs *sc_regs; /* HW address of SII controller chip */
+ int sc_flags;
+ int sc_target; /* target SCSI ID if connected */
+ int sc_hostid;
+ ScsiCmd *sc_cmd[SII_NCMD]; /* active command indexed by ID */
+ void (*sii_copytobuf)(void *, u_char *, u_int, int);
+ void (*sii_copyfrombuf)(void *, u_int, u_char *, int);
+
+ State sc_st[SII_NCMD]; /* state info for each active command */
+
+ u_char sc_buf[258]; /* used for extended messages */
+};
+
+/* Machine-independent back-end attach entry point */
+void sii_attach(struct sii_softc *sc);
+int sii_intr(void *sc);
+
+#endif /* _SIIVAR_H */
diff --git a/sys/arch/vax/include/clock.h b/sys/arch/vax/include/clock.h
index ff228c73e03..00caf4d1c2a 100644
--- a/sys/arch/vax/include/clock.h
+++ b/sys/arch/vax/include/clock.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.h,v 1.7 2008/08/15 22:41:46 miod Exp $ */
+/* $OpenBSD: clock.h,v 1.8 2008/08/18 23:19:24 miod Exp $ */
/* $NetBSD: clock.h,v 1.4 1999/09/06 19:52:53 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
@@ -74,3 +74,6 @@ int generic_clkread(time_t);
void generic_clkwrite(void);
int chip_clkread(time_t);
void chip_clkwrite(void);
+
+int yeartonum(int);
+int numtoyear(int);
diff --git a/sys/arch/vax/include/nexus.h b/sys/arch/vax/include/nexus.h
index 69c7583dc41..fe2101f5f53 100644
--- a/sys/arch/vax/include/nexus.h
+++ b/sys/arch/vax/include/nexus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nexus.h,v 1.13 2006/08/27 16:55:41 miod Exp $ */
+/* $OpenBSD: nexus.h,v 1.14 2008/08/18 23:19:24 miod Exp $ */
/* $NetBSD: nexus.h,v 1.17 2000/06/04 17:58:19 ragge Exp $ */
/*-
@@ -54,6 +54,7 @@ struct mainbus_attach_args {
#define VAX_IBUS 8 /* Internal Microvax bus */
#define VAX_XMIBUS 9 /* XMI master bus (6000) */
#define VAX_VXTBUS 10 /* Pseudo VXT2000 bus */
+#define VAX_MBUS 11 /* M-bus (KA60) */
#define VAX_LEDS 0x42 /* pseudo value to attach led0 */
diff --git a/sys/arch/vax/include/rpb.h b/sys/arch/vax/include/rpb.h
index 1f2ca79be23..1a4438b7c8a 100644
--- a/sys/arch/vax/include/rpb.h
+++ b/sys/arch/vax/include/rpb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rpb.h,v 1.10 2002/06/11 09:36:24 hugh Exp $ */
+/* $OpenBSD: rpb.h,v 1.11 2008/08/18 23:19:24 miod Exp $ */
/* $NetBSD: rpb.h,v 1.6 1998/07/01 09:37:11 ragge Exp $ */
/*
* Copyright (c) 1995 Ludd, University of Lule}, Sweden.
@@ -113,6 +113,7 @@ struct rpb { /* size description */
#define BDEV_NK 35
#define BDEV_RD 36 /* ST506/MFM disk on HDC9224 */
#define BDEV_ST 37 /* SCSI tape on NCR5380 */
+#define BDEV_SDS 39 /* SCSI disk on SII */
#define BDEV_SD 42 /* SCSI disk on NCR5380 */
#define BDEV_SDN 46 /* SCSI disk on NCR5394 */
#define BDEV_CNSL 64
diff --git a/sys/arch/vax/include/scb.h b/sys/arch/vax/include/scb.h
index 5f2b6d8b7dc..cc16863bc22 100644
--- a/sys/arch/vax/include/scb.h
+++ b/sys/arch/vax/include/scb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scb.h,v 1.9 2007/04/10 18:31:44 miod Exp $ */
+/* $OpenBSD: scb.h,v 1.10 2008/08/18 23:19:24 miod Exp $ */
/* $NetBSD: scb.h,v 1.11 2000/07/10 09:14:34 ragge Exp $ */
/*
@@ -131,10 +131,11 @@ extern const struct ivec_dsp idsptch;
extern struct scb *scb;
extern struct ivec_dsp *scb_vec;
-extern paddr_t scb_init (paddr_t);
-extern int scb_vecref (int *, int *);
-extern void scb_fake (int, int);
-extern void scb_vecalloc (int, void(*)(void *), void *, int, struct evcount *);
+extern paddr_t scb_init(paddr_t);
+extern int scb_vecref(int *, int *);
+extern void scb_fake(int, int);
+extern void scb_stray(void *);
+extern void scb_vecalloc(int, void(*)(void *), void *, int, struct evcount *);
#endif /* _KERNEL */
#endif /* _VAX_SCB_H */
diff --git a/sys/arch/vax/mbus/dz_fwio.c b/sys/arch/vax/mbus/dz_fwio.c
new file mode 100644
index 00000000000..678d833bac0
--- /dev/null
+++ b/sys/arch/vax/mbus/dz_fwio.c
@@ -0,0 +1,215 @@
+/* $OpenBSD: dz_fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*
+ * Copyright (c) 1998 Ludd, University of Lule}, Sweden.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+#include <vax/qbus/dzreg.h>
+#include <vax/qbus/dzvar.h>
+
+#include <vax/dec/dzkbdvar.h>
+
+#include <sys/tty.h>
+#include <dev/cons.h>
+
+#include "dzkbd.h"
+#include "dzms.h"
+
+int dz_fwio_match(struct device *, void *, void *);
+void dz_fwio_attach(struct device *, struct device *, void *);
+
+struct cfattach dz_fwio_ca = {
+ sizeof(struct dz_softc), dz_fwio_match, dz_fwio_attach
+};
+
+extern struct cfdriver dz_cd;
+
+int dz_fwio_intr(void *);
+
+#define DZ_FWIO_CSR 0
+#define DZ_FWIO_RBUF 4
+#define DZ_FWIO_DTR 9
+#define DZ_FWIO_BREAK 13
+#define DZ_FWIO_TBUF 12
+#define DZ_FWIO_TCR 8
+#define DZ_FWIO_DCD 13
+#define DZ_FWIO_RING 13
+
+int
+dz_fwio_match(struct device *parent, void *vcf, void *aux)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+ return strcmp(faa->faa_dev, dz_cd.cd_name) == 0 ? 1 : 0;
+}
+
+void
+dz_fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+ struct dz_softc *sc = (struct dz_softc *)self;
+ paddr_t basepa;
+#if NDZKBD > 0 || NDZMS > 0
+ struct dzkm_attach_args daa;
+ extern struct consdev wsdisplay_cons;
+#endif
+ extern vaddr_t dz_console_regs;
+ vaddr_t dz_regs;
+ unsigned int vec;
+ int console;
+ int serial_console;
+
+ vec = faa->faa_vecbase + FBIC_DEVIRQ2 * 4;
+ printf(" vec %d: ", vec);
+
+ /*
+ * Map registers.
+ */
+
+ if (dz_console_regs != 0 && faa->faa_mid == mbus_ioslot) {
+ dz_regs = dz_console_regs;
+ console = 1;
+ serial_console = 1; /* XXX forced for now */
+ if (serial_console)
+ printf("console, ");
+ } else {
+ basepa = faa->faa_base + FWIO_DZ_REG_OFFSET;
+ dz_regs = vax_map_physmem(basepa, 1);
+ console = 0;
+ }
+
+ /*
+ * XXX - This is evil and ugly, but...
+ * due to the nature of how bus_space_* works on VAX, this will
+ * be perfectly good until everything is converted.
+ */
+ sc->sc_ioh = dz_regs;
+
+ sc->sc_dr.dr_csr = DZ_FWIO_CSR;
+ sc->sc_dr.dr_rbuf = DZ_FWIO_RBUF;
+ sc->sc_dr.dr_tbuf = DZ_FWIO_TBUF;
+ sc->sc_dr.dr_tcr = DZ_FWIO_TCR;
+ sc->sc_dr.dr_dtr = DZ_FWIO_DTR;
+ sc->sc_dr.dr_break = DZ_FWIO_BREAK;
+ sc->sc_dr.dr_dcd = DZ_FWIO_DCD;
+ sc->sc_dr.dr_ring = DZ_FWIO_RING;
+
+ sc->sc_type = DZ_DZV;
+
+ /* no modem ctrl bits except on line 2 */
+ sc->sc_dsr = (1 << 0) | (1 << 1) | (1 << 3);
+
+ printf("4 lines");
+
+ /*
+ * Complete attachment.
+ */
+
+ dzattach(sc);
+
+ /*
+ * Register interrupt handler.
+ */
+
+ if (mbus_intr_establish(vec, IPL_TTY, dz_fwio_intr, sc,
+ self->dv_xname) != 0) {
+ printf("\n%s: can't establish interrupt\n", self->dv_xname);
+ return;
+ }
+
+ /*
+ * Attach input devices, if any.
+ */
+
+#if NDZKBD > 0
+ daa.daa_line = 0;
+ DZ_WRITE_WORD(sc, dr_rbuf, DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) |
+ DZ_LPR_8_BIT_CHAR | daa.daa_line);
+ daa.daa_flags =
+ (console && cn_tab == &wsdisplay_cons ? DZKBD_CONSOLE : 0);
+ config_found(self, &daa, dz_print);
+#endif
+#if NDZMS > 0
+ daa.daa_line = 1;
+ DZ_WRITE_WORD(sc, dr_rbuf, DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) |
+ DZ_LPR_8_BIT_CHAR | DZ_LPR_PARENB | DZ_LPR_OPAR | daa.daa_line);
+ daa.daa_flags = 0;
+ config_found(self, &daa, dz_print);
+#endif
+}
+
+int
+dz_fwio_intr(void *v)
+{
+ struct dz_softc *sc = (struct dz_softc *)v;
+
+ /*
+ * FBIC expects edge interrupts, while the dz does level
+ * interrupts. To avoid missing interrupts while servicing,
+ * we disable further device interrupts while servicing.
+ */
+ DZ_WRITE_WORD(sc, dr_csr,
+ DZ_READ_WORD(sc, dr_csr) & ~(DZ_CSR_RXIE | DZ_CSR_TXIE));
+
+ dzrint(sc);
+ dzxint(sc);
+
+ DZ_WRITE_WORD(sc, dr_csr,
+ DZ_READ_WORD(sc, dr_csr) | (DZ_CSR_RXIE | DZ_CSR_TXIE));
+
+ return 1;
+}
diff --git a/sys/arch/vax/mbus/files.mbus b/sys/arch/vax/mbus/files.mbus
new file mode 100644
index 00000000000..8b692910545
--- /dev/null
+++ b/sys/arch/vax/mbus/files.mbus
@@ -0,0 +1,29 @@
+# $OpenBSD: files.mbus,v 1.1 2008/08/18 23:19:25 miod Exp $
+
+# VAXstation 3[58][24]0 internal bus
+device mbus { [mid = -1] }
+attach mbus at mainbus
+file arch/vax/mbus/mbus.c mbus
+
+# L2003 Firefox Workstation I/O Module
+device fwio {}
+attach fwio at mbus
+file arch/vax/mbus/fwio.c fwio
+
+attach dz at fwio with dz_fwio: dzcons
+file arch/vax/mbus/dz_fwio.c dz_fwio
+
+attach le at fwio with le_fwio
+file arch/vax/mbus/if_le_fwio.c le_fwio
+
+attach sii at fwio with sii_fwio
+file arch/vax/mbus/sii_fwio.c sii_fwio
+
+# L2008 CQBIC
+attach uba at mbus with uba_mbus
+file arch/vax/mbus/uba_mbus.c uba_mbus
+
+# L2001 or L2010 CPU
+# L2004 LEGSS video
+# (with L2005 8-plane output module and optional L2006 16-plane module)
+# L2007 memory
diff --git a/sys/arch/vax/mbus/fwio.c b/sys/arch/vax/mbus/fwio.c
new file mode 100644
index 00000000000..32d62fc7542
--- /dev/null
+++ b/sys/arch/vax/mbus/fwio.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*
+ * Firefox Workstation I/O Module
+ *
+ * This M-bus board sports:
+ * - a System Support Chip implementing the (off cpu) clocks.
+ * - a SII controller, in SCSI mode, with 128KB static memory.
+ * - a LANCE Ethernet controller, with 128KB static memory.
+ * - a DZQ11-compatible DC7085 4 lines serial controller.
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/nexus.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+struct fwio_softc {
+ struct device sc_dev;
+ int sc_loc[1]; /* locators override */
+};
+
+void fwio_attach(struct device *, struct device *, void *);
+int fwio_match(struct device *, void *, void *);
+
+struct cfdriver fwio_cd = {
+ NULL, "fwio", DV_DULL
+};
+
+const struct cfattach fwio_ca = {
+ sizeof(struct fwio_softc), fwio_match, fwio_attach
+};
+
+int fwio_print(void *, const char *);
+
+int
+fwio_match(struct device *parent, void *vcf, void *aux)
+{
+ struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+
+ if (maa->maa_class == CLASS_IO && maa->maa_interface == INTERFACE_FBIC)
+ return 1;
+
+ return 0;
+}
+
+void
+fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+ struct fwio_softc *sc = (struct fwio_softc *)self;
+ struct fwio_attach_args faa;
+
+ printf("\n");
+
+ /*
+ * Save our mid in locators. booted_sd() in autoconf.c depends
+ * on this to find the correct boot device.
+ */
+ sc->sc_loc[0] = maa->maa_mid;
+ self->dv_cfdata->cf_loc = sc->sc_loc;
+
+ faa.faa_mid = maa->maa_mid;
+ faa.faa_base = MBUS_SLOT_BASE(maa->maa_mid);
+ faa.faa_vecbase = maa->maa_vecbase;
+
+ faa.faa_dev = "dz";
+ (void)config_found(self, &faa, fwio_print);
+
+ faa.faa_dev = "le";
+ (void)config_found(self, &faa, fwio_print);
+
+ faa.faa_dev = "sii";
+ (void)config_found(self, &faa, fwio_print);
+}
+
+int
+fwio_print(void *aux, const char *pnp)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+ if (pnp != NULL)
+ printf("%s at %s", faa->faa_dev, pnp);
+
+ return (UNCONF);
+}
diff --git a/sys/arch/vax/mbus/fwioreg.h b/sys/arch/vax/mbus/fwioreg.h
new file mode 100644
index 00000000000..81b4a6986d7
--- /dev/null
+++ b/sys/arch/vax/mbus/fwioreg.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: fwioreg.h,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*
+ * Firefox Workstation I/O Module registers and memory layout
+ */
+
+#define FWIO_SSC_REMAP_ADDR 0x21400000
+
+#define FWIO_SII_REG_OFFSET 0x000000
+#define FWIO_LANCE_REG_OFFSET 0x200000
+#define FWIO_SII_BUF_OFFSET 0x400000
+#define FWIO_SII_BUF_SIZE 0x020000
+#define FWIO_DZ_REG_OFFSET 0x600000
+#define FWIO_IOCSR_OFFSET 0x800000
+#define FWIO_ESAR_OFFSET 0x800000
+#define FWIO_LANCE_BUF_OFFSET 0xa00000
+#define FWIO_LANCE_BUF_SIZE 0x020000
+
+/*
+ * IOCSR bits
+ */
+
+#define FWIO_IOCSR_CNSL 0x80000000 /* break on line 3 asserts MHALT */
+#define FWIO_IOCSR_MRUN 0x40000000 /* assert MRUN */
+#define FWIO_IOCSR_CLKIEN 0x20000000 /* drive MCLKI */
+#define FWIO_IOCSR_RSTWS 0x10000000 /* reset workstation */
+
+#define FWIO_ESAR_MASK 0x00ff0000
+#define FWIO_ESAR_SHIFT 16
diff --git a/sys/arch/vax/mbus/fwiovar.h b/sys/arch/vax/mbus/fwiovar.h
new file mode 100644
index 00000000000..05f5e4a26af
--- /dev/null
+++ b/sys/arch/vax/mbus/fwiovar.h
@@ -0,0 +1,28 @@
+/* $OpenBSD: fwiovar.h,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*
+ * Firefox Workstation I/O Module subdevice attachment glue
+ */
+
+struct fwio_attach_args {
+ const char *faa_dev;
+ unsigned int faa_mid;
+ paddr_t faa_base;
+ unsigned int faa_vecbase;
+};
diff --git a/sys/arch/vax/mbus/if_le_fwio.c b/sys/arch/vax/mbus/if_le_fwio.c
new file mode 100644
index 00000000000..8a0011535f5
--- /dev/null
+++ b/sys/arch/vax/mbus/if_le_fwio.c
@@ -0,0 +1,272 @@
+/* $OpenBSD: if_le_fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 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) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)if_le.c 8.2 (Berkeley) 11/16/93
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#if INET
+#include <netinet/in.h>
+#endif
+#include <netinet/if_ether.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+struct le_fwio_softc {
+ struct am7990_softc sc_am7990;
+ volatile uint16_t *sc_rap;
+ volatile uint16_t *sc_rdp;
+};
+
+int le_fwio_match(struct device *, void *, void *);
+void le_fwio_attach(struct device *, struct device *, void *);
+
+struct cfattach le_fwio_ca = {
+ sizeof(struct le_fwio_softc), le_fwio_match, le_fwio_attach
+};
+
+int le_fwio_intr(void *);
+uint16_t le_fwio_rdcsr(struct am7990_softc *, uint16_t);
+void le_fwio_wrcsr(struct am7990_softc *, uint16_t, uint16_t);
+void le_fwio_wrcsr_interrupt(struct am7990_softc *, uint16_t, uint16_t);
+
+int
+le_fwio_match(struct device *parent, void *vcf, void *aux)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+ return strcmp(faa->faa_dev, le_cd.cd_name) == 0 ? 1 : 0;
+}
+
+void
+le_fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+ struct le_fwio_softc *sc = (struct le_fwio_softc *)self;
+ unsigned int vec;
+ uint32_t *esar;
+ int i;
+
+ vec = faa->faa_vecbase + FBIC_DEVIRQ1 * 4;
+ printf(" vec %d", vec);
+
+ /*
+ * Map registers.
+ */
+
+ sc->sc_rdp = (volatile uint16_t *)
+ vax_map_physmem(faa->faa_base + FWIO_LANCE_REG_OFFSET, 1);
+ sc->sc_rap = sc->sc_rdp + 2;
+
+ /*
+ * Register access functions.
+ */
+
+ sc->sc_am7990.sc_rdcsr = le_fwio_rdcsr;
+ sc->sc_am7990.sc_wrcsr = le_fwio_wrcsr;
+
+ /*
+ * Map buffers.
+ */
+
+ sc->sc_am7990.sc_mem =
+ (void *)uvm_km_valloc(kernel_map, FWIO_LANCE_BUF_SIZE);
+ if (sc->sc_am7990.sc_mem == NULL) {
+ vax_unmap_physmem(faa->faa_base + FWIO_LANCE_REG_OFFSET, 1);
+ printf(": can't map buffers\n");
+ return;
+ }
+
+ ioaccess((vaddr_t)sc->sc_am7990.sc_mem, faa->faa_base +
+ FWIO_LANCE_BUF_OFFSET, FWIO_LANCE_BUF_SIZE >> VAX_PGSHIFT);
+
+ sc->sc_am7990.sc_addr = FWIO_LANCE_BUF_OFFSET;
+ sc->sc_am7990.sc_memsize = FWIO_LANCE_BUF_SIZE;
+ sc->sc_am7990.sc_conf3 = 0;
+
+ sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig;
+ sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig;
+ sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig;
+ sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig;
+ sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig;
+
+ /*
+ * Get the Ethernet address from the Station Address ROM.
+ */
+
+ esar = (uint32_t *)vax_map_physmem(faa->faa_base + FWIO_ESAR_OFFSET, 1);
+ for (i = 0; i < 6; i++)
+ sc->sc_am7990.sc_arpcom.ac_enaddr[i] =
+ (esar[i] & FWIO_ESAR_MASK) >> FWIO_ESAR_SHIFT;
+ vax_unmap_physmem((vaddr_t)esar, 1);
+ bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ);
+
+ /*
+ * Register interrupt handler.
+ */
+
+ if (mbus_intr_establish(vec, IPL_NET, le_fwio_intr, sc,
+ self->dv_xname) != 0) {
+ vax_unmap_physmem(faa->faa_base + FWIO_LANCE_REG_OFFSET, 1);
+ uvm_km_free(kernel_map, (vaddr_t)sc->sc_am7990.sc_mem,
+ FWIO_LANCE_BUF_SIZE);
+ printf(": can't establish interrupt\n");
+ return;
+ }
+
+ /*
+ * Complete attachment.
+ */
+
+ am7990_config(&sc->sc_am7990);
+}
+
+int
+le_fwio_intr(void *v)
+{
+ struct le_fwio_softc *lsc = (struct le_fwio_softc *)v;
+ int rc;
+
+ /*
+ * FBIC expects edge interrupts, while the LANCE does level
+ * interrupts. To avoid missing interrupts while servicing,
+ * we disable further device interrupts while servicing.
+ *
+ * However, am7990_intr() will flip the interrupt enable bit
+ * itself; we override wrcsr with a specific version during
+ * servicing, so as not to reenable interrupts accidentally...
+ */
+ lsc->sc_am7990.sc_wrcsr = le_fwio_wrcsr_interrupt;
+
+ rc = am7990_intr(v);
+
+ lsc->sc_am7990.sc_wrcsr = le_fwio_wrcsr;
+ /*
+ * ...but we should not forget to reenable interrupts at this point!
+ */
+ le_fwio_wrcsr(&lsc->sc_am7990, LE_CSR0, LE_C0_INEA |
+ le_fwio_rdcsr(&lsc->sc_am7990, LE_CSR0));
+
+ return rc;
+}
+
+uint16_t
+le_fwio_rdcsr(struct am7990_softc *sc, uint16_t port)
+{
+ struct le_fwio_softc *lsc = (struct le_fwio_softc *)sc;
+
+ *lsc->sc_rap = port;
+ return *lsc->sc_rdp;
+}
+
+void
+le_fwio_wrcsr(struct am7990_softc *sc, uint16_t port, uint16_t val)
+{
+ struct le_fwio_softc *lsc = (struct le_fwio_softc *)sc;
+
+ *lsc->sc_rap = port;
+ *lsc->sc_rdp = val;
+}
+
+void
+le_fwio_wrcsr_interrupt(struct am7990_softc *sc, uint16_t port, uint16_t val)
+{
+ if (port == LE_CSR0)
+ val &= ~LE_C0_INEA;
+
+ le_fwio_wrcsr(sc, port, val);
+}
diff --git a/sys/arch/vax/mbus/mbus.c b/sys/arch/vax/mbus/mbus.c
new file mode 100644
index 00000000000..a9fc92145fb
--- /dev/null
+++ b/sys/arch/vax/mbus/mbus.c
@@ -0,0 +1,441 @@
+/* $OpenBSD: mbus.c,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/nexus.h>
+#include <machine/scb.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+
+#define PR_CPUID 14
+
+/*
+ * FBIC interrupt handlers
+ */
+struct fbic_irq {
+ int (*fi_fn)(void *);
+ void *fi_arg;
+ struct evcount fi_cnt;
+ int fi_ipl;
+};
+
+/*
+ * Generic information for each slot.
+ *
+ * This information is maintained at the mbus level, rather than
+ * enforcing each child driver to provide it. This allows proper
+ * M-bus configuration on slots where no driver attaches.
+ */
+
+struct fbic {
+ paddr_t base;
+ vaddr_t regs;
+ int vecbase;
+ struct fbic_irq *firq[FBIC_DEVIRQMAX];
+};
+
+struct mbus_slot {
+ uint8_t ms_interface; /* MODTYPE interface */
+ uint8_t ms_class; /* MODTYPE class */
+
+ unsigned int ms_nfbic;
+ struct fbic ms_fbic[2];
+};
+
+struct mbus_softc {
+ struct device sc_dev;
+ struct mbus_slot *sc_slots[MBUS_SLOT_MAX];
+};
+
+void mbus_attach(struct device *, struct device *, void *);
+int mbus_match(struct device *, void *, void *);
+
+struct cfdriver mbus_cd = {
+ NULL, "mbus", DV_DULL
+};
+
+const struct cfattach mbus_ca = {
+ sizeof(struct mbus_softc), mbus_match, mbus_attach
+};
+
+void mbus_initialize_cpu(struct mbus_slot *, unsigned int, int);
+void mbus_initialize_device(struct mbus_slot *, unsigned int, uint8_t);
+void mbus_intr_dispatch(void *);
+int mbus_print(void *, const char *);
+int mbus_submatch(struct device *, void *, void *);
+
+unsigned int mbus_ioslot = (unsigned int)-1;
+
+int
+mbus_match(struct device *parent, void *vcf, void *aux)
+{
+ struct mainbus_attach_args *maa = (struct mainbus_attach_args *)aux;
+
+ return maa->maa_bustype == VAX_MBUS ? 1 : 0;
+}
+
+void
+mbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct mbus_softc *sc = (struct mbus_softc *)self;
+ struct mbus_slot *ms;
+ unsigned int mid;
+ struct mbus_attach_args maa;
+ paddr_t pa;
+ vaddr_t fbic;
+ uint32_t modtype;
+ uint8_t class, interface;
+
+ printf("\n");
+
+ /*
+ * Walk the bus and probe slots.
+ * We will also record information about all occupied slots,
+ * and keep a permanent mapping of their FBIC, as we will end
+ * up needing to play with them often...
+ */
+
+ for (mid = 0; mid < MBUS_SLOT_MAX; mid++) {
+
+ /*
+ * Map main (and often, only) FBIC.
+ */
+
+ pa = MBUS_SLOT_BASE(mid);
+ fbic = vax_map_physmem(pa + FBIC_BASE, 1);
+ if (fbic == NULL)
+ panic("unable to map slot %d registers", mid);
+
+ if (badaddr((caddr_t)(fbic + FBIC_MODTYPE), 4) != 0)
+ modtype = 0;
+ else
+ modtype = *(uint32_t *)(fbic + FBIC_MODTYPE);
+
+ if (modtype == 0 || modtype == 0xffffffff) {
+ vax_unmap_physmem(fbic, 1);
+ continue;
+ }
+
+ /*
+ * The slot is populated. Write things down.
+ */
+
+ ms = (struct mbus_slot *)malloc(sizeof(*ms),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (ms == NULL)
+ panic("not enough memory to probe M-bus");
+
+ sc->sc_slots[mid] = ms;
+ ms->ms_nfbic = 1; /* only one so far! */
+ ms->ms_fbic[0].base = pa + FBIC_BASE;
+ ms->ms_fbic[0].regs = fbic;
+
+ class = (modtype & MODTYPE_CLASS_MASK) >> MODTYPE_CLASS_SHIFT;
+ interface = (modtype & MODTYPE_INTERFACE_MASK) >>
+ MODTYPE_INTERFACE_SHIFT;
+
+ ms->ms_interface = interface;
+ ms->ms_class = class;
+
+ /*
+ * If there are two FBICs on this board, map the second one.
+ */
+
+ if (class == CLASS_CPU) {
+ /* the FBIC we mapped is in fact the second one... */
+ ms->ms_fbic[1].base = ms->ms_fbic[0].base;
+ ms->ms_fbic[1].regs = ms->ms_fbic[0].regs;
+ ms->ms_nfbic = 2;
+ fbic = vax_map_physmem(pa + FBIC_CPUA_BASE, 1);
+ if (fbic == NULL)
+ panic("unable to map slot %d registers", mid);
+ ms->ms_fbic[0].base = pa + FBIC_CPUA_BASE;
+ ms->ms_fbic[0].regs = fbic;
+ }
+
+ /*
+ * Perform a minimal sane initialization.
+ */
+
+ if (class == CLASS_CPU) {
+ mbus_initialize_cpu(ms, mid, 0);
+ mbus_initialize_cpu(ms, mid, 1);
+ } else
+ mbus_initialize_device(ms, mid, interface);
+
+ /*
+ * Attach subdevices if possible.
+ */
+
+ maa.maa_mid = mid;
+ maa.maa_class = class;
+ maa.maa_subclass = (modtype & MODTYPE_SUBCLASS_MASK) >>
+ MODTYPE_SUBCLASS_SHIFT;
+ maa.maa_interface = interface;
+ maa.maa_revision = (modtype & MODTYPE_REVISION_MASK) >>
+ MODTYPE_REVISION_SHIFT;
+ maa.maa_addr = pa;
+ maa.maa_vecbase = ms->ms_fbic[0].vecbase;
+
+ (void)config_found_sm(self, &maa, mbus_print, mbus_submatch);
+ }
+}
+
+int
+mbus_print(void *aux, const char *pnp)
+{
+ struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+ int rc = UNCONF;
+ const char *descr;
+
+ switch (maa->maa_class) {
+ case CLASS_BA:
+ descr = "Bus Adaptor";
+ break;
+ case CLASS_GRAPHICS:
+ descr = "Graphics";
+ break;
+ case CLASS_IO:
+ descr = "I/O Module";
+ break;
+ case CLASS_CPU:
+ descr = "cpu";
+ break;
+ case CLASS_MEMORY:
+ descr = maa->maa_interface == INTERFACE_FMDC ?
+ "ECC memory" : "Memory";
+ break;
+ default:
+ rc = UNSUPP;
+ break;
+ }
+
+ if (maa->maa_interface != INTERFACE_FBIC) {
+ if (maa->maa_class != CLASS_MEMORY ||
+ (maa->maa_interface != INTERFACE_FMCM &&
+ maa->maa_interface != INTERFACE_FMDC))
+ rc = UNSUPP;
+ }
+
+ if (pnp != NULL) {
+ if (rc == UNSUPP) {
+ printf("logic board class %02x:%02x interface %u.%u ",
+ maa->maa_class, maa->maa_subclass,
+ maa->maa_interface, maa->maa_revision);
+ if (descr != NULL)
+ printf("(%s)", descr);
+ } else
+ printf("%s", descr);
+ printf(" at %s", pnp);
+ }
+ printf(" mid %u", maa->maa_mid);
+
+ return (rc);
+}
+
+int
+mbus_submatch(struct device *parent, void *vcf, void *aux)
+{
+ struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+ struct cfdata *cf = (struct cfdata *)vcf;
+
+ /*
+ * If attachment specifies the mid, it has to match.
+ */
+ if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != maa->maa_mid)
+ return 0;
+
+ return (*cf->cf_attach->ca_match)(parent, vcf, aux);
+}
+
+/*
+ * CPU board initialization.
+ */
+
+void
+mbus_initialize_cpu(struct mbus_slot *ms, unsigned int mid, int cpu)
+{
+ struct fbic *fbic = &ms->ms_fbic[cpu];
+ uint32_t fbicsr;
+ int cpuid;
+
+ cpuid = (mid << CPUID_MID_SHIFT) |
+ (cpu != 0 ? CPUID_PROC_1 : CPUID_PROC_0);
+
+ /*
+ * Clear error log
+ */
+ *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = BUSCSR_RESET;
+
+ /*
+ * Set (IPI) interrupt vectors base, but do not enable them yet.
+ */
+ fbic->vecbase = MBUS_VECTOR_BASE(mid, cpu);
+ *(uint32_t *)(fbic->regs + FBIC_IPDVINT) = 0 /* IPDVINT_IPUNIT */ |
+ (fbic->vecbase & IPDVINT_VECTOR_MASK);
+
+ /*
+ * Enable all interrupt sources if on the boot processor,
+ * disable them otherwise (this does not affect IPIs).
+ */
+ fbicsr = *(uint32_t *)(fbic->regs + FBIC_BUSCSR);
+ if (cpuid == mfpr(PR_CPUID))
+ fbicsr |= FBICSR_IRQEN_MASK;
+ else
+ fbicsr &= ~FBICSR_IRQEN_MASK;
+
+ /*
+ * Route interrupts from the M-bus to the CVAX.
+ */
+ fbicsr &= ~FBICSR_IRQC2M_MASK;
+
+ /*
+ * Allow the CPU to be halted.
+ */
+ fbicsr |= FBICSR_HALTEN;
+
+ *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = fbicsr;
+}
+
+/*
+ * Device board initialization.
+ */
+
+void
+mbus_initialize_device(struct mbus_slot *ms, unsigned int mid,
+ uint8_t interface)
+{
+ struct fbic *fbic = ms->ms_fbic;
+ uint32_t fbicsr;
+
+ /*
+ * Clear error log if applicable
+ */
+ if (interface == INTERFACE_FBIC || interface == INTERFACE_FMDC)
+ *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = BUSCSR_RESET;
+
+ if (interface == INTERFACE_FBIC) {
+ /*
+ * Set interrupt vector base.
+ */
+ fbic->vecbase = MBUS_VECTOR_BASE(mid, 0);
+ *(uint32_t *)(fbic->regs + FBIC_IPDVINT) = IPDVINT_DEVICE |
+ (fbic->vecbase & IPDVINT_VECTOR_MASK);
+
+ /*
+ * Disable all interrupt sources, and route them
+ * from the devices to the M-bus.
+ */
+ fbicsr = *(uint32_t *)(fbic->regs + FBIC_BUSCSR);
+ fbicsr &= ~FBICSR_IRQEN_MASK;
+ fbicsr |= FBICSR_IRQC2M_MASK;
+ *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = fbicsr;
+ }
+}
+
+/*
+ * Interrupt handling.
+ */
+
+int
+mbus_intr_establish(unsigned int vec, int ipl, int (*fn)(void *), void *arg,
+ const char *name)
+{
+ struct mbus_softc *sc;
+ struct mbus_slot *ms;
+ struct fbic *fbic;
+ struct fbic_irq *fi;
+ uint32_t fbicsr;
+ unsigned int mid, fbicirq;
+
+ mid = MBUS_VECTOR_TO_MID(vec);
+
+#ifdef DIAGNOSTIC
+ if (mid >= MBUS_SLOT_MAX)
+ return EINVAL;
+ if (mbus_cd.cd_ndevs == 0)
+ return ENXIO;
+#endif
+ sc = (struct mbus_softc *)mbus_cd.cd_devs[0];
+#ifdef DIAGNOSTIC
+ if (sc == NULL)
+ return ENXIO;
+#endif
+ ms = sc->sc_slots[mid];
+#ifdef DIAGNOSTIC
+ if (ms == NULL)
+ return ENXIO;
+#endif
+ fi = (struct fbic_irq *)malloc(sizeof *fi, M_DEVBUF, M_NOWAIT);
+ if (fi == NULL)
+ return ENOMEM;
+
+ /*
+ * This interface is intended to be used for device interrupts
+ * only, so there is no need to handle dual-FBIC slots.
+ */
+ fbic = &ms->ms_fbic[0 /* MBUS_VECTOR_TO_FBIC(vec) */];
+
+ fi->fi_fn = fn;
+ fi->fi_arg = arg;
+ fi->fi_ipl = ipl;
+ evcount_attach(&fi->fi_cnt, name, &fi->fi_ipl, &evcount_intr);
+
+ fbicirq = MBUS_VECTOR_TO_IRQ(vec);
+ fbic->firq[fbicirq] = fi;
+ scb_vecalloc(vec, mbus_intr_dispatch, fi, SCB_ISTACK, &fi->fi_cnt);
+
+ /*
+ * Enable device interrupt in the module FBIC. Proper direction
+ * has been setup in mbus_slot_initialize().
+ */
+
+ fbicsr = *(uint32_t *)(fbic->regs + FBIC_BUSCSR);
+ fbicsr |= fbicirq << FBICSR_IRQEN_SHIFT;
+ *(uint32_t *)(fbic + FBIC_BUSCSR) = fbicsr;
+
+ return 0;
+}
+
+/*
+ * Interrupt dispatcher.
+ */
+
+void
+mbus_intr_dispatch(void *v)
+{
+ struct fbic_irq *fi = (struct fbic_irq *)v;
+ int s;
+
+ /*
+ * FBIC interrupts are at fixed levels. In case the level is
+ * below the level the driver expects the interrupt at, we need
+ * to raise spl to be safe (e.g. for sii).
+ */
+ s = _splraise(fi->fi_ipl);
+ (void)(*fi->fi_fn)(fi->fi_arg);
+ splx(s);
+}
diff --git a/sys/arch/vax/mbus/mbusreg.h b/sys/arch/vax/mbus/mbusreg.h
new file mode 100644
index 00000000000..cea06e6041e
--- /dev/null
+++ b/sys/arch/vax/mbus/mbusreg.h
@@ -0,0 +1,251 @@
+/* $OpenBSD: mbusreg.h,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*
+ * M-bus
+ *
+ * The M-bus connects up to 8 slots, of 32MB memory space each.
+ *
+ * All these modules contain a ``Firefox Bus Interface Chip'' (FBIC),
+ * which provides common registers at the end of each slot address space,
+ * allowing modules to recognize and configure each other.
+ */
+
+#define MBUS_SLOT_MAX 8
+
+/*
+ * Addressing
+ *
+ * The M-bus provides a 32-bit address space.
+ *
+ * The low half (bit 31 clear) is the physical memory space (and being on
+ * vax, really stops at 512MB).
+ * The high half is the I/O space, where each slot has a 32MB window.
+ * In addition to its window, there are two 128MB areas, allowing a given
+ * module to provide functionnality regardless of its actual position on
+ * the bus.
+ *
+ * From the host CPU, the M-bus I/O space is remapped in the vax I/O space.
+ *
+ * The address map is thus:
+ * M-bus address CPU address Length
+ * 0000.0000 0000.0000 2000.0000 memory space
+ * 8000.0000 2000.0000 0800.0000 global I/O
+ * 8800.0000 2800.0000 0800.0000 local I/O
+ * 9000.0000 3000.0000 0200.0000 slot 0 I/O
+ * 9200.0000 3200.0000 0200.0000 slot 1 I/O
+ * 9400.0000 3400.0000 0200.0000 slot 2 I/O
+ * 9600.0000 3600.0000 0200.0000 slot 3 I/O
+ * 9800.0000 3800.0000 0200.0000 slot 4 I/O
+ * 9a00.0000 3a00.0000 0200.0000 slot 5 I/O
+ * 9c00.0000 3c00.0000 0200.0000 slot 6 I/O
+ * 9e00.0000 3e00.0000 0200.0000 slot 7 I/O
+ */
+
+/* base address of a slot, as seen from the cpu */
+#define MBUS_SLOT_BASE(s) (0x30000000 + ((s) << 25))
+
+/* convert I/O space addresses (assumed to be in their correct range) */
+#define HOST_TO_MBUS(pa) ((pa) ^ 0xa0000000)
+#define MBUS_TO_HOST(pa) ((pa) ^ 0xa0000000)
+
+/*
+ * Common FBIC slot registers
+ */
+
+/* FBIC or compatible registers occupy the last page (running down)... */
+#define FBIC_BASE 0x1fffe00
+/* ...but dual-CPU modules have two of them. */
+#define FBIC_CPUA_BASE 0x0fffe00
+#define FBIC_CPUB_BASE 0x1fffe00
+
+/* module identification */
+#define FBIC_MODTYPE 0x1fc
+/* M-bus error status */
+#define FBIC_BUSCSR 0x1f8
+/* M-bus error control signal log */
+#define FBIC_BUSCTL 0x1f4
+/* M-bus error address signal log */
+#define FBIC_BUSADR 0x1f0
+/* M-bus error data signal log */
+#define FBIC_BUSDAT 0x1ec
+/* FBIC control and status */
+#define FBIC_CSR 0x1e8
+/* I/O space range decode */
+#define FBIC_RANGE 0x1e4
+/* Interprocessor and device interrupt */
+#define FBIC_IPDVINT 0x1e0
+/* Unique software ID */
+#define FBIC_WHAMI 0x1dc
+/* Unique hardware ID */
+#define FBIC_CPUID 0x1d8
+/* Interlock 1 address */
+#define FBIC_IADR1 0x1d4
+/* Interlock 2 address */
+#define FBIC_IADR2 0x1d0
+/* Console scratch register */
+#define FBIC_SAVGPR 0x1c4
+
+/*
+ * Module identification
+ */
+#define MODTYPE_CLASS_MASK 0x000000ff
+#define MODTYPE_CLASS_SHIFT 0
+#define CLASS_BA 0x01
+#define CLASS_GRAPHICS 0x02
+#define CLASS_IO 0x04
+#define CLASS_CPU 0x08
+#define CLASS_MEMORY 0x10
+#define MODTYPE_SUBCLASS_MASK 0x0000ff00
+#define MODTYPE_SUBCLASS_SHIFT 8
+#define MODTYPE_INTERFACE_MASK 0x00ff0000
+#define MODTYPE_INTERFACE_SHIFT 16
+#define INTERFACE_FBIC 0x01
+#define INTERFACE_FMDC 0x02 /* ECC memory */
+#define INTERFACE_FMCM 0xfe /* 8MB board */
+#define MODTYPE_REVISION_MASK 0xff000000
+#define MODTYPE_REVISION_SHIFT 24
+
+/*
+ * M-bus error status and error logging
+ * Conditions are active low
+ */
+#define BUSCSR_FRZN 0x80000000 /* logging frozen */
+#define BUSCSR_ARB 0x40000000 /* arbitration error */
+#define BUSCSR_ICMD 0x20000000 /* invalid MCMD encoding */
+#define BUSCSR_IDAT 0x10000000 /* invalid data supplied */
+#define BUSCSR_MTPE 0x08000000 /* tag parity error */
+#define BUSCSR_MDPE 0x04000000 /* MDAL parity error */
+#define BUSCSR_MSPE 0x02000000 /* MSTATUS parity error */
+#define BUSCSR_MCPE 0x01000000 /* MCMD parity error */
+#define BUSCSR_ILCK 0x00800000 /* interlock violation */
+#define BUSCSR_MTO 0x00400000 /* slave timeout */
+#define BUSCSR_NOS 0x00200000 /* no slave response */
+#define BUSCSR_CTO 0x00100000 /* CDAL data cycle timeout */
+#define BUSCSR_CDPE 0x00080000 /* CDAL parity error */
+#define BUSCSR_CTPE 0x00040000 /* CDAL tag parity error */
+#define BUSCSR_SERR 0x00020000 /* error on MSTATUS */
+#define BUSCSR_DBLE 0x00010000 /* double M-bus error */
+
+#define BUSCSR_RESET 0xffff0000 /* reset all conditions */
+
+/*
+ * FBIC control and status
+ */
+#define FBICSR_MFMD_MASK 0xc0000000 /* manufacturing mode */
+#define FBICSR_CMISS 0x08000000 /* CVAX cache miss */
+#define FBICSR_EXCAEN 0x04000000 /* external cache enable */
+#define FBICSR_HALTCPU 0x02000000 /* CVAX halt */
+#define FBICSR_RESET 0x01000000 /* CVAX reset */
+#define FBICSR_IRQEN_MASK 0x00f00000 /* interrupt enables */
+#define FBICSR_IRQEN_SHIFT 20
+#define FBIC_DEVIRQ0 0
+#define FBIC_DEVIRQ1 1
+#define FBIC_DEVIRQ2 2
+#define FBIC_DEVIRQ3 3
+#define FBIC_DEVIRQMAX 4
+#define FBICSR_IRQC2M_MASK 0x000f0000 /* interrupt direction */
+#define FBICSR_IRQC2M_SHIFT 16
+#define FBICSR_LEDS_MASK 0x00003f00 /* module leds, active low */
+#define FBICSR_LEDS_SHIFT 8
+#define FBICSR_HALTEN 0x00000080 /* halt enable */
+#define FBICSR_TSTFNC_MASK 0x0000007e /* test function */
+#define FBICSR_TSTFNC_SHIFT 1
+#define TSTFNC_NORMAL_MODE 0x1f /* normal operation */
+#define FBICSR_CDPE 0x00000001 /* CVAX parity enable */
+
+/*
+ * I/O Range
+ *
+ * This programs an M-bus address range which in the global I/O space, which
+ * is answered by this module. Note that the upper bit in the match field
+ * must be set, for the address to be in the I/O space; this is why the
+ * upper bit of the mask field acts as an enable.
+ */
+#define RANGE_MATCH 0xffff0000 /* address bits 31:16 */
+#define RANGE_ENABLE 0x00008000 /* mask address bit 31 */
+#define RANGE_MASK 0x00007fff /* address bits 30:16 */
+
+/*
+ * Interprocessor and device interrupts
+ */
+#define IPDVINT_IPL17 0x08000000 /* trigger IRQ3 */
+#define IPDVINT_IPL16 0x04000000 /* trigger IRQ2 */
+#define IPDVINT_IPL15 0x02000000 /* trigger IRQ1 */
+#define IPDVINT_IPL14 0x01000000 /* trigger IRQ0 */
+#define IPDVINT_IPUNIT 0x00020000 /* interrupts CPU */
+#define IPDVINT_DEVICE 0x00010000 /* interrupts M-bus */
+#define IPDVINT_VECTOR_MASK 0x0000fff0 /* interrupt vector */
+#define IPDVINT_VECTOR_SHIFT 4
+#define IPDVINT_IPL_MASK 0x0000000c /* interrupt ipl */
+#define IPDVINT_IPL_SHIFT 2
+
+/*
+ * CPUID (also EPR 14)
+ */
+#define CPUID_MID_MASK 0x0000001c /* slot mid */
+#define CPUID_MID_SHIFT 2
+#define CPUID_PROC_MASK 0x00000003 /* slot processor id */
+#define CPUID_PROC_SHIFT 0
+#define CPUID_PROC_0 0x00
+#define CPUID_PROC_1 0x03
+
+/*
+ * FMCM registers (not FBIC compatible except for MODTYPE and BUSCSR)
+ */
+
+/* module identification */
+#define FMCM_MODTYPE 0x1fc
+/* M-bus error status */
+/* NOTE: only implements FRZN, ICMD, MDPE, MSPE and MCPE */
+#define FMCM_BUSCSR 0x1f8
+/* FMCM control and status register */
+#define FMCM_FMDCSR 0x1f4
+/* Memory space base address register */
+#define FMCM_BASEADDR 0x1f0
+
+#define FMDCSR_ISOLATE 0x00008000 /* no MABORT on error */
+#define FMDCSR_DIAGNOSTIC_REFRESH_START 0x00004000
+#define FMDCSR_REFRESH_PERIOD_SELECT 0x00002000 /* set: slow (80ns) */
+#define FMDCSR_DISABLE_REFRESH 0x00001000
+
+#define BASEADDR_STARTADDR_MASK 0x7ff00000
+#define BASEADDR_MEMORY_SPACE_ENABLE 0x80000000
+
+/*
+ * Interrupt vector assignments
+ *
+ * Since each FBIC controls four interrupts, and passes the IPI in bits
+ * 3:2 of the vector number, we have to reserve them on 0x10 boundaries.
+ *
+ * Note that this is different from the usual scheme of using bits 5:4
+ * for this purpose.
+ *
+ * CPU boards also use the IPDVINT to have an extra 0x10 range for IPIs.
+ *
+ * To make things simpler, we use a static assignment where the number is
+ * computed from the mid and fbic number (for cpu boards).
+ *
+ * This means the 0x100..0x1fc range is used for M-bus interrupts only.
+ * Q-bus interrupts will use the usual 0x200..0x3fc range.
+ */
+
+#define MBUS_VECTOR_BASE(mid,fbic) (0x100 + (mid) * 0x20 + (fbic) * 0x10)
+#define MBUS_VECTOR_TO_MID(vec) (((vec) - 0x100) >> 5)
+#define MBUS_VECTOR_TO_FBIC(vec) (((vec) & 0x10) >> 4)
+#define MBUS_VECTOR_TO_IRQ(vec) (((vec) & 0xc) >> 2)
diff --git a/sys/arch/vax/mbus/mbusvar.h b/sys/arch/vax/mbus/mbusvar.h
new file mode 100644
index 00000000000..d48fdda3002
--- /dev/null
+++ b/sys/arch/vax/mbus/mbusvar.h
@@ -0,0 +1,33 @@
+/* $OpenBSD: mbusvar.h,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+struct mbus_attach_args {
+ unsigned int maa_mid;
+ uint8_t maa_class;
+ uint8_t maa_subclass;
+ uint8_t maa_interface;
+ uint8_t maa_revision;
+ paddr_t maa_addr;
+ unsigned int maa_vecbase;
+};
+
+extern unsigned int mbus_ioslot;
+
+int mbus_intr_establish(unsigned int, int, int (*)(void *), void *,
+ const char *);
+uint32_t mbus_ddb_hook(int, uint32_t);
diff --git a/sys/arch/vax/mbus/sii_fwio.c b/sys/arch/vax/mbus/sii_fwio.c
new file mode 100644
index 00000000000..f1d329a2121
--- /dev/null
+++ b/sys/arch/vax/mbus/sii_fwio.c
@@ -0,0 +1,163 @@
+/* $OpenBSD: sii_fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_message.h>
+
+#include <vax/dec/siireg.h>
+#include <vax/dec/siivar.h>
+
+struct sii_fwio_softc {
+ struct sii_softc sc_dev;
+ u_char *sc_buf;
+};
+
+int sii_fwio_match(struct device *, void *, void *);
+void sii_fwio_attach(struct device *, struct device *, void *);
+
+struct cfattach sii_fwio_ca = {
+ sizeof(struct sii_fwio_softc), sii_fwio_match, sii_fwio_attach
+};
+
+extern struct cfdriver sii_cd;
+
+void sii_fwio_copyfrombuf(void *, u_int, u_char *, int);
+void sii_fwio_copytobuf(void *, u_char *, u_int, int);
+int sii_fwio_intr(void *);
+
+int
+sii_fwio_match(struct device *parent, void *vcf, void *aux)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+ return strcmp(faa->faa_dev, sii_cd.cd_name) == 0 ? 1 : 0;
+}
+
+void
+sii_fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+ struct sii_fwio_softc *sfc = (struct sii_fwio_softc *)self;
+ struct sii_softc *sc = &sfc->sc_dev;
+ unsigned int vec;
+
+ vec = faa->faa_vecbase + FBIC_DEVIRQ0 * 4;
+ printf(" vec %d", vec);
+
+ /*
+ * Map registers.
+ */
+
+ sc->sc_regs =
+ (SIIRegs *)vax_map_physmem(faa->faa_base + FWIO_SII_REG_OFFSET, 1);
+
+ /*
+ * Map buffers.
+ */
+
+ sfc->sc_buf = (u_char *)uvm_km_valloc(kernel_map, FWIO_SII_BUF_SIZE);
+ if (sfc->sc_buf == NULL) {
+ vax_unmap_physmem(faa->faa_base + FWIO_SII_REG_OFFSET, 1);
+ printf(": can't map buffers\n");
+ return;
+ }
+
+ ioaccess((vaddr_t)sfc->sc_buf, faa->faa_base + FWIO_SII_BUF_OFFSET,
+ FWIO_SII_BUF_SIZE >> VAX_PGSHIFT);
+
+ sc->sii_copytobuf = sii_fwio_copytobuf;
+ sc->sii_copyfrombuf = sii_fwio_copyfrombuf;
+
+ /*
+ * Register interrupt handler.
+ */
+
+ if (mbus_intr_establish(vec, IPL_BIO, sii_fwio_intr, sfc,
+ self->dv_xname) != 0) {
+ vax_unmap_physmem(faa->faa_base + FWIO_SII_REG_OFFSET, 1);
+ uvm_km_free(kernel_map, (vaddr_t)sfc->sc_buf,
+ FWIO_SII_BUF_SIZE);
+ printf(": can't establish interrupt\n");
+ return;
+ }
+
+ /*
+ * Complete attachment.
+ */
+ sc->sc_hostid = 7; /* hardcoded */
+ sii_attach(sc);
+}
+
+int
+sii_fwio_intr(void *v)
+{
+ struct sii_softc *sc = (struct sii_softc *)v;
+ int rc;
+ uint16_t csr;
+
+ /*
+ * FBIC expects edge interrupts, while the sii does level
+ * interrupts. To avoid missing interrupts while servicing,
+ * we disable further device interrupts while servicing.
+ */
+ csr = sc->sc_regs->csr;
+ sc->sc_regs->csr = csr & ~SII_IE;
+
+ rc = sii_intr(v);
+
+ sc->sc_regs->csr = csr;
+
+ return rc;
+}
+
+/*
+ * Copy data between the fixed SCSI buffers. The sii driver only ``knows''
+ * offsets inside the SCSI buffer.
+ */
+
+void
+sii_fwio_copyfrombuf(void *v, u_int offs, u_char *dst, int len)
+{
+ struct sii_fwio_softc *sc = (struct sii_fwio_softc *)v;
+ u_char *src = sc->sc_buf + offs;
+
+ memcpy(dst, src, len);
+}
+
+void
+sii_fwio_copytobuf(void *v, u_char *src, u_int offs, int len)
+{
+ struct sii_fwio_softc *sc = (struct sii_fwio_softc *)v;
+ u_char *dst = sc->sc_buf + offs;
+
+ memcpy(dst, src, len);
+}
diff --git a/sys/arch/vax/mbus/uba_mbus.c b/sys/arch/vax/mbus/uba_mbus.c
new file mode 100644
index 00000000000..ed78ffdcf2b
--- /dev/null
+++ b/sys/arch/vax/mbus/uba_mbus.c
@@ -0,0 +1,174 @@
+/* $OpenBSD: uba_mbus.c,v 1.1 2008/08/18 23:19:25 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+#include <machine/sgmap.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/uba/uba_common.h>
+#include <arch/vax/uba/ubareg.h>
+
+#define QBASIZE (8192 * VAX_NBPG)
+
+void uba_mbus_attach(struct device *, struct device *, void *);
+int uba_mbus_match(struct device *, void *, void *);
+
+const struct cfattach uba_mbus_ca = {
+ sizeof(struct uba_vsoftc), uba_mbus_match, uba_mbus_attach
+};
+
+void uba_mbus_beforescan(struct uba_softc*);
+void uba_mbus_init(struct uba_softc*);
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+uba_mbus_match(struct device *parent, void *vcf, void *aux)
+{
+ struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+
+ /*
+ * There can only be one QBus adapter (because it uses range-mapped
+ * MBus I/O), and it has to be in slot zero for connectivity reasons.
+ */
+ if (maa->maa_mid != 0)
+ return 0;
+
+ if (maa->maa_class == CLASS_BA && maa->maa_interface == INTERFACE_FBIC)
+ return 1;
+
+ return 0;
+}
+
+void
+uba_mbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+ struct uba_vsoftc *sc = (void *)self;
+ paddr_t modaddr;
+ vaddr_t fbic;
+
+ printf(": Q22\n");
+
+ /*
+ * Configure M-Bus I/O range.
+ *
+ * This will map the sgmap at 2008xxxx (QBAMAP), and the doorbell
+ * registers at 2000xxxx (QIOPAGE).
+ */
+ modaddr = MBUS_SLOT_BASE(maa->maa_mid);
+ fbic = vax_map_physmem(modaddr + FBIC_BASE, 1);
+ if (fbic == NULL) {
+ printf("%s: can't setup M-bus range register\n");
+ return;
+ }
+ *(uint32_t *)(fbic + FBIC_RANGE) =
+ (HOST_TO_MBUS(QBAMAP & RANGE_MATCH)) | RANGE_ENABLE |
+ ((QBAMAP ^ QIOPAGE) >> 16);
+ vax_unmap_physmem(fbic, 1);
+
+ /*
+ * There is nothing special to do to enable interrupt routing;
+ * the CQBIC will route Q-bus interrupts to the C-bus, and
+ * mbus(4) has already configured our FBIC interrupt registers
+ * to route C-bus interrupts to the M-bus (whether they are
+ * generated by the FBIC or by the Q-bus), which will make them
+ * visible to the processor.
+ *
+ * Note that we do not enable the boards' FBIC memory error
+ * interrupt yet.
+ */
+
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_beforescan = uba_mbus_beforescan;
+ sc->uv_sc.uh_ubainit = uba_mbus_init;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = QBAMAP; /* Physical address of map registers */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, QIOPAGE);
+}
+
+/*
+ * Called when the CQBIC is set up; to enable DMA access from
+ * Q-bus devices to main memory.
+ */
+void
+uba_mbus_beforescan(sc)
+ struct uba_softc *sc;
+{
+ bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE);
+}
+
+void
+uba_mbus_init(sc)
+ struct uba_softc *sc;
+{
+ DELAY(500000);
+ uba_mbus_beforescan(sc);
+}
diff --git a/sys/arch/vax/uba/ubareg.h b/sys/arch/vax/uba/ubareg.h
index f225c6e9dc0..4870197817f 100644
--- a/sys/arch/vax/uba/ubareg.h
+++ b/sys/arch/vax/uba/ubareg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ubareg.h,v 1.12 2008/08/18 23:10:39 miod Exp $ */
+/* $OpenBSD: ubareg.h,v 1.13 2008/08/18 23:19:27 miod Exp $ */
/* $NetBSD: ubareg.h,v 1.11 2000/01/24 02:40:36 matt Exp $ */
/*-
@@ -63,7 +63,7 @@
#define DW730 3 /* has adaptor regs, no sr: 750, 730 */
#endif
-#if VAX630 || VAX650 || VAX660 || VAX670
+#if VAX630 || VAX650 || VAX660 || VAX670 || VAX60
#define QBA 4 /* 22-bit Q-bus, no adaptor regs: uVAX II */
#endif
@@ -190,7 +190,7 @@ struct uba_regs {
* Symbolic BUS addresses for UBAs.
*/
-#if VAX630 || VAX650
+#if VAX630 || VAX650 || VAX60
#define QBAMAP 0x20088000
#define QMEM 0x30000000
#define QIOPAGE 0x20000000
diff --git a/sys/arch/vax/vax/autoconf.c b/sys/arch/vax/vax/autoconf.c
index ca7153c4732..82d551c8439 100644
--- a/sys/arch/vax/vax/autoconf.c
+++ b/sys/arch/vax/vax/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.30 2008/07/21 04:35:54 todd Exp $ */
+/* $OpenBSD: autoconf.c,v 1.31 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: autoconf.c,v 1.45 1999/10/23 14:56:05 ragge Exp $ */
/*
@@ -51,9 +51,11 @@
#include <machine/ioa.h>
#include <machine/ka820.h>
#include <machine/ka750.h>
-#include <machine/ka650.h>
#include <machine/clock.h>
#include <machine/rpb.h>
+#ifdef VAX60
+#include <vax/mbus/mbusreg.h>
+#endif
#include <dev/cons.h>
@@ -64,14 +66,13 @@
#include <vax/bi/bireg.h>
void dumpconf(void); /* machdep.c */
-void gencnslask(void);
struct cpu_dep *dep_call;
int mastercpu; /* chief of the system */
struct device *bootdv;
-int booted_partition; /* defaults to 0 (aka 'a' partition */
+int booted_partition; /* defaults to 0 (aka 'a' partition) */
void
cpu_configure()
@@ -340,27 +341,29 @@ booted_sd(struct device *dev, void *aux)
/* Is this a SCSI device? */
if (jmfr("sd", dev, BDEV_SD) && jmfr("cd", dev, BDEV_SD) &&
- jmfr("sd", dev, BDEV_SDN) && jmfr("cd", dev, BDEV_SDN))
+ jmfr("sd", dev, BDEV_SDN) && jmfr("cd", dev, BDEV_SDN) &&
+ jmfr("sd", dev, BDEV_SDS) && jmfr("cd", dev, BDEV_SDS))
return 0;
-#ifdef __NetBSD__
- if (sa->sa_periph->periph_channel->chan_bustype->bustype_type !=
- SCSIPI_BUSTYPE_SCSI)
- return 0; /* ``Cannot happen'' */
-#endif
-
if (sa->sa_sc_link->target != rpb.unit)
return 0; /* Wrong unit */
ppdev = dev->dv_parent->dv_parent;
/* VS3100 NCR 53C80 (si) & VS4000 NCR 53C94 (asc) */
- if (((jmfr("ncr", ppdev, BDEV_SD) == 0) || /* old name */
+ if (((jmfr("ncr", ppdev, BDEV_SD) == 0) || /* old name */
(jmfr("asc", ppdev, BDEV_SD) == 0) ||
(jmfr("asc", ppdev, BDEV_SDN) == 0)) &&
(ppdev->dv_cfdata->cf_loc[0] == rpb.csrphy))
return 1;
+#ifdef VAX60
+ /* VS35x0 (sii) */
+ if (jmfr("sii", ppdev, BDEV_SDS) == 0 && rpb.csrphy ==
+ MBUS_SLOT_BASE(ppdev->dv_parent->dv_cfdata->cf_loc[0]))
+ return 1;
+#endif
+
return 0; /* Where did we come from??? */
}
#endif
diff --git a/sys/arch/vax/vax/clock.c b/sys/arch/vax/vax/clock.c
index 1990ebe7c0b..085e580f1d7 100644
--- a/sys/arch/vax/vax/clock.c
+++ b/sys/arch/vax/vax/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.20 2008/08/15 22:41:48 miod Exp $ */
+/* $OpenBSD: clock.c,v 1.21 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: clock.c,v 1.35 2000/06/04 06:16:58 matt Exp $ */
/*
* Copyright (c) 1995 Ludd, University of Lule}, Sweden.
@@ -44,9 +44,6 @@
#include <machine/cpu.h>
#include <machine/uvax.h>
-int yeartonum(int);
-int numtoyear(int);
-
struct evcount clock_intrcnt;
/*
diff --git a/sys/arch/vax/vax/conf.c b/sys/arch/vax/vax/conf.c
index 69f4a90c40c..c142eeb0904 100644
--- a/sys/arch/vax/vax/conf.c
+++ b/sys/arch/vax/vax/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.54 2008/05/14 20:49:48 miod Exp $ */
+/* $OpenBSD: conf.c,v 1.55 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: conf.c,v 1.44 1999/10/27 16:38:54 ragge Exp $ */
/*-
@@ -163,7 +163,7 @@ struct consdev constab[]={
#else
#define NGEN 0
#endif
-#if VAX410 || VAX43 || VAX46 || VAX48 || VAX49 || VAX53
+#if VAX410 || VAX43 || VAX46 || VAX48 || VAX49 || VAX53 || VAX60
#if NDZ > 0
cons_init(dz), /* DZ11-like serial console on VAXstations */
#endif
diff --git a/sys/arch/vax/vax/findcpu.c b/sys/arch/vax/vax/findcpu.c
index bc6a4b65b34..8b6a76f6d4d 100644
--- a/sys/arch/vax/vax/findcpu.c
+++ b/sys/arch/vax/vax/findcpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: findcpu.c,v 1.12 2006/08/27 16:55:41 miod Exp $ */
+/* $OpenBSD: findcpu.c,v 1.13 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: findcpu.c,v 1.5 1999/08/23 19:10:43 ragge Exp $ */
/*
* Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden.
@@ -51,7 +51,7 @@ int vax_boardtype; /* machine dependend, combination of SID and SIE */
int vax_cpudata = 0; /* contents of the SID register */
int vax_siedata = 0; /* contents of the SIE register */
-int vax_confdata; /* machine dependend, configuration/setup data */
+int vax_confdata; /* machine dependent, configuration/setup data */
void findcpu(void);
@@ -112,6 +112,9 @@ findcpu(void)
break;
case VAX_BTYP_60:
+ vax_bustype = VAX_MBUS;
+ break;
+
case VAX_BTYP_630:
case VAX_BTYP_650:
case VAX_BTYP_660:
diff --git a/sys/arch/vax/vax/ka60.c b/sys/arch/vax/vax/ka60.c
new file mode 100644
index 00000000000..a8db3f103c7
--- /dev/null
+++ b/sys/arch/vax/vax/ka60.c
@@ -0,0 +1,358 @@
+/* $OpenBSD: ka60.c,v 1.1 2008/08/18 23:19:29 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 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.
+ */
+
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mt. Xinu.
+ *
+ * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)ka650.c 7.7 (Berkeley) 12/16/90
+ */
+
+/*
+ * VAXstation 3500 (KA60) specific code. Based on the KA650 specific code.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <uvm/uvm_extern.h>
+
+#include <machine/cvax.h>
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/psl.h>
+#include <machine/sid.h>
+#include <machine/rpb.h>
+#include <machine/cca.h>
+#include <machine/scb.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+
+int ka60_clkread(time_t);
+void ka60_clkwrite(void);
+void ka60_clrf(void);
+void ka60_conf(void);
+void ka60_halt(void);
+void ka60_hardclock(struct clockframe *);
+void ka60_init(void);
+int ka60_mchk(caddr_t);
+void ka60_memerr(void);
+void ka60_reboot(int);
+
+struct cpu_dep ka60_calls = {
+ ka60_init,
+ ka60_mchk,
+ ka60_memerr,
+ ka60_conf,
+ ka60_clkread,
+ ka60_clkwrite,
+ 3, /* ~VUPS */
+ 2, /* SCB pages */
+#if 0 /* this ought to work, dammit! */
+ cvax_halt,
+ cvax_reboot,
+#else
+ ka60_halt,
+ ka60_reboot,
+#endif
+ ka60_clrf,
+ NULL,
+ ka60_hardclock
+};
+
+void ka60_memwrtmo(void *);
+
+struct cca *cca;
+unsigned int cca_size;
+
+unsigned int ka60cpus = 1;
+uint32_t *ka60_iocsr;
+
+/*
+ * Early system initialization, while still running physical.
+ *
+ * The PROM will have enabled the L2 cache, but each individual
+ * CPU still has its own L1 cache disabled.
+ *
+ * L1 cache configuration is similar to KA650, without external
+ * configuration registers.
+ */
+void
+ka60_init()
+{
+ unsigned int mid;
+ paddr_t fbicaddr;
+ uint32_t modtype, fbicrange;
+ int i;
+
+ /*
+ * Enable CPU cache.
+ */
+ mtpr(CADR_SEN2 | CADR_SEN1 | CADR_CENI | CADR_CEND, PR_CADR);
+
+ cca = (struct cca *)rpb.cca_addr; /* physical!!! */
+ if (cca == NULL) {
+ /*
+ * If things are *that* wrong, stick to 2 cpus and a
+ * monoprocessor kernel, really. We could try looking
+ * for a CCA signature from the top of memory downwards,
+ * or count CPU boards to get the correct number of
+ * processors, but is it really worth doing? I don't
+ * think we are in Kansas anymore anyway...
+ */
+ ka60cpus = 2;
+ } else {
+ cca_size = vax_atop(cca->cca_size);
+
+ /*
+ * Count the other processors.
+ */
+ for (i = 0; i < cca->cca_nproc; i++)
+ if (cca->cca_console & (1 << i))
+ ka60cpus++;
+ }
+
+ snprintf(cpu_model, sizeof cpu_model, "VAXstation 35%d0", ka60cpus);
+
+ /*
+ * Silence memory write timeout errors now.
+ */
+ scb_vecalloc(0x60, ka60_memwrtmo, NULL, 0, NULL);
+
+ /*
+ * We need to find out which M-bus slot contains the I/O
+ * module. This could not have been done before because
+ * we were not able to handle machine check (and thus run
+ * badaddr() on each slot), and this has to be done before
+ * consinit() may try to talk to the serial ports.
+ *
+ * Note that there might be multiple I/O modules in the system.
+ * We do not know which I/O module the PROM will prefer; however
+ * since only one module should be configured to map the SSC at
+ * its preferred address, it is possible to find out which one
+ * has been selected.
+ */
+
+ for (mid = 0; mid < MBUS_SLOT_MAX; mid++) {
+ fbicaddr = MBUS_SLOT_BASE(mid) + FBIC_BASE;
+ if (badaddr((caddr_t)(fbicaddr + FBIC_MODTYPE), 4) != 0)
+ continue;
+ modtype = *(uint32_t *)(fbicaddr + FBIC_MODTYPE);
+ if ((modtype & MODTYPE_CLASS_MASK) >> MODTYPE_CLASS_SHIFT !=
+ CLASS_IO)
+ continue;
+
+ mbus_ioslot = mid;
+
+ fbicrange = *(uint32_t *)(fbicaddr + FBIC_RANGE);
+ if (fbicrange ==
+ ((HOST_TO_MBUS(CVAX_SSC) & RANGE_MATCH) | RANGE_ENABLE))
+ break;
+ }
+
+ if ((int)mbus_ioslot < 0) {
+ /*
+ * This shouldn't happen. Try mid #5 (enclosure slot #4) as a
+ * supposedly sane default.
+ */
+ mbus_ioslot = 5;
+ }
+}
+
+/*
+ * Early system initialization, while running virtual, and before
+ * devices are probed.
+ */
+void
+ka60_conf()
+{
+ printf("cpu0: KA60\n");
+
+ cvax_ssc_ptr = (void *)vax_map_physmem(CVAX_SSC, 3);
+
+ /*
+ * Remap the CCA now we're running virtual.
+ */
+ if (cca != NULL)
+ cca = (void *)vax_map_physmem((paddr_t)cca, cca_size);
+
+ /*
+ * Map the IOCSR register of the main I/O module, and enable
+ * CPU clock. We'll need this mapping for reset as well.
+ */
+ ka60_iocsr = (uint32_t *)vax_map_physmem(MBUS_SLOT_BASE(mbus_ioslot) +
+ FWIO_IOCSR_OFFSET, 1);
+ if (ka60_iocsr == 0)
+ panic("can not map IOCSR");
+
+ *ka60_iocsr |= FWIO_IOCSR_CLKIEN | FWIO_IOCSR_MRUN | FWIO_IOCSR_CNSL;
+}
+
+/*
+ * Corrected memory error trap.
+ */
+void
+ka60_memerr()
+{
+ printf("cpu0: corrected memory error\n");
+ /*
+ * Need to peek at the M-bus error logs, display anything
+ * interesting, and clear them.
+ */
+}
+
+/*
+ * Machine check trap.
+ */
+int
+ka60_mchk(caddr_t mcef)
+{
+ struct cvax_mchk_frame *mcf = (struct cvax_mchk_frame *)mcef;
+ u_int type = mcf->cvax_summary;
+ const char *descr;
+
+ printf("machine check %x", type);
+ descr = cvax_mchk_descr(type);
+ if (descr != NULL)
+ printf(": %s", descr);
+ printf("\n\tvap %x istate1 %x istate2 %x pc %x psl %x\n",
+ mcf->cvax_mrvaddr, mcf->cvax_istate1, mcf->cvax_istate2,
+ mcf->cvax_pc, mcf->cvax_psl);
+
+ return MCHK_PANIC;
+}
+
+/*
+ * Clock routines. They need to access the TODR through the SSC.
+ */
+int
+ka60_clkread(time_t base)
+{
+ unsigned klocka = cvax_ssc_ptr->ssc_todr;
+
+ /*
+ * Sanity check.
+ */
+ if (klocka < TODRBASE) {
+ if (klocka == 0) {
+ printf("TODR stopped");
+ cvax_ssc_ptr->ssc_todr = 1; /* spin it */
+ } else
+ printf("TODR too small");
+ return CLKREAD_BAD;
+ }
+
+ time.tv_sec = yeartonum(numtoyear(base)) + (klocka - TODRBASE) / 100;
+ return CLKREAD_OK;
+}
+
+void
+ka60_clkwrite()
+{
+ unsigned tid = time.tv_sec, bastid;
+
+ bastid = tid - yeartonum(numtoyear(tid));
+ cvax_ssc_ptr->ssc_todr = (bastid * 100) + TODRBASE;
+}
+
+void
+ka60_halt()
+{
+ printf("system halted.\n");
+ asm("halt");
+}
+
+void
+ka60_reboot(arg)
+ int arg;
+{
+ printf("resetting system...\n");
+ delay(500000);
+ *ka60_iocsr |= FWIO_IOCSR_RSTWS;
+}
+
+/*
+ * Probing empty M-bus slots causes this vector to be triggered.
+ *
+ * We get one after the first spl0(), if probing for the console
+ * slot caused us to look at empty slots, and then one per empty
+ * slot during autoconf.
+ *
+ * There shouldn't be any such error after autoconf, though.
+ */
+void
+ka60_memwrtmo(void *arg)
+{
+ /* do nothing */
+}
+
+void
+ka60_clrf(void)
+{
+ /*
+ * Restore the memory write timeout vector.
+ */
+ scb_vecalloc(0x60, scb_stray, (void *)0x60, SCB_ISTACK, NULL);
+}
+
+/*
+ * SSC clock interrupts come at level 0x16, which is not enough for
+ * our needs, so raise the level here before invoking hardclock().
+ */
+void
+ka60_hardclock(struct clockframe *cf)
+{
+ int s;
+
+ s = splclock();
+ hardclock(cf);
+ splx(s);
+}
diff --git a/sys/arch/vax/vax/locore.c b/sys/arch/vax/vax/locore.c
index 7181a51d144..d9e457574cc 100644
--- a/sys/arch/vax/vax/locore.c
+++ b/sys/arch/vax/vax/locore.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.c,v 1.33 2008/03/30 18:25:13 miod Exp $ */
+/* $OpenBSD: locore.c,v 1.34 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: locore.c,v 1.43 2000/03/26 11:39:45 ragge Exp $ */
/*
* Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden.
@@ -50,11 +50,13 @@
#include <machine/pmap.h>
#include <machine/nexus.h>
#include <machine/rpb.h>
+#include <machine/cca.h>
void start(struct rpb *);
void main(void);
extern paddr_t avail_end;
+extern int physmem;
paddr_t esym;
u_int proc0paddr;
char cpu_model[100];
@@ -78,6 +80,7 @@ extern struct cpu_dep ka650_calls;
extern struct cpu_dep ka660_calls;
extern struct cpu_dep ka670_calls;
extern struct cpu_dep ka680_calls;
+extern struct cpu_dep ka60_calls;
extern struct cpu_dep vxt_calls;
/*
@@ -90,6 +93,7 @@ void
start(struct rpb *prpb)
{
extern vaddr_t scratch;
+ int preserve_cca = 0;
mtpr(AST_NO, PR_ASTLVL); /* Turn off ASTs */
@@ -301,6 +305,13 @@ start(struct rpb *prpb)
strlcpy(cpu_model, "VAX 8200", sizeof cpu_model);
break;
#endif
+#ifdef VAX60
+ case VAX_BTYP_60:
+ dep_call = &ka60_calls;
+ preserve_cca = 1;
+ /* cpu_model will be set in ka60_init */
+ break;
+#endif
default:
/* CPU not supported, just give up */
asm("halt");
@@ -331,6 +342,33 @@ start(struct rpb *prpb)
avail_end += VAX_NBPG * 128;
boothowto = prpb->rpb_bootr5;
+ physmem = atop(avail_end);
+
+ /*
+ * If we need to use the Console Communication Area, make sure
+ * we will not stomp over it.
+ *
+ * On KA60 systems, the PROM apparently forgets to keep the CCA
+ * out of the reported memory size. It's no real surprise, as
+ * the memory bitmap pointed to by the CCA reports all physical
+ * memory (including itself and the CCA) as available!
+ * (which means the bitmap is not worth looking at either)
+ */
+
+ if (preserve_cca) {
+ if (prpb->cca_addr != 0 && avail_end > prpb->cca_addr) {
+ struct cca *cca = (struct cca *)prpb->cca_addr;
+
+ /*
+ * XXX Should validate the CCA image here.
+ */
+
+ avail_end = prpb->cca_addr;
+ if (cca->cca_bitmap != 0 && avail_end > cca->cca_bitmap)
+ avail_end = cca->cca_bitmap;
+ }
+ }
+
avail_end = TRUNC_PAGE(avail_end); /* be sure */
proc0.p_addr = (struct user *)proc0paddr; /* XXX */
diff --git a/sys/arch/vax/vax/machdep.c b/sys/arch/vax/vax/machdep.c
index 847792aeb58..1eaa5fb3ac9 100644
--- a/sys/arch/vax/vax/machdep.c
+++ b/sys/arch/vax/vax/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.98 2008/08/18 23:08:57 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.99 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: machdep.c,v 1.108 2000/09/13 15:00:23 thorpej Exp $ */
/*
@@ -174,7 +174,6 @@ cpu_startup()
caddr_t v;
int sz;
vaddr_t minaddr, maxaddr;
- extern unsigned int avail_end;
extern char cpu_model[];
/*
@@ -190,9 +189,8 @@ cpu_startup()
if (dep_call->cpu_conf)
(*dep_call->cpu_conf)();
- printf("real mem = %u (%uMB)\n", avail_end,
- avail_end/1024/1024);
- physmem = atop(avail_end);
+ printf("real mem = %u (%uMB)\n", ptoa(physmem),
+ ptoa(physmem)/1024/1024);
mtpr(AST_NO, PR_ASTLVL);
spl0();
@@ -228,7 +226,7 @@ cpu_startup()
exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
-#if VAX46 || VAX48 || VAX49 || VAX53
+#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60
/*
* Allocate a submap for physio. This map effectively limits the
* number of processes doing physio at any one time.
@@ -237,7 +235,8 @@ cpu_startup()
* can perform address translation, do not need this.
*/
if (vax_boardtype == VAX_BTYP_46 || vax_boardtype == VAX_BTYP_48 ||
- vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_1303)
+ vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_1303 ||
+ vax_boardtype == VAX_BTYP_60)
phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
VM_PHYS_SIZE, 0, FALSE, NULL);
#endif
@@ -283,10 +282,7 @@ dumpconf(void)
if (nblks <= ctod(1))
return;
- /*
- * XXX include the final RAM page which is not included in physmem.
- */
- dumpsize = physmem + 1;
+ dumpsize = physmem;
if (dumpsize > atop(dbtob(nblks - dumplo)))
dumpsize = atop(dbtob(nblks - dumplo));
else if (dumplo == 0)
diff --git a/sys/arch/vax/vax/pmap.c b/sys/arch/vax/vax/pmap.c
index 24b71bf7980..79dff3b8e87 100644
--- a/sys/arch/vax/vax/pmap.c
+++ b/sys/arch/vax/vax/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.46 2008/08/15 22:38:23 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.47 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: pmap.c,v 1.74 1999/11/13 21:32:25 matt Exp $ */
/*
* Copyright (c) 1994, 1998, 1999 Ludd, University of Lule}, Sweden.
@@ -185,7 +185,7 @@ pmap_bootstrap()
avail_start = scratch + 4 * VAX_NBPG - KERNBASE;
/* Kernel message buffer */
- avail_end -= MSGBUFSIZE;
+ avail_end -= round_page(MSGBUFSIZE);
msgbufp = (void *)(avail_end + KERNBASE);
msgbufp->msg_magic = MSG_MAGIC-1; /* ensure that it will be zeroed */
@@ -257,9 +257,8 @@ pmap_bootstrap()
/*
* Now everything should be complete, start virtual memory.
*/
- uvm_page_physload(avail_start >> PGSHIFT, avail_end >> PGSHIFT,
- avail_start >> PGSHIFT, avail_end >> PGSHIFT,
- VM_FREELIST_DEFAULT);
+ uvm_page_physload(atop(avail_start), atop(avail_end),
+ atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
mtpr(sysptsize, PR_SLR);
rpb.sbr = mfpr(PR_SBR);
rpb.slr = mfpr(PR_SLR);
@@ -299,7 +298,7 @@ pmap_steal_memory(size, vstartp, vendp)
#endif
/*
- * A vax only have one segment of memory.
+ * A vax only has one segment of memory.
*/
v = (vm_physmem[0].avail_start << PGSHIFT) | KERNBASE;
diff --git a/sys/arch/vax/vax/scb.c b/sys/arch/vax/vax/scb.c
index c8260484898..1150b9f3a57 100644
--- a/sys/arch/vax/vax/scb.c
+++ b/sys/arch/vax/vax/scb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scb.c,v 1.5 2004/07/07 23:10:46 deraadt Exp $ */
+/* $OpenBSD: scb.c,v 1.6 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: scb.c,v 1.12 2000/06/04 06:16:59 matt Exp $ */
/*
* Copyright (c) 1999 Ludd, University of Lule}, Sweden.
@@ -49,7 +49,6 @@
struct scb *scb;
struct ivec_dsp *scb_vec;
-static void scb_stray(void *);
static volatile int vector, ipl, gotintr;
/*
@@ -70,7 +69,7 @@ scb_init(paddr_t avail_start)
/* Init the whole SCB with interrupt catchers */
for (i = 0; i < (scb_size * VAX_NBPG)/4; i++) {
ivec[i] = &scb_vec[i];
- (int)ivec[i] |= 1; /* On istack, please */
+ (int)ivec[i] |= SCB_ISTACK; /* On istack, please */
scb_vec[i] = idsptch;
scb_vec[i].hoppaddr = scb_stray;
scb_vec[i].pushlarg = (void *) (i * 4);
@@ -85,6 +84,7 @@ scb_init(paddr_t avail_start)
for (i = 0; i < 64; i++)
if (old[i])
ivec[i] = old[i];
+
/* Last action: set the SCB */
mtpr(avail_start, PR_SCBB);
diff --git a/sys/arch/vax/vax/vm_machdep.c b/sys/arch/vax/vax/vm_machdep.c
index 2a2daf1a21d..03a6d9e6522 100644
--- a/sys/arch/vax/vax/vm_machdep.c
+++ b/sys/arch/vax/vax/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.37 2008/02/16 22:59:34 miod Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.38 2008/08/18 23:19:29 miod Exp $ */
/* $NetBSD: vm_machdep.c,v 1.67 2000/06/29 07:14:34 mrg Exp $ */
/*
@@ -266,7 +266,7 @@ vmapbuf(bp, len)
struct buf *bp;
vsize_t len;
{
-#if VAX46 || VAX48 || VAX49 || VAX53
+#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60
vaddr_t faddr, taddr, off;
paddr_t pa;
struct proc *p;
@@ -303,7 +303,7 @@ vunmapbuf(bp, len)
struct buf *bp;
vsize_t len;
{
-#if VAX46 || VAX48 || VAX49 || VAX53
+#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60
vaddr_t addr, off;
if (phys_map == NULL)