aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Long <scottl@FreeBSD.org>2002-02-06 01:34:09 +0000
committerScott Long <scottl@FreeBSD.org>2002-02-06 01:34:09 +0000
commitfe94b852b3fba66785cefea758a500a1db449aed (patch)
tree2c29666f75c1b8f758defbca6609bded1c3a739e
parent0b94a0e9f9b82dba7f26ad4ba2e272208d13f129 (diff)
downloadsrc-fe94b852b3fba66785cefea758a500a1db449aed.tar.gz
src-fe94b852b3fba66785cefea758a500a1db449aed.zip
Don't attach to Dell PERC2/QC cards that have a firmware rev of 1.x. This
check is complicated by the fact that the Adaptec 5400S cards claim to use 1.x firmware also. PERC2/QC 1.x firmware is not compatible with this driver and will cause a system hang. MFC after: 3 days
Notes
Notes: svn path=/head/; revision=90275
-rw-r--r--sys/dev/aac/aac.c40
-rw-r--r--sys/dev/aac/aac_pci.c8
-rw-r--r--sys/dev/aac/aacreg.h1
-rw-r--r--sys/dev/aac/aacvar.h2
4 files changed, 51 insertions, 0 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index 9d47b641ca9a..1bb4ac7dab8f 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -100,6 +100,7 @@ static void aac_unmap_command(struct aac_command *cm);
/* Hardware Interface */
static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg,
int error);
+static int aac_check_firmware(struct aac_softc *sc);
static int aac_init(struct aac_softc *sc);
static int aac_sync_command(struct aac_softc *sc, u_int32_t command,
u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
@@ -259,6 +260,12 @@ aac_attach(struct aac_softc *sc)
sc->aac_state |= AAC_STATE_SUSPEND;
/*
+ * Check that the firmware on the card is supported.
+ */
+ if ((error = aac_check_firmware(sc)) != 0)
+ return(error);
+
+ /*
* Allocate command structures.
*/
if ((error = aac_alloc_commands(sc)) != 0)
@@ -1345,6 +1352,39 @@ aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
sc->aac_common_busaddr = segs[0].ds_addr;
}
+/*
+ * Retrieve the firmware version numbers. Dell PERC2/QC cards with
+ * firmware version 1.x are not compatible with this driver.
+ */
+static int
+aac_check_firmware(struct aac_softc *sc)
+{
+ u_int32_t major, minor;
+
+ debug_called(1);
+
+ if (sc->quirks & AAC_QUIRK_PERC2QC) {
+ if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
+ NULL)) {
+ device_printf(sc->aac_dev,
+ "Error reading firmware version\n");
+ return (EIO);
+ }
+
+ /* These numbers are stored as ASCII! */
+ major = (AAC_GETREG4(sc, AAC_SA_MAILBOX + 4) & 0xff) - 0x30;
+ minor = (AAC_GETREG4(sc, AAC_SA_MAILBOX + 8) & 0xff) - 0x30;
+ if (major == 1) {
+ device_printf(sc->aac_dev,
+ "Firmware version %d.%d is not supported.\n",
+ major, minor);
+ return (EINVAL);
+ }
+ }
+
+ return (0);
+}
+
static int
aac_init(struct aac_softc *sc)
{
diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
index c5d9dc63184c..35625c381ea7 100644
--- a/sys/dev/aac/aac_pci.c
+++ b/sys/dev/aac/aac_pci.c
@@ -295,6 +295,14 @@ aac_pci_attach(device_t dev)
goto out;
}
+
+ /*
+ * Check for quirky hardware
+ */
+ if (pci_get_subdevice(dev) == 0x1364 &&
+ pci_get_subvendor(dev) == 0x9005)
+ sc->quirks |= AAC_QUIRK_PERC2QC;
+
/*
* Do bus-independent initialisation.
*/
diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h
index 766c2d463391..8d526683afe9 100644
--- a/sys/dev/aac/aacreg.h
+++ b/sys/dev/aac/aacreg.h
@@ -523,6 +523,7 @@ struct aac_adapter_info {
*/
#define AAC_MONKER_INITSTRUCT 0x05
#define AAC_MONKER_SYNCFIB 0x0c
+#define AAC_MONKER_GETKERNVER 0x11
/*
* Adapter Status Register
diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h
index 012c7d2e59ea..a4af5daa1c0a 100644
--- a/sys/dev/aac/aacvar.h
+++ b/sys/dev/aac/aacvar.h
@@ -356,6 +356,8 @@ struct aac_softc
#define AAC_AIFFLAGS_PENDING (1 << 1)
#define AAC_AIFFLAGS_EXIT (1 << 2)
#define AAC_AIFFLAGS_EXITED (1 << 3)
+ u_int32_t quirks;
+#define AAC_QUIRK_PERC2QC (1 << 0)
};