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: