[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