summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-08-08 18:54:49 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-08-08 18:54:49 +0000
commit5514f4babeeb3af00ee0c325e3cda7a562cc3d65 (patch)
treeedd733879cab73e41324a99ca5da7bc154c4196d /drivers/scsi
parent6a9366db547e958e8c9bf8e1c13bcea6cb2bf393 (diff)
Merge with Linux 2.4.0-test6-pre4.
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-xxxx.c6
-rw-r--r--drivers/scsi/ips.c1948
-rw-r--r--drivers/scsi/ips.h651
3 files changed, 1970 insertions, 635 deletions
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index ebe4e33ba..ba6cc03cf 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -62,6 +62,8 @@
1.02.00.001 - Added support for full command packet posts through ioctls
for 3DM.
Bug fix so hot spare drives don't show up.
+ 1.02.00.002 - Fix bug with tw_setfeature() call that caused oops on some
+ systems.
*/
#include <linux/module.h>
@@ -107,7 +109,7 @@ static struct notifier_block tw_notifier = {
};
/* Globals */
-char *tw_driver_version="1.02.00.001";
+char *tw_driver_version="1.02.00.002";
TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
int tw_device_extension_count = 0;
@@ -747,7 +749,7 @@ int tw_findcards(Scsi_Host_Template *tw_host)
kfree(tw_dev);
/* Tell the firmware we support shutdown notification*/
- tw_setfeature(tw_dev, 2, 1, &c);
+ tw_setfeature(tw_dev2, 2, 1, &c);
}
if (numcards == 0)
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index e5c5ca10f..9ebe9e927 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -66,6 +66,18 @@
/* 3.60.01 - Remove bogus error check in passthru routine */
/* 3.60.02 - Make DCDB direction based on lookup table */
/* - Only allow one DCDB command to a SCSI ID at a time */
+/* 4.00.00 - Add support for ServeRAID 4 */
+/* 4.00.01 - Add support for First Failure Data Capture */
+/* 4.00.02 - Fix problem with PT DCDB with no buffer */
+/* 4.00.03 - Add alternative passthru interface */
+/* - Add ability to flash ServeRAID BIOS */
+/* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */
+/* 4.00.05 - Remove wish_block from init routine */
+/* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */
+/* 2.3.18 and later */
+/* - Sync with other changes from the 2.3 kernels */
+/* 4.00.06 - Fix timeout with initial FFDC command */
+/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@caldera.de> */
/* */
/*****************************************************************************/
@@ -78,9 +90,7 @@
*
*/
-#if defined (MODULE)
- #include <linux/module.h>
-#endif /* MODULE */
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -110,14 +120,33 @@
#include <linux/stat.h>
#include <linux/config.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,18)
#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
#include <linux/smp.h>
/*
* DRIVER_VER
*/
-#define IPS_VERSION_HIGH "3.60" /* MUST be 4 chars */
-#define IPS_VERSION_LOW ".02 " /* MUST be 4 chars */
+#define IPS_VERSION_HIGH "4.00" /* MUST be 4 chars */
+#define IPS_VERSION_LOW ".06 " /* MUST be 4 chars */
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+struct proc_dir_entry proc_scsi_ips = {
+#if !defined(PROC_SCSI_IPS)
+ 0, /* Use dynamic inode allocation */
+#else
+ PROC_SCSI_IPS,
+#endif
+ 3, "ips",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+}
+;
+#endif
#if !defined(__i386__)
#error "This driver has only been tested on the x86 platform"
@@ -132,7 +161,7 @@
#endif
#if IPS_DEBUG >= 12
- #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*ONE_SEC)
+ #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*IPS_ONE_SEC)
#elif IPS_DEBUG >= 11
#define DBG(s) printk(KERN_NOTICE s "\n")
#else
@@ -149,7 +178,7 @@ static unsigned int ips_num_controllers = 0;
static int ips_cmd_timeout = 60;
static int ips_reset_timeout = 60 * 5;
-#define MAX_ADAPTER_NAME 6
+#define MAX_ADAPTER_NAME 7
static char ips_adapter_name[][30] = {
"ServeRAID",
@@ -157,64 +186,65 @@ static char ips_adapter_name[][30] = {
"ServeRAID on motherboard",
"ServeRAID on motherboard",
"ServeRAID 3H",
- "ServeRAID 3L"
+ "ServeRAID 3L",
+ "ServeRAID 4H"
};
/*
* Direction table
*/
static char ips_command_direction[] = {
-IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
-IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK,
-IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
-IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT,
-IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT,
-IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN,
-IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK,
-IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
-IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE,
-IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
-IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT,
-IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE,
-IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK,
-IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE,
-IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT,
-IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE,
-IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
-IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK
+IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
+IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK,
+IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT,
+IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT,
+IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN,
+IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
+IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT,
+IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE,
+IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK,
+IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE,
+IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT,
+IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE,
+IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK
};
/*
@@ -232,8 +262,8 @@ const char * ips_info(struct Scsi_Host *);
void do_ipsintr(int, void *, struct pt_regs *);
static int ips_hainit(ips_ha_t *);
static int ips_map_status(ips_scb_t *, ips_stat_t *);
-static int ips_send(ips_ha_t *, ips_scb_t *, scb_callback);
-static int ips_send_wait(ips_ha_t *, ips_scb_t *, int);
+static int ips_send(ips_ha_t *, ips_scb_t *, ips_scb_callback);
+static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
static int ips_chkstatus(ips_ha_t *);
static int ips_online(ips_ha_t *, ips_scb_t *);
@@ -247,14 +277,14 @@ static int ips_statupd(ips_ha_t *);
static int ips_issue(ips_ha_t *, ips_scb_t *);
static int ips_isintr(ips_ha_t *);
static int ips_wait(ips_ha_t *, int, int);
-static int ips_write_driver_status(ips_ha_t *);
-static int ips_read_adapter_status(ips_ha_t *);
-static int ips_read_subsystem_parameters(ips_ha_t *);
-static int ips_read_config(ips_ha_t *);
-static int ips_clear_adapter(ips_ha_t *);
-static int ips_readwrite_page5(ips_ha_t *, int);
+static int ips_write_driver_status(ips_ha_t *, int);
+static int ips_read_adapter_status(ips_ha_t *, int);
+static int ips_read_subsystem_parameters(ips_ha_t *, int);
+static int ips_read_config(ips_ha_t *, int);
+static int ips_clear_adapter(ips_ha_t *, int);
+static int ips_readwrite_page5(ips_ha_t *, int, int);
static void ips_intr(ips_ha_t *);
-static void ips_next(ips_ha_t *);
+static void ips_next(ips_ha_t *, int);
static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
static void ipsintr_done(ips_ha_t *, struct ips_scb *);
static void ips_done(ips_ha_t *, ips_scb_t *);
@@ -262,6 +292,9 @@ static void ips_free(ips_ha_t *);
static void ips_init_scb(ips_ha_t *, ips_scb_t *);
static void ips_freescb(ips_ha_t *, ips_scb_t *);
static void ips_statinit(ips_ha_t *);
+static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
+static void ips_ffdc_reset(ips_ha_t *, int);
+static void ips_ffdc_time(ips_ha_t *, int);
static ips_scb_t * ips_getscb(ips_ha_t *);
static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
@@ -271,17 +304,26 @@ static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *);
static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static inline void ips_putq_copp_head(ips_copp_queue_t *, ips_copp_wait_item_t *);
+static inline void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *);
+static inline ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *);
+static inline ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t *);
+static int ips_erase_bios(ips_ha_t *);
+static int ips_program_bios(ips_ha_t *, char *, int);
+static int ips_verify_bios(ips_ha_t *, char *, int);
#ifndef NO_IPS_CMDLINE
static int ips_is_passthru(Scsi_Cmnd *);
static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *);
static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+static int ips_newusrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
#endif
int ips_proc_info(char *, char **, off_t, int, int, int);
static int ips_host_info(ips_ha_t *, char *, off_t, int);
-static void copy_mem_info(INFOSTR *, char *, int);
-static int copy_info(INFOSTR *, char *, ...);
+static void copy_mem_info(IPS_INFOSTR *, char *, int);
+static int copy_info(IPS_INFOSTR *, char *, ...);
/*--------------------------------------------------------------------------*/
/* Exported Functions */
@@ -295,6 +337,8 @@ static int copy_info(INFOSTR *, char *, ...);
/* */
/* Detect and initialize the driver */
/* */
+/* NOTE: this routine is called under the io_request_lock spinlock */
+/* */
/****************************************************************************/
int
ips_detect(Scsi_Host_Template *SHT) {
@@ -302,6 +346,7 @@ ips_detect(Scsi_Host_Template *SHT) {
ips_ha_t *ha;
u32 io_addr;
u16 planer;
+ u8 revision_id;
u8 bus;
u8 func;
u8 irq;
@@ -311,7 +356,11 @@ ips_detect(Scsi_Host_Template *SHT) {
DBG("ips_detect");
SHT->proc_info = ips_proc_info;
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
+ SHT->proc_dir = &proc_scsi_ips;
+#else
SHT->proc_name = "ips";
+#endif
#if defined(CONFIG_PCI)
@@ -325,26 +374,27 @@ ips_detect(Scsi_Host_Template *SHT) {
if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev)))
break;
+
if (pci_enable_device(dev))
- break;
+ break;
+
/* stuff that we get in dev */
irq = dev->irq;
bus = dev->bus->number;
func = dev->devfn;
io_addr = pci_resource_start(dev, 0);
+
+ /* check I/O address */
+ if (pci_resource_flags(dev, 0) & IORESOURCE_MEM)
+ continue;
/* get planer status */
if (pci_read_config_word(dev, 0x04, &planer)) {
printk(KERN_WARNING "(%s%d) can't get planer status.\n",
ips_name, index);
-
continue;
}
- /* check I/O address */
- if (pci_resource_flags(dev, 0) & IORESOURCE_MEM)
- continue;
-
/* check to see if an onboard planer controller is disabled */
if (!(planer & 0x000C)) {
@@ -361,6 +411,14 @@ ips_detect(Scsi_Host_Template *SHT) {
ips_name, index, bus, func, irq, io_addr);
#endif
+ /* get the revision ID */
+ if (pci_read_config_byte(dev, 0x08, &revision_id)) {
+ printk(KERN_WARNING "(%s%d) can't get revision id.\n",
+ ips_name, index);
+
+ continue;
+ }
+
/* found a controller */
sh = scsi_register(SHT, sizeof(ips_ha_t));
@@ -371,19 +429,23 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
- ha = HA(sh);
+ ha = IPS_HA(sh);
memset(ha, 0, sizeof(ips_ha_t));
/* Initialize spin lock */
spin_lock_init(&ha->scb_lock);
spin_lock_init(&ha->copp_lock);
+ spin_lock_init(&ha->ips_lock);
+ spin_lock_init(&ha->copp_waitlist.lock);
+ spin_lock_init(&ha->scb_waitlist.lock);
+ spin_lock_init(&ha->scb_activelist.lock);
ips_sh[ips_num_controllers] = sh;
ips_ha[ips_num_controllers] = ha;
ips_num_controllers++;
ha->active = 1;
- ha->enq = kmalloc(sizeof(ENQCMD), GFP_KERNEL|GFP_DMA);
+ ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_KERNEL|GFP_DMA);
if (!ha->enq) {
printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n",
@@ -394,7 +456,7 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
- ha->adapt = kmalloc(sizeof(ADAPTER_AREA), GFP_KERNEL|GFP_DMA);
+ ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_KERNEL|GFP_DMA);
if (!ha->adapt) {
printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n",
@@ -405,7 +467,7 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
- ha->conf = kmalloc(sizeof(CONFCMD), GFP_KERNEL|GFP_DMA);
+ ha->conf = kmalloc(sizeof(IPS_CONF), GFP_KERNEL|GFP_DMA);
if (!ha->conf) {
printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n",
@@ -416,7 +478,7 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
- ha->nvram = kmalloc(sizeof(NVRAM_PAGE5), GFP_KERNEL|GFP_DMA);
+ ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_KERNEL|GFP_DMA);
if (!ha->nvram) {
printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n",
@@ -427,7 +489,7 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
- ha->subsys = kmalloc(sizeof(SUBSYS_PARAM), GFP_KERNEL|GFP_DMA);
+ ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_KERNEL|GFP_DMA);
if (!ha->subsys) {
printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n",
@@ -438,7 +500,7 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
- ha->dummy = kmalloc(sizeof(BASIC_IO_CMD), GFP_KERNEL|GFP_DMA);
+ ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_KERNEL|GFP_DMA);
if (!ha->dummy) {
printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n",
@@ -449,6 +511,17 @@ ips_detect(Scsi_Host_Template *SHT) {
continue;
}
+ ha->ioctl_data = kmalloc(IPS_IOCTL_SIZE, GFP_KERNEL|GFP_DMA);
+ ha->ioctl_datasize = IPS_IOCTL_SIZE;
+ if (!ha->ioctl_data) {
+ printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data - skipping controller\n",
+ ips_name, index);
+
+ ha->active = 0;
+
+ continue;
+ }
+
/* Store away needed values for later use */
sh->io_port = io_addr;
sh->n_io_port = 255;
@@ -465,6 +538,7 @@ ips_detect(Scsi_Host_Template *SHT) {
ha->io_addr = io_addr;
ha->irq = irq;
ha->host_num = index;
+ ha->revision_id = revision_id;
/* install the interrupt handler */
if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
@@ -491,7 +565,7 @@ ips_detect(Scsi_Host_Template *SHT) {
}
memset(ha->scbs, 0, sizeof(ips_scb_t));
- ha->scbs->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA);
+ ha->scbs->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_KERNEL|GFP_DMA);
if (!ha->scbs->sg_list) {
/* couldn't allocate a temp SCB S/G list */
printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
@@ -569,7 +643,7 @@ ips_release(struct Scsi_Host *sh) {
panic("(%s) release, invalid Scsi_Host pointer.\n",
ips_name);
- ha = HA(sh);
+ ha = IPS_HA(sh);
if (!ha)
return (FALSE);
@@ -580,11 +654,11 @@ ips_release(struct Scsi_Host *sh) {
ips_init_scb(ha, scb);
scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = FLUSH_CACHE;
+ scb->cdb[0] = IPS_CMD_FLUSH;
- scb->cmd.flush_cache.op_code = FLUSH_CACHE;
+ scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.flush_cache.state = NORM_STATE;
+ scb->cmd.flush_cache.state = IPS_NORM_STATE;
scb->cmd.flush_cache.reserved = 0;
scb->cmd.flush_cache.reserved2 = 0;
scb->cmd.flush_cache.reserved3 = 0;
@@ -593,7 +667,7 @@ ips_release(struct Scsi_Host *sh) {
printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num);
/* send command */
- if (ips_send_wait(ha, scb, ips_cmd_timeout) == IPS_FAILURE)
+ if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE)
printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num);
printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num);
@@ -625,6 +699,7 @@ ips_release(struct Scsi_Host *sh) {
int
ips_eh_abort(Scsi_Cmnd *SC) {
ips_ha_t *ha;
+ ips_copp_wait_item_t *item;
DBG("ips_eh_abort");
@@ -651,9 +726,23 @@ ips_eh_abort(Scsi_Cmnd *SC) {
if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
return (FAILED);
+ /* See if the command is on the copp queue */
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
+ item = ha->copp_waitlist.head;
+ while ((item) && (item->scsi_cmd != SC))
+ item = item->next;
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
+
+ if (item) {
+ /* Found it */
+ ips_removeq_copp(&ha->copp_waitlist, item);
+ clear_bit(IPS_IN_ABORT, &ha->flags);
+
+ return (SUCCESS);
+ }
+
/* See if the command is on the wait queue */
- if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
- ips_removeq_wait(&ha->copp_waitlist, SC)) {
+ if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
/* command not sent yet */
clear_bit(IPS_IN_ABORT, &ha->flags);
@@ -678,6 +767,7 @@ ips_eh_abort(Scsi_Cmnd *SC) {
int
ips_abort(Scsi_Cmnd *SC) {
ips_ha_t *ha;
+ ips_copp_wait_item_t *item;
DBG("ips_abort");
@@ -704,9 +794,23 @@ ips_abort(Scsi_Cmnd *SC) {
if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
return (SCSI_ABORT_SNOOZE);
+ /* See if the command is on the copp queue */
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
+ item = ha->copp_waitlist.head;
+ while ((item) && (item->scsi_cmd != SC))
+ item = item->next;
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
+
+ if (item) {
+ /* Found it */
+ ips_removeq_copp(&ha->copp_waitlist, item);
+ clear_bit(IPS_IN_ABORT, &ha->flags);
+
+ return (SCSI_ABORT_PENDING);
+ }
+
/* See if the command is on the wait queue */
- if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
- ips_removeq_wait(&ha->copp_waitlist, SC)) {
+ if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
/* command not sent yet */
clear_bit(IPS_IN_ABORT, &ha->flags);
@@ -727,11 +831,15 @@ ips_abort(Scsi_Cmnd *SC) {
/* */
/* Reset the controller (with new eh error code) */
/* */
+/* NOTE: this routine is called under the io_request_lock spinlock */
+/* */
/****************************************************************************/
int
ips_eh_reset(Scsi_Cmnd *SC) {
- ips_ha_t *ha;
- ips_scb_t *scb;
+ u32 cpu_flags;
+ ips_ha_t *ha;
+ ips_scb_t *scb;
+ ips_copp_wait_item_t *item;
DBG("ips_eh_reset");
@@ -765,11 +873,25 @@ ips_eh_reset(Scsi_Cmnd *SC) {
if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
return (FAILED);
- /* See if the command is on the waiting queue */
- if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
- ips_removeq_wait(&ha->copp_waitlist, SC)) {
+ /* See if the command is on the copp queue */
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
+ item = ha->copp_waitlist.head;
+ while ((item) && (item->scsi_cmd != SC))
+ item = item->next;
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
+
+ if (item) {
+ /* Found it */
+ ips_removeq_copp(&ha->copp_waitlist, item);
+ clear_bit(IPS_IN_RESET, &ha->flags);
+
+ return (SUCCESS);
+ }
+
+ /* See if the command is on the wait queue */
+ if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
/* command not sent yet */
- clear_bit(IPS_IN_ABORT, &ha->flags);
+ clear_bit(IPS_IN_RESET, &ha->flags);
return (SUCCESS);
}
@@ -784,25 +906,39 @@ ips_eh_reset(Scsi_Cmnd *SC) {
return (FAILED);
}
- if (!ips_clear_adapter(ha)) {
+ if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
clear_bit(IPS_IN_RESET, &ha->flags);
return (FAILED);
}
+ /* FFDC */
+ if (ha->subsys->param[3] & 0x300000) {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ IPS_HA_LOCK(cpu_flags);
+ ha->last_ffdc = tv.tv_sec;
+ ha->reset_count++;
+ IPS_HA_UNLOCK(cpu_flags);
+ ips_ffdc_reset(ha, IPS_INTR_IORL);
+ }
+
/* Now fail all of the active commands */
#if IPS_DEBUG >= 1
printk(KERN_WARNING "(%s%d) Failing active commands\n",
ips_name, ha->host_num);
#endif
while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
- scb->scsi_cmd->result = DID_RESET << 16;
+ scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
ips_freescb(ha, scb);
}
/* Reset the number of active IOCTLs */
+ IPS_HA_LOCK(cpu_flags);
ha->num_ioctl = 0;
+ IPS_HA_UNLOCK(cpu_flags);
clear_bit(IPS_IN_RESET, &ha->flags);
@@ -814,7 +950,7 @@ ips_eh_reset(Scsi_Cmnd *SC) {
* handler wants to do this and since
* interrupts are turned off here....
*/
- ips_next(ha);
+ ips_next(ha, IPS_INTR_IORL);
}
return (SUCCESS);
@@ -831,11 +967,15 @@ ips_eh_reset(Scsi_Cmnd *SC) {
/* */
/* Reset the controller */
/* */
+/* NOTE: this routine is called under the io_request_lock spinlock */
+/* */
/****************************************************************************/
int
ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
- ips_ha_t *ha;
- ips_scb_t *scb;
+ u32 cpu_flags;
+ ips_ha_t *ha;
+ ips_scb_t *scb;
+ ips_copp_wait_item_t *item;
DBG("ips_reset");
@@ -869,11 +1009,25 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
return (SCSI_RESET_SNOOZE);
- /* See if the command is on the waiting queue */
- if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
- ips_removeq_wait(&ha->copp_waitlist, SC)) {
+ /* See if the command is on the copp queue */
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
+ item = ha->copp_waitlist.head;
+ while ((item) && (item->scsi_cmd != SC))
+ item = item->next;
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
+
+ if (item) {
+ /* Found it */
+ ips_removeq_copp(&ha->copp_waitlist, item);
+ clear_bit(IPS_IN_RESET, &ha->flags);
+
+ return (SCSI_RESET_SNOOZE);
+ }
+
+ /* See if the command is on the wait queue */
+ if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
/* command not sent yet */
- clear_bit(IPS_IN_ABORT, &ha->flags);
+ clear_bit(IPS_IN_RESET, &ha->flags);
return (SCSI_RESET_SNOOZE);
}
@@ -885,25 +1039,39 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
return (SCSI_RESET_ERROR);
}
- if (!ips_clear_adapter(ha)) {
+ if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
clear_bit(IPS_IN_RESET, &ha->flags);
return (SCSI_RESET_ERROR);
}
+ /* FFDC */
+ if (ha->subsys->param[3] & 0x300000) {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ IPS_HA_LOCK(cpu_flags);
+ ha->last_ffdc = tv.tv_sec;
+ ha->reset_count++;
+ IPS_HA_UNLOCK(cpu_flags);
+ ips_ffdc_reset(ha, IPS_INTR_IORL);
+ }
+
/* Now fail all of the active commands */
#if IPS_DEBUG >= 1
printk(KERN_WARNING "(%s%d) Failing active commands\n",
ips_name, ha->host_num);
#endif
while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
- scb->scsi_cmd->result = DID_RESET << 16;
+ scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
ips_freescb(ha, scb);
}
/* Reset the number of active IOCTLs */
+ IPS_HA_LOCK(cpu_flags);
ha->num_ioctl = 0;
+ IPS_HA_UNLOCK(cpu_flags);
clear_bit(IPS_IN_RESET, &ha->flags);
@@ -915,7 +1083,7 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
* handler wants to do this and since
* interrupts are turned off here....
*/
- ips_next(ha);
+ ips_next(ha, IPS_INTR_IORL);
}
return (SCSI_RESET_SUCCESS);
@@ -932,10 +1100,15 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
/* */
/* Send a command to the controller */
/* */
+/* NOTE: */
+/* Linux obtains io_request_lock before calling this function */
+/* */
/****************************************************************************/
int
ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
ips_ha_t *ha;
+ u32 cpu_flags;
+ DECLARE_MUTEX_LOCKED(sem);
DBG("ips_queue");
@@ -949,19 +1122,27 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
#ifndef NO_IPS_CMDLINE
if (ips_is_passthru(SC)) {
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
SC->result = DID_BUS_BUSY << 16;
done(SC);
return (0);
+ } else {
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
}
} else {
#endif
+ IPS_QUEUE_LOCK(&ha->scb_waitlist);
if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
+ IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
SC->result = DID_BUS_BUSY << 16;
done(SC);
return (0);
+ } else {
+ IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
}
#ifndef NO_IPS_CMDLINE
@@ -978,21 +1159,82 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
SC->target,
SC->lun);
#if IPS_DEBUG >= 11
- MDELAY(2*ONE_SEC);
+ MDELAY(2*IPS_ONE_SEC);
#endif
#endif
#ifndef NO_IPS_CMDLINE
- if (ips_is_passthru(SC))
- ips_putq_wait_tail(&ha->copp_waitlist, SC);
+ if (ips_is_passthru(SC)) {
+ ips_copp_wait_item_t *scratch;
+
+ /* allocate space for the scribble */
+ scratch = kmalloc(sizeof(ips_copp_wait_item_t), GFP_KERNEL);
+
+ if (!scratch) {
+ SC->result = DID_ERROR << 16;
+ done(SC);
+
+ return (0);
+ }
+
+ scratch->scsi_cmd = SC;
+ scratch->sem = &sem;
+ scratch->next = NULL;
+
+ ips_putq_copp_tail(&ha->copp_waitlist, scratch);
+ }
else
#endif
ips_putq_wait_tail(&ha->scb_waitlist, SC);
+ IPS_HA_LOCK(cpu_flags);
if ((!test_bit(IPS_IN_INTR, &ha->flags)) &&
(!test_bit(IPS_IN_ABORT, &ha->flags)) &&
- (!test_bit(IPS_IN_RESET, &ha->flags)))
- ips_next(ha);
+ (!test_bit(IPS_IN_RESET, &ha->flags))) {
+ IPS_HA_UNLOCK(cpu_flags);
+ ips_next(ha, IPS_INTR_IORL);
+ } else {
+ IPS_HA_UNLOCK(cpu_flags);
+ }
+
+ /*
+ * If this request was a new style IOCTL wait
+ * for it to finish.
+ *
+ * NOTE: we relinquished the lock above so this should
+ * not cause contention problems
+ */
+ if (ips_is_passthru(SC) && SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
+ char *user_area;
+ char *kern_area;
+ u32 datasize;
+
+ /* free io_request_lock */
+ spin_unlock_irq(&io_request_lock);
+
+ /* wait for the command to finish */
+ down(&sem);
+
+ /* reobtain the lock */
+ spin_lock_irq(&io_request_lock);
+
+ /* command finished -- copy back */
+ user_area = *((char **) &SC->cmnd[4]);
+ kern_area = ha->ioctl_data;
+ datasize = *((u32 *) &SC->cmnd[8]);
+
+ if (copy_to_user(user_area, kern_area, datasize) > 0) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) passthru failed - unable to copy out user data\n",
+ ips_name, ha->host_num);
+#endif
+
+ SC->result = DID_ERROR << 16;
+ SC->scsi_done(SC);
+ } else {
+ SC->scsi_done(SC);
+ }
+ }
return (0);
}
@@ -1024,17 +1266,17 @@ ips_biosparam(Disk *disk, kdev_t dev, int geom[]) {
if (!ha->active)
return (0);
- if (!ips_read_adapter_status(ha))
+ if (!ips_read_adapter_status(ha, IPS_INTR_ON))
/* ?!?! Enquiry command failed */
return (0);
if ((disk->capacity > 0x400000) &&
((ha->enq->ucMiscFlag & 0x8) == 0)) {
- heads = NORM_MODE_HEADS;
- sectors = NORM_MODE_SECTORS;
+ heads = IPS_NORM_HEADS;
+ sectors = IPS_NORM_SECTORS;
} else {
- heads = COMP_MODE_HEADS;
- sectors = COMP_MODE_SECTORS;
+ heads = IPS_COMP_HEADS;
+ sectors = IPS_COMP_SECTORS;
}
cylinders = disk->capacity / (heads * sectors);
@@ -1063,7 +1305,7 @@ ips_biosparam(Disk *disk, kdev_t dev, int geom[]) {
void
do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
ips_ha_t *ha;
- unsigned int cpu_flags;
+ u32 cpu_flags;
DBG("do_ipsintr");
@@ -1096,6 +1338,9 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
clear_bit(IPS_IN_INTR, &ha->flags);
spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+
+ /* start the next command */
+ ips_next(ha, IPS_INTR_ON);
}
/****************************************************************************/
@@ -1114,6 +1359,7 @@ ips_intr(ips_ha_t *ha) {
ips_stat_t *sp;
ips_scb_t *scb;
int status;
+ u32 cpu_flags;
DBG("ips_intr");
@@ -1123,6 +1369,7 @@ ips_intr(ips_ha_t *ha) {
if (!ha->active)
return;
+ IPS_HA_LOCK(cpu_flags);
while (ips_isintr(ha)) {
sp = &ha->sp;
@@ -1139,10 +1386,12 @@ ips_intr(ips_ha_t *ha) {
* use the callback function to finish things up
* NOTE: interrupts are OFF for this
*/
+ IPS_HA_UNLOCK(cpu_flags);
(*scb->callback) (ha, scb);
+ IPS_HA_LOCK(cpu_flags);
}
- clear_bit(IPS_IN_INTR, &ha->flags);
+ IPS_HA_UNLOCK(cpu_flags);
}
/****************************************************************************/
@@ -1162,7 +1411,7 @@ ips_info(struct Scsi_Host *SH) {
DBG("ips_info");
- ha = HA(SH);
+ ha = IPS_HA(SH);
if (!ha)
return (NULL);
@@ -1250,10 +1499,10 @@ ips_is_passthru(Scsi_Cmnd *SC) {
if (!SC)
return (0);
- if ((SC->channel == 0) &&
+ if (((SC->cmnd[0] == IPS_IOCTL_COMMAND) || (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND)) &&
+ (SC->channel == 0) &&
(SC->target == IPS_ADAPTER_ID) &&
(SC->lun == 0) &&
- (SC->cmnd[0] == 0x0d) &&
(SC->request_bufflen) &&
(!SC->use_sg) &&
(((char *) SC->request_buffer)[0] == 'C') &&
@@ -1268,7 +1517,7 @@ ips_is_passthru(Scsi_Cmnd *SC) {
/****************************************************************************/
/* */
-/* Routine Name: ips_is_passthru */
+/* Routine Name: ips_make_passthru */
/* */
/* Routine Description: */
/* */
@@ -1315,17 +1564,23 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
}
pt = (ips_passthru_t *) SC->request_buffer;
- scb->scsi_cmd = SC;
-
- if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) {
- /* wrong size */
-#if IPS_DEBUG_PT >= 1
- printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
- ips_name, ha->host_num);
-#endif
- return (IPS_FAILURE);
- }
+ /*
+ * Some notes about the passthru interface used
+ *
+ * IF the scsi op_code == 0x0d then we assume
+ * that the data came along with/goes with the
+ * packet we received from the sg driver. In this
+ * case the CmdBSize field of the pt structure is
+ * used for the size of the buffer.
+ *
+ * IF the scsi op_code == 0x81 then we assume that
+ * we will need our own buffer and we will copy the
+ * data to/from the user buffer passed in the scsi
+ * command. The data address resides at offset 4
+ * in the scsi command. The length of the data resides
+ * at offset 8 in the scsi command.
+ */
switch (pt->CoppCmd) {
case IPS_NUMCTRLS:
@@ -1334,19 +1589,128 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
SC->result = DID_OK << 16;
return (IPS_SUCCESS_IMM);
+
case IPS_CTRLINFO:
memcpy(SC->request_buffer + sizeof(ips_passthru_t),
ha, sizeof(ips_ha_t));
SC->result = DID_OK << 16;
return (IPS_SUCCESS_IMM);
- case COPPUSRCMD:
- if (ips_usrcmd(ha, pt, scb))
- return (IPS_SUCCESS);
- else
- return (IPS_FAILURE);
+
+ case IPS_COPPUSRCMD:
+ case IPS_COPPIOCCMD:
+ if (SC->cmnd[0] == IPS_IOCTL_COMMAND) {
+ if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) {
+ /* wrong size */
+ #if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
+ ips_name, ha->host_num);
+ #endif
+
+ return (IPS_FAILURE);
+ }
+
+ if (ips_usrcmd(ha, pt, scb))
+ return (IPS_SUCCESS);
+ else
+ return (IPS_FAILURE);
+ } else if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
+ if (SC->request_bufflen < (sizeof(ips_passthru_t))) {
+ /* wrong size */
+ #if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
+ ips_name, ha->host_num);
+ #endif
+
+ return (IPS_FAILURE);
+ }
+
+ if (ips_newusrcmd(ha, pt, scb))
+ return (IPS_SUCCESS);
+ else
+ return (IPS_FAILURE);
+ }
+
break;
- }
+
+ case IPS_FLASHBIOS:
+ /* we must use the new interface */
+ if (SC->cmnd[0] != IPS_IOCTL_NEW_COMMAND)
+ return (IPS_FAILURE);
+
+ /* don't flash the BIOS on future cards */
+ if (ha->revision_id > IPS_REVID_TROMBONE64) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) flash bios failed - unsupported controller\n",
+ ips_name, ha->host_num);
+#endif
+ return (IPS_FAILURE);
+ }
+
+ /* copy in the size/buffer ptr from the scsi command */
+ memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4);
+ memcpy(&pt->CmdBSize, &SC->cmnd[8], 4);
+
+ /* must have a buffer */
+ if ((!pt->CmdBSize) || (!pt->CmdBuffer))
+ return (IPS_FAILURE);
+
+ /* make sure buffer is big enough */
+ if (pt->CmdBSize > ha->ioctl_datasize) {
+ void *bigger_struct;
+
+ /* try to allocate a bigger struct */
+ bigger_struct = kmalloc(pt->CmdBSize, GFP_KERNEL|GFP_DMA);
+ if (bigger_struct) {
+ /* free the old memory */
+ kfree(ha->ioctl_data);
+
+ /* use the new memory */
+ ha->ioctl_data = bigger_struct;
+ ha->ioctl_datasize = pt->CmdBSize;
+ } else
+ return (IPS_FAILURE);
+ }
+
+ /* copy in the buffer */
+ if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) flash bios failed - unable to copy user buffer\n",
+ ips_name, ha->host_num);
+#endif
+
+ return (IPS_FAILURE);
+ }
+
+ if (ips_erase_bios(ha)) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) flash bios failed - unable to erase flash\n",
+ ips_name, ha->host_num);
+#endif
+
+ return (IPS_FAILURE);
+ }
+
+ if (ips_program_bios(ha, ha->ioctl_data, pt->CmdBSize)) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) flash bios failed - unable to program flash\n",
+ ips_name, ha->host_num);
+#endif
+
+ return (IPS_FAILURE);
+ }
+
+ if (ips_verify_bios(ha, ha->ioctl_data, pt->CmdBSize)) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) flash bios failed - unable to verify flash\n",
+ ips_name, ha->host_num);
+#endif
+
+ return (IPS_FAILURE);
+ }
+
+ return (IPS_SUCCESS_IMM);
+ } /* end switch */
return (IPS_FAILURE);
}
@@ -1362,7 +1726,7 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
/****************************************************************************/
static int
ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
- SG_LIST *sg_list;
+ IPS_SG_LIST *sg_list;
DBG("ips_usrcmd");
@@ -1373,15 +1737,15 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
sg_list = scb->sg_list;
/* copy in the CP */
- memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IOCTL_INFO));
- memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(DCDB_TABLE));
+ memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD));
+ memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE));
/* FIX stuff that might be wrong */
scb->sg_list = sg_list;
scb->scb_busaddr = VIRT_TO_BUS(scb);
- scb->bus = 0;
- scb->target_id = 0;
- scb->lun = 0;
+ scb->bus = scb->scsi_cmd->channel;
+ scb->target_id = scb->scsi_cmd->target;
+ scb->lun = scb->scsi_cmd->lun;
scb->sg_len = 0;
scb->data_len = 0;
scb->flags = 0;
@@ -1391,9 +1755,9 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
/* we don't support DCDB/READ/WRITE Scatter Gather */
- if ((scb->cmd.basic_io.op_code == READ_SCATTER_GATHER) ||
- (scb->cmd.basic_io.op_code == WRITE_SCATTER_GATHER) ||
- (scb->cmd.basic_io.op_code == DIRECT_CDB_SCATTER_GATHER))
+ if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
+ (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
+ (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
return (0);
if (pt->CmdBSize) {
@@ -1402,13 +1766,129 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
scb->data_busaddr = 0L;
}
+ if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
+ scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
+
if (pt->CmdBSize) {
- if (scb->cmd.dcdb.op_code == DIRECT_CDB) {
- scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
+ if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
scb->dcdb.buffer_pointer = scb->data_busaddr;
- } else {
+ else
scb->cmd.basic_io.sg_addr = scb->data_busaddr;
+ }
+
+ /* set timeouts */
+ if (pt->TimeOut) {
+ scb->timeout = pt->TimeOut;
+
+ if (pt->TimeOut <= 10)
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
+ else if (pt->TimeOut <= 60)
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
+ else
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
+ }
+
+ /* assume success */
+ scb->scsi_cmd->result = DID_OK << 16;
+
+ /* success */
+ return (1);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_newusrcmd */
+/* */
+/* Routine Description: */
+/* */
+/* Process a user command and make it ready to send */
+/* */
+/****************************************************************************/
+static int
+ips_newusrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
+ IPS_SG_LIST *sg_list;
+ char *user_area;
+ char *kern_area;
+ u32 datasize;
+
+ DBG("ips_usrcmd");
+
+ if ((!scb) || (!pt) || (!ha))
+ return (0);
+
+ /* Save the S/G list pointer so it doesn't get clobbered */
+ sg_list = scb->sg_list;
+
+ /* copy in the CP */
+ memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD));
+ memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE));
+
+ /* FIX stuff that might be wrong */
+ scb->sg_list = sg_list;
+ scb->scb_busaddr = VIRT_TO_BUS(scb);
+ scb->bus = scb->scsi_cmd->channel;
+ scb->target_id = scb->scsi_cmd->target;
+ scb->lun = scb->scsi_cmd->lun;
+ scb->sg_len = 0;
+ scb->data_len = 0;
+ scb->flags = 0;
+ scb->op_code = 0;
+ scb->callback = ipsintr_done;
+ scb->timeout = ips_cmd_timeout;
+ scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+
+ /* we don't support DCDB/READ/WRITE Scatter Gather */
+ if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
+ (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
+ (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
+ return (0);
+
+ if (pt->CmdBSize) {
+ if (pt->CmdBSize > ha->ioctl_datasize) {
+ void *bigger_struct;
+
+ /* try to allocate a bigger struct */
+ bigger_struct = kmalloc(pt->CmdBSize, GFP_KERNEL|GFP_DMA);
+ if (bigger_struct) {
+ /* free the old memory */
+ kfree(ha->ioctl_data);
+
+ /* use the new memory */
+ ha->ioctl_data = bigger_struct;
+ ha->ioctl_datasize = pt->CmdBSize;
+ } else
+ return (0);
+
}
+
+ scb->data_busaddr = VIRT_TO_BUS(ha->ioctl_data);
+
+ /* Attempt to copy in the data */
+ user_area = *((char **) &scb->scsi_cmd->cmnd[4]);
+ kern_area = ha->ioctl_data;
+ datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]);
+
+ if (copy_from_user(kern_area, user_area, datasize) > 0) {
+#if IPS_DEBUG_PT >= 1
+ printk(KERN_NOTICE "(%s%d) passthru failed - unable to copy in user data\n",
+ ips_name, ha->host_num);
+#endif
+
+ return (0);
+ }
+
+ } else {
+ scb->data_busaddr = 0L;
+ }
+
+ if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
+ scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
+
+ if (pt->CmdBSize) {
+ if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
+ scb->dcdb.buffer_pointer = scb->data_busaddr;
+ else
+ scb->cmd.basic_io.sg_addr = scb->data_busaddr;
}
/* set timeouts */
@@ -1416,15 +1896,15 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
scb->timeout = pt->TimeOut;
if (pt->TimeOut <= 10)
- scb->dcdb.cmd_attribute |= TIMEOUT_10;
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
else if (pt->TimeOut <= 60)
- scb->dcdb.cmd_attribute |= TIMEOUT_60;
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
else
- scb->dcdb.cmd_attribute |= TIMEOUT_20M;
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
}
- /* assume error */
- scb->scsi_cmd->result = DID_ERROR << 16;
+ /* assume success */
+ scb->scsi_cmd->result = DID_OK << 16;
/* success */
return (1);
@@ -1440,7 +1920,7 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
/* */
/****************************************************************************/
static void
-ips_cleanup_passthru(ips_scb_t *scb) {
+ips_cleanup_passthru(ips_ha_t *ha, ips_scb_t *scb) {
ips_passthru_t *pt;
DBG("ips_cleanup_passthru");
@@ -1456,10 +1936,15 @@ ips_cleanup_passthru(ips_scb_t *scb) {
pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer;
/* Copy data back to the user */
- pt->BasicStatus = scb->basic_status;
- pt->ExtendedStatus = scb->extended_status;
-
- scb->scsi_cmd->result = DID_OK << 16;
+ if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_COMMAND) {
+ /* Copy data back to the user */
+ pt->BasicStatus = scb->basic_status;
+ pt->ExtendedStatus = scb->extended_status;
+ } else {
+ pt->BasicStatus = scb->basic_status;
+ pt->ExtendedStatus = scb->extended_status;
+ up(scb->sem);
+ }
}
#endif
@@ -1475,7 +1960,7 @@ ips_cleanup_passthru(ips_scb_t *scb) {
/****************************************************************************/
static int
ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
- INFOSTR info;
+ IPS_INFOSTR info;
DBG("ips_host_info");
@@ -1486,7 +1971,7 @@ ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
- if ((ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) &&
+ if ((ha->nvram->signature == IPS_NVRAM_P5_SIG) &&
(ha->nvram->adapter_type != 0))
copy_info(&info, "\tController Type : %s\n", ips_adapter_name[ha->ad_type-1]);
else
@@ -1495,7 +1980,7 @@ ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
copy_info(&info, "\tIO port address : 0x%lx\n", ha->io_addr);
copy_info(&info, "\tIRQ number : %d\n", ha->irq);
- if (ha->nvram->signature == NVRAM_PAGE5_SIGNATURE)
+ if (ha->nvram->signature == IPS_NVRAM_P5_SIG)
copy_info(&info, "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
ha->nvram->bios_high[0], ha->nvram->bios_high[1],
ha->nvram->bios_high[2], ha->nvram->bios_high[3],
@@ -1541,11 +2026,11 @@ ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
/* */
/* Routine Description: */
/* */
-/* Copy data into an INFOSTR structure */
+/* Copy data into an IPS_INFOSTR structure */
/* */
/****************************************************************************/
static void
-copy_mem_info(INFOSTR *info, char *data, int len) {
+copy_mem_info(IPS_INFOSTR *info, char *data, int len) {
DBG("copy_mem_info");
if (info->pos + len > info->length)
@@ -1577,7 +2062,7 @@ copy_mem_info(INFOSTR *info, char *data, int len) {
/* */
/****************************************************************************/
static int
-copy_info(INFOSTR *info, char *fmt, ...) {
+copy_info(IPS_INFOSTR *info, char *fmt, ...) {
va_list args;
char buf[81];
int len;
@@ -1616,11 +2101,15 @@ ips_hainit(ips_ha_t *ha) {
/* initialize status queue */
ips_statinit(ha);
+ ha->reset_count = 1;
+
/* Setup HBA ID's */
- if (!ips_read_config(ha)) {
+ if (!ips_read_config(ha, IPS_INTR_IORL)) {
#ifndef NO_IPS_RESET
+ ha->reset_count++;
+
/* Try to reset the controller and try again */
if (!ips_reset_adapter(ha)) {
printk(KERN_WARNING "(%s%d) unable to reset controller.\n",
@@ -1629,7 +2118,7 @@ ips_hainit(ips_ha_t *ha) {
return (0);
}
- if (!ips_clear_adapter(ha)) {
+ if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
printk(KERN_WARNING "(%s%d) unable to initialize controller.\n",
ips_name, ha->host_num);
@@ -1638,7 +2127,7 @@ ips_hainit(ips_ha_t *ha) {
#endif
- if (!ips_read_config(ha)) {
+ if (!ips_read_config(ha, IPS_INTR_IORL)) {
printk(KERN_WARNING "(%s%d) unable to read config from controller.\n",
ips_name, ha->host_num);
@@ -1647,31 +2136,40 @@ ips_hainit(ips_ha_t *ha) {
} /* end if */
/* write driver version */
- if (!ips_write_driver_status(ha)) {
+ if (!ips_write_driver_status(ha, IPS_INTR_IORL)) {
printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n",
ips_name, ha->host_num);
return (0);
}
- if (!ips_read_adapter_status(ha)) {
+ if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) {
printk(KERN_WARNING "(%s%d) unable to read controller status.\n",
ips_name, ha->host_num);
return (0);
}
- if (!ips_read_subsystem_parameters(ha)) {
+ if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) {
printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n",
ips_name, ha->host_num);
return (0);
}
+ /* FFDC */
+ if (ha->subsys->param[3] & 0x300000) {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ ha->last_ffdc = tv.tv_sec;
+ ips_ffdc_reset(ha, IPS_INTR_IORL);
+ }
+
/* set limits on SID, LUN, BUS */
- ha->ntargets = MAX_TARGETS + 1;
+ ha->ntargets = IPS_MAX_TARGETS + 1;
ha->nlun = 1;
- ha->nbus = (ha->enq->ucMaxPhysicalDevices / MAX_TARGETS);
+ ha->nbus = (ha->enq->ucMaxPhysicalDevices / IPS_MAX_TARGETS);
switch (ha->conf->logical_drive[0].ucStripeSize) {
case 4:
@@ -1736,21 +2234,55 @@ ips_hainit(ips_ha_t *ha) {
/* */
/* Take the next command off the queue and send it to the controller */
/* */
-/* ASSUMED to be called from within a lock */
-/* */
/****************************************************************************/
static void
-ips_next(ips_ha_t *ha) {
- ips_scb_t *scb;
- Scsi_Cmnd *SC;
- Scsi_Cmnd *p;
- int ret;
+ips_next(ips_ha_t *ha, int intr) {
+ ips_scb_t *scb;
+ Scsi_Cmnd *SC;
+ Scsi_Cmnd *p;
+ ips_copp_wait_item_t *item;
+ int ret;
+ int intr_status;
+ u32 cpu_flags;
+ u32 cpu_flags2;
DBG("ips_next");
if (!ha)
return ;
+ /*
+ * Block access to the queue function so
+ * this command won't time out
+ */
+ if (intr == IPS_INTR_ON) {
+ spin_lock_irqsave(&io_request_lock, cpu_flags2);
+ intr_status = IPS_INTR_IORL;
+ } else {
+ intr_status = intr;
+
+ /* Quiet the compiler */
+ cpu_flags2 = 0;
+ }
+
+ if (ha->subsys->param[3] & 0x300000) {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+
+ IPS_HA_LOCK(cpu_flags);
+ if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
+ ha->last_ffdc = tv.tv_sec;
+ IPS_HA_UNLOCK(cpu_flags);
+ ips_ffdc_time(ha, intr_status);
+ } else {
+ IPS_HA_UNLOCK(cpu_flags);
+ }
+ }
+
+ if (intr == IPS_INTR_ON)
+ spin_unlock_irqrestore(&io_request_lock, cpu_flags2);
+
#ifndef NO_IPS_CMDLINE
/*
* Send passthru commands
@@ -1759,32 +2291,50 @@ ips_next(ips_ha_t *ha) {
* since we limit the number that can be active
* on the card at any one time
*/
+ IPS_HA_LOCK(cpu_flags);
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
(ha->copp_waitlist.head) &&
(scb = ips_getscb(ha))) {
- SC = ips_removeq_wait_head(&ha->copp_waitlist);
- ret = ips_make_passthru(ha, SC, scb);
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
+ IPS_HA_UNLOCK(cpu_flags);
+ item = ips_removeq_copp_head(&ha->copp_waitlist);
+ scb->scsi_cmd = item->scsi_cmd;
+ scb->sem = item->sem;
+ kfree(item);
+
+ ret = ips_make_passthru(ha, scb->scsi_cmd, scb);
switch (ret) {
case IPS_FAILURE:
if (scb->scsi_cmd) {
+ /* raise the semaphore */
+ if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
+ up(scb->sem);
+
scb->scsi_cmd->result = DID_ERROR << 16;
- scb->scsi_cmd->scsi_done(scb->scsi_cmd);
}
ips_freescb(ha, scb);
break;
case IPS_SUCCESS_IMM:
- if (scb->scsi_cmd)
- scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+ if (scb->scsi_cmd) {
+ /* raise the semaphore */
+ if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
+ up(scb->sem);
+ }
+
ips_freescb(ha, scb);
break;
default:
break;
} /* end case */
- if (ret != IPS_SUCCESS)
+ if (ret != IPS_SUCCESS) {
+ IPS_HA_LOCK(cpu_flags);
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
continue;
+ }
ret = ips_send_cmd(ha, scb);
@@ -1796,27 +2346,43 @@ ips_next(ips_ha_t *ha) {
switch(ret) {
case IPS_FAILURE:
if (scb->scsi_cmd) {
+ /* raise the semaphore */
+ if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
+ up(scb->sem);
+
scb->scsi_cmd->result = DID_ERROR << 16;
- scb->scsi_cmd->scsi_done(scb->scsi_cmd);
}
ips_freescb(ha, scb);
break;
case IPS_SUCCESS_IMM:
- if (scb->scsi_cmd)
- scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+ if (scb->scsi_cmd) {
+ /* raise the semaphore */
+ if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
+ up(scb->sem);
+ }
+
ips_freescb(ha, scb);
break;
default:
break;
} /* end case */
+
+ IPS_HA_LOCK(cpu_flags);
+ IPS_QUEUE_LOCK(&ha->copp_waitlist);
}
+
+ IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
+ IPS_HA_UNLOCK(cpu_flags);
#endif
/*
* Send "Normal" I/O commands
*/
+ IPS_HA_LOCK(cpu_flags);
+ IPS_QUEUE_LOCK(&ha->scb_waitlist);
p = ha->scb_waitlist.head;
+ IPS_QUEUE_UNLOCK(&ha->scb_waitlist);
while ((p) && (scb = ips_getscb(ha))) {
if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) {
ips_freescb(ha, scb);
@@ -1824,6 +2390,8 @@ ips_next(ips_ha_t *ha) {
continue;
}
+ IPS_HA_UNLOCK(cpu_flags);
+
SC = ips_removeq_wait(&ha->scb_waitlist, p);
SC->result = DID_OK;
@@ -1904,7 +2472,7 @@ ips_next(ips_ha_t *ha) {
scb->dcdb.transfer_length = 0;
if (scb->data_len >= IPS_MAX_XFER) {
- scb->dcdb.cmd_attribute |= TRANSFER_64K;
+ scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
scb->dcdb.transfer_length = 0;
}
@@ -1939,7 +2507,11 @@ ips_next(ips_ha_t *ha) {
} /* end case */
p = (Scsi_Cmnd *) p->host_scribble;
+
+ IPS_HA_LOCK(cpu_flags);
} /* end while */
+
+ IPS_HA_UNLOCK(cpu_flags);
}
/****************************************************************************/
@@ -1960,6 +2532,8 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
if (!item)
return ;
+ IPS_QUEUE_LOCK(queue);
+
item->q_next = queue->head;
queue->head = item;
@@ -1967,6 +2541,8 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
queue->tail = item;
queue->count++;
+
+ IPS_QUEUE_UNLOCK(queue);
}
/****************************************************************************/
@@ -1987,6 +2563,8 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
if (!item)
return ;
+ IPS_QUEUE_LOCK(queue);
+
item->q_next = NULL;
if (queue->tail)
@@ -1998,6 +2576,8 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
queue->head = item;
queue->count++;
+
+ IPS_QUEUE_UNLOCK(queue);
}
/****************************************************************************/
@@ -2017,10 +2597,15 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) {
DBG("ips_removeq_scb_head");
+ IPS_QUEUE_LOCK(queue);
+
item = queue->head;
- if (!item)
+ if (!item) {
+ IPS_QUEUE_UNLOCK(queue);
+
return (NULL);
+ }
queue->head = item->q_next;
item->q_next = NULL;
@@ -2030,6 +2615,8 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) {
queue->count--;
+ IPS_QUEUE_UNLOCK(queue);
+
return (item);
}
@@ -2053,8 +2640,13 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
if (!item)
return (NULL);
- if (item == queue->head)
+ IPS_QUEUE_LOCK(queue);
+
+ if (item == queue->head) {
+ IPS_QUEUE_UNLOCK(queue);
+
return (ips_removeq_scb_head(queue));
+ }
p = queue->head;
@@ -2071,9 +2663,13 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
item->q_next = NULL;
queue->count--;
+ IPS_QUEUE_UNLOCK(queue);
+
return (item);
}
+ IPS_QUEUE_UNLOCK(queue);
+
return (NULL);
}
@@ -2095,6 +2691,8 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
if (!item)
return ;
+ IPS_QUEUE_LOCK(queue);
+
item->host_scribble = (char *) queue->head;
queue->head = item;
@@ -2102,6 +2700,8 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
queue->tail = item;
queue->count++;
+
+ IPS_QUEUE_UNLOCK(queue);
}
/****************************************************************************/
@@ -2122,6 +2722,8 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
if (!item)
return ;
+ IPS_QUEUE_LOCK(queue);
+
item->host_scribble = NULL;
if (queue->tail)
@@ -2133,6 +2735,8 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
queue->head = item;
queue->count++;
+
+ IPS_QUEUE_UNLOCK(queue);
}
/****************************************************************************/
@@ -2152,10 +2756,15 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) {
DBG("ips_removeq_wait_head");
+ IPS_QUEUE_LOCK(queue);
+
item = queue->head;
- if (!item)
+ if (!item) {
+ IPS_QUEUE_UNLOCK(queue);
+
return (NULL);
+ }
queue->head = (Scsi_Cmnd *) item->host_scribble;
item->host_scribble = NULL;
@@ -2165,6 +2774,8 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) {
queue->count--;
+ IPS_QUEUE_UNLOCK(queue);
+
return (item);
}
@@ -2188,8 +2799,13 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
if (!item)
return (NULL);
- if (item == queue->head)
+ IPS_QUEUE_LOCK(queue);
+
+ if (item == queue->head) {
+ IPS_QUEUE_UNLOCK(queue);
+
return (ips_removeq_wait_head(queue));
+ }
p = queue->head;
@@ -2206,9 +2822,172 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
item->host_scribble = NULL;
queue->count--;
+ IPS_QUEUE_UNLOCK(queue);
+
return (item);
}
+ IPS_QUEUE_UNLOCK(queue);
+
+ return (NULL);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_putq_copp_head */
+/* */
+/* Routine Description: */
+/* */
+/* Add an item to the head of the queue */
+/* */
+/* ASSUMED to be called from within a lock */
+/* */
+/****************************************************************************/
+static inline void
+ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
+ DBG("ips_putq_copp_head");
+
+ if (!item)
+ return ;
+
+ IPS_QUEUE_LOCK(queue);
+
+ item->next = queue->head;
+ queue->head = item;
+
+ if (!queue->tail)
+ queue->tail = item;
+
+ queue->count++;
+
+ IPS_QUEUE_UNLOCK(queue);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_putq_copp_tail */
+/* */
+/* Routine Description: */
+/* */
+/* Add an item to the tail of the queue */
+/* */
+/* ASSUMED to be called from within a lock */
+/* */
+/****************************************************************************/
+static inline void
+ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
+ DBG("ips_putq_copp_tail");
+
+ if (!item)
+ return ;
+
+ IPS_QUEUE_LOCK(queue);
+
+ item->next = NULL;
+
+ if (queue->tail)
+ queue->tail->next = item;
+
+ queue->tail = item;
+
+ if (!queue->head)
+ queue->head = item;
+
+ queue->count++;
+
+ IPS_QUEUE_UNLOCK(queue);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_removeq_copp_head */
+/* */
+/* Routine Description: */
+/* */
+/* Remove the head of the queue */
+/* */
+/* ASSUMED to be called from within a lock */
+/* */
+/****************************************************************************/
+static inline ips_copp_wait_item_t *
+ips_removeq_copp_head(ips_copp_queue_t *queue) {
+ ips_copp_wait_item_t *item;
+
+ DBG("ips_removeq_copp_head");
+
+ IPS_QUEUE_LOCK(queue);
+
+ item = queue->head;
+
+ if (!item) {
+ IPS_QUEUE_UNLOCK(queue);
+
+ return (NULL);
+ }
+
+ queue->head = item->next;
+ item->next = NULL;
+
+ if (queue->tail == item)
+ queue->tail = NULL;
+
+ queue->count--;
+
+ IPS_QUEUE_UNLOCK(queue);
+
+ return (item);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_removeq_copp */
+/* */
+/* Routine Description: */
+/* */
+/* Remove an item from a queue */
+/* */
+/* ASSUMED to be called from within a lock */
+/* */
+/****************************************************************************/
+static inline ips_copp_wait_item_t *
+ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) {
+ ips_copp_wait_item_t *p;
+
+ DBG("ips_removeq_copp");
+
+ if (!item)
+ return (NULL);
+
+ IPS_QUEUE_LOCK(queue);
+
+ if (item == queue->head) {
+ IPS_QUEUE_UNLOCK(queue);
+
+ return (ips_removeq_copp_head(queue));
+ }
+
+ p = queue->head;
+
+ while ((p) && (item != p->next))
+ p = p->next;
+
+ if (p) {
+ /* found a match */
+ p->next = item->next;
+
+ if (!item->next)
+ queue->tail = p;
+
+ item->next = NULL;
+ queue->count--;
+
+ IPS_QUEUE_UNLOCK(queue);
+
+ return (item);
+ }
+
+ IPS_QUEUE_UNLOCK(queue);
+
return (NULL);
}
@@ -2269,6 +3048,7 @@ ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) {
static void
ips_done(ips_ha_t *ha, ips_scb_t *scb) {
int ret;
+ u32 cpu_flags;
DBG("ips_done");
@@ -2277,8 +3057,10 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) {
#ifndef NO_IPS_CMDLINE
if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
- ips_cleanup_passthru(scb);
+ ips_cleanup_passthru(ha, scb);
+ IPS_HA_LOCK(cpu_flags);
ha->num_ioctl--;
+ IPS_HA_UNLOCK(cpu_flags);
} else {
#endif
/*
@@ -2342,11 +3124,12 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) {
scb->dcdb.cmd_attribute |=
ips_command_direction[scb->scsi_cmd->cmnd[0]];
-
+
if (!scb->dcdb.cmd_attribute & 0x3)
scb->dcdb.transfer_length = 0;
+
if (scb->data_len >= IPS_MAX_XFER) {
- scb->dcdb.cmd_attribute |= TRANSFER_64K;
+ scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
scb->dcdb.transfer_length = 0;
}
@@ -2379,15 +3162,17 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) {
} /* end if passthru */
#endif
- if (scb->bus)
+ if (scb->bus) {
+ IPS_HA_LOCK(cpu_flags);
ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
+ IPS_HA_UNLOCK(cpu_flags);
+ }
/* call back to SCSI layer */
- scb->scsi_cmd->scsi_done(scb->scsi_cmd);
- ips_freescb(ha, scb);
+ if (scb->scsi_cmd && scb->scsi_cmd->cmnd[0] != IPS_IOCTL_NEW_COMMAND)
+ scb->scsi_cmd->scsi_done(scb->scsi_cmd);
- /* do the next command */
- ips_next(ha);
+ ips_freescb(ha, scb);
}
/****************************************************************************/
@@ -2426,19 +3211,19 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
/* default driver error */
errcode = DID_ERROR;
- switch (scb->basic_status & GSC_STATUS_MASK) {
- case CMD_TIMEOUT:
+ switch (scb->basic_status & IPS_GSC_STATUS_MASK) {
+ case IPS_CMD_TIMEOUT:
errcode = DID_TIME_OUT;
break;
- case INVAL_OPCO:
- case INVAL_CMD_BLK:
- case INVAL_PARM_BLK:
- case LOG_DRV_ERROR:
- case CMD_CMPLT_WERROR:
+ case IPS_INVAL_OPCO:
+ case IPS_INVAL_CMD_BLK:
+ case IPS_INVAL_PARM_BLK:
+ case IPS_LD_ERROR:
+ case IPS_CMD_CMPLT_WERROR:
break;
- case PHYS_DRV_ERROR:
+ case IPS_PHYS_DRV_ERROR:
/*
* For physical drive errors that
* are not on a logical drive should
@@ -2449,14 +3234,14 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
errcode = DID_OK;
switch (scb->extended_status) {
- case SELECTION_TIMEOUT:
+ case IPS_ERR_SEL_TO:
if (scb->bus) {
scb->scsi_cmd->result |= DID_TIME_OUT << 16;
return (0);
}
break;
- case DATA_OVER_UNDER_RUN:
+ case IPS_ERR_OU_RUN:
if ((scb->bus) && (scb->dcdb.transfer_length < scb->data_len)) {
if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
@@ -2475,7 +3260,7 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
}
break;
- case EXT_RECOVERY:
+ case IPS_ERR_RECOVERY:
/* don't fail recovered errors */
if (scb->bus) {
scb->scsi_cmd->result |= DID_OK << 16;
@@ -2484,12 +3269,12 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
}
break;
- case EXT_HOST_RESET:
- case EXT_DEVICE_RESET:
+ case IPS_ERR_HOST_RESET:
+ case IPS_ERR_DEV_RESET:
errcode = DID_RESET;
break;
- case EXT_CHECK_CONDITION:
+ case IPS_ERR_CKCOND:
break;
} /* end switch */
} /* end switch */
@@ -2509,7 +3294,7 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
/* */
/****************************************************************************/
static int
-ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) {
+ips_send(ips_ha_t *ha, ips_scb_t *scb, ips_scb_callback callback) {
int ret;
DBG("ips_send");
@@ -2531,7 +3316,7 @@ ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) {
/* */
/****************************************************************************/
static int
-ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) {
+ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout, int intr) {
int ret;
DBG("ips_send_wait");
@@ -2544,7 +3329,7 @@ ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) {
if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
return (ret);
- ret = ips_wait(ha, timeout, IPS_INTR_OFF);
+ ret = ips_wait(ha, timeout, intr);
return (ret);
}
@@ -2610,9 +3395,9 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
scb->scsi_cmd->result = DID_OK << 16;
if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
- IPS_INQUIRYDATA inq;
+ IPS_INQ_DATA inq;
- memset(&inq, 0, sizeof(IPS_INQUIRYDATA));
+ memset(&inq, 0, sizeof(IPS_INQ_DATA));
inq.DeviceType = TYPE_PROCESSOR;
inq.DeviceTypeQualifier = 0;
@@ -2628,7 +3413,7 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
scb->scsi_cmd->result = DID_OK << 16;
}
} else {
- scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO;
+ scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
scb->cmd.logical_info.reserved = 0;
@@ -2647,10 +3432,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
case WRITE_6:
if (!scb->sg_len) {
scb->cmd.basic_io.op_code =
- (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_READ : IPS_WRITE;
+ (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ : IPS_CMD_WRITE;
} else {
scb->cmd.basic_io.op_code =
- (scb->scsi_cmd->cmnd[0] == READ_6) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER;
+ (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG;
}
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
@@ -2678,10 +3463,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
case WRITE_10:
if (!scb->sg_len) {
scb->cmd.basic_io.op_code =
- (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_READ : IPS_WRITE;
+ (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ : IPS_CMD_WRITE;
} else {
scb->cmd.basic_io.op_code =
- (scb->scsi_cmd->cmnd[0] == READ_10) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER;
+ (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG;
}
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
@@ -2719,14 +3504,14 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
break;
case MODE_SENSE:
- scb->cmd.basic_io.op_code = ENQUIRY;
+ scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
ret = IPS_SUCCESS;
break;
case READ_CAPACITY:
- scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO;
+ scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
scb->cmd.logical_info.reserved = 0;
@@ -2758,9 +3543,9 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
/* setup DCDB */
if (scb->bus > 0) {
if (!scb->sg_len)
- scb->cmd.dcdb.op_code = DIRECT_CDB;
+ scb->cmd.dcdb.op_code = IPS_CMD_DCDB;
else
- scb->cmd.dcdb.op_code = DIRECT_CDB_SCATTER_GATHER;
+ scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG;
ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id);
scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
@@ -2770,19 +3555,19 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
scb->cmd.dcdb.reserved3 = 0;
scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id;
- scb->dcdb.cmd_attribute |= DISCONNECT_ALLOWED;
+ scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED;
if (scb->timeout) {
if (scb->timeout <= 10)
- scb->dcdb.cmd_attribute |= TIMEOUT_10;
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
else if (scb->timeout <= 60)
- scb->dcdb.cmd_attribute |= TIMEOUT_60;
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
else
- scb->dcdb.cmd_attribute |= TIMEOUT_20M;
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
}
- if (!(scb->dcdb.cmd_attribute & TIMEOUT_20M))
- scb->dcdb.cmd_attribute |= TIMEOUT_20M;
+ if (!(scb->dcdb.cmd_attribute & IPS_TIMEOUT20M))
+ scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
scb->dcdb.sense_length = sizeof(scb->scsi_cmd->sense_buffer);
scb->dcdb.buffer_pointer = scb->data_busaddr;
@@ -2817,7 +3602,7 @@ ips_chkstatus(ips_ha_t *ha) {
command_id = ips_statupd(ha);
- if (command_id > (MAX_CMDS-1)) {
+ if (command_id > (IPS_MAX_CMDS-1)) {
printk(KERN_NOTICE "(%s%d) invalid command id received: %d\n",
ips_name, ha->host_num, command_id);
@@ -2827,7 +3612,7 @@ ips_chkstatus(ips_ha_t *ha) {
scb = &ha->scbs[command_id];
sp->scb_addr = (u32) scb;
sp->residue_len = 0;
- scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & BASIC_STATUS_MASK;
+ scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & IPS_BASIC_STATUS_MASK;
scb->extended_status = ext_status = ha->adapt->p_status_tail->extended_status;
/* Remove the item from the active queue */
@@ -2846,12 +3631,12 @@ ips_chkstatus(ips_ha_t *ha) {
errcode = DID_OK;
ret = 0;
- if (((basic_status & GSC_STATUS_MASK) == SSUCCESS) ||
- ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR)) {
+ if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) ||
+ ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) {
if (scb->bus == 0) {
#if IPS_DEBUG >= 1
- if ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR) {
+ if ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR) {
printk(KERN_NOTICE "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n",
ips_name, ha->host_num,
scb->cmd.basic_io.op_code, basic_status, ext_status);
@@ -2975,20 +3760,20 @@ static int
ips_online(ips_ha_t *ha, ips_scb_t *scb) {
DBG("ips_online");
- if (scb->target_id >= MAX_LOGICAL_DRIVES)
+ if (scb->target_id >= IPS_MAX_LD)
return (0);
- if ((scb->basic_status & GSC_STATUS_MASK) > 1) {
+ if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) {
memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info));
return (0);
}
if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != OFF_LINE &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != FREE &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != CRS &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != SYS)
+ ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE &&
+ ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_FREE &&
+ ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_CRS &&
+ ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_SYS)
return (1);
else
return (0);
@@ -3005,11 +3790,11 @@ ips_online(ips_ha_t *ha, ips_scb_t *scb) {
/****************************************************************************/
static int
ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
- IPS_INQUIRYDATA inq;
+ IPS_INQ_DATA inq;
DBG("ips_inquiry");
- memset(&inq, 0, sizeof(IPS_INQUIRYDATA));
+ memset(&inq, 0, sizeof(IPS_INQ_DATA));
inq.DeviceType = TYPE_DISK;
inq.DeviceTypeQualifier = 0;
@@ -3036,14 +3821,14 @@ ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
/****************************************************************************/
static int
ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) {
- CAPACITY_T *cap;
+ IPS_CAPACITY *cap;
DBG("ips_rdcap");
if (scb->scsi_cmd->bufflen < 8)
return (0);
- cap = (CAPACITY_T *) scb->scsi_cmd->request_buffer;
+ cap = (IPS_CAPACITY *) scb->scsi_cmd->request_buffer;
cap->lba = htonl(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count - 1);
cap->len = htonl((u32) IPS_BLKSIZE);
@@ -3071,11 +3856,11 @@ ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
if (ha->enq->ulDriveSize[scb->target_id] > 0x400000 &&
(ha->enq->ucMiscFlag & 0x8) == 0) {
- heads = NORM_MODE_HEADS;
- sectors = NORM_MODE_SECTORS;
+ heads = IPS_NORM_HEADS;
+ sectors = IPS_NORM_SECTORS;
} else {
- heads = COMP_MODE_HEADS;
- sectors = COMP_MODE_SECTORS;
+ heads = IPS_COMP_HEADS;
+ sectors = IPS_COMP_SECTORS;
}
cylinders = ha->enq->ulDriveSize[scb->target_id] / (heads * sectors);
@@ -3088,7 +3873,7 @@ ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
case 0x03: /* page 3 */
mdata.pdata.pg3.pg_pc = 0x3;
mdata.pdata.pg3.pg_res1 = 0;
- mdata.pdata.pg3.pg_len = sizeof(DADF_T);
+ mdata.pdata.pg3.pg_len = sizeof(IPS_DADF);
mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg3.pg_len;
mdata.pdata.pg3.pg_trk_z = 0;
mdata.pdata.pg3.pg_asec_z = 0;
@@ -3110,7 +3895,7 @@ ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
case 0x4:
mdata.pdata.pg4.pg_pc = 0x4;
mdata.pdata.pg4.pg_res1 = 0;
- mdata.pdata.pg4.pg_len = sizeof(RDDG_T);
+ mdata.pdata.pg4.pg_len = sizeof(IPS_RDDG);
mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg4.pg_len;
mdata.pdata.pg4.pg_cylu = (cylinders >> 8) & 0xffff;
mdata.pdata.pg4.pg_cyll = cylinders & 0xff;
@@ -3204,6 +3989,12 @@ ips_free(ips_ha_t *ha) {
ha->dummy = NULL;
}
+ if (ha->ioctl_data) {
+ kfree(ha->ioctl_data);
+ ha->ioctl_data = NULL;
+ ha->ioctl_datasize = 0;
+ }
+
if (ha->scbs) {
for (i = 0; i < ha->max_cmds; i++) {
if (ha->scbs[i].sg_list)
@@ -3241,7 +4032,7 @@ ips_allocatescbs(ips_ha_t *ha) {
scb_p = &ha->scbs[i];
/* allocate S/G list */
- scb_p->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA);
+ scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_KERNEL|GFP_DMA);
if (! scb_p->sg_list)
return (0);
@@ -3268,7 +4059,7 @@ ips_allocatescbs(ips_ha_t *ha) {
/****************************************************************************/
static void
ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
- SG_LIST *sg_list;
+ IPS_SG_LIST *sg_list;
DBG("ips_init_scb");
@@ -3279,19 +4070,19 @@ ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
/* zero fill */
memset(scb, 0, sizeof(ips_scb_t));
- memset(ha->dummy, 0, sizeof(BASIC_IO_CMD));
+ memset(ha->dummy, 0, sizeof(IPS_IO_CMD));
/* Initialize dummy command bucket */
ha->dummy->op_code = 0xFF;
ha->dummy->ccsar = VIRT_TO_BUS(ha->dummy);
- ha->dummy->command_id = MAX_CMDS;
+ ha->dummy->command_id = IPS_MAX_CMDS;
/* set bus address of scb */
scb->scb_busaddr = VIRT_TO_BUS(scb);
scb->sg_list = sg_list;
/* Neptune Fix */
- scb->cmd.basic_io.cccr = ILE;
+ scb->cmd.basic_io.cccr = IPS_BIT_ILE;
scb->cmd.basic_io.ccsar = VIRT_TO_BUS(ha->dummy);
}
@@ -3309,13 +4100,13 @@ ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
static ips_scb_t *
ips_getscb(ips_ha_t *ha) {
ips_scb_t *scb;
- unsigned int cpu_flags;
+ u32 cpu_flags;
DBG("ips_getscb");
- spin_lock_irqsave(&ha->scb_lock, cpu_flags);
+ IPS_SCB_LOCK(cpu_flags);
if ((scb = ha->scb_freelist) == NULL) {
- spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
+ IPS_SCB_UNLOCK(cpu_flags);
return (NULL);
}
@@ -3323,7 +4114,7 @@ ips_getscb(ips_ha_t *ha) {
ha->scb_freelist = scb->q_next;
scb->q_next = NULL;
- spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
+ IPS_SCB_UNLOCK(cpu_flags);
ips_init_scb(ha, scb);
@@ -3343,16 +4134,16 @@ ips_getscb(ips_ha_t *ha) {
/****************************************************************************/
static void
ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
- unsigned int cpu_flags;
+ u32 cpu_flags;
DBG("ips_freescb");
/* check to make sure this is not our "special" scb */
if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
- spin_lock_irqsave(&ha->scb_lock, cpu_flags);
+ IPS_SCB_LOCK(cpu_flags);
scb->q_next = ha->scb_freelist;
ha->scb_freelist = scb;
- spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
+ IPS_SCB_UNLOCK(cpu_flags);
}
}
@@ -3369,10 +4160,11 @@ static int
ips_reset_adapter(ips_ha_t *ha) {
u8 Isr;
u8 Cbsp;
- u8 PostByte[MAX_POST_BYTES];
- u8 ConfigByte[MAX_CONFIG_BYTES];
+ u8 PostByte[IPS_MAX_POST_BYTES];
+ u8 ConfigByte[IPS_MAX_CONFIG_BYTES];
int i, j;
int reset_counter;
+ u32 cpu_flags;
DBG("ips_reset_adapter");
@@ -3381,108 +4173,125 @@ ips_reset_adapter(ips_ha_t *ha) {
ha->io_addr, ha->irq);
#endif
+ IPS_HA_LOCK(cpu_flags);
+
reset_counter = 0;
while (reset_counter < 2) {
reset_counter++;
- outb(RST, ha->io_addr + SCPR);
- MDELAY(ONE_SEC);
- outb(0, ha->io_addr + SCPR);
- MDELAY(ONE_SEC);
+ outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
+ MDELAY(IPS_ONE_SEC);
+ outb(0, ha->io_addr + IPS_REG_SCPR);
+ MDELAY(IPS_ONE_SEC);
- for (i = 0; i < MAX_POST_BYTES; i++) {
+ for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
for (j = 0; j < 45; j++) {
- Isr = inb(ha->io_addr + HISR);
- if (Isr & GHI)
+ Isr = inb(ha->io_addr + IPS_REG_HISR);
+ if (Isr & IPS_BIT_GHI)
break;
- MDELAY(ONE_SEC);
+ MDELAY(IPS_ONE_SEC);
}
if (j >= 45) {
/* error occured */
if (reset_counter < 2)
continue;
- else
+ else {
/* reset failed */
+ IPS_HA_UNLOCK(cpu_flags);
+
return (0);
+ }
}
- PostByte[i] = inb(ha->io_addr + ISPR);
- outb(Isr, ha->io_addr + HISR);
+ PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
+ outb(Isr, ha->io_addr + IPS_REG_HISR);
}
- if (PostByte[0] < GOOD_POST_BASIC_STATUS) {
+ if (PostByte[0] < IPS_GOOD_POST_STATUS) {
printk("(%s%d) reset controller fails (post status %x %x).\n",
ips_name, ha->host_num, PostByte[0], PostByte[1]);
+ IPS_HA_UNLOCK(cpu_flags);
+
return (0);
}
- for (i = 0; i < MAX_CONFIG_BYTES; i++) {
+ for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
for (j = 0; j < 240; j++) {
- Isr = inb(ha->io_addr + HISR);
- if (Isr & GHI)
+ Isr = inb(ha->io_addr + IPS_REG_HISR);
+ if (Isr & IPS_BIT_GHI)
break;
- MDELAY(ONE_SEC); /* 100 msec */
+ MDELAY(IPS_ONE_SEC); /* 100 msec */
}
if (j >= 240) {
/* error occured */
if (reset_counter < 2)
continue;
- else
+ else {
/* reset failed */
+ IPS_HA_UNLOCK(cpu_flags);
+
return (0);
+ }
}
- ConfigByte[i] = inb(ha->io_addr + ISPR);
- outb(Isr, ha->io_addr + HISR);
+ ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
+ outb(Isr, ha->io_addr + IPS_REG_HISR);
}
if (ConfigByte[0] == 0 && ConfigByte[1] == 2) {
printk("(%s%d) reset controller fails (status %x %x).\n",
ips_name, ha->host_num, ConfigByte[0], ConfigByte[1]);
+ IPS_HA_UNLOCK(cpu_flags);
+
return (0);
}
for (i = 0; i < 240; i++) {
- Cbsp = inb(ha->io_addr + CBSP);
+ Cbsp = inb(ha->io_addr + IPS_REG_CBSP);
- if ((Cbsp & OP) == 0)
+ if ((Cbsp & IPS_BIT_OP) == 0)
break;
- MDELAY(ONE_SEC);
+ MDELAY(IPS_ONE_SEC);
}
if (i >= 240) {
/* error occured */
if (reset_counter < 2)
continue;
- else
+ else {
/* reset failed */
+ IPS_HA_UNLOCK(cpu_flags);
+
return (0);
+ }
}
/* setup CCCR */
- outw(0x1010, ha->io_addr + CCCR);
+ outw(0x1010, ha->io_addr + IPS_REG_CCCR);
/* Enable busmastering */
- outb(EBM, ha->io_addr + SCPR);
+ outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
/* setup status queues */
ips_statinit(ha);
/* Enable interrupts */
- outb(EI, ha->io_addr + HISR);
+ outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR);
/* if we get here then everything went OK */
break;
}
+ IPS_HA_UNLOCK(cpu_flags);
+
return (1);
}
@@ -3502,14 +4311,14 @@ ips_statinit(ips_ha_t *ha) {
DBG("ips_statinit");
ha->adapt->p_status_start = ha->adapt->status;
- ha->adapt->p_status_end = ha->adapt->status + MAX_CMDS;
+ ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
ha->adapt->p_status_tail = ha->adapt->status;
phys_status_start = VIRT_TO_BUS(ha->adapt->status);
- outl(phys_status_start, ha->io_addr + SQSR);
- outl(phys_status_start + STATUS_Q_SIZE, ha->io_addr + SQER);
- outl(phys_status_start + STATUS_SIZE, ha->io_addr + SQHR);
- outl(phys_status_start, ha->io_addr + SQTR);
+ outl(phys_status_start, ha->io_addr + IPS_REG_SQSR);
+ outl(phys_status_start + IPS_STATUS_Q_SIZE, ha->io_addr + IPS_REG_SQER);
+ outl(phys_status_start + IPS_STATUS_SIZE, ha->io_addr + IPS_REG_SQHR);
+ outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
ha->adapt->hw_status_start = phys_status_start;
ha->adapt->hw_status_tail = phys_status_start;
@@ -3532,13 +4341,13 @@ ips_statupd(ips_ha_t *ha) {
if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
ha->adapt->p_status_tail++;
- ha->adapt->hw_status_tail += sizeof(STATUS);
+ ha->adapt->hw_status_tail += sizeof(IPS_STATUS);
} else {
ha->adapt->p_status_tail = ha->adapt->p_status_start;
ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
}
- outl(ha->adapt->hw_status_tail, ha->io_addr + SQTR);
+ outl(ha->adapt->hw_status_tail, ha->io_addr + IPS_REG_SQTR);
command_id = ha->adapt->p_status_tail->command_id;
@@ -3560,6 +4369,7 @@ static int
ips_issue(ips_ha_t *ha, ips_scb_t *scb) {
u32 TimeOut;
u16 val;
+ u32 cpu_flags;
DBG("ips_issue");
@@ -3577,17 +4387,19 @@ ips_issue(ips_ha_t *ha, ips_scb_t *scb) {
ips_name,
scb->cmd.basic_io.command_id);
#if IPS_DEBUG >= 11
- MDELAY(ONE_SEC);
+ MDELAY(IPS_ONE_SEC);
#endif
#endif
+ IPS_HA_LOCK(cpu_flags);
+
TimeOut = 0;
- while ((val = inw(ha->io_addr + CCCR)) & SEMAPHORE) {
+ while ((val = inw(ha->io_addr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
UDELAY(1000);
- if (++TimeOut >= SEMAPHORE_TIMEOUT) {
- if (!(val & START_STOP_BIT))
+ if (++TimeOut >= IPS_SEM_TIMEOUT) {
+ if (!(val & IPS_BIT_START_STOP))
break;
printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
@@ -3595,12 +4407,16 @@ ips_issue(ips_ha_t *ha, ips_scb_t *scb) {
printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
ips_name, ha->host_num);
+ IPS_HA_UNLOCK(cpu_flags);
+
return (IPS_FAILURE);
} /* end if */
} /* end while */
- outl(scb->scb_busaddr, ha->io_addr + CCSAR);
- outw(START_COMMAND, ha->io_addr + CCCR);
+ outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
+ outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
+
+ IPS_HA_UNLOCK(cpu_flags);
return (IPS_SUCCESS);
}
@@ -3620,18 +4436,18 @@ ips_isintr(ips_ha_t *ha) {
DBG("ips_isintr");
- Isr = inb(ha->io_addr + HISR);
+ Isr = inb(ha->io_addr + IPS_REG_HISR);
if (Isr == 0xFF)
/* ?!?! Nothing really there */
return (0);
- if (Isr & SCE)
+ if (Isr & IPS_BIT_SCE)
return (1);
- else if (Isr & (SQO | GHI)) {
+ else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
/* status queue overflow or GHI */
/* just clear the interrupt */
- outb(Isr, ha->io_addr + HISR);
+ outb(Isr, ha->io_addr + IPS_REG_HISR);
}
return (0);
@@ -3649,15 +4465,23 @@ ips_isintr(ips_ha_t *ha) {
static int
ips_wait(ips_ha_t *ha, int time, int intr) {
int ret;
+ u8 done;
DBG("ips_wait");
ret = IPS_FAILURE;
+ done = FALSE;
- time *= ONE_SEC; /* convert seconds to milliseconds */
+ time *= IPS_ONE_SEC; /* convert seconds to milliseconds */
- while (time > 0) {
- if (intr == IPS_INTR_OFF) {
+ while ((time > 0) && (!done)) {
+ if (intr == IPS_INTR_ON) {
+ if (ha->waitflag == FALSE) {
+ ret = IPS_SUCCESS;
+ done = TRUE;
+ break;
+ }
+ } else if (intr == IPS_INTR_IORL) {
if (ha->waitflag == FALSE) {
/*
* controller generated an interupt to
@@ -3665,28 +4489,50 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
* and ips_intr() has serviced the interrupt.
*/
ret = IPS_SUCCESS;
+ done = TRUE;
break;
}
/*
- * NOTE: Interrupts are disabled here
- * On an SMP system interrupts will only
- * be disabled on one processor.
- * So, ultimately we still need to set the
- * "I'm in the interrupt handler flag"
+ * NOTE: we already have the io_request_lock so
+ * even if we get an interrupt it won't get serviced
+ * until after we finish.
*/
+
while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
UDELAY(1000);
ips_intr(ha);
clear_bit(IPS_IN_INTR, &ha->flags);
-
- } else {
+ } else if (intr == IPS_INTR_HAL) {
if (ha->waitflag == FALSE) {
+ /*
+ * controller generated an interupt to
+ * acknowledge completion of the command
+ * and ips_intr() has serviced the interrupt.
+ */
ret = IPS_SUCCESS;
+ done = TRUE;
break;
}
+
+ /*
+ * NOTE: since we were not called with the iorequest lock
+ * we must obtain it before we can call the interrupt handler.
+ * We were called under the HA lock so we can assume that interrupts
+ * are masked.
+ */
+ spin_lock(&io_request_lock);
+
+ while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
+ UDELAY(1000);
+
+ ips_intr(ha);
+
+ clear_bit(IPS_IN_INTR, &ha->flags);
+
+ spin_unlock(&io_request_lock);
}
UDELAY(1000); /* 1 milisecond */
@@ -3706,10 +4552,10 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
/* */
/****************************************************************************/
static int
-ips_write_driver_status(ips_ha_t *ha) {
+ips_write_driver_status(ips_ha_t *ha, int intr) {
DBG("ips_write_driver_status");
- if (!ips_readwrite_page5(ha, FALSE)) {
+ if (!ips_readwrite_page5(ha, FALSE, intr)) {
printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n",
ips_name, ha->host_num);
@@ -3718,7 +4564,7 @@ ips_write_driver_status(ips_ha_t *ha) {
/* check to make sure the page has a valid */
/* signature */
- if (ha->nvram->signature != NVRAM_PAGE5_SIGNATURE) {
+ if (ha->nvram->signature != IPS_NVRAM_P5_SIG) {
#if IPS_DEBUG >= 1
printk("(%s%d) NVRAM page 5 has an invalid signature: %X.\n",
ips_name, ha->host_num, ha->nvram->signature);
@@ -3739,12 +4585,12 @@ ips_write_driver_status(ips_ha_t *ha) {
ha->ad_type = ha->nvram->adapter_type;
/* change values (as needed) */
- ha->nvram->operating_system = OS_LINUX;
+ ha->nvram->operating_system = IPS_OS_LINUX;
strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
/* now update the page */
- if (!ips_readwrite_page5(ha, TRUE)) {
+ if (!ips_readwrite_page5(ha, TRUE, intr)) {
printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n",
ips_name, ha->host_num);
@@ -3764,7 +4610,7 @@ ips_write_driver_status(ips_ha_t *ha) {
/* */
/****************************************************************************/
static int
-ips_read_adapter_status(ips_ha_t *ha) {
+ips_read_adapter_status(ips_ha_t *ha, int intr) {
ips_scb_t *scb;
int ret;
@@ -3775,9 +4621,9 @@ ips_read_adapter_status(ips_ha_t *ha) {
ips_init_scb(ha, scb);
scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = ENQUIRY;
+ scb->cdb[0] = IPS_CMD_ENQUIRY;
- scb->cmd.basic_io.op_code = ENQUIRY;
+ scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.basic_io.sg_count = 0;
scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
@@ -3787,7 +4633,7 @@ ips_read_adapter_status(ips_ha_t *ha) {
scb->cmd.basic_io.reserved = 0;
/* send command */
- ret = ips_send_wait(ha, scb, ips_cmd_timeout);
+ ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr);
if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
return (0);
@@ -3804,7 +4650,7 @@ ips_read_adapter_status(ips_ha_t *ha) {
/* */
/****************************************************************************/
static int
-ips_read_subsystem_parameters(ips_ha_t *ha) {
+ips_read_subsystem_parameters(ips_ha_t *ha, int intr) {
ips_scb_t *scb;
int ret;
@@ -3815,9 +4661,9 @@ ips_read_subsystem_parameters(ips_ha_t *ha) {
ips_init_scb(ha, scb);
scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = GET_SUBSYS_PARAM;
+ scb->cdb[0] = IPS_CMD_GET_SUBSYS;
- scb->cmd.basic_io.op_code = GET_SUBSYS_PARAM;
+ scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS;
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.basic_io.sg_count = 0;
scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->subsys);
@@ -3827,7 +4673,7 @@ ips_read_subsystem_parameters(ips_ha_t *ha) {
scb->cmd.basic_io.reserved = 0;
/* send command */
- ret = ips_send_wait(ha, scb, ips_cmd_timeout);
+ ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr);
if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
return (0);
@@ -3844,7 +4690,7 @@ ips_read_subsystem_parameters(ips_ha_t *ha) {
/* */
/****************************************************************************/
static int
-ips_read_config(ips_ha_t *ha) {
+ips_read_config(ips_ha_t *ha, int intr) {
ips_scb_t *scb;
int i;
int ret;
@@ -3861,18 +4707,18 @@ ips_read_config(ips_ha_t *ha) {
ips_init_scb(ha, scb);
scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = READ_NVRAM_CONFIGURATION;
+ scb->cdb[0] = IPS_CMD_READ_CONF;
- scb->cmd.basic_io.op_code = READ_NVRAM_CONFIGURATION;
+ scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF;
scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->conf);
/* send command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) ||
+ if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
(ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & GSC_STATUS_MASK) > 1)) {
+ ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
- memset(ha->conf, 0, sizeof(CONFCMD));
+ memset(ha->conf, 0, sizeof(IPS_CONF));
/* reset initiator IDs */
ha->conf->init_id[0] = IPS_ADAPTER_ID;
@@ -3891,11 +4737,11 @@ ips_read_config(ips_ha_t *ha) {
/* */
/* Routine Description: */
/* */
-/* Read the configuration on the adapter */
+/* Read nvram page 5 from the adapter */
/* */
/****************************************************************************/
static int
-ips_readwrite_page5(ips_ha_t *ha, int write) {
+ips_readwrite_page5(ips_ha_t *ha, int write, int intr) {
ips_scb_t *scb;
int ret;
@@ -3906,9 +4752,9 @@ ips_readwrite_page5(ips_ha_t *ha, int write) {
ips_init_scb(ha, scb);
scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = RW_NVRAM_PAGE;
+ scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE;
- scb->cmd.nvram.op_code = RW_NVRAM_PAGE;
+ scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE;
scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.nvram.page = 5;
scb->cmd.nvram.write = write;
@@ -3917,11 +4763,11 @@ ips_readwrite_page5(ips_ha_t *ha, int write) {
scb->cmd.nvram.reserved2 = 0;
/* issue the command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) ||
+ if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
(ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & GSC_STATUS_MASK) > 1)) {
+ ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
- memset(ha->nvram, 0, sizeof(NVRAM_PAGE5));
+ memset(ha->nvram, 0, sizeof(IPS_NVRAM_P5));
return (0);
}
@@ -3939,7 +4785,7 @@ ips_readwrite_page5(ips_ha_t *ha, int write) {
/* */
/****************************************************************************/
static int
-ips_clear_adapter(ips_ha_t *ha) {
+ips_clear_adapter(ips_ha_t *ha, int intr) {
ips_scb_t *scb;
int ret;
@@ -3950,43 +4796,415 @@ ips_clear_adapter(ips_ha_t *ha) {
ips_init_scb(ha, scb);
scb->timeout = ips_reset_timeout;
- scb->cdb[0] = CONFIG_SYNC;
+ scb->cdb[0] = IPS_CMD_CONFIG_SYNC;
- scb->cmd.config_sync.op_code = CONFIG_SYNC;
+ scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC;
scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.config_sync.channel = 0;
- scb->cmd.config_sync.source_target = POCL;
+ scb->cmd.config_sync.source_target = IPS_POCL;
scb->cmd.config_sync.reserved = 0;
scb->cmd.config_sync.reserved2 = 0;
scb->cmd.config_sync.reserved3 = 0;
/* issue command */
- ret = ips_send_wait(ha, scb, ips_reset_timeout);
+ ret = ips_send_wait(ha, scb, ips_reset_timeout, intr);
if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
return (0);
/* send unlock stripe command */
ips_init_scb(ha, scb);
- scb->cdb[0] = GET_ERASE_ERROR_TABLE;
+ scb->cdb[0] = IPS_CMD_ERROR_TABLE;
scb->timeout = ips_reset_timeout;
- scb->cmd.unlock_stripe.op_code = GET_ERASE_ERROR_TABLE;
+ scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE;
scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.unlock_stripe.log_drv = 0;
- scb->cmd.unlock_stripe.control = CSL;
+ scb->cmd.unlock_stripe.control = IPS_CSL;
scb->cmd.unlock_stripe.reserved = 0;
scb->cmd.unlock_stripe.reserved2 = 0;
scb->cmd.unlock_stripe.reserved3 = 0;
/* issue command */
- ret = ips_send_wait(ha, scb, ips_reset_timeout);
+ ret = ips_send_wait(ha, scb, ips_reset_timeout, intr);
if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
return (0);
return (1);
}
+/****************************************************************************/
+/* */
+/* Routine Name: ips_ffdc_reset */
+/* */
+/* Routine Description: */
+/* */
+/* FFDC: write reset info */
+/* */
+/****************************************************************************/
+static void
+ips_ffdc_reset(ips_ha_t *ha, int intr) {
+ ips_scb_t *scb;
+
+ DBG("ips_ffdc_reset");
+
+ scb = &ha->scbs[ha->max_cmds-1];
+
+ ips_init_scb(ha, scb);
+
+ scb->timeout = ips_cmd_timeout;
+ scb->cdb[0] = IPS_CMD_FFDC;
+ scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
+ scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
+ scb->cmd.ffdc.reset_count = ha->reset_count;
+ scb->cmd.ffdc.reset_type = 0x80;
+
+ /* convert time to what the card wants */
+ ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
+
+ /* issue command */
+ ips_send_wait(ha, scb, ips_cmd_timeout, intr);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_ffdc_time */
+/* */
+/* Routine Description: */
+/* */
+/* FFDC: write time info */
+/* */
+/****************************************************************************/
+static void
+ips_ffdc_time(ips_ha_t *ha, int intr) {
+ ips_scb_t *scb;
+
+ DBG("ips_ffdc_time");
+
+#if IPS_DEBUG >= 1
+ printk(KERN_NOTICE "(%s%d) Sending time update.\n",
+ ips_name, ha->host_num);
+#endif
+
+ scb = &ha->scbs[ha->max_cmds-1];
+
+ ips_init_scb(ha, scb);
+
+ scb->timeout = ips_cmd_timeout;
+ scb->cdb[0] = IPS_CMD_FFDC;
+ scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
+ scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
+ scb->cmd.ffdc.reset_count = 0;
+ scb->cmd.ffdc.reset_type = 0x80;
+
+ /* convert time to what the card wants */
+ ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
+
+ /* issue command */
+ ips_send_wait(ha, scb, ips_cmd_timeout, intr);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_fix_ffdc_time */
+/* */
+/* Routine Description: */
+/* Adjust time_t to what the card wants */
+/* */
+/****************************************************************************/
+static void
+ips_fix_ffdc_time(ips_ha_t *ha, ips_scb_t *scb, time_t current_time) {
+ long days;
+ long rem;
+ int i;
+ int year;
+ int yleap;
+ int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
+ int month_lengths[12][2] = { {31, 31},
+ {28, 29},
+ {31, 31},
+ {30, 30},
+ {31, 31},
+ {30, 30},
+ {31, 31},
+ {31, 31},
+ {30, 30},
+ {31, 31},
+ {30, 30},
+ {31, 31} };
+
+ days = current_time / IPS_SECS_DAY;
+ rem = current_time % IPS_SECS_DAY;
+
+ scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
+ rem = rem % IPS_SECS_HOUR;
+ scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
+ scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
+
+ year = IPS_EPOCH_YEAR;
+ while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
+ int newy;
+
+ newy = year + (days / IPS_DAYS_NORMAL_YEAR);
+ if (days < 0)
+ --newy;
+ days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
+ IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
+ IPS_NUM_LEAP_YEARS_THROUGH(year - 1);
+ year = newy;
+ }
+
+ scb->cmd.ffdc.yearH = year / 100;
+ scb->cmd.ffdc.yearL = year % 100;
+
+ for (i = 0; days >= month_lengths[i][yleap]; ++i)
+ days -= month_lengths[i][yleap];
+
+ scb->cmd.ffdc.month = i + 1;
+ scb->cmd.ffdc.day = days + 1;
+}
+
+/****************************************************************************
+ * BIOS Flash Routines *
+ ****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_erase_bios */
+/* */
+/* Routine Description: */
+/* Erase the BIOS on the adapter */
+/* */
+/****************************************************************************/
+static int
+ips_erase_bios(ips_ha_t *ha) {
+ int timeout;
+ u8 status;
+
+ /* Clear the status register */
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ outb(0x50, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ /* Erase Setup */
+ outb(0x20, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ /* Erase Confirm */
+ outb(0xD0, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ /* Erase Status */
+ outb(0x70, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ timeout = 80000; /* 80 seconds */
+
+ while (timeout > 0) {
+ if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ UDELAY(5); /* 5 us */
+ }
+
+ status = inb(ha->io_addr + IPS_REG_FLDP);
+
+ if (status & 0x80)
+ break;
+
+ MDELAY(1);
+ timeout--;
+ }
+
+ /* check for timeout */
+ if (timeout <= 0) {
+ /* timeout */
+
+ /* try to suspend the erase */
+ outb(0xB0, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ /* wait for 10 seconds */
+ timeout = 10000;
+ while (timeout > 0) {
+ if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ UDELAY(5); /* 5 us */
+ }
+
+ status = inb(ha->io_addr + IPS_REG_FLDP);
+
+ if (status & 0xC0)
+ break;
+
+ MDELAY(1);
+ timeout--;
+ }
+
+ return (1);
+ }
+
+ /* check for valid VPP */
+ if (status & 0x08)
+ /* VPP failure */
+ return (1);
+
+ /* check for succesful flash */
+ if (status & 0x30)
+ /* sequence error */
+ return (1);
+
+ /* Otherwise, we were successful */
+ /* clear status */
+ outb(0x50, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ /* enable reads */
+ outb(0xFF, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ return (0);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_program_bios */
+/* */
+/* Routine Description: */
+/* Program the BIOS on the adapter */
+/* */
+/****************************************************************************/
+static int
+ips_program_bios(ips_ha_t *ha, char *buffer, int buffersize) {
+ int i;
+ int timeout;
+ u8 status;
+
+ for (i = 0; i < buffersize; i++) {
+ /* write a byte */
+ outl(i, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ outb(0x40, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ /* wait up to one second */
+ timeout = 1000;
+ while (timeout > 0) {
+ if (ha->revision_id == IPS_REVID_TROMBONE64) {
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ UDELAY(5); /* 5 us */
+ }
+
+ status = inb(ha->io_addr + IPS_REG_FLDP);
+
+ if (status & 0x80)
+ break;
+
+ MDELAY(1);
+ timeout--;
+ }
+
+ if (timeout == 0) {
+ /* timeout error */
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ outb(0xFF, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ return (1);
+ }
+
+ /* check the status */
+ if (status & 0x18) {
+ /* programming error */
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ outb(0xFF, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ return (1);
+ }
+ } /* end for */
+
+ /* Enable reading */
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ outb(0xFF, ha->io_addr + IPS_REG_FLDP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ return (0);
+}
+
+/****************************************************************************/
+/* */
+/* Routine Name: ips_verify_bios */
+/* */
+/* Routine Description: */
+/* Verify the BIOS on the adapter */
+/* */
+/****************************************************************************/
+static int
+ips_verify_bios(ips_ha_t *ha, char *buffer, int buffersize) {
+ u8 checksum;
+ int i;
+
+ /* test 1st byte */
+ outl(0, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
+ return (1);
+
+ outl(1, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+ if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
+ return (1);
+
+ checksum = 0xff;
+ for (i = 2; i < buffersize; i++) {
+
+ outl(i, ha->io_addr + IPS_REG_FLAP);
+ if (ha->revision_id == IPS_REVID_TROMBONE64)
+ UDELAY(5); /* 5 us */
+
+ checksum = (u8) checksum + inb(ha->io_addr + IPS_REG_FLDP);
+ }
+
+ if (checksum != 0)
+ /* failure */
+ return (1);
+ else
+ /* success */
+ return (0);
+}
+
#if defined (MODULE)
Scsi_Host_Template driver_template = IPS;
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index d760ae3a6..e93fe8153 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -47,7 +47,6 @@
#ifndef _IPS_H_
#define _IPS_H_
- #include <linux/config.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -67,209 +66,276 @@
* Some handy macros
*/
#ifndef LinuxVersionCode
- #define LinuxVersionCode(x,y,z) (((x)<<16)+((y)<<8)+(z))
+ #define LinuxVersionCode(x,y,z) (((x)<<16)+((y)<<8)+(z))
#endif
- #define HA(x) ((ips_ha_t *) x->hostdata)
+ #define IPS_HA(x) ((ips_ha_t *) x->hostdata)
#define IPS_COMMAND_ID(ha, scb) (int) (scb - ha->scbs)
- #define VIRT_TO_BUS(x) (unsigned int)virt_to_bus((void *) x)
+
+ #ifndef VIRT_TO_BUS
+ #define VIRT_TO_BUS(x) (unsigned int)virt_to_bus((void *) x)
+ #endif
- #define UDELAY udelay
- #define MDELAY mdelay
+ #ifndef UDELAY
+ #define UDELAY udelay
+ #endif
+
+ #ifndef MDELAY
+ #define MDELAY mdelay
+ #endif
- #define verify_area_20(t,a,sz) (0) /* success */
- #define PUT_USER put_user
- #define __PUT_USER __put_user
- #define PUT_USER_RET put_user_ret
- #define GET_USER get_user
- #define __GET_USER __get_user
- #define GET_USER_RET get_user_ret
+ #ifndef verify_area_20
+ #define verify_area_20(t,a,sz) (0) /* success */
+ #endif
+
+ #ifndef PUT_USER
+ #define PUT_USER put_user
+ #endif
+
+ #ifndef __PUT_USER
+ #define __PUT_USER __put_user
+ #endif
+
+ #ifndef PUT_USER_RET
+ #define PUT_USER_RET put_user_ret
+ #endif
+
+ #ifndef GET_USER
+ #define GET_USER get_user
+ #endif
+
+ #ifndef __GET_USER
+ #define __GET_USER __get_user
+ #endif
+
+ #ifndef GET_USER_RET
+ #define GET_USER_RET get_user_ret
+ #endif
-/*
- * Adapter address map equates
- */
- #define HISR 0x08 /* Host Interrupt Status Reg */
- #define CCSAR 0x10 /* Cmd Channel System Addr Reg */
- #define CCCR 0x14 /* Cmd Channel Control Reg */
- #define SQHR 0x20 /* Status Q Head Reg */
- #define SQTR 0x24 /* Status Q Tail Reg */
- #define SQER 0x28 /* Status Q End Reg */
- #define SQSR 0x2C /* Status Q Start Reg */
- #define SCPR 0x05 /* Subsystem control port reg */
- #define ISPR 0x06 /* interrupt status port reg */
- #define CBSP 0x07 /* CBSP register */
+ /*
+ * Lock macros
+ */
+ #define IPS_SCB_LOCK(cpu_flags) spin_lock_irqsave(&ha->scb_lock, cpu_flags)
+ #define IPS_SCB_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->scb_lock, cpu_flags)
+ #define IPS_QUEUE_LOCK(queue) spin_lock_irqsave(&(queue)->lock, (queue)->cpu_flags)
+ #define IPS_QUEUE_UNLOCK(queue) spin_unlock_irqrestore(&(queue)->lock, (queue)->cpu_flags)
+ #define IPS_HA_LOCK(cpu_flags) spin_lock_irqsave(&ha->ips_lock, cpu_flags)
+ #define IPS_HA_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->ips_lock, cpu_flags)
-/*
- * Adapter register bit equates
- */
- #define GHI 0x04 /* HISR General Host Interrupt */
- #define SQO 0x02 /* HISR Status Q Overflow */
- #define SCE 0x01 /* HISR Status Channel Enqueue */
- #define SEMAPHORE 0x08 /* CCCR Semaphore Bit */
- #define ILE 0x10 /* CCCR ILE Bit */
- #define START_COMMAND 0x101A /* CCCR Start Command Channel */
- #define START_STOP_BIT 0x0002 /* CCCR Start/Stop Bit */
- #define RST 0x80 /* SCPR Reset Bit */
- #define EBM 0x02 /* SCPR Enable Bus Master */
- #define EI 0x80 /* HISR Enable Interrupts */
- #define OP 0x01 /* OP bit in CBSP */
+ /*
+ * Adapter address map equates
+ */
+ #define IPS_REG_HISR 0x08 /* Host Interrupt Status Reg */
+ #define IPS_REG_CCSAR 0x10 /* Cmd Channel System Addr Reg */
+ #define IPS_REG_CCCR 0x14 /* Cmd Channel Control Reg */
+ #define IPS_REG_SQHR 0x20 /* Status Q Head Reg */
+ #define IPS_REG_SQTR 0x24 /* Status Q Tail Reg */
+ #define IPS_REG_SQER 0x28 /* Status Q End Reg */
+ #define IPS_REG_SQSR 0x2C /* Status Q Start Reg */
+ #define IPS_REG_SCPR 0x05 /* Subsystem control port reg */
+ #define IPS_REG_ISPR 0x06 /* interrupt status port reg */
+ #define IPS_REG_CBSP 0x07 /* CBSP register */
+ #define IPS_REG_FLAP 0x18 /* Flash address port */
+ #define IPS_REG_FLDP 0x1C /* Flash data port */
-/*
- * Adapter Command ID Equates
- */
- #define GET_LOGICAL_DRIVE_INFO 0x19
- #define GET_SUBSYS_PARAM 0x40
- #define READ_NVRAM_CONFIGURATION 0x38
- #define RW_NVRAM_PAGE 0xBC
- #define IPS_READ 0x02
- #define IPS_WRITE 0x03
- #define ENQUIRY 0x05
- #define FLUSH_CACHE 0x0A
- #define NORM_STATE 0x00
- #define READ_SCATTER_GATHER 0x82
- #define WRITE_SCATTER_GATHER 0x83
- #define DIRECT_CDB 0x04
- #define DIRECT_CDB_SCATTER_GATHER 0x84
- #define CONFIG_SYNC 0x58
- #define POCL 0x30
- #define GET_ERASE_ERROR_TABLE 0x17
- #define RESET_CHANNEL 0x1A
- #define CSL 0xFF
- #define ADAPT_RESET 0xFF
+ /*
+ * Adapter register bit equates
+ */
+ #define IPS_BIT_GHI 0x04 /* HISR General Host Interrupt */
+ #define IPS_BIT_SQO 0x02 /* HISR Status Q Overflow */
+ #define IPS_BIT_SCE 0x01 /* HISR Status Channel Enqueue */
+ #define IPS_BIT_SEM 0x08 /* CCCR Semaphore Bit */
+ #define IPS_BIT_ILE 0x10 /* CCCR ILE Bit */
+ #define IPS_BIT_START_CMD 0x101A /* CCCR Start Command Channel */
+ #define IPS_BIT_START_STOP 0x0002 /* CCCR Start/Stop Bit */
+ #define IPS_BIT_RST 0x80 /* SCPR Reset Bit */
+ #define IPS_BIT_EBM 0x02 /* SCPR Enable Bus Master */
+ #define IPS_BIT_EI 0x80 /* HISR Enable Interrupts */
+ #define IPS_BIT_OP 0x01 /* OP bit in CBSP */
-/*
- * Adapter Equates
- */
+ /*
+ * Adapter Command ID Equates
+ */
+ #define IPS_CMD_GET_LD_INFO 0x19
+ #define IPS_CMD_GET_SUBSYS 0x40
+ #define IPS_CMD_READ_CONF 0x38
+ #define IPS_CMD_RW_NVRAM_PAGE 0xBC
+ #define IPS_CMD_READ 0x02
+ #define IPS_CMD_WRITE 0x03
+ #define IPS_CMD_FFDC 0xD7
+ #define IPS_CMD_ENQUIRY 0x05
+ #define IPS_CMD_FLUSH 0x0A
+ #define IPS_CMD_READ_SG 0x82
+ #define IPS_CMD_WRITE_SG 0x83
+ #define IPS_CMD_DCDB 0x04
+ #define IPS_CMD_DCDB_SG 0x84
+ #define IPS_CMD_CONFIG_SYNC 0x58
+ #define IPS_CMD_ERROR_TABLE 0x17
+
+ /*
+ * Adapter Equates
+ */
+ #define IPS_CSL 0xFF
+ #define IPS_POCL 0x30
+ #define IPS_NORM_STATE 0x00
#define IPS_MAX_ADAPTERS 16
#define IPS_MAX_IOCTL 1
#define IPS_MAX_IOCTL_QUEUE 8
#define IPS_MAX_QUEUE 128
#define IPS_BLKSIZE 512
- #define MAX_SG_ELEMENTS 17
- #define MAX_LOGICAL_DRIVES 8
- #define MAX_CHANNELS 3
- #define MAX_TARGETS 15
- #define MAX_CHUNKS 16
- #define MAX_CMDS 128
+ #define IPS_MAX_SG 17
+ #define IPS_MAX_LD 8
+ #define IPS_MAX_CHANNELS 4
+ #define IPS_MAX_TARGETS 15
+ #define IPS_MAX_CHUNKS 16
+ #define IPS_MAX_CMDS 128
#define IPS_MAX_XFER 0x10000
- #define COMP_MODE_HEADS 128
- #define COMP_MODE_SECTORS 32
- #define NORM_MODE_HEADS 254
- #define NORM_MODE_SECTORS 63
- #define NVRAM_PAGE5_SIGNATURE 0xFFDDBB99
- #define MAX_POST_BYTES 0x02
- #define MAX_CONFIG_BYTES 0x02
- #define GOOD_POST_BASIC_STATUS 0x80
- #define SEMAPHORE_TIMEOUT 2000
- #define IPS_INTR_OFF 0
- #define IPS_INTR_ON 1
+ #define IPS_NVRAM_P5_SIG 0xFFDDBB99
+ #define IPS_MAX_POST_BYTES 0x02
+ #define IPS_MAX_CONFIG_BYTES 0x02
+ #define IPS_GOOD_POST_STATUS 0x80
+ #define IPS_SEM_TIMEOUT 2000
+ #define IPS_IOCTL_COMMAND 0x0D
+ #define IPS_IOCTL_NEW_COMMAND 0x81
+ #define IPS_INTR_ON 0
+ #define IPS_INTR_IORL 1
+ #define IPS_INTR_HAL 2
#define IPS_ADAPTER_ID 0xF
#define IPS_VENDORID 0x1014
#define IPS_DEVICEID 0x002E
- #define TIMEOUT_10 0x10
- #define TIMEOUT_60 0x20
- #define TIMEOUT_20M 0x30
- #define STATUS_SIZE 4
- #define STATUS_Q_SIZE (MAX_CMDS+1) * STATUS_SIZE
- #define ONE_MSEC 1
- #define ONE_SEC 1000
+ #define IPS_IOCTL_SIZE 8192
+ #define IPS_STATUS_SIZE 4
+ #define IPS_STATUS_Q_SIZE (IPS_MAX_CMDS+1) * IPS_STATUS_SIZE
+ #define IPS_ONE_MSEC 1
+ #define IPS_ONE_SEC 1000
+
+ /*
+ * Geometry Settings
+ */
+ #define IPS_COMP_HEADS 128
+ #define IPS_COMP_SECTORS 32
+ #define IPS_NORM_HEADS 254
+ #define IPS_NORM_SECTORS 63
-/*
- * Adapter Basic Status Codes
- */
- #define BASIC_STATUS_MASK 0xFF
- #define GSC_STATUS_MASK 0x0F
- #define SSUCCESS 0x00
- #define RECOVERED_ERROR 0x01
- #define IPS_CHECK_CONDITION 0x02
- #define INVAL_OPCO 0x03
- #define INVAL_CMD_BLK 0x04
- #define INVAL_PARM_BLK 0x05
+ /*
+ * Adapter Basic Status Codes
+ */
+ #define IPS_BASIC_STATUS_MASK 0xFF
+ #define IPS_GSC_STATUS_MASK 0x0F
+ #define IPS_CMD_SUCCESS 0x00
+ #define IPS_CMD_RECOVERED_ERROR 0x01
+ #define IPS_INVAL_OPCO 0x03
+ #define IPS_INVAL_CMD_BLK 0x04
+ #define IPS_INVAL_PARM_BLK 0x05
#define IPS_BUSY 0x08
- #define ADAPT_HARDWARE_ERROR 0x09
- #define ADAPT_FIRMWARE_ERROR 0x0A
- #define CMD_CMPLT_WERROR 0x0C
- #define LOG_DRV_ERROR 0x0D
- #define CMD_TIMEOUT 0x0E
- #define PHYS_DRV_ERROR 0x0F
+ #define IPS_CMD_CMPLT_WERROR 0x0C
+ #define IPS_LD_ERROR 0x0D
+ #define IPS_CMD_TIMEOUT 0x0E
+ #define IPS_PHYS_DRV_ERROR 0x0F
-/*
- * Adapter Extended Status Equates
- */
- #define SELECTION_TIMEOUT 0xF0
- #define DATA_OVER_UNDER_RUN 0xF2
- #define EXT_HOST_RESET 0xF7
- #define EXT_DEVICE_RESET 0xF8
- #define EXT_RECOVERY 0xFC
- #define EXT_CHECK_CONDITION 0xFF
+ /*
+ * Adapter Extended Status Equates
+ */
+ #define IPS_ERR_SEL_TO 0xF0
+ #define IPS_ERR_OU_RUN 0xF2
+ #define IPS_ERR_HOST_RESET 0xF7
+ #define IPS_ERR_DEV_RESET 0xF8
+ #define IPS_ERR_RECOVERY 0xFC
+ #define IPS_ERR_CKCOND 0xFF
-/*
- * Operating System Defines
- */
- #define OS_WINDOWS_NT 0x01
- #define OS_NETWARE 0x02
- #define OS_OPENSERVER 0x03
- #define OS_UNIXWARE 0x04
- #define OS_SOLARIS 0x05
- #define OS_OS2 0x06
- #define OS_LINUX 0x07
- #define OS_FREEBSD 0x08
+ /*
+ * Operating System Defines
+ */
+ #define IPS_OS_WINDOWS_NT 0x01
+ #define IPS_OS_NETWARE 0x02
+ #define IPS_OS_OPENSERVER 0x03
+ #define IPS_OS_UNIXWARE 0x04
+ #define IPS_OS_SOLARIS 0x05
+ #define IPS_OS_OS2 0x06
+ #define IPS_OS_LINUX 0x07
+ #define IPS_OS_FREEBSD 0x08
-/*
- * Adapter Command/Status Packet Definitions
- */
+ /*
+ * Adapter Revision ID's
+ */
+ #define IPS_REVID_SERVERAID 0x02
+ #define IPS_REVID_NAVAJO 0x03
+ #define IPS_REVID_SERVERAID2 0x04
+ #define IPS_REVID_CLARINETP1 0x05
+ #define IPS_REVID_CLARINETP2 0x07
+ #define IPS_REVID_CLARINETP3 0x0D
+ #define IPS_REVID_TROMBONE32 0x0F
+ #define IPS_REVID_TROMBONE64 0x10
+
+ /*
+ * Adapter Command/Status Packet Definitions
+ */
#define IPS_SUCCESS 0x01 /* Successfully completed */
#define IPS_SUCCESS_IMM 0x02 /* Success - Immediately */
#define IPS_FAILURE 0x04 /* Completed with Error */
-/*
- * Logical Drive Equates
- */
- #define OFF_LINE 0x02
- #define OKAY 0x03
- #define FREE 0x00
- #define SYS 0x06
- #define CRS 0x24
+ /*
+ * Logical Drive Equates
+ */
+ #define IPS_LD_OFFLINE 0x02
+ #define IPS_LD_OKAY 0x03
+ #define IPS_LD_FREE 0x00
+ #define IPS_LD_SYS 0x06
+ #define IPS_LD_CRS 0x24
-/*
- * DCDB Table Equates
- */
- #define NO_DISCONNECT 0x00
- #define DISCONNECT_ALLOWED 0x80
- #define NO_AUTO_REQUEST_SENSE 0x40
- #define IPS_DATA_NONE 0x00
- #define IPS_DATA_UNK 0x00
+ /*
+ * DCDB Table Equates
+ */
+ #define IPS_NO_DISCONNECT 0x00
+ #define IPS_DISCONNECT_ALLOWED 0x80
+ #define IPS_NO_AUTO_REQSEN 0x40
+ #define IPS_DATA_NONE 0x00
+ #define IPS_DATA_UNK 0x00
#define IPS_DATA_IN 0x01
#define IPS_DATA_OUT 0x02
- #define TRANSFER_64K 0x08
- #define NOTIMEOUT 0x00
- #define TIMEOUT10 0x10
- #define TIMEOUT60 0x20
- #define TIMEOUT20M 0x30
+ #define IPS_TRANSFER64K 0x08
+ #define IPS_NOTIMEOUT 0x00
+ #define IPS_TIMEOUT10 0x10
+ #define IPS_TIMEOUT60 0x20
+ #define IPS_TIMEOUT20M 0x30
-/*
- * Host adapter Flags (bit numbers)
- */
+ /*
+ * Host adapter Flags (bit numbers)
+ */
#define IPS_IN_INTR 0
#define IPS_IN_ABORT 1
#define IPS_IN_RESET 2
-/*
- * SCB Flags
- */
- #define SCB_ACTIVE 0x00001
- #define SCB_WAITING 0x00002
+ /*
+ * SCB Flags
+ */
+ #define IPS_SCB_ACTIVE 0x00001
+ #define IPS_SCB_WAITING 0x00002
-/*
- * Passthru stuff
- */
- #define COPPUSRCMD (('C'<<8) | 65)
+ /*
+ * Passthru stuff
+ */
+ #define IPS_COPPUSRCMD (('C'<<8) | 65)
+ #define IPS_COPPIOCCMD (('C'<<8) | 66)
#define IPS_NUMCTRLS (('C'<<8) | 68)
#define IPS_CTRLINFO (('C'<<8) | 69)
+ #define IPS_FLASHBIOS (('C'<<8) | 70)
-/*
- * Scsi_Host Template
- */
+ /* time oriented stuff */
+ #define IPS_IS_LEAP_YEAR(y) (((y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0))) ? 1 : 0)
+ #define IPS_NUM_LEAP_YEARS_THROUGH(y) ((y) / 4 - (y) / 100 + (y) / 400)
+
+ #define IPS_SECS_MIN 60
+ #define IPS_SECS_HOUR 3600
+ #define IPS_SECS_8HOURS 28800
+ #define IPS_SECS_DAY 86400
+ #define IPS_DAYS_NORMAL_YEAR 365
+ #define IPS_DAYS_LEAP_YEAR 366
+ #define IPS_EPOCH_YEAR 1970
+
+ /*
+ * Scsi_Host Template
+ */
#define IPS { \
next : NULL, \
module : NULL, \
@@ -291,7 +357,7 @@
bios_param : ips_biosparam, \
can_queue : 0, \
this_id: -1, \
- sg_tablesize : MAX_SG_ELEMENTS, \
+ sg_tablesize : IPS_MAX_SG, \
cmd_per_lun: 16, \
present : 0, \
unchecked_isa_dma : 0, \
@@ -313,7 +379,7 @@ typedef struct {
u16 reserved;
u32 ccsar;
u32 cccr;
-} BASIC_IO_CMD, *PBASIC_IO_CMD;
+} IPS_IO_CMD, *PIPS_IO_CMD;
typedef struct {
u8 op_code;
@@ -324,7 +390,7 @@ typedef struct {
u32 reserved3;
u32 ccsar;
u32 cccr;
-} LOGICAL_INFO, *PLOGICAL_INFO;
+} IPS_LD_CMD, *PIPS_LD_CMD;
typedef struct {
u8 op_code;
@@ -334,7 +400,7 @@ typedef struct {
u32 reserved3;
u32 buffer_addr;
u32 reserved4;
-} IOCTL_INFO, *PIOCTL_INFO;
+} IPS_IOCTL_CMD, *PIPS_IOCTL_CMD;
typedef struct {
u8 op_code;
@@ -345,7 +411,7 @@ typedef struct {
u32 reserved3;
u32 ccsar;
u32 cccr;
-} DCDB_CMD, *PDCDB_CMD;
+} IPS_DCDB_CMD, *PIPS_DCDB_CMD;
typedef struct {
u8 op_code;
@@ -357,7 +423,7 @@ typedef struct {
u32 reserved3;
u32 ccsar;
u32 cccr;
-} CONFIG_SYNC_CMD, *PCONFIG_SYNC_CMD;
+} IPS_CS_CMD, *PIPS_CS_CMD;
typedef struct {
u8 op_code;
@@ -369,7 +435,7 @@ typedef struct {
u32 reserved3;
u32 ccsar;
u32 cccr;
-} UNLOCK_STRIPE_CMD, *PUNLOCK_STRIPE_CMD;
+} IPS_US_CMD, *PIPS_US_CMD;
typedef struct {
u8 op_code;
@@ -381,7 +447,7 @@ typedef struct {
u32 reserved4;
u32 ccsar;
u32 cccr;
-} FLUSH_CACHE_CMD, *PFLUSH_CACHE_CMD;
+} IPS_FC_CMD, *PIPS_FC_CMD;
typedef struct {
u8 op_code;
@@ -393,7 +459,7 @@ typedef struct {
u32 reserved3;
u32 ccsar;
u32 cccr;
-} STATUS_CMD, *PSTATUS_CMD;
+} IPS_STATUS_CMD, *PIPS_STATUS_CMD;
typedef struct {
u8 op_code;
@@ -405,19 +471,36 @@ typedef struct {
u32 reserved2;
u32 ccsar;
u32 cccr;
-} NVRAM_CMD, *PNVRAM_CMD;
+} IPS_NVRAM_CMD, *PIPS_NVRAM_CMD;
+
+typedef struct {
+ u8 op_code;
+ u8 command_id;
+ u8 reset_count;
+ u8 reset_type;
+ u8 second;
+ u8 minute;
+ u8 hour;
+ u8 day;
+ u8 reserved1[4];
+ u8 month;
+ u8 yearH;
+ u8 yearL;
+ u8 reserved2;
+} IPS_FFDC_CMD, *PIPS_FFDC_CMD;
typedef union {
- BASIC_IO_CMD basic_io;
- LOGICAL_INFO logical_info;
- IOCTL_INFO ioctl_info;
- DCDB_CMD dcdb;
- CONFIG_SYNC_CMD config_sync;
- UNLOCK_STRIPE_CMD unlock_stripe;
- FLUSH_CACHE_CMD flush_cache;
- STATUS_CMD status;
- NVRAM_CMD nvram;
-} HOST_COMMAND, *PHOST_COMMAND;
+ IPS_IO_CMD basic_io;
+ IPS_LD_CMD logical_info;
+ IPS_IOCTL_CMD ioctl_info;
+ IPS_DCDB_CMD dcdb;
+ IPS_CS_CMD config_sync;
+ IPS_US_CMD unlock_stripe;
+ IPS_FC_CMD flush_cache;
+ IPS_STATUS_CMD status;
+ IPS_NVRAM_CMD nvram;
+ IPS_FFDC_CMD ffdc;
+} IPS_HOST_COMMAND, *PIPS_HOST_COMMAND;
typedef struct {
u8 logical_id;
@@ -425,25 +508,13 @@ typedef struct {
u8 raid_level;
u8 state;
u32 sector_count;
-} DRIVE_INFO, *PDRIVE_INFO;
-
-typedef struct {
- u8 no_of_log_drive;
- u8 reserved[3];
- DRIVE_INFO drive_info[MAX_LOGICAL_DRIVES];
-} LOGICAL_DRIVE_INFO, *PLOGICAL_DRIVE_INFO;
+} IPS_DRIVE_INFO, *PIPS_DRIVE_INFO;
typedef struct {
- u8 ha_num;
- u8 bus_num;
- u8 id;
- u8 device_type;
- u32 data_len;
- u32 data_ptr;
- u8 scsi_cdb[12];
- u32 data_counter;
- u32 block_size;
-} NON_DISK_DEVICE_INFO, *PNON_DISK_DEVICE_INFO;
+ u8 no_of_log_drive;
+ u8 reserved[3];
+ IPS_DRIVE_INFO drive_info[IPS_MAX_LD];
+} IPS_LD_INFO, *PIPS_LD_INFO;
typedef struct {
u8 device_address;
@@ -458,24 +529,24 @@ typedef struct {
u8 sense_info[64];
u8 scsi_status;
u8 reserved2[3];
-} DCDB_TABLE, *PDCDB_TABLE;
+} IPS_DCDB_TABLE, *PIPS_DCDB_TABLE;
typedef struct {
volatile u8 reserved;
volatile u8 command_id;
volatile u8 basic_status;
volatile u8 extended_status;
-} STATUS, *PSTATUS;
+} IPS_STATUS, *PIPS_STATUS;
typedef struct {
- STATUS status[MAX_CMDS + 1];
- volatile PSTATUS p_status_start;
- volatile PSTATUS p_status_end;
- volatile PSTATUS p_status_tail;
+ IPS_STATUS status[IPS_MAX_CMDS + 1];
+ volatile PIPS_STATUS p_status_start;
+ volatile PIPS_STATUS p_status_end;
+ volatile PIPS_STATUS p_status_tail;
volatile u32 hw_status_start;
volatile u32 hw_status_tail;
- LOGICAL_DRIVE_INFO logical_drive_info;
-} ADAPTER_AREA, *PADAPTER_AREA;
+ IPS_LD_INFO logical_drive_info;
+} IPS_ADAPTER, *PIPS_ADAPTER;
typedef struct {
u8 ucLogDriveCount;
@@ -488,7 +559,7 @@ typedef struct {
u8 ucNVramDevChgCnt;
u8 CodeBlkVersion[8];
u8 BootBlkVersion[8];
- u32 ulDriveSize[MAX_LOGICAL_DRIVES];
+ u32 ulDriveSize[IPS_MAX_LD];
u8 ucConcurrentCmdCount;
u8 ucMaxPhysicalDevices;
u16 usFlashRepgmCount;
@@ -499,8 +570,8 @@ typedef struct {
u16 usConfigUpdateCount;
u8 ucBlkFlag;
u8 reserved;
- u16 usAddrDeadDisk[MAX_CHANNELS * MAX_TARGETS];
-} ENQCMD, *PENQCMD;
+ u16 usAddrDeadDisk[IPS_MAX_CHANNELS * IPS_MAX_TARGETS];
+} IPS_ENQ, *PIPS_ENQ;
typedef struct {
u8 ucInitiator;
@@ -509,7 +580,7 @@ typedef struct {
u8 ucState;
u32 ulBlockCount;
u8 ucDeviceId[28];
-} DEVSTATE, *PDEVSTATE;
+} IPS_DEVSTATE, *PIPS_DEVSTATE;
typedef struct {
u8 ucChn;
@@ -517,7 +588,7 @@ typedef struct {
u16 ucReserved;
u32 ulStartSect;
u32 ulNoOfSects;
-} CHUNK, *PCHUNK;
+} IPS_CHUNK, *PIPS_CHUNK;
typedef struct {
u16 ucUserField;
@@ -528,8 +599,8 @@ typedef struct {
u8 ucParams;
u8 ucReserved;
u32 ulLogDrvSize;
- CHUNK chunk[MAX_CHUNKS];
-} LOGICAL_DRIVE, *PLOGICAL_DRIVE;
+ IPS_CHUNK chunk[IPS_MAX_CHUNKS];
+} IPS_LD, *PIPS_LD;
typedef struct {
u8 board_disc[8];
@@ -539,7 +610,7 @@ typedef struct {
u8 ucCompression;
u8 ucNvramType;
u32 ulNvramSize;
-} HARDWARE_DISC, *PHARDWARE_DISC;
+} IPS_HARDWARE, *PIPS_HARDWARE;
typedef struct {
u8 ucLogDriveCount;
@@ -563,12 +634,12 @@ typedef struct {
u16 user_field;
u8 ucRebuildRate;
u8 ucReserve;
- HARDWARE_DISC hardware_disc;
- LOGICAL_DRIVE logical_drive[MAX_LOGICAL_DRIVES];
- DEVSTATE dev[MAX_CHANNELS][MAX_TARGETS+1];
+ IPS_HARDWARE hardware_disc;
+ IPS_LD logical_drive[IPS_MAX_LD];
+ IPS_DEVSTATE dev[IPS_MAX_CHANNELS][IPS_MAX_TARGETS+1];
u8 reserved[512];
-} CONFCMD, *PCONFCMD;
+} IPS_CONF, *PIPS_CONF;
typedef struct {
u32 signature;
@@ -583,11 +654,11 @@ typedef struct {
u8 driver_high[4];
u8 driver_low[4];
u8 reserved4[100];
-} NVRAM_PAGE5, *PNVRAM_PAGE5;
+} IPS_NVRAM_P5, *PIPS_NVRAM_P5;
-typedef struct _SUBSYS_PARAM {
+typedef struct _IPS_SUBSYS {
u32 param[128];
-} SUBSYS_PARAM, *PSUBSYS_PARAM;
+} IPS_SUBSYS, *PIPS_SUBSYS;
/*
* Inquiry Data Format
@@ -614,7 +685,7 @@ typedef struct {
u8 ProductRevisionLevel[4];
u8 VendorSpecific[20];
u8 Reserved3[40];
-} IPS_INQUIRYDATA, *IPS_PINQUIRYDATA;
+} IPS_INQ_DATA, *PIPS_INQ_DATA;
/*
* Read Capacity Data Format
@@ -622,7 +693,7 @@ typedef struct {
typedef struct {
u32 lba;
u32 len;
-} CAPACITY_T;
+} IPS_CAPACITY;
/*
* Sense Data Format
@@ -646,7 +717,7 @@ typedef struct {
u32 pg_rmb:1; /* Removeable */
u32 pg_hsec:1; /* Hard sector formatting */
u32 pg_ssec:1; /* Soft sector formatting */
-} DADF_T;
+} IPS_DADF;
typedef struct {
u8 pg_pc:6; /* Page Code */
@@ -662,9 +733,9 @@ typedef struct {
u32 pg_landu:16; /* Landing zone cylinder (upper) */
u32 pg_landl:8; /* Landing zone cylinder (lower) */
u32 pg_res2:24; /* Reserved */
-} RDDG_T;
+} IPS_RDDG;
-struct blk_desc {
+struct ips_blk_desc {
u8 bd_dencode;
u8 bd_nblks1;
u8 bd_nblks2;
@@ -681,15 +752,15 @@ typedef struct {
u8 plh_res:7; /* Reserved */
u8 plh_wp:1; /* Write protect */
u8 plh_bdl; /* Block descriptor length */
-} SENSE_PLH_T;
+} ips_sense_plh_t;
typedef struct {
- SENSE_PLH_T plh;
- struct blk_desc blk_desc;
+ ips_sense_plh_t plh;
+ struct ips_blk_desc blk_desc;
union {
- DADF_T pg3;
- RDDG_T pg4;
+ IPS_DADF pg3;
+ IPS_RDDG pg4;
} pdata;
} ips_mdata_t;
@@ -699,14 +770,14 @@ typedef struct {
typedef struct ips_sglist {
u32 address;
u32 length;
-} SG_LIST, *PSG_LIST;
+} IPS_SG_LIST, *PIPS_SG_LIST;
-typedef struct _INFOSTR {
+typedef struct _IPS_INFOSTR {
char *buffer;
int length;
int offset;
int pos;
-} INFOSTR;
+} IPS_INFOSTR;
/*
* Status Info
@@ -722,7 +793,9 @@ typedef struct ips_stat {
typedef struct ips_scb_queue {
struct ips_scb *head;
struct ips_scb *tail;
- unsigned int count;
+ u32 count;
+ u32 cpu_flags;
+ spinlock_t lock;
} ips_scb_queue_t;
/*
@@ -731,12 +804,28 @@ typedef struct ips_scb_queue {
typedef struct ips_wait_queue {
Scsi_Cmnd *head;
Scsi_Cmnd *tail;
- unsigned int count;
+ u32 count;
+ u32 cpu_flags;
+ spinlock_t lock;
} ips_wait_queue_t;
+typedef struct ips_copp_wait_item {
+ Scsi_Cmnd *scsi_cmd;
+ struct semaphore *sem;
+ struct ips_copp_wait_item *next;
+} ips_copp_wait_item_t;
+
+typedef struct ips_copp_queue {
+ struct ips_copp_wait_item *head;
+ struct ips_copp_wait_item *tail;
+ u32 count;
+ u32 cpu_flags;
+ spinlock_t lock;
+} ips_copp_queue_t;
+
typedef struct ips_ha {
- u8 ha_id[MAX_CHANNELS+1];
- u32 dcdb_active[MAX_CHANNELS];
+ u8 ha_id[IPS_MAX_CHANNELS+1];
+ u32 dcdb_active[IPS_MAX_CHANNELS];
u32 io_addr; /* Base I/O address */
u8 irq; /* IRQ for adapter */
u8 ntargets; /* Number of targets */
@@ -751,35 +840,39 @@ typedef struct ips_ha {
struct ips_scb *scbs; /* Array of all CCBS */
struct ips_scb *scb_freelist; /* SCB free list */
ips_wait_queue_t scb_waitlist; /* Pending SCB list */
- ips_wait_queue_t copp_waitlist; /* Pending PT list */
+ ips_copp_queue_t copp_waitlist; /* Pending PT list */
ips_scb_queue_t scb_activelist; /* Active SCB list */
- BASIC_IO_CMD *dummy; /* dummy command */
- ADAPTER_AREA *adapt; /* Adapter status area */
- ENQCMD *enq; /* Adapter Enquiry data */
- CONFCMD *conf; /* Adapter config data */
- NVRAM_PAGE5 *nvram; /* NVRAM page 5 data */
- SUBSYS_PARAM *subsys; /* Subsystem parameters */
+ IPS_IO_CMD *dummy; /* dummy command */
+ IPS_ADAPTER *adapt; /* Adapter status area */
+ IPS_ENQ *enq; /* Adapter Enquiry data */
+ IPS_CONF *conf; /* Adapter config data */
+ IPS_NVRAM_P5 *nvram; /* NVRAM page 5 data */
+ IPS_SUBSYS *subsys; /* Subsystem parameters */
+ char *ioctl_data; /* IOCTL data area */
+ u32 ioctl_datasize; /* IOCTL data size */
u32 cmd_in_progress; /* Current command in progress*/
u32 flags; /* HA flags */
u8 waitflag; /* are we waiting for cmd */
u8 active;
- u32 reserved:16; /* reserved space */
- wait_queue_head_t copp_queue; /* passthru sync queue */
+ u16 reset_count; /* number of resets */
+ u32 last_ffdc; /* last time we sent ffdc info*/
+ u8 revision_id; /* Revision level */
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
spinlock_t scb_lock;
spinlock_t copp_lock;
+ spinlock_t ips_lock;
#endif
} ips_ha_t;
-typedef void (*scb_callback) (ips_ha_t *, struct ips_scb *);
+typedef void (*ips_scb_callback) (ips_ha_t *, struct ips_scb *);
/*
* SCB Format
*/
typedef struct ips_scb {
- HOST_COMMAND cmd;
- DCDB_TABLE dcdb;
+ IPS_HOST_COMMAND cmd;
+ IPS_DCDB_TABLE dcdb;
u8 target_id;
u8 bus;
u8 lun;
@@ -794,32 +887,54 @@ typedef struct ips_scb {
u32 sg_len;
u32 flags;
u32 op_code;
- SG_LIST *sg_list;
+ IPS_SG_LIST *sg_list;
Scsi_Cmnd *scsi_cmd;
struct ips_scb *q_next;
- scb_callback callback;
+ ips_scb_callback callback;
+ struct semaphore *sem;
} ips_scb_t;
+typedef struct ips_scb_pt {
+ IPS_HOST_COMMAND cmd;
+ IPS_DCDB_TABLE dcdb;
+ u8 target_id;
+ u8 bus;
+ u8 lun;
+ u8 cdb[12];
+ u32 scb_busaddr;
+ u32 data_busaddr;
+ u32 timeout;
+ u8 basic_status;
+ u8 extended_status;
+ u16 breakup;
+ u32 data_len;
+ u32 sg_len;
+ u32 flags;
+ u32 op_code;
+ IPS_SG_LIST *sg_list;
+ Scsi_Cmnd *scsi_cmd;
+ struct ips_scb *q_next;
+ ips_scb_callback callback;
+} ips_scb_pt_t;
+
/*
* Passthru Command Format
*/
typedef struct {
- u8 CoppID[4];
- u32 CoppCmd;
- u32 PtBuffer;
- u8 *CmdBuffer;
- u32 CmdBSize;
- ips_scb_t CoppCP;
- u32 TimeOut;
- u8 BasicStatus;
- u8 ExtendedStatus;
- u16 reserved;
+ u8 CoppID[4];
+ u32 CoppCmd;
+ u32 PtBuffer;
+ u8 *CmdBuffer;
+ u32 CmdBSize;
+ ips_scb_pt_t CoppCP;
+ u32 TimeOut;
+ u8 BasicStatus;
+ u8 ExtendedStatus;
+ u16 reserved;
} ips_passthru_t;
#endif
-
-
/*
* Overrides for Emacs so that we almost follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically