[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    ami(4) needs testing
From:       Marco Peereboom <marco () peereboom ! us>
Date:       2004-12-22 17:42:55
Message-ID: 20041222174247.GA5623 () peereboom ! us
[Download RAW message or body]

This diff should fix long outstanding issues with ami(4).  The reported
symptoms that were fixed are:
* Very slow throughput
* ccb timeout (i.e. ami0: timeout ccb 1)
* All IO to ami devices hangs
* Only 1 LD (Logical Drive) can be accessed at the same time
* System hangs/freezes

Issues it doesn't fix:
* Really old ULTRA-2 controllers still crash whenever more than 1 LD are
  accessed at the same time therefore the driver limits the maximum LDs to 1.

Currently this diff is in the snapshots so please download and test the
stability of the patch.  For the amd64 fans out there, please download and test
a snap too; ami support for everyone :-) Keep in mind that the controllers must
have the latest firmware on them, the firmware I tested with was released
earlier in 2004.  I tested LSI and Dell firmware on the controllers.
Download firmware at:
* megaraid express 500  http://www.lsilogic.com/downloads/selectDownload.do
* Dell PERC http://support.dell.com/support/downloads/

What I have not been able to test are the really, really old cards.  So if
someone has a ULTRA controller out there please give it a twirl and report back.

Lots of people helped getting this done.  Thanks LSI, mickey@, deraadt@, beck@
and some others for testing, prodding, suggestions and yelling.

/marco

Index: ic/ami.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/ami.c,v
retrieving revision 1.24
diff -u -r1.24 ami.c
--- ic/ami.c	9 Jan 2004 21:32:23 -0000	1.24
+++ ic/ami.c	21 Dec 2004 00:16:20 -0000
@@ -103,8 +103,14 @@
 	NULL, NULL, NULL, NULL
 };
 
-static __inline struct ami_ccb *ami_get_ccb(struct ami_softc *sc);
-static __inline void ami_put_ccb(struct ami_ccb *ccb);
+struct ami_ccb *ami_get_ccb(struct ami_softc *sc);
+void ami_put_ccb(struct ami_ccb *ccb);
+
+void ami_write_inbound_db(struct ami_softc *, u_int32_t);
+void ami_write_outbound_db(struct ami_softc *, u_int32_t);
+u_int32_t ami_read_inbound_db(struct ami_softc *);
+u_int32_t ami_read_outbound_db(struct ami_softc *);
+
 void ami_copyhds(struct ami_softc *sc, const u_int32_t *sizes,
 	const u_int8_t *props, const u_int8_t *stats);
 void *ami_allocmem(bus_dma_tag_t dmat, bus_dmamap_t *map,
@@ -121,7 +127,7 @@
 int  ami_inquire(struct ami_softc *sc, u_int8_t op);
 
 
-static __inline struct ami_ccb *
+struct ami_ccb *
 ami_get_ccb(sc)
 	struct ami_softc *sc;
 {
@@ -135,7 +141,7 @@
 	return ccb;
 }
 
-static __inline void
+void
 ami_put_ccb(ccb)
 	struct ami_ccb *ccb;
 {
@@ -145,6 +151,58 @@
 	TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
 }
 
+void
+ami_write_inbound_db(sc, v)
+	struct ami_softc *sc;
+	u_int32_t v;
+{
+	AMI_DPRINTF(AMI_D_CMD, ("ami_write_inbound_db(%x)", v));
+
+	bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, v);
+	bus_space_barrier(sc->iot, sc->ioh,
+	    AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE);
+}
+
+u_int32_t
+ami_read_inbound_db(sc)
+	struct ami_softc *sc;
+{
+	u_int32_t rv;
+	
+	bus_space_barrier(sc->iot, sc->ioh,
+	    AMI_QIDB, 4, BUS_SPACE_BARRIER_READ);
+	rv = bus_space_read_4(sc->iot, sc->ioh, AMI_QIDB);
+	AMI_DPRINTF(AMI_D_CMD, ("ami_read_inbound_db(%x)", rv));
+
+	return (rv);
+}
+
+void
+ami_write_outbound_db(sc, v)
+	struct ami_softc *sc;
+	u_int32_t v;
+{
+	AMI_DPRINTF(AMI_D_CMD, ("ami_write_outbound_db(%x)", v));
+
+	bus_space_write_4(sc->iot, sc->ioh, AMI_QODB, v);
+	bus_space_barrier(sc->iot, sc->ioh,
+	    AMI_QODB, 4, BUS_SPACE_BARRIER_WRITE);
+}
+
+u_int32_t
+ami_read_outbound_db(sc)
+	struct ami_softc *sc;
+{
+	u_int32_t rv;
+
+	bus_space_barrier(sc->iot, sc->ioh,
+	    AMI_QODB, 4, BUS_SPACE_BARRIER_READ);
+	rv = bus_space_read_4(sc->iot, sc->ioh, AMI_QODB);
+	AMI_DPRINTF(AMI_D_CMD, ("ami_read_outbound_db(%x)", rv));
+
+	return (rv);
+}
+
 void *
 ami_allocmem(dmat, map, segp, isize, nent, iname)
 	bus_dma_tag_t dmat;
