Subject: kern/6654: add support of AMD Am53c974 PCscsi-PCI SCSI
To: None <gnats-bugs@gnats.netbsd.org>
From: None <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 12/27/1998 01:33:55
>Number: 6654
>Category: kern
>Synopsis: add support of AMD Am53c974 PCscsi-PCI SCSI
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Dec 26 08:50:01 1998
>Last-Modified:
>Originator: Izumi Tsutsui
>Organization:
Izumi Tsutsui Himeji City Japan
>Release: NetBSD-current supped around 19981205
>Environment:
System: NetBSD mirage 1.3I NetBSD 1.3I (LANCER) #416: Sat Dec 26 19:51:35 JST 1998 tsutsui@lancer:/usr/src/sys/arch/macppc/compile/LANCER macppc
>Description:
AMD Am53c974 PCscsi-PCI SCSI is not supported by NetBSD currently.
>How-To-Repeat:
Put the device (like Tekram DC-390) on your machine and
try to configure.
>Fix:
Attached is a diff to support Am53c974.
It uses MI ncr53c9x driver. `esp_pci.c' is device dependent code
which contains PCI probe, attachment and ncr53c9x glue functions.
ncr53c9x*.[ch] is also modified to support Am53c974 quirks.
Although files are named `esp*.[ch]', the device name defined
in files.pci is `amd'. `esp' is already defined in files.isa and
files.macppc so naming `esp' causes name space conflicts.
I think `ncr53c9x' is MI device name, but `esp' is MD one.
alpha uses `asc' for TC ncr53c9x, and amiga uses flsc etc. for FAS216.
I think it might be needed to rename `esp_pci' to `amd'...
This driver is tested only Tekram DC-390 on macppc,
but would work on the other archs, hopefully.
Please test on the other archs. At lease,
this can compile on i386 and alpha.
Because of Am53c974 hardware specification, the scatter and gather
code will not work on archs which have logical pagesize less than 4096.
Anyway, there is no such arch currently...
--- sys/dev/pci/files.pci.orig Wed Nov 4 21:11:22 1998
+++ sys/dev/pci/files.pci Sat Dec 19 12:04:40 1998
@@ -43,6 +43,11 @@
attach isp at pci with isp_pci
file dev/pci/isp_pci.c isp_pci
+# AMD Am53c974 PCscsi-PCI SCSI
+device amd: scsi, ncr53c9x
+attach amd at pci with esp_pci
+file dev/pci/esp_pci.c esp_pci
+
# Ethernet driver for DC21040-based boards
device de: ether, ifnet, arp
attach de at pci
--- sys/dev/ic/ncr53c9x.c.orig Mon Nov 30 21:14:53 1998
+++ sys/dev/ic/ncr53c9x.c Thu Dec 24 23:13:08 1998
@@ -143,6 +143,7 @@
"ESP406",
"FAS408",
"FAS216",
+ "AM53C974",
};
/*
@@ -266,6 +267,7 @@
case NCR_VARIANT_ESP406:
case NCR_VARIANT_FAS408:
NCR_SCSIREGS(sc);
+ case NCR_VARIANT_AM53C974:
case NCR_VARIANT_FAS216:
case NCR_VARIANT_NCR53C94:
case NCR_VARIANT_NCR53C96:
@@ -288,6 +290,10 @@
NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
}
+ /* XXX cannot put this in the above switch() */
+ if (sc->sc_rev == NCR_VARIANT_AM53C974)
+ NCR_WRITE_REG(sc, NCR_AMDCFG4,
+ NCRAMDCFG4_GE12NS | NCRAMDCFG4_RADE);
}
/*
@@ -437,8 +443,16 @@
* put the chip in Fast SCSI mode.
*/
if (ti->period <= 50)
- cfg3 |= NCRCFG3_FSCSI;
+ cfg3 |= (sc->sc_rev == NCR_VARIANT_AM53C974) ?
+ NCRAMDCFG3_FSCSI : NCRCFG3_FSCSI;
}
+ /*
+ * Am53c974 requires different SYNCTP values
+ * when the FASTSCSI bit is off.
+ */
+ if (sc->sc_rev == NCR_VARIANT_AM53C974 &&
+ (cfg3 & NCRAMDCFG3_FSCSI) == 0)
+ synctp--;
} else {
syncoff = 0;
synctp = 0;
--- sys/dev/ic/ncr53c9xreg.h.orig Sun May 18 20:21:23 1997
+++ sys/dev/ic/ncr53c9xreg.h Sat Dec 26 00:33:53 1998
@@ -224,3 +224,26 @@
#define NCRCFG5_AINT 0x01 /* ATA Interupt Enable */
#define NCR_SIGNTR 0x0e /* RO - Signature */
+
+/* The following registers are only on the Am53c974. */
+
+/* Config #3 different on Am53c974 */
+#define NCR_AMDCFG3 0x0c /* RW - Configuration #3 */
+#define NCRAMDCFG3_IDM 0x80 /* ID Message Res Check */
+#define NCRAMDCFG3_QTE 0x40 /* Queue Tag Enable */
+#define NCRAMDCFG3_CDB 0x20 /* CDB 10-bytes OK */
+#define NCRAMDCFG3_FSCSI 0x10 /* Fast SCSI */
+#define NCRAMDCFG3_FCLK 0x08 /* Fast Clock (40MHz) */
+#define NCRAMDCFG3_RSVD 0x07 /* Reserved */
+
+/* Config #4 on Am53c974 */
+#define NCR_AMDCFG4 0x0d /* RW - Configuration #4 */
+#define NCRAMDCFG4_GE 0xC0 /* Glitch Eater */
+#define NCRAMDCFG4_GE12NS 0x00 /* Signal window 12ns */
+#define NCRAMDCFG4_GE25NS 0x80 /* Signal window 25ns */
+#define NCRAMDCFG4_GE35NS 0x40 /* Signal window 35ns */
+#define NCRAMDCFG4_GE0NS 0xC0 /* Signal window 0ns */
+#define NCRAMDCFG4_PWD 0x20 /* Reduced power future */
+#define NCRAMDCFG4_RSVD 0x13 /* reserved */
+#define NCRAMDCFG4_RAE 0x08 /* Active neg. REQ/ACK */
+#define NCRAMDCFG4_RADE 0x04 /* Active neg. REQ/ACK/DAT */
--- sys/dev/ic/ncr53c9xvar.h.orig Fri Nov 20 21:25:20 1998
+++ sys/dev/ic/ncr53c9xvar.h Sat Dec 12 13:36:35 1998
@@ -86,7 +86,8 @@
#define NCR_VARIANT_ESP406 5
#define NCR_VARIANT_FAS408 6
#define NCR_VARIANT_FAS216 7
-#define NCR_VARIANT_MAX 8
+#define NCR_VARIANT_AM53C974 8
+#define NCR_VARIANT_MAX 9
/*
* ECB. Holds additional information for each SCSI command Comments: We
--- /dev/null Fri Dec 25 23:07:55 1998
+++ sys/dev/pci/esp_pci.c Thu Dec 24 23:40:01 1998
@@ -0,0 +1,716 @@
+/* $NetBSD: esp_pci.c $ */
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1994 Peter Galbavy
+ * 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 Peter Galbavy
+ * 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.
+ */
+
+/*
+ * Based on aic6360 by Jarle Greipsland
+ *
+ * Acknowledgements: Many of the algorithms used in this driver are
+ * inspired by the work of Julian Elischer (julian@tfs.com) and
+ * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
+ */
+
+/*
+ * esp_pci.c: device dependent code for AMD Am53c974 (PCscsi-PCI)
+ * written by Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
+ *
+ * Technical manual available at
+ * http://www.amd.com/products/npd/techdocs/19113a.pdf
+ *
+ * XXX naming device `esp' causes conflicts with isa and macppc obio...
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsi_message.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/ic/ncr53c9xreg.h>
+#include <dev/ic/ncr53c9xvar.h>
+
+#include <dev/pci/espreg.h>
+#include <dev/pci/espvar.h>
+
+#define IO_MAP_REG 0x10
+#define MEM_MAP_REG 0x14
+
+/* don't have to use MI defines in MD code... */
+#undef NCR_READ_REG
+#define NCR_READ_REG(sc, reg) esp_pci_read_reg((sc), (reg))
+#undef NCR_WRITE_REG
+#define NCR_WRITE_REG(sc, reg, val) esp_pci_write_reg((sc), (reg), (val))
+
+int esp_pci_match __P((struct device *, struct cfdata *, void *));
+void esp_pci_attach __P((struct device *, struct device *, void *));
+
+struct cfattach esp_pci_ca = {
+ sizeof(struct esp_pci_softc), esp_pci_match, esp_pci_attach
+};
+
+struct scsipi_device esp_pci_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+};
+
+int esp_debug = 0; /* ESP_SHOWTRAC | ESP_SHOWREGS | ESP_SHOWMISC */
+
+/*
+ * Functions and the switch for the MI code.
+ */
+
+u_char esp_pci_read_reg __P((struct ncr53c9x_softc *, int));
+void esp_pci_write_reg __P((struct ncr53c9x_softc *, int, u_char));
+int esp_pci_dma_isintr __P((struct ncr53c9x_softc *));
+void esp_pci_dma_reset __P((struct ncr53c9x_softc *));
+int esp_pci_dma_intr __P((struct ncr53c9x_softc *));
+int esp_pci_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
+ size_t *, int, size_t *));
+void esp_pci_dma_go __P((struct ncr53c9x_softc *));
+void esp_pci_dma_stop __P((struct ncr53c9x_softc *));
+int esp_pci_dma_isactive __P((struct ncr53c9x_softc *));
+
+struct ncr53c9x_glue esp_pci_glue = {
+ esp_pci_read_reg,
+ esp_pci_write_reg,
+ esp_pci_dma_isintr,
+ esp_pci_dma_reset,
+ esp_pci_dma_intr,
+ esp_pci_dma_setup,
+ esp_pci_dma_go,
+ esp_pci_dma_stop,
+ esp_pci_dma_isactive,
+ NULL, /* gl_clear_latched_intr */
+};
+
+int
+esp_pci_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+ if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD)
+ return 0;
+
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_AMD_PCSCSI_PCI:
+/* case PCI_PRODUCT_AMD_PCNETS_PCI: */
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Attach this instance, and then all the sub-devices
+ */
+
+void
+esp_pci_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+ struct esp_pci_softc *esc = (void *)self;
+ struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
+ bus_space_tag_t st, iot, memt;
+ bus_space_handle_t sh, ioh, memh;
+ int ioh_valid, memh_valid;
+ pci_intr_handle_t ih;
+ const char *intrstr;
+ pcireg_t csr;
+ bus_dma_segment_t seg;
+ int error, rseg;
+
+ ioh_valid = (pci_mapreg_map(pa, IO_MAP_REG,
+ PCI_MAPREG_TYPE_IO, 0,
+ &iot, &ioh, NULL, NULL) == 0);
+#if 0 /* XXX cannot use memory map? */
+ memh_valid = (pci_mapreg_map(pa, MEM_MAP_REG,
+ PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
+ &memt, &memh, NULL, NULL) == 0);
+#else
+ memh_valid = 0;
+#endif
+
+ if (memh_valid) {
+ st = memt;
+ sh = memh;
+ } else if (ioh_valid) {
+ st = iot;
+ sh = ioh;
+ } else {
+ printf(": unable to map registers\n");
+ return;
+ }
+ printf("\n");
+
+ sc->sc_glue = &esp_pci_glue;
+
+ esc->sc_st = st;
+ esc->sc_sh = sh;
+ esc->sc_pc = pa->pa_pc;
+ esc->sc_tag = pa->pa_tag;
+ esc->sc_dmat = pa->pa_dmat;
+
+ csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+ csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE);
+
+ /*
+ * XXX More of this should be in ncr53c9x_attach(), but
+ * XXX should we really poke around the chip that much in
+ * XXX the MI code? Think about this more...
+ */
+
+ /*
+ * Set up static configuration info.
+ */
+
+ /*
+ * XXX should read configuration from EEPROM?
+ *
+ * MI ncr53c9x driver does not support configuration
+ * per each target device, though...
+ */
+ sc->sc_id = 7;
+ sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
+ sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE;
+ sc->sc_cfg3 = NCRAMDCFG3_IDM | NCRAMDCFG3_FCLK;
+ sc->sc_rev = NCR_VARIANT_AM53C974;
+ sc->sc_features = NCR_F_FASTSCSI;
+ sc->sc_freq = 40; /* MHz */
+
+ /*
+ * XXX minsync and maxxfer _should_ be set up in MI code,
+ * XXX but it appears to have some dependency on what sort
+ * XXX of DMA we're hooked up to, etc.
+ */
+
+ /*
+ * This is the value used to start sync negotiations
+ * Note that the NCR register "SYNCTP" is programmed
+ * in "clocks per byte", and has a minimum value of 4.
+ * The SCSI period used in negotiation is one-fourth
+ * of the time (in nanoseconds) needed to transfer one byte.
+ * Since the chip's clock is given in MHz, we have the following
+ * formula: 4 * period = (1000 / freq) * 4
+ */
+
+ sc->sc_minsync = 1000 / sc->sc_freq;
+
+ /* Really no limit, but since we want to fit into the TCR... */
+ sc->sc_maxxfer = 16 * 1024 * 1024;
+
+ /* map and establish interrupt */
+ if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &ih)) {
+ printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ intrstr = pci_intr_string(pa->pa_pc, ih);
+ esc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
+ (int (*)(void *))ncr53c9x_intr, esc);
+ if (esc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt", sc->sc_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+ if (intrstr != NULL)
+ printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname,
+ intrstr);
+
+ /*
+ * Create the DMA maps for the data transfers.
+ */
+
+#define MDL_SEG_SIZE 0x1000 /* 4kbyte per segment */
+#define MDL_SEG_OFFSET 0x0FFF
+#define MDL_SIZE (MAXPHYS / MDL_SEG_SIZE + 1) /* no hardware limit? */
+
+ if (bus_dmamap_create(esc->sc_dmat, MAXPHYS, MDL_SIZE, MAXPHYS, 0,
+ BUS_DMA_NOWAIT, &esc->sc_xfermap)) {
+ printf("%s: can't create dma maps\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /*
+ * Allocate and map memory for the MDL.
+ */
+
+ if ((error = bus_dmamem_alloc(esc->sc_dmat,
+ sizeof(u_int32_t) * MDL_SIZE, NBPG, 0, &seg, 1, &rseg,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf("%s: unable to allocate memory for the MDL, "
+ "error = %d\n", sc->sc_dev.dv_xname, error);
+ return;
+ }
+ if ((error = bus_dmamem_map(esc->sc_dmat, &seg, rseg,
+ sizeof(u_int32_t) * MDL_SIZE , (caddr_t *)&esc->sc_mdladdr,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("%s: unable to map the MDL memory, error = %d\n",
+ sc->sc_dev.dv_xname, error);
+ return;
+ }
+ if ((error = bus_dmamap_create(esc->sc_dmat,
+ sizeof(u_int32_t) * MDL_SIZE, 1, sizeof(u_int32_t) * MDL_SIZE,
+ 0, BUS_DMA_NOWAIT, &esc->sc_mdldmap)) != 0) {
+ printf("%s: unable to map_create for the MDL, error = %d\n",
+ sc->sc_dev.dv_xname, error);
+ return;
+ }
+ if ((error = bus_dmamap_load(esc->sc_dmat, esc->sc_mdldmap,
+ esc->sc_mdladdr, sizeof(u_int32_t) * MDL_SIZE,
+ NULL, BUS_DMA_NOWAIT)) != 0) {
+ printf("%s: unable to load for the MDL, error = %d\n",
+ sc->sc_dev.dv_xname, error);
+ return;
+ }
+
+ /* save MDL physical address for SMDLA register */
+ esc->sc_smdla = esc->sc_mdldmap->dm_segs[0].ds_addr;
+
+ /* Do the common parts of attachment. */
+ printf("%s", sc->sc_dev.dv_xname);
+
+ sc->sc_adapter.scsipi_cmd = ncr53c9x_scsi_cmd;
+ sc->sc_adapter.scsipi_minphys = minphys;
+
+ ncr53c9x_attach(sc, &esp_pci_dev);
+
+ /* Turn on target selection using the `dma' method */
+ ncr53c9x_dmaselect = 1;
+}
+
+/*
+ * Glue functions.
+ */
+
+u_char
+esp_pci_read_reg(sc, reg)
+ struct ncr53c9x_softc *sc;
+ int reg;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+
+ return bus_space_read_1(esc->sc_st, esc->sc_sh, reg << 2);
+}
+
+void
+esp_pci_write_reg(sc, reg, v)
+ struct ncr53c9x_softc *sc;
+ int reg;
+ u_char v;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+
+ bus_space_write_1(esc->sc_st, esc->sc_sh, reg << 2, v);
+}
+
+int
+esp_pci_dma_isintr(sc)
+ struct ncr53c9x_softc *sc;
+{
+ ESP_TRACE(("[esp_dma_isintr] "));
+
+ return NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT;
+}
+
+void
+esp_pci_dma_reset(sc)
+ struct ncr53c9x_softc *sc;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+
+ ESP_TRACE(("[esp_dma_reset] "));
+
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE);
+
+ esc->sc_active = 0;
+}
+
+int
+esp_pci_dma_intr(sc)
+ struct ncr53c9x_softc *sc;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+ int trans, resid, i;
+ bus_dmamap_t dmap = esc->sc_xfermap;
+ int datain = esc->sc_datain;
+ u_int32_t dmastat;
+ char *p = NULL;
+
+ ESP_TRACE(("[esp_dma_intr] "));
+
+ dmastat = READ_DMAREG(esc, DMA_STAT);
+
+ if (dmastat & DMASTAT_ERR) {
+ /* XXX not tested... */
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_ABORT |
+ (datain ? DMACMD_DIR : 0));
+
+ printf("%s: error: DMA error detected; Aborting.\n",
+ sc->sc_dev.dv_xname);
+ bus_dmamap_unload(esc->sc_dmat, dmap);
+ return -1;
+ }
+
+ if (dmastat & DMASTAT_ABT) {
+ /* XXX What should be done? */
+ printf("%s: dma_intr: DMA aborted.\n", sc->sc_dev.dv_xname);
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE |
+ (datain ? DMACMD_DIR : 0));
+ esc->sc_active = 0;
+ return 0;
+ }
+
+ /* This is an "assertion" :) */
+ if (esc->sc_active == 0)
+ panic("esp_pci dmaintr: DMA wasn't active");
+
+ /* DMA has stopped */
+
+ esc->sc_active = 0;
+
+ if (esc->sc_dmasize == 0) {
+ /* A "Transfer Pad" operation completed */
+ NCR_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n",
+ NCR_READ_REG(sc, NCR_TCL) |
+ (NCR_READ_REG(sc, NCR_TCM) << 8),
+ NCR_READ_REG(sc, NCR_TCL),
+ NCR_READ_REG(sc, NCR_TCM)));
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE |
+ (datain ? DMACMD_DIR : 0));
+ bus_dmamap_unload(esc->sc_dmat, dmap);
+ return 0;
+ }
+
+ resid = 0;
+
+ if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
+ /*
+ * `Terminal count' is off, so read the residue
+ * out of the ESP counter registers.
+ */
+ if (datain) {
+ resid = NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF;
+ while (resid > 1)
+ resid = NCR_READ_REG(sc, NCR_FFLAG) &
+ NCRFIFO_FF;
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_BLAST | DMACMD_MDL |
+ (datain ? DMACMD_DIR : 0));
+
+ for (i = 0; i < 0x8000; i++) /* XXX 0x8000 ? */
+ if (READ_DMAREG(esc, DMA_STAT) & DMASTAT_BCMP)
+ break;
+
+ /* See the below comments... */
+ if (resid)
+ p = *esc->sc_dmaaddr;
+ }
+
+ resid += (NCR_READ_REG(sc, NCR_TCL) |
+ (NCR_READ_REG(sc, NCR_TCM) << 8) |
+ ((sc->sc_cfg2 & NCRCFG2_FE)
+ ? (NCR_READ_REG(sc, NCR_TCH) << 16) : 0));
+
+ if (resid == 0 && esc->sc_dmasize == 65536 &&
+ (sc->sc_cfg2 & NCRCFG2_FE) == 0)
+ /* A transfer of 64K is encoded as `TCL=TCM=0' */
+ resid = 65536;
+ } else {
+ while((dmastat & DMASTAT_DONE) == 0)
+ dmastat = READ_DMAREG(esc, DMA_STAT);
+ }
+
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain ? DMACMD_DIR : 0));
+
+ bus_dmamap_sync(esc->sc_dmat, dmap, 0, dmap->dm_mapsize,
+ datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(esc->sc_dmat, dmap);
+
+ trans = esc->sc_dmasize - resid;
+
+ /*
+ * From the technical manual notes:
+ *
+ * `In some odd byte conditions, one residual byte will be left
+ * in the SCSI FIFO, and the FIFO flags will never count to 0.
+ * When this happens, the residual byte should be retrieved
+ * via PIO following completion of the BLAST operation.'
+ */
+
+ if (p) {
+ p += trans;
+ *p = NCR_READ_REG(sc, NCR_FIFO);
+ trans++;
+ }
+
+ if (trans < 0) { /* transferred < 0 ? */
+#if 0
+ /*
+ * This situation can happen in perfectly normal operation
+ * if the ESP is reselected while using DMA to select
+ * another target. As such, don't print the warning.
+ */
+ printf("%s: xfer (%d) > req (%d)\n",
+ sc->sc_dev.dv_xname, trans, esc->sc_dmasize);
+#endif
+ trans = esc->sc_dmasize;
+ }
+
+ NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
+ NCR_READ_REG(sc, NCR_TCL),
+ NCR_READ_REG(sc, NCR_TCM),
+ (sc->sc_cfg2 & NCRCFG2_FE)
+ ? NCR_READ_REG(sc, NCR_TCH) : 0,
+ trans, resid));
+
+ *esc->sc_dmalen -= trans;
+ *esc->sc_dmaaddr += trans;
+
+ return 0;
+}
+
+int
+esp_pci_dma_setup(sc, addr, len, datain, dmasize)
+ struct ncr53c9x_softc *sc;
+ caddr_t *addr;
+ size_t *len;
+ int datain;
+ size_t *dmasize;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+ bus_dmamap_t dmap = esc->sc_xfermap;
+ u_int32_t *mdl;
+ int error, nseg, seg;
+ bus_addr_t s_offset, s_addr;
+ long rest, count;
+
+ ESP_TRACE(("[esp_dma_setup] "));
+
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | (datain ? DMACMD_DIR : 0));
+
+ esc->sc_dmaaddr = addr;
+ esc->sc_dmalen = len;
+ esc->sc_dmasize = *dmasize;
+ esc->sc_datain = datain;
+
+#ifdef DIAGNOSTIC
+ if ((*dmasize / MDL_SEG_SIZE) > MDL_SIZE)
+ panic("esp_pci: transfer size too large");
+#endif
+
+ /*
+ * XXX should handle `Transfer Pad' operation?
+ * (case of *dmasize == 0)
+ */
+
+ error = bus_dmamap_load(esc->sc_dmat, dmap, *esc->sc_dmaaddr,
+ *esc->sc_dmalen, NULL,
+ sc->sc_nexus->xs->flags & SCSI_NOSLEEP ?
+ BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+ if (error) {
+ printf("%s: unable to load dmamap, error = %d\n",
+ sc->sc_dev.dv_xname, error);
+ return error;
+ }
+
+ /* set transfer length */
+ WRITE_DMAREG(esc, DMA_STC, *dmasize);
+
+ /* set up MDL */
+ mdl = esc->sc_mdladdr;
+ nseg = dmap->dm_nsegs;
+ seg = 0;
+
+ /* the first segment is possibly not aligned with 4k MDL boundary */
+ count = dmap->dm_segs[seg].ds_len;
+ s_offset = dmap->dm_segs[seg].ds_addr & MDL_SEG_OFFSET;
+ s_addr = dmap->dm_segs[seg].ds_addr - s_offset;
+ rest = MDL_SEG_SIZE - s_offset;
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define htopci(addr) bswap32(addr)
+#else
+#define htopci(addr) (addr)
+#endif
+
+ /* set the first MDL and offset */
+ WRITE_DMAREG(esc, DMA_SPA, s_offset);
+ *mdl++ = htopci(s_addr);
+ count -= rest;
+
+ /* rests of the first dmamap segment */
+ while (count > 0) {
+ s_addr += MDL_SEG_SIZE;
+ *mdl++ = htopci(s_addr);
+ count -= MDL_SEG_SIZE;
+ }
+
+ /* the rest dmamap segments are aligned with 4k boundary */
+ for (seg = 1; seg < nseg; seg++) {
+ count = dmap->dm_segs[seg].ds_len;
+ s_addr = dmap->dm_segs[seg].ds_addr;
+
+ /* first 4kbyte of each dmamap segment */
+ *mdl++ = htopci(s_addr);
+ count -= MDL_SEG_SIZE;
+
+ /* trailing contiguous 4k frames of each dmamap segments */
+ while (count > 0) {
+ s_addr += MDL_SEG_SIZE;
+ *mdl++ = htopci(s_addr);
+ count -= MDL_SEG_SIZE;
+ }
+ }
+
+ ESP_TRACE(("[esp_dma_setup]: return "));
+ return 0;
+}
+
+void
+esp_pci_dma_go(sc)
+ struct ncr53c9x_softc *sc;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+ bus_dmamap_t dmap = esc->sc_xfermap, mdldmap = esc->sc_mdldmap;
+ int datain = esc->sc_datain;
+
+ ESP_TRACE(("[esp_dma_go] "));
+
+ /* sync transfer buffer */
+ bus_dmamap_sync(esc->sc_dmat, dmap, 0, dmap->dm_mapsize,
+ datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+
+ /* sync MDL */
+ bus_dmamap_sync(esc->sc_dmat, mdldmap, 0, mdldmap->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ /* set Starting MDL Address */
+ WRITE_DMAREG(esc, DMA_SMDLA, esc->sc_smdla);
+
+ /* set DMA command register bits */
+ /* XXX DMA Transfer Interrupt Enable bit is broken? */
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE | DMACMD_MDL |
+ /* DMACMD_INTE | */
+ (datain ? DMACMD_DIR : 0));
+
+ /* issue DMA start command */
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_START | DMACMD_MDL |
+ /* DMACMD_INTE | */
+ (datain ? DMACMD_DIR : 0));
+
+ esc->sc_active = 1;
+}
+
+void
+esp_pci_dma_stop(sc)
+ struct ncr53c9x_softc *sc;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+
+ ESP_TRACE(("[esp_dma_stop] "));
+
+ /* dma stop */
+ /* XXX What should we do here ? */
+ WRITE_DMAREG(esc, DMA_CMD, DMACMD_ABORT |
+ ( esc->sc_datain ? DMACMD_DIR : 0));
+
+ esc->sc_active = 0;
+}
+
+int
+esp_pci_dma_isactive(sc)
+ struct ncr53c9x_softc *sc;
+{
+ struct esp_pci_softc *esc = (struct esp_pci_softc *)sc;
+
+ ESP_TRACE(("[esp_dma_isactive] "));
+
+ /* XXX should check esc->sc_active? */
+ if ((READ_DMAREG(esc, DMA_CMD) & DMACMD_CMD) != DMACMD_IDLE)
+ return 1;
+ return 0;
+}
--- /dev/null Fri Dec 25 23:07:55 1998
+++ sys/dev/pci/espreg.h Sun Dec 20 03:51:23 1998
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* am53c974 DMA engine registors */
+
+#define READ_DMAREG(sc, reg) \
+ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
+#define WRITE_DMAREG(sc, reg, var) \
+ bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (var))
+
+#define DMA_CMD 0x40 /* Command */
+#define DMACMD_RSVD 0xFFFFFF28 /* reserved */
+#define DMACMD_DIR 0x00000080 /* Transfer Direction (read:1) */
+#define DMACMD_INTE 0x00000040 /* DMA Interrupt Enable */
+#define DMACMD_MDL 0x00000010 /* Map to Memory Description List */
+#define DMACMD_DIAG 0x00000004 /* Diagnostic */
+#define DMACMD_CMD 0x00000003 /* Command Code Bit */
+#define DMACMD_IDLE 0x00000000 /* Idle */
+#define DMACMD_BLAST 0x00000001 /* Blast */
+#define DMACMD_ABORT 0x00000002 /* Abort */
+#define DMACMD_START 0x00000003 /* Start */
+
+#define DMA_STC 0x44 /* Start Transfer Count */
+#define DMA_SPA 0x48 /* Start Physical Address */
+#define DMA_WBC 0x4C /* Working Byte Counter */
+#define DMA_WAC 0x50 /* Working Address Counter */
+
+#define DMA_STAT 0x54 /* Status Register */
+#define DMASTAT_RSVD 0xFFFFFF80 /* reserved */
+#define DMASTAT_PABT 0x00000040 /* PCI master/target Abort */
+#define DMASTAT_BCMP 0x00000020 /* BLAST Complete */
+#define DMASTAT_SINT 0x00000010 /* SCSI Interrupt */
+#define DMASTAT_DONE 0x00000008 /* DMA Transfer Terminated */
+#define DMASTAT_ABT 0x00000004 /* DMA Transfer Aborted */
+#define DMASTAT_ERR 0x00000002 /* DMA Transfer Error */
+#define DMASTAT_PWDN 0x00000001 /* Power Down Indicator */
+
+#define DMA_SMDLA 0x58 /* Starting Memory Descpritor List Address */
+#define DMA_WMAC 0x5C /* Working MDL Counter */
+#define DMA_SBAC 0x70 /* SCSI Bus and Control */
--- /dev/null Fri Dec 25 23:07:55 1998
+++ sys/dev/pci/espvar.h Thu Dec 17 23:39:17 1998
@@ -0,0 +1,105 @@
+/* $NetBSD: espvar.h,v 1.2 1997/05/18 06:08:04 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1997 Allen Briggs.
+ * 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 Peter Galbavy.
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1997 Eric S. Hvozda (hvozda@netcom.com)
+ * 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 Eric S. Hvozda.
+ * 4. The name of Eric S. Hvozda 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.
+ */
+
+struct esp_pci_softc {
+ struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
+
+ int sc_active; /* DMA state vars */
+ int sc_datain; /* DMA Data Direction */
+ size_t sc_dmasize; /* DMA size */
+ char **sc_dmaaddr; /* DMA address */
+ size_t *sc_dmalen; /* DMA length */
+
+ pci_chipset_tag_t sc_pc; /* pci chipset tag */
+ pcitag_t sc_tag; /* pci device tag */
+ bus_space_tag_t sc_st; /* pci bus space tag */
+ bus_space_handle_t sc_sh; /* pci bus space handle */
+ void *sc_ih; /* interrupt handle */
+ bus_dma_tag_t sc_dmat; /* bus DMA tag */
+ bus_dmamap_t sc_xfermap; /* bus DMA map */
+ u_int32_t *sc_mdladdr; /* MDL array */
+ u_int32_t sc_smdla; /* SMDLA */
+ bus_dmamap_t sc_mdldmap; /* MDL DMA map */
+
+#ifdef ESP_DEBUG
+ int sc_debug;
+#endif
+};
+
+#ifdef ESP_DEBUG
+extern int esp_debug;
+
+#define ESP_SHOWTRAC 0x01
+#define ESP_SHOWREGS 0x02
+#define ESP_SHOWMISC 0x04
+
+#define ESP_TRACE(str) \
+ do {if (esp_debug & ESP_SHOWTRAC) printf str;} while (0)
+#define ESP_REGS(str) \
+ do {if (esp_debug & ESP_SHOWREGS) printf str;} while (0)
+#define ESP_MISC(str) \
+ do {if (esp_debug & ESP_SHOWMISC) printf str;} while (0)
+#else
+#define ESP_TRACE(str)
+#define ESP_REGS(str)
+#define ESP_MISC(str)
+#endif
--- sys/arch/macppc/conf/GENERIC.orig Thu Nov 26 21:20:06 1998
+++ sys/arch/macppc/conf/GENERIC Sat Dec 26 23:16:44 1998
@@ -115,9 +115,11 @@
ne* at pci? dev ? function ? # NE2000-compatible Ethernet
adv* at pci? dev ? function ? # AdvanSys 1200[A,B], 9xx[U,UA] SCSI
#ahc* at pci? dev ? function ? # Adaptec 294x, aic78x0 SCSI
+amd* at pci? dev ? function ? # AMD Am53c974 PCscsi-PCI SCSI
scsibus* at adv?
#scsibus* at ahc?
+scsibus* at amd?
obio0 at pci? dev ? function ?
nvram0 at obio0 # nvram
>Audit-Trail:
>Unformatted: