diff options
author | scottl <scottl@FreeBSD.org> | 2002-02-06 01:34:09 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2002-02-06 01:34:09 +0000 |
commit | 2ccafe67719df1396683dbe7ad031f38c13eac67 (patch) | |
tree | 2c29666f75c1b8f758defbca6609bded1c3a739e /sys | |
parent | 9371a9a23b6795e0a824d3f629c1e32aaa07513d (diff) | |
download | FreeBSD-src-2ccafe67719df1396683dbe7ad031f38c13eac67.zip FreeBSD-src-2ccafe67719df1396683dbe7ad031f38c13eac67.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/aac/aac.c | 40 | ||||
-rw-r--r-- | sys/dev/aac/aac_pci.c | 8 | ||||
-rw-r--r-- | sys/dev/aac/aacreg.h | 1 | ||||
-rw-r--r-- | sys/dev/aac/aacvar.h | 2 |
4 files changed, 51 insertions, 0 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 9d47b64..1bb4ac7 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 c5d9dc6..35625c3 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 766c2d4..8d52668 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 012c7d2..a4af5da 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) }; |