summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/aic7xxx')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c191
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h46
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg5
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq9
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h71
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c67
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);
}
OpenPOWER on IntegriCloud