@@ -414,8 +472,22 @@
 
 		AMI_UNLOCK_AMI(sc, lock);
 
-		if (sc->sc_maxcmds > AMI_MAXCMDS)
-			sc->sc_maxcmds = 1 /* AMI_MAXCMDS */;
+		if (sc->sc_quirks & AMI_BROKEN) {
+			sc->sc_link.openings = 1;
+			sc->sc_maxcmds = 1;
+			sc->sc_maxunits = 1;
+		}
+		else {
+			sc->sc_maxunits = AMI_BIG_MAX_LDRIVES;
+			if (sc->sc_maxcmds > AMI_MAXCMDS)
+				sc->sc_maxcmds = AMI_MAXCMDS;
+
+			if (sc->sc_nunits)
+				sc->sc_link.openings =
+				    sc->sc_maxcmds / sc->sc_nunits;
+			else
+				sc->sc_link.openings = sc->sc_maxcmds;
+		}
 	}
 	ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "init data");
 
@@ -431,22 +503,35 @@
 		    sc->sc_biosver[2], sc->sc_biosver[1], sc->sc_biosver[0]);
 	}
 
-	printf(": FW %s, BIOS v%s, %dMB RAM\n"
-	     "%s: %d channels, %d %ss, %d logical drives\n",
-	    sc->sc_fwver, sc->sc_biosver, sc->sc_memory,
-	    sc->sc_dev.dv_xname,
-	    sc->sc_channels, sc->sc_targets, p, sc->sc_nunits);
-
 	/* TODO: fetch & print cache strategy */
 	/* TODO: fetch & print scsi and raid info */
 
 	sc->sc_link.device = &ami_dev;
-	sc->sc_link.openings = sc->sc_maxcmds;
 	sc->sc_link.adapter_softc = sc;
 	sc->sc_link.adapter = &ami_switch;
 	sc->sc_link.adapter_target = sc->sc_maxunits;
 	sc->sc_link.adapter_buswidth = sc->sc_maxunits;
 
+#ifdef AMI_DEBUG
+	printf(": FW %s, BIOS v%s, %dMB RAM\n"
+	     "%s: %d channels, %d %ss, %d logical drives, "
+	     "openings %d, max commands %d, quirks: %04x\n",
+	    sc->sc_fwver, sc->sc_biosver, sc->sc_memory,
+	    sc->sc_dev.dv_xname,
+	    sc->sc_channels, sc->sc_targets, p, sc->sc_nunits,
+	    sc->sc_link.openings, sc->sc_maxcmds, sc->sc_quirks);
+#else
+	printf(": FW %s, BIOS v%s, %dMB RAM\n"
+	     "%s: %d channels, %d %ss, %d logical drives\n",
+	    sc->sc_fwver, sc->sc_biosver, sc->sc_memory,
+	    sc->sc_dev.dv_xname,
+	    sc->sc_channels, sc->sc_targets, p, sc->sc_nunits);
+#endif /* AMI_DEBUG */
+
+	if (sc->sc_quirks & AMI_BROKEN && sc->sc_nunits > 1)
+		printf("%s: firmware buggy, limiting access to first logical "
+		    "disk\n", sc->sc_dev.dv_xname);
+
 	config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
 #if 0
 	rsc = malloc(sizeof(struct ami_rawsoftc) * sc->sc_channels,
@@ -483,9 +568,7 @@
 ami_quartz_init(sc)
 	struct ami_softc *sc;
 {
-	bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, 0);
-	bus_space_barrier(sc->iot, sc->ioh,
-		    AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE);
+	ami_write_inbound_db(sc, 0);
 
 	return 0;
 }
