summaryrefslogtreecommitdiff
path: root/linux/src/drivers/scsi/aic7xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/src/drivers/scsi/aic7xxx.c')
-rw-r--r--linux/src/drivers/scsi/aic7xxx.c1254
1 files changed, 679 insertions, 575 deletions
diff --git a/linux/src/drivers/scsi/aic7xxx.c b/linux/src/drivers/scsi/aic7xxx.c
index 5cec782..be817bb 100644
--- a/linux/src/drivers/scsi/aic7xxx.c
+++ b/linux/src/drivers/scsi/aic7xxx.c
@@ -38,7 +38,7 @@
* Parts of this driver were also based on the FreeBSD driver by
* Justin T. Gibbs. His copyright follows:
*
- * --------------------------------------------------------------------------
+ * --------------------------------------------------------------------------
* Copyright (c) 1994-1997 Justin Gibbs.
* All rights reserved.
*
@@ -54,8 +54,8 @@
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
- * Where this Software is combined with software released under the terms of
- * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
* combined work to also be released under the terms of the GPL, the terms
* and conditions of this License will apply in addition to those of the
* GPL with the exception of any terms or conditions of this License that
@@ -73,7 +73,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.1 1999/04/26 05:54:15 tb Exp $
+ * $Id: aic7xxx.c,v 1.1.4.1 2004/01/16 22:41:26 roland Exp $
*---------------------------------------------------------------------------
*
* Thanks also go to (in alphabetical order) the following:
@@ -93,7 +93,6 @@
*
* Daniel M. Eischen, deischen@iworks.InterWorks.org, 1/23/97
*
- * $Id: aic7xxx.c,v 1.1 1999/04/26 05:54:15 tb Exp $
*-M*************************************************************************/
/*+M**************************************************************************
@@ -145,7 +144,7 @@
* doesn't provide the same protection techniques as FreeBSD does, nor can
* they be easily implemented in any middle ware code since they would truly
* belong in the kernel proper and would effect all drivers. For the time
- * being, I see issues such as these as major stumbling blocks to the
+ * being, I see issues such as these as major stumbling blocks to the
* reliability of code based upon such middle ware. Therefore, I choose to
* use a different approach to importing the FreeBSD code that doesn't
* involve any middle ware type code. My approach is to import the sequencer
@@ -252,7 +251,7 @@
* I'm going to make the default to use the fake commands, we'll see how
* it goes.
*/
-
+
#define AIC7XXX_FAKE_NEGOTIATION_CMDS
/*
@@ -299,11 +298,11 @@
* complete and no longer needs debugging. OK...a lot of things are now
* surrounded by this define, so turning this off does have an impact.
*/
-
+
/*
* #define AIC7XXX_VERBOSE_DEBUGGING
*/
-
+
#if defined(MODULE) || defined(PCMCIA)
#include <linux/module.h>
#endif
@@ -336,6 +335,7 @@
#include "aic7xxx/sequencer.h"
#include "aic7xxx/scsi_message.h"
#include "aic7xxx_reg.h"
+#include <scsi/scsicam.h>
#include <linux/stat.h>
#include <linux/malloc.h> /* for kmalloc() */
@@ -354,7 +354,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-#define AIC7XXX_C_VERSION "5.1.4"
+#define AIC7XXX_C_VERSION "5.1.13"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -447,8 +447,10 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
* You can try raising me if tagged queueing is enabled, or lowering
* me if you only have 4 SCBs.
*/
-#ifdef CONFIG_AIC7XXX_CMDS_PER_LUN
-#define AIC7XXX_CMDS_PER_LUN CONFIG_AIC7XXX_CMDS_PER_LUN
+#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE
+#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE
+#else
+#define AIC7XXX_CMDS_PER_DEVICE 8
#endif
/* Set this to the delay in seconds after SCSI bus reset. */
@@ -492,8 +494,8 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
* indexes 0-7 for channel 0, and indexes 8-15 for channel 1.
*
* *** Determining commands per LUN ***
- *
- * When AIC7XXX_CMDS_PER_LUN is not defined, the driver will use its
+ *
+ * When AIC7XXX_CMDS_PER_DEVICE is not defined, the driver will use its
* own algorithm to determine the commands/LUN. If SCB paging is
* enabled, which is always now, the default is 8 commands per lun
* that indicates it supports tagged queueing. All non-tagged devices
@@ -511,8 +513,13 @@ typedef struct
* Make a define that will tell the driver not to use tagged queueing
* by default.
*/
+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+#define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\
+ 0, 0, 0, 0, 0, 0, 0, 0}
+#else
#define DEFAULT_TAG_COMMANDS {255, 255, 255, 255, 255, 255, 255, 255,\
255, 255, 255, 255, 255, 255, 255, 255}
+#endif
/*
* Modify this as you see fit for your system. By setting tag_commands
@@ -551,6 +558,27 @@ adapter_tag_info_t aic7xxx_tag_info[] =
};
*/
+static adapter_tag_info_t aic7xxx_tag_info[] =
+{
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS}
+};
+
+
/*
* Define an array of board names that can be indexed by aha_type.
* Don't forget to change this when changing the types!
@@ -577,9 +605,14 @@ static const char *board_names[] = {
"Adaptec AHA-2944 Ultra SCSI host adapter", /* AIC_7884 */
"Adaptec AIC-7895 Ultra SCSI host adapter", /* AIC_7895 */
"Adaptec AIC-7890/1 Ultra2 SCSI host adapter", /* AIC_7890 */
+ "Adaptec AHA-293X Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AHA-294X Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AIC-7896/7 Ultra2 SCSI host adapter", /* AIC_7896 */
- "Adaptec AHA-394X Ultra2 SCSI host adapter" /* AIC_7897 */
+ "Adaptec AHA-394X Ultra2 SCSI host adapter", /* AIC_7897 */
+ "Adaptec AHA-395X Ultra2 SCSI host adapter", /* AIC_7897 */
+ "Adaptec PCMCIA SCSI controller", /* card bus stuff */
+ "Adaptec AIC-7892 Ultra 160/m SCSI host adapter", /* AIC_7892 */
+ "Adaptec AIC-7899 Ultra 160/m SCSI host adapter", /* AIC_7899 */
};
/*
@@ -851,7 +884,7 @@ typedef enum {
SCB_MSGOUT_SENT = 0x0200,
SCB_MSGOUT_SDTR = 0x0400,
SCB_MSGOUT_WDTR = 0x0800,
- SCB_MSGOUT_BITS = SCB_MSGOUT_SENT |
+ SCB_MSGOUT_BITS = SCB_MSGOUT_SENT |
SCB_MSGOUT_SDTR |
SCB_MSGOUT_WDTR,
SCB_QUEUED_ABORT = 0x1000,
@@ -882,6 +915,7 @@ typedef enum {
* and what flags weren't. This way, I could clean up the flag usage on
* a use by use basis. Doug Ledford
*/
+ AHC_RESET_DELAY = 0x00080000,
AHC_A_SCANNED = 0x00100000,
AHC_B_SCANNED = 0x00200000,
AHC_MULTI_CHANNEL = 0x00400000,
@@ -908,6 +942,8 @@ typedef enum {
AHC_AIC7890 = 0x0006,
AHC_AIC7895 = 0x0007,
AHC_AIC7896 = 0x0008,
+ AHC_AIC7892 = 0x0009,
+ AHC_AIC7899 = 0x000a,
AHC_VL = 0x0100,
AHC_EISA = 0x0200,
AHC_PCI = 0x0400,
@@ -924,6 +960,7 @@ typedef enum {
AHC_QUEUE_REGS = 0x0040,
AHC_SG_PRELOAD = 0x0080,
AHC_SPIOCAP = 0x0100,
+ AHC_ULTRA160 = 0x0200,
AHC_AIC7770_FE = AHC_FENONE,
AHC_AIC7850_FE = AHC_SPIOCAP,
AHC_AIC7860_FE = AHC_ULTRA|AHC_SPIOCAP,
@@ -933,6 +970,8 @@ typedef enum {
AHC_QUEUE_REGS|AHC_SG_PRELOAD,
AHC_AIC7895_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA,
AHC_AIC7896_FE = AHC_AIC7890_FE,
+ AHC_AIC7892_FE = AHC_AIC7890_FE|AHC_ULTRA160,
+ AHC_AIC7899_FE = AHC_AIC7890_FE|AHC_ULTRA160,
} ahc_feature;
struct aic7xxx_scb {
@@ -941,7 +980,6 @@ struct aic7xxx_scb {
struct aic7xxx_scb *q_next; /* next scb in queue */
volatile scb_flag_type flags; /* current state of scb */
struct hw_scatterlist *sg_list; /* SG list in adapter format */
- void *kmalloc_ptr;
unsigned char tag_action;
unsigned char sg_count;
unsigned char sense_cmd[6]; /*
@@ -952,6 +990,7 @@ struct aic7xxx_scb {
* don't have to calculate anything
* during underflow/overflow/stat code
*/
+ void *kmalloc_ptr;
};
/*
@@ -1029,88 +1068,73 @@ struct aic7xxx_host {
* This is the first 64 bytes in the host struct
*/
- struct Scsi_Host *host; /* pointer to scsi host */
- struct aic7xxx_host *next; /* allow for multiple IRQs */
- int host_no; /* SCSI host number */
- unsigned long base; /* card base address */
- volatile unsigned char *maddr; /* memory mapped address */
- unsigned long mbase; /* I/O memory address */
+ /*
+ * We are grouping things here....first, items that get either read or
+ * written with nearly every interrupt
+ */
volatile ahc_flag_type flags;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
- spinlock_t spin_lock;
-#endif
- volatile unsigned char cpu_lock_count[NR_CPUS];
- ahc_chip chip; /* chip type */
ahc_feature features; /* chip features */
- unsigned long last_reset;
+ unsigned long base; /* card base address */
+ volatile unsigned char *maddr; /* memory mapped address */
unsigned long isr_count; /* Interrupt count */
unsigned long spurious_int;
- struct target_cmd *targetcmds;
- unsigned int num_targetcmds;
+ scb_data_type *scb_data;
+ volatile unsigned short needsdtr;
+ volatile unsigned short sdtr_pending;
+ volatile unsigned short needwdtr;
+ volatile unsigned short wdtr_pending;
+ struct aic7xxx_cmd_queue {
+ Scsi_Cmnd *head;
+ Scsi_Cmnd *tail;
+ } completeq;
+
+ /*
+ * Things read/written on nearly every entry into aic7xxx_queue()
+ */
+ volatile scb_queue_type waiting_scbs;
unsigned short discenable; /* Targets allowed to disconnect */
unsigned short tagenable; /* Targets using tagged I/O */
unsigned short orderedtag; /* Ordered Q tags allowed */
- volatile unsigned char activescbs; /* active scbs */
- volatile unsigned char max_activescbs;
unsigned char unpause; /* unpause value for HCNTRL */
unsigned char pause; /* pause value for HCNTRL */
volatile unsigned char qoutfifonext;
+ volatile unsigned char activescbs; /* active scbs */
+ volatile unsigned char max_activescbs;
volatile unsigned char qinfifonext;
- /*
- * MAX_TARGETS is currently == 16, so that makes these entries the next
- * 64 bytes
- */
-
#define DEVICE_PRESENT 0x01
#define BUS_DEVICE_RESET_PENDING 0x02
-#define DEVICE_TIMEOUT 0x04
+#define DEVICE_RESET_DELAY 0x04
#define DEVICE_PRINT_SDTR 0x08
#define DEVICE_PRINT_WDTR 0x10
-#define DEVICE_SUCCESS 0x20
-#define DEVICE_TAGGED_SUCCESS 0x40
+#define DEVICE_WAS_BUSY 0x20
#define DEVICE_SCANNED 0x80
volatile unsigned char dev_flags[MAX_TARGETS];
volatile unsigned char dev_active_cmds[MAX_TARGETS];
volatile unsigned char dev_temp_queue_depth[MAX_TARGETS];
unsigned char dev_commands_sent[MAX_TARGETS];
- /*
- * The next 128 (or 256 on 64 bit machines)....
- */
- Scsi_Cmnd *dev_wdtr_cmnd[MAX_TARGETS];
- Scsi_Cmnd *dev_sdtr_cmnd[MAX_TARGETS];
+ unsigned int dev_timer_active; /* Which devs have a timer set */
+ struct timer_list dev_timer;
+ unsigned long dev_expires[MAX_TARGETS];
- /*
- * The next 64....
- */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+ spinlock_t spin_lock;
+ volatile unsigned char cpu_lock_count[NR_CPUS];
+#endif
- long dev_last_reset[MAX_TARGETS];
- /*
- * The next 64....
- */
+#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
+ Scsi_Cmnd *dev_wdtr_cmnd[MAX_TARGETS];
+ Scsi_Cmnd *dev_sdtr_cmnd[MAX_TARGETS];
+#endif
- unsigned char dev_mid_level_queue_depth[MAX_TARGETS];
unsigned char dev_last_queue_full[MAX_TARGETS];
unsigned char dev_last_queue_full_count[MAX_TARGETS];
unsigned char dev_max_queue_depth[MAX_TARGETS];
- /*
- * The next 128....
- */
-
volatile scb_queue_type delayed_scbs[MAX_TARGETS];
- /*
- *
- */
-
- struct timer_list dev_timer[MAX_TARGETS];
-
- /*
- * The next 64....
- */
unsigned char msg_buf[9]; /* The message for the target */
unsigned char msg_type;
@@ -1120,16 +1144,6 @@ struct aic7xxx_host {
unsigned char msg_len; /* Length of message */
unsigned char msg_index; /* Index into msg_buf array */
transinfo_type transinfo[MAX_TARGETS];
- volatile scb_queue_type waiting_scbs; /*
- * SCBs waiting for space in
- * the QINFIFO.
- */
- scb_data_type *scb_data;
-
- struct aic7xxx_cmd_queue {
- Scsi_Cmnd *head;
- Scsi_Cmnd *tail;
- } completeq;
/*
@@ -1147,16 +1161,11 @@ struct aic7xxx_host {
volatile unsigned char qoutfifo[256];
volatile unsigned char qinfifo[256];
unsigned int irq; /* IRQ for this adapter */
- volatile unsigned short needsdtr;
- volatile unsigned short sdtr_pending;
- volatile unsigned short needwdtr;
- volatile unsigned short wdtr_pending;
int instance; /* aic7xxx instance number */
int scsi_id; /* host adapter SCSI ID */
int scsi_id_b; /* channel B for twin adapters */
unsigned int bios_address;
int board_name_index;
- unsigned long reset_start;
unsigned short needsdtr_copy; /* default config */
unsigned short needwdtr_copy; /* default config */
unsigned short ultraenb; /* Ultra mode target list */
@@ -1170,6 +1179,11 @@ struct aic7xxx_host {
struct seeprom_config sc;
unsigned short sc_type;
unsigned short sc_size;
+ struct aic7xxx_host *next; /* allow for multiple IRQs */
+ struct Scsi_Host *host; /* pointer to scsi host */
+ int host_no; /* SCSI host number */
+ unsigned long mbase; /* I/O memory address */
+ ahc_chip chip; /* chip type */
/*
* Statistics Kept:
@@ -1184,21 +1198,27 @@ struct aic7xxx_host {
*
* NOTE: Enabling this feature is likely to cause a noticeable performance
* decrease as the accesses into the stats structures blows apart multiple
- * cache lines and is CPU time consuming. We keep the xfer count always
- * for use by the aic7xxx_proc.c code, but only do the bins if the
- * proc stats code is enabled.
+ * cache lines and is CPU time consuming.
+ *
+ * NOTE: Since it doesn't really buy us much, but consumes *tons* of RAM
+ * and blows apart all sorts of cache lines, I modified this so that we
+ * no longer look at the LUN. All LUNs now go into the same bin on each
+ * device for stats purposes.
*/
struct aic7xxx_xferstats {
- long xfers; /* total xfer count */
- long w_total; /* total writes */
- long w_total512; /* 512 byte blocks written */
- long r_total; /* total reads */
- long r_total512; /* 512 byte blocks read */
+ long w_total; /* total writes */
+ long r_total; /* total reads */
#ifdef AIC7XXX_PROC_STATS
- long w_bins[10]; /* binned write */
- long r_bins[10]; /* binned reads */
+ long w_bins[8]; /* binned write */
+ long r_bins[8]; /* binned reads */
#endif /* AIC7XXX_PROC_STATS */
- } stats[MAX_TARGETS][MAX_LUNS]; /* [(channel << 3)|target][lun] */
+ } stats[MAX_TARGETS]; /* [(channel << 3)|target] */
+
+#if 0
+ struct target_cmd *targetcmds;
+ unsigned int num_targetcmds;
+#endif
+
};
/*
@@ -1282,11 +1302,9 @@ static unsigned int aic7xxx_no_reset = 0;
*/
static int aic7xxx_reverse_scan = 0;
/*
- * This setting enables a hack to fix the IRQ settings on buggy 7895
- * MB controller setups:
- * -1 == Disable this hack
- * 0 == Use the Channel A IRQ for both channels
- * 1 == Use the Channel B IRQ for both channels
+ * Should we force EXTENDED translation on a controller.
+ * 0 == Use whatever is in the SEEPROM or default to off
+ * 1 == Use whatever is in the SEEPROM or default to on
*/
static unsigned int aic7xxx_extended = 0;
/*
@@ -1301,7 +1319,7 @@ static int aic7xxx_irq_trigger = -1;
* This should not be used under normal conditions. However, in the case
* that a controller does not have a readable SEEPROM (so that we can't
* read the SEEPROM settings directly) and that a controller has a buggered
- * version of the cable detection logic, this can be used to force the
+ * version of the cable detection logic, this can be used to force the
* correct termination. It is preferable to use the manual termination
* settings in the BIOS if possible, but some motherboard controllers store
* those settings in a format we can't read. In other cases, auto term
@@ -1382,7 +1400,7 @@ static int aic7xxx_pci_parity = 0;
* Set this to any non-0 value to cause us to dump the contents of all
* the card's registers in a hex dump format tailored to each model of
* controller.
- *
+ *
* NOTE: THE CONTROLLER IS LEFT IN AN UNUSEABLE STATE BY THIS OPTION.
* YOU CANNOT BOOT UP WITH THIS OPTION, IT IS FOR DEBUGGING PURPOSES
* ONLY
@@ -1426,35 +1444,6 @@ static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";
#endif
-/*
- * See the comments earlier in the file for what this item is all about
- * If you have more than 4 controllers, you will need to increase the
- * the number of items in the array below. Additionally, if you don't
- * want to have lilo pass a humongous config line to the aic7xxx driver,
- * then you can get in and manually adjust these instead of leaving them
- * at the default. Pay attention to the comments earlier in this file
- * concerning this array if you are going to hand modify these values.
- */
-static adapter_tag_info_t aic7xxx_tag_info[] =
-{
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS}
-};
-
#define VERBOSE_NORMAL 0x0000
#define VERBOSE_NEGOTIATION 0x0001
#define VERBOSE_SEQINT 0x0002
@@ -1511,6 +1500,21 @@ mdelay(int milliseconds)
for(i=0; i<milliseconds; i++)
udelay(1000);
}
+
+static inline int
+time_after_eq(unsigned long a, unsigned long b)
+{
+ return((long)((a) - (b)) >= 0L);
+}
+
+static inline int
+timer_pending(struct timer_list *timer)
+{
+ return( timer->prev != NULL );
+}
+
+#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
+
#endif
static inline unsigned char
@@ -1636,7 +1640,7 @@ aic7xxx_setup(char *s, int *dummy)
device++;
else if (instance >= 0)
instance++;
- if ( (device >= MAX_TARGETS) ||
+ if ( (device >= MAX_TARGETS) ||
(instance >= NUMBER(aic7xxx_tag_info)) )
done = TRUE;
tok++;
@@ -1821,7 +1825,7 @@ aic7xxx_download_instr(struct aic7xxx_host *p, int instrptr,
instr = *(union ins_formats*) &seqprog[instrptr * 4];
instr.integer = le32_to_cpu(instr.integer);
-
+
fmt1_ins = &instr.format1;
fmt3_ins = NULL;
@@ -1950,7 +1954,10 @@ aic7xxx_loadseq(struct aic7xxx_host *p)
{
printk(KERN_INFO "(scsi%d) Downloading sequencer code...", p->host_no);
}
+#if 0
download_consts[TMODE_NUMCMDS] = p->num_targetcmds;
+#endif
+ download_consts[TMODE_NUMCMDS] = 0;
cur_patch = &sequencer_patches[0];
downloaded = 0;
skip_addr = 0;
@@ -1996,7 +2003,7 @@ static void
aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded)
{
int i, k, temp;
-
+
aic_outb(p, PERRORDIS|LOADRAM|FAILDIS|FASTMODE, SEQCTL);
aic_outb(p, 0, SEQADDR0);
aic_outb(p, 0, SEQADDR1);
@@ -2224,7 +2231,7 @@ aic7xxx_set_syncrate(struct aic7xxx_host *p, struct aic7xxx_syncrate *syncrate,
old_period = p->transinfo[tindex].cur_period;
old_offset = p->transinfo[tindex].cur_offset;
-
+
if (type & AHC_TRANS_CUR)
{
unsigned int scsirate;
@@ -2283,7 +2290,7 @@ aic7xxx_set_syncrate(struct aic7xxx_host *p, struct aic7xxx_syncrate *syncrate,
if (offset)
{
int rate_mod = (scsirate & WIDEXFER) ? 1 : 0;
-
+
printk(INFO_LEAD "Synchronous at %s Mbyte/sec, "
"offset %d.\n", p->host_no, channel, target, lun,
syncrate->rate[rate_mod], offset);
@@ -2327,7 +2334,7 @@ aic7xxx_set_width(struct aic7xxx_host *p, int target, int channel, int lun,
tindex = target | (channel << 3);
target_mask = 1 << tindex;
-
+
old_width = p->transinfo[tindex].cur_width;
if (p->features & AHC_ULTRA2)
@@ -2336,8 +2343,8 @@ aic7xxx_set_width(struct aic7xxx_host *p, int target, int channel, int lun,
new_offset = MAX_OFFSET_16BIT;
else
new_offset = MAX_OFFSET_8BIT;
-
- if (type & AHC_TRANS_CUR)
+
+ if (type & AHC_TRANS_CUR)
{
unsigned char scsirate;
@@ -2354,7 +2361,7 @@ aic7xxx_set_width(struct aic7xxx_host *p, int target, int channel, int lun,
p->transinfo[tindex].cur_width = width;
- if ((aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+ if ((aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
(p->dev_flags[tindex] & DEVICE_PRINT_WDTR))
{
printk(INFO_LEAD "Using %s transfers\n", p->host_no, channel, target,
@@ -2377,7 +2384,7 @@ aic7xxx_set_width(struct aic7xxx_host *p, int target, int channel, int lun,
p->transinfo[tindex].goal_offset = new_offset;
}
-
+
/*+F*************************************************************************
* Function:
* scbq_init
@@ -2794,27 +2801,17 @@ aic7xxx_done_cmds_complete(struct aic7xxx_host *p)
Scsi_Cmnd *cmd;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
unsigned int cpu_flags = 0;
-
+#endif
+
DRIVER_LOCK
while (p->completeq.head != NULL)
{
cmd = p->completeq.head;
p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble;
cmd->host_scribble = NULL;
- sti();
cmd->scsi_done(cmd);
- cli();
}
DRIVER_UNLOCK
-#else
- while (p->completeq.head != NULL)
- {
- cmd = p->completeq.head;
- p->completeq.head = (Scsi_Cmnd *)cmd->host_scribble;
- cmd->host_scribble = NULL;
- cmd->scsi_done(cmd);
- }
-#endif
}
/*+F*************************************************************************
@@ -2872,7 +2869,8 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
if ( (cmd->cmnd[0] == INQUIRY) && (cmd->result == DID_OK) )
{
char *buffer;
-
+
+ p->dev_flags[tindex] |= DEVICE_PRESENT;
if(cmd->use_sg)
{
struct scatterlist *sg;
@@ -2914,23 +2912,34 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
p->needsdtr_copy |= (1<<tindex);
if (p->flags & AHC_SEEPROM_FOUND)
+ {
p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
- else if (p->features & AHC_ULTRA2)
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
- else if (p->features & AHC_ULTRA)
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
- else
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
-
- if (p->features & AHC_ULTRA2)
- p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
- else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
- p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ p->transinfo[tindex].goal_offset = p->transinfo[tindex].user_offset;
+ }
else
- p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ {
+ if (p->features & AHC_ULTRA2)
+ {
+ p->transinfo[tindex].goal_period =
+ aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
+ }
+ else if (p->features & AHC_ULTRA)
+ {
+ p->transinfo[tindex].goal_period =
+ aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
+ }
+ else
+ {
+ p->transinfo[tindex].goal_period =
+ aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
+ }
+ if (p->features & AHC_ULTRA2)
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+ else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ else
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ }
}
else
{
@@ -2951,12 +2960,12 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
int message_error = FALSE;
mask = 0x01 << tindex;
-
+
/*
* Check to see if we get an invalid message or a message error
* after failing to negotiate a wide or sync transfer message.
*/
- if ((scb->flags & SCB_SENSE) &&
+ if ((scb->flags & SCB_SENSE) &&
((scb->cmd->sense_buffer[12] == 0x43) || /* INVALID_MESSAGE */
(scb->cmd->sense_buffer[12] == 0x49))) /* MESSAGE_ERROR */
{
@@ -3060,7 +3069,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
/*
* XXX: we should actually know how much actually transferred
* XXX: for each command, but apparently that's too difficult.
- *
+ *
* We set a lower limit of 512 bytes on the transfer length. We
* ignore anything less than this because we don't have a real
* reason to count it. Read/Writes to tapes are usually about 20K
@@ -3076,12 +3085,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
int x;
#endif /* AIC7XXX_PROC_STATS */
- sp = &p->stats[TARGET_INDEX(cmd)][cmd->lun & 0x7];
- sp->xfers++;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if ( (sp->xfers > 16) && (aic7xxx_verbose > 0xffff) )
- aic7xxx_verbose &= 0xffff;
-#endif
+ sp = &p->stats[TARGET_INDEX(cmd)];
/*
* For block devices, cmd->request.cmd is always == either READ or
@@ -3093,7 +3097,10 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
(cmd->data_cmnd[0] == WRITE_FILEMARKS) )
{
sp->w_total++;
- sp->w_total512 += (actual >> 9);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
+ if ( (sp->w_total > 16) && (aic7xxx_verbose > 0xffff) )
+ aic7xxx_verbose &= 0xffff;
+#endif
#ifdef AIC7XXX_PROC_STATS
ptr = sp->w_bins;
#endif /* AIC7XXX_PROC_STATS */
@@ -3101,23 +3108,32 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
else
{
sp->r_total++;
- sp->r_total512 += (actual >> 9);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
+ if ( (sp->r_total > 16) && (aic7xxx_verbose > 0xffff) )
+ aic7xxx_verbose &= 0xffff;
+#endif
#ifdef AIC7XXX_PROC_STATS
ptr = sp->r_bins;
#endif /* AIC7XXX_PROC_STATS */
}
#ifdef AIC7XXX_PROC_STATS
- for (x = 9; x <= 17; x++)
+ x = -10;
+ while(actual)
{
- if (actual < (1 << x))
- {
- ptr[x - 9]++;
- break;
- }
+ actual >>= 1;
+ x++;
+ }
+ if (x < 0)
+ {
+ ptr[0]++;
}
- if (x > 17)
+ else if (x > 7)
{
- ptr[x - 9]++;
+ ptr[7]++;
+ }
+ else
+ {
+ ptr[x]++;
}
#endif /* AIC7XXX_PROC_STATS */
}
@@ -3393,7 +3409,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
}
}
else
- {
+ {
min_target = target | (channel << 3);
max_target = min_target;
}
@@ -3401,42 +3417,24 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
for (i = min_target; i <= max_target; i++)
{
+ if ( i == p->scsi_id )
+ {
+ continue;
+ }
if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
printk(INFO_LEAD "Cleaning up status information "
"and delayed_scbs.\n", p->host_no, channel, i, lun);
- if ( !(p->dev_flags[i] & DEVICE_TAGGED_SUCCESS) &&
- (p->dev_active_cmds[i]) &&
- (p->tagenable & (0x01 << i)) )
- {
- printk(INFO_LEAD "Device appears to be choking on tagged commands.\n",
- p->host_no, channel, i, lun);
- printk(INFO_LEAD "Will use untagged I/O instead.\n", p->host_no,
- channel, i, lun);
- p->dev_max_queue_depth[i] = 1;
- p->dev_temp_queue_depth[i] = 1;
- p->tagenable &= ~(0x01 << i);
- p->orderedtag &= ~(0x01 << i);
- }
p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
if ( tag == SCB_LIST_NULL )
{
- p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR;
- p->dev_last_reset[i] = jiffies;
+ p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR |
+ DEVICE_RESET_DELAY;
+ p->dev_expires[i] = jiffies + (4 * HZ);
+ p->dev_timer_active |= (0x01 << i);
p->dev_last_queue_full_count[i] = 0;
p->dev_last_queue_full[i] = 0;
p->dev_temp_queue_depth[i] =
p->dev_max_queue_depth[i];
- /*
- * In case this isn't a full bus reset, we want to add a 4 second timer in
- * here so that we can delay all re-sent commands for this device for the
- * 4 seconds and then have our timer routine pick them back up.
- */
- if(p->dev_timer[i].expires)
- {
- del_timer(&p->dev_timer[i]);
- }
- p->dev_timer[i].expires = jiffies + (4 * HZ);
- add_timer(&p->dev_timer[i]);
}
for(j=0; j<MAX_LUNS; j++)
{
@@ -3448,8 +3446,8 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
(tag == SCB_LIST_NULL) )
aic7xxx_index_busy_target(p, tcl, /* unbusy */ TRUE);
}
- j = 0;
- prev_scbp = NULL;
+ j = 0;
+ prev_scbp = NULL;
scbp = p->delayed_scbs[i].head;
while ( (scbp != NULL) && (j++ <= (p->scb_data->numscbs + 1)) )
{
@@ -3483,11 +3481,13 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
"delayed_scbs queue!\n", p->host_no, channel, i, lun);
scbq_init(&p->delayed_scbs[i]);
}
- if ( (p->delayed_scbs[i].head == NULL) &&
- (p->dev_timer[i].expires) )
+ if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) ||
+ time_after_eq(p->dev_timer.expires, p->dev_expires[i]) )
{
- del_timer(&p->dev_timer[i]);
- p->dev_timer[i].expires = 0;
+ del_timer(&p->dev_timer);
+ p->dev_timer.expires = p->dev_expires[i];
+ add_timer(&p->dev_timer);
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
}
}
}
@@ -3507,8 +3507,8 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
{
struct aic7xxx_scb *scbp, *prev_scbp;
- j = 0;
- prev_scbp = NULL;
+ j = 0;
+ prev_scbp = NULL;
scbp = p->waiting_scbs.head;
while ( (scbp != NULL) && (j++ <= (p->scb_data->numscbs + 1)) )
{
@@ -3620,7 +3620,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
printk(INFO_LEAD "Cleaning disconnected scbs "
"list.\n", p->host_no, channel, target, lun);
- if (p->features & AHC_PAGESCBS)
+ if (p->flags & AHC_PAGESCBS)
{
unsigned char next, prev, scb_index;
@@ -3672,7 +3672,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
* Walk the free list making sure no entries on the free list have
* a valid SCB_TAG value or SCB_CONTROL byte.
*/
- if (p->features & AHC_PAGESCBS)
+ if (p->flags & AHC_PAGESCBS)
{
unsigned char next;
@@ -3953,12 +3953,6 @@ aic7xxx_reset_channel(struct aic7xxx_host *p, int channel, int initiate_reset)
*/
aic7xxx_reset_device(p, ALL_TARGETS, channel, ALL_LUNS, SCB_LIST_NULL);
- /*
- * Convince Mid Level SCSI code to leave us be for a little bit...
- */
- p->last_reset = jiffies;
- p->host->last_reset = (jiffies + (HZ * AIC7XXX_RESET_DELAY));
-
if ( !(p->features & AHC_TWIN) )
{
restart_sequencer(p);
@@ -4000,38 +3994,18 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
tindex = TARGET_INDEX(scb->cmd);
if ( !scb->tag_action && (p->tagenable & (1<<tindex)) )
{
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- printk(INFO_LEAD "Reducing Queue depth for untagged command.\n",
- p->host_no, CTL_OF_SCB(scb));
-#endif
p->dev_temp_queue_depth[tindex] = 1;
}
if ( (p->dev_active_cmds[tindex] >=
p->dev_temp_queue_depth[tindex]) ||
- (p->dev_last_reset[tindex] >= (jiffies - (4 * HZ))) )
+ (p->dev_flags[tindex] & (DEVICE_RESET_DELAY|DEVICE_WAS_BUSY)) ||
+ (p->flags & AHC_RESET_DELAY) )
{
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- printk(INFO_LEAD "Moving SCB to Delayed Queue.\n",
- p->host_no, CTL_OF_SCB(scb));
-#endif
scbq_insert_tail(&p->delayed_scbs[tindex], scb);
- if ( !(p->dev_timer[tindex].expires) &&
- !(p->dev_active_cmds[tindex]) )
- {
- p->dev_timer[tindex].expires = p->dev_last_reset[tindex] + (4 * HZ);
- add_timer(&p->dev_timer[tindex]);
- }
}
else
{
scb->flags &= ~SCB_WAITINGQ;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- printk(INFO_LEAD "Sending command %d/0x%x to QINFIFO\n", p->host_no,
- CTL_OF_SCB(scb), scb->hscb->tag, scb->flags);
-#endif
p->dev_active_cmds[tindex]++;
p->activescbs++;
if ( !(scb->tag_action) )
@@ -4044,16 +4018,6 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
}
if (sent)
{
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- {
- printk(INFO_LEAD "Sending commands to QINFIFO\n", p->host_no,
- -1, -1, -1);
- if ( (p->isr_count < 16) && (aic7xxx_panic_on_abort) &&
- (p->flags & AHC_PAGESCBS) )
- aic7xxx_check_scbs(p, "While sending commands to QINFIFO");
- }
-#endif
if (p->features & AHC_QUEUE_REGS)
aic_outb(p, p->qinfifonext, HNSCB_QOFF);
else
@@ -4118,7 +4082,7 @@ aic7xxx_pci_intr(struct aic7xxx_host *p)
if ( (status1 & DPR) && (aic7xxx_verbose & VERBOSE_MINOR_ERROR) )
printk(WARN_LEAD "Data Parity Error has been reported via PCI pin "
"PERR#\n", p->host_no, -1, -1, -1);
-
+
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
pci_write_config_byte(p->pdev, PCI_STATUS + 1, status1);
#else
@@ -4149,22 +4113,26 @@ aic7xxx_timer(struct aic7xxx_host *p)
unsigned long cpu_flags = 0;
struct aic7xxx_scb *scb;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
DRIVER_LOCK
#else
spin_lock_irqsave(&io_request_lock, cpu_flags);
#endif
+ p->dev_timer_active &= ~(0x01 << MAX_TARGETS);
+ if ( (p->dev_timer_active & (0x01 << p->scsi_id)) &&
+ time_after_eq(jiffies, p->dev_expires[p->scsi_id]) )
+ {
+ p->flags &= ~AHC_RESET_DELAY;
+ p->dev_timer_active &= ~(0x01 << p->scsi_id);
+ }
for(i=0; i<MAX_TARGETS; i++)
{
- if ( (p->dev_timer[i].expires) &&
- (p->dev_timer[i].expires <= jiffies) )
+ if ( (i != p->scsi_id) &&
+ (p->dev_timer_active & (0x01 << i)) &&
+ time_after_eq(jiffies, p->dev_expires[i]) )
{
- p->dev_timer[i].expires = 0;
- if ( (p->dev_timer[i].prev != NULL) ||
- (p->dev_timer[i].next != NULL) )
- {
- del_timer(&p->dev_timer[i]);
- }
+ p->dev_timer_active &= ~(0x01 << i);
+ p->dev_flags[i] &= ~(DEVICE_RESET_DELAY|DEVICE_WAS_BUSY);
p->dev_temp_queue_depth[i] = p->dev_max_queue_depth[i];
j = 0;
while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) &&
@@ -4184,9 +4152,29 @@ aic7xxx_timer(struct aic7xxx_host *p)
*/
}
}
+ else if ( p->dev_timer_active & (0x01 << i) )
+ {
+ if ( p->dev_timer_active & (0x01 << MAX_TARGETS) )
+ {
+ if ( time_after_eq(p->dev_timer.expires, p->dev_expires[i]) )
+ {
+ p->dev_timer.expires = p->dev_expires[i];
+ }
+ }
+ else
+ {
+ p->dev_timer.expires = p->dev_expires[i];
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ }
+ }
+ }
+ if ( p->dev_timer_active & (0x01 << MAX_TARGETS) )
+ {
+ add_timer(&p->dev_timer);
}
+
aic7xxx_run_waiting_queues(p);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
DRIVER_UNLOCK
#else
spin_unlock_irqrestore(&io_request_lock, cpu_flags);
@@ -4427,7 +4415,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
channel, target, lun);
#endif
- /*
+ /*
* To actually receive the message, simply turn on
* REQINIT interrupts and let our interrupt handler
* do the rest (REQINIT should already be true).
@@ -4459,8 +4447,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
(scb->tag_action) &&
!(scb->flags & SCB_MSGOUT_BITS) )
{
- if ((scb->tag_action == MSG_ORDERED_Q_TAG) &&
- (p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS))
+ if (scb->tag_action == MSG_ORDERED_Q_TAG)
{
/*
* OK...the device seems able to accept tagged commands, but
@@ -4481,8 +4468,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
aic_outb(p, MSG_IDENTIFYFLAG, MSG_OUT);
aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
}
- else if ( (scb->tag_action == MSG_SIMPLE_Q_TAG) &&
- !(p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS) )
+ else if (scb->tag_action == MSG_SIMPLE_Q_TAG)
{
unsigned char i, reset = 0;
struct aic7xxx_scb *scbp;
@@ -4656,9 +4642,9 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
scb->sense_cmd[1] = (cmd->lun << 5);
scb->sense_cmd[4] = sizeof(cmd->sense_buffer);
- scb->sg_list[0].address =
+ scb->sg_list[0].address =
cpu_to_le32(VIRT_TO_BUS(&cmd->sense_buffer[0]));
- scb->sg_list[0].length =
+ scb->sg_list[0].length =
cpu_to_le32(sizeof(cmd->sense_buffer));
/*
@@ -4668,11 +4654,11 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
/* hscb->control &= DISCENB; */
hscb->control = 0;
hscb->target_status = 0;
- hscb->SG_list_pointer =
+ hscb->SG_list_pointer =
cpu_to_le32(VIRT_TO_BUS(&scb->sg_list[0]));
hscb->data_pointer = scb->sg_list[0].address;
hscb->data_count = scb->sg_list[0].length;
- hscb->SCSI_cmd_pointer =
+ hscb->SCSI_cmd_pointer =
cpu_to_le32(VIRT_TO_BUS(&scb->sense_cmd[0]));
hscb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
hscb->residual_SG_segment_count = 0;
@@ -4693,7 +4679,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
(p->dev_flags[tindex] & DEVICE_SCANNED) &&
- !(p->wdtr_pending & target_mask) &&
+ !(p->wdtr_pending & target_mask) &&
!(p->sdtr_pending & target_mask) )
{
p->needwdtr |= (p->needwdtr_copy & target_mask);
@@ -4740,14 +4726,14 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
*/
if (cmd->next->cmnd[0] != TEST_UNIT_READY)
{
- scb->sg_list[0].address =
+ scb->sg_list[0].address =
cpu_to_le32(VIRT_TO_BUS(&cmd->next->sense_buffer[0]));
hscb->data_pointer = scb->sg_list[0].address;
}
}
#else
if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
- !(scb->flags & SCB_MSGOUT_BITS) &&
+ !(scb->flags & SCB_MSGOUT_BITS) &&
(scb->cmd->lun == 0) &&
(p->dev_flags[TARGET_INDEX(scb->cmd)] & DEVICE_SCANNED) )
{
@@ -4896,18 +4882,30 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
p->dev_active_cmds[tindex]--;
p->activescbs--;
scb->flags |= SCB_WAITINGQ | SCB_WAS_BUSY;
-
- if (p->dev_timer[tindex].expires == 0)
+
+ if ( !(p->dev_timer_active & (0x01 << tindex)) )
{
+ p->dev_timer_active |= (0x01 << tindex);
if ( p->dev_active_cmds[tindex] )
{
- p->dev_timer[tindex].expires = jiffies + (HZ * 2);
- add_timer(&p->dev_timer[tindex]);
+ p->dev_expires[tindex] = jiffies + HZ;
}
else
{
- p->dev_timer[tindex].expires = jiffies + (HZ / 2);
- add_timer(&p->dev_timer[tindex]);
+ p->dev_expires[tindex] = jiffies + (HZ / 10);
+ }
+ if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) )
+ {
+ p->dev_timer.expires = p->dev_expires[tindex];
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ add_timer(&p->dev_timer);
+ }
+ else if ( time_after_eq(p->dev_timer.expires,
+ p->dev_expires[tindex]) )
+ {
+ del_timer(&p->dev_timer);
+ p->dev_timer.expires = p->dev_expires[tindex];
+ add_timer(&p->dev_timer);
}
}
#ifdef AIC7XXX_VERBOSE_DEBUGGING
@@ -4925,12 +4923,12 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
#endif
if (queue_flag)
{
- p->dev_temp_queue_depth[tindex] =
+ p->dev_temp_queue_depth[tindex] =
p->dev_active_cmds[tindex];
if ( p->dev_last_queue_full[tindex] !=
p->dev_active_cmds[tindex] )
{
- p->dev_last_queue_full[tindex] =
+ p->dev_last_queue_full[tindex] =
p->dev_active_cmds[tindex];
p->dev_last_queue_full_count[tindex] = 0;
}
@@ -4944,15 +4942,19 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
printk(INFO_LEAD "Queue depth reduced to %d\n", p->host_no,
CTL_OF_SCB(scb), p->dev_active_cmds[tindex]);
- p->dev_max_queue_depth[tindex] =
+ p->dev_max_queue_depth[tindex] =
p->dev_active_cmds[tindex];
p->dev_last_queue_full[tindex] = 0;
p->dev_last_queue_full_count[tindex] = 0;
}
+ else
+ {
+ p->dev_flags[tindex] |= DEVICE_WAS_BUSY;
+ }
}
break;
}
-
+
default:
if (aic7xxx_verbose & VERBOSE_SEQINT)
printk(INFO_LEAD "Unexpected target status 0x%x.\n", p->host_no,
@@ -5029,7 +5031,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
/*
* We need to set an accurate goal_offset instead of
* the ridiculously high one we default to. We should
- * now know if we are wide. Plus, the WDTR code will
+ * now know if we are wide. Plus, the WDTR code will
* set our goal_offset for us as well.
*/
if (p->transinfo[tindex].goal_offset)
@@ -5077,7 +5079,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
aic7xxx_construct_sdtr(p, period,
p->transinfo[tindex].goal_offset);
}
- else
+ else
{
sti();
panic("aic7xxx: AWAITING_MSG for an SCB that does "
@@ -5115,7 +5117,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
* XXX - What do we really want to do on an overrun? The
* mid-level SCSI code should handle this, but for now,
* we'll just indicate that the command should retried.
- * If we retrieved sense info on this target, then the
+ * If we retrieved sense info on this target, then the
* base SENSE info should have been saved prior to the
* overrun error. In that case, we return DID_OK and let
* the mid level code pick up on the sense info. Otherwise
@@ -5124,7 +5126,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
if ( !(scb->flags & SCB_SENSE) )
{
printk(WARN_LEAD "Data overrun detected in %s phase, tag %d;\n",
- p->host_no, CTL_OF_SCB(scb),
+ p->host_no, CTL_OF_SCB(scb),
(lastphase == P_DATAIN) ? "Data-In" : "Data-Out", scb->hscb->tag);
printk(KERN_WARNING " %s seen Data Phase. Length=%d, NumSGs=%d.\n",
(aic_inb(p, SEQ_FLAGS) & DPHASE) ? "Have" : "Haven't",
@@ -5132,7 +5134,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
for (i = 0; i < scb->sg_count; i++)
{
printk(KERN_WARNING " sg[%d] - Addr 0x%x : Length %d\n",
- i,
+ i,
le32_to_cpu(scb->sg_list[i].address),
le32_to_cpu(scb->sg_list[i].length) );
}
@@ -5144,7 +5146,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
}
break;
-#if AIC7XXX_NOT_YET
+#if AIC7XXX_NOT_YET
case TRACEPOINT:
{
printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no, channel,
@@ -5232,7 +5234,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
unsigned int period, offset;
unsigned char maxsync, saved_offset;
struct aic7xxx_syncrate *syncrate;
-
+
if (p->msg_buf[1] != MSG_EXT_SDTR_LEN)
{
reject = TRUE;
@@ -5267,50 +5269,61 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
maxsync = AHC_SYNCRATE_FAST;
}
-
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- {
- printk(INFO_LEAD "Finished receipt of SDTR, parsing %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
- printk(INFO_LEAD "After find_syncrate() %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- aic7xxx_validate_offset(p, syncrate, &offset,
- target_scsirate & WIDEXFER);
- printk(INFO_LEAD "After validate_offset() %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
- printk(INFO_LEAD "Final values of Period/Offset as set: %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- }
- else
+ /*
+ * We might have a device that is starting negotiation with us
+ * before we can start up negotiation with it....be prepared to
+ * have a device ask for a higher speed then we want to give it
+ * in that case
+ */
+ if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) )
{
- syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
- aic7xxx_validate_offset(p, syncrate, &offset,
- target_scsirate & WIDEXFER);
- aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+ if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+ {
+ /*
+ * Not only is the device starting this up, but it also hasn't
+ * been scanned yet, so this would likely be our TUR or our
+ * INQUIRY command at scan time, so we need to use the
+ * settings from the SEEPROM if they existed. Of course, even
+ * if we didn't find a SEEPROM, we stuffed default values into
+ * the user settings anyway, so use those in all cases.
+ */
+ p->transinfo[tindex].goal_period =
+ p->transinfo[tindex].user_period;
+ p->transinfo[tindex].goal_offset =
+ p->transinfo[tindex].user_offset;
+ p->needsdtr_copy |= target_mask;
+ }
+ if ( !p->transinfo[tindex].goal_offset )
+ period = 255;
+ if ( p->transinfo[tindex].goal_period > period )
+ period = p->transinfo[tindex].goal_period;
}
-#else
+
syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
aic7xxx_validate_offset(p, syncrate, &offset,
target_scsirate & WIDEXFER);
aic7xxx_set_syncrate(p, syncrate, target, channel, period,
offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-#endif
- if (offset == 0)
+ /*
+ * Did we drop to async? If so, are we sending a reply? If we are,
+ * then we have to make sure that the reply value reflects the proper
+ * settings so we need to set the goal values according to what
+ * we need to send.
+ */
+ if ( (offset == 0) || (offset != saved_offset) ||
+ ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) )
{
- /*
- * Uhh ohh, things fell through to async....update the goal
- * items and the needsdtr_copy to reflect this...
- */
aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
- p->needsdtr_copy &= ~target_mask;
+ offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+ if ( offset == 0 )
+ {
+ p->needsdtr_copy &= ~target_mask;
+ }
}
+
/*
* Did we start this, if not, or if we went to low and had to
* go async, then send an SDTR back to the target
@@ -5325,32 +5338,6 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
}
else
{
- /*
- * Send a reply SDTR back. Even if we sent the first one, it
- * is valid to send another one out immediately to re-negotiate
- * things, and a few devices don't like getting rejects after
- * we already sent them one SDTR. Just send an SDTR for async
- * this time if need be (or for the correct params if we didn't
- * start all of this). If this is a Reject Reply type message,
- * then we've put the async settings into the goal area for
- * future reference (when we get the AWAITING_MSG interrupt).
- * If this is a case where we are responding to the target's
- * initiated SDTR, then leave our own goal and user values in
- * place (unless the device hasn't been scanned yet, in which
- * case, put the user values into the goal values so we don't
- * send out an Async message).
- */
- if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
- {
- p->transinfo[tindex].goal_width =
- p->transinfo[tindex].user_width;
- p->transinfo[tindex].goal_period =
- p->transinfo[tindex].user_period;
- p->transinfo[tindex].goal_offset =
- p->transinfo[tindex].user_offset;
- p->needwdtr_copy |= target_mask;
- p->needsdtr_copy |= target_mask;
- }
scb->flags &= ~SCB_MSGOUT_BITS;
scb->flags |= SCB_MSGOUT_SDTR;
aic_outb(p, HOST_MSG, MSG_OUT);
@@ -5362,7 +5349,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
case MSG_EXT_WDTR:
{
unsigned char bus_width;
-
+
if (p->msg_buf[1] != MSG_EXT_WDTR_LEN)
{
reject = TRUE;
@@ -5414,17 +5401,17 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
reply = TRUE;
if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
{
- /*
+ /*
* Well, we now know the WDTR and SYNC caps of this device since
* it contacted us first, mark it as such and copy the user stuff
* over to the goal stuff.
*/
- p->transinfo[tindex].goal_width =
- p->transinfo[tindex].user_width;
p->transinfo[tindex].goal_period =
p->transinfo[tindex].user_period;
p->transinfo[tindex].goal_offset =
p->transinfo[tindex].user_offset;
+ p->transinfo[tindex].goal_width =
+ p->transinfo[tindex].user_width;
p->needwdtr_copy |= target_mask;
p->needsdtr_copy |= target_mask;
}
@@ -5444,6 +5431,8 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
p->needwdtr_copy &= ~target_mask;
bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+ aic7xxx_set_width(p, target, channel, lun, bus_width,
+ AHC_TRANS_GOAL|AHC_TRANS_QUITE);
break;
}
}
@@ -5454,7 +5443,7 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
}
aic7xxx_set_width(p, target, channel, lun, bus_width,
AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-
+
/*
* By virtue of the SCSI spec, a WDTR message negates any existing
* SDTR negotiations. So, even if needsdtr isn't marked for this
@@ -5820,23 +5809,19 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat)
* Put this SCB back on the free list.
*/
aic7xxx_add_curscb_to_free_list(p);
- /*
- * XXX - If we queued an abort tag, go clean up the disconnected list.
- * We know that this particular SCB had to be the queued abort since
- * the disconnected SCB would have gotten a reconnect instead.
- * However, if this is an abort command, then DID_TIMEOUT isn't
- * appropriate, neither is returning the command for that matter.
- * What we need to do then is to let the command timeout again so
- * we get a reset since this abort just failed.
- */
#ifdef AIC7XXX_VERBOSE_DEBUGGING
if (aic7xxx_verbose > 0xffff)
printk(INFO_LEAD "Selection Timeout.\n", p->host_no, CTL_OF_SCB(scb));
#endif
- if (p->flags & SCB_QUEUED_ABORT)
+ if (scb->flags & SCB_QUEUED_ABORT)
{
+ /*
+ * We know that this particular SCB had to be the queued abort since
+ * the disconnected SCB would have gotten a reconnect instead.
+ * What we need to do then is to let the command timeout again so
+ * we get a reset since this abort just failed.
+ */
cmd->result = 0;
- scb->flags &= ~SCB_QUEUED_ABORT;
scb = NULL;
}
}
@@ -6041,7 +6026,7 @@ aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer)
temp = aic_inb(p, SCB_NEXT);
}
}
-
+
wait_scbh = aic_inb(p, WAITING_SCBH);
if ( (wait_scbh != SCB_LIST_NULL) &&
(wait_scbh >= p->scb_data->maxhscbs) )
@@ -6176,7 +6161,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
if(aic7xxx_verbose > 0xffff)
printk(INFO_LEAD "Command Complete Int.\n", p->host_no, -1, -1, -1);
#endif
-
+
/*
* Clear interrupt status before running the completion loop.
* This eliminates a race condition whereby a command could
@@ -6253,15 +6238,9 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
aic7xxx_calculate_residual(p, scb);
}
cmd->result |= (aic7xxx_error(cmd) << 16);
- if (scb->tag_action)
- p->dev_flags[TARGET_INDEX(cmd)] |=
- DEVICE_TAGGED_SUCCESS | DEVICE_SUCCESS | DEVICE_PRESENT;
- else
- p->dev_flags[TARGET_INDEX(cmd)] |=
- DEVICE_SUCCESS | DEVICE_PRESENT;
aic7xxx_done(p, scb);
break;
- }
+ }
}
}
@@ -6341,7 +6320,7 @@ do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long cpu_flags;
struct aic7xxx_host *p;
-
+
p = (struct aic7xxx_host *)dev_id;
if(!p)
return;
@@ -6384,7 +6363,7 @@ do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
* Determines the queue depth for a given device. There are two ways
* a queue depth can be obtained for a tagged queueing device. One
* way is the default queue depth which is determined by whether
- * AIC7XXX_CMDS_PER_LUN is defined. If it is defined, then it is used
+ * AIC7XXX_CMDS_PER_DEVICE is defined. If it is defined, then it is used
* as the default queue depth. Otherwise, we use either 4 or 8 as the
* default queue depth (dependent on the number of hardware SCBs).
* The other way we determine queue depth is through the use of the
@@ -6404,7 +6383,6 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
target_mask = (1 << tindex);
device->queue_depth = default_depth;
- p->dev_mid_level_queue_depth[tindex] = 3;
p->dev_temp_queue_depth[tindex] = 1;
p->dev_max_queue_depth[tindex] = 1;
p->tagenable &= ~target_mask;
@@ -6413,12 +6391,8 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
{
int tag_enabled = TRUE;
-#ifdef AIC7XXX_CMDS_PER_LUN
- default_depth = AIC7XXX_CMDS_PER_LUN;
-#else
- default_depth = 8; /* Not many SCBs to work with. */
-#endif
-
+ default_depth = AIC7XXX_CMDS_PER_DEVICE;
+
if (!(p->discenable & target_mask))
{
if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
@@ -6469,7 +6443,6 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
}
p->dev_max_queue_depth[tindex] = device->queue_depth;
p->dev_temp_queue_depth[tindex] = device->queue_depth;
- p->dev_mid_level_queue_depth[tindex] = device->queue_depth;
p->tagenable |= target_mask;
p->orderedtag |= target_mask;
device->tagged_queue = 1;
@@ -6827,7 +6800,7 @@ release_seeprom(struct aic7xxx_host *p)
* instructions
* *Note: A value of X for address is a don't care condition.
* *Note: The 93C56 and 93C66 have 8 address bits.
- *
+ *
*
* The 93C46 has a four wire interface: clock, chip select, data in, and
* data out. In order to perform one of the above functions, you need
@@ -6853,7 +6826,7 @@ release_seeprom(struct aic7xxx_host *p)
* this case, has no implied timing.
*-F*************************************************************************/
static int
-read_seeprom(struct aic7xxx_host *p, int offset,
+read_seeprom(struct aic7xxx_host *p, int offset,
unsigned short *scarray, unsigned int len, seeprom_chip_type chip)
{
int i = 0, k;
@@ -6980,7 +6953,7 @@ read_seeprom(struct aic7xxx_host *p, int offset,
}
printk("\n");
#endif
- if (checksum != scarray[len - 1])
+ if ( (checksum != scarray[len - 1]) || (checksum == 0) )
{
return (0);
}
@@ -7234,7 +7207,7 @@ configure_termination(struct aic7xxx_host *p)
aic785x_cable_detect(p, &internal50_present, &external_present,
&eprom_present);
}
-
+
if (max_target <= 8)
internal68_present = 0;
@@ -7319,7 +7292,7 @@ configure_termination(struct aic7xxx_host *p)
printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n",
p->host_no);
}
-
+
if (enableLVD_high != 0)
{
brddat |= BRDDAT4;
@@ -7464,7 +7437,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
}
p->host = host;
- p->last_reset = 0;
p->host_no = host->host_no;
host->unique_id = p->instance;
p->isr_count = 0;
@@ -7473,6 +7445,10 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
p->completeq.tail = NULL;
scbq_init(&p->scb_data->free_scbs);
scbq_init(&p->waiting_scbs);
+ init_timer(&p->dev_timer);
+ p->dev_timer.data = (unsigned long)p;
+ p->dev_timer.function = (void *)aic7xxx_timer;
+ p->dev_timer_active = 0;
for (i = 0; i < NUMBER(p->untagged_scbs); i++)
{
@@ -7491,17 +7467,12 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
p->dev_commands_sent[i] = 0;
p->dev_flags[i] = 0;
p->dev_active_cmds[i] = 0;
- p->dev_last_reset[i] = 0;
p->dev_last_queue_full[i] = 0;
p->dev_last_queue_full_count[i] = 0;
p->dev_max_queue_depth[i] = 1;
p->dev_temp_queue_depth[i] = 1;
- p->dev_mid_level_queue_depth[i] = 3;
+ p->dev_expires[i] = 0;
scbq_init(&p->delayed_scbs[i]);
- init_timer(&p->dev_timer[i]);
- p->dev_timer[i].expires = 0;
- p->dev_timer[i].data = (unsigned long)p;
- p->dev_timer[i].function = (void *)aic7xxx_timer;
}
printk(KERN_INFO "(scsi%d) <%s> found at ", p->host_no,
@@ -7551,10 +7522,9 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
}
aic_outb(p, 0, SEQ_FLAGS);
- /*
- * Detect SCB parameters and initialize the SCB array.
- */
detect_maxscb(p);
+
+
printk("%d/%d SCBs\n", p->scb_data->maxhscbs, p->scb_data->maxscbs);
if (aic7xxx_verbose & VERBOSE_PROBE2)
{
@@ -7622,7 +7592,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
unsigned char term_override;
term_override = ( (aic7xxx_override_term >> (p->instance * 4)) & 0x0f);
- p->adapter_control &=
+ p->adapter_control &=
~(CFSTERM|CFWSTERM|CFLVDSTERM|CFAUTOTERM|CFSEAUTOTERM);
if ( (p->features & AHC_ULTRA2) && (term_override & 0x0c) )
{
@@ -7673,7 +7643,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
aic_outb(p, p->scsi_id_b, SCSIID);
scsi_conf = aic_inb(p, SCSICONF + 1);
aic_outb(p, DFON | SPIOEN, SXFRCTL0);
- aic_outb(p, (scsi_conf & ENSPCHK) | term |
+ aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term |
ENSTIMER | ACTNEGEN, SXFRCTL1);
aic_outb(p, 0, SIMODE0);
aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -7690,7 +7660,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
aic_outb(p, p->scsi_id, SCSIID);
scsi_conf = aic_inb(p, SCSICONF);
aic_outb(p, DFON | SPIOEN, SXFRCTL0);
- aic_outb(p, (scsi_conf & ENSPCHK) | term |
+ aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term |
ENSTIMER | ACTNEGEN, SXFRCTL1);
aic_outb(p, 0, SIMODE0);
aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -7865,6 +7835,11 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
*/
aic7xxx_loadseq(p);
+ /*
+ * Make sure the AUTOFLUSHDIS bit is *not* set in the SBLKCTL register
+ */
+ aic_outb(p, aic_inb(p, SBLKCTL) & ~AUTOFLUSHDIS, SBLKCTL);
+
if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 )
{
aic_outb(p, ENABLE, BCTL); /* Enable the boards BUS drivers. */
@@ -7892,7 +7867,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
}
printk(KERN_INFO "(scsi%d) Resetting channel%s\n", p->host_no, channel);
}
-
+
/*
* Some of the new Ultra2 chipsets need a longer delay after a chip
* reset than just the init setup creates, so we have to delay here
@@ -7923,7 +7898,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
aic7xxx_delay(AIC7XXX_RESET_DELAY);
}
}
-
+
/*
* Register IRQ with the kernel. Only allow sharing IRQs with
* PCI devices.
@@ -8102,7 +8077,7 @@ aic7xxx_free(struct aic7xxx_host *p)
kfree(p->scb_data->scb_array[i]->kmalloc_ptr);
p->scb_data->scb_array[i] = NULL;
}
-
+
/*
* Free the SCB data area.
*/
@@ -8151,6 +8126,8 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
p->flags |= AHC_TERM_ENB_A;
if ( (p->features & AHC_TWIN) && (aic_inb(p, SCSICONF + 1) & TERM_ENB) )
p->flags |= AHC_TERM_ENB_B;
+ aic_outb(p, 0, DISC_DSB);
+ aic_outb(p, 0, DISC_DSB + 1);
break;
case (AHC_AIC7770|AHC_VL):
@@ -8169,6 +8146,21 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
scarray, p->sc_size, C46);
}
+ if (!have_seeprom)
+ {
+ p->sc_size = 128;
+ have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+ scarray, p->sc_size, p->sc_type);
+ if (!have_seeprom)
+ {
+ if(p->sc_type == C46)
+ have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+ scarray, p->sc_size, C56_66);
+ else
+ have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+ scarray, p->sc_size, C46);
+ }
+ }
break;
}
@@ -8194,13 +8186,16 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
{
printk("aic7xxx: Using leftover BIOS values.\n");
}
- if ( *sxfrctl1 & STPWEN )
+ if ( ((p->chip & ~AHC_CHIPID_MASK) == AHC_PCI) && (*sxfrctl1 & STPWEN) )
{
p->flags |= AHC_TERM_ENB_SE_LOW | AHC_TERM_ENB_SE_HIGH;
sc->adapter_control &= ~CFAUTOTERM;
sc->adapter_control |= CFSTERM | CFWSTERM | CFLVDSTERM;
}
- p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
+ if (aic7xxx_extended)
+ p->flags |= (AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
+ else
+ p->flags &= ~(AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
}
else
{
@@ -8260,7 +8255,7 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
}
p->discenable = 0;
-
+
/*
* Limit to 16 targets just in case. The 2842 for one is known to
* blow the max_targets setting, future cards might also.
@@ -8288,14 +8283,14 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
mask = (0x01 << i);
if (!have_seeprom)
{
- if(aic_inb(p, SCSISEQ) != 0)
+ if (aic_inb(p, SCSISEQ) != 0)
{
/*
* OK...the BIOS set things up and left behind the settings we need.
* Just make our sc->device_flags[i] entry match what the card has
* set for this device.
*/
- p->discenable =
+ p->discenable =
~(aic_inb(p, DISC_DSB) | (aic_inb(p, DISC_DSB + 1) << 8) );
p->ultraenb =
(aic_inb(p, ULTRA_ENB) | (aic_inb(p, ULTRA_ENB + 1) << 8) );
@@ -8348,19 +8343,30 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
}
if (p->flags & AHC_NEWEEPROM_FMT)
{
- if (sc->device_flags[i] & CFSYNCHISULTRA)
- {
- p->ultraenb |= mask;
- }
- else if (sc->device_flags[i] & CFNEWULTRAFORMAT)
+ if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) &&
+ !(p->features & AHC_ULTRA2) )
{
- if ( (sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03 )
+ /*
+ * I know of two different Ultra BIOSes that do this differently.
+ * One on the Gigabyte 6BXU mb that wants flags[i] & CFXFER to
+ * be == to 0x03 and SYNCISULTRA to be true to mean 40MByte/s
+ * while on the IBM Netfinity 5000 they want the same thing
+ * to be something else, while flags[i] & CFXFER == 0x03 and
+ * SYNCISULTRA false should be 40MByte/s. So, we set both to
+ * 40MByte/s and the lower speeds be damned. People will have
+ * to select around the conversely mapped lower speeds in order
+ * to select lower speeds on these boards.
+ */
+ if ((sc->device_flags[i] & (CFXFER)) == 0x03)
{
sc->device_flags[i] &= ~CFXFER;
sc->device_flags[i] |= CFSYNCHISULTRA;
- p->ultraenb |= mask;
}
}
+ if (sc->device_flags[i] & CFSYNCHISULTRA)
+ {
+ p->ultraenb |= mask;
+ }
}
else if (sc->adapter_control & CFULTRAEN)
{
@@ -8409,7 +8415,7 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
AHC_SYNCRATE_FAST);
p->transinfo[i].cur_period = aic7xxx_find_period(p,
aic_inb(p, TARG_SCSIRATE + i),
- (ultraenb & mask) ?
+ (ultraenb & mask) ?
AHC_SYNCRATE_ULTRA :
AHC_SYNCRATE_FAST);
}
@@ -8449,7 +8455,7 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
if (p->features & AHC_ULTRA)
p->ultraenb = aic_inb(p, ULTRA_ENB) | (aic_inb(p, ULTRA_ENB + 1) << 8);
-
+
scsi_conf = (p->scsi_id & HSCSIID);
if(have_seeprom)
@@ -8635,12 +8641,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
current_p = current_p->next;
current_p->next = temp_p;
}
- if (aic7xxx_extended)
- {
- temp_p->flags |= AHC_EXTEND_TRANS_A;
- if (temp_p->flags & AHC_MULTI_CHANNEL)
- temp_p->flags |= AHC_EXTEND_TRANS_B;
- }
switch (type)
{
@@ -8797,6 +8797,14 @@ aic7xxx_detect(Scsi_Host_Template *template)
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7855, AHC_AIC7850,
AHC_PAGESCBS, AHC_AIC7850_FE, 6,
32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7821, AHC_AIC7860,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7860_FE, 7,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_3860, AHC_AIC7860,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7860_FE, 7,
+ 32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
AHC_AIC7860_FE, 7,
@@ -8839,6 +8847,18 @@ aic7xxx_detect(Scsi_Host_Template *template)
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7884, AHC_AIC7880,
AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7885, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7886, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
+ 32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
AHC_AIC7895_FE, 19,
@@ -8847,25 +8867,70 @@ aic7xxx_detect(Scsi_Host_Template *template)
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
AHC_AIC7890_FE, 20,
32, C46 },
- {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7890_FE, 20,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
AHC_AIC7890_FE, 21,
32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7890_FE, 22,
+ 32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 22,
+ AHC_AIC7896_FE, 23,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 23,
+ AHC_AIC7896_FE, 24,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+ AHC_AIC7896_FE, 25,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7860_FE, 26,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7892_FE, 27,
+ 32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7899_FE, 28,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7899_FE, 28,
32, C56_66 },
};
unsigned short command;
unsigned int devconfig, i, oldverbose;
-#ifdef MMAPIO
- unsigned long page_offset, base;
-#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
struct pci_dev *pdev = NULL;
#else
@@ -8919,7 +8984,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
temp_p->base = pdev->base_address[0];
temp_p->mbase = pdev->base_address[1];
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at PCI %d/%d\n",
+ printk("aic7xxx: <%s> at PCI %d/%d\n",
board_names[aic_pdevs[i].board_name_index],
PCI_SLOT(temp_p->pdev->devfn),
PCI_FUNC(temp_p->pdev->devfn));
@@ -8960,7 +9025,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
temp_p->pci_bus = pci_bus;
temp_p->pci_device_fn = pci_devfn;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at PCI %d/%d\n",
+ printk("aic7xxx: <%s> at PCI %d/%d\n",
board_names[aic_pdevs[i].board_name_index],
PCI_SLOT(temp_p->pci_device_fn),
PCI_FUNC(temp_p->pci_device_fn));
@@ -9016,21 +9081,68 @@ aic7xxx_detect(Scsi_Host_Template *template)
temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK;
temp_p->unpause = INTEN;
temp_p->pause = temp_p->unpause | PAUSE;
+ if ( ((temp_p->base == 0) &&
+ (temp_p->mbase == 0)) ||
+ (temp_p->irq == 0) )
+ {
+ printk("aic7xxx: <%s> at PCI %d/%d\n",
+ board_names[aic_pdevs[i].board_name_index],
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
+ printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
+ kfree(temp_p);
+ temp_p = NULL;
+ continue;
+ }
#ifdef MMAPIO
- base = temp_p->mbase & PAGE_MASK;
- page_offset = temp_p->mbase - base;
+ {
+ unsigned long page_offset, base;
+
+ base = temp_p->mbase & PAGE_MASK;
+ page_offset = temp_p->mbase - base;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
- temp_p->maddr = ioremap_nocache(base, page_offset + 256);
+ temp_p->maddr = ioremap_nocache(base, page_offset + 256);
#else
- temp_p->maddr = vremap(base, page_offset + 256);
+ temp_p->maddr = vremap(base, page_offset + 256);
#endif
- if(temp_p->maddr)
- {
- temp_p->maddr += page_offset;
+ if(temp_p->maddr)
+ {
+ temp_p->maddr += page_offset;
+ /*
+ * We need to check the I/O with the MMAPed address. Some machines
+ * simply fail to work with MMAPed I/O and certain controllers.
+ */
+ if(aic_inb(temp_p, HCNTRL) == 0xff)
+ {
+ /*
+ * OK.....we failed our test....go back to programmed I/O
+ */
+ printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n",
+ board_names[aic_pdevs[i].board_name_index],
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
+ printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
+ "Programmed I/O.\n");
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+ iounmap((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
+#else
+ vfree((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
+#endif
+ temp_p->maddr = 0;
+ }
+ }
}
#endif
+ /*
+ * We HAVE to make sure the first pause_sequencer() and all other
+ * subsequent I/O that isn't PCI config space I/O takes place
+ * after the MMAPed I/O region is configured and tested. The
+ * problem is the PowerPC architecture that doesn't support
+ * programmed I/O at all, so we have to have the MMAP I/O set up
+ * for this pause to even work on those machines.
+ */
pause_sequencer(temp_p);
/*
@@ -9065,44 +9177,36 @@ aic7xxx_detect(Scsi_Host_Template *template)
}
/*
- * Doing a switch based upon i is really gross, but since Justin
- * changed around the chip ID stuff, we can't use that any more.
- * Since we don't scan the devices the same way as FreeBSD, we end
- * up doing this gross hack in order to avoid totally splitting
- * away from Justin's init code in ahc_pci.c
+ * We need to set the CHNL? assignments before loading the SEEPROM
+ * The 3940 and 3985 cards (original stuff, not any of the later
+ * stuff) are 7870 and 7880 class chips. The Ultra2 stuff falls
+ * under 7896 and 7897. The 7895 is in a class by itself :)
*/
- switch (i)
+ switch (temp_p->chip & AHC_CHIPID_MASK)
{
- case 7: /* 3940 */
- case 12: /* 3940-Ultra */
- switch(PCI_SLOT(temp_p->pci_device_fn))
- {
- case 5:
- temp_p->flags |= AHC_CHNLB;
- break;
- default:
- break;
- }
- break;
-
- case 8: /* 3985 */
- case 13: /* 3985-Ultra */
- switch(PCI_SLOT(temp_p->pci_device_fn))
+ case AHC_AIC7870: /* 3840 / 3985 */
+ case AHC_AIC7880: /* 3840 UW / 3985 UW */
+ if(temp_p->flags & AHC_MULTI_CHANNEL)
{
- case 8:
- temp_p->flags |= AHC_CHNLB;
- break;
- case 12:
- temp_p->flags |= AHC_CHNLC;
- break;
- default:
- break;
+ switch(PCI_SLOT(temp_p->pci_device_fn))
+ {
+ case 5:
+ temp_p->flags |= AHC_CHNLB;
+ break;
+ case 8:
+ temp_p->flags |= AHC_CHNLB;
+ break;
+ case 12:
+ temp_p->flags |= AHC_CHNLC;
+ break;
+ default:
+ break;
+ }
}
break;
- case 15:
- case 18:
- case 19:
+ case AHC_AIC7895: /* 7895 */
+ case AHC_AIC7896: /* 7896/7 */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
if (PCI_FUNC(temp_p->pdev->devfn) != 0)
{
@@ -9178,16 +9282,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
CACHETHEN | MPARCKEN | USCBSIZE32 |
CIOPARCKEN) & ~DPARCKEN, DSCOMMAND0);
- /* FALLTHROUGH */
- default:
- /*
- * We attempt to read a SEEPROM on *everything*. If we fail,
- * then we fail, but this covers things like 2910c cards that
- * now have SEEPROMs with their 7856 chipset that we would
- * otherwise ignore. They still don't have a BIOS, but they
- * have a SEEPROM that the SCSISelect utility on the Adaptec
- * diskettes can configure.
- */
aic7xxx_load_seeprom(temp_p, &sxfrctl1);
break;
case AHC_AIC7850:
@@ -9199,14 +9293,13 @@ aic7xxx_detect(Scsi_Host_Template *template)
aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
CACHETHEN | MPARCKEN) & ~DPARCKEN,
DSCOMMAND0);
+ /* FALLTHROUGH */
+ default:
aic7xxx_load_seeprom(temp_p, &sxfrctl1);
break;
case AHC_AIC7880:
/*
- * Only set the DSCOMMAND0 register if this is a Rev B.
- * chipset. For those, we also enable Ultra mode by
- * force due to brain-damage on the part of some BIOSes
- * We overload the devconfig variable here since we can.
+ * Check the rev of the chipset before we change DSCOMMAND0
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
@@ -9223,7 +9316,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
aic7xxx_load_seeprom(temp_p, &sxfrctl1);
break;
}
-
+
/*
* and then we need another switch based on the type in order to
@@ -9247,7 +9340,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
{
if ( PCI_FUNC(current_p->pci_device_fn) == 0 )
{
- temp_p->flags |=
+ temp_p->flags |=
(current_p->flags & AHC_CHANNEL_B_PRIMARY);
temp_p->flags &= ~(AHC_BIOS_ENABLED|AHC_USEDEFAULTS);
temp_p->flags |=
@@ -9270,13 +9363,10 @@ aic7xxx_detect(Scsi_Host_Template *template)
}
/*
- * We do another switch based on i so that we can exclude all
- * 3895 devices from the next option since the 3895 cards use
- * shared external SCB RAM while all other cards have dedicated
- * external SCB RAM per channel. Also exclude the 7850 and
- * 7860 based stuff since they can have garbage in the bit
- * that indicates external RAM and get some of this stuff
- * wrong as a result.
+ * We only support external SCB RAM on the 7895/6/7 chipsets.
+ * We could support it on the 7890/1 easy enough, but I don't
+ * know of any 7890/1 based cards that have it. I do know
+ * of 7895/6/7 cards that have it and they work properly.
*/
switch(temp_p->chip & AHC_CHIPID_MASK)
{
@@ -9322,7 +9412,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
/*
* Take the LED out of diagnostic mode
*/
- aic_outb(temp_p,
+ aic_outb(temp_p,
(aic_inb(temp_p, SBLKCTL) & ~(DIAGLEDEN | DIAGLEDON)),
SBLKCTL);
@@ -9340,9 +9430,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
aic_outb(temp_p, DFTHRSH_100, DSPCISTATUS);
}
- if (aic7xxx_extended)
- temp_p->flags |= AHC_EXTEND_TRANS_A;
-
if ( list_p == NULL )
{
list_p = current_p = temp_p;
@@ -9359,7 +9446,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
} /* Found an Adaptec PCI device. */
else /* Well, we found one, but we couldn't get any memory */
{
- printk("aic7xxx: Found <%s>\n",
+ printk("aic7xxx: Found <%s>\n",
board_names[aic_pdevs[i].board_name_index]);
printk(KERN_INFO "aic7xxx: Unable to allocate device memory, "
"skipping.\n");
@@ -9432,19 +9519,19 @@ aic7xxx_detect(Scsi_Host_Template *template)
vlb->next = current_p;
}
}
-
+
if (p->flags & AHC_BIOS_ENABLED)
sort_list[0] = vlb;
else
sort_list[2] = vlb;
-
+
break;
}
default: /* All PCI controllers fall through to default */
{
p = temp_p;
- if (p->flags & AHC_BIOS_ENABLED)
+ if (p->flags & AHC_BIOS_ENABLED)
pci = sort_list[1];
else
pci = sort_list[3];
@@ -9463,7 +9550,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
{
while ( (current_p != NULL) &&
( (PCI_SLOT(current_p->pci_device_fn) |
- (current_p->pci_bus << 8)) <
+ (current_p->pci_bus << 8)) <
(PCI_SLOT(temp_p->pci_device_fn) |
(temp_p->pci_bus << 8)) ) )
{
@@ -9475,7 +9562,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
{
while ( (current_p != NULL) &&
( (PCI_SLOT(current_p->pci_device_fn) |
- (current_p->pci_bus << 8)) >
+ (current_p->pci_bus << 8)) >
(PCI_SLOT(temp_p->pci_device_fn) |
(temp_p->pci_bus << 8)) ) )
{
@@ -9539,7 +9626,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
*/
{
int i;
-
+
left = found;
for (i=0; i<NUMBER(sort_list); i++)
{
@@ -9636,7 +9723,7 @@ aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p, Scsi_Cmnd *old_cmd,
* it's outside of the above if()...
*/
p->dev_wdtr_cmnd[tindex]->next = old_cmd;
- aic7xxx_queue(p->dev_wdtr_cmnd[tindex],
+ aic7xxx_queue(p->dev_wdtr_cmnd[tindex],
aic7xxx_negotiation_complete);
}
else if ( (p->needsdtr & (1<<tindex)) && !(p->sdtr_pending & (1<<tindex)) &&
@@ -9672,7 +9759,7 @@ aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p, Scsi_Cmnd *old_cmd,
* it's outside of the above if()...
*/
p->dev_sdtr_cmnd[tindex]->next = old_cmd;
- aic7xxx_queue(p->dev_sdtr_cmnd[tindex],
+ aic7xxx_queue(p->dev_sdtr_cmnd[tindex],
aic7xxx_negotiation_complete);
}
}
@@ -9691,7 +9778,7 @@ static void
aic7xxx_print_scb(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
int i;
- unsigned char *x;
+ unsigned char *x;
x = (unsigned char *)&scb->hscb->control;
@@ -9925,7 +10012,7 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
/*
* Check to see if channel was scanned.
*/
-
+
#ifdef AIC7XXX_VERBOSE_DEBUGGING
if (!(p->flags & AHC_A_SCANNED) && (cmd->channel == 0))
{
@@ -9949,7 +10036,7 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
{
printk(WARN_LEAD "Commands queued exceeds queue "
"depth, active=%d\n",
- p->host_no, CTL_OF_CMD(cmd),
+ p->host_no, CTL_OF_CMD(cmd),
p->dev_active_cmds[tindex]);
if ( p->dev_active_cmds[tindex] > 220 )
p->dev_active_cmds[tindex] = 0;
@@ -10101,7 +10188,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
return(SCSI_RESET_ERROR);
}
if (scb->hscb->tag == aic_inb(p, SCB_TAG))
- {
+ {
if ( (lastphase != P_MESGOUT) && (lastphase != P_MESGIN) )
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
@@ -10109,9 +10196,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
"message buffer\n", p->host_no, CTL_OF_SCB(scb));
scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
aic7xxx_error(scb->cmd) = DID_RESET;
- p->dev_flags[TARGET_INDEX(scb->cmd)] &=
- ~DEVICE_SUCCESS;
- p->dev_flags[TARGET_INDEX(scb->cmd)] |=
+ p->dev_flags[TARGET_INDEX(scb->cmd)] |=
BUS_DEVICE_RESET_PENDING;
/* Send the abort message to the active SCB. */
aic_outb(p, HOST_MSG, MSG_OUT);
@@ -10131,9 +10216,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
"in use\n", p->host_no, CTL_OF_SCB(scb));
scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
aic7xxx_error(scb->cmd) = DID_RESET;
- p->dev_flags[TARGET_INDEX(scb->cmd)] &=
- ~DEVICE_SUCCESS;
- p->dev_flags[TARGET_INDEX(scb->cmd)] |=
+ p->dev_flags[TARGET_INDEX(scb->cmd)] |=
BUS_DEVICE_RESET_PENDING;
return(SCSI_RESET_ERROR);
}
@@ -10160,8 +10243,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
*/
scb->hscb->control |= MK_MESSAGE;
scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
- p->dev_flags[TARGET_INDEX(scb->cmd)] &= ~DEVICE_SUCCESS;
- p->dev_flags[TARGET_INDEX(scb->cmd)] |=
+ p->dev_flags[TARGET_INDEX(scb->cmd)] |=
BUS_DEVICE_RESET_PENDING;
if (hscb_index != SCB_LIST_NULL)
{
@@ -10240,7 +10322,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
{
mask = (0x01 << i);
printk(INFO_LEAD "dev_flags=0x%x, WDTR:%c/%c/%c, SDTR:%c/%c/%c,"
- " q_depth=%d:%d:%d\n",
+ " q_depth=%d:%d\n",
p->host_no, 0, i, 0, p->dev_flags[i],
(p->wdtr_pending & mask) ? 'Y' : 'N',
(p->needwdtr & mask) ? 'Y' : 'N',
@@ -10249,7 +10331,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
(p->needsdtr & mask) ? 'Y' : 'N',
(p->needsdtr_copy & mask) ? 'Y' : 'N',
p->dev_active_cmds[i],
- p->dev_max_queue_depth[i], p->dev_mid_level_queue_depth[i]);
+ p->dev_max_queue_depth[i] );
printk(INFO_LEAD "targ_scsirate=0x%x", p->host_no, 0, i, 0,
aic_inb(p, TARG_SCSIRATE + i));
if (p->features & AHC_ULTRA2)
@@ -10283,7 +10365,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
if (p->qinfifo[qinpos] == need_tag)
found=TRUE;
printk("%d ", p->qinfifo[qinpos++]);
- }
+ }
printk("\n");
printk("Current SCB: (SCBPTR/TAG/CONTROL) %d/%d/0x%x\n", aic_inb(p, SCBPTR),
aic_inb(p, SCB_TAG), aic_inb(p, SCB_CONTROL) );
@@ -10333,7 +10415,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
aic_inb(p, SCB_PREV), aic_inb(p, SCB_NEXT));
}
}
-
+
for (i=0; i < p->scb_data->numscbs; i++)
{
@@ -10425,9 +10507,9 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
/* code needs to find it. */
cmd_next = p->completeq.head;
cmd_prev = NULL;
- while (cmd_next != NULL)
+ while (cmd_next != NULL)
{
- if (cmd_next == cmd)
+ if (cmd_next == cmd)
{
if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
printk(INFO_LEAD "Abort called for command "
@@ -10441,7 +10523,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
DRIVER_UNLOCK
return(SCSI_ABORT_NOT_RUNNING); /* It's already back as a successful
* completion */
- }
+ }
cmd_prev = cmd_next;
cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble;
}
@@ -10452,7 +10534,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
DRIVER_UNLOCK
return(SCSI_ABORT_NOT_RUNNING);
}
-
+
/* At this point we know the following:
* the SCB pointer is valid
* the command pointer passed in to us and the scb->cmd pointer match
@@ -10487,8 +10569,8 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
DRIVER_UNLOCK
return(SCSI_ABORT_SNOOZE);
}
- if ( (p->flags & (AHC_RESET_PENDING | AHC_ABORT_PENDING)) ||
- (p->dev_flags[TARGET_INDEX(scb->cmd)] &
+ if ( (p->flags & (AHC_RESET_PENDING | AHC_ABORT_PENDING)) ||
+ (p->dev_flags[TARGET_INDEX(scb->cmd)] &
BUS_DEVICE_RESET_PENDING) )
{
if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
@@ -10584,7 +10666,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
return(SCSI_ABORT_PENDING);
}
#endif
- if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
+ if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
printk(INFO_LEAD "SCB found on waiting list and "
"aborted.\n", p->host_no, CTL_OF_SCB(scb));
scbq_remove(&p->waiting_scbs, scb);
@@ -10601,7 +10683,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
*/
if ( found == 0 )
{
- if ( ((found = aic7xxx_search_qinfifo(p, cmd->target,
+ if ( ((found = aic7xxx_search_qinfifo(p, cmd->target,
cmd->channel,
cmd->lun, scb->hscb->tag, SCB_ABORT | SCB_QUEUED_FOR_DONE,
FALSE, NULL)) != 0) &&
@@ -10657,7 +10739,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
}
aic_outb(p, saved_hscbptr, SCBPTR );
}
-
+
/*
* Hmmm...completeq, QOUTFIFO, QINFIFO, WAITING_SCBH, waitingq all checked.
* OK...the sequencer's paused, interrupts are off, and we haven't found the
@@ -10674,7 +10756,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
scb->flags |= SCB_QUEUED_ABORT | SCB_ABORT | SCB_RECOVERY_SCB;
scb->hscb->control |= MK_MESSAGE;
result=aic7xxx_find_scb(p, scb);
- if ( result != SCB_LIST_NULL )
+ if ( result != SCB_LIST_NULL )
{
saved_hscbptr = aic_inb(p, SCBPTR);
aic_outb(p, result, SCBPTR);
@@ -10713,7 +10795,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
if ( found != 0 )
return(SCSI_ABORT_SUCCESS);
else
- return(SCSI_ABORT_PENDING);
+ return(SCSI_ABORT_PENDING);
}
@@ -10792,7 +10874,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
action = BUS_RESET;
}
}
- else if (scb->cmd != cmd)
+ else if (scb->cmd != cmd)
{
if (aic7xxx_verbose & VERBOSE_RESET_MID)
printk(INFO_LEAD "Reset called with recycled SCB "
@@ -10853,12 +10935,12 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
{
action = BUS_RESET;
}
- else
+ else
{
action = DEVICE_RESET;
}
}
- if ( (action & DEVICE_RESET) &&
+ if ( (action & DEVICE_RESET) &&
(p->dev_flags[tindex] & BUS_DEVICE_RESET_PENDING) )
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
@@ -10878,7 +10960,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
}
action = BUS_RESET;
}
- if ( (action & DEVICE_RESET) &&
+ if ( (action & DEVICE_RESET) &&
(p->flags & (AHC_RESET_PENDING | AHC_ABORT_PENDING)) )
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
@@ -10890,7 +10972,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
{
action = HOST_RESET;
}
- if ( ((jiffies - p->dev_last_reset[tindex]) < (HZ * 3)) &&
+ if ( (p->dev_flags[tindex] & DEVICE_RESET_DELAY) &&
!(action & (HOST_RESET | BUS_RESET)))
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
@@ -10902,23 +10984,14 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
}
action = BUS_RESET;
}
- if ( ((jiffies - p->last_reset) < (HZ * 3)) &&
- (action & (HOST_RESET | BUS_RESET)) )
+ if ( (p->flags & AHC_RESET_DELAY) &&
+ (action & (HOST_RESET | BUS_RESET)) )
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
printk(INFO_LEAD "Reset called too soon after "
"last bus reset, delaying.\n", p->host_no, CTL_OF_CMD(cmd));
action = RESET_DELAY;
}
- if ( (action & (BUS_RESET | HOST_RESET)) && (p->flags & AHC_IN_RESET)
- && ((jiffies - p->reset_start) > (2 * HZ * 3)) )
- {
- printk(KERN_ERR "(scsi%d:%d:%d:%d) Yikes!! Card must have left to go "
- "back to Adaptec!!\n", p->host_no, CTL_OF_CMD(cmd));
- unpause_sequencer(p, FALSE);
- DRIVER_UNLOCK
- return(SCSI_RESET_SNOOZE);
- }
/*
* By this point, we want to already know what we are going to do and
* only have the following code implement our course of action.
@@ -10950,15 +11023,23 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
case BUS_RESET:
case HOST_RESET:
default:
- p->reset_start = jiffies;
- p->flags |= AHC_IN_RESET;
+ p->flags |= AHC_IN_RESET | AHC_RESET_DELAY;
+ p->dev_expires[p->scsi_id] = jiffies + (3 * HZ);
+ p->dev_timer_active |= (0x01 << p->scsi_id);
+ if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) ||
+ time_after_eq(p->dev_timer.expires, p->dev_expires[p->scsi_id]) )
+ {
+ del_timer(&p->dev_timer);
+ p->dev_timer.expires = p->dev_expires[p->scsi_id];
+ add_timer(&p->dev_timer);
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ }
aic7xxx_reset_channel(p, cmd->channel, TRUE);
if ( (p->features & AHC_TWIN) && (action & HOST_RESET) )
{
aic7xxx_reset_channel(p, cmd->channel ^ 0x01, TRUE);
restart_sequencer(p);
}
- p->last_reset = jiffies;
if (action != HOST_RESET)
result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
else
@@ -10973,9 +11054,27 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
p->msg_len = 0;
}
aic7xxx_run_done_queue(p, TRUE);
+ /*
+ * If this a SCSI_RESET_SYNCHRONOUS then the command we were given is
+ * in need of being re-started, so send it on through to aic7xxx_queue
+ * and let it set until the delay is over. This keeps it from dying
+ * entirely and avoids getting a bogus dead command back through the
+ * mid-level code due to too many retries.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132)
+ if ( flags & SCSI_RESET_SYNCHRONOUS )
+ {
+ cmd->result = DID_BUS_BUSY << 16;
+ cmd->done(cmd);
+ }
+#endif
p->flags &= ~AHC_IN_RESET;
- /* We can't rely on run_waiting_queues to unpause the sequencer for
- * PCI based controllers since we use AAP */
+ /*
+ * We can't rely on run_waiting_queues to unpause the sequencer for
+ * PCI based controllers since we use AAP. NOTE: this also sets
+ * the timer for the one command we might have queued in the case
+ * of a synch reset.
+ */
aic7xxx_run_waiting_queues(p);
unpause_sequencer(p, FALSE);
DRIVER_UNLOCK
@@ -10994,16 +11093,21 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
int
aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[])
{
- int heads, sectors, cylinders;
+ int heads, sectors, cylinders, ret;
struct aic7xxx_host *p;
+ struct buffer_head *bh;
p = (struct aic7xxx_host *) disk->device->host->hostdata;
+ bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024);
+
+ if ( bh )
+ {
+ ret = scsi_partsize(bh, disk->capacity, &geom[2], &geom[0], &geom[1]);
+ brelse(bh);
+ if ( ret != -1 )
+ return(ret);
+ }
- /*
- * XXX - if I could portably find the card's configuration
- * information, then this could be autodetected instead
- * of left to a boot-time switch.
- */
heads = 64;
sectors = 32;
cylinders = disk->capacity / (heads * sectors);
@@ -11152,7 +11256,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
#ifdef CONFIG_PCI
{
unsigned char temp;
-
+
printk("PCI Dump:\n");
k=0;
for(i=0; i<cards_ns[chip].num_ranges; i++)
@@ -11204,7 +11308,7 @@ aic7xxx_print_card(struct aic7xxx_host *p)
{
unsigned short *sc1;
sc1 = (unsigned short *)&p->sc;
-
+
printk("SEEPROM dump.\n");
for(i=1; i<=32; i++)
{