summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorSteve Murphree <smurph@cvs.openbsd.org>2000-01-25 04:18:19 +0000
committerSteve Murphree <smurph@cvs.openbsd.org>2000-01-25 04:18:19 +0000
commite40439a3e2496cea86c39162e0063dee4d8e547e (patch)
tree7894a4ed2821db7fdd4280362beffca3b5467f45 /sys/arch
parente20b3a79bd049247aa2a4a09532c4d5d9f7734af (diff)
Added support for MVME328 SCSI VME board.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/mvme68k/conf/GENERIC12
-rw-r--r--sys/arch/mvme68k/conf/MINIROOT11
-rw-r--r--sys/arch/mvme68k/conf/MVME16216
-rw-r--r--sys/arch/mvme68k/conf/MVME16715
-rw-r--r--sys/arch/mvme68k/conf/MVME17715
-rw-r--r--sys/arch/mvme68k/conf/files.mvme68k8
-rw-r--r--sys/arch/mvme68k/dev/vs.c1025
-rw-r--r--sys/arch/mvme68k/dev/vsdma.c188
-rw-r--r--sys/arch/mvme68k/dev/vsreg.h756
-rw-r--r--sys/arch/mvme68k/dev/vsvar.h132
10 files changed, 2171 insertions, 7 deletions
diff --git a/sys/arch/mvme68k/conf/GENERIC b/sys/arch/mvme68k/conf/GENERIC
index 5a01c6ecd3c..6a3123fe638 100644
--- a/sys/arch/mvme68k/conf/GENERIC
+++ b/sys/arch/mvme68k/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.12 2000/01/24 05:20:53 smurph Exp $
+# $OpenBSD: GENERIC,v 1.13 2000/01/25 04:18:17 smurph Exp $
machine mvme68k m68k
@@ -71,10 +71,18 @@ sram0 at mainbus0 addr 0xffe00000
bugtty0 at mainbus0
vmes0 at vme0
+
+vs* at vmes0 addr 0xffff9000 ipl 2 vec 0x80 len 0x800
+vs* at vmes0 addr 0xffff9800 ipl 2 vec 0x82 len 0x800
+vs* at vmes0 addr 0xffff4800 ipl 2 vec 0x84 len 0x800
+vs* at vmes0 addr 0xffff5800 ipl 2 vec 0x86 len 0x800
+vs* at vmes0 addr 0xffff7000 ipl 2 vec 0x88 len 0x800
+vs* at vmes0 addr 0xffff7800 ipl 2 vec 0x8a len 0x800
+
le* at vmes0 addr 0xffff1200 ipl 1 vec 0x74 len 0x100
le* at vmes0 addr 0xffff1400 ipl 1 vec 0x75 len 0x100
le* at vmes0 addr 0xffff1600 ipl 1 vec 0x76 len 0x100
-le* at vmes0 addr 0xffffd200 ipl 1 vec 0x76 len 0x100
+le* at vmes0 addr 0xffffd200 ipl 1 vec 0x77 len 0x100
vmel0 at vme0
diff --git a/sys/arch/mvme68k/conf/MINIROOT b/sys/arch/mvme68k/conf/MINIROOT
index cf7c56778a3..207f623096e 100644
--- a/sys/arch/mvme68k/conf/MINIROOT
+++ b/sys/arch/mvme68k/conf/MINIROOT
@@ -1,4 +1,4 @@
-# $OpenBSD: MINIROOT,v 1.4 2000/01/24 05:20:53 smurph Exp $
+# $OpenBSD: MINIROOT,v 1.5 2000/01/25 04:18:17 smurph Exp $
machine mvme68k m68k
@@ -70,6 +70,15 @@ sram0 at mainbus0 addr 0xffe00000
bugtty0 at mainbus0
vmes0 at vme0
+
+vs* at vmes0 addr 0xffff9000 ipl 2 vec 0x80 len 0x800
+vs* at vmes0 addr 0xffff9800 ipl 2 vec 0x82 len 0x800
+vs* at vmes0 addr 0xffff4800 ipl 2 vec 0x84 len 0x800
+vs* at vmes0 addr 0xffff5800 ipl 2 vec 0x86 len 0x800
+vs* at vmes0 addr 0xffff7000 ipl 2 vec 0x88 len 0x800
+vs* at vmes0 addr 0xffff7800 ipl 2 vec 0x8a len 0x800
+
+
vmel0 at vme0
scsibus* at wdsc?
diff --git a/sys/arch/mvme68k/conf/MVME162 b/sys/arch/mvme68k/conf/MVME162
index cf3ec08bfd3..8f42ae90010 100644
--- a/sys/arch/mvme68k/conf/MVME162
+++ b/sys/arch/mvme68k/conf/MVME162
@@ -1,4 +1,4 @@
-# $OpenBSD: MVME162,v 1.10 1997/03/31 00:23:53 downsj Exp $
+# $OpenBSD: MVME162,v 1.11 2000/01/25 04:18:17 smurph Exp $
machine mvme68k m68k
@@ -93,6 +93,19 @@ fooip* at ipic? manu 0x11 prod 0x22 ipl 1
#bugtty0 at mainbus0
vmes0 at vme0
+
+vs* at vmes0 addr 0xffff9000 ipl 2 vec 0x80 len 0x800
+vs* at vmes0 addr 0xffff9800 ipl 2 vec 0x82 len 0x800
+vs* at vmes0 addr 0xffff4800 ipl 2 vec 0x84 len 0x800
+vs* at vmes0 addr 0xffff5800 ipl 2 vec 0x86 len 0x800
+vs* at vmes0 addr 0xffff7000 ipl 2 vec 0x88 len 0x800
+vs* at vmes0 addr 0xffff7800 ipl 2 vec 0x8a len 0x800
+
+le* at vmes0 addr 0xffff1200 ipl 1 vec 0x74 len 0x100
+le* at vmes0 addr 0xffff1400 ipl 1 vec 0x75 len 0x100
+le* at vmes0 addr 0xffff1600 ipl 1 vec 0x76 len 0x100
+le* at vmes0 addr 0xffffd200 ipl 1 vec 0x77 len 0x100
+
vmel0 at vme0
#si0 at vmes0 addr 0xff200000 ipl 2 vec 0x40
@@ -105,3 +118,4 @@ scsibus* at siop?
sd* at scsibus? target ? lun ?
st* at scsibus? target ? lun ?
cd* at scsibus? target ? lun ?
+
diff --git a/sys/arch/mvme68k/conf/MVME167 b/sys/arch/mvme68k/conf/MVME167
index ff63dbe1075..3ad2d6c2bf3 100644
--- a/sys/arch/mvme68k/conf/MVME167
+++ b/sys/arch/mvme68k/conf/MVME167
@@ -1,4 +1,4 @@
-# $OpenBSD: MVME167,v 1.10 1997/03/31 00:23:54 downsj Exp $
+# $OpenBSD: MVME167,v 1.11 2000/01/25 04:18:17 smurph Exp $
machine mvme68k m68k
@@ -92,6 +92,19 @@ sram0 at mainbus0 addr 0xffe00000
#bugtty0 at mainbus0
vmes0 at vme0
+
+vs* at vmes0 addr 0xffff9000 ipl 2 vec 0x80 len 0x800
+vs* at vmes0 addr 0xffff9800 ipl 2 vec 0x82 len 0x800
+vs* at vmes0 addr 0xffff4800 ipl 2 vec 0x84 len 0x800
+vs* at vmes0 addr 0xffff5800 ipl 2 vec 0x86 len 0x800
+vs* at vmes0 addr 0xffff7000 ipl 2 vec 0x88 len 0x800
+vs* at vmes0 addr 0xffff7800 ipl 2 vec 0x8a len 0x800
+
+le* at vmes0 addr 0xffff1200 ipl 1 vec 0x74 len 0x100
+le* at vmes0 addr 0xffff1400 ipl 1 vec 0x75 len 0x100
+le* at vmes0 addr 0xffff1600 ipl 1 vec 0x76 len 0x100
+le* at vmes0 addr 0xffffd200 ipl 1 vec 0x77 len 0x100
+
vmel0 at vme0
#si0 at vmes0 addr 0xff200000 ipl 2 vec 0x40
diff --git a/sys/arch/mvme68k/conf/MVME177 b/sys/arch/mvme68k/conf/MVME177
index 35cc007fbd5..1101017d638 100644
--- a/sys/arch/mvme68k/conf/MVME177
+++ b/sys/arch/mvme68k/conf/MVME177
@@ -1,4 +1,4 @@
-# $OpenBSD: MVME177,v 1.1 2000/01/06 03:28:24 smurph Exp $
+# $OpenBSD: MVME177,v 1.2 2000/01/25 04:18:17 smurph Exp $
machine mvme68k m68k
@@ -44,6 +44,19 @@ sram0 at mainbus0 addr 0xffe00000
bugtty0 at mainbus0
vmes0 at vme0
+
+vs* at vmes0 addr 0xffff9000 ipl 2 vec 0x80 len 0x800
+vs* at vmes0 addr 0xffff9800 ipl 2 vec 0x82 len 0x800
+vs* at vmes0 addr 0xffff4800 ipl 2 vec 0x84 len 0x800
+vs* at vmes0 addr 0xffff5800 ipl 2 vec 0x86 len 0x800
+vs* at vmes0 addr 0xffff7000 ipl 2 vec 0x88 len 0x800
+vs* at vmes0 addr 0xffff7800 ipl 2 vec 0x8a len 0x800
+
+le* at vmes0 addr 0xffff1200 ipl 1 vec 0x74 len 0x100
+le* at vmes0 addr 0xffff1400 ipl 1 vec 0x75 len 0x100
+le* at vmes0 addr 0xffff1600 ipl 1 vec 0x76 len 0x100
+le* at vmes0 addr 0xffffd200 ipl 1 vec 0x77 len 0x100
+
vmel0 at vme0
scsibus* at siop?
diff --git a/sys/arch/mvme68k/conf/files.mvme68k b/sys/arch/mvme68k/conf/files.mvme68k
index 577bcf1987c..90ef30e250e 100644
--- a/sys/arch/mvme68k/conf/files.mvme68k
+++ b/sys/arch/mvme68k/conf/files.mvme68k
@@ -1,4 +1,4 @@
-# $OpenBSD: files.mvme68k,v 1.12 2000/01/24 05:20:53 smurph Exp $
+# $OpenBSD: files.mvme68k,v 1.13 2000/01/25 04:18:17 smurph Exp $
# config file for mvme68k
@@ -142,3 +142,9 @@ device wl: tty
attach wl at vmes
file arch/mvme68k/dev/wl.c wl needs-count
+file arch/mvme88k/dev/memdevs.c nvram | sram
+
+device vs: scsi
+attach vs at vmes
+file arch/mvme68k/dev/vs.c vs
+file arch/mvme68k/dev/vsdma.c vs
diff --git a/sys/arch/mvme68k/dev/vs.c b/sys/arch/mvme68k/dev/vs.c
new file mode 100644
index 00000000000..c57eb483c54
--- /dev/null
+++ b/sys/arch/mvme68k/dev/vs.c
@@ -0,0 +1,1025 @@
+/* $OpenBSD: vs.c,v 1.1 2000/01/25 04:18:17 smurph Exp $ */
+
+/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * MVME328 scsi adaptor driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <machine/autoconf.h>
+#include <machine/param.h>
+
+#define PAGESIZE 4096 /* should get this out of a header? XXX - smurph */
+#if defined(MVME187) || defined(MVME188) || defined(MVME197)
+ #include <mvme88k/dev/vsreg.h>
+ #include <mvme88k/dev/vsvar.h>
+ #include "machine/mmu.h"
+ #define ROUND_PAGE m88k_round_page
+ #define TRUNC_PAGE m88k_trunc_page
+#else
+ #include <mvme68k/dev/vsreg.h>
+ #include <mvme68k/dev/vsvar.h>
+ #define ROUND_PAGE m68k_round_page
+ #define TRUNC_PAGE m68k_trunc_page
+#endif /* defined(MVME187) || defined(MVME188) || defined(MVME197) */
+
+int vs_checkintr __P((struct vs_softc *, struct scsi_xfer *, int *));
+int vs_chksense __P((struct scsi_xfer *));
+void vs_reset __P((struct vs_softc *));
+void vs_resync __P((struct vs_softc *));
+void vs_initialize __P((struct vs_softc *));
+int vs_intr __P((struct vs_softc *));
+int vs_poll __P((struct vs_softc *, struct scsi_xfer *));
+void vs_scsidone __P((struct scsi_xfer *, int));
+M328_CQE * vs_getcqe __P((struct vs_softc *));
+M328_IOPB * vs_getiopb __P((struct vs_softc *));
+
+extern int cold;
+extern u_int kvtop();
+/*
+ * 16 bit 's' memory functions. MVME328 is a D16 board.
+ * We must program with that in mind or else...
+ * bcopy/bzero (the 'b' meaning byte) is implemented in
+ * 32 bit operations for speed, so thay are not really
+ * 'byte' operations at all!! MVME1x7 can be set up to
+ * handle D32 -> D16 read/writes via VMEChip2 Address
+ * modifiers, however MVME188 can not. These next two
+ * functions insure 16 bit copy/zero operations. The
+ * structures are all implemented with 16 bit or less
+ * types. smurph
+ */
+
+void
+scopy(void *src, void *dst, unsigned short cnt)
+{
+ register unsigned short volatile *x, *y, z;
+
+ z = cnt >> 1;
+ x = (unsigned short *) src;
+ y = (unsigned short *) dst;
+
+ while (z--) {
+ *y++ = *x++;
+ }
+}
+
+void
+szero(void *src, u_long cnt)
+{
+ register unsigned short *source;
+ register unsigned short zero = 0;
+ register unsigned short z;
+
+ source = (unsigned short *) src;
+ z = cnt >> 1;
+
+ while (z--) {
+ *source++ = zero;
+ }
+ return;
+}
+
+
+
+
+
+/*
+ * default minphys routine for MVME328 based controllers
+ */
+void
+vs_minphys(bp)
+struct buf *bp;
+{
+ /*
+ * No max transfer at this level.
+ */
+ minphys(bp);
+}
+
+int do_vspoll(sc, to)
+struct vs_softc *sc;
+int to;
+{
+ int i;
+ if (to <= 0 ) to = 50000;
+ /* use cmd_wait values? */
+ i = 50000;
+ /*spl0();*/
+ while (!(CRSW & (M_CRSW_CRBV | M_CRSW_CC))) {
+ if (--i <= 0) {
+#ifdef DEBUG
+ printf ("waiting: timeout %d crsw 0x%x\n", to, CRSW);
+#endif
+ i = 50000;
+ --to;
+ if (to <= 0) {
+ /*splx(s);*/
+ vs_reset(sc);
+ vs_resync(sc);
+ printf ("timed out: timeout %d crsw 0x%x\n", to, CRSW);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int
+vs_poll(sc, xs)
+struct vs_softc *sc;
+struct scsi_xfer *xs;
+{
+ M328_CIB *cib = (M328_CIB *)&sc->sc_vsreg->sh_CIB;
+ M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE;
+ M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ M328_IOPB *miopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB;
+ M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
+ M328_CQE *cqep;
+ M328_IOPB *iopb;
+ int i;
+ int status;
+ int s;
+ int to;
+
+ /*s = splbio();*/
+ to = xs->timeout / 1000;
+ for (;;) {
+ if (do_vspoll(sc, to)) break;
+ if (vs_checkintr(sc, xs, &status)) {
+ vs_scsidone(xs, status);
+ }
+ if (CRSW & M_CRSW_ER)
+ CRB_CLR_ER(CRSW);
+ CRB_CLR_DONE(CRSW);
+ if (xs->flags & ITSDONE) break;
+ }
+ return (COMPLETE);
+}
+
+void thaw_queue(sc, target)
+struct vs_softc *sc;
+u_int8_t target;
+{
+ u_short t;
+ t = target << 8;
+ t |= 0x0001;
+ THAW_REG = t;
+ /* loop until thawed */
+ while (THAW_REG & 0x01);
+}
+
+void
+vs_scsidone (xs, stat)
+struct scsi_xfer *xs;
+int stat;
+{
+ struct scsi_link *slp = xs->sc_link;
+ struct vs_softc *sc = slp->adapter_softc;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ xs->status = stat;
+ while (xs->status == SCSI_CHECK) {
+ vs_chksense(xs);
+ thaw_queue(sc, slp->target + 1);
+ }
+ xs->flags |= ITSDONE;
+ /*sc->sc_tinfo[slp->target].cmds++;*/
+ if (CRSW & M_CRSW_ER)
+ CRB_CLR_ER(CRSW);
+ CRB_CLR_DONE(CRSW);
+ thaw_queue(sc, slp->target + 1);
+ szero(riopb, sizeof(M328_IOPB));
+ scsi_done(xs);
+}
+
+int
+vs_scsicmd(xs)
+struct scsi_xfer *xs;
+{
+ struct scsi_link *slp = xs->sc_link;
+ struct vs_softc *sc = slp->adapter_softc;
+ int flags, s, i;
+ unsigned long buf, len;
+ u_short iopb_len;
+ M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE;
+ M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ M328_IOPB *miopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB;
+ M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
+ M328_CQE *cqep;
+ M328_IOPB *iopb;
+ M328_CMD *m328_cmd;
+
+ /* If the target doesn't exist, abort */
+ if (!sc->sc_tinfo[slp->target].avail) {
+ xs->error = XS_SELTIMEOUT;
+ xs->status = -1;
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+ }
+
+ slp->quirks |= SDEV_NOLUNS;
+ flags = xs->flags;
+#ifdef SDEBUG
+ printf("scsi_cmd() ");
+ if (xs->cmd->opcode == 0) {
+ printf("TEST_UNIT_READY ");
+ } else if (xs->cmd->opcode == REQUEST_SENSE) {
+ printf("REQUEST_SENSE ");
+ } else if (xs->cmd->opcode == INQUIRY) {
+ printf("INQUIRY ");
+ } else if (xs->cmd->opcode == MODE_SELECT) {
+ printf("MODE_SELECT ");
+ } else if (xs->cmd->opcode == MODE_SENSE) {
+ printf("MODE_SENSE ");
+ } else if (xs->cmd->opcode == START_STOP) {
+ printf("START_STOP ");
+ } else if (xs->cmd->opcode == RESERVE) {
+ printf("RESERVE ");
+ } else if (xs->cmd->opcode == RELEASE) {
+ printf("RELEASE ");
+ } else if (xs->cmd->opcode == PREVENT_ALLOW) {
+ printf("PREVENT_ALLOW ");
+ } else if (xs->cmd->opcode == POSITION_TO_ELEMENT) {
+ printf("POSITION_TO_EL ");
+ } else if (xs->cmd->opcode == CHANGE_DEFINITION) {
+ printf("CHANGE_DEF ");
+ } else if (xs->cmd->opcode == MODE_SENSE_BIG) {
+ printf("MODE_SENSE_BIG ");
+ } else if (xs->cmd->opcode == MODE_SELECT_BIG) {
+ printf("MODE_SELECT_BIG ");
+ } else if (xs->cmd->opcode == 0x25) {
+ printf("READ_CAPACITY ");
+ } else if (xs->cmd->opcode == 0x08) {
+ printf("READ_COMMAND ");
+ }
+#endif
+ if (flags & SCSI_POLL) {
+ cqep = mc;
+ iopb = miopb;
+ } else {
+ cqep = vs_getcqe(sc);
+ iopb = vs_getiopb(sc);
+ }
+ if (cqep == NULL) {
+ xs->error = XS_DRIVER_STUFFUP;
+ return (TRY_AGAIN_LATER);
+ }
+
+/* s = splbio();*/
+ iopb_len = sizeof(M328_short_IOPB) + xs->cmdlen;
+ szero(iopb, sizeof(M328_IOPB));
+
+ scopy(xs->cmd, &iopb->iopb_SCSI[0], xs->cmdlen);
+ iopb->iopb_CMD = IOPB_SCSI;
+#if 0
+ LV(iopb->iopb_BUFF, kvtop(xs->data));
+ LV(iopb->iopb_LENGTH, xs->datalen);
+#endif
+ iopb->iopb_UNIT = slp->lun << 3;
+ iopb->iopb_UNIT |= slp->target;
+ iopb->iopb_NVCT = (u_char)sc->sc_nvec;
+ iopb->iopb_EVCT = (u_char)sc->sc_evec;
+
+ /*
+ * Since the 88k's don't support cache snooping, we have
+ * to flush the cache for a write and flush with inval for
+ * a read, prior to starting the IO.
+ */
+ if (xs->flags & SCSI_DATA_IN) { /* read */
+#if defined(MVME187) || defined(MVME188) || defined(MVME197)
+ dma_cachectl((vm_offset_t)xs->data, xs->datalen,
+ DMA_CACHE_SYNC_INVAL);
+#endif
+ iopb->iopb_OPTION |= OPT_READ;
+ } else { /* write */
+#if defined(MVME187)
+ dma_cachectl((vm_offset_t)xs->data, xs->datalen,
+ DMA_CACHE_SYNC);
+#endif
+ iopb->iopb_OPTION |= OPT_WRITE;
+ }
+
+ if (flags & SCSI_POLL) {
+ iopb->iopb_OPTION |= OPT_INTDIS;
+ iopb->iopb_LEVEL = 0;
+ } else {
+ iopb->iopb_OPTION |= OPT_INTEN;
+ iopb->iopb_LEVEL = sc->sc_ipl;
+ }
+ iopb->iopb_ADDR = ADDR_MOD;
+
+ /*
+ * Wait until we can use the command queue entry.
+ * Should only have to wait if the master command
+ * queue entry is busy.
+ */
+ while (cqep->cqe_QECR & M_QECR_GO);
+
+ cqep->cqe_IOPB_ADDR = OFF(iopb);
+ cqep->cqe_IOPB_LENGTH = iopb_len;
+ if (flags & SCSI_POLL) {
+ cqep->cqe_WORK_QUEUE = slp->target + 1;
+ } else {
+ cqep->cqe_WORK_QUEUE = slp->target + 1;
+ }
+
+ MALLOC(m328_cmd, M328_CMD*, sizeof(M328_CMD), M_DEVBUF, M_WAITOK);
+
+ m328_cmd->xs = xs;
+ if (xs->datalen) {
+ m328_cmd->top_sg_list = vs_build_memory_structure(xs, iopb);
+ } else {
+ m328_cmd->top_sg_list = (M328_SG)0;
+ }
+
+ LV(cqep->cqe_CTAG, m328_cmd);
+
+ if (crb->crb_CRSW & M_CRSW_AQ) {
+ cqep->cqe_QECR = M_QECR_AA;
+ }
+ VL(buf, iopb->iopb_BUFF);
+ VL(len, iopb->iopb_LENGTH);
+#ifdef SDEBUG
+ printf("tgt %d lun %d buf %x len %d wqn %d ipl %d\n", slp->target,
+ slp->lun, buf, len, cqep->cqe_WORK_QUEUE, iopb->iopb_LEVEL);
+#endif
+ cqep->cqe_QECR |= M_QECR_GO;
+
+ if (flags & SCSI_POLL) {
+ /* poll for the command to complete */
+/* splx(s);*/
+ vs_poll(sc, xs);
+ return (COMPLETE);
+ }
+/* splx(s);*/
+ return (SUCCESSFULLY_QUEUED);
+}
+
+int
+vs_chksense(xs)
+struct scsi_xfer *xs;
+{
+ int flags, s, i;
+ struct scsi_link *slp = xs->sc_link;
+ struct vs_softc *sc = slp->adapter_softc;
+ struct scsi_sense *ss;
+ M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ M328_IOPB *miopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB;
+
+ /* ack and clear the error */
+ CRB_CLR_DONE(CRSW);
+ CRB_CLR_ER(CRSW);
+ xs->status = 0;
+
+ szero(miopb, sizeof(M328_IOPB));
+ /* This is a command, so point to it */
+ ss = (void *)&miopb->iopb_SCSI[0];
+ szero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = slp->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+
+ miopb->iopb_CMD = IOPB_SCSI;
+ miopb->iopb_OPTION = OPT_READ;
+ miopb->iopb_NVCT = (u_char)sc->sc_nvec;
+ miopb->iopb_EVCT = (u_char)sc->sc_evec;
+ miopb->iopb_LEVEL = 0; /*sc->sc_ipl;*/
+ miopb->iopb_ADDR = ADDR_MOD;
+ LV(miopb->iopb_BUFF, kvtop(&xs->sense));
+ LV(miopb->iopb_LENGTH, sizeof(struct scsi_sense_data));
+
+ szero(mc, sizeof(M328_CQE));
+ mc->cqe_IOPB_ADDR = OFF(miopb);
+ mc->cqe_IOPB_LENGTH = sizeof(M328_short_IOPB) + sizeof(struct scsi_sense);
+ mc->cqe_WORK_QUEUE = 0;
+ mc->cqe_QECR = M_QECR_GO;
+ /* poll for the command to complete */
+ s = splbio();
+ do_vspoll(sc, 0);
+ /*
+ if (xs->cmd->opcode != PREVENT_ALLOW) {
+ xs->error = XS_SENSE;
+ }
+ */
+ xs->status = riopb->iopb_STATUS >> 8;
+#ifdef SDEBUG
+ scsi_print_sense(xs, 2);
+#endif
+ splx(s);
+}
+
+M328_CQE *
+vs_getcqe(sc)
+struct vs_softc *sc;
+{
+ M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
+ M328_CQE *cqep;
+
+ cqep = (M328_CQE *)&sc->sc_vsreg->sh_CQE[mcsb->mcsb_QHDP];
+
+ if (cqep->cqe_QECR & M_QECR_GO)
+ return NULL; /* Hopefully, this will never happen */
+ mcsb->mcsb_QHDP++;
+ if (mcsb->mcsb_QHDP == NUM_CQE) mcsb->mcsb_QHDP = 0;
+ szero(cqep, sizeof(M328_CQE));
+ return cqep;
+}
+
+M328_IOPB *
+vs_getiopb(sc)
+struct vs_softc *sc;
+{
+ M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
+ M328_IOPB *iopb;
+ int slot;
+
+ if (mcsb->mcsb_QHDP == 0) {
+ slot = NUM_CQE;
+ } else {
+ slot = mcsb->mcsb_QHDP - 1;
+ }
+ iopb = (M328_IOPB *)&sc->sc_vsreg->sh_IOPB[slot];
+ szero(iopb, sizeof(M328_IOPB));
+ return iopb;
+}
+
+void
+vs_initialize(sc)
+struct vs_softc *sc;
+{
+ M328_CIB *cib = (M328_CIB *)&sc->sc_vsreg->sh_CIB;
+ M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE;
+ M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
+ M328_IOPB *iopb;
+ M328_WQCF *wiopb = (M328_WQCF *)&sc->sc_vsreg->sh_MCE_IOPB;
+ u_short i, crsw;
+ int failed = 0;
+
+ CRB_CLR_DONE(CRSW);
+ szero(cib, sizeof(M328_CIB));
+ mcsb->mcsb_QHDP = 0;
+ sc->sc_qhp = 0;
+ cib->cib_NCQE = 10;
+ cib->cib_BURST = 0;
+ cib->cib_NVECT = sc->sc_ipl << 8;
+ cib->cib_NVECT |= sc->sc_nvec;
+ cib->cib_EVECT = sc->sc_ipl << 8;
+ cib->cib_EVECT |= sc->sc_evec;
+ cib->cib_PID = 0x07;
+ cib->cib_SID = 0x00;
+ cib->cib_CRBO = OFF(crb);
+ cib->cib_SELECT_msw = HI(SELECTION_TIMEOUT);
+ cib->cib_SELECT_lsw = LO(SELECTION_TIMEOUT);
+ cib->cib_WQ0TIMO_msw = HI(4);
+ cib->cib_WQ0TIMO_lsw = LO(4);
+ cib->cib_VMETIMO_msw = 0; /*HI(VME_BUS_TIMEOUT);*/
+ cib->cib_VMETIMO_lsw = 0; /*LO(VME_BUS_TIMEOUT);*/
+ cib->cib_SBRIV = sc->sc_ipl << 8;
+ cib->cib_SBRIV |= sc->sc_evec;
+ cib->cib_SOF0 = 0x15;
+ cib->cib_SRATE0 = 100/4;
+ cib->cib_SOF1 = 0x0;
+ cib->cib_SRATE1 = 0x0;
+
+ iopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB;
+ szero(iopb, sizeof(M328_IOPB));
+ iopb->iopb_CMD = CNTR_INIT;
+ iopb->iopb_OPTION = 0;
+ iopb->iopb_NVCT = (u_char)sc->sc_nvec;
+ iopb->iopb_EVCT = (u_char)sc->sc_evec;
+ iopb->iopb_LEVEL = 0; /*sc->sc_ipl;*/
+ iopb->iopb_ADDR = SHIO_MOD;
+ LV(iopb->iopb_BUFF, OFF(cib));
+ LV(iopb->iopb_LENGTH, sizeof(M328_CIB));
+
+ szero(mc, sizeof(M328_CQE));
+ mc->cqe_IOPB_ADDR = OFF(iopb);
+ mc->cqe_IOPB_LENGTH = sizeof(M328_IOPB);
+ mc->cqe_WORK_QUEUE = 0;
+ mc->cqe_QECR = M_QECR_GO;
+ /* poll for the command to complete */
+ do_vspoll(sc, 0);
+ CRB_CLR_DONE(CRSW);
+
+ /* initialize work queues */
+ for (i=1; i<8; i++) {
+ szero(wiopb, sizeof(M328_IOPB));
+ wiopb->wqcf_CMD = CNTR_INIT_WORKQ;
+ wiopb->wqcf_OPTION = 0;
+ wiopb->wqcf_NVCT = (u_char)sc->sc_nvec;
+ wiopb->wqcf_EVCT = (u_char)sc->sc_evec;
+ wiopb->wqcf_ILVL = 0; /*sc->sc_ipl;*/
+ wiopb->wqcf_WORKQ = i;
+ wiopb->wqcf_WOPT = (WQO_FOE | WQO_INIT);
+ wiopb->wqcf_SLOTS = JAGUAR_MAX_Q_SIZ;
+ LV(wiopb->wqcf_CMDTO, 2);
+
+ szero(mc, sizeof(M328_CQE));
+ mc->cqe_IOPB_ADDR = OFF(wiopb);
+ mc->cqe_IOPB_LENGTH = sizeof(M328_IOPB);
+ mc->cqe_WORK_QUEUE = 0;
+ mc->cqe_QECR = M_QECR_GO;
+ /* poll for the command to complete */
+ do_vspoll(sc, 0);
+ if (CRSW & M_CRSW_ER) {
+ /*printf("\nerror: queue %d status = 0x%x\n", i, riopb->iopb_STATUS);*/
+ /*failed = 1;*/
+ CRB_CLR_ER(CRSW);
+ }
+ CRB_CLR_DONE(CRSW);
+ delay(500);
+ }
+ /* start queue mode */
+ CRSW = 0;
+ mcsb->mcsb_MCR |= M_MCR_SQM;
+ crsw = CRSW;
+ do_vspoll(sc, 0);
+ if (CRSW & M_CRSW_ER) {
+ printf("error: status = 0x%x\n", riopb->iopb_STATUS);
+ CRB_CLR_ER(CRSW);
+ }
+ CRB_CLR_DONE(CRSW);
+
+ if (failed) {
+ printf(": failed!\n");
+ return;
+ }
+ /* reset SCSI bus */
+ vs_reset(sc);
+ /* sync all devices */
+ vs_resync(sc);
+ printf(": target %d\n", sc->sc_link.adapter_target);
+}
+
+void
+vs_resync(sc)
+struct vs_softc *sc;
+{
+ M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ M328_DRCF *devreset = (M328_DRCF *)&sc->sc_vsreg->sh_MCE_IOPB;
+ u_short i;
+
+ for (i=0; i<7; i++) {
+ szero(devreset, sizeof(M328_DRCF));
+ devreset->drcf_CMD = CNTR_DEV_REINIT;
+ devreset->drcf_OPTION = 0x00; /* no interrupts yet... */
+ devreset->drcf_NVCT = sc->sc_nvec;
+ devreset->drcf_EVCT = sc->sc_evec;
+ devreset->drcf_ILVL = 0;
+ devreset->drcf_UNIT = i;
+
+ szero(mc, sizeof(M328_CQE));
+ mc->cqe_IOPB_ADDR = OFF(devreset);
+ mc->cqe_IOPB_LENGTH = sizeof(M328_DRCF);
+ mc->cqe_WORK_QUEUE = 0;
+ mc->cqe_QECR = M_QECR_GO;
+ /* poll for the command to complete */
+ do_vspoll(sc, 0);
+ if (riopb->iopb_STATUS) {
+ sc->sc_tinfo[i].avail = 0;
+ } else {
+ sc->sc_tinfo[i].avail = 1;
+ }
+ if (CRSW & M_CRSW_ER) {
+ CRB_CLR_ER(CRSW);
+ }
+ CRB_CLR_DONE(CRSW);
+ }
+}
+
+void
+vs_reset(sc)
+struct vs_softc *sc;
+{
+ struct vsreg * rp;
+ u_int s;
+ u_char i;
+ struct iopb_reset* iopr;
+ struct cqe *cqep;
+ struct iopb_scsi *iopbs;
+ struct scsi_sense *ss;
+ M328_CIB *cib = (M328_CIB *)&sc->sc_vsreg->sh_CIB;
+ M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE;
+ M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
+ M328_SRCF *reset = (M328_SRCF *)&sc->sc_vsreg->sh_MCE_IOPB;
+ M328_IOPB *iopb;
+
+ szero(reset, sizeof(M328_SRCF));
+ reset->srcf_CMD = IOPB_RESET;
+ reset->srcf_OPTION = 0x00; /* no interrupts yet... */
+ reset->srcf_NVCT = sc->sc_nvec;
+ reset->srcf_EVCT = sc->sc_evec;
+ reset->srcf_ILVL = 0;
+ reset->srcf_BUSID = 0;
+ s = splbio();
+
+ szero(mc, sizeof(M328_CQE));
+ mc->cqe_IOPB_ADDR = OFF(reset);
+ mc->cqe_IOPB_LENGTH = sizeof(M328_SRCF);
+ mc->cqe_WORK_QUEUE = 0;
+ mc->cqe_QECR = M_QECR_GO;
+ /* poll for the command to complete */
+ while (1) {
+ do_vspoll(sc, 0);
+ /* ack & clear scsi error condition cause by reset */
+ if (CRSW & M_CRSW_ER) {
+ CRB_CLR_ER(CRSW);
+ CRB_CLR_DONE(CRSW);
+ riopb->iopb_STATUS = 0;
+ break;
+ }
+ CRB_CLR_DONE(CRSW);
+ }
+ /* thaw all work queues */
+ thaw_queue(sc, 0xFF);
+ splx (s);
+}
+
+
+/*
+ * Process an interrupt from the MVME328
+ * We'll generally update: xs->{flags,resid,error,sense,status} and
+ * occasionally xs->retries.
+ */
+
+int
+vs_checkintr(sc, xs, status)
+struct vs_softc *sc;
+struct scsi_xfer *xs;
+int *status;
+{
+ struct vsreg * rp = sc->sc_vsreg;
+ int target = -1;
+ int lun = -1;
+ M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
+ M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB;
+ struct scsi_generic *cmd;
+ u_long buf;
+ u_long len;
+ u_char error;
+
+ target = xs->sc_link->target;
+ lun = xs->sc_link->lun;
+ cmd = (struct scsi_generic *)&riopb->iopb_SCSI[0];
+
+ VL(buf, riopb->iopb_BUFF);
+ VL(len, riopb->iopb_LENGTH);
+ *status = riopb->iopb_STATUS >> 8;
+ error = riopb->iopb_STATUS & 0xFF;
+
+#ifdef SDEBUG
+ printf("scsi_chk() ");
+
+ if (xs->cmd->opcode == 0) {
+ printf("TEST_UNIT_READY ");
+ } else if (xs->cmd->opcode == REQUEST_SENSE) {
+ printf("REQUEST_SENSE ");
+ } else if (xs->cmd->opcode == INQUIRY) {
+ printf("INQUIRY ");
+ } else if (xs->cmd->opcode == MODE_SELECT) {
+ printf("MODE_SELECT ");
+ } else if (xs->cmd->opcode == MODE_SENSE) {
+ printf("MODE_SENSE ");
+ } else if (xs->cmd->opcode == START_STOP) {
+ printf("START_STOP ");
+ } else if (xs->cmd->opcode == RESERVE) {
+ printf("RESERVE ");
+ } else if (xs->cmd->opcode == RELEASE) {
+ printf("RELEASE ");
+ } else if (xs->cmd->opcode == PREVENT_ALLOW) {
+ printf("PREVENT_ALLOW ");
+ } else if (xs->cmd->opcode == POSITION_TO_ELEMENT) {
+ printf("POSITION_TO_EL ");
+ } else if (xs->cmd->opcode == CHANGE_DEFINITION) {
+ printf("CHANGE_DEF ");
+ } else if (xs->cmd->opcode == MODE_SENSE_BIG) {
+ printf("MODE_SENSE_BIG ");
+ } else if (xs->cmd->opcode == MODE_SELECT_BIG) {
+ printf("MODE_SELECT_BIG ");
+ } else if (xs->cmd->opcode == 0x25) {
+ printf("READ_CAPACITY ");
+ } else if (xs->cmd->opcode == 0x08) {
+ printf("READ_COMMAND ");
+ }
+
+ printf("tgt %d lun %d buf %x len %d status %x ", target, lun, buf, len, riopb->iopb_STATUS);
+
+ if (CRSW & M_CRSW_EX) {
+ printf("[ex]");
+ }
+ if (CRSW & M_CRSW_QMS) {
+ printf("[qms]");
+ }
+ if (CRSW & M_CRSW_SC) {
+ printf("[sc]");
+ }
+ if (CRSW & M_CRSW_SE) {
+ printf("[se]");
+ }
+ if (CRSW & M_CRSW_AQ) {
+ printf("[aq]");
+ }
+ if (CRSW & M_CRSW_ER) {
+ printf("[er]");
+ }
+ printf("\n");
+#endif
+ if (len != xs->datalen) {
+ xs->resid = xs->datalen - len;
+ } else {
+ xs->resid = 0;
+ }
+
+ if (error == SCSI_SELECTION_TO) {
+ xs->error = XS_SELTIMEOUT;
+ xs->status = -1;
+ *status = -1;
+ }
+ return 1;
+}
+
+int
+vs_intr (sc)
+register struct vs_softc *sc;
+{
+ M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
+ struct scsi_xfer *xs;
+ M328_CMD *m328_cmd;
+ unsigned long loc;
+ int status;
+ int s;
+ s = splbio();
+ /* Got a valid interrupt on this device */
+
+ VL(loc, crb->crb_CTAG);
+#ifdef SDEBUG
+ printf("Interrupt!!! ");
+ printf("loc == 0x%x\n", loc);
+#endif
+ /*
+ * If this is a controller error, there won't be a m328_cmd
+ * pointer in the CTAG feild. Bad things happen if you try
+ * to point to address 0. Controller error should be handeled
+ * in vsdma.c I'll change this soon - steve.
+ */
+ if (loc) {
+ m328_cmd = (M328_CMD *)loc;
+ xs = m328_cmd->xs;
+ if (m328_cmd->top_sg_list) {
+ vs_dealloc_scatter_gather(m328_cmd->top_sg_list);
+ m328_cmd->top_sg_list = (M328_SG)0;
+ }
+
+ FREE(m328_cmd, M_DEVBUF); /* free the command tag */
+ if (vs_checkintr (sc, xs, &status)) {
+ vs_scsidone(xs, status);
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Useful functions for scatter/gather list
+ */
+
+M328_SG
+vs_alloc_scatter_gather(void)
+{
+ M328_SG sg;
+
+ MALLOC(sg, M328_SG, sizeof(struct m328_sg), M_DEVBUF, M_WAITOK);
+ assert ( sg );
+ if ( !sg ) {
+ panic ("Memory for scatter_gather_list not available");
+ }
+ bzero(sg, sizeof(struct m328_sg));
+
+ return (sg);
+}
+
+void
+vs_dealloc_scatter_gather(M328_SG sg)
+{
+ register int i;
+
+ if (sg->level > 0) {
+ for (i=0; sg->down[i] && i<MAX_SG_ELEMENTS; i++) {
+ vs_dealloc_scatter_gather(sg->down[i]);
+ }
+ }
+ FREE(sg, M_DEVBUF);
+}
+
+void
+vs_link_sg_element(sg_list_element_t * element,
+ register vm_offset_t phys_add,
+ register int len)
+{
+ element->count.bytes = len;
+ LV(element->address, phys_add);
+ element->link = 0; /* FALSE */
+ element->transfer_type = NORMAL_TYPE;
+ element->memory_type = LONG_TRANSFER;
+ element->address_modifier = 0xD;
+}
+
+void
+vs_link_sg_list(sg_list_element_t * list,
+ register vm_offset_t phys_add,
+ register int elements)
+{
+
+ list->count.scatter.gather = elements;
+ LV(list->address, phys_add);
+ list->link = 1; /* TRUE */
+ list->transfer_type = NORMAL_TYPE;
+ list->memory_type = LONG_TRANSFER;
+ list->address_modifier = 0xD;
+}
+
+
+M328_SG
+vs_build_memory_structure(xs, iopb)
+struct scsi_xfer *xs;
+M328_IOPB *iopb; /* the iopb */
+{
+ M328_SG sg;
+ vm_offset_t starting_point_virt, starting_point_phys, point_virt,
+ point1_phys, point2_phys, virt;
+ unsigned len;
+ int level;
+
+ sg = (M328_SG)0; /* Hopefully we need no scatter/gather list */
+
+ /*
+ * We have the following things:
+ * virt the virtuell address of the contiguous virtual memory block
+ * len the lenght of the contiguous virtual memory block
+ * starting_point_virt the virtual address of the contiguous *physical* memory block
+ * starting_point_phys the *physical* address of the contiguous *physical* memory block
+ * point_virt the pointer to the virtual memory we are checking at the moment
+ * point1_phys the pointer to the *physical* memory we are checking at the moment
+ * point2_phys the pointer to the *physical* memory we are checking at the moment
+ */
+
+ level = 0;
+ virt = starting_point_virt = (vm_offset_t)xs->data;
+ point1_phys = starting_point_phys = kvtop(xs->data);
+ len = xs->datalen;
+ /*
+ * Check if we need scatter/gather
+ */
+
+ if (len > PAGESIZE) {
+ for (level = 0, point_virt = ROUND_PAGE(starting_point_virt+1);
+ /* if we do already scatter/gather we have to stay in the loop and jump */
+ point_virt < virt + (vm_offset_t)len || sg ;
+ point_virt += PAGESIZE) { /* out later */
+
+ point2_phys = kvtop(point_virt);
+
+ if ((point2_phys - TRUNC_PAGE(point1_phys) - PAGESIZE) || /* physical memory is not contiguous */
+ (point_virt - starting_point_virt >= MAX_SG_BLOCK_SIZE && sg)) { /* we only can access (1<<16)-1 bytes in scatter/gather_mode */
+ if (point_virt - starting_point_virt >= MAX_SG_BLOCK_SIZE) { /* We were walking too far for one scatter/gather block ... */
+ assert( MAX_SG_BLOCK_SIZE > PAGESIZE );
+ point_virt = TRUNC_PAGE(starting_point_virt+MAX_SG_BLOCK_SIZE-1); /* So go back to the beginning of the last matching page */
+ /* and gererate the physadress of this location for the next time. */
+ point2_phys = kvtop(point_virt);
+ }
+
+ if (!sg) {
+ /* We allocate our fist scatter/gather list */
+ sg = vs_alloc_scatter_gather();
+ }
+#if 1 /* broken firmware */
+
+ if (sg->elements >= MAX_SG_ELEMENTS) {
+ vs_dealloc_scatter_gather(sg);
+ return (NULL);
+ }
+
+#else /* if the firmware will ever get fixed */
+ while (sg->elements >= MAX_SG_ELEMENTS) {
+ if (!sg->up) { /* If the list full in this layer ? */
+ sg->up = vs_alloc_scatter_gather();
+ sg->up->level = sg->level+1;
+ sg->up->down[0] = sg;
+ sg->up->elements = 1;
+ }
+ /* link this full list also in physical memory */
+ vs_link_sg_list(&(sg->up->list[sg->up->elements-1]),
+ kvtop((vm_offset_t)sg->list),
+ sg->elements);
+ sg = sg->up; /* Climb up */
+ }
+ while (sg->level) { /* As long as we are not a the base level */
+ register int i;
+
+ i = sg->elements;
+ /* We need a new element */
+ sg->down[i] = vs_alloc_scatter_gather();
+ sg->down[i]->level = sg->level - 1;
+ sg->down[i]->up = sg;
+ sg->elements++;
+ sg = sg->down[i]; /* Climb down */
+ }
+#endif /* 1 */
+
+ if (point_virt < virt+(vm_offset_t)len) {
+ /* linking element */
+ vs_link_sg_element(&(sg->list[sg->elements]),
+ starting_point_phys,
+ point_virt-starting_point_virt);
+ sg->elements++;
+ } else {
+ /* linking last element */
+ vs_link_sg_element(&(sg->list[sg->elements]),
+ starting_point_phys,
+ (vm_offset_t)(virt+len)-starting_point_virt);
+ sg->elements++;
+ break; /* We have now collected all blocks */
+ }
+ starting_point_virt = point_virt;
+ starting_point_phys = point2_phys;
+ }
+ point1_phys = point2_phys;
+ }
+ }
+
+ /*
+ * Climb up along the right side of the tree until we reach the top.
+ */
+
+ if (sg) {
+ while (sg->up) {
+ /* link this list also in physical memory */
+ vs_link_sg_list(&(sg->up->list[sg->up->elements-1]),
+ kvtop((vm_offset_t)sg->list),
+ sg->elements);
+ sg = sg->up; /* Climb up */
+ }
+
+ iopb->iopb_OPTION |= M_OPT_SG;
+ iopb->iopb_ADDR |= M_ADR_SG_LINK;
+ LV(iopb->iopb_BUFF, kvtop((vm_offset_t)sg->list));
+ LV(iopb->iopb_LENGTH, sg->elements);
+ LV(iopb->iopb_SGTTL, len);
+ } else {
+ /* no scatter/gather neccessary */
+ LV(iopb->iopb_BUFF, starting_point_phys);
+ LV(iopb->iopb_LENGTH, len);
+ }
+ return (sg);
+}
+
diff --git a/sys/arch/mvme68k/dev/vsdma.c b/sys/arch/mvme68k/dev/vsdma.c
new file mode 100644
index 00000000000..2158eb3e0d2
--- /dev/null
+++ b/sys/arch/mvme68k/dev/vsdma.c
@@ -0,0 +1,188 @@
+/* $OpenBSD: vsdma.c,v 1.1 2000/01/25 04:18:18 smurph Exp $ */
+/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
+ * 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 by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)vsdma.c
+ */
+
+/*
+ * MVME328 scsi adaptor driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <machine/autoconf.h>
+
+#if defined(MVME187) || defined(MVME188) || defined(MVME197)
+#include <machine/board.h>
+#include <mvme88k/dev/vsreg.h>
+#include <mvme88k/dev/vsvar.h>
+#include <mvme88k/dev/vme.h>
+#include "machine/mmu.h"
+#else
+#include <mvme68k/dev/vsreg.h>
+#include <mvme68k/dev/vsvar.h>
+#include <mvme68k/dev/vme.h>
+#endif /* defined(MVME187) || defined(MVME188) || defined(MVME197) */
+
+int vsmatch __P((struct device *, void *, void *));
+void vsattach __P((struct device *, struct device *, void *));
+int vsprint __P((void *auxp, char *));
+void vs_initialize __P((struct vs_softc *));
+int vs_intr __P((struct vs_softc *));
+int vs_nintr __P((struct vs_softc *));
+int vs_eintr __P((struct vs_softc *));
+
+struct scsi_adapter vs_scsiswitch = {
+ vs_scsicmd,
+ vs_minphys,
+ 0, /* no lun support */
+ 0, /* no lun support */
+};
+
+struct scsi_device vs_scsidev = {
+ NULL, /* use default error handler */
+ NULL, /* do not have a start function */
+ NULL, /* have no async handler */
+ NULL, /* Use default done routine */
+};
+
+struct cfattach vs_ca = {
+ sizeof(struct vs_softc), vsmatch, vsattach,
+};
+
+struct cfdriver vs_cd = {
+ NULL, "vs", DV_DULL, 0
+};
+
+int
+vsmatch(pdp, vcf, args)
+ struct device *pdp;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+ struct confargs *ca = args;
+ return(!badvaddr(ca->ca_vaddr, 1));
+}
+
+void
+vsattach(parent, self, auxp)
+ struct device *parent, *self;
+ void *auxp;
+{
+ struct vs_softc *sc = (struct vs_softc *)self;
+ struct confargs *ca = auxp;
+ struct vsreg * rp;
+ int tmp;
+ extern int cpuspeed;
+
+ sc->sc_vsreg = rp = ca->ca_vaddr;
+
+ sc->sc_ipl = ca->ca_ipl;
+ sc->sc_nvec = ca->ca_vec + 0;
+ sc->sc_evec = ca->ca_vec + 1;
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = 7;
+ sc->sc_link.adapter = &vs_scsiswitch;
+ sc->sc_link.device = &vs_scsidev;
+ sc->sc_link.openings = 1;
+
+ sc->sc_ih_n.ih_fn = vs_nintr;
+ sc->sc_ih_n.ih_arg = sc;
+ sc->sc_ih_n.ih_ipl = ca->ca_ipl;
+
+ sc->sc_ih_e.ih_fn = vs_eintr;
+ sc->sc_ih_e.ih_arg = sc;
+ sc->sc_ih_e.ih_ipl = ca->ca_ipl;
+
+ vs_initialize(sc);
+
+ vmeintr_establish(sc->sc_nvec, &sc->sc_ih_n);
+ vmeintr_establish(sc->sc_evec, &sc->sc_ih_e);
+ evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt_n);
+ evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt_e);
+
+ /*
+ * attach all scsi units on us, watching for boot device
+ * (see dk_establish).
+ */
+ tmp = bootpart;
+ if (ca->ca_paddr != bootaddr)
+ bootpart = -1; /* invalid flag to dk_establish */
+ config_found(self, &sc->sc_link, scsiprint);
+ bootpart = tmp; /* restore old value */
+}
+
+/*
+ * print diag if pnp is NULL else just extra
+ */
+int
+vsprint(auxp, pnp)
+ void *auxp;
+ char *pnp;
+{
+ if (pnp == NULL)
+ return (UNCONF);
+ return (QUIET);
+}
+
+/* normal interrupt function */
+int
+vs_nintr(sc)
+ struct vs_softc *sc;
+{
+#ifdef SDEBUG
+ printf("Normal Interrupt!!!\n");
+#endif
+ vs_intr(sc);
+ sc->sc_intrcnt_n.ev_count++;
+ return (1);
+}
+
+/* error interrupt function */
+int
+vs_eintr(sc)
+ struct vs_softc *sc;
+{
+#ifdef SDEBUG
+ printf("Error Interrupt!!!\n");
+#endif
+ vs_intr(sc);
+ sc->sc_intrcnt_e.ev_count++;
+ return (1);
+}
+
+
diff --git a/sys/arch/mvme68k/dev/vsreg.h b/sys/arch/mvme68k/dev/vsreg.h
new file mode 100644
index 00000000000..7fdf8107745
--- /dev/null
+++ b/sys/arch/mvme68k/dev/vsreg.h
@@ -0,0 +1,756 @@
+/* $OpenBSD: vsreg.h,v 1.1 2000/01/25 04:18:18 smurph Exp $ */
+/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from source contributed by Mark Bellon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 !defined(_M328REG_H_)
+#define _M328REG_H_
+
+
+typedef struct LONGV
+{
+ u_short msw;
+ u_short lsw;
+} LONGV;
+
+#define MSW(x) ((x).msw)
+#define LSW(x) ((x).lsw)
+
+/*
+ * macro to convert a unsigned long to a LONGV
+ */
+
+#define LV( a, b) \
+{ \
+ MSW( a ) = ( (( (unsigned long)(b) ) >> 16) & 0xffff ); \
+ LSW( a ) = ( ( (unsigned long)(b) ) & 0xffff); \
+}
+
+/*
+ * macro to convert a LONGV to a unsigned long
+ */
+
+#define VL( a, b) \
+{ \
+ a = ( (((unsigned long) MSW(b)) << 16 ) | (((unsigned long) LSW(b)) & 0x0ffff) ); \
+}
+
+#define COUGAR 0x4220 /* board type (config. status area) */
+#define JAGUAR 0
+
+/*
+ * JAGUAR specific device limits.
+ */
+
+#define JAGUAR_MIN_Q_SIZ 2 /* got'a have at least one! */
+#define JAGUAR_MAX_Q_SIZ 2 /* can't have more */
+#define JAGUAR_MAX_CTLR_CMDS 80 /* Interphase says so */
+
+/*
+ * COUGAR specific device limits.
+ */
+
+#define COUGAR_MIN_Q_SIZ 2 /* got'a have at least one! */
+#define COUGAR_CMDS_PER_256K 42 /* Interphase says so */
+
+/*
+ * Structures
+ */
+
+#define NUM_CQE 10
+#define MAX_IOPB 64
+#define NUM_IOPB NUM_CQE
+#define S_IOPB_RES (MAX_IOPB - sizeof(M328_short_IOPB))
+#define S_SHORTIO 2048
+#define S_IOPB sizeof(M328_IOPB)
+#define S_CIB sizeof(M328_CIB)
+#define S_MCSB sizeof(M328_MCSB)
+#define S_MCE sizeof(M328_CQE)
+#define S_CQE (sizeof(M328_CQE) * NUM_CQE)
+#define S_HIOPB (sizeof(M328_IOPB) * NUM_IOPB)
+#define S_HSB sizeof(M328_HSB)
+#define S_CRB sizeof(M328_CRB)
+#define S_CSS sizeof(M328_CSB)
+#define S_NOT_HOST (S_MCSB + S_MCE + S_CQE + S_HIOPB + S_IOPB + \
+ S_CIB + S_HSB + S_CRB + S_IOPB + S_CSS)
+#define S_HUS_FREE (S_SHORTIO - S_NOT_HOST)
+
+#define S_WQCF sizeof(M328_WQCF)
+
+#define HOST_ID 0x4321
+
+
+/**************** Master Control Status Block (MCSB) *******************/
+
+/*
+ * defines for Master Status Register
+ */
+
+#define M_MSR_QFC 0x0004 /* queue flush complete */
+#define M_MSR_BOK 0x0002 /* board OK */
+#define M_MSR_CNA 0x0001 /* controller not available */
+
+/*
+ * defines for Master Control Register
+ */
+
+#define M_MCR_SFEN 0x2000 /* sysfail enable */
+#define M_MCR_RES 0x1000 /* reset controller */
+#define M_MCR_FLQ 0x0800 /* flush queue */
+#define M_MCR_FLQR 0x0004 /* flush queue and report */
+#define M_MCR_SQM 0x0001 /* start queue mode */
+
+/*
+ * defines for Interrupt on Queue Available Register
+ */
+
+#define M_IQAR_IQEA 0x8000 /* interrupt on queue entry avail */
+#define M_IQAR_IQEH 0x4000 /* interrupt on queue half empty */
+#define M_IQAR_ILVL 0x0700 /* interrupt lvl on queue avaliable */
+#define M_IQAR_IVCT 0x00FF /* interrupt vector on queue avail */
+
+/*
+ * defines for Thaw Work Queue Register
+ */
+
+#define M_THAW_TWQN 0xff00 /* thaw work queue number */
+#define M_THAW_TWQE 0x0001 /* thaw work queue enable */
+
+typedef struct mcsb
+{ /* Master control/Status Block */
+ volatile u_short mcsb_MSR; /* Master status register */
+ volatile u_short mcsb_MCR; /* Master Control register */
+ volatile u_short mcsb_IQAR; /* Interrupt on Queue Available Reg */
+ volatile u_short mcsb_QHDP; /* Queue head pointer */
+ volatile u_short mcsb_THAW; /* Thaw work Queue */
+ volatile u_short mcsb_RES0; /* Reserved word 0 */
+ volatile u_short mcsb_RES1; /* Reserved word 1 */
+ volatile u_short mcsb_RES2; /* Reserved word 2 */
+} M328_MCSB;
+
+/**************** END Master Control Status Block (MCSB) *******************/
+
+/**************** Scater/Gather Stuff *******************/
+
+typedef struct {
+ union {
+ unsigned short bytes :16;
+ #define MAX_SG_BLOCK_SIZE (1<<16) /* the size *has* to be always *smaller* */
+ struct {
+ unsigned short :8;
+ unsigned short gather :8;
+ } scatter;
+ } count;
+ LONGV address;
+ unsigned short link :1;
+ unsigned short :3;
+ unsigned short transfer_type :2;
+ /* 0x0 is reserved */
+ #define SHORT_TREANSFER 0x1
+ #define LONG_TRANSFER 0x2
+ #define SCATTER_GATTER_LIST_IN_SHORT_IO 0x3
+ unsigned short memory_type :2;
+ #define NORMAL_TYPE 0x0
+ #define BLOCK_MODE 0x1
+ /* 0x2 is reserved */
+ /* 0x3 is reserved */
+ unsigned short address_modifier :8;
+}sg_list_element_t;
+
+typedef sg_list_element_t * scatter_gather_list_t;
+
+#define MAX_SG_ELEMENTS 64
+
+struct m328_sg {
+ struct m328_sg *up;
+ int elements;
+ int level;
+ struct m328_sg *down[MAX_SG_ELEMENTS];
+ sg_list_element_t list[MAX_SG_ELEMENTS];
+};
+
+typedef struct m328_sg *M328_SG;
+
+typedef struct {
+ struct scsi_xfer *xs;
+ M328_SG top_sg_list;
+} M328_CMD;
+/**************** END Scater/Gather Stuff *******************/
+
+/**************** Host Semaphore Block (HSB) *******************/
+
+typedef struct hsb
+{ /* Host Semaphore Block */
+ volatile u_short hsb_INITQ; /* Init MCE Flag */
+ volatile u_short hsb_WORKQ; /* Work Queue number */
+ volatile u_short hsb_MAGIC; /* Magic word */
+ volatile u_short hsb_RES0; /* Reserved word */
+} M328_HSB;
+
+/**************** END Host Semaphore Block (HSB) *******************/
+
+/**************** Perform Diagnostics Command Format *******************/
+
+typedef struct pdcf
+{ /* Perform Diagnostics Cmd Format */
+ volatile u_short pdcf_CMD; /* Command normally 0x40 */
+ volatile u_short pdcf_RES0; /* Reserved word */
+ volatile u_short pdcf_STATUS; /* Return Status */
+ volatile u_short pdcf_RES1; /* Reserved Word */
+ volatile u_short pdcf_ROM; /* ROM Test Results */
+ volatile u_short pdcf_BUFRAM; /* Buffer RAM results */
+ volatile u_short pdcf_EVENT_RAM; /* Event Ram test Results */
+ volatile u_short pdcf_SCSI_PRI_PORT; /* SCSI Primary Port Reg test */
+ volatile u_short pdcf_SCSI_SEC_PORT; /* SCSI Secondary Port Reg test */
+} M328_PDCF;
+
+#define PDCF_SUCCESS 0xFFFF
+
+/**************** END Perform Diagnostics Command Format *******************/
+
+/*************** Controller Initialization Block (CIB) *****************/
+
+/*
+ * defines for Interrupt Vectors
+ */
+
+#define M_VECT_ILVL 0x0700 /* Interrupt Level */
+#define M_VECT_IVCT 0x00FF /* Interrupt Vector */
+
+/*
+ * defines for SCSI Bus ID Registers
+ */
+
+#define M_PSID_DFT 0x0008 /* default ID enable */
+#define M_PSID_ID 0x0007 /* Primary/Secondary SCSI ID */
+
+/*
+ * Error recovery flags.
+ */
+
+#define M_ERRFLGS_FOSR 0x0001 /* Freeze on SCSI bus reset */
+#define M_ERRFLGS_RIN 0x0002 /* SCSI bus reset interrupt */
+#define M_ERRFLGS_RSE 0x0004 /* Report COUGAR SCSI errors */
+
+/*
+ * Controller Initialization Block
+ */
+
+typedef struct cib
+{
+ volatile u_short cib_NCQE; /* Number of Command Queue Entries */
+ volatile u_short cib_BURST; /* DMA Burst count */
+ volatile u_short cib_NVECT; /* Normal Completion Vector */
+ volatile u_short cib_EVECT; /* Error Completion Vector */
+ volatile u_short cib_PID; /* Primary SCSI Bus ID */
+ volatile u_short cib_SID; /* Secondary SCSI Bus ID */
+ volatile u_short cib_CRBO; /* Command Response Block Offset */
+ volatile u_short cib_SELECT_msw;/* Selection timeout in milli_second */
+ volatile u_short cib_SELECT_lsw;/* Selection timeout in milli_second */
+ volatile u_short cib_WQ0TIMO_msw;/* Work Q - timeout in 256 ms */
+ volatile u_short cib_WQ0TIMO_lsw;/* Work Q - timeout in 256 ms */
+ volatile u_short cib_VMETIMO_msw;/* VME Time out in 32 ms */
+ volatile u_short cib_VMETIMO_lsw;/* VME Time out in 32 ms */
+ volatile u_short cib_RES0[2]; /* Reserved words */
+ volatile u_short cib_OBMT; /* offbrd CRB mtype/xfer type/ad mod */
+ volatile u_short cib_OBADDR_msw;/* host mem address for offboard CRB */
+ volatile u_short cib_OBADDR_lsw;/* host mem address for offboard CRB */
+ volatile u_short cib_ERR_FLGS; /* error recovery flags */
+ volatile u_short cib_RES1; /* reserved word */
+ volatile u_short cib_RES2; /* reserved word */
+ volatile u_short cib_SBRIV; /* SCSI Bus Reset Interrupt Vector */
+ volatile u_char cib_SOF0; /* Synchronous offset (Bus 0) */
+ volatile u_char cib_SRATE0; /* Sync negotiation rate (Bus 0) */
+ volatile u_char cib_SOF1; /* Synchronous offset (Bus 1) */
+ volatile u_char cib_SRATE1; /* Sync negotiation rate (Bus 1) */
+} M328_CIB;
+
+/**************** END Controller Initialization Block (CIB) *****************/
+
+/**************** Command Queue Entry (CQE) *******************/
+
+/*
+ * defines for Queue Entry Control Register
+ */
+
+#define M_QECR_IOPB 0x0F00 /* IOPB type (must be zero) */
+#define M_QECR_HPC 0x0004 /* High Priority command */
+#define M_QECR_AA 0x0002 /* abort acknowledge */
+#define M_QECR_GO 0x0001 /* Go/Busy */
+
+#define CQE_GO(qecr) ((qecr) |= M_QECR_GO)
+#define CQE_AA_GO(qecr) ((qecr) |= (M_QECR_GO + M_QECR_AA))
+
+typedef struct cqe
+{ /* Command Queue Entry */
+ volatile u_short cqe_QECR; /* Queue Entry Control Register */
+ volatile u_short cqe_IOPB_ADDR; /* IOPB Address */
+ volatile LONGV cqe_CTAG; /* Command Tag */
+ volatile u_char cqe_IOPB_LENGTH;/* IOPB Length */
+ volatile u_char cqe_WORK_QUEUE; /* Work Queue Number */
+ volatile u_short cqe_RES0; /* Reserved word */
+} M328_CQE;
+
+/**************** END Command Queue Entry (CQE) *******************/
+
+/**************** Command Response Block (CRB) *******************/
+
+/*
+ * defines for Command Response Status Word
+ */
+
+#define M_CRSW_SE 0x0800 /* SCSI error (COUGAR) */
+#define M_CRSW_RST 0x0400 /* SCSI Bus reset (COUGAR) */
+#define M_CRSW_SC 0x0080 /* status change */
+#define M_CRSW_CQA 0x0040 /* Command queue entry available */
+#define M_CRSW_QMS 0x0020 /* queue mode started */
+#define M_CRSW_AQ 0x0010 /* abort queue */
+#define M_CRSW_EX 0x0008 /* exception */
+#define M_CRSW_ER 0x0004 /* error */
+#define M_CRSW_CC 0x0002 /* command complete */
+#define M_CRSW_CRBV 0x0001 /* cmd response block valid/clear */
+
+#define CRB_CLR_DONE(crsw) ((crsw) = 0)
+#define CRB_CLR_ER(crsw) ((crsw) &= ~M_CRSW_ER)
+
+typedef struct crb
+{ /* Command Response Block */
+ volatile u_short crb_CRSW; /* Command Response Status Word */
+ volatile u_short crb_RES0; /* Reserved word */
+ volatile LONGV crb_CTAG; /* Command Tag */
+ volatile u_char crb_IOPB_LENGTH;/* IOPB Length */
+ volatile u_char crb_WORK_QUEUE; /* Work Queue Number */
+ volatile u_short crb_RES1; /* Reserved word */
+} M328_CRB;
+
+/**************** END Command Response Block (CRB) *******************/
+
+/*********** Controller Error Vector Status Block (CEVSB) **************/
+
+typedef struct cevsb
+{ /* Command Response Block */
+ volatile u_short cevsb_CRSW; /* Command Response Status Word */
+ volatile u_char cevsb_TYPE; /* IOPB type */
+ volatile u_char cevsb_RES0; /* Reserved byte */
+ volatile LONGV cevsb_CTAG; /* Command Tag */
+ volatile u_char cevsb_IOPB_LENGTH;/* IOPB Length */
+ volatile u_char cevsb_WORK_QUEUE;/* Work Queue Number */
+ volatile u_short cevsb_RES1; /* Reserved word */
+ volatile u_char cevsb_RES2; /* Reserved byte */
+ volatile u_char cevsb_ERROR; /* error code */
+ volatile u_short cevsb_AUXERR; /* COUGAR error code */
+} M328_CEVSB;
+
+/*********** END Controller Error Vector Status Block (CEVSB) **************/
+
+/**************** Configuration Status Block (CSB) *******************/
+
+typedef struct csb
+{ /* Configuration Status Blk */
+ volatile u_short csb_TYPE; /* 0x0=JAGUAR, 0x4220=COUGAR */
+ volatile u_char csb_RES1; /* Reserved byte */
+ volatile u_char csb_PCODE[3]; /* Product Code */
+ volatile u_short csb_RES2; /* Reserved word */
+ volatile u_char csb_RES3; /* Reserved byte */
+ volatile u_char csb_PVAR; /* Product Variation */
+ volatile u_short csb_RES4; /* Reserved word */
+ volatile u_char csb_RES5; /* Reserved byte */
+ volatile u_char csb_FREV[3]; /* Firmware Revision level */
+ volatile u_short csb_RES6; /* Reserved word */
+ volatile u_char csb_FDATE[8]; /* Firmware Release date */
+ volatile u_short csb_SSIZE; /* System memory size in Kbytes */
+ volatile u_short csb_BSIZE; /* Buffer memory size in Kbytes */
+ volatile u_short csb_RES8; /* Reserved word */
+ volatile u_char csb_PFECID; /* Primary Bus FEC ID */
+ volatile u_char csb_SFECID; /* Secondard Bus FEC ID */
+ volatile u_char csb_PID; /* Primary Bus ID */
+ volatile u_char csb_SID; /* Secondary Bus ID */
+ volatile u_char csb_LPDS; /* Last Primary Device Selected */
+ volatile u_char csb_LSDS; /* Last Secondary Device Selected */
+ volatile u_char csb_PPS; /* Primary Phase Sense */
+ volatile u_char csb_SPS; /* Secondary Phase Sense */
+ volatile u_char csb_RES10; /* Reserved byte */
+ volatile u_char csb_DBID; /* Daughter Board ID */
+ volatile u_char csb_RES11; /* Reserved byte */
+ volatile u_char csb_SDS; /* Software DIP Switch */
+ volatile u_short csb_RES12; /* Reserved word */
+ volatile u_short csb_FWQR; /* Frozen Work Queues Register */
+ volatile u_char csb_RES13[72]; /* Reserved bytes */
+} M328_CSB;
+
+/**************** END Configuration Status Block (CSB) *******************/
+
+/**************** IOPB Format (IOPB) *******************/
+
+/*
+ * defines for IOPB Option Word
+ */
+
+#define M_OPT_HEAD_TAG 0x3000 /* head of queue command queue tag */
+#define M_OPT_ORDERED_TAG 0x2000 /* order command queue tag */
+#define M_OPT_SIMPLE_TAG 0x1000 /* simple command queue tag */
+#define M_OPT_GO_WIDE 0x0800 /* use WIDE transfers */
+#define M_OPT_DIR 0x0100 /* VME direction bit */
+#define M_OPT_SG_BLOCK 0x0008 /* scatter/gather in 512 byte blocks */
+#define M_OPT_SS 0x0004 /* Suppress synchronous transfer */
+#define M_OPT_SG 0x0002 /* scatter/gather bit */
+#define M_OPT_IE 0x0001 /* Interrupt enable */
+
+/*
+ * defines for IOPB Address Type and Modifier
+ */
+
+#define M_ADR_TRANS 0x0C00 /* transfer type */
+#define M_ADR_MEMT 0x0300 /* memory type */
+#define M_ADR_MOD 0x00FF /* VME address modifier */
+#define M_ADR_SG_LINK 0x8000 /* Scatter/Gather Link bit */
+
+/*
+ * defines for IOPB Unit Address on SCSI Bus
+ */
+
+#define M_UNIT_EXT_LUN 0xFF00 /* Extended Address */
+#define M_UNIT_EXT 0x0080 /* Extended Address Enable */
+#define M_UNIT_BUS 0x0040 /* SCSI Bus Selection */
+#define M_UNIT_LUN 0x0038 /* Logical Unit Number */
+#define M_UNIT_ID 0x0007 /* SCSI Device ID */
+
+typedef struct short_iopb
+{
+ volatile u_short iopb_CMD; /* IOPB Command code */
+ volatile u_short iopb_OPTION; /* IOPB Option word */
+ volatile u_short iopb_STATUS; /* IOPB Return Status word */
+ volatile u_short iopb_RES0; /* IOPB Reserved word */
+ volatile u_char iopb_NVCT; /* IOPB Normal completion Vector */
+ volatile u_char iopb_EVCT; /* IOPB Error completion Vector */
+ volatile u_short iopb_LEVEL; /* IOPB Interrupt Level */
+ volatile u_short iopb_RES1; /* IOPB Reserved word */
+ volatile u_short iopb_ADDR; /* IOPB Address type and modifer */
+ volatile LONGV iopb_BUFF; /* IOPB Buffer Address */
+ volatile LONGV iopb_LENGTH; /* IOPB Max-Transfer Length */
+ volatile LONGV iopb_SGTTL; /* IOPB Scatter/Gather Total Transfer len */
+ volatile u_short iopb_RES4; /* IOPB Reserved word */
+ volatile u_short iopb_UNIT; /* IOPB Unit address on SCSI bus */
+} M328_short_IOPB;
+
+typedef struct iopb
+{
+ volatile u_short iopb_CMD; /* IOPB Command code */
+ volatile u_short iopb_OPTION; /* IOPB Option word */
+ volatile u_short iopb_STATUS; /* IOPB Return Status word */
+ volatile u_short iopb_RES0; /* IOPB Reserved word */
+ volatile u_char iopb_NVCT; /* IOPB Normal completion Vector */
+ volatile u_char iopb_EVCT; /* IOPB Error completion Vector */
+ volatile u_short iopb_LEVEL; /* IOPB Interrupt Level */
+ volatile u_short iopb_RES1; /* IOPB Reserved word */
+ volatile u_short iopb_ADDR; /* IOPB Address type and modifer */
+ volatile LONGV iopb_BUFF; /* IOPB Buffer Address */
+ volatile LONGV iopb_LENGTH; /* IOPB Max-Transfer Length */
+ volatile LONGV iopb_SGTTL; /* IOPB Scatter/Gather Total Transfer len */
+ volatile u_short iopb_RES4; /* IOPB Reserved word */
+ volatile u_short iopb_UNIT; /* IOPB Unit address on SCSI bus */
+ u_short iopb_SCSI[S_IOPB_RES/2]; /* IOPB SCSI words for pass thru */
+} M328_IOPB;
+
+/**************** END IOPB Format (IOPB) *******************/
+
+/**************** Initialize Work Queue Command Format (WQCF) ***********/
+
+#define M_WOPT_IWQ 0x8000 /* initialize work queue */
+#define M_WOPT_PE 0x0008 /* parity check enable */
+#define M_WOPT_FE 0x0004 /* freeze on error enable */
+#define M_WOPT_TM 0x0002 /* target mode enable */
+#define M_WOPT_AE 0x0001 /* abort enable */
+
+typedef struct wqcf
+{ /* Initialize Work Queue Cmd Format*/
+ volatile u_short wqcf_CMD; /* Command Normally (0x42) */
+ volatile u_short wqcf_OPTION; /* Command Options */
+ volatile u_short wqcf_STATUS; /* Return Status */
+ volatile u_short wqcf_RES0; /* Reserved word */
+ volatile u_char wqcf_NVCT; /* Normal Completion Vector */
+ volatile u_char wqcf_EVCT; /* Error Completion Vector */
+ volatile u_short wqcf_ILVL; /* Interrupt Level */
+ volatile u_short wqcf_RES1[8]; /* Reserved words */
+ volatile u_short wqcf_WORKQ; /* Work Queue Number */
+ volatile u_short wqcf_WOPT; /* Work Queue Options */
+ volatile u_short wqcf_SLOTS; /* Number of slots in Work Queues */
+ volatile u_short wqcf_RES2; /* Reserved word */
+ volatile LONGV wqcf_CMDTO; /* Command timeout */
+ volatile u_short wqcf_RES3; /* Reserved word */
+} M328_WQCF;
+
+/**************** END Initialize Work Queue Command Format (WQCF) ***********/
+
+/**************** SCSI Reset Command Format (SRCF) ***********/
+
+typedef struct srcf
+{ /* SCSI Reset Cmd Format*/
+ volatile u_short srcf_CMD; /* Command Normally (0x22) */
+ volatile u_short srcf_OPTION; /* Command Options */
+ volatile u_short srcf_STATUS; /* Return Status */
+ volatile u_short srcf_RES0; /* Reserved word */
+ volatile u_char srcf_NVCT; /* Normal Completion Vector */
+ volatile u_char srcf_EVCT; /* Error Completion Vector */
+ volatile u_short srcf_ILVL; /* Interrupt Level */
+ volatile u_short srcf_RES1[8]; /* Reserved words */
+ volatile u_short srcf_BUSID; /* SCSI bus ID to reset */
+} M328_SRCF;
+
+/**************** END SCSI Reset Command Format (SRCF) ***********/
+
+/**************** Device Reinitialize Command Format (DRCF) ***********/
+
+typedef struct drcf
+{ /* Device Reinitialize Cmd Format*/
+ volatile u_short drcf_CMD; /* Command Normally (0x4C) */
+ volatile u_short drcf_OPTION; /* Command Options */
+ volatile u_short drcf_STATUS; /* Return Status */
+ volatile u_short drcf_RES0; /* Reserved word */
+ volatile u_char drcf_NVCT; /* Normal Completion Vector */
+ volatile u_char drcf_EVCT; /* Error Completion Vector */
+ volatile u_short drcf_ILVL; /* Interrupt Level */
+ volatile u_short drcf_RES1[9]; /* Reserved words */
+ volatile u_short drcf_UNIT; /* Unit Address */
+} M328_DRCF;
+
+/**************** END SCSI Reset Command Format (SRCF) ***********/
+
+/**************** Host Down Loadable Firmware (HDLF) ***********/
+
+typedef struct hdlf
+{ /* Host Down Loadable Firmware cmd */
+ volatile u_short hdlf_CMD; /* Command Normally (0x4F) */
+ volatile u_short hdlf_OPTION; /* Command Options */
+ volatile u_short hdlf_STATUS; /* Return Status */
+ volatile u_short hdlf_RES0; /* Reserved word */
+ volatile u_char hdlf_NVCT; /* Normal Completion Vector */
+ volatile u_char hdlf_EVCT; /* Error Completion Vector */
+ volatile u_short hdlf_ILVL; /* Interrupt Level */
+ volatile u_short hdlf_RES1; /* Reserved word */
+ volatile u_short hdlf_ADDR; /* Address type and modifer */
+ volatile LONGV hdlf_BUFF; /* Buffer Address */
+ volatile LONGV hdlf_LENGTH; /* Max-Transfer Length */
+ volatile LONGV hdlf_CSUM; /* Checksum */
+ volatile u_short hdlf_RES2; /* Reserved word */
+ volatile u_short hdlf_SEQ; /* Sequence number */
+ volatile u_short hdlf_RES3[6]; /* Reserved words */
+} M328_HDLF;
+
+#define M328_INITIALIZE_DOWNLOAD 0x0010
+#define M328_TRANSFER_PACKET 0x0020
+#define M328_PROGRAM_FLASH 0x0040
+#define M328_MOTOROLA_S_RECORDS 0x1000
+
+/**************** END SCSI Reset Command Format (SRCF) ***********/
+
+/**************** Short I/O Format *******************/
+
+struct vsreg
+{
+ M328_MCSB sh_MCSB; /* Master Control / Status Block */
+ M328_CQE sh_MCE; /* Master Command Entry */
+ M328_CQE sh_CQE[NUM_CQE]; /* Command Queue Entry */
+ M328_IOPB sh_IOPB[NUM_IOPB]; /* Host IOPB Space */
+ M328_IOPB sh_MCE_IOPB; /* Host MCE IOPB Space */
+ M328_CIB sh_CIB; /* Controller Initialization Block */
+ volatile u_char sh_HUS[S_HUS_FREE];/* Host Usable Space */
+ M328_HSB sh_HSB; /* Host Semaphore Block */
+ M328_CRB sh_CRB; /* Command Response Block */
+ M328_IOPB sh_RET_IOPB; /* Returned IOPB */
+ M328_CSB sh_CSS; /* Controller Specific Space/Block */
+};
+
+#define CRSW sc->sc_vsreg->sh_CRB.crb_CRSW
+#define THAW_REG sc->sc_vsreg->sh_MCSB.mcsb_THAW
+#define THAW(x) THAW_REG=((u_char)x << 8);THAW_REG |= M_THAW_TWQE
+#define QUEUE_FZN(x) (sc->sc_vsreg->sh_CSS.csb_FWQR & (1 << x))
+#define SELECTION_TIMEOUT 250 /* milliseconds */
+#define VME_BUS_TIMEOUT 0xF /* units of 30ms */
+#define M328_INFINITE_TIMEOUT 0 /* wait forever */
+
+/**************** END Short I/O Format *******************/
+
+/*
+ * Scatter gather structure
+ */
+
+typedef struct ipsg
+{
+ volatile u_short sg_count; /* byte/entry count */
+ volatile u_short sg_addrhi; /* datablock/entry address high */
+ volatile u_short sg_addrlo; /* datablock/entry address low */
+ volatile u_short sg_meminfo; /* memory information */
+}IPSG;
+
+#define MACSI_SG 256 /* number of MACSI scat/gat entries */
+#define S_MACSI_SG (MACSI_SG * sizeof(IPSG))
+#define MACSI_SG_RSIZE 65535 /* max len of each scatter/gather entry */
+
+/*
+ * SCSI IOPB definitions
+ */
+
+#define IOPB_PASS_THRU 0x20 /* SCSI Pass Through commands */
+#define IOPB_PASS_THRU_EXT 0x21 /* SCSI Pass Through Extended commands */
+#define IOPB_RESET 0x22 /* SCSI Reset bus */
+
+/*
+ * SCSI Control IOPB's
+ */
+
+#define CNTR_DIAG 0x40 /* Perform Diagnostics */
+#define CNTR_INIT 0x41 /* Initialize Controller */
+#define CNTR_INIT_WORKQ 0x42 /* Initialize Work Queue */
+#define CNTR_DUMP_INIT 0x43 /* Dump Initialization Parameters */
+#define CNTR_DUMP_WORDQ 0x44 /* Dump work Queue Parameters */
+#define CNTR_CANCEL_IOPB 0x48 /* Cancel command tag */
+#define CNTR_FLUSH_WORKQ 0x49 /* Flush Work Queue */
+#define CNTR_DEV_REINIT 0x4C /* Reinitialize Device */
+#define CNTR_ISSUE_ABORT 0x4E /* An abort has been issued */
+#define CNTR_DOWNLOAD_FIRMWARE 0x4F /* Download firmware (COUGAR) */
+
+
+/*
+ * Memory types
+ */
+
+#define MEMT_16BIT 1 /* 16 Bit Memory type */
+#define MEMT_32BIT 2 /* 32 Bit Memory type */
+#define MEMT_SHIO 3 /* Short I/O Memory type */
+#define MEMTYPE MEMT_32BIT /* do 32-bit transfers */
+
+/*
+ * Transfer types
+ */
+
+#define TT_NORMAL 0 /* Normal Mode Tranfers */
+#define TT_BLOCK 1 /* block Mode Tranfers */
+#define TT_DISABLE_INC_ADDR 2 /* Disable Incrementing Addresses */
+#define TT_D64 3 /* D64 Mode Transfers */
+
+/*
+ * Error codes.
+ */
+
+#define MACSI_GOOD_STATUS 0x00 /* Good status */
+#define MACSI_QUEUE_FULL 0x01 /* The work queue is full */
+#define MACSI_CMD_CODE_ERR 0x04 /* The IOPB command field is invalid */
+#define MACSI_QUEUE_NUMBER_ERR 0x05 /* Invalid queue number */
+
+#define RESET_BUS_STATUS 0x11 /* SCSI bus reset IOPB forced this */
+#define NO_SECONDARY_PORT 0x12 /* second SCSI bus not available */
+#define SCSI_DEVICE_IS_RESET 0x14 /* device has been reset */
+#define CMD_ABORT_BY_RESET 0x15 /* device has been reset */
+
+#define VME_BUS_ERROR 0x20 /* There was a VME BUS error */
+#define VME_BUS_ACC_TIMEOUT 0x21
+#define VME_BUS_BAD_ADDR 0x23
+#define VME_BUS_BAD_MEM_TYPE 0x24
+#define VME_BUS_BAD_COUNT 0x25
+#define VME_BUS_FETCH_ERROR 0x26
+#define VME_BUS_FETCH_TIMEOUT 0x27
+#define VME_BUS_POST_ERROR 0x28
+#define VME_BUS_POST_TIMEOUT 0x29
+#define VME_BUS_BAD_FETCH_ADDR 0x2A
+#define VME_BUS_BAD_POST_ADDR 0x2B
+#define VME_BUS_SG_FETCH 0x2C
+#define VME_BUS_SG_TIMEOUT 0x2D
+#define VME_BUS_SG_COUNT 0x2E
+
+#define SCSI_SELECTION_TO 0x30 /* select time out */
+#define SCSI_DISCONNECT_TIMEOUT 0x31 /* disconnect timeout */
+#define SCSI_ABNORMAL_SEQ 0x32 /* abnormal sequence */
+#define SCSI_DISCONNECT_ERR 0x33 /* disconnect error */
+#define SCSI_XFER_EXCEPTION 0x34 /* transfer cnt exception */
+#define SCSI_PARITY_ERROR 0x35 /* parity error */
+
+#define DEVICE_NO_IOPB 0x82 /* IOPB no available */
+#define IOPB_CTLR_EHX 0x83 /* IOPB counter exhausted */
+#define IOPB_DIR_ERROR 0x84 /* IOPB direction wrong */
+#define COUGAR_ERROR 0x86 /* COUGAR unrecoverable error */
+#define MACSI_INCORRECT_HARDWARE 0x90 /* Insufficient memory */
+#define MACSI_ILGL_IOPB_VAL 0x92 /* Invalid field in the IOPB */
+#define MACSI_ILLEGAL_IMAGE 0x9C /* Submitted fails reuested action */
+#define IOPB_TYPE_ERR 0xC0 /* IOPB type not 0 */
+#define IOPB_TIMEOUT 0xC1 /* IOPB timed out */
+
+#define COUGAR_PANIC 0xFF /* COUGAR paniced */
+
+#define MACSI_INVALID_TIMEOUT 0x843 /* The SCSI byte to byte timer expired */
+
+/*
+ * Handy vector macro.
+ */
+
+#define VEC(c, vec) (((c) -> mc_ipl << 8) + (vec))
+
+/*
+ * VME addressing modes
+ */
+
+#define ADRM_STD_S_P 0x3E /* Standard Supervisory Program */
+#define ADRM_STD_S_D 0x3D /* Standard Supervisory Data */
+#define ADRM_STD_N_P 0x3A /* Standard Normal Program */
+#define ADRM_STD_N_D 0x39 /* Standard Normal Data */
+#define ADRM_SHT_S_IO 0x2D /* Short Supervisory IO */
+#define ADRM_SHT_N_IO 0x29 /* Short Normal IO */
+#define ADRM_EXT_S_P 0x0E /* Extended Supervisory Program */
+#define ADRM_EXT_S_D 0x0D /* Extended Supervisory Data */
+#define ADRM_EXT_N_P 0x0A /* Extended Normal Program */
+#define ADRM_EXT_N_D 0x09 /* Extended Normal Data */
+#define ADRM_EXT_S_BM 0x0F /* Extended Supervisory Block Mode */
+#define ADRM_EXT_S_D64 0x0C /* Extended Supervisory D64 Mode */
+
+#define ADDR_MOD ( (TT_NORMAL << 10) | (MEMTYPE << 8) | ADRM_EXT_S_D )
+#define BLOCK_MOD ( (TT_BLOCK << 10) | (MEMTYPE << 8) | ADRM_EXT_S_BM )
+#define D64_MOD ( (TT_D64 << 10) | (MEMTYPE << 8) | ADRM_EXT_S_D64 )
+#define SHIO_MOD ( (TT_NORMAL << 10) | (MEMT_SHIO << 8) | ADRM_SHT_N_IO)
+
+/*
+ * Scatter/gather functions
+ */
+
+M328_SG vs_alloc_scatter_gather __P((void));
+void vs_dealloc_scatter_gather __P((M328_SG sg));
+void vs_link_scatter_gather_element __P((sg_list_element_t *element,
+ register vm_offset_t phys_add,
+ register int len));
+void vs_link_scatter_gather_list __P((sg_list_element_t *list,
+ register vm_offset_t phys_add,
+ register int elements));
+M328_SG vs_build_memory_structure __P((struct scsi_xfer *xs, M328_IOPB *iopb));
+
+#endif /* _M328REG_H_ */
diff --git a/sys/arch/mvme68k/dev/vsvar.h b/sys/arch/mvme68k/dev/vsvar.h
new file mode 100644
index 00000000000..b72a86cf4e9
--- /dev/null
+++ b/sys/arch/mvme68k/dev/vsvar.h
@@ -0,0 +1,132 @@
+/* $OpenBSD: vsvar.h,v 1.1 2000/01/25 04:18:18 smurph Exp $ */
+/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+#ifndef _VSVAR_H_
+#define _VSVAR_H_
+
+/*
+ * The largest single request will be MAXPHYS bytes which will require
+ * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
+ * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
+ * buffer is not page aligned (+1).
+ */
+#define DMAMAXIO (MAXPHYS/NBPG+1)
+#define LO(x) (u_short)((unsigned long)x & 0x0000FFFF)
+#define HI(x) (u_short)((unsigned long)x >> 16)
+#define OFF(x) (u_short)((long)kvtop(x) - (long)kvtop(sc->sc_vsreg))
+
+struct vs_tinfo {
+ int cmds; /* #commands processed */
+ int dconns; /* #disconnects */
+ int touts; /* #timeouts */
+ int perrs; /* #parity errors */
+ int senses; /* #request sense commands sent */
+ ushort lubusy; /* What local units/subr. are busy? */
+ u_char flags;
+ u_char period; /* Period suggestion */
+ u_char offset; /* Offset suggestion */
+ int avail; /* Is there a device there */
+} tinfo_t;
+
+struct vs_softc {
+ struct device sc_dev;
+ struct intrhand sc_ih_e;
+ struct intrhand sc_ih_n;
+ struct evcnt sc_intrcnt_e;
+ struct evcnt sc_intrcnt_n;
+ u_short sc_ipl;
+ u_short sc_evec;
+ u_short sc_nvec;
+ struct scsi_link sc_link; /* proto for sub devices */
+ u_long sc_chnl; /* channel 0 or 1 for dual bus cards */
+ u_long sc_qhp; /* Command queue head pointer */
+ struct vsreg *sc_vsreg;
+#define SIOP_NACB 8
+ struct vs_tinfo sc_tinfo[8];
+ u_char sc_flags;
+ u_char sc_sien;
+ u_char sc_dien;
+ u_char sc_minsync;
+ struct map *hus_map;
+ /* one for each target */
+ struct syncpar {
+ u_char state;
+ u_char sxfer;
+ u_char sbcl;
+ } sc_sync[8];
+};
+
+/* sync states */
+#define SYNC_START 0 /* no sync handshake started */
+#define SYNC_SENT 1 /* we sent sync request, no answer yet */
+#define SYNC_DONE 2 /* target accepted our (or inferior) settings,
+ or it rejected the request and we stay async */
+
+#define IOPB_SCSI 0x20
+#define IOPB_RESET 0x22
+#define IOPB_INIT 0x41
+#define IOPB_WQINIT 0x42
+#define IOPB_DEV_RESET 0x4D
+
+#define OPT_INTEN 0x0001
+#define OPT_INTDIS 0x0000
+#define OPT_SG 0x0002
+#define OPT_SST 0x0004
+#define OPT_SIT 0x0040
+#define OPT_READ 0x0000
+#define OPT_WRITE 0x0100
+
+#define AM_S32 0x01
+#define AM_S16 0x05
+#define AM_16 0x0100
+#define AM_32 0x0200
+#define AM_SHORT 0x0300
+#define AM_NORMAL 0x0000
+#define AM_BLOCK 0x0400
+#define AM_D64BLOCK 0x0C00
+
+#define WQO_AE 0x0001 /* abort enable bit */
+#define WQO_FOE 0x0004 /* freeze on error */
+#define WQO_PE 0x0008 /* parity enable bit */
+#define WQO_ARE 0x0010 /* autosense recovery enable bit */
+#define WQO_RFWQ 0x0020 /* report frozen work queue bit */
+#define WQO_INIT 0x8000 /* work queue init bit */
+
+void vs_minphys __P((struct buf *bp));
+int vs_scsicmd __P((struct scsi_xfer *));
+
+#endif /* _M328VAR_H */