summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aic7xxx_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx_pci.c')
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c67
1 files changed, 43 insertions, 24 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index 959908d..ed1e641 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -39,7 +39,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#53 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#57 $
*
* $FreeBSD$
*/
@@ -641,6 +641,7 @@ const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
#define AHC_494X_SLOT_CHANNEL_D 7
#define DEVCONFIG 0x40
+#define PCIERRGENDIS 0x80000000ul
#define SCBSIZE32 0x00010000ul /* aic789X only */
#define REXTVALID 0x00001000ul /* ultra cards only */
#define MPORTMODE 0x00000400ul /* aic7870+ only */
@@ -785,6 +786,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
u_int sxfrctl1;
u_int scsiseq;
u_int dscommand0;
+ uint32_t devconfig;
int error;
uint8_t sblkctl;
@@ -809,6 +811,8 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
*/
ahc_intr_enable(ahc, FALSE);
+ devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
+
/*
* If we need to support high memory, enable dual
* address cycles. This bit must be set to enable
@@ -816,21 +820,30 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
* 64bit bus (PCI64BIT set in devconfig).
*/
if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- uint32_t devconfig;
if (bootverbose)
printf("%s: Enabling 39Bit Addressing\n",
ahc_name(ahc));
- devconfig = ahc_pci_read_config(ahc->dev_softc,
- DEVCONFIG, /*bytes*/4);
devconfig |= DACEN;
- ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
- devconfig, /*bytes*/4);
}
+ /* Ensure that pci error generation, a test feature, is disabled. */
+ devconfig |= PCIERRGENDIS;
+
+ ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
+
/* Ensure busmastering is enabled */
command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
command |= PCIM_CMD_BUSMASTEREN;
+
+ /*
+ * Disable PCI parity error reporting. Users typically
+ * do this to work around broken PCI chipsets that get
+ * the parity timing wrong and thus generate lots of spurious
+ * errors.
+ */
+ if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
+ command &= ~PCIM_CMD_PERRESPEN;
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1);
/* On all PCI adapters, we allow SCB paging */
@@ -947,7 +960,8 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
* a SEEPROM.
*/
/* See if someone else set us up already */
- if (scsiseq != 0) {
+ if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
+ && scsiseq != 0) {
printf("%s: Using left over BIOS settings\n",
ahc_name(ahc));
ahc->flags &= ~AHC_USEDEFAULTS;
@@ -1202,15 +1216,20 @@ done:
int
ahc_pci_test_register_access(struct ahc_softc *ahc)
{
- int error;
- u_int status1;
- uint8_t seqctl;
+ int error;
+ u_int status1;
+ uint32_t cmd;
+ uint8_t hcntrl;
error = EIO;
- /* Enable PCI error interrupt status */
- seqctl = ahc_inb(ahc, SEQCTL);
- ahc_outb(ahc, SEQCTL, seqctl & ~FAILDIS);
+ /*
+ * Enable PCI error interrupt status, but suppress NMIs
+ * generated by SERR raised due to target aborts.
+ */
+ cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+ cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
/*
* First a simple test to see if any
@@ -1220,7 +1239,8 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* be zero so it is a good register to
* use for this test.
*/
- if (ahc_inb(ahc, HCNTRL) == 0xFF)
+ hcntrl = ahc_inb(ahc, HCNTRL);
+ if (hcntrl == 0xFF)
goto fail;
/*
@@ -1230,15 +1250,13 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* either, so look for data corruption and/or flagged
* PCI errors.
*/
- ahc_outb(ahc, SRAM_BASE, 0xaa);
- ahc_outb(ahc, SRAM_BASE + 1, 0x55);
- ahc_outb(ahc, SRAM_BASE + 2, 0xa5);
- ahc_outb(ahc, SRAM_BASE + 3, 0x5a);
-
- if ((ahc_inb(ahc, SRAM_BASE) != 0xaa)
- || (ahc_inb(ahc, SRAM_BASE + 1) != 0x55)
- || (ahc_inb(ahc, SRAM_BASE + 2) != 0xa5)
- || (ahc_inb(ahc, SRAM_BASE + 3) != 0x5a))
+ ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
+ while (ahc_is_paused(ahc) == 0)
+ ;
+ ahc_outb(ahc, SEQCTL, PERRORDIS);
+ ahc_outb(ahc, SCBPTR, 0);
+ ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
+ if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
goto fail;
status1 = ahc_pci_read_config(ahc->dev_softc,
@@ -1255,7 +1273,8 @@ fail:
ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
status1, /*bytes*/1);
ahc_outb(ahc, CLRINT, CLRPARERR);
- ahc_outb(ahc, SEQCTL, seqctl);
+ ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
return (error);
}
OpenPOWER on IntegriCloud