From 2cd3cc377a0239a0f517938eef41dc47ca1c0974 Mon Sep 17 00:00:00 2001 From: "Justin T. Gibbs" Date: Thu, 6 Mar 2003 23:58:34 +0000 Subject: [PATCH] aic79xx.c: Include read streaming in the PPR flags we display in diagnostics. In ahd_reset(), set the known mode after our initial pause prior to setting the mode. We can't just set the mode directly because the current mode, after the pause, is most likely unknown and setting the mode when the saved mode is unknown will trigger an assertion in the mode debug code. Complete an audit for SCB RAM reads. These reads must be performed via the special ahd_in?_scbram() methods so we can perform a Rev A. PCI-X workaround. Remove a superfluous mode save operation that was performed just prior to a call to ahd_clear_critical_section(). The saved mode was never restored and wouldn't have been valid anyway since the mode could change while single stepping out of a critical section. aic79xx.h: Add new BUG definition AHD_PCIX_SCBRAM_RD_BUG. aic79xx_inline.h: Update ahd_inb_scbram routine to check for AHD_PCIX_SCBRAM_RD_BUG and only apply the workaround if this bug is active. The old code applied the workaround in all cases. aic79xx_pci.c: Set AHD_PCIX_SCBRAM_RD_BUG for the A4. Remove an attempted saved_modes call in ahd_pci_test_register_access(). Saving the modes can only occur when we are paused, but the call was happening before the chip was known to be paused. Restoring the modes doesn't make sense either since the code makes no assumptions about the state of the sequencer until the first time the mode is set by the driver. This happens after the registers are successfully mapped. --- sys/dev/aic7xxx/aic79xx.c | 29 ++++++++++++++++---------- sys/dev/aic7xxx/aic79xx.h | 35 +++++++++++++++++--------------- sys/dev/aic7xxx/aic79xx_inline.h | 5 +++-- sys/dev/aic7xxx/aic79xx_pci.c | 15 ++++++-------- 4 files changed, 46 insertions(+), 38 deletions(-) diff --git a/sys/dev/aic7xxx/aic79xx.c b/sys/dev/aic7xxx/aic79xx.c index ae0f62e5dd28..f1ef6a8d69b6 100644 --- a/sys/dev/aic7xxx/aic79xx.c +++ b/sys/dev/aic7xxx/aic79xx.c @@ -37,7 +37,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.c#165 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#170 $ * * $FreeBSD$ */ @@ -406,7 +406,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) u_int i; ahd_set_scbptr(ahd, scbid); - next_scbid = ahd_inw(ahd, SCB_NEXT_COMPLETE); + next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { printf("%s: Warning - DMA-up and complete " @@ -415,7 +415,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) } hscb_ptr = (uint8_t *)scb->hscb; for (i = 0; i < sizeof(struct hardware_scb); i++) - *hscb_ptr++ = ahd_inb(ahd, SCB_BASE + i); + *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i); ahd_complete_scb(ahd, scb); scbid = next_scbid; @@ -426,7 +426,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) while (!SCBID_IS_NULL(scbid)) { ahd_set_scbptr(ahd, scbid); - next_scbid = ahd_inw(ahd, SCB_NEXT_COMPLETE); + next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { printf("%s: Warning - Complete SCB %d invalid\n", @@ -1667,7 +1667,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) next = SCB_LIST_NULL; } else { ahd_set_scbptr(ahd, waiting_h); - next = ahd_inw(ahd, SCB_NEXT2); + next = ahd_inw_scbram(ahd, SCB_NEXT2); } ahd_set_scbptr(ahd, scbid); ahd_outw(ahd, SCB_NEXT2, next); @@ -1998,7 +1998,8 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) if ((seq_flags & NO_CDB_SENT) != 0) { ahd_print_path(ahd, scb); printf("No or incomplete CDB sent to device.\n"); - } else if ((ahd_inb(ahd, SCB_CONTROL) & STATUS_RCVD) == 0) { + } else if ((ahd_inb_scbram(ahd, SCB_CONTROL) + & STATUS_RCVD) == 0) { /* * The target never bothered to provide status to * us prior to completing the command. Since we don't @@ -2615,8 +2616,12 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_name(ahd), devinfo->target, period, offset); options = 0; + if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) { + printf("(RDSTRM"); + options++; + } if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { - printf("(DT"); + printf("%s", options ? "|DT" : "(DT"); options++; } if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { @@ -4990,6 +4995,7 @@ ahd_reset(struct ahd_softc *ahd) * to disturb the integrity of the bus. */ ahd_pause(ahd); + ahd_update_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); sxfrctl1 = ahd_inb(ahd, SXFRCTL1); @@ -5042,10 +5048,13 @@ ahd_reset(struct ahd_softc *ahd) /* * Mode should be SCSI after a chip reset, but lets - * set it just to be safe. + * set it just to be safe. We touch the MODE_PTR + * register directly so as to bypass the lazy update + * code in ahd_set_modes(). */ - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + ahd_outb(ahd, MODE_PTR, + ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI)); /* * Restore SXFRCTL1. @@ -7689,7 +7698,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { struct hardware_scb *hscb; u_int qfreeze_cnt; - ahd_mode_state saved_modes; /* * The sequencer freezes its select-out queue @@ -7701,7 +7709,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) /* Freeze the queue until the client sees the error. */ ahd_pause(ahd); - saved_modes = ahd_save_modes(ahd); ahd_clear_critical_section(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_freeze_devq(ahd, scb); diff --git a/sys/dev/aic7xxx/aic79xx.h b/sys/dev/aic7xxx/aic79xx.h index f1607f8f18cd..87452c7fc898 100644 --- a/sys/dev/aic7xxx/aic79xx.h +++ b/sys/dev/aic7xxx/aic79xx.h @@ -37,7 +37,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.h#84 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#85 $ * * $FreeBSD$ */ @@ -258,27 +258,30 @@ typedef enum { AHD_PCIX_CHIPRST_BUG = 0x0040, /* MMAPIO is not functional in PCI-X mode. */ AHD_PCIX_MMAPIO_BUG = 0x0080, + /* Reads to SCBRAM fail to reset the discard timer. */ + AHD_PCIX_SCBRAM_RD_BUG = 0x0100, /* Bug workarounds that can be disabled on non-PCIX busses. */ AHD_PCIX_BUG_MASK = AHD_PCIX_CHIPRST_BUG - | AHD_PCIX_MMAPIO_BUG, + | AHD_PCIX_MMAPIO_BUG + | AHD_PCIX_SCBRAM_RD_BUG, /* * LQOSTOP0 status set even for forced selections with ATN * to perform non-packetized message delivery. */ - AHD_LQO_ATNO_BUG = 0x0100, + AHD_LQO_ATNO_BUG = 0x0200, /* FIFO auto-flush does not always trigger. */ - AHD_AUTOFLUSH_BUG = 0x0200, + AHD_AUTOFLUSH_BUG = 0x0400, /* The CLRLQO registers are not self-clearing. */ - AHD_CLRLQO_AUTOCLR_BUG = 0x0400, + AHD_CLRLQO_AUTOCLR_BUG = 0x0800, /* The PACKETIZED status bit refers to the previous connection. */ - AHD_PKTIZED_STATUS_BUG = 0x0800, + AHD_PKTIZED_STATUS_BUG = 0x1000, /* "Short Luns" are not placed into outgoing LQ packets correctly. */ - AHD_PKT_LUN_BUG = 0x1000, + AHD_PKT_LUN_BUG = 0x2000, /* * Only the FIFO allocated to the non-packetized connection may * be in use during a non-packetzied connection. */ - AHD_NONPACKFIFO_BUG = 0x2000, + AHD_NONPACKFIFO_BUG = 0x4000, /* * Writing to a DFF SCBPTR register may fail if concurent with * a hardware write to the other DFF SCBPTR register. This is @@ -286,30 +289,30 @@ typedef enum { * this bug have the AHD_NONPACKFIFO_BUG and all writes of concern * occur in non-packetized connections. */ - AHD_MDFF_WSCBPTR_BUG = 0x4000, + AHD_MDFF_WSCBPTR_BUG = 0x8000, /* SGHADDR updates are slow. */ - AHD_REG_SLOW_SETTLE_BUG = 0x8000, + AHD_REG_SLOW_SETTLE_BUG = 0x10000, /* * Changing the MODE_PTR coincident with an interrupt that * switches to a different mode will cause the interrupt to * be in the mode written outside of interrupt context. */ - AHD_SET_MODE_BUG = 0x10000, + AHD_SET_MODE_BUG = 0x20000, /* Non-packetized busfree revision does not work. */ - AHD_BUSFREEREV_BUG = 0x20000, + AHD_BUSFREEREV_BUG = 0x40000, /* * Paced transfers are indicated with a non-standard PPR * option bit in the neg table, 160MHz is indicated by * sync factor 0x7, and the offset if off by a factor of 2. */ - AHD_PACED_NEGTABLE_BUG = 0x40000, + AHD_PACED_NEGTABLE_BUG = 0x80000, /* LQOOVERRUN false positives. */ - AHD_LQOOVERRUN_BUG = 0x80000, + AHD_LQOOVERRUN_BUG = 0x100000, /* * Controller write to INTSTAT will lose to a host * write to CLRINT. */ - AHD_INTCOLLISION_BUG = 0x100000, + AHD_INTCOLLISION_BUG = 0x200000, /* * The GEM318 violates the SCSI spec by not waiting * the mandated bus settle delay between phase changes @@ -319,7 +322,7 @@ typedef enum { * glitches. This flag tells the firmware to tolerate * early REQ assertions. */ - AHD_EARLY_REQ_BUG = 0x200000 + AHD_EARLY_REQ_BUG = 0x400000 } ahd_bug; /* diff --git a/sys/dev/aic7xxx/aic79xx_inline.h b/sys/dev/aic7xxx/aic79xx_inline.h index d5963ce92f36..78462adc6457 100644 --- a/sys/dev/aic7xxx/aic79xx_inline.h +++ b/sys/dev/aic7xxx/aic79xx_inline.h @@ -37,7 +37,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_inline.h#43 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#44 $ * * $FreeBSD$ */ @@ -678,7 +678,8 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) * Razor #528 */ value = ahd_inb(ahd, offset); - ahd_inb(ahd, MODE_PTR); + if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0) + ahd_inb(ahd, MODE_PTR); return (value); } diff --git a/sys/dev/aic7xxx/aic79xx_pci.c b/sys/dev/aic7xxx/aic79xx_pci.c index 4869afbece0c..588681ecf749 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#66 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#67 $ * * $FreeBSD$ */ @@ -385,12 +385,10 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) int ahd_pci_test_register_access(struct ahd_softc *ahd) { - ahd_mode_state saved_modes; uint32_t cmd; int error; uint8_t hcntrl; - saved_modes = ahd_save_modes(ahd); error = EIO; /* @@ -456,7 +454,6 @@ ahd_pci_test_register_access(struct ahd_softc *ahd) ahd_outb(ahd, CLRINT, CLRPCIINT); } - ahd_restore_modes(ahd, saved_modes); ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); @@ -886,11 +883,11 @@ ahd_aic7902_setup(struct ahd_softc *ahd) | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG - | 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_NONPACKFIFO_BUG - | AHD_PACED_NEGTABLE_BUG; + | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_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_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG; /* * IO Cell paramter setup.