@@ -495,31 +578,32 @@
 	struct ami_softc *sc;
 	struct ami_iocmd *cmd;
 {
-	u_int32_t qidb;
+	u_int32_t qidb, i;
 
-	bus_space_barrier(sc->iot, sc->ioh,
-	    AMI_QIDB, 4, BUS_SPACE_BARRIER_READ);
-	qidb = bus_space_read_4(sc->iot, sc->ioh, AMI_QIDB);
-	if (qidb & (AMI_QIDB_EXEC | AMI_QIDB_ACK)) {
-		AMI_DPRINTF(AMI_D_CMD, ("qidb1=%x ", qidb));
-		return (EBUSY);
-	}
+	AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_exec() "));
 
-	/* do not scramble the busy mailbox */
+	i = 0;
+	while (sc->sc_mbox->acc_busy && (i < AMI_MAX_BUSYWAIT)) {
+		delay(1);
+		i++;
+	}
 	if (sc->sc_mbox->acc_busy) {
 		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
 		return (EBUSY);
 	}
 
-	*sc->sc_mbox = *cmd;
-	bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sizeof(*cmd),
+	memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16);
+	bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, 16,
 	    BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
 
+	sc->sc_mbox->acc_busy = 1;
+	sc->sc_mbox->acc_poll = 0;
+	sc->sc_mbox->acc_ack = 0;
+
 	qidb = sc->sc_mbox_pa | AMI_QIDB_EXEC;
-	AMI_DPRINTF(AMI_D_CMD, ("qidb2=%x ", qidb));
-	bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, qidb);
-	bus_space_barrier(sc->iot, sc->ioh,
-	    AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE);
+	ami_write_inbound_db(sc, qidb);
+
+	AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_exec() returning "));
 	return (0);
 }
 
@@ -528,46 +612,72 @@
 	struct ami_softc *sc;
 	struct ami_iocmd *mbox;
 {
-	u_int32_t qdb;
-
-	bus_space_barrier(sc->iot, sc->ioh,
-	    AMI_QIDB, 4, BUS_SPACE_BARRIER_READ);
-	qdb = bus_space_read_4(sc->iot, sc->ioh, AMI_QIDB);
-	if (qdb & (AMI_QIDB_EXEC | AMI_QIDB_ACK)) {
-		AMI_DPRINTF(AMI_D_CMD, ("qidb3=%x ", qdb));
-		return (0);
+	u_int32_t qdb, i, n;
+	u_int8_t nstat, status;
+	u_int8_t completed[AMI_MAXSTATACK];
+
+	AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_done() "));
+
+	qdb = ami_read_outbound_db(sc);
+	if (qdb != AMI_QODB_READY)
+		return (0); /* nothing to do */
+
+	ami_write_outbound_db(sc, AMI_QODB_READY);
+
+	/*
+	 * The following sequence is not supposed to have a timeout clause
+	 * since the firmware has a "guarantee" that all commands will
+	 * complete.  The choice is either panic or hoping for a miracle
+	 * and that the IOs will complete much later.
+	 */
+	i = 0;
+	while ((nstat = sc->sc_mbox->acc_nstat) == 0xff) {
+		delay(1);
+		if (i++ > 1000000)
+			return (0); /* nothing to do */
+	}
+	sc->sc_mbox->acc_nstat = 0xff;
+
+	/* wait until fw wrote out all completions */
+	i = 0;
+	AMI_DPRINTF(AMI_D_CMD, ("ami_quartz_done() nstat %d ", nstat));
+	for (n = 0; n < nstat; n++) {
+		while ((completed[n] = sc->sc_mbox->acc_cmplidl[n]) ==
+		    0xff) {
+			delay(1);
+			if (i++ > 1000000)
+				return (0); /* nothing to do */
+		}
+		sc->sc_mbox->acc_cmplidl[n] = 0xff;
+	}
+
+	/* this should never happen, someone screwed up the completion status */
+	if ((status = sc->sc_mbox->acc_status) == 0xff)
+		panic("%s: status 0xff from the firmware", sc->sc_dev.dv_xname);
+
+	sc->sc_mbox->acc_status = 0xff;
+
+	/* ack interrupt */
+	ami_write_inbound_db(sc, AMI_QIDB_ACK);
+
+	i = 0;
+	while(ami_read_inbound_db(sc) & AMI_QIDB_ACK) {
+		delay(1);
+		if (i++ > 1000000)
+			return (0); /* nothing to do */
+	}
+
+	/* copy mailbox to temporary one and fixup other changed values */
+	bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, 16,
+	    BUS_DMASYNC_POSTWRITE);
+	memcpy(mbox, (struct ami_iocmd *)sc->sc_mbox, 16);
+	mbox->acc_nstat = nstat;
+	mbox->acc_status = status;
+	for (n = 0; n < nstat; n++) {
+		mbox->acc_cmplidl[n] = completed[n];
 	}
 
-	/* do not scramble the busy mailbox */
-	if (sc->sc_mbox->acc_busy) {
-		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
-		return (0);
-	}
-
-	bus_space_barrier(sc->iot, sc->ioh,
-	    AMI_QODB, 4, BUS_SPACE_BARRIER_READ);
-	qdb = bus_space_read_4(sc->iot, sc->ioh, AMI_QODB);
-	if (qdb == AMI_QODB_READY) {
-
-		bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sizeof(*mbox),
-		    BUS_DMASYNC_POSTWRITE);
-		*mbox = *sc->sc_mbox;
-
-		/* ack interrupt */
-		bus_space_write_4(sc->iot, sc->ioh, AMI_QODB, AMI_QODB_READY);
-		bus_space_barrier(sc->iot, sc->ioh,
-		    AMI_QODB, 4, BUS_SPACE_BARRIER_WRITE);
-
-		qdb = sc->sc_mbox_pa | AMI_QIDB_ACK;
-		bus_space_write_4(sc->iot, sc->ioh, AMI_QIDB, qdb);
-		bus_space_barrier(sc->iot, sc->ioh,
-		    AMI_QIDB, 4, BUS_SPACE_BARRIER_WRITE);
-		return (1);
-	}
-
-	AMI_DPRINTF(AMI_D_CMD, ("qodb=%x ", qdb));
-
-	return (0);
+	return (1); /* ready to complete all IOs in acc_cmplidl */
 }
 
 int
