diff options
author | scottl <scottl@FreeBSD.org> | 2002-12-01 07:59:01 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2002-12-01 07:59:01 +0000 |
commit | 45781e3228deefd9c61819301caa86bc57d9ab63 (patch) | |
tree | 99e2a0860f26f519dc0889307aa4f65d8d8b36ba /sys/dev/aic7xxx | |
parent | 30b77bf7809e2bb17b71103bb73a484c9fc0e93f (diff) | |
download | FreeBSD-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.c | 217 |
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); } - |