summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2002-12-01 07:59:01 +0000
committerscottl <scottl@FreeBSD.org>2002-12-01 07:59:01 +0000
commit45781e3228deefd9c61819301caa86bc57d9ab63 (patch)
tree99e2a0860f26f519dc0889307aa4f65d8d8b36ba /sys/dev/aic7xxx
parent30b77bf7809e2bb17b71103bb73a484c9fc0e93f (diff)
downloadFreeBSD-src-45781e3228deefd9c61819301caa86bc57d9ab63.zip
FreeBSD-src-45781e3228deefd9c61819301caa86bc57d9ab63.tar.gz
Implement workaround for broken busfree-rev in the A4.
HP -> CPQ Rearrange IDs to better match which chips they use. Convert to uniform product description strings. Simplify 7901A setup function. Add the NONPACKFIFO_BUG and PACED_NEGTABLE_BUG entries for the A. Add rev B bugs and features. The double write workaround for CURRSCB is only required if abort pending is set. Remove this work around and set the abort pending bug bit on the B at least until we have better confirmation that the double write is always safe. Add updated H2B identifiers Move IOCell paramters into softc and add a hook for the OSM to modify these as well as other settings prior to committing them to the chip. SLEW -> SLEWRATE PREQDIS in DEVCONFIG1 went away after the A2. Remove all code that references this bit. This is especially important since this bit was reused in the B for a different HW fix workaround. Properly set the AHD_NEW_IOCELL_OPTS and AHD_NEW_DFCNTRL_OPTS features for the B. Remove stray/random extra 7901A generic PCI table entry. Also switch the correct 7901A generic entry to use ID_ALL_MASK since we can only differentiate the 7901A from the 7902 by checking for a "type field" of 0xE. Set AHD_INTCOLLISIONT_BUG for the Rev B. Set the PREQDIS bit in DEVCONFIG1 for the B. The bit is misnamed, but seems to disable a work-around that breaks on the B on PCI busses. Add a routine for testing memory mapped register access. This will hopefully detect things like buggy via chipsets so that the OSM can fallback to using I/O mapped access when memory mapped I/O simply will not work. Approved by: re (blanket)
Diffstat (limited to 'sys/dev/aic7xxx')
-rw-r--r--sys/dev/aic7xxx/aic79xx_pci.c217
1 files changed, 148 insertions, 69 deletions
diff --git a/sys/dev/aic7xxx/aic79xx_pci.c b/sys/dev/aic7xxx/aic79xx_pci.c
index c165ce2..fdbfc45 100644
--- a/sys/dev/aic7xxx/aic79xx_pci.c
+++ b/sys/dev/aic7xxx/aic79xx_pci.c
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#44 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#54 $
*
* $FreeBSD$
*/
@@ -69,21 +69,26 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
#define ID_AIC7901 0x800F9005FFFF9005ull
-#define ID_AIC7901_IROC 0x80089005FFFF9005ull
#define ID_AIC7901A 0x801E9005FFFF9005ull
+#define ID_AIC7901A_IROC 0x809E9005FFFF9005ull
#define ID_AHA_29320A 0x8000900500609005ull
+#define ID_AHA_29320LP 0x8014900500449005ull
+#define ID_AHA_29320LP_IROC 0x8094900500449005ull
#define ID_AIC7902 0x801F9005FFFF9005ull
-#define ID_AIC7902_IROC 0x80189005FFFF9005ull
+#define ID_AIC7902_IROC 0x809F9005FFFF9005ull
+#define ID_AIC7902_B 0x801D9005FFFF9005ull
+#define ID_AIC7902_B_IROC 0x809D9005FFFF9005ull
#define ID_AHA_39320 0x8010900500409005ull
#define ID_AHA_39320D 0x8011900500419005ull
-#define ID_AHA_39320D_CPQ 0x8011900500AC0E11ull
+#define ID_AHA_39320D_B 0x801C900500419005ull
+#define ID_AHA_39320D_HP 0x8011900500AC0E11ull
+#define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull
#define ID_AHA_29320 0x8012900500429005ull
#define ID_AHA_29320B 0x8013900500439005ull
-#define ID_AHA_29320LP 0x8014900500449005ull
#define ID_AIC7902_PCI_REV_A4 0x3
#define ID_AIC7902_PCI_REV_B0 0x10
-#define SUBID_CPQ 0x0E11
+#define SUBID_HP 0x0E11
#define DEVID_9005_TYPE(id) ((id) & 0xF)
#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
@@ -107,18 +112,23 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define SUBID_9005_SEEPTYPE_NONE 0x0
#define SUBID_9005_SEEPTYPE_4K 0x1
-static ahd_device_setup_t ahd_aic7901_setup;
-static ahd_device_setup_t ahd_aic7902_setup;
static ahd_device_setup_t ahd_aic7901A_setup;
+static ahd_device_setup_t ahd_aic7902_setup;
struct ahd_pci_identity ahd_pci_ident_table [] =
{
- /* aic7901 based controllers */
+ /* aic7901A based controllers */
+ {
+ ID_AHA_29320LP,
+ ID_ALL_MASK,
+ "Adaptec 29320LP Ultra320 SCSI adapter",
+ ahd_aic7901A_setup
+ },
{
ID_AHA_29320A,
ID_ALL_MASK,
"Adaptec 29320A Ultra320 SCSI adapter",
- ahd_aic7901_setup
+ ahd_aic7901A_setup
},
/* aic7902 based controllers */
{
@@ -134,46 +144,46 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
ahd_aic7902_setup
},
{
- ID_AHA_39320D_CPQ,
+ ID_AHA_39320D_HP,
ID_ALL_MASK,
- "Adaptec (Compaq OEM) 39320D Ultra320 SCSI adapter",
+ "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
ahd_aic7902_setup
},
{
- ID_AHA_29320,
+ ID_AHA_39320D_B,
ID_ALL_MASK,
- "Adaptec 29320 Ultra320 SCSI adapter",
+ "Adaptec 39320D Ultra320 SCSI adapter",
ahd_aic7902_setup
},
{
- ID_AHA_29320B,
+ ID_AHA_39320D_B_HP,
ID_ALL_MASK,
- "Adaptec 29320B Ultra320 SCSI adapter",
+ "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
ahd_aic7902_setup
},
{
- ID_AHA_29320LP,
+ ID_AHA_29320,
ID_ALL_MASK,
- "Adaptec 29320LP Ultra320 SCSI adapter",
+ "Adaptec 29320 Ultra320 SCSI adapter",
ahd_aic7902_setup
},
{
- ID_AIC7901A & ID_9005_GENERIC_MASK,
- ID_9005_GENERIC_MASK,
- "Adaptec 7901A Ultra320 SCSI adapter",
- ahd_aic7901A_setup
+ ID_AHA_29320B,
+ ID_ALL_MASK,
+ "Adaptec 29320B Ultra320 SCSI adapter",
+ ahd_aic7902_setup
},
/* Generic chip probes for devices we don't know 'exactly' */
{
- ID_AIC7901 & ID_9005_GENERIC_MASK,
- ID_9005_GENERIC_MASK,
- "Adaptec aic7901 Ultra320 SCSI adapter",
- ahd_aic7901_setup
+ ID_AIC7901A & ID_ALL_MASK,
+ ID_ALL_MASK,
+ "Adaptec AIC7901A Ultra320 SCSI adapter",
+ ahd_aic7901A_setup
},
{
ID_AIC7902 & ID_9005_GENERIC_MASK,
ID_9005_GENERIC_MASK,
- "Adaptec aic7902 Ultra320 SCSI adapter",
+ "Adaptec AIC7902 Ultra320 SCSI adapter",
ahd_aic7902_setup
}
};
@@ -266,11 +276,19 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
int error;
shared_scb_data = NULL;
+ ahd->description = entry->name;
+ /*
+ * Record if this is an HP board.
+ */
+ subvendor = ahd_pci_read_config(ahd->dev_softc,
+ PCIR_SUBVEND_0, /*bytes*/2);
+ if (subvendor == SUBID_HP)
+ ahd->flags |= AHD_HP_BOARD;
+
error = entry->setup(ahd);
if (error != 0)
return (error);
- ahd->description = entry->name;
devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {
ahd->chip |= AHD_PCI;
@@ -281,14 +299,6 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
}
ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
- /*
- * Record if this is a Compaq board.
- */
- subvendor = ahd_pci_read_config(ahd->dev_softc,
- PCIR_SUBVEND_0, /*bytes*/2);
- if (subvendor == SUBID_CPQ)
- ahd->flags |= AHD_CPQ_BOARD;
-
ahd_power_state_change(ahd, AHD_POWER_STATE_D0);
error = ahd_pci_map_registers(ahd);
@@ -362,6 +372,64 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
}
/*
+ * Perform some simple tests that should catch situations where
+ * our registers are invalidly mapped.
+ */
+int
+ahd_pci_test_register_access(struct ahd_softc *ahd)
+{
+ int i;
+
+ /*
+ * First a simple test to see if any
+ * registers can be read. Reading
+ * HCNTRL has no side effects and has
+ * at least one bit that is guaranteed to
+ * be zero so it is a good register to
+ * use for this test.
+ */
+ if (ahd_inb(ahd, HCNTRL) == 0xFF)
+ return (EIO);
+
+ /*
+ * Next create a situation where write combining
+ * or read prefetching could be initiated by the
+ * CPU or host bridge. Our device does not support
+ * either, so look for data corruption and/or flaged
+ * PCI errors.
+ */
+ for (i = 0; i < 16; i++)
+ ahd_outb(ahd, SRAM_BASE + i, i);
+
+ for (i = 0; i < 16; i++)
+ if (ahd_inb(ahd, SRAM_BASE + i) != i)
+ return (EIO);
+
+ if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
+ ahd_mode_state saved_modes;
+ u_int targpcistat;
+ u_int pci_status1;
+
+ saved_modes = ahd_save_modes(ahd);
+ ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
+ targpcistat = ahd_inb(ahd, TARGPCISTAT);
+
+ /* Silently clear any latched errors. */
+ ahd_outb(ahd, TARGPCISTAT, targpcistat);
+ pci_status1 = ahd_pci_read_config(ahd->dev_softc,
+ PCIR_STATUS + 1, /*bytes*/1);
+ ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
+ pci_status1, /*bytes*/1);
+ ahd_restore_modes(ahd, saved_modes);
+
+ if ((targpcistat & STA) != 0)
+ return (EIO);
+ }
+
+ return (0);
+}
+
+/*
* Check the external port logic for a serial eeprom
* and termination/cable detection contrls.
*/
@@ -746,14 +814,14 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
}
static int
-ahd_aic7901_setup(struct ahd_softc *ahd)
+ahd_aic7901A_setup(struct ahd_softc *ahd)
{
- ahd_dev_softc_t pci;
-
- pci = ahd->dev_softc;
- ahd->channel = 'A';
- ahd->chip = AHD_AIC7901;
- ahd->features = AHD_AIC7901_FE;
+ int error;
+
+ error = ahd_aic7902_setup(ahd);
+ if (error != 0)
+ return (error);
+ ahd->chip = AHD_AIC7901A;
return (0);
}
@@ -762,7 +830,6 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
{
ahd_dev_softc_t pci;
u_int rev;
- u_int devconfig1;
pci = ahd->dev_softc;
rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
@@ -772,17 +839,11 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/1);
return (ENXIO);
}
+ ahd->channel = ahd_get_pci_function(pci) + 'A';
+ ahd->chip = AHD_AIC7902;
+ ahd->features = AHD_AIC7902_FE;
if (rev < ID_AIC7902_PCI_REV_B0) {
/*
- * Pending request assertion does not work on the A if we have
- * DMA requests outstanding on both channels. See H2A3 Razors
- * #327 and #365.
- */
- devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
- ahd_pci_write_config(pci, DEVCONFIG1,
- devconfig1|PREQDIS, /*bytes*/1);
- devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
- /*
* Enable A series workarounds.
*/
ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG
@@ -793,24 +854,42 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
| AHD_PCIX_CHIPRST_BUG|AHD_PKTIZED_STATUS_BUG
| AHD_PKT_LUN_BUG|AHD_MDFF_WSCBPTR_BUG
| AHD_REG_SLOW_SETTLE_BUG|AHD_SET_MODE_BUG
- | AHD_BUSFREEREV_BUG;
- }
+ | AHD_BUSFREEREV_BUG|AHD_NONPACKFIFO_BUG
+ | AHD_PACED_NEGTABLE_BUG;
- ahd->channel = ahd_get_pci_function(pci) + 'A';
- ahd->chip = AHD_AIC7902;
- ahd->features = AHD_AIC7902_FE;
- return (0);
-}
+ /*
+ * IO Cell paramter setup.
+ */
+ AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
-static int
-ahd_aic7901A_setup(struct ahd_softc *ahd)
-{
- int error;
+ if ((ahd->flags & AHD_HP_BOARD) == 0)
+ AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
+ } else {
+ u_int devconfig1;
+
+ ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
+ | AHD_NEW_DFCNTRL_OPTS;
+ ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_ABORT_LQI_BUG
+ | AHD_INTCOLLISION_BUG;
+
+ /*
+ * IO Cell paramter setup.
+ */
+ AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
+ AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
+ AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);
+
+ /*
+ * Set the PREQDIS bit for H2B which disables some workaround
+ * that doesn't work on regular PCI busses.
+ * XXX - Find out exactly what this does from the hardware
+ * folks!
+ */
+ devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
+ ahd_pci_write_config(pci, DEVCONFIG1,
+ devconfig1|PREQDIS, /*bytes*/1);
+ devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
+ }
- error = ahd_aic7902_setup(ahd);
- if (error != 0)
- return (error);
- ahd->chip = AHD_AIC7901A;
return (0);
}
-
OpenPOWER on IntegriCloud