@@ -576,6 +686,8 @@
 {
 	u_int32_t a = (u_int32_t)sc->sc_mbox_pa;
 
+	AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_init() "));
+
 	bus_space_write_4(sc->iot, sc->ioh, AMI_SMBADDR, a);
 	/* XXX 40bit address ??? */
 	bus_space_write_1(sc->iot, sc->ioh, AMI_SMBENA, 0);
@@ -592,10 +704,18 @@
 	struct ami_softc *sc;
 	struct ami_iocmd *cmd;
 {
-	if (bus_space_read_1(sc->iot, sc->ioh, AMI_SMBSTAT) & AMI_SMBST_BUSY)
+	AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_exec() "));
+
+	if (bus_space_read_1(sc->iot, sc->ioh, AMI_SMBSTAT) & AMI_SMBST_BUSY) {
+		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
 		return EBUSY;
+	}
+
+	memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16);
+	sc->sc_mbox->acc_busy = 1;
+	sc->sc_mbox->acc_poll = 0;
+	sc->sc_mbox->acc_ack = 0;
 
-	*sc->sc_mbox = *cmd;
 	bus_space_write_1(sc->iot, sc->ioh, AMI_SCMD, AMI_SCMD_EXEC);
 	return 0;
 }
@@ -606,6 +726,8 @@
 	struct ami_iocmd *mbox;
 {
 	u_int8_t stat;
+
+	AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_done() "));
 #if 0
 	/* do not scramble the busy mailbox */
 	if (sc->sc_mbox->acc_busy)
@@ -619,6 +741,8 @@
 		bus_space_write_1(sc->iot, sc->ioh, AMI_ISTAT, stat);
 
 		*mbox = *sc->sc_mbox;
+		AMI_DPRINTF(AMI_D_CMD, ("ami_schwartz_done() acc_nstat %d ",
+		    mbox->acc_nstat));
 
 		bus_space_write_1(sc->iot, sc->ioh, AMI_SCMD, AMI_SCMD_ACK);
 
@@ -735,10 +859,6 @@
 
 	AMI_DPRINTF(AMI_D_CMD, ("exec "));
 
-	cmd->acc_busy = 1;
-	cmd->acc_poll = 0;
-	cmd->acc_ack = 0;
-
 	if (!(i = (sc->sc_exec)(sc, cmd))) {
 		ccb->ccb_state = AMI_CCB_QUEUED;
 		TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
@@ -1301,7 +1421,6 @@
 	lock = AMI_LOCK_AMI(sc);
 	s = splimp();	/* XXX need to do this to mask timeouts */
 	while ((sc->sc_done)(sc, &mbox)) {
-		AMI_DPRINTF(AMI_D_CMD, ("got#%d ", mbox.acc_nstat));
 		for (i = 0; i < mbox.acc_nstat; i++ ) {
 			int ready = mbox.acc_cmplidl[i];
 
@@ -1324,3 +1443,24 @@
 	AMI_DPRINTF(AMI_D_INTR, ("exit "));
 	return (rv);
 }
+
+#ifdef AMI_DEBUG
+void
+ami_print_mbox(mbox)
+	struct ami_iocmd *mbox;
+{
+	int i;
+
+	printf("acc_cmd: %d  aac_id: %d  acc_busy: %d  acc_nstat: %d",
+	    mbox->acc_cmd, mbox->acc_id, mbox->acc_busy, mbox->acc_nstat);
+	printf("acc_status: %d  acc_poll: %d  acc_ack: %d\n",
+	    mbox->acc_status, mbox->acc_poll, mbox->acc_ack);
+
+	printf("acc_cmplidl: ");
+	for (i = 0; i < AMI_MAXSTATACK; i++) {
+		printf("[%d] = %d  ", i, mbox->acc_cmplidl[i]);
+	}
+
+	printf("\n");
+}
+#endif /* AMI_DEBUG */
Index: ic/amireg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/amireg.h,v
retrieving revision 1.4
diff -u -r1.4 amireg.h
--- ic/amireg.h	2 Jun 2003 19:24:22 -0000	1.4
+++ ic/amireg.h	20 Dec 2004 23:50:08 -0000
@@ -36,10 +36,11 @@
 #define	AMI_BIG_MAX_SPANDEPTH	8
 #define	AMI_BIG_MAX_DEVDEPTH	32
 
-#define	AMI_MAXCMDS	120	/* theoretical limit is 255 */
+#define	AMI_MAXCMDS	126	/* theoretical limit is 250 */
 #define	AMI_SECTOR_SIZE	512
 #define	AMI_MAXOFFSETS	26
 #define	AMI_SGEPERCMD	32	/* to prevent page boundary crossing */
+#define AMI_MAX_BUSYWAIT 10	/* wait up to 10 usecs */
 
 #define	AMI_MAXFER	(AMI_MAXOFFSETS * PAGE_SIZE)
 
Index: ic/amivar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/amivar.h,v
retrieving revision 1.6
diff -u -r1.6 amivar.h
--- ic/amivar.h	2 Jun 2003 19:24:22 -0000	1.6
+++ ic/amivar.h	20 Dec 2004 23:50:08 -0000
@@ -86,6 +86,10 @@
 	struct timeout	sc_requeue_tmo;
 	struct timeout	sc_poll_tmo;
 
+/* don't use 0x0001 */
+#define AMI_BROKEN 0x0002
+	u_int16_t sc_quirks;
+
 	char	sc_fwver[16];
 	char	sc_biosver[16];
 	int	sc_maxcmds;
@@ -122,3 +126,6 @@
 int ami_schwartz_exec(struct ami_softc *sc, struct ami_iocmd *);
 int ami_schwartz_done(struct ami_softc *sc, struct ami_iocmd *);
 
+#ifdef AMI_DEBUG
+void ami_print_mbox(struct ami_iocmd *);
+#endif /* AMI_DEBUG */
Index: pci/ami_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ami_pci.c,v
retrieving revision 1.20
diff -u -r1.20 ami_pci.c
--- pci/ami_pci.c	22 Nov 2004 21:09:18 -0000	1.20
+++ pci/ami_pci.c	20 Dec 2004 23:50:08 -0000
@@ -62,6 +62,7 @@
 #define		AMI_SGL_LHC	0x00000299
 #define		AMI_SGL_HLC	0x00000199
 
+int	ami_pci_find_device(void *);
 int	ami_pci_match(struct device *, void *, void *);
 void	ami_pci_attach(struct device *, struct device *, void *);
 
@@ -77,12 +78,13 @@
 #define	AMI_CHECK_SIGN	0x001
 } ami_pci_devices[] = {
 	{ PCI_VENDOR_AMI,	PCI_PRODUCT_AMI_MEGARAID,	0 },
-	{ PCI_VENDOR_AMI,	PCI_PRODUCT_AMI_MEGARAID428,	0 },
-	{ PCI_VENDOR_AMI,	PCI_PRODUCT_AMI_MEGARAID434,	0 },
+	{ PCI_VENDOR_AMI,	PCI_PRODUCT_AMI_MEGARAID428,	AMI_BROKEN },
+	{ PCI_VENDOR_AMI,	PCI_PRODUCT_AMI_MEGARAID434,	AMI_BROKEN },
 	{ PCI_VENDOR_DELL,	PCI_PRODUCT_DELL_PERC_4DI,	0 },
 	{ PCI_VENDOR_DELL,	PCI_PRODUCT_DELL_PERC_4DI_2,	0 },
 	{ PCI_VENDOR_DELL,	PCI_PRODUCT_DELL_PERC_4EDI,	0 },	
-	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_80960RP_ATU, AMI_CHECK_SIGN },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_80960RP_ATU,
+	    AMI_CHECK_SIGN | AMI_BROKEN },
 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID,	0 },
 	{ 0 }
 };
