diff options
author | gibbs <gibbs@FreeBSD.org> | 2003-01-20 20:44:55 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 2003-01-20 20:44:55 +0000 |
commit | e7aa3377469bf8ef7a953f0fbced267c5cfa641d (patch) | |
tree | 0d74937224ea8fbc781ea9b09c338fe357c9586b /sys | |
parent | c85fe3ebb178be2d42bfd46a619e69acb19e2706 (diff) | |
download | FreeBSD-src-e7aa3377469bf8ef7a953f0fbced267c5cfa641d.zip FreeBSD-src-e7aa3377469bf8ef7a953f0fbced267c5cfa641d.tar.gz |
aic7xxx.reg:
Add a constant for the controller's stack size and the
maximum scsi offset.
aic7xxx.seq:
Style nit. The source is implied to be the destination
unless overridden in an "and" instruction.
Update target mode code for changes in identify seen
sequencer flags.
aic7xxx_pci.c:
Ensure that the PCIERRGENDIS bit is set in the
PCIERRGEN config space register. Perhaps this
is a reason for the spurios parity errors reported
on U160 controllers.
Honor the AHC_NO_BIOS_INIT flag.
Allow PCI interrupt reporting to be disabled,
by clearing the PERRRESEN bit in the command
register. This option is now enabled via a new
softc flag: AHC_DISABLE_PCI_PERR.
Disable SERR and pause the controller prior to performing
our mmapped I/O test. This should handle the case of
controllers that do not "auto-access pause". For legacy
controllers, use SCB ram instead of scratch ram since
the latter may contain settings left over from the BIOS
that we will use if an seeprom is not found.
Make use of new ahc_inl/outl() inlines.
aic7xxx.h:
Reformat a few comments to follow driver style.
Add a controller flags that indicate that a controller
has not been initialized by the BIOS and whether to
disable PCI parity errors..
Remove stack probing softc members.
Add a few more syncrate constants that are useful in speed
fallback calculations.
Add the SHOW_MASKED_ERRORS debug flag.
aic7xxx.h:
aic7xxx.c:
Implement the SCB_SILENT flag. This is useful for
hushing up the driver during DV or other operations
that we expect to cause transmission errors. The
messages will still print if the SHOW_MASKED_ERRORS
debug option is enabled.
aic7xxx_inline.h:
Implement ahc_[in|out][w|l|q]. This removes the need
for manual 'or and shift" type operations throughout
the driver.
aic7xxx.c:
Move SELTO dignostic so that the SCB is still valid
when we use it for printing path information.
If we are narrow, limit syncrate to Ultra2.
Don't clobber ppr_options when forcing a renegotiation.
The current ppr_options may be referenced while queuing
new commands. Don't set our width to unknown when forcing
negotiation on narrow controllers. This will confuse the
negotiation code into negotiating with a wide message on
narrow controllers.
Add an "asserting atn" diagnostic with controller/target
information.
Remove the probe_stack code. The stack is always
4 deep on legacy controllers, so probing is pointless.
This also avoids an issue where probing the stack would
upset the aic7770.
In ahc_reset(), record whether or not we found the
controller in a reset state. If the controller was
already reset, assume that no BIOS has initialized
the controller and ignore left over scratch ram
settings.
Fix an ifdef bug that caused sequencer debugging to
be enabled always.
Clear the ultraenb flag in our tstate during startup.
The ultraenbled'ness of a device is recorded in the user
transfer settings. tstate->ultraenb bitmask indicates
which devices we have negotiated an ultra speed with.
Just after initialization, we are async. Setting the
ultraenb flag while async seems to be harmless, but it
was confusing to see the ULTRAENB flag set in the SCB.
Enhance residual diagnostic to indicate if the residual
if for sense information or normal data transfers.
Indicate the features, bugs, and flags set in the softc
that are used to control firmware patch download when
booting verbose.
In ahc_dump_card_state() fix a logic reversal. The
SCSIPHASE register only exists on U160 controllers.
The SCSISIGI register exists on all controllers. Not
the other way around. Also print out the ERROR register.
Allow ahc_dump_card_state() to be called when the sequencer
is not paused. Add dump card state markers as in the U320
driver.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 191 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 46 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.reg | 5 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 9 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_inline.h | 71 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_pci.c | 67 |
6 files changed, 251 insertions, 138 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c index 1985ffb..3816f90 100644 --- a/sys/dev/aic7xxx/aic7xxx.c +++ b/sys/dev/aic7xxx/aic7xxx.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/aic7xxx.c#100 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#112 $ * * $FreeBSD$ */ @@ -230,7 +230,6 @@ static int ahc_check_patch(struct ahc_softc *ahc, u_int start_instr, u_int *skip_addr); static void ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts); -static int ahc_probe_stack_size(struct ahc_softc *ahc); #ifdef AHC_TARGET_MODE static void ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate, @@ -1040,6 +1039,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) u_int scsirate; u_int i; u_int sstat2; + int silent; lastphase = ahc_inb(ahc, LASTPHASE); curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; @@ -1067,39 +1067,49 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) break; } mesg_out = ahc_phase_table[i].mesg_out; + silent = FALSE; if (scb != NULL) { - ahc_print_path(ahc, scb); + if (SCB_IS_SILENT(scb)) + silent = TRUE; + else + ahc_print_path(ahc, scb); scb->flags |= SCB_TRANSMISSION_ERROR; } else printf("%s:%c:%d: ", ahc_name(ahc), intr_channel, SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID))); scsirate = ahc_inb(ahc, SCSIRATE); - printf("parity error detected %s. " - "SEQADDR(0x%x) SCSIRATE(0x%x)\n", - ahc_phase_table[i].phasemsg, - ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8), - scsirate); - - if ((ahc->features & AHC_DT) != 0) { - - if ((sstat2 & CRCVALERR) != 0) - printf("\tCRC Value Mismatch\n"); - if ((sstat2 & CRCENDERR) != 0) - printf("\tNo terminal CRC packet recevied\n"); - if ((sstat2 & CRCREQERR) != 0) - printf("\tIllegal CRC packet request\n"); - if ((sstat2 & DUAL_EDGE_ERR) != 0) { - printf("\tUnexpected %sDT Data Phase\n", - (scsirate & SINGLE_EDGE) ? "" : "non-"); - /* - * This error applies regardless of - * data direction, so ignore the value - * in the phase table. - */ - mesg_out = MSG_INITIATOR_DET_ERR; + if (silent == FALSE) { + printf("parity error detected %s. " + "SEQADDR(0x%x) SCSIRATE(0x%x)\n", + ahc_phase_table[i].phasemsg, + ahc_inw(ahc, SEQADDR0), + scsirate); + if ((ahc->features & AHC_DT) != 0) { + if ((sstat2 & CRCVALERR) != 0) + printf("\tCRC Value Mismatch\n"); + if ((sstat2 & CRCENDERR) != 0) + printf("\tNo terminal CRC packet " + "recevied\n"); + if ((sstat2 & CRCREQERR) != 0) + printf("\tIllegal CRC packet " + "request\n"); + if ((sstat2 & DUAL_EDGE_ERR) != 0) + printf("\tUnexpected %sDT Data Phase\n", + (scsirate & SINGLE_EDGE) + ? "" : "non-"); } } + if ((ahc->features & AHC_DT) != 0 + && (sstat2 & DUAL_EDGE_ERR) != 0) { + /* + * This error applies regardless of + * data direction, so ignore the value + * in the phase table. + */ + mesg_out = MSG_INITIATOR_DET_ERR; + } + /* * We've set the hardware to assert ATN if we * get a parity error on "in" phases, so all we @@ -1155,6 +1165,13 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) ahc_name(ahc), scbptr, scb_index); ahc_dump_card_state(ahc); } else { +#ifdef AHC_DEBUG + if ((ahc_debug & AHC_SHOW_SELTO) != 0) { + ahc_print_path(ahc, scb); + printf("Saw Selection Timeout for SCB 0x%x\n", + scb_index); + } +#endif /* * Force a renegotiation with this target just in * case the cable was pulled and will later be @@ -1167,13 +1184,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) ahc_force_renegotiation(ahc); ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahc_freeze_devq(ahc, scb); -#ifdef AHC_DEBUG - if ((ahc_debug & AHC_SHOW_SELTO) != 0) { - ahc_print_path(ahc, scb); - printf("Saw Selection Timeout for SCB 0x%x\n", - scb_index); - } -#endif } ahc_outb(ahc, CLRINT, CLRSCSIINT); ahc_restart(ahc); @@ -1642,6 +1652,10 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc, else transinfo = &tinfo->goal; *ppr_options &= transinfo->ppr_options; + if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) { + maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); + *ppr_options &= ~MSG_EXT_PPR_DT_REQ; + } if (transinfo->period == 0) { *period = 0; *ppr_options = 0; @@ -1830,10 +1844,10 @@ ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, * occurs the need to renegotiate is * recorded persistently. */ + if ((ahc->features & AHC_WIDE) != 0) + tinfo->curr.width = AHC_WIDTH_UNKNOWN; tinfo->curr.period = AHC_PERIOD_UNKNOWN; - tinfo->curr.width = AHC_WIDTH_UNKNOWN; tinfo->curr.offset = AHC_OFFSET_UNKNOWN; - tinfo->curr.ppr_options = AHC_OFFSET_UNKNOWN; } if (tinfo->curr.period != tinfo->goal.period || tinfo->curr.width != tinfo->goal.width @@ -2756,8 +2770,15 @@ reswitch: * assert ATN so the target takes us to the * message out phase. */ - if (ahc->msgout_len != 0) + if (ahc->msgout_len != 0) { +#ifdef AHC_DEBUG + if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { + ahc_print_devinfo(ahc, &devinfo); + printf("Asserting ATN for response\n"); + } +#endif ahc_assert_atn(ahc); + } } else ahc->msgin_index++; @@ -3423,7 +3444,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) * but rejected our response, we already cleared the * sync rate before sending our WDTR. */ - if (tinfo->goal.offset) { + if (tinfo->goal.offset != tinfo->curr.offset) { /* Start the sync negotiation */ ahc->msgout_index = 0; @@ -3984,8 +4005,6 @@ ahc_free(struct ahc_softc *ahc) free(ahc->name, M_DEVBUF); if (ahc->seep_config != NULL) free(ahc->seep_config, M_DEVBUF); - if (ahc->saved_stack != NULL) - free(ahc->saved_stack, M_DEVBUF); #ifndef __FreeBSD__ free(ahc, M_DEVBUF); #endif @@ -4027,6 +4046,14 @@ ahc_reset(struct ahc_softc *ahc) * to disturb the integrity of the bus. */ ahc_pause(ahc); + if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) { + /* + * The chip has not been initialized since + * PCI/EISA/VLB bus reset. Don't trust + * "left over BIOS data". + */ + ahc->flags |= AHC_NO_BIOS_INIT; + } sxfrctl1_b = 0; if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { u_int sblkctl; @@ -4521,14 +4548,9 @@ ahc_init(struct ahc_softc *ahc) size_t driver_data_size; uint32_t physaddr; - ahc->stack_size = ahc_probe_stack_size(ahc); - ahc->saved_stack = malloc(ahc->stack_size * sizeof(uint16_t), - M_DEVBUF, M_NOWAIT); - if (ahc->saved_stack == NULL) - return (ENOMEM); - -#ifdef AHC_DEBUG_SEQUENCER - ahc->flags |= AHC_SEQUENCER_DEBUG; +#ifdef AHC_DEBUG + if ((ahc_debug & AHC_DEBUG_SEQUENCER) != 0) + ahc->flags |= AHC_SEQUENCER_DEBUG; #endif #ifdef AHC_PRINT_SRAM @@ -4863,7 +4885,7 @@ ahc_init(struct ahc_softc *ahc) tinfo->curr.protocol_version = 2; tinfo->curr.transport_version = 2; } - tstate->ultraenb = ultraenb; + tstate->ultraenb = 0; } ahc->user_discenable = discenable; ahc->user_tagenable = tagenable; @@ -6255,7 +6277,8 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { ahc_print_path(ahc, scb); - printf("Handled Residual of %d bytes\n", resid); + printf("Handled %sResidual of %d bytes\n", + (scb->flags & SCB_SENSE) ? "Sense " : "", resid); } #endif } @@ -6470,8 +6493,11 @@ ahc_loadseq(struct ahc_softc *ahc) ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE); ahc_restart(ahc); - if (bootverbose) + if (bootverbose) { printf(" %d instructions downloaded\n", downloaded); + printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", + ahc_name(ahc), ahc->features, ahc->bugs, ahc->flags); + } } static int @@ -6635,41 +6661,6 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) } } -static int -ahc_probe_stack_size(struct ahc_softc *ahc) -{ - int last_probe; - - last_probe = 0; - while (1) { - int i; - - /* - * We avoid using 0 as a pattern to avoid - * confusion if the stack implementation - * "back-fills" with zeros when "poping' - * entries. - */ - for (i = 1; i <= last_probe+1; i++) { - ahc_outb(ahc, STACK, i & 0xFF); - ahc_outb(ahc, STACK, (i >> 8) & 0xFF); - } - - /* Verify */ - for (i = last_probe+1; i > 0; i--) { - u_int stack_entry; - - stack_entry = ahc_inb(ahc, STACK) - |(ahc_inb(ahc, STACK) << 8); - if (stack_entry != i) - goto sized; - } - last_probe++; - } -sized: - return (last_probe); -} - int ahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries, const char *name, u_int address, u_int value, @@ -6724,6 +6715,7 @@ ahc_dump_card_state(struct ahc_softc *ahc) struct scb *scb; struct scb_tailq *untagged_q; u_int cur_col; + int paused; int target; int maxtarget; int i; @@ -6734,12 +6726,21 @@ ahc_dump_card_state(struct ahc_softc *ahc) uint8_t scb_index; uint8_t saved_scbptr; - saved_scbptr = ahc_inb(ahc, SCBPTR); + if (ahc_is_paused(ahc)) { + paused = 1; + } else { + paused = 0; + ahc_pause(ahc); + } + saved_scbptr = ahc_inb(ahc, SCBPTR); last_phase = ahc_inb(ahc, LASTPHASE); - printf("%s: Dumping Card State %s, at SEQADDR 0x%x\n", + printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" + "%s: Dumping Card State %s, at SEQADDR 0x%x\n", ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg, ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); + if (paused) + printf("Card was paused\n"); printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n", ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX), ahc_inb(ahc, ARG_2)); @@ -6747,12 +6748,14 @@ ahc_dump_card_state(struct ahc_softc *ahc) ahc_inb(ahc, SCBPTR)); cur_col = 0; if ((ahc->features & AHC_DT) != 0) - ahc_scsisigi_print(ahc_inb(ahc, SCSISIGI), &cur_col, 50); - ahc_scsiphase_print(ahc_inb(ahc, SCSIPHASE), &cur_col, 50); + ahc_scsiphase_print(ahc_inb(ahc, SCSIPHASE), &cur_col, 50); + ahc_scsisigi_print(ahc_inb(ahc, SCSISIGI), &cur_col, 50); + ahc_error_print(ahc_inb(ahc, ERROR), &cur_col, 50); ahc_scsibusl_print(ahc_inb(ahc, SCSIBUSL), &cur_col, 50); ahc_lastphase_print(ahc_inb(ahc, LASTPHASE), &cur_col, 50); ahc_scsiseq_print(ahc_inb(ahc, SCSISEQ), &cur_col, 50); ahc_sblkctl_print(ahc_inb(ahc, SBLKCTL), &cur_col, 50); + ahc_scsirate_print(ahc_inb(ahc, SCSIRATE), &cur_col, 50); ahc_seqctl_print(ahc_inb(ahc, SEQCTL), &cur_col, 50); ahc_seq_flags_print(ahc_inb(ahc, SEQ_FLAGS), &cur_col, 50); ahc_sstat0_print(ahc_inb(ahc, SSTAT0), &cur_col, 50); @@ -6767,11 +6770,8 @@ ahc_dump_card_state(struct ahc_softc *ahc) if (cur_col != 0) printf("\n"); printf("STACK:"); - for (i = 0; i < ahc->stack_size; i++) { - ahc->saved_stack[i] = - ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8); - printf(" 0x%x", ahc->saved_stack[i]); - } + for (i = 0; i < STACK_SIZE; i++) + printf(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8)); printf("\nSCB count = %d\n", ahc->scb_data->numscbs); printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); @@ -6886,7 +6886,10 @@ ahc_dump_card_state(struct ahc_softc *ahc) } ahc_platform_dump_card_state(ahc); + printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); ahc_outb(ahc, SCBPTR, saved_scbptr); + if (paused == 0) + ahc_unpause(ahc); } /************************* Target Mode ****************************************/ diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h index 12acab3..a30deb3 100644 --- a/sys/dev/aic7xxx/aic7xxx.h +++ b/sys/dev/aic7xxx/aic7xxx.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/aic7xxx.h#62 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#70 $ * * $FreeBSD$ */ @@ -98,6 +98,14 @@ struct seeprom_descriptor; (SCB_GET_TARGET(ahc, scb) + (SCB_IS_SCSIBUS_B(ahc, scb) ? 8 : 0)) #define SCB_GET_TARGET_MASK(ahc, scb) \ (0x01 << (SCB_GET_TARGET_OFFSET(ahc, scb))) +#ifdef AHC_DEBUG +#define SCB_IS_SILENT(scb) \ + ((ahc_debug & AHC_SHOW_MASKED_ERRORS) == 0 \ + && (((scb)->flags & SCB_SILENT) != 0)) +#else +#define SCB_IS_SILENT(scb) \ + (((scb)->flags & SCB_SILENT) != 0) +#endif #define TCL_TARGET_OFFSET(tcl) \ ((((tcl) >> 4) & TID) >> 4) #define TCL_LUN(tcl) \ @@ -310,11 +318,11 @@ typedef enum { */ typedef enum { AHC_FNONE = 0x000, - AHC_PRIMARY_CHANNEL = 0x003,/* + AHC_PRIMARY_CHANNEL = 0x003, /* * The channel that should * be probed first. */ - AHC_USEDEFAULTS = 0x004,/* + AHC_USEDEFAULTS = 0x004, /* * For cards without an seeprom * or a BIOS to initialize the chip's * SRAM, we use the default target @@ -322,29 +330,29 @@ typedef enum { */ AHC_SEQUENCER_DEBUG = 0x008, AHC_SHARED_SRAM = 0x010, - AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */ + AHC_LARGE_SEEPROM = 0x020, /* Uses C56_66 not C46 */ AHC_RESET_BUS_A = 0x040, AHC_RESET_BUS_B = 0x080, AHC_EXTENDED_TRANS_A = 0x100, AHC_EXTENDED_TRANS_B = 0x200, AHC_TERM_ENB_A = 0x400, AHC_TERM_ENB_B = 0x800, - AHC_INITIATORROLE = 0x1000,/* + AHC_INITIATORROLE = 0x1000, /* * Allow initiator operations on * this controller. */ - AHC_TARGETROLE = 0x2000,/* + AHC_TARGETROLE = 0x2000, /* * Allow target operations on this * controller. */ AHC_NEWEEPROM_FMT = 0x4000, AHC_RESOURCE_SHORTAGE = 0x8000, - AHC_TQINFIFO_BLOCKED = 0x10000,/* Blocked waiting for ATIOs */ - AHC_INT50_SPEEDFLEX = 0x20000,/* + AHC_TQINFIFO_BLOCKED = 0x10000, /* Blocked waiting for ATIOs */ + AHC_INT50_SPEEDFLEX = 0x20000, /* * Internal 50pin connector * sits behind an aic3860 */ - AHC_SCB_BTT = 0x40000,/* + AHC_SCB_BTT = 0x40000, /* * The busy targets table is * stored in SCB space rather * than SRAM. @@ -355,7 +363,9 @@ typedef enum { AHC_EDGE_INTERRUPT = 0x800000, /* Device uses edge triggered ints */ AHC_39BIT_ADDRESSING = 0x1000000, /* Use 39 bit addressing scheme. */ AHC_LSCBS_ENABLED = 0x2000000, /* 64Byte SCBs enabled */ - AHC_SCB_CONFIG_USED = 0x4000000 /* No SEEPROM but SCB2 had info. */ + AHC_SCB_CONFIG_USED = 0x4000000, /* No SEEPROM but SCB2 had info. */ + AHC_NO_BIOS_INIT = 0x8000000, /* No BIOS left over settings. */ + AHC_DISABLE_PCI_PERR = 0x10000000 } ahc_flag; /************************* Hardware SCB Definition ***************************/ @@ -548,7 +558,13 @@ typedef enum { * responding to our attempt * to report the error. */ - SCB_TARGET_SCB = 0x2000 + SCB_TARGET_SCB = 0x2000, + SCB_SILENT = 0x4000 /* + * Be quiet about transmission type + * errors. They are expected and we + * don't want to upset the user. This + * flag is typically used during DV. + */ } scb_flag; struct scb { @@ -733,7 +749,7 @@ struct ahc_syncrate { }; /* Safe and valid period for async negotiations. */ -#define AHC_ASYNC_XFER_PERIOD 0x44 +#define AHC_ASYNC_XFER_PERIOD 0x45 #define AHC_ULTRA2_XFER_PERIOD 0x0a /* @@ -743,6 +759,8 @@ struct ahc_syncrate { #define AHC_SYNCRATE_ULTRA2 1 #define AHC_SYNCRATE_ULTRA 3 #define AHC_SYNCRATE_FAST 6 +#define AHC_SYNCRATE_MAX AHC_SYNCRATE_DT +#define AHC_SYNCRATE_MIN 13 /***************************** Lookup Tables **********************************/ /* @@ -1038,7 +1056,6 @@ struct ahc_softc { u_int pci_cachesize; u_int stack_size; - uint16_t *saved_stack; /* Per-Unit descriptive information */ const char *description; @@ -1273,7 +1290,8 @@ extern uint32_t ahc_debug; #define AHC_SHOW_QFULL 0x0200 #define AHC_SHOW_QUEUE 0x0400 #define AHC_SHOW_TQIN 0x0800 -#define AHC_DEBUG_SEQUENCER 0x1000 +#define AHC_SHOW_MASKED_ERRORS 0x1000 +#define AHC_DEBUG_SEQUENCER 0x2000 #endif void ahc_print_scb(struct scb *scb); void ahc_print_devinfo(struct ahc_softc *ahc, diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg index b3e4456..7dc8f6d 100644 --- a/sys/dev/aic7xxx/aic7xxx.reg +++ b/sys/dev/aic7xxx/aic7xxx.reg @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#35 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#37 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -673,6 +673,8 @@ register STACK { access_mode RO } +const STACK_SIZE 4 + /* * Board Control (p. 3-43) */ @@ -1578,6 +1580,7 @@ const BUS_32_BIT 0x02 const MAX_OFFSET_8BIT 0x0f const MAX_OFFSET_16BIT 0x08 const MAX_OFFSET_ULTRA2 0x7f +const MAX_OFFSET 0xff const HOST_MSG 0xff /* Target mode command processing constants */ diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index b784635..19d19d8 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#52 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#54 $" PATCH_ARG_LIST = "struct ahc_softc *ahc" PREFIX = "ahc_" @@ -70,7 +70,7 @@ bus_free_sel: * Turn off the selection hardware. We need to reset the * selection request in order to perform a new selection. */ - and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ; + and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP; and SIMODE1, ~ENBUSFREE; poll_for_work: call clear_target_state; @@ -193,7 +193,7 @@ select_in: * Setup the DMA for sending the identify and * command information. */ - or SEQ_FLAGS, CMDPHASE_PENDING; + mvi SEQ_FLAGS, CMDPHASE_PENDING; mov A, TQINPOS; if ((ahc->features & AHC_CMD_CHAN) != 0) { @@ -306,7 +306,7 @@ ident_messages_done: } else { mvi DFDAT, SCB_LIST_NULL; } - mvi SEQ_FLAGS, TARG_CMD_PENDING; + or SEQ_FLAGS, TARG_CMD_PENDING; test SEQ_FLAGS2, TARGET_MSG_PENDING jnz target_mesgout_pending; test SCSISIGI, ATNI jnz target_mesgout_continue; @@ -512,6 +512,7 @@ target_mesgout: target_mesgout_continue: call target_inb; target_mesgout_pending: + and SEQ_FLAGS2, ~TARGET_MSG_PENDING; /* Local Processing goes here... */ jmp host_target_message_loop; diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h index f594e78..53de390 100644 --- a/sys/dev/aic7xxx/aic7xxx_inline.h +++ b/sys/dev/aic7xxx/aic7xxx_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/aic7xxx_inline.h#38 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#39 $ * * $FreeBSD$ */ @@ -238,6 +238,18 @@ static __inline struct ahc_initiator_tinfo * char channel, u_int our_id, u_int remote_id, struct ahc_tmode_tstate **tstate); +static __inline uint16_t + ahc_inw(struct ahc_softc *ahc, u_int port); +static __inline void ahc_outw(struct ahc_softc *ahc, u_int port, + u_int value); +static __inline uint32_t + ahc_inl(struct ahc_softc *ahc, u_int port); +static __inline void ahc_outl(struct ahc_softc *ahc, u_int port, + uint32_t value); +static __inline uint64_t + ahc_inq(struct ahc_softc *ahc, u_int port); +static __inline void ahc_outq(struct ahc_softc *ahc, u_int port, + uint64_t value); static __inline struct scb* ahc_get_scb(struct ahc_softc *ahc); static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb); @@ -285,6 +297,63 @@ ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, return (&(*tstate)->transinfo[remote_id]); } +static __inline uint16_t +ahc_inw(struct ahc_softc *ahc, u_int port) +{ + return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port)); +} + +static __inline void +ahc_outw(struct ahc_softc *ahc, u_int port, u_int value) +{ + ahc_outb(ahc, port, value & 0xFF); + ahc_outb(ahc, port+1, (value >> 8) & 0xFF); +} + +static __inline uint32_t +ahc_inl(struct ahc_softc *ahc, u_int port) +{ + return ((ahc_inb(ahc, port)) + | (ahc_inb(ahc, port+1) << 8) + | (ahc_inb(ahc, port+2) << 16) + | (ahc_inb(ahc, port+3) << 24)); +} + +static __inline void +ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value) +{ + ahc_outb(ahc, port, (value) & 0xFF); + ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF); + ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF); + ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF); +} + +static __inline uint64_t +ahc_inq(struct ahc_softc *ahc, u_int port) +{ + return ((ahc_inb(ahc, port)) + | (ahc_inb(ahc, port+1) << 8) + | (ahc_inb(ahc, port+2) << 16) + | (ahc_inb(ahc, port+3) << 24) + | (((uint64_t)ahc_inb(ahc, port+4)) << 32) + | (((uint64_t)ahc_inb(ahc, port+5)) << 40) + | (((uint64_t)ahc_inb(ahc, port+6)) << 48) + | (((uint64_t)ahc_inb(ahc, port+7)) << 56)); +} + +static __inline void +ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value) +{ + ahc_outb(ahc, port, value & 0xFF); + ahc_outb(ahc, port+1, (value >> 8) & 0xFF); + ahc_outb(ahc, port+2, (value >> 16) & 0xFF); + ahc_outb(ahc, port+3, (value >> 24) & 0xFF); + ahc_outb(ahc, port+4, (value >> 32) & 0xFF); + ahc_outb(ahc, port+5, (value >> 40) & 0xFF); + ahc_outb(ahc, port+6, (value >> 48) & 0xFF); + ahc_outb(ahc, port+7, (value >> 56) & 0xFF); +} + /* * Get a free scb. If there are none, see if we can allocate a new SCB. */ 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); } |