summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-03-12 00:04:58 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-03-12 00:04:58 +0000
commita64ef287e3bc4ca300b0cdca525c011f4c8dcf35 (patch)
tree9b7d2a92a0372201003cfc2ac3df316de5aaca75 /sys
parentd57b8b0940d9b2c0bc9222002b7686dcbdb9843d (diff)
Preliminary port of NetBSD oosiop driver, for NCR53C700 chips, as commonly
encountered on the oldest hppa machines. Currently compiled in, but disabled, in the kernel, until it is stable enough - right now read access are fine, but writes eventually time out and do not complete. ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hppa/conf/GENERIC6
-rw-r--r--sys/arch/hppa/conf/RAMDISK6
-rw-r--r--sys/arch/hppa/conf/files.hppa5
-rw-r--r--sys/arch/hppa/gsc/oosiop_gsc.c169
-rw-r--r--sys/arch/hppa/gsc/osiop_gsc.c26
-rw-r--r--sys/dev/ic/oosiop.c1378
-rw-r--r--sys/dev/ic/oosiopreg.h324
-rw-r--r--sys/dev/ic/oosiopvar.h164
-rw-r--r--sys/dev/microcode/siop/Makefile11
-rw-r--r--sys/dev/microcode/siop/ncr53cxxx.c10
-rw-r--r--sys/dev/microcode/siop/oosiop.ss150
11 files changed, 2221 insertions, 28 deletions
diff --git a/sys/arch/hppa/conf/GENERIC b/sys/arch/hppa/conf/GENERIC
index c9e80bb2ee2..69f9c4be934 100644
--- a/sys/arch/hppa/conf/GENERIC
+++ b/sys/arch/hppa/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.47 2004/02/26 02:29:56 mickey Exp $
+# $OpenBSD: GENERIC,v 1.48 2004/03/12 00:04:56 miod Exp $
# Machine architecture; required by config(8)
machine hppa
@@ -97,9 +97,11 @@ ie0 at gsc0 irq 8 # 82C596DX/CA ether
#ie* at isa? port 0x300 irq 10
#ie* at pci? dev ? function ?
#tms* at gsc? irq 10 # TMS380C26 Network Controller
-osiop* at gsc? irq 9 # NCR 53C700/710 (Narrow SE)
+osiop* at gsc? irq 9 # NCR 53C710 (Narrow SE)
#osiop* at eisa? slot ?
scsibus* at osiop?
+oosiop* at gsc? disable irq 9 # NCR 53C700 (Narrow SE)
+scsibus* at oosiop?
harmony* at gsc? irq 13 # Audio Type 2 (CS4215/AD1849)
audio* at harmony?
gsckbc* at gsc? irq 26
diff --git a/sys/arch/hppa/conf/RAMDISK b/sys/arch/hppa/conf/RAMDISK
index d04a4e8a6de..130806ac265 100644
--- a/sys/arch/hppa/conf/RAMDISK
+++ b/sys/arch/hppa/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.26 2003/12/29 23:27:04 mickey Exp $
+# $OpenBSD: RAMDISK,v 1.27 2004/03/12 00:04:57 miod Exp $
#
# Diskless kernel config
#
@@ -112,9 +112,11 @@ ie0 at gsc0 irq 8 # 82C596DX/CA ether
#ie* at isa? port 0x300 irq 10
#ie* at pci? dev ? function ?
#tms* at gsc? irq 10 # TMS380C26 Network Controller
-osiop* at gsc? irq 9 # NCR 53C700/710 (Narrow SE)
+osiop* at gsc? irq 9 # NCR 53C710 (Narrow SE)
#osiop* at eisa? slot ?
scsibus* at osiop?
+oosiop* at gsc? disable irq 9 # NCR 53C700 (Narrow SE)
+scsibus* at oosiop?
#harmony* at gsc? irq 13 # Audio Type 2 (CS4215/AD1849)
#audio* at harmony?
gsckbc* at gsc? irq 26
diff --git a/sys/arch/hppa/conf/files.hppa b/sys/arch/hppa/conf/files.hppa
index 23f3a60e089..4021d88bdec 100644
--- a/sys/arch/hppa/conf/files.hppa
+++ b/sys/arch/hppa/conf/files.hppa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.hppa,v 1.50 2004/02/13 20:39:31 mickey Exp $
+# $OpenBSD: files.hppa,v 1.51 2004/03/12 00:04:57 miod Exp $
#
# hppa-specific configuration info
@@ -191,6 +191,9 @@ file arch/hppa/gsc/if_ie_gsc.c ie_gsc
attach osiop at gsc with osiop_gsc
file arch/hppa/gsc/osiop_gsc.c osiop_gsc
+attach oosiop at gsc with oosiop_gsc
+file arch/hppa/gsc/oosiop_gsc.c oosiop_gsc
+
attach hil at gsc with hil_gsc
file arch/hppa/gsc/hil_gsc.c hil_gsc
diff --git a/sys/arch/hppa/gsc/oosiop_gsc.c b/sys/arch/hppa/gsc/oosiop_gsc.c
new file mode 100644
index 00000000000..80cec2b516e
--- /dev/null
+++ b/sys/arch/hppa/gsc/oosiop_gsc.c
@@ -0,0 +1,169 @@
+/* $OpenBSD: oosiop_gsc.c,v 1.1 2004/03/12 00:04:57 miod Exp $ */
+/* $NetBSD: oosiop_gsc.c,v 1.2 2003/07/15 02:29:25 lukem Exp $ */
+
+/*
+ * Copyright (c) 2001 Matt Fredette. All rights reserved.
+ * Copyright (c) 2001,2002 Izumi Tsutsui. 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. 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 AUTHORS ``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 AUTHORS 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) 1998 Michael Shalayeff
+ * 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 Michael Shalayeff.
+ * 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/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/iomod.h>
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/ic/oosiopreg.h>
+#include <dev/ic/oosiopvar.h>
+
+#include <hppa/dev/cpudevs.h>
+#include <hppa/gsc/gscbusvar.h>
+
+#define OOSIOP_GSC_RESET 0x0000
+#define OOSIOP_GSC_OFFSET 0x0100
+
+int oosiop_gsc_match(struct device *, void *, void *);
+void oosiop_gsc_attach(struct device *, struct device *, void *);
+int oosiop_gsc_intr(void *);
+
+struct cfattach oosiop_gsc_ca = {
+ sizeof(struct oosiop_softc), oosiop_gsc_match, oosiop_gsc_attach
+};
+
+int
+oosiop_gsc_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct gsc_attach_args *ga = aux;
+
+ if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
+ ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI)
+ return 0;
+
+ return 1;
+}
+
+void
+oosiop_gsc_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct oosiop_softc *sc = (void *)self;
+ struct gsc_attach_args *ga = aux;
+ bus_space_handle_t ioh;
+
+ sc->sc_bst = ga->ga_iot;
+ sc->sc_dmat = ga->ga_dmatag;
+ if (bus_space_map(sc->sc_bst, ga->ga_hpa,
+ OOSIOP_GSC_OFFSET + OOSIOP_NREGS, 0, &ioh))
+ panic("oosiop_gsc_attach: couldn't map I/O ports");
+ if (bus_space_subregion(sc->sc_bst, ioh,
+ OOSIOP_GSC_OFFSET, OOSIOP_NREGS, &sc->sc_bsh))
+ panic("oosiop_gsc_attach: couldn't get chip ports");
+
+ sc->sc_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14];
+ if (!sc->sc_freq)
+ sc->sc_freq = 50 * 1000000;
+
+ sc->sc_chip = OOSIOP_700;
+ sc->sc_id = 7; /* XXX */
+
+ /*
+ * Reset the SCSI subsystem.
+ */
+ bus_space_write_1(sc->sc_bst, ioh, OOSIOP_GSC_RESET, 0);
+ DELAY(1000);
+
+ /*
+ * Call common attachment
+ */
+#ifdef OOSIOP_DEBUG
+ {
+ extern int oosiop_debug;
+ oosiop_debug = -1;
+ }
+#endif /* OOSIOP_DEBUG */
+ oosiop_attach(sc);
+
+ (void)gsc_intr_establish((struct gsc_softc *)parent,
+ ga->ga_irq, IPL_BIO, oosiop_gsc_intr, sc, sc->sc_dev.dv_xname);
+}
+
+/*
+ * interrupt handler
+ */
+int
+oosiop_gsc_intr(arg)
+ void *arg;
+{
+ struct oosiop_softc *sc = arg;
+ int rv;
+
+ rv = oosiop_intr(sc);
+
+#ifdef USELEDS
+ ledctl(PALED_DISK, 0, 0);
+#endif
+
+ return (rv);
+}
diff --git a/sys/arch/hppa/gsc/osiop_gsc.c b/sys/arch/hppa/gsc/osiop_gsc.c
index f9b879148a0..c928bdd5dd0 100644
--- a/sys/arch/hppa/gsc/osiop_gsc.c
+++ b/sys/arch/hppa/gsc/osiop_gsc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: osiop_gsc.c,v 1.10 2004/02/13 21:28:19 mickey Exp $ */
+/* $OpenBSD: osiop_gsc.c,v 1.11 2004/03/12 00:04:57 miod Exp $ */
/* $NetBSD: osiop_gsc.c,v 1.6 2002/10/02 05:17:50 thorpej Exp $ */
/*
@@ -79,7 +79,7 @@
#include <hppa/gsc/gscbusvar.h>
/* #include <hppa/hppa/machdep.h> */
-#define OSIOP_GSC_RESET 0x0000
+#define OSIOP_GSC_RESET 0x0000
#define OSIOP_GSC_OFFSET 0x0100
int osiop_gsc_match(struct device *, void *, void *);
@@ -98,8 +98,7 @@ osiop_gsc_match(parent, match, aux)
struct gsc_attach_args *ga = aux;
if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
- (ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI /* &&
- ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI */))
+ ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI)
return 0;
return 1;
@@ -117,27 +116,20 @@ osiop_gsc_attach(parent, self, aux)
sc->sc_bst = ga->ga_iot;
sc->sc_dmat = ga->ga_dmatag;
if (bus_space_map(sc->sc_bst, ga->ga_hpa,
- OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
+ OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
panic("osiop_gsc_attach: couldn't map I/O ports");
if (bus_space_subregion(sc->sc_bst, ioh,
- OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg))
+ OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg))
panic("osiop_gsc_attach: couldn't get chip ports");
sc->sc_clock_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14] / 1000000;
if (!sc->sc_clock_freq)
sc->sc_clock_freq = 50;
- if (ga->ga_ca.ca_type.iodc_sv_model == HPPA_FIO_GSCSI) {
- sc->sc_dcntl = OSIOP_DCNTL_EA;
- /* XXX set burst mode to 8 words (32 bytes) */
- sc->sc_ctest7 = OSIOP_CTEST7_CDIS;
- sc->sc_dmode = OSIOP_DMODE_BL8; /* | OSIOP_DMODE_FC2 */
- } else {
- sc->sc_dcntl = 0;
- sc->sc_ctest7 = 0;
- sc->sc_dmode = 0; /* | OSIOP_DMODE_FC2 */
- }
-
+ sc->sc_dcntl = OSIOP_DCNTL_EA;
+ /* XXX set burst mode to 8 words (32 bytes) */
+ sc->sc_ctest7 = OSIOP_CTEST7_CDIS;
+ sc->sc_dmode = OSIOP_DMODE_BL8; /* | OSIOP_DMODE_FC2 */
sc->sc_flags = 0;
sc->sc_id = 7; /* XXX */
diff --git a/sys/dev/ic/oosiop.c b/sys/dev/ic/oosiop.c
new file mode 100644
index 00000000000..dc633457488
--- /dev/null
+++ b/sys/dev/ic/oosiop.c
@@ -0,0 +1,1378 @@
+/* $OpenBSD: oosiop.c,v 1.1 2004/03/12 00:04:57 miod Exp $ */
+/* $NetBSD: oosiop.c,v 1.4 2003/10/29 17:45:55 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 2001 Shuichiro URATA. 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. 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.
+ */
+
+/*
+ * NCR53C700 SCSI I/O processor (OOSIOP) driver
+ *
+ * TODO:
+ * - More better error handling.
+ * - Implement tagged queuing.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/timeout.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_message.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <dev/ic/oosiopreg.h>
+#include <dev/ic/oosiopvar.h>
+
+/* 53C700 script */
+#include <dev/microcode/siop/oosiop.out>
+
+int oosiop_alloc_cb(struct oosiop_softc *, int);
+
+static __inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t);
+static __inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t);
+static __inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t,
+ int);
+static __inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t,
+ bus_addr_t);
+static __inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t,
+ bus_size_t, bus_addr_t);
+
+void oosiop_load_script(struct oosiop_softc *);
+void oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *);
+void oosiop_setup_dma(struct oosiop_softc *);
+void oosiop_flush_fifo(struct oosiop_softc *);
+void oosiop_clear_fifo(struct oosiop_softc *);
+void oosiop_phasemismatch(struct oosiop_softc *);
+void oosiop_setup_syncxfer(struct oosiop_softc *);
+void oosiop_set_syncparam(struct oosiop_softc *, int, int, int);
+void oosiop_minphys(struct buf *);
+int oosiop_scsicmd(struct scsi_xfer *);
+void oosiop_done(struct oosiop_softc *, struct oosiop_cb *);
+void oosiop_timeout(void *);
+void oosiop_reset(struct oosiop_softc *);
+void oosiop_reset_bus(struct oosiop_softc *);
+void oosiop_scriptintr(struct oosiop_softc *);
+void oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *);
+
+/* Trap interrupt code for unexpected data I/O */
+#define DATAIN_TRAP 0xdead0001
+#define DATAOUT_TRAP 0xdead0002
+
+/* Possible TP and SCF conbination */
+static const struct {
+ u_int8_t tp;
+ u_int8_t scf;
+} synctbl[] = {
+ {0, 1}, /* SCLK / 4.0 */
+ {1, 1}, /* SCLK / 5.0 */
+ {2, 1}, /* SCLK / 6.0 */
+ {3, 1}, /* SCLK / 7.0 */
+ {1, 2}, /* SCLK / 7.5 */
+ {4, 1}, /* SCLK / 8.0 */
+ {5, 1}, /* SCLK / 9.0 */
+ {6, 1}, /* SCLK / 10.0 */
+ {3, 2}, /* SCLK / 10.5 */
+ {7, 1}, /* SCLK / 11.0 */
+ {4, 2}, /* SCLK / 12.0 */
+ {5, 2}, /* SCLK / 13.5 */
+ {3, 3}, /* SCLK / 14.0 */
+ {6, 2}, /* SCLK / 15.0 */
+ {4, 3}, /* SCLK / 16.0 */
+ {7, 2}, /* SCLK / 16.5 */
+ {5, 3}, /* SCLK / 18.0 */
+ {6, 3}, /* SCLK / 20.0 */
+ {7, 3} /* SCLK / 22.0 */
+};
+#define NSYNCTBL (sizeof(synctbl) / sizeof(synctbl[0]))
+
+#define oosiop_period(sc, tp, scf) \
+ (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40)
+
+struct cfdriver oosiop_cd = {
+ NULL, "oosiop", DV_DULL
+};
+
+struct scsi_adapter oosiop_adapter = {
+ oosiop_scsicmd,
+ oosiop_minphys,
+ NULL,
+ NULL
+};
+
+struct scsi_device oosiop_dev = {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+void
+oosiop_attach(struct oosiop_softc *sc)
+{
+ bus_size_t scrsize;
+ bus_dma_segment_t seg;
+ struct oosiop_cb *cb;
+ int err, i, nseg;
+
+ /*
+ * Allocate DMA-safe memory for the script and map it.
+ */
+ scrsize = round_page(sizeof(oosiop_script));
+ err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1,
+ &nseg, BUS_DMA_NOWAIT);
+ if (err) {
+ printf(": failed to allocate script memory, err=%d\n", err);
+ return;
+ }
+ err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize,
+ (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ if (err) {
+ printf(": failed to map script memory, err=%d\n", err);
+ return;
+ }
+ err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0,
+ BUS_DMA_NOWAIT, &sc->sc_scrdma);
+ if (err) {
+ printf(": failed to create script map, err=%d\n", err);
+ return;
+ }
+ err = bus_dmamap_load(sc->sc_dmat, sc->sc_scrdma, sc->sc_scr, scrsize,
+ NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
+ if (err) {
+ printf(": failed to load script map, err=%d\n", err);
+ return;
+ }
+ bzero(sc->sc_scr, scrsize);
+ sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr;
+
+ /* Initialize command block array */
+ TAILQ_INIT(&sc->sc_free_cb);
+ TAILQ_INIT(&sc->sc_cbq);
+ if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0)
+ return;
+
+ /* Use first cb to reselection msgin buffer */
+ cb = TAILQ_FIRST(&sc->sc_free_cb);
+ sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr +
+ offsetof(struct oosiop_xfer, msgin[0]);
+
+ for (i = 0; i < OOSIOP_NTGT; i++) {
+ sc->sc_tgt[i].nexus = NULL;
+ sc->sc_tgt[i].flags = 0;
+ }
+
+ /* Setup asynchronous clock divisor parameters */
+ if (sc->sc_freq <= 25000000) {
+ sc->sc_ccf = 10;
+ sc->sc_dcntl = OOSIOP_DCNTL_CF_1;
+ } else if (sc->sc_freq <= 37500000) {
+ sc->sc_ccf = 15;
+ sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5;
+ } else if (sc->sc_freq <= 50000000) {
+ sc->sc_ccf = 20;
+ sc->sc_dcntl = OOSIOP_DCNTL_CF_2;
+ } else {
+ sc->sc_ccf = 30;
+ sc->sc_dcntl = OOSIOP_DCNTL_CF_3;
+ }
+
+ if (sc->sc_chip == OOSIOP_700)
+ sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf);
+ else
+ sc->sc_minperiod = oosiop_period(sc, 4, 10);
+
+ if (sc->sc_minperiod < 25)
+ sc->sc_minperiod = 25; /* limit to 10MB/s */
+
+ printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n",
+ sc->sc_chip == OOSIOP_700_66 ? "-66" : "",
+ oosiop_read_1(sc, OOSIOP_CTEST7) >> 4,
+ sc->sc_freq / 1000000, sc->sc_id);
+ /*
+ * Reset all
+ */
+ oosiop_reset(sc);
+ oosiop_reset_bus(sc);
+
+ /*
+ * Start SCRIPTS processor
+ */
+ oosiop_load_script(sc);
+ sc->sc_active = 0;
+ oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect);
+
+ /*
+ * Fill in the sc_link.
+ */
+ sc->sc_link.adapter = &oosiop_adapter;
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.device = &oosiop_dev;
+ sc->sc_link.openings = 4;
+ sc->sc_link.adapter_buswidth = OOSIOP_NTGT;
+ sc->sc_link.adapter_target = sc->sc_id;
+ sc->sc_link.quirks = ADEV_NODOORLOCK;
+
+ /*
+ * Now try to attach all the sub devices.
+ */
+ config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
+}
+
+int
+oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
+{
+ struct oosiop_cb *cb;
+ struct oosiop_xfer *xfer;
+ bus_size_t xfersize;
+ bus_dma_segment_t seg;
+ int i, s, err, nseg;
+
+ /*
+ * Allocate oosiop_cb.
+ */
+ cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT);
+ if (cb == NULL) {
+ printf(": failed to allocate cb memory\n");
+ return (ENOMEM);
+ }
+ bzero(cb, sizeof(struct oosiop_cb) * ncb);
+
+ /*
+ * Allocate DMA-safe memory for the oosiop_xfer and map it.
+ */
+ xfersize = sizeof(struct oosiop_xfer) * ncb;
+ err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1,
+ &nseg, BUS_DMA_NOWAIT);
+ if (err) {
+ printf(": failed to allocate xfer block memory, err=%d\n", err);
+ return (err);
+ }
+ err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
+ (caddr_t *)(void *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ if (err) {
+ printf(": failed to map xfer block memory, err=%d\n", err);
+ return (err);
+ }
+
+ /* Initialize each command block */
+ for (i = 0; i < ncb; i++) {
+ err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
+ 0, BUS_DMA_NOWAIT, &cb->cmddma);
+ if (err) {
+ printf(": failed to create cmddma map, err=%d\n", err);
+ return (err);
+ }
+
+ err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER,
+ OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT,
+ &cb->datadma);
+ if (err) {
+ printf(": failed to create datadma map, err=%d\n", err);
+ return (err);
+ }
+
+ err = bus_dmamap_create(sc->sc_dmat,
+ sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer),
+ 0, BUS_DMA_NOWAIT, &cb->xferdma);
+ if (err) {
+ printf(": failed to create xfer block map, err=%d\n",
+ err);
+ return (err);
+ }
+ err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer,
+ sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT);
+ if (err) {
+ printf(": failed to load xfer block, err=%d\n", err);
+ return (err);
+ }
+
+ cb->xfer = xfer;
+
+ s = splbio();
+ TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+ splx(s);
+
+ cb++;
+ xfer++;
+ }
+
+ return (0);
+}
+
+static __inline void
+oosiop_relocate_io(struct oosiop_softc *sc, bus_addr_t addr)
+{
+ u_int32_t dcmd;
+ int32_t dsps;
+
+ dcmd = letoh32(sc->sc_scr[addr / 4 + 0]);
+ dsps = letoh32(sc->sc_scr[addr / 4 + 1]);
+
+ /* convert relative to absolute */
+ if (dcmd & 0x04000000) {
+ dcmd &= ~0x04000000;
+#if 0
+ /*
+ * sign extension isn't needed here because
+ * ncr53cxxx.c generates 32 bit dsps.
+ */
+ dsps <<= 8;
+ dsps >>= 8;
+#endif
+ sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
+ dsps += addr + 8;
+ }
+
+ sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
+}
+
+static __inline void
+oosiop_relocate_tc(struct oosiop_softc *sc, bus_addr_t addr)
+{
+ u_int32_t dcmd;
+ int32_t dsps;
+
+ dcmd = letoh32(sc->sc_scr[addr / 4 + 0]);
+ dsps = letoh32(sc->sc_scr[addr / 4 + 1]);
+
+ /* convert relative to absolute */
+ if (dcmd & 0x00800000) {
+ dcmd &= ~0x00800000;
+ sc->sc_scr[addr / 4] = htole32(dcmd);
+#if 0
+ /*
+ * sign extension isn't needed here because
+ * ncr53cxxx.c generates 32 bit dsps.
+ */
+ dsps <<= 8;
+ dsps >>= 8;
+#endif
+ dsps += addr + 8;
+ }
+
+ sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
+}
+
+static __inline void
+oosiop_fixup_select(struct oosiop_softc *sc, bus_addr_t addr, int id)
+{
+ u_int32_t dcmd;
+
+ dcmd = letoh32(sc->sc_scr[addr / 4]);
+ dcmd &= 0xff00ffff;
+ dcmd |= 0x00010000 << id;
+ sc->sc_scr[addr / 4] = htole32(dcmd);
+}
+
+static __inline void
+oosiop_fixup_jump(struct oosiop_softc *sc, bus_addr_t addr, bus_addr_t dst)
+{
+
+ sc->sc_scr[addr / 4 + 1] = htole32(dst);
+}
+
+static __inline void
+oosiop_fixup_move(struct oosiop_softc *sc, bus_addr_t addr, bus_size_t dbc,
+ bus_addr_t dsps)
+{
+ u_int32_t dcmd;
+
+ dcmd = letoh32(sc->sc_scr[addr / 4]);
+ dcmd &= 0xff000000;
+ dcmd |= dbc & 0x00ffffff;
+ sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
+ sc->sc_scr[addr / 4 + 1] = htole32(dsps);
+}
+
+void
+oosiop_load_script(struct oosiop_softc *sc)
+{
+ int i;
+
+ /* load script */
+ for (i = 0; i < sizeof(oosiop_script) / sizeof(oosiop_script[0]); i++)
+ sc->sc_scr[i] = htole32(oosiop_script[i]);
+
+ /* relocate script */
+ for (i = 0; i < (sizeof(oosiop_script) / 8); i++) {
+ switch (oosiop_script[i * 2] >> 27) {
+ case 0x08: /* select */
+ case 0x0a: /* wait reselect */
+ oosiop_relocate_io(sc, i * 8);
+ break;
+ case 0x10: /* jump */
+ case 0x11: /* call */
+ oosiop_relocate_tc(sc, i * 8);
+ break;
+ }
+ }
+
+ oosiop_fixup_move(sc, Ent_p_resel_msgin_move, 1, sc->sc_reselbuf);
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+}
+
+void
+oosiop_setup_sgdma(struct oosiop_softc *sc, struct oosiop_cb *cb)
+{
+ struct oosiop_xfer *xfer = cb->xfer;
+ struct scsi_xfer *xs = cb->xs;
+ int i, n, off;
+
+ OOSIOP_XFERSCR_SYNC(sc, cb,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ off = cb->curdp;
+
+ if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
+ /* Find start segment */
+ for (i = 0; i < cb->datadma->dm_nsegs; i++) {
+ if (off < cb->datadma->dm_segs[i].ds_len)
+ break;
+ off -= cb->datadma->dm_segs[i].ds_len;
+ }
+
+ /* build MOVE block */
+ if (xs->flags & SCSI_DATA_IN) {
+ n = 0;
+ while (i < cb->datadma->dm_nsegs) {
+ xfer->datain_scr[n * 2 + 0] =
+ htole32(0x09000000 |
+ (cb->datadma->dm_segs[i].ds_len - off));
+ xfer->datain_scr[n * 2 + 1] =
+ htole32(cb->datadma->dm_segs[i].ds_addr +
+ off);
+ n++;
+ i++;
+ off = 0;
+ }
+ xfer->datain_scr[n * 2 + 0] = htole32(0x80080000);
+ xfer->datain_scr[n * 2 + 1] =
+ htole32(sc->sc_scrbase + Ent_phasedispatch);
+ }
+ if (xs->flags & SCSI_DATA_OUT) {
+ n = 0;
+ while (i < cb->datadma->dm_nsegs) {
+ xfer->dataout_scr[n * 2 + 0] =
+ htole32(0x08000000 |
+ (cb->datadma->dm_segs[i].ds_len - off));
+ xfer->dataout_scr[n * 2 + 1] =
+ htole32(cb->datadma->dm_segs[i].ds_addr +
+ off);
+ n++;
+ i++;
+ off = 0;
+ }
+ xfer->dataout_scr[n * 2 + 0] = htole32(0x80080000);
+ xfer->dataout_scr[n * 2 + 1] =
+ htole32(sc->sc_scrbase + Ent_phasedispatch);
+ }
+ }
+ if ((xs->flags & SCSI_DATA_IN) == 0) {
+ xfer->datain_scr[0] = htole32(0x98080000);
+ xfer->datain_scr[1] = htole32(DATAIN_TRAP);
+ }
+ if ((xs->flags & SCSI_DATA_OUT) == 0) {
+ xfer->dataout_scr[0] = htole32(0x98080000);
+ xfer->dataout_scr[1] = htole32(DATAOUT_TRAP);
+ }
+ OOSIOP_XFERSCR_SYNC(sc, cb,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+}
+
+/*
+ * Setup DMA pointer into script.
+ */
+void
+oosiop_setup_dma(struct oosiop_softc *sc)
+{
+ struct oosiop_cb *cb;
+ bus_addr_t xferbase;
+
+ cb = sc->sc_curcb;
+ xferbase = cb->xferdma->dm_segs[0].ds_addr;
+
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+
+ oosiop_fixup_select(sc, Ent_p_select, cb->id);
+ oosiop_fixup_jump(sc, Ent_p_datain_jump, xferbase +
+ offsetof(struct oosiop_xfer, datain_scr[0]));
+ oosiop_fixup_jump(sc, Ent_p_dataout_jump, xferbase +
+ offsetof(struct oosiop_xfer, dataout_scr[0]));
+ oosiop_fixup_move(sc, Ent_p_msgin_move, 1, xferbase +
+ offsetof(struct oosiop_xfer, msgin[0]));
+ oosiop_fixup_move(sc, Ent_p_extmsglen_move, 1, xferbase +
+ offsetof(struct oosiop_xfer, msgin[1]));
+ oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, xferbase +
+ offsetof(struct oosiop_xfer, msgout[0]));
+ oosiop_fixup_move(sc, Ent_p_status_move, 1, xferbase +
+ offsetof(struct oosiop_xfer, status));
+ oosiop_fixup_move(sc, Ent_p_cmdout_move, cb->xs->cmdlen,
+ cb->cmddma->dm_segs[0].ds_addr);
+
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+}
+
+void
+oosiop_flush_fifo(struct oosiop_softc *sc)
+{
+
+ oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
+ OOSIOP_DFIFO_FLF);
+ while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
+ OOSIOP_CTEST1_FMT)
+ ;
+ oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
+ ~OOSIOP_DFIFO_FLF);
+}
+
+void
+oosiop_clear_fifo(struct oosiop_softc *sc)
+{
+
+ oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
+ OOSIOP_DFIFO_CLF);
+ while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
+ OOSIOP_CTEST1_FMT)
+ ;
+ oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
+ ~OOSIOP_DFIFO_CLF);
+}
+
+void
+oosiop_phasemismatch(struct oosiop_softc *sc)
+{
+ struct oosiop_cb *cb;
+ u_int32_t dsp, dbc, n, i, len;
+ u_int8_t dfifo, sstat1;
+
+ cb = sc->sc_curcb;
+ if (cb == NULL)
+ return;
+
+ dsp = oosiop_read_4(sc, OOSIOP_DSP);
+ dbc = oosiop_read_4(sc, OOSIOP_DBC) & OOSIOP_DBC_MAX;
+ len = 0;
+
+ n = dsp - cb->xferdma->dm_segs[0].ds_addr - 8;
+ if (n >= offsetof(struct oosiop_xfer, datain_scr[0]) &&
+ n < offsetof(struct oosiop_xfer, datain_scr[OOSIOP_NSG * 2])) {
+ n -= offsetof(struct oosiop_xfer, datain_scr[0]);
+ n >>= 3;
+ OOSIOP_DINSCR_SYNC(sc, cb,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ for (i = 0; i <= n; i++)
+ len += letoh32(cb->xfer->datain_scr[i * 2]) &
+ 0x00ffffff;
+ OOSIOP_DINSCR_SYNC(sc, cb,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ /* All data in the chip are already flushed */
+ } else if (n >= offsetof(struct oosiop_xfer, dataout_scr[0]) &&
+ n < offsetof(struct oosiop_xfer, dataout_scr[OOSIOP_NSG * 2])) {
+ n -= offsetof(struct oosiop_xfer, dataout_scr[0]);
+ n >>= 3;
+ OOSIOP_DOUTSCR_SYNC(sc, cb,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ for (i = 0; i <= n; i++)
+ len += letoh32(cb->xfer->dataout_scr[i * 2]) &
+ 0x00ffffff;
+ OOSIOP_DOUTSCR_SYNC(sc, cb,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ dfifo = oosiop_read_1(sc, OOSIOP_DFIFO);
+ dbc += ((dfifo & OOSIOP_DFIFO_BO) - (dbc & OOSIOP_DFIFO_BO)) &
+ OOSIOP_DFIFO_BO;
+
+ sstat1 = oosiop_read_1(sc, OOSIOP_SSTAT1);
+ if (sstat1 & OOSIOP_SSTAT1_OLF)
+ dbc++;
+ if ((sc->sc_tgt[cb->id].sxfer != 0) &&
+ (sstat1 & OOSIOP_SSTAT1_ORF) != 0)
+ dbc++;
+
+ oosiop_clear_fifo(sc);
+ } else {
+ printf("%s: phase mismatch addr=%08x\n", sc->sc_dev.dv_xname,
+ oosiop_read_4(sc, OOSIOP_DSP) - 8);
+ oosiop_clear_fifo(sc);
+ return;
+ }
+
+ len -= dbc;
+ if (len) {
+ cb->curdp += len;
+ oosiop_setup_sgdma(sc, cb);
+ }
+}
+
+void
+oosiop_setup_syncxfer(struct oosiop_softc *sc)
+{
+ int id;
+
+ id = sc->sc_curcb->id;
+ if (sc->sc_chip != OOSIOP_700)
+ oosiop_write_1(sc, OOSIOP_SBCL, sc->sc_tgt[id].scf);
+
+ oosiop_write_1(sc, OOSIOP_SXFER, sc->sc_tgt[id].sxfer);
+}
+
+void
+oosiop_set_syncparam(struct oosiop_softc *sc, int id, int period, int offset)
+{
+ int i, p;
+
+ printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, id);
+
+ if (offset == 0) {
+ /* Asynchronous */
+ sc->sc_tgt[id].scf = 0;
+ sc->sc_tgt[id].sxfer = 0;
+ printf("asynchronous");
+ } else {
+ /* Synchronous */
+ if (sc->sc_chip == OOSIOP_700) {
+ for (i = 4; i < 12; i++) {
+ p = oosiop_period(sc, i, sc->sc_ccf);
+ if (p >= period)
+ break;
+ }
+ if (i == 12) {
+ printf("%s: target %d period too large\n",
+ sc->sc_dev.dv_xname, id);
+ i = 11; /* XXX */
+ }
+ sc->sc_tgt[id].scf = 0;
+ sc->sc_tgt[id].sxfer = ((i - 4) << 4) | offset;
+ } else {
+ for (i = 0; i < NSYNCTBL; i++) {
+ p = oosiop_period(sc, synctbl[i].tp + 4,
+ (synctbl[i].scf + 1) * 5);
+ if (p >= period)
+ break;
+ }
+ if (i == NSYNCTBL) {
+ printf("%s: target %d period too large\n",
+ sc->sc_dev.dv_xname, id);
+ i = NSYNCTBL - 1; /* XXX */
+ }
+ sc->sc_tgt[id].scf = synctbl[i].scf;
+ sc->sc_tgt[id].sxfer = (synctbl[i].tp << 4) | offset;
+ }
+ /* XXX print actual ns period... */
+ printf(" synchronous");
+ }
+ printf(" xfers\n");
+}
+
+void
+oosiop_minphys(struct buf *bp)
+{
+
+ if (bp->b_bcount > OOSIOP_MAX_XFER)
+ bp->b_bcount = OOSIOP_MAX_XFER;
+ minphys(bp);
+}
+
+int
+oosiop_scsicmd(struct scsi_xfer *xs)
+{
+ struct oosiop_softc *sc;
+ struct oosiop_cb *cb;
+ struct oosiop_xfer *xfer;
+ int s, err;
+
+ sc = (struct oosiop_softc *)xs->sc_link->adapter_softc;
+
+ s = splbio();
+ cb = TAILQ_FIRST(&sc->sc_free_cb);
+ TAILQ_REMOVE(&sc->sc_free_cb, cb, chain);
+ splx(s);
+
+ cb->xs = xs;
+ cb->xsflags = xs->flags;
+ cb->datalen = xs->datalen;
+ cb->flags = 0;
+ cb->id = xs->sc_link->target;
+ cb->lun = xs->sc_link->lun;
+ cb->curdp = 0;
+ cb->savedp = 0;
+ xfer = cb->xfer;
+
+ /* Setup SCSI command buffer DMA */
+ err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, xs->cmd,
+ xs->cmdlen, NULL, ((xs->flags & SCSI_NOSLEEP) ?
+ BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_WRITE);
+ if (err) {
+ printf("%s: unable to load cmd DMA map: %d",
+ sc->sc_dev.dv_xname, err);
+ xs->error = XS_DRIVER_STUFFUP;
+ TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+ scsi_done(xs);
+ return (COMPLETE);
+ }
+ bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
+ BUS_DMASYNC_PREWRITE);
+
+ /* Setup data buffer DMA */
+ if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
+ err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
+ xs->data, xs->datalen, NULL,
+ ((xs->flags & SCSI_NOSLEEP) ?
+ BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
+ BUS_DMA_STREAMING |
+ ((xs->flags & SCSI_DATA_IN) ? BUS_DMA_READ :
+ BUS_DMA_WRITE));
+ if (err) {
+ printf("%s: unable to load data DMA map: %d",
+ sc->sc_dev.dv_xname, err);
+ xs->error = XS_DRIVER_STUFFUP;
+ bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
+ TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+ scsi_done(xs);
+ return (COMPLETE);
+ }
+ bus_dmamap_sync(sc->sc_dmat, cb->datadma,
+ 0, xs->datalen,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ }
+
+ oosiop_setup_sgdma(sc, cb);
+
+ /* Setup msgout buffer */
+ OOSIOP_XFERMSG_SYNC(sc, cb,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ xfer->msgout[0] = MSG_IDENTIFY(cb->lun,
+ (cb->xfer->scsi_cmd.opcode != REQUEST_SENSE));
+ cb->msgoutlen = 1;
+
+ if (sc->sc_tgt[cb->id].flags & TGTF_SYNCNEG) {
+ /* Send SDTR */
+ xfer->msgout[1] = MSG_EXTENDED;
+ xfer->msgout[2] = MSG_EXT_SDTR_LEN;
+ xfer->msgout[3] = MSG_EXT_SDTR;
+ xfer->msgout[4] = sc->sc_minperiod;
+ xfer->msgout[5] = OOSIOP_MAX_OFFSET;
+ cb->msgoutlen = 6;
+ sc->sc_tgt[cb->id].flags &= ~TGTF_SYNCNEG;
+ sc->sc_tgt[cb->id].flags |= TGTF_WAITSDTR;
+ }
+
+ xfer->status = SCSI_OOSIOP_NOSTATUS;
+
+ OOSIOP_XFERMSG_SYNC(sc, cb,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ s = splbio();
+
+ /*
+ * Always initialize timeout so it does not contain trash
+ * that could confuse timeout_del().
+ */
+ timeout_set(&xs->stimeout, oosiop_timeout, cb);
+
+ TAILQ_INSERT_TAIL(&sc->sc_cbq, cb, chain);
+
+ if (!sc->sc_active) {
+ /* Abort script to start selection */
+ oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
+ }
+ if (xs->flags & SCSI_POLL) {
+ /* Poll for command completion */
+ while ((xs->flags & ITSDONE) == 0) {
+ delay(1000);
+ oosiop_intr(sc);
+ }
+ } else {
+ /* start expire timer */
+ timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz);
+ }
+
+ splx(s);
+
+ if ((xs->flags & ITSDONE) == 0)
+ return (SUCCESSFULLY_QUEUED);
+ else
+ return (COMPLETE);
+}
+
+void
+oosiop_done(struct oosiop_softc *sc, struct oosiop_cb *cb)
+{
+ struct scsi_xfer *xs;
+ struct scsi_link *periph;
+ int autosense;
+
+ xs = cb->xs;
+ periph = xs->sc_link;
+
+ /*
+ * Record if this is the completion of an auto sense
+ * scsi command, and then reset the flag so we don't loop
+ * when such a command fails or times out.
+ */
+ autosense = cb->flags & CBF_AUTOSENSE;
+ cb->flags &= ~CBF_AUTOSENSE;
+
+ if (cb == sc->sc_curcb)
+ sc->sc_curcb = NULL;
+ if (cb == sc->sc_lastcb)
+ sc->sc_lastcb = NULL;
+ sc->sc_tgt[cb->id].nexus = NULL;
+
+ if (cb->datalen > 0) {
+ bus_dmamap_sync(sc->sc_dmat, cb->datadma, 0, xs->datalen,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, cb->datadma);
+ }
+
+ timeout_del(&xs->stimeout);
+
+ xs->status = cb->xfer->status;
+
+ if (cb->flags & CBF_SELTOUT)
+ xs->error = XS_SELTIMEOUT;
+ else if (cb->flags & CBF_TIMEOUT)
+ xs->error = XS_TIMEOUT;
+ else switch (xs->status) {
+ case SCSI_OK:
+ if (autosense == 0)
+ xs->error = XS_NOERROR;
+ else
+ xs->error = XS_SENSE;
+ break;
+
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+ case SCSI_CHECK:
+ if (autosense == 0)
+ cb->flags |= CBF_AUTOSENSE;
+ else
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ case SCSI_OOSIOP_NOSTATUS:
+ /* the status byte was not updated, cmd was aborted. */
+ xs->error = XS_SELTIMEOUT;
+ break;
+
+ default:
+ xs->error = XS_RESET;
+ break;
+ }
+
+ if ((cb->flags & CBF_AUTOSENSE) == 0) {
+ /* Put it on the free list. */
+FREE:
+ TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+ xs->resid = 0;
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+ } else {
+ /* Set up REQUEST_SENSE command */
+ struct scsi_sense *cmd =
+ (struct scsi_sense *)&cb->xfer->scsi_cmd;
+ int err;
+
+ bzero(cmd, sizeof(*cmd));
+ cmd->opcode = REQUEST_SENSE;
+ cmd->byte2 = xs->sc_link->lun << 5;
+ cmd->length = sizeof(xs->sense);
+
+ /* Sotup DMA map for data buffer */
+ cb->xsflags &= SCSI_POLL | SCSI_NOSLEEP;
+ cb->xsflags |= SCSI_DATA_IN;
+ cb->datalen = sizeof xs->sense;
+
+ err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
+ &xs->sense, sizeof(xs->sense), NULL,
+ BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ);
+ if (err) {
+ printf("%s: unable to load REQUEST_SENSE data DMA map: %d",
+ sc->sc_dev.dv_xname, err);
+ xs->error = XS_DRIVER_STUFFUP;
+ goto FREE;
+ }
+ bus_dmamap_sync(sc->sc_dmat, cb->datadma,
+ 0, sizeof(xs->sense), BUS_DMASYNC_PREREAD);
+
+ TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
+ if ((cb->xs->flags & SCSI_POLL) == 0) {
+ /* start expire timer */
+ timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz);
+ }
+ }
+}
+
+void
+oosiop_timeout(void *arg)
+{
+ struct oosiop_cb *cb = arg;
+ struct scsi_xfer *xs = cb->xs;
+ struct oosiop_softc *sc = xs->sc_link->adapter_softc;
+ int s;
+
+ sc_print_addr(xs->sc_link);
+ printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs);
+
+ s = splbio();
+
+ cb->flags |= CBF_TIMEOUT;
+ oosiop_done(sc, cb);
+
+ splx(s);
+}
+
+void
+oosiop_reset(struct oosiop_softc *sc)
+{
+ int i, s;
+
+ s = splbio();
+
+ /* Stop SCRIPTS processor */
+ oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
+ delay(100);
+ oosiop_write_1(sc, OOSIOP_ISTAT, 0);
+
+ /* Reset the chip */
+ oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl | OOSIOP_DCNTL_RST);
+ delay(100);
+ oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
+ delay(10000);
+
+ /* Set up various chip parameters */
+ oosiop_write_1(sc, OOSIOP_SCNTL0, OOSIOP_ARB_FULL | OOSIOP_SCNTL0_EPG);
+ oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_ESR);
+ oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
+ oosiop_write_1(sc, OOSIOP_DMODE, OOSIOP_DMODE_BL_8);
+ oosiop_write_1(sc, OOSIOP_SCID, OOSIOP_SCID_VALUE(sc->sc_id));
+ oosiop_write_1(sc, OOSIOP_DWT, 0xff); /* Enable DMA timeout */
+ oosiop_write_1(sc, OOSIOP_CTEST7, 0);
+ oosiop_write_1(sc, OOSIOP_SXFER, 0);
+
+ /* Clear all interrupts */
+ (void)oosiop_read_1(sc, OOSIOP_SSTAT0);
+ (void)oosiop_read_1(sc, OOSIOP_SSTAT1);
+ (void)oosiop_read_1(sc, OOSIOP_DSTAT);
+
+ /* Enable interrupts */
+ oosiop_write_1(sc, OOSIOP_SIEN,
+ OOSIOP_SIEN_M_A | OOSIOP_SIEN_STO | OOSIOP_SIEN_SGE |
+ OOSIOP_SIEN_UDC | OOSIOP_SIEN_RST | OOSIOP_SIEN_PAR);
+ oosiop_write_1(sc, OOSIOP_DIEN,
+ OOSIOP_DIEN_ABRT | OOSIOP_DIEN_SSI | OOSIOP_DIEN_SIR |
+ OOSIOP_DIEN_WTD | OOSIOP_DIEN_IID);
+
+ /* Set target state to asynchronous */
+ for (i = 0; i < OOSIOP_NTGT; i++) {
+ sc->sc_tgt[i].flags = 0;
+ sc->sc_tgt[i].scf = 0;
+ sc->sc_tgt[i].sxfer = 0;
+ }
+
+ splx(s);
+}
+
+void
+oosiop_reset_bus(struct oosiop_softc *sc)
+{
+ int s, i;
+
+ s = splbio();
+
+ /* Assert SCSI RST */
+ oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_RST);
+ delay(25); /* Reset hold time (25us) */
+ oosiop_write_1(sc, OOSIOP_SCNTL1, 0);
+
+ /* Remove all nexuses */
+ for (i = 0; i < OOSIOP_NTGT; i++) {
+ if (sc->sc_tgt[i].nexus) {
+ sc->sc_tgt[i].nexus->xfer->status =
+ SCSI_OOSIOP_NOSTATUS; /* XXX */
+ oosiop_done(sc, sc->sc_tgt[i].nexus);
+ }
+ }
+
+ sc->sc_curcb = NULL;
+
+ delay(250000); /* Reset to selection (250ms) */
+
+ splx(s);
+}
+
+/*
+ * interrupt handler
+ */
+int
+oosiop_intr(struct oosiop_softc *sc)
+{
+ struct oosiop_cb *cb;
+ u_int32_t dcmd;
+ u_int8_t istat, dstat, sstat0;
+
+ istat = oosiop_read_1(sc, OOSIOP_ISTAT);
+
+ if ((istat & (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0)
+ return (0);
+
+ sc->sc_nextdsp = Ent_wait_reselect;
+
+ /* DMA interrupts */
+ if (istat & OOSIOP_ISTAT_DIP) {
+ oosiop_write_1(sc, OOSIOP_ISTAT, 0);
+
+ dstat = oosiop_read_1(sc, OOSIOP_DSTAT);
+
+ if (dstat & OOSIOP_DSTAT_ABRT) {
+ sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
+ sc->sc_scrbase - 8;
+
+ if (sc->sc_nextdsp == Ent_p_resel_msgin_move &&
+ (oosiop_read_1(sc, OOSIOP_SBCL) & OOSIOP_ACK)) {
+ if ((dstat & OOSIOP_DSTAT_DFE) == 0)
+ oosiop_flush_fifo(sc);
+ sc->sc_nextdsp += 8;
+ }
+ }
+
+ if (dstat & OOSIOP_DSTAT_SSI) {
+ sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
+ sc->sc_scrbase;
+ printf("%s: single step %08x\n", sc->sc_dev.dv_xname,
+ sc->sc_nextdsp);
+ }
+
+ if (dstat & OOSIOP_DSTAT_SIR) {
+ if ((dstat & OOSIOP_DSTAT_DFE) == 0)
+ oosiop_flush_fifo(sc);
+ oosiop_scriptintr(sc);
+ }
+
+ if (dstat & OOSIOP_DSTAT_WTD) {
+ printf("%s: DMA time out\n", sc->sc_dev.dv_xname);
+ oosiop_reset(sc);
+ }
+
+ if (dstat & OOSIOP_DSTAT_IID) {
+ dcmd = oosiop_read_4(sc, OOSIOP_DBC);
+ if ((dcmd & 0xf8000000) == 0x48000000) {
+ printf("%s: REQ asserted on WAIT DISCONNECT\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_nextdsp = Ent_phasedispatch; /* XXX */
+ } else {
+ printf("%s: invalid SCRIPTS instruction "
+ "addr=%08x dcmd=%08x dsps=%08x\n",
+ sc->sc_dev.dv_xname,
+ oosiop_read_4(sc, OOSIOP_DSP) - 8, dcmd,
+ oosiop_read_4(sc, OOSIOP_DSPS));
+ oosiop_reset(sc);
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+ oosiop_load_script(sc);
+ }
+ }
+
+ if ((dstat & OOSIOP_DSTAT_DFE) == 0)
+ oosiop_clear_fifo(sc);
+ }
+
+ /* SCSI interrupts */
+ if (istat & OOSIOP_ISTAT_SIP) {
+ if (istat & OOSIOP_ISTAT_DIP)
+ delay(1);
+ sstat0 = oosiop_read_1(sc, OOSIOP_SSTAT0);
+
+ if (sstat0 & OOSIOP_SSTAT0_M_A) {
+ /* SCSI phase mismatch during MOVE operation */
+ oosiop_phasemismatch(sc);
+ sc->sc_nextdsp = Ent_phasedispatch;
+ }
+
+ if (sstat0 & OOSIOP_SSTAT0_STO) {
+ if (sc->sc_curcb) {
+ sc->sc_curcb->flags |= CBF_SELTOUT;
+ oosiop_done(sc, sc->sc_curcb);
+ }
+ }
+
+ if (sstat0 & OOSIOP_SSTAT0_SGE) {
+ printf("%s: SCSI gross error\n", sc->sc_dev.dv_xname);
+ oosiop_reset(sc);
+ }
+
+ if (sstat0 & OOSIOP_SSTAT0_UDC) {
+ /* XXX */
+ if (sc->sc_curcb) {
+ printf("%s: unexpected disconnect\n",
+ sc->sc_dev.dv_xname);
+ oosiop_done(sc, sc->sc_curcb);
+ }
+ }
+
+ if (sstat0 & OOSIOP_SSTAT0_RST)
+ oosiop_reset(sc);
+
+ if (sstat0 & OOSIOP_SSTAT0_PAR)
+ printf("%s: parity error\n", sc->sc_dev.dv_xname);
+ }
+
+ /* Start next command if available */
+ if (sc->sc_nextdsp == Ent_wait_reselect && TAILQ_FIRST(&sc->sc_cbq)) {
+ cb = sc->sc_curcb = TAILQ_FIRST(&sc->sc_cbq);
+ TAILQ_REMOVE(&sc->sc_cbq, cb, chain);
+ sc->sc_tgt[cb->id].nexus = cb;
+
+ oosiop_setup_dma(sc);
+ oosiop_setup_syncxfer(sc);
+ sc->sc_lastcb = cb;
+ sc->sc_nextdsp = Ent_start_select;
+
+ /* Schedule timeout */
+ if ((cb->xs->flags & SCSI_POLL) == 0) {
+ /* start expire timer */
+ timeout_add(&cb->xs->stimeout,
+ (cb->xs->timeout / 1000) * hz);
+ }
+ }
+
+ sc->sc_active = (sc->sc_nextdsp != Ent_wait_reselect);
+
+ /* Restart script */
+ oosiop_write_4(sc, OOSIOP_DSP, sc->sc_nextdsp + sc->sc_scrbase);
+
+ return (1);
+}
+
+void
+oosiop_scriptintr(struct oosiop_softc *sc)
+{
+ struct oosiop_cb *cb;
+ u_int32_t icode;
+ u_int32_t dsp;
+ int i;
+ u_int8_t sfbr, resid, resmsg;
+
+ cb = sc->sc_curcb;
+ icode = oosiop_read_4(sc, OOSIOP_DSPS);
+
+ switch (icode) {
+ case A_int_done:
+ if (cb)
+ oosiop_done(sc, cb);
+ break;
+
+ case A_int_msgin:
+ if (cb)
+ oosiop_msgin(sc, cb);
+ break;
+
+ case A_int_extmsg:
+ /* extended message in DMA setup request */
+ sfbr = oosiop_read_1(sc, OOSIOP_SFBR);
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+ oosiop_fixup_move(sc, Ent_p_extmsgin_move, sfbr,
+ cb->xferdma->dm_segs[0].ds_addr +
+ offsetof(struct oosiop_xfer, msgin[2]));
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+ sc->sc_nextdsp = Ent_rcv_extmsg;
+ break;
+
+ case A_int_resel:
+ /* reselected */
+ resid = oosiop_read_1(sc, OOSIOP_SFBR);
+ for (i = 0; i < OOSIOP_NTGT; i++)
+ if (resid & (1 << i))
+ break;
+ if (i == OOSIOP_NTGT) {
+ printf("%s: missing reselection target id\n",
+ sc->sc_dev.dv_xname);
+ break;
+ }
+ sc->sc_resid = i;
+ sc->sc_nextdsp = Ent_wait_resel_identify;
+
+ if (cb) {
+ /* Current command was lost arbitration */
+ sc->sc_tgt[cb->id].nexus = NULL;
+ TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
+ sc->sc_curcb = NULL;
+ }
+
+ break;
+
+ case A_int_res_id:
+ cb = sc->sc_tgt[sc->sc_resid].nexus;
+ resmsg = oosiop_read_1(sc, OOSIOP_SFBR);
+ if (MSG_ISIDENTIFY(resmsg) && cb &&
+ (resmsg & MSG_IDENTIFY_LUNMASK) == cb->lun) {
+ sc->sc_curcb = cb;
+ if (cb != sc->sc_lastcb) {
+ oosiop_setup_dma(sc);
+ oosiop_setup_syncxfer(sc);
+ sc->sc_lastcb = cb;
+ }
+ if (cb->curdp != cb->savedp) {
+ cb->curdp = cb->savedp;
+ oosiop_setup_sgdma(sc, cb);
+ }
+ sc->sc_nextdsp = Ent_ack_msgin;
+ } else {
+ /* Reselection from invalid target */
+ oosiop_reset_bus(sc);
+ }
+ break;
+
+ case A_int_resfail:
+ /* reselect failed */
+ break;
+
+ case A_int_disc:
+ /* disconnected */
+ sc->sc_curcb = NULL;
+ break;
+
+ case A_int_err:
+ /* generic error */
+ dsp = oosiop_read_4(sc, OOSIOP_DSP);
+ printf("%s: script error at 0x%08x\n", sc->sc_dev.dv_xname,
+ dsp - 8);
+ sc->sc_curcb = NULL;
+ break;
+
+ case DATAIN_TRAP:
+ printf("%s: unexpected datain\n", sc->sc_dev.dv_xname);
+ /* XXX: need to reset? */
+ break;
+
+ case DATAOUT_TRAP:
+ printf("%s: unexpected dataout\n", sc->sc_dev.dv_xname);
+ /* XXX: need to reset? */
+ break;
+
+ default:
+ printf("%s: unknown intr code %08x\n", sc->sc_dev.dv_xname,
+ icode);
+ break;
+ }
+}
+
+void
+oosiop_msgin(struct oosiop_softc *sc, struct oosiop_cb *cb)
+{
+ struct oosiop_xfer *xfer;
+ int msgout;
+
+ xfer = cb->xfer;
+ sc->sc_nextdsp = Ent_ack_msgin;
+ msgout = 0;
+
+ OOSIOP_XFERMSG_SYNC(sc, cb,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ switch (xfer->msgin[0]) {
+ case MSG_EXTENDED:
+ switch (xfer->msgin[2]) {
+ case MSG_EXT_SDTR:
+ if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
+ /* Host initiated SDTR */
+ sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
+ } else {
+ /* Target initiated SDTR */
+ if (xfer->msgin[3] < sc->sc_minperiod)
+ xfer->msgin[3] = sc->sc_minperiod;
+ if (xfer->msgin[4] > OOSIOP_MAX_OFFSET)
+ xfer->msgin[4] = OOSIOP_MAX_OFFSET;
+ xfer->msgout[0] = MSG_EXTENDED;
+ xfer->msgout[1] = MSG_EXT_SDTR_LEN;
+ xfer->msgout[2] = MSG_EXT_SDTR;
+ xfer->msgout[3] = xfer->msgin[3];
+ xfer->msgout[4] = xfer->msgin[4];
+ cb->msgoutlen = 5;
+ msgout = 1;
+ }
+ oosiop_set_syncparam(sc, cb->id, (int)xfer->msgin[3],
+ (int)xfer->msgin[4]);
+ oosiop_setup_syncxfer(sc);
+ break;
+
+ default:
+ /* Reject message */
+ xfer->msgout[0] = MSG_MESSAGE_REJECT;
+ cb->msgoutlen = 1;
+ msgout = 1;
+ break;
+ }
+ break;
+
+ case MSG_SAVEDATAPOINTER:
+ cb->savedp = cb->curdp;
+ break;
+
+ case MSG_RESTOREPOINTERS:
+ if (cb->curdp != cb->savedp) {
+ cb->curdp = cb->savedp;
+ oosiop_setup_sgdma(sc, cb);
+ }
+ break;
+
+ case MSG_MESSAGE_REJECT:
+ if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
+ /* SDTR rejected */
+ sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
+ oosiop_set_syncparam(sc, cb->id, 0, 0);
+ oosiop_setup_syncxfer(sc);
+ }
+ break;
+
+ default:
+ /* Reject message */
+ xfer->msgout[0] = MSG_MESSAGE_REJECT;
+ cb->msgoutlen = 1;
+ msgout = 1;
+ }
+
+ OOSIOP_XFERMSG_SYNC(sc, cb,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ if (msgout) {
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+ oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen,
+ cb->xferdma->dm_segs[0].ds_addr +
+ offsetof(struct oosiop_xfer, msgout[0]));
+ OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+ sc->sc_nextdsp = Ent_sendmsg;
+ }
+}
diff --git a/sys/dev/ic/oosiopreg.h b/sys/dev/ic/oosiopreg.h
new file mode 100644
index 00000000000..f924a2f0877
--- /dev/null
+++ b/sys/dev/ic/oosiopreg.h
@@ -0,0 +1,324 @@
+/* $OpenBSD: oosiopreg.h,v 1.1 2004/03/12 00:04:57 miod Exp $ */
+/* $NetBSD: oosiopreg.h,v 1.3 2003/11/02 11:07:45 wiz Exp $ */
+
+/*
+ * 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. 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.
+ *
+ * @(#)siopreg.h 7.3 (Berkeley) 2/5/91
+ */
+
+/*
+ * NCR 53C700 SCSI interface hardware description.
+ *
+ * From the Mach scsi driver for the 53C700 and amiga siop driver
+ */
+
+#define OOSIOP_SCNTL0 0x00 /* rw: SCSI control reg 0 */
+#define OOSIOP_SCNTL1 0x01 /* rw: SCSI control reg 1 */
+#define OOSIOP_SDID 0x02 /* rw: SCSI destination ID */
+#define OOSIOP_SIEN 0x03 /* rw: SCSI interrupt enable */
+#define OOSIOP_SCID 0x04 /* rw: SCSI Chip ID reg */
+#define OOSIOP_SXFER 0x05 /* rw: SCSI Transfer reg */
+#define OOSIOP_SODL 0x06 /* rw: SCSI Output Data Latch */
+#define OOSIOP_SOCL 0x07 /* rw: SCSI Output Control Latch */
+#define OOSIOP_SFBR 0x08 /* ro: SCSI First Byte Received */
+#define OOSIOP_SIDL 0x09 /* ro: SCSI Input Data Latch */
+#define OOSIOP_SBDL 0x0a /* ro: SCSI Bus Data Lines */
+#define OOSIOP_SBCL 0x0b /* rw: SCSI Bus Control Lines */
+#define OOSIOP_DSTAT 0x0c /* ro: DMA status */
+#define OOSIOP_SSTAT0 0x0d /* ro: SCSI status reg 0 */
+#define OOSIOP_SSTAT1 0x0e /* ro: SCSI status reg 1 */
+#define OOSIOP_SSTAT2 0x0f /* ro: SCSI status reg 2 */
+#define OOSIOP_SCRA0 0x10 /* rw: Scratch A */
+#define OOSIOP_SCRA1 0x11
+#define OOSIOP_SCRA2 0x12
+#define OOSIOP_SCRA3 0x13
+#define OOSIOP_CTEST0 0x14 /* ro: Chip test register 0 */
+#define OOSIOP_CTEST1 0x15 /* ro: Chip test register 1 */
+#define OOSIOP_CTEST2 0x16 /* ro: Chip test register 2 */
+#define OOSIOP_CTEST3 0x17 /* ro: Chip test register 3 */
+#define OOSIOP_CTEST4 0x18 /* rw: Chip test register 4 */
+#define OOSIOP_CTEST5 0x19 /* rw: Chip test register 5 */
+#define OOSIOP_CTEST6 0x1a /* rw: Chip test register 6 */
+#define OOSIOP_CTEST7 0x1b /* rw: Chip test register 7 */
+#define OOSIOP_TEMP 0x1c /* rw: Temporary Stack reg */
+#define OOSIOP_DFIFO 0x20 /* rw: DMA FIFO */
+#define OOSIOP_ISTAT 0x21 /* rw: Interrupt Status reg */
+#define OOSIOP_CTEST8 0x22 /* rw: Chip test register 8 */
+#define OOSIOP_CTEST9 0x23 /* ro: Chip test register 9 */
+#define OOSIOP_DBC 0x24 /* rw: DMA Byte Counter reg */
+#define OOSIOP_DCMD 0x27 /* rw: DMA Command Register */
+#define OOSIOP_DNAD 0x28 /* rw: DMA Next Address */
+#define OOSIOP_DSP 0x2c /* rw: DMA SCRIPTS Pointer reg */
+#define OOSIOP_DSPS 0x30 /* rw: DMA SCRIPTS Pointer Save reg */
+#define OOSIOP_DMODE 0x34 /* rw: DMA Mode reg */
+#define OOSIOP_RES35 0x35
+#define OOSIOP_RES36 0x36
+#define OOSIOP_RES37 0x37
+#define OOSIOP_RES38 0x38
+#define OOSIOP_DIEN 0x39 /* rw: DMA Interrupt Enable */
+#define OOSIOP_DWT 0x3a /* rw: DMA Watchdog Timer */
+#define OOSIOP_DCNTL 0x3b /* rw: DMA Control reg */
+#define OOSIOP_SCRB0 0x3c /* rw: Scratch B */
+#define OOSIOP_SCRB1 0x3d
+#define OOSIOP_SCRB2 0x3e
+#define OOSIOP_SCRB3 0x3f
+
+#define OOSIOP_NREGS 0x40
+
+
+/*
+ * Register defines
+ */
+
+/* Scsi control register 0 (scntl0) */
+
+#define OOSIOP_SCNTL0_ARB 0xc0 /* Arbitration mode */
+#define OOSIOP_ARB_SIMPLE 0x00
+#define OOSIOP_ARB_FULL 0xc0
+#define OOSIOP_SCNTL0_START 0x20 /* Start Sequence */
+#define OOSIOP_SCNTL0_WATN 0x10 /* (Select) With ATN */
+#define OOSIOP_SCNTL0_EPC 0x08 /* Enable Parity Checking */
+#define OOSIOP_SCNTL0_EPG 0x04 /* Enable Parity Generation */
+#define OOSIOP_SCNTL0_AAP 0x02 /* Assert ATN on Parity Error */
+#define OOSIOP_SCNTL0_TRG 0x01 /* Target Mode */
+
+/* Scsi control register 1 (scntl1) */
+
+#define OOSIOP_SCNTL1_EXC 0x80 /* Extra Clock Cycle of data setup */
+#define OOSIOP_SCNTL1_ADB 0x40 /* Assert Data Bus */
+#define OOSIOP_SCNTL1_ESR 0x20 /* Enable Selection/Reselection */
+#define OOSIOP_SCNTL1_CON 0x10 /* Connected */
+#define OOSIOP_SCNTL1_RST 0x08 /* Assert RST */
+#define OOSIOP_SCNTL1_AESP 0x04 /* Assert even SCSI parity */
+#define OOSIOP_SCNTL1_SND 0x02 /* Start Send operation */
+#define OOSIOP_SCNTL1_RCV 0x01 /* Start Receive operation */
+
+/* Scsi interrupt enable register (sien) */
+
+#define OOSIOP_SIEN_M_A 0x80 /* Phase Mismatch or ATN active */
+#define OOSIOP_SIEN_FC 0x40 /* Function Complete */
+#define OOSIOP_SIEN_STO 0x20 /* (Re)Selection timeout */
+#define OOSIOP_SIEN_SEL 0x10 /* (Re)Selected */
+#define OOSIOP_SIEN_SGE 0x08 /* SCSI Gross Error */
+#define OOSIOP_SIEN_UDC 0x04 /* Unexpected Disconnect */
+#define OOSIOP_SIEN_RST 0x02 /* RST asserted */
+#define OOSIOP_SIEN_PAR 0x01 /* Parity Error */
+
+/* Scsi chip ID (scid) */
+
+#define OOSIOP_SCID_VALUE(i) (1 << i)
+
+/* Scsi transfer register (sxfer) */
+
+#define OOSIOP_SXFER_DHP 0x80 /* Disable Halt on Parity error/
+ ATN asserted */
+#define OOSIOP_SXFER_TP 0x70 /* Synch Transfer Period */
+ /* see specs for formulas:
+ Period = TCP * (4 + XFERP )
+ TCP = 1 + CLK + 1..2;
+ */
+#define OOSIOP_SXFER_MO 0x0f /* Synch Max Offset */
+#define OOSIOP_MAX_OFFSET 8
+
+/* Scsi output data latch register (sodl) */
+
+/* Scsi output control latch register (socl) */
+
+#define OOSIOP_REQ 0x80 /* SCSI signal <x> asserted */
+#define OOSIOP_ACK 0x40
+#define OOSIOP_BSY 0x20
+#define OOSIOP_SEL 0x10
+#define OOSIOP_ATN 0x08
+#define OOSIOP_MSG 0x04
+#define OOSIOP_CD 0x02
+#define OOSIOP_IO 0x01
+
+#define OOSIOP_PHASE(socl) SCSI_PHASE(socl)
+
+/* Scsi first byte received register (sfbr) */
+
+/* Scsi input data latch register (sidl) */
+
+/* Scsi bus data lines register (sbdl) */
+
+/* Scsi bus control lines register (sbcl). Same as socl */
+
+#define OOSIOP_SBCL_SSCF1 0x02 /* wo */
+#define OOSIOP_SBCL_SSCF0 0x01 /* wo */
+
+/* DMA status register (dstat) */
+
+#define OOSIOP_DSTAT_DFE 0x80 /* DMA FIFO empty */
+#define OOSIOP_DSTAT_ABRT 0x10 /* Aborted */
+#define OOSIOP_DSTAT_SSI 0x08 /* SCRIPT Single Step */
+#define OOSIOP_DSTAT_SIR 0x04 /* SCRIPT Interrupt Instruction */
+#define OOSIOP_DSTAT_WTD 0x02 /* Watchdog Timeout Detected */
+#define OOSIOP_DSTAT_IID 0x01 /* Invalid Instruction Detected */
+
+/* Scsi status register 0 (sstat0) */
+
+#define OOSIOP_SSTAT0_M_A 0x80 /* Phase Mismatch or ATN active */
+#define OOSIOP_SSTAT0_FC 0x40 /* Function Complete */
+#define OOSIOP_SSTAT0_STO 0x20 /* (Re)Selection timeout */
+#define OOSIOP_SSTAT0_SEL 0x10 /* (Re)Selected */
+#define OOSIOP_SSTAT0_SGE 0x08 /* SCSI Gross Error */
+#define OOSIOP_SSTAT0_UDC 0x04 /* Unexpected Disconnect */
+#define OOSIOP_SSTAT0_RST 0x02 /* RST asserted */
+#define OOSIOP_SSTAT0_PAR 0x01 /* Parity Error */
+
+/* Scsi status register 1 (sstat1) */
+
+#define OOSIOP_SSTAT1_ILF 0x80 /* Input latch (sidl) full */
+#define OOSIOP_SSTAT1_ORF 0x40 /* output reg (sodr) full */
+#define OOSIOP_SSTAT1_OLF 0x20 /* output latch (sodl) full */
+#define OOSIOP_SSTAT1_AIP 0x10 /* Arbitration in progress */
+#define OOSIOP_SSTAT1_LOA 0x08 /* Lost arbitration */
+#define OOSIOP_SSTAT1_WOA 0x04 /* Won arbitration */
+#define OOSIOP_SSTAT1_RST 0x02 /* SCSI RST current value */
+#define OOSIOP_SSTAT1_SDP 0x01 /* SCSI SDP current value */
+
+/* Scsi status register 2 (sstat2) */
+
+#define OOSIOP_SSTAT2_FF 0xf0 /* SCSI FIFO flags (bytecount) */
+#define OOSIOP_SCSI_FIFO_DEEP 8
+#define OOSIOP_SSTAT2_SDP 0x08 /* Latched (on REQ) SCSI SDP */
+#define OOSIOP_SSTAT2_MSG 0x04 /* Latched SCSI phase */
+#define OOSIOP_SSTAT2_CD 0x02
+#define OOSIOP_SSTAT2_IO 0x01
+
+/* Chip test register 0 (ctest0) */
+
+#define OOSIOP_CTEST0_RTRG 0x02 /* Real Target Mode */
+#define OOSIOP_CTEST0_DDIR 0x01 /* Xfer direction (1-> from SCSI bus) */
+
+/* Chip test register 1 (ctest1) */
+
+#define OOSIOP_CTEST1_FMT 0xf0 /* Byte empty in DMA FIFO bottom
+ (high->byte3) */
+#define OOSIOP_CTEST1_FFL 0x0f /* Byte full in DMA FIFO top, same */
+
+/* Chip test register 2 (ctest2) */
+
+#define OOSIOP_CTEST2_SOFF 0x20 /* Synch Offset compare
+ (1-> zero Init, max Tgt) */
+#define OOSIOP_CTEST2_SFP 0x10 /* SCSI FIFO Parity */
+#define OOSIOP_CTEST2_DFP 0x08 /* DMA FIFO Parity */
+#define OOSIOP_CTEST2_TEOP 0x04 /* True EOP (a-la 5380) */
+#define OOSIOP_CTEST2_DREQ 0x02 /* DREQ status */
+#define OOSIOP_CTEST2_DACK 0x01 /* DACK status */
+
+/* Chip test register 3 (ctest3) read-only, top of SCSI FIFO */
+
+/* Chip test register 4 (ctest4) */
+
+#define OOSIOP_CTEST4_ZMOD 0x40 /* High-impedance outputs */
+#define OOSIOP_CTEST4_SZM 0x20 /* ditto, SCSI "outputs" */
+#define OOSIOP_CTEST4_SLBE 0x10 /* SCSI loopback enable */
+#define OOSIOP_CTEST4_SFWR 0x08 /* SCSI FIFO write enable (from sodl) */
+#define OOSIOP_CTEST4_FBL 0x07 /* DMA FIFO Byte Lane select
+ (from ctest6) 4->0, .. 7->3 */
+
+/* Chip test register 5 (ctest5) */
+
+#define OOSIOP_CTEST5_ADCK 0x80 /* Clock Address Incrementor */
+#define OOSIOP_CTEST5_BBCK 0x40 /* Clock Byte counter */
+#define OOSIOP_CTEST5_ROFF 0x20 /* Reset SCSI offset */
+#define OOSIOP_CTEST5_MASR 0x10 /* Master set/reset pulses
+ (of bits 3-0) */
+#define OOSIOP_CTEST5_DDIR 0x08 /* (re)set internal DMA direction */
+#define OOSIOP_CTEST5_EOP 0x04 /* (re)set internal EOP */
+#define OOSIOP_CTEST5_DREQ 0x02 /* (re)set internal REQ */
+#define OOSIOP_CTEST5_DACK 0x01 /* (re)set internal ACK */
+
+/* Chip test register 6 (ctest6) DMA FIFO access */
+
+/* Chip test register 7 (ctest7) */
+
+#define OOSIOP_CTEST7_STD 0x10 /* Selection timeout disable */
+#define OOSIOP_CTEST7_DFP 0x08 /* DMA FIFO parity bit */
+#define OOSIOP_CTEST7_EVP 0x04 /* Even parity (to host bus) */
+#define OOSIOP_CTEST7_DIFF 0x01 /* Differential mode */
+
+/* DMA FIFO register (dfifo) */
+
+#define OOSIOP_DFIFO_FLF 0x80 /* Flush (spill) DMA FIFO */
+#define OOSIOP_DFIFO_CLF 0x40 /* Clear DMA and SCSI FIFOs */
+#define OOSIOP_DFIFO_BO 0x3f /* FIFO byte offset counter */
+
+/* Interrupt status register (istat) */
+
+#define OOSIOP_ISTAT_ABRT 0x80 /* Abort operation */
+#define OOSIOP_ISTAT_CON 0x08 /* Connected */
+#define OOSIOP_ISTAT_PRE 0x04 /* Pointer register empty */
+#define OOSIOP_ISTAT_SIP 0x02 /* SCSI Interrupt pending */
+#define OOSIOP_ISTAT_DIP 0x01 /* DMA Interrupt pending */
+
+/* Chip test register 8 (ctest8) */
+
+/* DMA Byte Counter register (dbc) */
+#define OOSIOP_DBC_MAX 0x00ffffff
+
+/* DMA Mode register (dmode) */
+
+#define OOSIOP_DMODE_BL_MASK 0xc0 /* 0->1 1->2 2->4 3->8 */
+#define OOSIOP_DMODE_BL_1 0x00
+#define OOSIOP_DMODE_BL_2 0x40
+#define OOSIOP_DMODE_BL_4 0x80
+#define OOSIOP_DMODE_BL_8 0xc0
+#define OOSIOP_DMODE_BW16 0x20 /* Bus Width is 16 bits */
+#define OOSIOP_DMODE_286 0x10 /* 286 mode */
+#define OOSIOP_DMODE_IO_M 0x08 /* xfer data to memory or I/O space */
+#define OOSIOP_DMODE_FAM 0x04 /* fixed address mode */
+#define OOSIOP_DMODE_PIPE 0x02 /* SCRIPTS in Pipeline mode */
+#define OOSIOP_DMODE_MAN 0x01 /* SCRIPTS in Manual start mode */
+
+/* DMA interrupt enable register (dien) */
+
+#define OOSIOP_DIEN_BF 0x20 /* On Bus Fault */
+#define OOSIOP_DIEN_ABRT 0x10 /* On Abort */
+#define OOSIOP_DIEN_SSI 0x08 /* On SCRIPTS sstep */
+#define OOSIOP_DIEN_SIR 0x04 /* On SCRIPTS intr instruction */
+#define OOSIOP_DIEN_WTD 0x02 /* On watchdog timeout */
+#define OOSIOP_DIEN_IID 0x01 /* On illegal instruction detected */
+
+/* DMA control register (dcntl) */
+
+#define OOSIOP_DCNTL_CF_MASK 0xc0 /* Clock frequency dividers: */
+#define OOSIOP_DCNTL_CF_2 0x00 /* 0 --> 37.51..50.00 MHz, div=2 */
+#define OOSIOP_DCNTL_CF_1_5 0x40 /* 1 --> 25.01..37.50 MHz, div=1.5 */
+#define OOSIOP_DCNTL_CF_1 0x80 /* 2 --> 16.67..25.00 MHz, div=1 */
+#define OOSIOP_DCNTL_CF_3 0xc0 /* 3 --> 50.01..66.67 MHz, div=3 */
+#define OOSIOP_DCNTL_S16 0x20 /* SCRIPTS fetches 16bits at a time */
+#define OOSIOP_DCNTL_SSM 0x10 /* Single step mode */
+#define OOSIOP_DCNTL_LLM 0x08 /* Enable SCSI Low-level mode */
+#define OOSIOP_DCNTL_STD 0x04 /* Start DMA operation */
+#define OOSIOP_DCNTL_RST 0x01 /* Software reset */
diff --git a/sys/dev/ic/oosiopvar.h b/sys/dev/ic/oosiopvar.h
new file mode 100644
index 00000000000..e197773efb4
--- /dev/null
+++ b/sys/dev/ic/oosiopvar.h
@@ -0,0 +1,164 @@
+/* $OpenBSD: oosiopvar.h,v 1.1 2004/03/12 00:04:57 miod Exp $ */
+/* $NetBSD: oosiopvar.h,v 1.2 2003/05/03 18:11:23 wiz Exp $ */
+
+/*
+ * Copyright (c) 2001 Shuichiro URATA. 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. 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.
+ */
+
+#define OOSIOP_NTGT 8 /* Max targets */
+#define OOSIOP_NCB 32 /* Initial command buffers */
+#define OOSIOP_NSG (MIN(btoc(MAXPHYS) + 1, 32)) /* Max S/G operation */
+#define OOSIOP_MAX_XFER ctob(OOSIOP_NSG - 1)
+
+struct oosiop_xfer {
+ /* script for scatter/gather DMA (move*nsg+jump) */
+ u_int32_t datain_scr[(OOSIOP_NSG + 1) * 2];
+ u_int32_t dataout_scr[(OOSIOP_NSG + 1) * 2];
+
+ u_int8_t msgin[8];
+ u_int8_t msgout[8];
+ u_int8_t status;
+ u_int8_t pad[7];
+
+ struct scsi_generic scsi_cmd; /* DMA'able copy of xs->cmd */
+ u_int32_t pad2[1+4]; /* pad to 256 bytes */
+} __packed;
+
+#define SCSI_OOSIOP_NOSTATUS 0xff /* device didn't report status */
+
+#define OOSIOP_XFEROFF(x) offsetof(struct oosiop_xfer, x)
+#define OOSIOP_DINSCROFF OOSIOP_XFEROFF(datain_scr[0])
+#define OOSIOP_DOUTSCROFF OOSIOP_XFEROFF(dataout_scr[0])
+#define OOSIOP_MSGINOFF OOSIOP_XFEROFF(msgin[0])
+#define OOSIOP_MSGOUTOFF OOSIOP_XFEROFF(msgout[0])
+#define OOSIOP_CMDOFF OOSIOP_XFEROFF(scsi_cmd)
+
+#define OOSIOP_XFERSCR_SYNC(sc, cb, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DINSCROFF, \
+ OOSIOP_MSGINOFF - OOSIOP_DINSCROFF, (ops))
+#define OOSIOP_DINSCR_SYNC(sc, cb, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DINSCROFF, \
+ OOSIOP_DOUTSCROFF - OOSIOP_DINSCROFF, (ops))
+#define OOSIOP_DOUTSCR_SYNC(sc, cb, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DOUTSCROFF,\
+ OOSIOP_MSGINOFF - OOSIOP_DOUTSCROFF, (ops))
+#define OOSIOP_XFERMSG_SYNC(sc, cb, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_MSGINOFF, \
+ sizeof(struct oosiop_xfer) - OOSIOP_MSGINOFF, (ops))
+
+#define OOSIOP_SCRIPT_SYNC(sc, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_scrdma, \
+ 0, sizeof(oosiop_script), (ops))
+
+struct oosiop_cb {
+ TAILQ_ENTRY(oosiop_cb) chain;
+
+ struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
+ int flags;
+ int id; /* target scsi id */
+ int lun; /* target lun */
+
+ bus_dmamap_t cmddma; /* DMA map for command out */
+ bus_dmamap_t datadma; /* DMA map for data I/O */
+ bus_dmamap_t xferdma; /* DMA map for xfer block */
+
+ int curdp; /* current data pointer */
+ int savedp; /* saved data pointer */
+ int msgoutlen;
+
+ int xsflags; /* copy of xs->flags */
+ int datalen; /* copy of xs->datalen */
+
+ struct oosiop_xfer *xfer; /* DMA xfer block */
+};
+
+/* oosiop_cb flags */
+#define CBF_SELTOUT 0x01 /* Selection timeout */
+#define CBF_TIMEOUT 0x02 /* Command timeout */
+#define CBF_AUTOSENSE 0x04 /* Request sense due to SCSI_CHECK */
+
+struct oosiop_target {
+ struct oosiop_cb *nexus;
+ int flags;
+ u_int8_t scf; /* synchronous clock divisor */
+ u_int8_t sxfer; /* synchronous period and offset */
+};
+
+/* target flags */
+#define TGTF_SYNCNEG 0x01 /* Trigger synchronous negotiation */
+#define TGTF_WAITSDTR 0x02 /* Waiting SDTR from target */
+
+struct oosiop_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_bst; /* bus space tag */
+ bus_space_handle_t sc_bsh; /* bus space handle */
+
+ bus_dma_tag_t sc_dmat; /* bus DMA tag */
+ bus_dmamap_t sc_scrdma; /* script DMA map */
+
+ bus_addr_t sc_scrbase; /* script DMA base address */
+ u_int32_t *sc_scr; /* ptr to script memory */
+
+ int sc_chip; /* 700 or 700-66 */
+#define OOSIOP_700 0
+#define OOSIOP_700_66 1
+
+ int sc_id; /* SCSI ID of this interface */
+ int sc_freq; /* SCLK frequency */
+ int sc_ccf; /* asynchronous divisor (*10) */
+ u_int8_t sc_dcntl;
+ u_int8_t sc_minperiod;
+
+ struct oosiop_target sc_tgt[OOSIOP_NTGT];
+
+ struct scsi_link sc_link;
+
+ /* Lists of command blocks */
+ TAILQ_HEAD(oosiop_cb_queue, oosiop_cb) sc_free_cb,
+ sc_cbq;
+
+ struct oosiop_cb *sc_curcb; /* current command */
+ struct oosiop_cb *sc_lastcb; /* last activated command */
+
+ bus_addr_t sc_reselbuf; /* msgin buffer for reselection */
+ int sc_resid; /* reselected target id */
+
+ int sc_active;
+ int sc_nextdsp;
+};
+
+#define oosiop_read_1(sc, addr) \
+ bus_space_read_1((sc)->sc_bst, (sc)->sc_bsh, (addr))
+#define oosiop_write_1(sc, addr, data) \
+ bus_space_write_1((sc)->sc_bst, (sc)->sc_bsh, (addr), (data))
+/* XXX byte swapping should be handled by MD bus_space(9)? */
+#define oosiop_read_4(sc, addr) \
+ letoh32(bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (addr)))
+#define oosiop_write_4(sc, addr, data) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (addr), htole32(data))
+
+void oosiop_attach(struct oosiop_softc *);
+int oosiop_intr(struct oosiop_softc *);
diff --git a/sys/dev/microcode/siop/Makefile b/sys/dev/microcode/siop/Makefile
index db8a569b205..223a767324a 100644
--- a/sys/dev/microcode/siop/Makefile
+++ b/sys/dev/microcode/siop/Makefile
@@ -1,7 +1,7 @@
-# $OpenBSD: Makefile,v 1.2 2003/01/08 02:11:38 krw Exp $
+# $OpenBSD: Makefile,v 1.3 2004/03/12 00:04:57 miod Exp $
# $NetBSD: Makefile,v 1.1 2000/04/21 17:57:01 bouyer Exp $
-all: siop.out osiop.out
+all: siop.out osiop.out oosiop.out
PROG= ncr53cxxx
MKSHARE=no
@@ -9,11 +9,14 @@ MAN=
.include <bsd.prog.mk>
-regen: siop.out osiop.out
-headers: siop.out osiop.out
+regen: siop.out osiop.out oosiop.out
+headers: siop.out osiop.out oosiop.out
siop.out: siop.ss ${PROG}
./${PROG} siop.ss -p siop.out
osiop.out: osiop.ss ${PROG}
./${PROG} osiop.ss -p osiop.out
+
+oosiop.out: oosiop.ss ${PROG}
+ ./${PROG} oosiop.ss -p oosiop.out
diff --git a/sys/dev/microcode/siop/ncr53cxxx.c b/sys/dev/microcode/siop/ncr53cxxx.c
index d742fdd6c80..12b6c0aa06f 100644
--- a/sys/dev/microcode/siop/ncr53cxxx.c
+++ b/sys/dev/microcode/siop/ncr53cxxx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ncr53cxxx.c,v 1.5 2003/06/27 20:38:49 krw Exp $ */
+/* $OpenBSD: ncr53cxxx.c,v 1.6 2004/03/12 00:04:57 miod Exp $ */
/* $NetBSD: ncr53cxxx.c,v 1.10 2002/04/21 22:40:10 bouyer Exp $ */
/*
@@ -415,7 +415,7 @@ main (int argc, char *argv[])
if (outfp) {
time_t cur_time;
- fprintf(outfp, "/*\t$NetBSD: ncr53cxxx.c,v 1.10 2002/04/21 22:40:10 bouyer Exp $\t*/\n");
+ fprintf(outfp, "/*\t$OpenBSD: ncr53cxxx.c,v 1.6 2004/03/12 00:04:57 miod Exp $\t*/\n");
fprintf(outfp, "/*\n");
fprintf(outfp, " *\tDO NOT EDIT - this file is automatically generated.\n");
time(&cur_time);
@@ -1046,10 +1046,12 @@ void f_wait (void)
errout ("Expected SELECT or RESELECT");
++i;
if (reserved ("rel", i)) {
+#if 0 /* XXX driver will fix relative dsps to absolute */
if (arch < ARCH710) {
errout ("Wrong arch for relative dsps");
return;
}
+#endif
i += 2;
inst1 = evaluate (i) - dsps - 8;
inst0 |= 0x04000000;
@@ -1157,10 +1159,12 @@ void transfer (int word0, int type)
i = tokenix;
inst0 = word0;
if (type == 0 && reserved ("rel", i)) {
+#if 0 /* XXX driver will fix relative dsps to absolute */
if (arch < ARCH710) {
errout ("Wrong arch for relative dsps");
return;
}
+#endif
inst1 = evaluate (i + 2) - dsps - 8;
i += 4;
inst0 |= 0x00800000;
@@ -1244,10 +1248,12 @@ void select_reselect (int t)
inst0 |= (evaluate (t++) & 0xff) << 16;
if (tokens[t++].type == ',') {
if (reserved ("rel", t)) {
+#if 0 /* XXX driver will fix relative dsps to absolute */
if (arch < ARCH710) {
errout ("Wrong arch for relative dsps");
return;
}
+#endif
inst0 |= 0x04000000;
inst1 = evaluate (t + 2) - dsps - 8;
}
diff --git a/sys/dev/microcode/siop/oosiop.ss b/sys/dev/microcode/siop/oosiop.ss
new file mode 100644
index 00000000000..b1c084f803c
--- /dev/null
+++ b/sys/dev/microcode/siop/oosiop.ss
@@ -0,0 +1,150 @@
+; $NetBSD: oosiop.ss,v 1.2 2003/04/06 09:48:42 tsutsui Exp $
+
+;
+; Copyright (c) 2001 Shuichiro URATA. 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. 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.
+;
+
+; NCR 53c700 script
+;
+
+ARCH 700
+
+; interrupt codes
+ABSOLUTE int_done = 0xbeef0000
+ABSOLUTE int_msgin = 0xbeef0001
+ABSOLUTE int_extmsg = 0xbeef0002
+ABSOLUTE int_resel = 0xbeef0003
+ABSOLUTE int_res_id = 0xbeef0004
+ABSOLUTE int_resfail = 0xbeef0005
+ABSOLUTE int_disc = 0xbeef0006
+ABSOLUTE int_err = 0xdeadbeef
+
+; patch entries
+ENTRY p_resel_msgin_move
+ENTRY p_select
+ENTRY p_datain_jump
+ENTRY p_dataout_jump
+ENTRY p_msgin_move
+ENTRY p_msgout_move
+ENTRY p_cmdout_move
+ENTRY p_status_move
+ENTRY p_extmsglen_move
+ENTRY p_extmsgin_move
+
+
+PROC oosiop_script:
+
+ENTRY wait_reselect
+wait_reselect:
+ WAIT RESELECT REL(reselect_fail)
+ INT int_resel
+reselect_fail:
+ INT int_resfail
+
+ENTRY wait_resel_identify
+wait_resel_identify:
+ INT int_err, WHEN NOT MSG_IN
+p_resel_msgin_move:
+ MOVE 0, 0, WHEN MSG_IN
+ INT int_res_id
+
+ENTRY start_select
+start_select:
+p_select:
+ SELECT ATN 0, REL(wait_reselect)
+
+ENTRY phasedispatch
+phasedispatch:
+ JUMP REL(msgin), WHEN MSG_IN
+ JUMP REL(msgout), WHEN MSG_OUT
+ JUMP REL(status), WHEN STATUS
+ JUMP REL(cmdout), WHEN CMD
+p_datain_jump:
+ JUMP 0, WHEN DATA_IN
+p_dataout_jump:
+ JUMP 0, WHEN DATA_OUT
+ INT int_err
+
+msgin:
+ CLEAR ATN
+p_msgin_move:
+ MOVE 0, 0, WHEN MSG_IN
+ JUMP REL(complete), IF 0x00
+ JUMP REL(extmsgsetup), IF 0x01
+ JUMP REL(disconnect), IF 0x04
+ INT int_msgin
+
+ENTRY ack_msgin
+ack_msgin:
+ CLEAR ACK
+ JUMP REL(phasedispatch)
+
+ENTRY sendmsg
+sendmsg:
+ SET ATN
+ CLEAR ACK
+msgout:
+p_msgout_move:
+ MOVE 0, 0, WHEN MSG_OUT
+ CLEAR ATN
+ JUMP REL(phasedispatch)
+
+cmdout:
+ CLEAR ATN
+p_cmdout_move:
+ MOVE 0, 0, WHEN CMD
+ JUMP REL(phasedispatch)
+
+status:
+p_status_move:
+ MOVE 0, 0, WHEN STATUS
+ JUMP REL(phasedispatch)
+
+disconnect:
+ CLEAR ACK
+ WAIT DISCONNECT
+ INT int_disc
+
+complete:
+ CLEAR ACK
+ WAIT DISCONNECT
+ INT int_done
+
+; receive extended message length
+extmsgsetup:
+ CLEAR ACK
+ INT int_err, IF NOT MSG_IN
+p_extmsglen_move:
+ MOVE 0, 0, WHEN MSG_IN
+ INT int_extmsg
+
+; receive extended message
+ENTRY rcv_extmsg
+rcv_extmsg:
+ CLEAR ACK
+ INT int_err, IF NOT MSG_IN
+p_extmsgin_move:
+ MOVE 0, 0, WHEN MSG_IN
+ INT int_msgin