From fe94b852b3fba66785cefea758a500a1db449aed Mon Sep 17 00:00:00 2001 From: Scott Long Date: Wed, 6 Feb 2002 01:34:09 +0000 Subject: [PATCH] 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 --- sys/dev/aac/aac.c | 40 ++++++++++++++++++++++++++++++++++++++++ sys/dev/aac/aac_pci.c | 8 ++++++++ sys/dev/aac/aacreg.h | 1 + sys/dev/aac/aacvar.h | 2 ++ 4 files changed, 51 insertions(+) diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 9d47b641ca9..1bb4ac7dab8 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, @@ -258,6 +259,12 @@ aac_attach(struct aac_softc *sc) /* mark controller as suspended until we get ourselves organised */ 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. */ @@ -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 c5d9dc63184..35625c381ea 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 766c2d46339..8d526683afe 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 012c7d2e59e..a4af5daa1c0 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) };