@@ -117,6 +119,25 @@
 	{ 0 }
 };
 
+int ami_pci_find_device(aux)
+	void *aux;
+{
+	int i;
+	struct pci_attach_args *pa = aux;
+
+	for (i = 0; ami_pci_devices[i].vendor; i++) {
+		if (ami_pci_devices[i].vendor == PCI_VENDOR(pa->pa_id) &&
+		    ami_pci_devices[i].product == PCI_PRODUCT(pa->pa_id)) {
+#ifdef AMI_DEBUG
+		    	printf(" ami_pci_find_device() %i ", i);
+#endif /* AMI_DEBUG */
+			return (i);
+		}
+	}
+
+	return (-1);
+}
+
 int
 ami_pci_match(parent, match, aux)
 	struct device *parent;
@@ -124,25 +145,29 @@
 	void *aux;
 {
 	struct pci_attach_args *pa = aux;
-	const struct ami_pci_device *pami;
+	int i;
 	pcireg_t sig;
 
 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O)
 		return (0);
 
-	for (pami = ami_pci_devices; pami->vendor; pami++) {
-		if (pami->vendor == PCI_VENDOR(pa->pa_id) &&
-		    pami->product == PCI_PRODUCT(pa->pa_id)) {
-			if (!(pami->flags & AMI_CHECK_SIGN))
-				return (1);
-			/* some cards have 0x11223344, but some only 16bit */
-			sig = pci_conf_read(pa->pa_pc, pa->pa_tag,
-			    AMI_PCI_SIG) & 0xffff;
-			if (sig == AMI_SIGNATURE_1 ||
-			    sig == AMI_SIGNATURE_2)
-				return (1);
-		}
+	if ((i = ami_pci_find_device(aux)) != -1) {
+#ifdef AMI_DEBUG
+		printf("\nvendor: %04x  product: %04x\n",
+			ami_pci_devices[i].vendor,
+			ami_pci_devices[i].product);
+#endif /* AMI_DEBUG */
+
+		if (!(ami_pci_devices[i].flags & AMI_CHECK_SIGN))
+			return (1);
+		/* some cards have 0x11223344, but some only 16bit */
+		sig = pci_conf_read(pa->pa_pc, pa->pa_tag,
+		    AMI_PCI_SIG) & 0xffff;
+		if (sig == AMI_SIGNATURE_1 ||
+		    sig == AMI_SIGNATURE_2)
+			return (1);
 	}
+
 	return (0);
 }
 
@@ -158,6 +183,7 @@
 	const struct ami_pci_subsys *ssp;
 	bus_size_t size;
 	pcireg_t csr;
+	int i;
 #if 0
 	/* reset */
 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_EBCR,
@@ -245,6 +271,17 @@
 	case AMI_SGL_LHC:	lhc = "64b/lhc";	break;
 	case AMI_SGL_HLC:	lhc = "64b/hlc";	break;
 	default:		lhc = "32b";
+	}
+
+	if ((i = ami_pci_find_device(aux)) != -1) {
+		if (ami_pci_devices[i].flags & AMI_BROKEN)
+			sc->sc_quirks = AMI_BROKEN;
+		else
+			sc->sc_quirks = 0x0000;
+	}
+	else {
+		/* this device existed at _match() should never happen */
+		panic("ami device dissapeared between match() and attach()\n");
 	}
 
 	printf(" %s/%s\n%s", model, lhc, sc->sc_dev.dv_xname);

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic