]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/scsi/ips.c
[SCSI] ses: add subenclosure support
[linux-2.6.git] / drivers / scsi / ips.c
index 47c263e5cd39d355e15b061d6564cd131b47c249..b2511acd39bd3feeb7f87e6f956ffae6b8e73780 100644 (file)
 /* 6.10.00  - Remove 1G Addressing Limitations                               */
 /* 6.11.xx  - Get VersionInfo buffer off the stack !              DDTS 60401 */
 /* 6.11.xx  - Make Logical Drive Info structure safe for DMA      DDTS 60639 */
-/* 7.10.xx  - Add highmem_io flag in SCSI Templete for 2.4 kernels           */
+/* 7.10.18  - Add highmem_io flag in SCSI Templete for 2.4 kernels           */
 /*          - Fix path/name for scsi_hosts.h include for 2.6 kernels         */
 /*          - Fix sort order of 7k                                           */
 /*          - Remove 3 unused "inline" functions                             */
+/* 7.12.xx  - Use STATIC functions whereever possible                        */
+/*          - Clean up deprecated MODULE_PARM calls                          */
+/* 7.12.05  - Remove Version Matching per IBM request                        */
 /*****************************************************************************/
 
 /*
 #include <asm/byteorder.h>
 #include <asm/page.h>
 #include <linux/stddef.h>
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 
 #include <linux/blkdev.h>
 #include <linux/types.h>
+#include <linux/dma-mapping.h>
 
 #include <scsi/sg.h>
-
 #include "scsi.h"
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include "hosts.h"
-#else
 #include <scsi/scsi_host.h>
-#endif
 
 #include "ips.h"
 
 #include <linux/module.h>
 
 #include <linux/stat.h>
-#include <linux/config.h>
 
 #include <linux/spinlock.h>
 #include <linux/init.h>
@@ -207,33 +203,17 @@ module_param(ips, charp, 0);
 /*
  * DRIVER_VER
  */
-#define IPS_VERSION_HIGH        "7.10"
-#define IPS_VERSION_LOW         ".18 "
+#define IPS_VERSION_HIGH        IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING
+#define IPS_VERSION_LOW         "." IPS_VER_BUILD_STRING " "
 
 #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
 #endif
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-#include <linux/blk.h>
-#include "sd.h"
-#define IPS_SG_ADDRESS(sg)       ((sg)->address)
-#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
-#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
-#ifndef __devexit_p
-#define __devexit_p(x) x
-#endif
-#else
-#define IPS_SG_ADDRESS(sg)      (page_address((sg)->page) ? \
-                                   page_address((sg)->page)+(sg)->offset : NULL)
-#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
-#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
-#endif
-
 #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
-                         SCSI_DATA_NONE == scb->scsi_cmd->sc_data_direction) ? \
+                         DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
                          PCI_DMA_BIDIRECTIONAL : \
-                         scsi_to_pci_dma_dir(scb->scsi_cmd->sc_data_direction))
+                         scb->scsi_cmd->sc_data_direction)
 
 #ifdef IPS_DEBUG
 #define METHOD_TRACE(s, i)    if (ips_debug >= (i+10)) printk(KERN_NOTICE s "\n");
@@ -248,13 +228,13 @@ module_param(ips, charp, 0);
 /*
  * Function prototypes
  */
-static int ips_detect(Scsi_Host_Template *);
+static int ips_detect(struct scsi_host_template *);
 static int ips_release(struct Scsi_Host *);
-static int ips_eh_abort(Scsi_Cmnd *);
-static int ips_eh_reset(Scsi_Cmnd *);
-static int ips_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
+static int ips_eh_abort(struct scsi_cmnd *);
+static int ips_eh_reset(struct scsi_cmnd *);
+static int ips_queue(struct Scsi_Host *, struct scsi_cmnd *);
 static const char *ips_info(struct Scsi_Host *);
-static irqreturn_t do_ipsintr(int, void *, struct pt_regs *);
+static irqreturn_t do_ipsintr(int, void *);
 static int ips_hainit(ips_ha_t *);
 static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
 static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
@@ -325,37 +305,40 @@ static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
 static uint32_t ips_statupd_morpheus(ips_ha_t *);
 static ips_scb_t *ips_getscb(ips_ha_t *);
 static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, struct scsi_cmnd *);
 static void ips_putq_copp_tail(ips_copp_queue_t *,
                                      ips_copp_wait_item_t *);
 static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
 static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *,
+                                         struct scsi_cmnd *);
 static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
                                                     ips_copp_wait_item_t *);
 static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
 
-static int ips_is_passthru(Scsi_Cmnd *);
-static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
+static int ips_is_passthru(struct scsi_cmnd *);
+static int ips_make_passthru(ips_ha_t *, struct scsi_cmnd *, ips_scb_t *, int);
 static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
 static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
-static void ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data,
+static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data,
                               unsigned int count);
-static void ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned int count);
+static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
+                             unsigned int count);
 
 static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int ips_host_info(ips_ha_t *, char *, off_t, int);
 static void copy_mem_info(IPS_INFOSTR *, char *, int);
 static int copy_info(IPS_INFOSTR *, char *, ...);
-static int ips_get_version_info(ips_ha_t * ha, dma_addr_t, int intr);
-static void ips_version_check(ips_ha_t * ha, int intr);
 static int ips_abort_init(ips_ha_t * ha, int index);
 static int ips_init_phase2(int index);
 
 static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);
 static int ips_register_scsi(int index);
 
+static int  ips_poll_for_flush_complete(ips_ha_t * ha);
+static void ips_flush_and_reset(ips_ha_t *ha);
+
 /*
  * global variables
  */
@@ -376,7 +359,7 @@ static char *ips_FlashData = NULL;  /* CD Boot - Flash Data Buffer      */
 static dma_addr_t ips_flashbusaddr;
 static long ips_FlashDataInUse;                /* CD Boot - Flash Data In Use Flag */
 static uint32_t MaxLiteCmds = 32;      /* Max Active Cmds for a Lite Adapter */
-static Scsi_Host_Template ips_driver_template = {
+static struct scsi_host_template ips_driver_template = {
        .detect                 = ips_detect,
        .release                = ips_release,
        .info                   = ips_info,
@@ -384,28 +367,15 @@ static Scsi_Host_Template ips_driver_template = {
        .eh_abort_handler       = ips_eh_abort,
        .eh_host_reset_handler  = ips_eh_reset,
        .proc_name              = "ips",
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
        .proc_info              = ips_proc_info,
        .slave_configure        = ips_slave_configure,
-#else
-       .proc_info              = ips_proc24_info,
-       .select_queue_depths    = ips_select_queue_depth,
-#endif
        .bios_param             = ips_biosparam,
        .this_id                = -1,
        .sg_tablesize           = IPS_MAX_SG,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       .use_new_eh_code        = 1,
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-    .highmem_io          = 1,   
-#endif
 };
 
-static IPS_DEFINE_COMPAT_TABLE( Compatable );  /* Version Compatability Table      */
-
 
 /* This table describes all ServeRAID Adapters */
 static struct  pci_device_id  ips_pci_table[] = {
@@ -418,17 +388,17 @@ static struct  pci_device_id  ips_pci_table[] = {
 MODULE_DEVICE_TABLE( pci, ips_pci_table );
 
 static char ips_hot_plug_name[] = "ips";
-   
+
 static int __devinit  ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
 static void __devexit ips_remove_device(struct pci_dev *pci_dev);
-   
+
 static struct pci_driver ips_pci_driver = {
        .name           = ips_hot_plug_name,
        .id_table       = ips_pci_table,
        .probe          = ips_insert_device,
        .remove         = __devexit_p(ips_remove_device),
 };
-           
+
 
 /*
  * Necessary forward function protoypes
@@ -556,7 +526,7 @@ ips_setup(char *ips_str)
                 * We now have key/value pairs.
                 * Update the variables
                 */
-               for (i = 0; i < (sizeof (options) / sizeof (options[0])); i++) {
+               for (i = 0; i < ARRAY_SIZE(options); i++) {
                        if (strnicmp
                            (key, options[i].option_name,
                             strlen(options[i].option_name)) == 0) {
@@ -588,7 +558,7 @@ __setup("ips=", ips_setup);
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_detect(Scsi_Host_Template * SHT)
+ips_detect(struct scsi_host_template * SHT)
 {
        int i;
 
@@ -616,7 +586,7 @@ static void
 ips_setup_funclist(ips_ha_t * ha)
 {
 
-       /*                                
+       /*
         * Setup Functions
         */
        if (IPS_IS_MORPHEUS(ha) || IPS_IS_MARCO(ha)) {
@@ -685,6 +655,8 @@ ips_release(struct Scsi_Host *sh)
 
        METHOD_TRACE("ips_release", 1);
 
+       scsi_remove_host(sh);
+
        for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ;
 
        if (i == IPS_MAX_ADAPTERS) {
@@ -729,14 +701,9 @@ ips_release(struct Scsi_Host *sh)
        /* free extra memory */
        ips_free(ha);
 
-       /* Free I/O Region */
-       if (ha->io_addr)
-               release_region(ha->io_addr, ha->io_len);
-
        /* free IRQ */
-       free_irq(ha->irq, ha);
+       free_irq(ha->pcidev->irq, ha);
 
-       IPS_REMOVE_HOST(sh);
        scsi_host_put(sh);
 
        ips_released_controllers++;
@@ -813,18 +780,19 @@ ips_halt(struct notifier_block *nb, ulong event, void *buf)
 /*   Abort a command (using the new error code stuff)                       */
 /* Note: this routine is called under the io_request_lock                   */
 /****************************************************************************/
-int
-ips_eh_abort(Scsi_Cmnd * SC)
+int ips_eh_abort(struct scsi_cmnd *SC)
 {
        ips_ha_t *ha;
        ips_copp_wait_item_t *item;
        int ret;
+       struct Scsi_Host *host;
 
        METHOD_TRACE("ips_eh_abort", 1);
 
        if (!SC)
                return (FAILED);
 
+       host = SC->device->host;
        ha = (ips_ha_t *) SC->device->host->hostdata;
 
        if (!ha)
@@ -833,6 +801,8 @@ ips_eh_abort(Scsi_Cmnd * SC)
        if (!ha->active)
                return (FAILED);
 
+       spin_lock(host->host_lock);
+
        /* See if the command is on the copp queue */
        item = ha->copp_waitlist.head;
        while ((item) && (item->scsi_cmd != SC))
@@ -851,6 +821,8 @@ ips_eh_abort(Scsi_Cmnd * SC)
                /* command must have already been sent */
                ret = (FAILED);
        }
+
+       spin_unlock(host->host_lock);
        return ret;
 }
 
@@ -865,8 +837,7 @@ ips_eh_abort(Scsi_Cmnd * SC)
 /* NOTE: this routine is called under the io_request_lock spinlock          */
 /*                                                                          */
 /****************************************************************************/
-static int
-ips_eh_reset(Scsi_Cmnd * SC)
+static int __ips_eh_reset(struct scsi_cmnd *SC)
 {
        int ret;
        int i;
@@ -962,7 +933,7 @@ ips_eh_reset(Scsi_Cmnd * SC)
        ret = (*ha->func.reset) (ha);
 
        if (!ret) {
-               Scsi_Cmnd *scsi_cmd;
+               struct scsi_cmnd *scsi_cmd;
 
                IPS_PRINTK(KERN_NOTICE, ha->pcidev,
                           "Controller reset failed - controller now offline.\n");
@@ -991,7 +962,7 @@ ips_eh_reset(Scsi_Cmnd * SC)
        }
 
        if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
-               Scsi_Cmnd *scsi_cmd;
+               struct scsi_cmnd *scsi_cmd;
 
                IPS_PRINTK(KERN_NOTICE, ha->pcidev,
                           "Controller reset failed - controller now offline.\n");
@@ -1033,8 +1004,7 @@ ips_eh_reset(Scsi_Cmnd * SC)
        DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num);
 
        while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
-               scb->scsi_cmd->result =
-                   (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+               scb->scsi_cmd->result = DID_RESET << 16;
                scb->scsi_cmd->scsi_done(scb->scsi_cmd);
                ips_freescb(ha, scb);
        }
@@ -1053,6 +1023,17 @@ ips_eh_reset(Scsi_Cmnd * SC)
 
 }
 
+static int ips_eh_reset(struct scsi_cmnd *SC)
+{
+       int rc;
+
+       spin_lock_irq(SC->device->host->host_lock);
+       rc = __ips_eh_reset(SC);
+       spin_unlock_irq(SC->device->host->host_lock);
+
+       return rc;
+}
+
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_queue                                                  */
@@ -1065,8 +1046,7 @@ ips_eh_reset(Scsi_Cmnd * SC)
 /*    Linux obtains io_request_lock before calling this function            */
 /*                                                                          */
 /****************************************************************************/
-static int
-ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
+static int ips_queue_lck(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
 {
        ips_ha_t *ha;
        ips_passthru_t *pt;
@@ -1104,8 +1084,8 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
                  SC->device->channel, SC->device->id, SC->device->lun);
 
        /* Check for command to initiator IDs */
-       if ((SC->device->channel > 0)
-           && (SC->device->id == ha->ha_id[SC->device->channel])) {
+       if ((scmd_channel(SC) > 0)
+           && (scmd_id(SC) == ha->ha_id[scmd_channel(SC)])) {
                SC->result = DID_NO_CONNECT << 16;
                done(SC);
 
@@ -1119,7 +1099,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
                /* A Reset IOCTL is only sent by the boot CD in extreme cases.           */
                /* There can never be any system activity ( network or disk ), but check */
                /* anyway just as a good practice.                                       */
-               pt = (ips_passthru_t *) SC->request_buffer;
+               pt = (ips_passthru_t *) scsi_sglist(SC);
                if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
                    (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
                        if (ha->scb_activelist.count != 0) {
@@ -1128,7 +1108,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
                                return (0);
                        }
                        ha->ioctl_reset = 1;    /* This reset request is from an IOCTL */
-                       ips_eh_reset(SC);
+                       __ips_eh_reset(SC);
                        SC->result = DID_OK << 16;
                        SC->scsi_done(SC);
                        return (0);
@@ -1157,6 +1137,8 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
        return (0);
 }
 
+static DEF_SCSI_QCMD(ips_queue)
+
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_biosparam                                              */
@@ -1166,18 +1148,10 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
 /*   Set bios geometry for the controller                                   */
 /*                                                                          */
 /****************************************************************************/
-static int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ips_biosparam(Disk * disk, kdev_t dev, int geom[])
-{
-       ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
-       unsigned long capacity = disk->capacity;
-#else
-ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-             sector_t capacity, int geom[])
+static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+                        sector_t capacity, int geom[])
 {
        ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
-#endif
        int heads;
        int sectors;
        int cylinders;
@@ -1215,70 +1189,6 @@ ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
        return (0);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-/* ips_proc24_info is a wrapper around ips_proc_info *
- * for compatibility with the 2.4 scsi parameters    */
-static int
-ips_proc24_info(char *buffer, char **start, off_t offset, int length,
-                             int hostno, int func)
-{
-       int i;
-
-       for (i = 0; i < ips_next_controller; i++) {
-               if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
-                       return ips_proc_info(ips_sh[i], buffer, start,
-                                            offset, length, func);
-               }
-       }
-       return -EINVAL; 
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_select_queue_depth                                     */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Select queue depths for the devices on the contoller                   */
-/*                                                                          */
-/****************************************************************************/
-static void
-ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device * scsi_devs)
-{
-       Scsi_Device *device;
-       ips_ha_t *ha;
-       int count = 0;
-       int min;
-
-       ha = IPS_HA(host);
-       min = ha->max_cmds / 4;
-
-       for (device = scsi_devs; device; device = device->next) {
-               if (device->host == host) {
-                       if ((device->channel == 0) && (device->type == 0))
-                               count++;
-               }
-       }
-
-       for (device = scsi_devs; device; device = device->next) {
-               if (device->host == host) {
-                       if ((device->channel == 0) && (device->type == 0)) {
-                               device->queue_depth =
-                                   (ha->max_cmds - 1) / count;
-                               if (device->queue_depth < min)
-                                       device->queue_depth = min;
-                       } else {
-                               device->queue_depth = 2;
-                       }
-
-                       if (device->queue_depth < 2)
-                               device->queue_depth = 2;
-               }
-       }
-}
-
-#else
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_slave_configure                                        */
@@ -1289,7 +1199,7 @@ ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device * scsi_devs)
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_slave_configure(Scsi_Device * SDptr)
+ips_slave_configure(struct scsi_device * SDptr)
 {
        ips_ha_t *ha;
        int min;
@@ -1301,9 +1211,11 @@ ips_slave_configure(Scsi_Device * SDptr)
                        min = ha->max_cmds - 1;
                scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
        }
+
+       SDptr->skip_ms_page_8 = 1;
+       SDptr->skip_ms_page_3f = 1;
        return 0;
 }
-#endif
 
 /****************************************************************************/
 /*                                                                          */
@@ -1315,10 +1227,9 @@ ips_slave_configure(Scsi_Device * SDptr)
 /*                                                                          */
 /****************************************************************************/
 static irqreturn_t
-do_ipsintr(int irq, void *dev_id, struct pt_regs * regs)
+do_ipsintr(int irq, void *dev_id)
 {
        ips_ha_t *ha;
-       unsigned long cpu_flags;
        struct Scsi_Host *host;
        int irqstatus;
 
@@ -1334,16 +1245,16 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs * regs)
                return IRQ_HANDLED;
        }
 
-       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+       spin_lock(host->host_lock);
 
        if (!ha->active) {
-               IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+               spin_unlock(host->host_lock);
                return IRQ_HANDLED;
        }
 
        irqstatus = (*ha->func.intr) (ha);
 
-       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+       spin_unlock(host->host_lock);
 
        /* start the next command */
        ips_next(ha, IPS_INTR_ON);
@@ -1398,7 +1309,7 @@ ips_intr_copperhead(ips_ha_t * ha)
                        cstatus.value = (*ha->func.statupd) (ha);
 
                if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
-                       /* Spurious Interupt ? */
+                       /* Spurious Interrupt ? */
                        continue;
                }
 
@@ -1581,9 +1492,10 @@ ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 /*   Determine if the specified SCSI command is really a passthru command   */
 /*                                                                          */
 /****************************************************************************/
-static int
-ips_is_passthru(Scsi_Cmnd * SC)
+static int ips_is_passthru(struct scsi_cmnd *SC)
 {
+       unsigned long flags;
+
        METHOD_TRACE("ips_is_passthru", 1);
 
        if (!SC)
@@ -1592,20 +1504,22 @@ ips_is_passthru(Scsi_Cmnd * SC)
        if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
            (SC->device->channel == 0) &&
            (SC->device->id == IPS_ADAPTER_ID) &&
-           (SC->device->lun == 0) && SC->request_buffer) {
-               if ((!SC->use_sg) && SC->request_bufflen &&
-                   (((char *) SC->request_buffer)[0] == 'C') &&
-                   (((char *) SC->request_buffer)[1] == 'O') &&
-                   (((char *) SC->request_buffer)[2] == 'P') &&
-                   (((char *) SC->request_buffer)[3] == 'P'))
-                       return 1;
-               else if (SC->use_sg) {
-                       struct scatterlist *sg = SC->request_buffer;
-                       char *buffer = IPS_SG_ADDRESS(sg);
-                       if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
-                           buffer[2] == 'P' && buffer[3] == 'P')
-                               return 1;
-               }
+           (SC->device->lun == 0) && scsi_sglist(SC)) {
+                struct scatterlist *sg = scsi_sglist(SC);
+                char  *buffer;
+
+                /* kmap_atomic() ensures addressability of the user buffer.*/
+                /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                local_irq_save(flags);
+                buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+                if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
+                    buffer[2] == 'P' && buffer[3] == 'P') {
+                        kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                        local_irq_restore(flags);
+                        return 1;
+                }
+                kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                local_irq_restore(flags);
        }
        return 0;
 }
@@ -1652,22 +1566,18 @@ ips_alloc_passthru_buffer(ips_ha_t * ha, int length)
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_make_passthru(ips_ha_t * ha, Scsi_Cmnd * SC, ips_scb_t * scb, int intr)
+ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr)
 {
        ips_passthru_t *pt;
        int length = 0;
-       int ret;
+       int i, ret;
+        struct scatterlist *sg = scsi_sglist(SC);
 
        METHOD_TRACE("ips_make_passthru", 1);
 
-       if (!SC->use_sg) {
-               length = SC->request_bufflen;
-       } else {
-               struct scatterlist *sg = SC->request_buffer;
-               int i;
-               for (i = 0; i < SC->use_sg; i++)
-                       length += sg[i].length;
-       }
+        scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
+               length += sg->length;
+
        if (length < sizeof (ips_passthru_t)) {
                /* wrong size */
                DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
@@ -1723,7 +1633,7 @@ ips_make_passthru(ips_ha_t * ha, Scsi_Cmnd * SC, ips_scb_t * scb, int intr)
                                return (IPS_FAILURE);
                        }
 
-                       if (ha->device_id == IPS_DEVICEID_COPPERHEAD &&
+                       if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
                            pt->CoppCP.cmd.flashfw.op_code ==
                            IPS_CMD_RW_BIOSFW) {
                                ret = ips_flash_copperhead(ha, pt, scb);
@@ -2091,7 +2001,7 @@ ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb)
 
        METHOD_TRACE("ips_cleanup_passthru", 1);
 
-       if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
+       if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
                DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
                          ips_name, ha->host_num);
 
@@ -2107,7 +2017,7 @@ ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb)
        pt->ExtendedStatus = scb->extended_status;
        pt->AdapterType = ha->ad_type;
 
-       if (ha->device_id == IPS_DEVICEID_COPPERHEAD &&
+       if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
            (scb->cmd.flashfw.op_code == IPS_CMD_DOWNLOAD ||
             scb->cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW))
                ips_free_flash_copperhead(ha);
@@ -2161,13 +2071,13 @@ ips_host_info(ips_ha_t * ha, char *ptr, off_t offset, int len)
                          ha->mem_ptr);
        }
 
-       copy_info(&info, "\tIRQ number                        : %d\n", ha->irq);
+       copy_info(&info, "\tIRQ number                        : %d\n", ha->pcidev->irq);
 
     /* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
     /* That keeps everything happy for "text" operations on the proc file.                    */
 
        if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
-        if (ha->nvram->bios_low[3] == 0) { 
+       if (ha->nvram->bios_low[3] == 0) {
             copy_info(&info,
                                  "\tBIOS Version                      : %c%c%c%c%c%c%c\n",
                                  ha->nvram->bios_high[0], ha->nvram->bios_high[1],
@@ -2318,31 +2228,31 @@ ips_identify_controller(ips_ha_t * ha)
 {
        METHOD_TRACE("ips_identify_controller", 1);
 
-       switch (ha->device_id) {
+       switch (ha->pcidev->device) {
        case IPS_DEVICEID_COPPERHEAD:
-               if (ha->revision_id <= IPS_REVID_SERVERAID) {
+               if (ha->pcidev->revision <= IPS_REVID_SERVERAID) {
                        ha->ad_type = IPS_ADTYPE_SERVERAID;
-               } else if (ha->revision_id == IPS_REVID_SERVERAID2) {
+               } else if (ha->pcidev->revision == IPS_REVID_SERVERAID2) {
                        ha->ad_type = IPS_ADTYPE_SERVERAID2;
-               } else if (ha->revision_id == IPS_REVID_NAVAJO) {
+               } else if (ha->pcidev->revision == IPS_REVID_NAVAJO) {
                        ha->ad_type = IPS_ADTYPE_NAVAJO;
-               } else if ((ha->revision_id == IPS_REVID_SERVERAID2)
+               } else if ((ha->pcidev->revision == IPS_REVID_SERVERAID2)
                           && (ha->slot_num == 0)) {
                        ha->ad_type = IPS_ADTYPE_KIOWA;
-               } else if ((ha->revision_id >= IPS_REVID_CLARINETP1) &&
-                          (ha->revision_id <= IPS_REVID_CLARINETP3)) {
+               } else if ((ha->pcidev->revision >= IPS_REVID_CLARINETP1) &&
+                          (ha->pcidev->revision <= IPS_REVID_CLARINETP3)) {
                        if (ha->enq->ucMaxPhysicalDevices == 15)
                                ha->ad_type = IPS_ADTYPE_SERVERAID3L;
                        else
                                ha->ad_type = IPS_ADTYPE_SERVERAID3;
-               } else if ((ha->revision_id >= IPS_REVID_TROMBONE32) &&
-                          (ha->revision_id <= IPS_REVID_TROMBONE64)) {
+               } else if ((ha->pcidev->revision >= IPS_REVID_TROMBONE32) &&
+                          (ha->pcidev->revision <= IPS_REVID_TROMBONE64)) {
                        ha->ad_type = IPS_ADTYPE_SERVERAID4H;
                }
                break;
 
        case IPS_DEVICEID_MORPHEUS:
-               switch (ha->subdevice_id) {
+               switch (ha->pcidev->subsystem_device) {
                case IPS_SUBDEVICEID_4L:
                        ha->ad_type = IPS_ADTYPE_SERVERAID4L;
                        break;
@@ -2371,7 +2281,7 @@ ips_identify_controller(ips_ha_t * ha)
                break;
 
        case IPS_DEVICEID_MARCO:
-               switch (ha->subdevice_id) {
+               switch (ha->pcidev->subsystem_device) {
                case IPS_SUBDEVICEID_6M:
                        ha->ad_type = IPS_ADTYPE_SERVERAID6M;
                        break;
@@ -2418,20 +2328,20 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
 
        strncpy(ha->bios_version, "       ?", 8);
 
-       if (ha->device_id == IPS_DEVICEID_COPPERHEAD) {
+       if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD) {
                if (IPS_USE_MEMIO(ha)) {
                        /* Memory Mapped I/O */
 
                        /* test 1st byte */
                        writel(0, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
                                return;
 
                        writel(1, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
@@ -2439,20 +2349,20 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
 
                        /* Get Major version */
                        writel(0x1FF, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        major = readb(ha->mem_ptr + IPS_REG_FLDP);
 
                        /* Get Minor version */
                        writel(0x1FE, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
                        minor = readb(ha->mem_ptr + IPS_REG_FLDP);
 
                        /* Get SubMinor version */
                        writel(0x1FD, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
                        subminor = readb(ha->mem_ptr + IPS_REG_FLDP);
 
@@ -2461,36 +2371,36 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
 
                        /* test 1st byte */
                        outl(0, ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
                                return;
 
-                       outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       outl(1, ha->io_addr + IPS_REG_FLAP);
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
                                return;
 
                        /* Get Major version */
-                       outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       outl(0x1FF, ha->io_addr + IPS_REG_FLAP);
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        major = inb(ha->io_addr + IPS_REG_FLDP);
 
                        /* Get Minor version */
-                       outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       outl(0x1FE, ha->io_addr + IPS_REG_FLAP);
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        minor = inb(ha->io_addr + IPS_REG_FLDP);
 
                        /* Get SubMinor version */
-                       outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       outl(0x1FD, ha->io_addr + IPS_REG_FLAP);
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        subminor = inb(ha->io_addr + IPS_REG_FLDP);
@@ -2701,12 +2611,11 @@ static void
 ips_next(ips_ha_t * ha, int intr)
 {
        ips_scb_t *scb;
-       Scsi_Cmnd *SC;
-       Scsi_Cmnd *p;
-       Scsi_Cmnd *q;
+       struct scsi_cmnd *SC;
+       struct scsi_cmnd *p;
+       struct scsi_cmnd *q;
        ips_copp_wait_item_t *item;
        int ret;
-       unsigned long cpu_flags = 0;
        struct Scsi_Host *host;
        METHOD_TRACE("ips_next", 1);
 
@@ -2718,7 +2627,7 @@ ips_next(ips_ha_t * ha, int intr)
         * this command won't time out
         */
        if (intr == IPS_INTR_ON)
-               IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+               spin_lock(host->host_lock);
 
        if ((ha->subsys->param[3] & 0x300000)
            && (ha->scb_activelist.count == 0)) {
@@ -2745,14 +2654,14 @@ ips_next(ips_ha_t * ha, int intr)
                item = ips_removeq_copp_head(&ha->copp_waitlist);
                ha->num_ioctl++;
                if (intr == IPS_INTR_ON)
-                       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+                       spin_unlock(host->host_lock);
                scb->scsi_cmd = item->scsi_cmd;
                kfree(item);
 
                ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
 
                if (intr == IPS_INTR_ON)
-                       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+                       spin_lock(host->host_lock);
                switch (ret) {
                case IPS_FAILURE:
                        if (scb->scsi_cmd) {
@@ -2809,12 +2718,12 @@ ips_next(ips_ha_t * ha, int intr)
 
        p = ha->scb_waitlist.head;
        while ((p) && (scb = ips_getscb(ha))) {
-               if ((p->device->channel > 0)
+               if ((scmd_channel(p) > 0)
                    && (ha->
-                       dcdb_active[p->device->channel -
-                                   1] & (1 << p->device->id))) {
+                       dcdb_active[scmd_channel(p) -
+                                   1] & (1 << scmd_id(p)))) {
                        ips_freescb(ha, scb);
-                       p = (Scsi_Cmnd *) p->host_scribble;
+                       p = (struct scsi_cmnd *) p->host_scribble;
                        continue;
                }
 
@@ -2822,13 +2731,11 @@ ips_next(ips_ha_t * ha, int intr)
                SC = ips_removeq_wait(&ha->scb_waitlist, q);
 
                if (intr == IPS_INTR_ON)
-                       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */
+                       spin_unlock(host->host_lock);   /* Unlock HA after command is taken off queue */
 
                SC->result = DID_OK;
                SC->host_scribble = NULL;
 
-               memset(SC->sense_buffer, 0, sizeof (SC->sense_buffer));
-
                scb->target_id = SC->device->id;
                scb->lun = SC->device->lun;
                scb->bus = SC->device->channel;
@@ -2842,52 +2749,36 @@ ips_next(ips_ha_t * ha, int intr)
                /* copy in the CDB */
                memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
 
-               /* Now handle the data buffer */
-               if (SC->use_sg) {
+                scb->sg_count = scsi_dma_map(SC);
+                BUG_ON(scb->sg_count < 0);
+               if (scb->sg_count) {
                        struct scatterlist *sg;
                        int i;
 
-                       sg = SC->request_buffer;
-                       scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
-                                                  scsi_to_pci_dma_dir(SC->
-                                                                      sc_data_direction));
                        scb->flags |= IPS_SCB_MAP_SG;
-                       for (i = 0; i < scb->sg_count; i++) {
+
+                        scsi_for_each_sg(SC, sg, scb->sg_count, i) {
                                if (ips_fill_scb_sg_single
-                                   (ha, sg_dma_address(&sg[i]), scb, i,
-                                    sg_dma_len(&sg[i])) < 0)
+                                   (ha, sg_dma_address(sg), scb, i,
+                                    sg_dma_len(sg)) < 0)
                                        break;
                        }
                        scb->dcdb.transfer_length = scb->data_len;
                } else {
-                       if (SC->request_bufflen) {
-                               scb->data_busaddr =
-                                   pci_map_single(ha->pcidev,
-                                                  SC->request_buffer,
-                                                  SC->request_bufflen,
-                                                  scsi_to_pci_dma_dir(SC->
-                                                                      sc_data_direction));
-                               scb->flags |= IPS_SCB_MAP_SINGLE;
-                               ips_fill_scb_sg_single(ha, scb->data_busaddr,
-                                                      scb, 0,
-                                                      SC->request_bufflen);
-                               scb->dcdb.transfer_length = scb->data_len;
-                       } else {
-                               scb->data_busaddr = 0L;
-                               scb->sg_len = 0;
-                               scb->data_len = 0;
-                               scb->dcdb.transfer_length = 0;
-                       }
-
+                        scb->data_busaddr = 0L;
+                        scb->sg_len = 0;
+                        scb->data_len = 0;
+                        scb->dcdb.transfer_length = 0;
                }
 
                scb->dcdb.cmd_attribute =
                    ips_command_direction[scb->scsi_cmd->cmnd[0]];
 
-        /* Allow a WRITE BUFFER Command to Have no Data */
-        /* This is Used by Tape Flash Utilites          */
-        if ((scb->scsi_cmd->cmnd[0] == WRITE_BUFFER) && (scb->data_len == 0)) 
-            scb->dcdb.cmd_attribute = 0;                  
+               /* Allow a WRITE BUFFER Command to Have no Data */
+               /* This is Used by Tape Flash Utilites          */
+               if ((scb->scsi_cmd->cmnd[0] == WRITE_BUFFER) &&
+                               (scb->data_len == 0))
+                       scb->dcdb.cmd_attribute = 0;
 
                if (!(scb->dcdb.cmd_attribute & 0x3))
                        scb->dcdb.transfer_length = 0;
@@ -2897,7 +2788,7 @@ ips_next(ips_ha_t * ha, int intr)
                        scb->dcdb.transfer_length = 0;
                }
                if (intr == IPS_INTR_ON)
-                       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+                       spin_lock(host->host_lock);
 
                ret = ips_send_cmd(ha, scb);
 
@@ -2931,12 +2822,12 @@ ips_next(ips_ha_t * ha, int intr)
                        break;
                }               /* end case */
 
-               p = (Scsi_Cmnd *) p->host_scribble;
+               p = (struct scsi_cmnd *) p->host_scribble;
 
        }                       /* end while */
 
        if (intr == IPS_INTR_ON)
-               IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+               spin_unlock(host->host_lock);
 }
 
 /****************************************************************************/
@@ -3059,8 +2950,7 @@ ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static void
-ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
 {
        METHOD_TRACE("ips_putq_wait_tail", 1);
 
@@ -3091,10 +2981,9 @@ ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static Scsi_Cmnd *
-ips_removeq_wait_head(ips_wait_queue_t * queue)
+static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
 {
-       Scsi_Cmnd *item;
+       struct scsi_cmnd *item;
 
        METHOD_TRACE("ips_removeq_wait_head", 1);
 
@@ -3104,7 +2993,7 @@ ips_removeq_wait_head(ips_wait_queue_t * queue)
                return (NULL);
        }
 
-       queue->head = (Scsi_Cmnd *) item->host_scribble;
+       queue->head = (struct scsi_cmnd *) item->host_scribble;
        item->host_scribble = NULL;
 
        if (queue->tail == item)
@@ -3126,10 +3015,10 @@ ips_removeq_wait_head(ips_wait_queue_t * queue)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static Scsi_Cmnd *
-ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *queue,
+                                         struct scsi_cmnd *item)
 {
-       Scsi_Cmnd *p;
+       struct scsi_cmnd *p;
 
        METHOD_TRACE("ips_removeq_wait", 1);
 
@@ -3142,8 +3031,8 @@ ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 
        p = queue->head;
 
-       while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
-               p = (Scsi_Cmnd *) p->host_scribble;
+       while ((p) && (item != (struct scsi_cmnd *) p->host_scribble))
+               p = (struct scsi_cmnd *) p->host_scribble;
 
        if (p) {
                /* found a match */
@@ -3357,52 +3246,34 @@ ips_done(ips_ha_t * ha, ips_scb_t * scb)
                 * the rest of the data and continue.
                 */
                if ((scb->breakup) || (scb->sg_break)) {
+                        struct scatterlist *sg;
+                        int i, sg_dma_index, ips_sg_index = 0;
+
                        /* we had a data breakup */
                        scb->data_len = 0;
 
-                       if (scb->sg_count) {
-                               /* S/G request */
-                               struct scatterlist *sg;
-                               int ips_sg_index = 0;
-                               int sg_dma_index;
-
-                               sg = scb->scsi_cmd->request_buffer;
-
-                               /* Spin forward to last dma chunk */
-                               sg_dma_index = scb->breakup;
-
-                               /* Take care of possible partial on last chunk */
-                               ips_fill_scb_sg_single(ha,
-                                                      sg_dma_address(&sg
-                                                                     [sg_dma_index]),
-                                                      scb, ips_sg_index++,
-                                                      sg_dma_len(&sg
-                                                                 [sg_dma_index]));
-
-                               for (; sg_dma_index < scb->sg_count;
-                                    sg_dma_index++) {
-                                       if (ips_fill_scb_sg_single
-                                           (ha,
-                                            sg_dma_address(&sg[sg_dma_index]),
-                                            scb, ips_sg_index++,
-                                            sg_dma_len(&sg[sg_dma_index])) < 0)
-                                               break;
-
-                               }
-
-                       } else {
-                               /* Non S/G Request */
-                               (void) ips_fill_scb_sg_single(ha,
-                                                             scb->
-                                                             data_busaddr +
-                                                             (scb->sg_break *
-                                                              ha->max_xfer),
-                                                             scb, 0,
-                                                             scb->scsi_cmd->
-                                                             request_bufflen -
-                                                             (scb->sg_break *
-                                                              ha->max_xfer));
-                       }
+                        sg = scsi_sglist(scb->scsi_cmd);
+
+                        /* Spin forward to last dma chunk */
+                        sg_dma_index = scb->breakup;
+                        for (i = 0; i < scb->breakup; i++)
+                                sg = sg_next(sg);
+
+                       /* Take care of possible partial on last chunk */
+                        ips_fill_scb_sg_single(ha,
+                                               sg_dma_address(sg),
+                                               scb, ips_sg_index++,
+                                               sg_dma_len(sg));
+
+                        for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
+                             sg_dma_index++, sg = sg_next(sg)) {
+                                if (ips_fill_scb_sg_single
+                                    (ha,
+                                     sg_dma_address(sg),
+                                     scb, ips_sg_index++,
+                                     sg_dma_len(sg)) < 0)
+                                        break;
+                        }
 
                        scb->dcdb.transfer_length = scb->data_len;
                        scb->dcdb.cmd_attribute |=
@@ -3468,6 +3339,7 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
        int device_error;
        uint32_t transfer_len;
        IPS_DCDB_TABLE_TAPE *tapeDCDB;
+       IPS_SCSI_INQ_DATA inquiryData;
 
        METHOD_TRACE("ips_map_status", 1);
 
@@ -3526,13 +3398,13 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
                                errcode = DID_OK;
 
                                /* Restrict access to physical DASD */
-                               if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
-                                   ((((char *) scb->scsi_cmd->
-                                      buffer)[0] & 0x1f) == TYPE_DISK)) {
-                                       /* underflow -- no error               */
-                                       /* restrict access to physical DASD    */
-                                       errcode = DID_TIME_OUT;
-                                       break;
+                               if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+                                   ips_scmd_buf_read(scb->scsi_cmd,
+                                      &inquiryData, sizeof (inquiryData));
+                                   if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) {
+                                       errcode = DID_TIME_OUT;
+                                       break;
+                                   }
                                }
                        } else
                                errcode = DID_ERROR;
@@ -3561,13 +3433,11 @@ ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
                                            (IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
                                        memcpy(scb->scsi_cmd->sense_buffer,
                                               tapeDCDB->sense_info,
-                                              sizeof (scb->scsi_cmd->
-                                                      sense_buffer));
+                                              SCSI_SENSE_BUFFERSIZE);
                                } else {
                                        memcpy(scb->scsi_cmd->sense_buffer,
                                               scb->dcdb.sense_info,
-                                              sizeof (scb->scsi_cmd->
-                                                      sense_buffer));
+                                              SCSI_SENSE_BUFFERSIZE);
                                }
                                device_error = 2;       /* check condition */
                        }
@@ -3627,31 +3497,16 @@ ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr)
 /* Routine Name: ips_scmd_buf_write                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
-/*  Write data to Scsi_Cmnd request_buffer at proper offsets                */
+/*  Write data to struct scsi_cmnd request_buffer at proper offsets        */
 /****************************************************************************/
 static void
-ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data, unsigned
-                  int count)
+ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
-       if (scmd->use_sg) {
-               int i;
-               unsigned int min_cnt, xfer_cnt;
-               char *cdata = (char *) data;
-               struct scatterlist *sg = scmd->request_buffer;
-               for (i = 0, xfer_cnt = 0;
-                    (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-                       if (!IPS_SG_ADDRESS(&sg[i]))
-                               return;
-                       min_cnt = min(count - xfer_cnt, sg[i].length);
-                       memcpy(IPS_SG_ADDRESS(&sg[i]), &cdata[xfer_cnt],
-                              min_cnt);
-                       xfer_cnt += min_cnt;
-               }
+       unsigned long flags;
 
-       } else {
-               unsigned int min_cnt = min(count, scmd->request_bufflen);
-               memcpy(scmd->request_buffer, data, min_cnt);
-       }
+       local_irq_save(flags);
+       scsi_sg_copy_from_buffer(scmd, data, count);
+       local_irq_restore(flags);
 }
 
 /****************************************************************************/
@@ -3659,31 +3514,16 @@ ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data, unsigned
 /* Routine Name: ips_scmd_buf_read                                          */
 /*                                                                          */
 /* Routine Description:                                                     */
-/*  Copy data from a Scsi_Cmnd to a new, linear buffer                      */
+/*  Copy data from a struct scsi_cmnd to a new, linear buffer              */
 /****************************************************************************/
 static void
-ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned
-                 int count)
+ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
-       if (scmd->use_sg) {
-               int i;
-               unsigned int min_cnt, xfer_cnt;
-               char *cdata = (char *) data;
-               struct scatterlist *sg = scmd->request_buffer;
-               for (i = 0, xfer_cnt = 0;
-                    (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-                       if (!IPS_SG_ADDRESS(&sg[i]))
-                               return;
-                       min_cnt = min(count - xfer_cnt, sg[i].length);
-                       memcpy(&cdata[xfer_cnt], IPS_SG_ADDRESS(&sg[i]),
-                              min_cnt);
-                       xfer_cnt += min_cnt;
-               }
+       unsigned long flags;
 
-       } else {
-               unsigned int min_cnt = min(count, scmd->request_bufflen);
-               memcpy(data, scmd->request_buffer, min_cnt);
-       }
+       local_irq_save(flags);
+       scsi_sg_copy_to_buffer(scmd, data, count);
+       local_irq_restore(flags);
 }
 
 /****************************************************************************/
@@ -3824,9 +3664,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
                        scb->cmd.basic_io.sg_count = scb->sg_len;
 
                        if (scb->cmd.basic_io.lba)
-                               scb->cmd.basic_io.lba =
-                                   cpu_to_le32(le32_to_cpu
-                                               (scb->cmd.basic_io.lba) +
+                               le32_add_cpu(&scb->cmd.basic_io.lba,
                                                le16_to_cpu(scb->cmd.basic_io.
                                                            sector_count));
                        else
@@ -3872,9 +3710,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
                        scb->cmd.basic_io.sg_count = scb->sg_len;
 
                        if (scb->cmd.basic_io.lba)
-                               scb->cmd.basic_io.lba =
-                                   cpu_to_le32(le32_to_cpu
-                                               (scb->cmd.basic_io.lba) +
+                               le32_add_cpu(&scb->cmd.basic_io.lba,
                                                le16_to_cpu(scb->cmd.basic_io.
                                                            sector_count));
                        else
@@ -3945,7 +3781,6 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
                        /* attempted, a Check Condition occurred, and Sense   */
                        /* Data indicating an Invalid CDB OpCode is returned. */
                        sp = (char *) scb->scsi_cmd->sense_buffer;
-                       memset(sp, 0, sizeof (scb->scsi_cmd->sense_buffer));
 
                        sp[0] = 0x70;   /* Error Code               */
                        sp[2] = ILLEGAL_REQUEST;        /* Sense Key 5 Illegal Req. */
@@ -3984,7 +3819,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
                scb->cmd.dcdb.segment_4G = 0;
                scb->cmd.dcdb.enhanced_sg = 0;
 
-               TimeOut = scb->scsi_cmd->timeout_per_command;
+               TimeOut = scb->scsi_cmd->request->timeout;
 
                if (ha->subsys->param[4] & 0x00100000) {        /* If NEW Tape DCDB is Supported */
                        if (!scb->sg_len) {
@@ -4090,6 +3925,7 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus)
        uint8_t basic_status;
        uint8_t ext_status;
        int errcode;
+       IPS_SCSI_INQ_DATA inquiryData;
 
        METHOD_TRACE("ips_chkstatus", 1);
 
@@ -4210,11 +4046,11 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus)
                        scb->scsi_cmd->result = errcode << 16;
                } else {        /* bus == 0 */
                        /* restrict access to physical drives */
-                       if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
-                           ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) ==
-                            TYPE_DISK)) {
-
-                               scb->scsi_cmd->result = DID_TIME_OUT << 16;
+                       if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+                           ips_scmd_buf_read(scb->scsi_cmd,
+                                  &inquiryData, sizeof (inquiryData));
+                           if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK)
+                               scb->scsi_cmd->result = DID_TIME_OUT << 16;
                        }
                }               /* else */
        } else {                /* recovered error / success */
@@ -4316,7 +4152,7 @@ ips_rdcap(ips_ha_t * ha, ips_scb_t * scb)
 
        METHOD_TRACE("ips_rdcap", 1);
 
-       if (scb->scsi_cmd->bufflen < 8)
+       if (scsi_bufflen(scb->scsi_cmd) < 8)
                return (0);
 
        cap.lba =
@@ -4472,10 +4308,8 @@ ips_free(ips_ha_t * ha)
                        ha->enq = NULL;
                }
 
-               if (ha->conf) {
-                       kfree(ha->conf);
-                       ha->conf = NULL;
-               }
+               kfree(ha->conf);
+               ha->conf = NULL;
 
                if (ha->adapt) {
                        pci_free_consistent(ha->pcidev,
@@ -4493,15 +4327,11 @@ ips_free(ips_ha_t * ha)
                        ha->logical_drive_info = NULL;
                }
 
-               if (ha->nvram) {
-                       kfree(ha->nvram);
-                       ha->nvram = NULL;
-               }
+               kfree(ha->nvram);
+               ha->nvram = NULL;
 
-               if (ha->subsys) {
-                       kfree(ha->subsys);
-                       ha->subsys = NULL;
-               }
+               kfree(ha->subsys);
+               ha->subsys = NULL;
 
                if (ha->ioctl_data) {
                        pci_free_consistent(ha->pcidev, ha->ioctl_len,
@@ -4519,8 +4349,6 @@ ips_free(ips_ha_t * ha)
                        ha->mem_ptr = NULL;
                }
 
-               if (ha->mem_addr)
-                       release_mem_region(ha->mem_addr, ha->mem_len);
                ha->mem_addr = 0;
 
        }
@@ -4707,8 +4535,7 @@ ips_freescb(ips_ha_t * ha, ips_scb_t * scb)
 
        METHOD_TRACE("ips_freescb", 1);
        if (scb->flags & IPS_SCB_MAP_SG)
-               pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer,
-                            scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb));
+                scsi_dma_unmap(scb->scsi_cmd);
        else if (scb->flags & IPS_SCB_MAP_SINGLE)
                pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
                                 IPS_DMA_DIR(scb));
@@ -4789,6 +4616,9 @@ ips_isinit_morpheus(ips_ha_t * ha)
 
        METHOD_TRACE("ips_is_init_morpheus", 1);
 
+       if (ips_isintr_morpheus(ha))
+           ips_flush_and_reset(ha);
+
        post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
        bits = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
 
@@ -4800,6 +4630,94 @@ ips_isinit_morpheus(ips_ha_t * ha)
                return (1);
 }
 
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_flush_and_reset                                        */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Perform cleanup ( FLUSH and RESET ) when the adapter is in an unknown  */
+/*   state ( was trying to INIT and an interrupt was already pending ) ...  */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_flush_and_reset(ips_ha_t *ha)
+{
+       ips_scb_t *scb;
+       int  ret;
+       int  time;
+       int  done;
+       dma_addr_t command_dma;
+
+       /* Create a usuable SCB */
+       scb = pci_alloc_consistent(ha->pcidev, sizeof(ips_scb_t), &command_dma);
+       if (scb) {
+           memset(scb, 0, sizeof(ips_scb_t));
+           ips_init_scb(ha, scb);
+           scb->scb_busaddr = command_dma;
+
+           scb->timeout = ips_cmd_timeout;
+           scb->cdb[0] = IPS_CMD_FLUSH;
+
+           scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
+           scb->cmd.flush_cache.command_id = IPS_MAX_CMDS;   /* Use an ID that would otherwise not exist */
+           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;
+           scb->cmd.flush_cache.reserved4 = 0;
+
+           ret = ips_send_cmd(ha, scb);                      /* Send the Flush Command */
+
+           if (ret == IPS_SUCCESS) {
+               time = 60 * IPS_ONE_SEC;                      /* Max Wait time is 60 seconds */
+               done = 0;
+
+               while ((time > 0) && (!done)) {
+                  done = ips_poll_for_flush_complete(ha);
+                  /* This may look evil, but it's only done during extremely rare start-up conditions ! */
+                  udelay(1000);
+                  time--;
+               }
+        }
+       }
+
+       /* Now RESET and INIT the adapter */
+       (*ha->func.reset) (ha);
+
+       pci_free_consistent(ha->pcidev, sizeof(ips_scb_t), scb, command_dma);
+       return;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_poll_for_flush_complete                                */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Poll for the Flush Command issued by ips_flush_and_reset() to complete */
+/*   All other responses are just taken off the queue and ignored           */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_poll_for_flush_complete(ips_ha_t * ha)
+{
+       IPS_STATUS cstatus;
+
+       while (TRUE) {
+           cstatus.value = (*ha->func.statupd) (ha);
+
+           if (cstatus.value == 0xffffffff)      /* If No Interrupt to process */
+                       break;
+
+           /* Success is when we see the Flush Command ID */
+           if (cstatus.fields.command_id == IPS_MAX_CMDS)
+               return 1;
+        }
+
+       return 0;
+}
+
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_enable_int_copperhead                                  */
@@ -4934,12 +4852,12 @@ ips_init_copperhead(ips_ha_t * ha)
                return (0);
 
        /* setup CCCR */
-       outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
+       outl(0x1010, ha->io_addr + IPS_REG_CCCR);
 
        /* Enable busmastering */
        outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
 
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                /* fix for anaconda64 */
                outl(0, ha->io_addr + IPS_REG_NDAE);
 
@@ -5033,7 +4951,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
        /* Enable busmastering */
        writeb(IPS_BIT_EBM, ha->mem_ptr + IPS_REG_SCPR);
 
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                /* fix for anaconda64 */
                writel(0, ha->mem_ptr + IPS_REG_NDAE);
 
@@ -5178,7 +5096,7 @@ ips_reset_copperhead(ips_ha_t * ha)
        METHOD_TRACE("ips_reset_copperhead", 1);
 
        DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
-                 ips_name, ha->host_num, ha->io_addr, ha->irq);
+                 ips_name, ha->host_num, ha->io_addr, ha->pcidev->irq);
 
        reset_counter = 0;
 
@@ -5223,7 +5141,7 @@ ips_reset_copperhead_memio(ips_ha_t * ha)
        METHOD_TRACE("ips_reset_copperhead_memio", 1);
 
        DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
-                 ips_name, ha->host_num, ha->mem_addr, ha->irq);
+                 ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
 
        reset_counter = 0;
 
@@ -5269,7 +5187,7 @@ ips_reset_morpheus(ips_ha_t * ha)
        METHOD_TRACE("ips_reset_morpheus", 1);
 
        DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
-                 ips_name, ha->host_num, ha->mem_addr, ha->irq);
+                 ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
 
        reset_counter = 0;
 
@@ -5316,12 +5234,12 @@ ips_statinit(ips_ha_t * ha)
        ha->adapt->p_status_tail = ha->adapt->status;
 
        phys_status_start = ha->adapt->hw_status_start;
-       outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
-       outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
+       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(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
+       outl(phys_status_start + IPS_STATUS_SIZE,
             ha->io_addr + IPS_REG_SQHR);
-       outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
+       outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
 
        ha->adapt->hw_status_tail = phys_status_start;
 }
@@ -5378,7 +5296,7 @@ ips_statupd_copperhead(ips_ha_t * ha)
                ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
        }
 
-       outl(cpu_to_le32(ha->adapt->hw_status_tail),
+       outl(ha->adapt->hw_status_tail,
             ha->io_addr + IPS_REG_SQTR);
 
        return (ha->adapt->p_status_tail->value);
@@ -5480,8 +5398,8 @@ ips_issue_copperhead(ips_ha_t * ha, ips_scb_t * scb)
                }               /* end if */
        }                       /* end while */
 
-       outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
-       outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
+       outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
+       outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
 
        return (IPS_SUCCESS);
 }
@@ -5566,7 +5484,7 @@ ips_issue_i2o(ips_ha_t * ha, ips_scb_t * scb)
                          ips_name, ha->host_num, scb->cmd.basic_io.command_id);
        }
 
-       outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
+       outl(scb->scb_busaddr, ha->io_addr + IPS_REG_I2O_INMSGQ);
 
        return (IPS_SUCCESS);
 }
@@ -5800,7 +5718,7 @@ ips_write_driver_status(ips_ha_t * ha, int intr)
        strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
        strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
 
-       ips_version_check(ha, intr);    /* Check BIOS/FW/Driver Versions */
+       ha->nvram->versioning = 0;      /* Indicate the Driver Does Not Support Versioning */
 
        /* now update the page */
        if (!ips_readwrite_page5(ha, TRUE, intr)) {
@@ -5956,7 +5874,7 @@ ips_read_config(ips_ha_t * ha, int intr)
 
                return (0);
        }
-       
+
        memcpy(ha->conf, ha->ioctl_data, sizeof(*ha->conf));
        return (1);
 }
@@ -5995,7 +5913,7 @@ ips_readwrite_page5(ips_ha_t * ha, int write, int intr)
        scb->cmd.nvram.buffer_addr = ha->ioctl_busaddr;
        if (write)
                memcpy(ha->ioctl_data, ha->nvram, sizeof(*ha->nvram));
-       
+
        /* issue the command */
        if (((ret =
              ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
@@ -6232,32 +6150,32 @@ ips_erase_bios(ips_ha_t * ha)
 
        /* Clear the status register */
        outl(0, ha->io_addr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        outb(0x50, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* Erase Setup */
        outb(0x20, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* Erase Confirm */
        outb(0xD0, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* Erase Status */
        outb(0x70, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        timeout = 80000;        /* 80 seconds */
 
        while (timeout > 0) {
-               if (ha->revision_id == IPS_REVID_TROMBONE64) {
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
                        outl(0, ha->io_addr + IPS_REG_FLAP);
                        udelay(25);     /* 25 us */
                }
@@ -6277,13 +6195,13 @@ ips_erase_bios(ips_ha_t * ha)
 
                /* try to suspend the erase */
                outb(0xB0, ha->io_addr + IPS_REG_FLDP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                /* wait for 10 seconds */
                timeout = 10000;
                while (timeout > 0) {
-                       if (ha->revision_id == IPS_REVID_TROMBONE64) {
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
                                outl(0, ha->io_addr + IPS_REG_FLAP);
                                udelay(25);     /* 25 us */
                        }
@@ -6305,7 +6223,7 @@ ips_erase_bios(ips_ha_t * ha)
                /* VPP failure */
                return (1);
 
-       /* check for succesful flash */
+       /* check for successful flash */
        if (status & 0x30)
                /* sequence error */
                return (1);
@@ -6313,12 +6231,12 @@ ips_erase_bios(ips_ha_t * ha)
        /* Otherwise, we were successful */
        /* clear status */
        outb(0x50, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* enable reads */
        outb(0xFF, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        return (0);
@@ -6344,32 +6262,32 @@ ips_erase_bios_memio(ips_ha_t * ha)
 
        /* Clear the status register */
        writel(0, ha->mem_ptr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* Erase Setup */
        writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* Erase Confirm */
        writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* Erase Status */
        writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        timeout = 80000;        /* 80 seconds */
 
        while (timeout > 0) {
-               if (ha->revision_id == IPS_REVID_TROMBONE64) {
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
                        writel(0, ha->mem_ptr + IPS_REG_FLAP);
                        udelay(25);     /* 25 us */
                }
@@ -6389,13 +6307,13 @@ ips_erase_bios_memio(ips_ha_t * ha)
 
                /* try to suspend the erase */
                writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                /* wait for 10 seconds */
                timeout = 10000;
                while (timeout > 0) {
-                       if (ha->revision_id == IPS_REVID_TROMBONE64) {
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
                                writel(0, ha->mem_ptr + IPS_REG_FLAP);
                                udelay(25);     /* 25 us */
                        }
@@ -6417,7 +6335,7 @@ ips_erase_bios_memio(ips_ha_t * ha)
                /* VPP failure */
                return (1);
 
-       /* check for succesful flash */
+       /* check for successful flash */
        if (status & 0x30)
                /* sequence error */
                return (1);
@@ -6425,12 +6343,12 @@ ips_erase_bios_memio(ips_ha_t * ha)
        /* Otherwise, we were successful */
        /* clear status */
        writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        /* enable reads */
        writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        return (0);
@@ -6458,22 +6376,22 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
 
        for (i = 0; i < buffersize; i++) {
                /* write a byte */
-               outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                outb(0x40, ha->io_addr + IPS_REG_FLDP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                /* wait up to one second */
                timeout = 1000;
                while (timeout > 0) {
-                       if (ha->revision_id == IPS_REVID_TROMBONE64) {
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
                                outl(0, ha->io_addr + IPS_REG_FLAP);
                                udelay(25);     /* 25 us */
                        }
@@ -6490,11 +6408,11 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
                if (timeout == 0) {
                        /* timeout error */
                        outl(0, ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        outb(0xFF, ha->io_addr + IPS_REG_FLDP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        return (1);
@@ -6504,11 +6422,11 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
                if (status & 0x18) {
                        /* programming error */
                        outl(0, ha->io_addr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        outb(0xFF, ha->io_addr + IPS_REG_FLDP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        return (1);
@@ -6517,11 +6435,11 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
 
        /* Enable reading */
        outl(0, ha->io_addr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        outb(0xFF, ha->io_addr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        return (0);
@@ -6550,21 +6468,21 @@ ips_program_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
        for (i = 0; i < buffersize; i++) {
                /* write a byte */
                writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                /* wait up to one second */
                timeout = 1000;
                while (timeout > 0) {
-                       if (ha->revision_id == IPS_REVID_TROMBONE64) {
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
                                writel(0, ha->mem_ptr + IPS_REG_FLAP);
                                udelay(25);     /* 25 us */
                        }
@@ -6581,11 +6499,11 @@ ips_program_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
                if (timeout == 0) {
                        /* timeout error */
                        writel(0, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        return (1);
@@ -6595,11 +6513,11 @@ ips_program_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
                if (status & 0x18) {
                        /* programming error */
                        writel(0, ha->mem_ptr + IPS_REG_FLAP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
-                       if (ha->revision_id == IPS_REVID_TROMBONE64)
+                       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        return (1);
@@ -6608,11 +6526,11 @@ ips_program_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
 
        /* Enable reading */
        writel(0, ha->mem_ptr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        return (0);
@@ -6637,14 +6555,14 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
 
        /* test 1st byte */
        outl(0, ha->io_addr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
                return (1);
 
-       outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       outl(1, ha->io_addr + IPS_REG_FLAP);
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
        if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
                return (1);
@@ -6652,8 +6570,8 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
        checksum = 0xff;
        for (i = 2; i < buffersize; i++) {
 
-               outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                checksum = (uint8_t) checksum + inb(ha->io_addr + IPS_REG_FLDP);
@@ -6686,14 +6604,14 @@ ips_verify_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
 
        /* test 1st byte */
        writel(0, ha->mem_ptr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
 
        if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
                return (1);
 
        writel(1, ha->mem_ptr + IPS_REG_FLAP);
-       if (ha->revision_id == IPS_REVID_TROMBONE64)
+       if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
        if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
                return (1);
@@ -6702,7 +6620,7 @@ ips_verify_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
        for (i = 2; i < buffersize; i++) {
 
                writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
-               if (ha->revision_id == IPS_REVID_TROMBONE64)
+               if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
                checksum =
@@ -6717,135 +6635,6 @@ ips_verify_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
                return (0);
 }
 
-/*---------------------------------------------------------------------------*/
-/*   Routine Name: ips_version_check                                         */
-/*                                                                           */
-/*   Dependencies:                                                           */
-/*     Assumes that ips_read_adapter_status() is called first filling in     */
-/*     the data for SubSystem Parameters.                                    */
-/*     Called from ips_write_driver_status() so it also assumes NVRAM Page 5 */
-/*     Data is available.                                                    */
-/*                                                                           */
-/*---------------------------------------------------------------------------*/
-static void
-ips_version_check(ips_ha_t * ha, int intr)
-{
-       IPS_VERSION_DATA *VersionInfo;
-       uint8_t FirmwareVersion[IPS_COMPAT_ID_LENGTH + 1];
-       uint8_t BiosVersion[IPS_COMPAT_ID_LENGTH + 1];
-       int MatchError;
-       int rc;
-       char BiosString[10];
-       char FirmwareString[10];
-
-       METHOD_TRACE("ips_version_check", 1);
-
-       VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data;
-
-       memset(FirmwareVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
-       memset(BiosVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
-
-       /* Get the Compatible BIOS Version from NVRAM Page 5 */
-       memcpy(BiosVersion, ha->nvram->BiosCompatibilityID,
-              IPS_COMPAT_ID_LENGTH);
-
-       rc = IPS_FAILURE;
-       if (ha->subsys->param[4] & IPS_GET_VERSION_SUPPORT) {   /* If Versioning is Supported */
-               /* Get the Version Info with a Get Version Command */
-               memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
-               rc = ips_get_version_info(ha, ha->ioctl_busaddr, intr);
-               if (rc == IPS_SUCCESS)
-                       memcpy(FirmwareVersion, VersionInfo->compatibilityId,
-                              IPS_COMPAT_ID_LENGTH);
-       }
-
-       if (rc != IPS_SUCCESS) {        /* If Data Not Obtainable from a GetVersion Command */
-               /* Get the Firmware Version from Enquiry Data */
-               memcpy(FirmwareVersion, ha->enq->CodeBlkVersion,
-                      IPS_COMPAT_ID_LENGTH);
-       }
-
-       /* printk(KERN_WARNING "Adapter's BIOS Version  = %s\n", BiosVersion);          */
-       /* printk(KERN_WARNING "BIOS Compatible Version = %s\n", IPS_COMPAT_BIOS);      */
-       /* printk(KERN_WARNING "Adapter's Firmware Version  = %s\n", FirmwareVersion);  */
-       /* printk(KERN_WARNING "Firmware Compatible Version = %s \n", Compatable[ ha->nvram->adapter_type ]); */
-
-       MatchError = 0;
-
-       if (strncmp
-           (FirmwareVersion, Compatable[ha->nvram->adapter_type],
-            IPS_COMPAT_ID_LENGTH) != 0)
-               MatchError = 1;
-
-       if (strncmp(BiosVersion, IPS_COMPAT_BIOS, IPS_COMPAT_ID_LENGTH) != 0)
-               MatchError = 1;
-
-       ha->nvram->versioning = 1;      /* Indicate the Driver Supports Versioning */
-
-       if (MatchError) {
-               ha->nvram->version_mismatch = 1;
-               if (ips_cd_boot == 0) {
-                       strncpy(&BiosString[0], ha->nvram->bios_high, 4);
-                       strncpy(&BiosString[4], ha->nvram->bios_low, 4);
-                       BiosString[8] = 0;
-
-                       strncpy(&FirmwareString[0], ha->enq->CodeBlkVersion, 8);
-                       FirmwareString[8] = 0;
-
-                       IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                                  "Warning ! ! ! ServeRAID Version Mismatch\n");
-                       IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                                  "Bios = %s, Firmware = %s, Device Driver = %s%s\n",
-                                  BiosString, FirmwareString, IPS_VERSION_HIGH,
-                                  IPS_VERSION_LOW);
-                       IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                                  "These levels should match to avoid possible compatibility problems.\n");
-               }
-       } else {
-               ha->nvram->version_mismatch = 0;
-       }
-
-       return;
-}
-
-/*---------------------------------------------------------------------------*/
-/*   Routine Name: ips_get_version_info                                      */
-/*                                                                           */
-/*   Routine Description:                                                    */
-/*     Issue an internal GETVERSION Command                                  */
-/*                                                                           */
-/*   Return Value:                                                           */
-/*     0 if Successful, else non-zero                                        */
-/*---------------------------------------------------------------------------*/
-static int
-ips_get_version_info(ips_ha_t * ha, dma_addr_t Buffer, int intr)
-{
-       ips_scb_t *scb;
-       int rc;
-
-       METHOD_TRACE("ips_get_version_info", 1);
-
-       scb = &ha->scbs[ha->max_cmds - 1];
-
-       ips_init_scb(ha, scb);
-
-       scb->timeout = ips_cmd_timeout;
-       scb->cdb[0] = IPS_CMD_GET_VERSION_INFO;
-       scb->cmd.version_info.op_code = IPS_CMD_GET_VERSION_INFO;
-       scb->cmd.version_info.command_id = IPS_COMMAND_ID(ha, scb);
-       scb->cmd.version_info.reserved = 0;
-       scb->cmd.version_info.count = sizeof (IPS_VERSION_DATA);
-       scb->cmd.version_info.reserved2 = 0;
-       scb->data_len = sizeof (IPS_VERSION_DATA);
-       scb->data_busaddr = Buffer;
-       scb->cmd.version_info.buffer_addr = Buffer;
-       scb->flags = 0;
-
-       /* issue command */
-       rc = ips_send_wait(ha, scb, ips_cmd_timeout, intr);
-       return (rc);
-}
-
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_abort_init                                             */
@@ -7002,42 +6791,44 @@ ips_register_scsi(int index)
        }
        ha = IPS_HA(sh);
        memcpy(ha, oldha, sizeof (ips_ha_t));
-       free_irq(oldha->irq, oldha);
+       free_irq(oldha->pcidev->irq, oldha);
        /* Install the interrupt handler with the new ha */
-       if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
+       if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
                IPS_PRINTK(KERN_WARNING, ha->pcidev,
                           "Unable to install interrupt handler\n");
-               scsi_host_put(sh);
-               return -1;
+               goto err_out_sh;
        }
 
        kfree(oldha);
-       ips_sh[index] = sh;
-       ips_ha[index] = ha;
-       IPS_SCSI_SET_DEVICE(sh, ha);
 
        /* Store away needed values for later use */
-       sh->io_port = ha->io_addr;
-       sh->n_io_port = ha->io_addr ? 255 : 0;
        sh->unique_id = (ha->io_addr) ? ha->io_addr : ha->mem_addr;
-       sh->irq = ha->irq;
        sh->sg_tablesize = sh->hostt->sg_tablesize;
        sh->can_queue = sh->hostt->can_queue;
        sh->cmd_per_lun = sh->hostt->cmd_per_lun;
-       sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
        sh->use_clustering = sh->hostt->use_clustering;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
        sh->max_sectors = 128;
-#endif
 
        sh->max_id = ha->ntargets;
        sh->max_lun = ha->nlun;
        sh->max_channel = ha->nbus - 1;
        sh->can_queue = ha->max_cmds - 1;
 
-       IPS_ADD_HOST(sh, NULL);
+       if (scsi_add_host(sh, &ha->pcidev->dev))
+               goto err_out;
+
+       ips_sh[index] = sh;
+       ips_ha[index] = ha;
+
+       scsi_scan_host(sh);
+
        return 0;
+
+err_out:
+       free_irq(ha->pcidev->irq, ha);
+err_out_sh:
+       scsi_host_put(sh);
+       return -1;
 }
 
 /*---------------------------------------------------------------------------*/
@@ -7049,20 +6840,14 @@ ips_register_scsi(int index)
 static void __devexit
 ips_remove_device(struct pci_dev *pci_dev)
 {
-       int i;
-       struct Scsi_Host *sh;
-       ips_ha_t *ha;
+       struct Scsi_Host *sh = pci_get_drvdata(pci_dev);
 
-       for (i = 0; i < IPS_MAX_ADAPTERS; i++) {
-               ha = ips_ha[i];
-               if (ha) {
-                       if ((pci_dev->bus->number == ha->pcidev->bus->number) &&
-                           (pci_dev->devfn == ha->pcidev->devfn)) {
-                               sh = ips_sh[i];
-                               ips_release(sh);
-                       }
-               }
-       }
+       pci_set_drvdata(pci_dev, NULL);
+
+       ips_release(sh);
+
+       pci_release_regions(pci_dev);
+       pci_disable_device(pci_dev);
 }
 
 /****************************************************************************/
@@ -7075,11 +6860,11 @@ ips_remove_device(struct pci_dev *pci_dev)
 static int __init
 ips_module_init(void)
 {
-       if (pci_module_init(&ips_pci_driver) < 0)
+       if (pci_register_driver(&ips_pci_driver) < 0)
                return -ENODEV;
        ips_driver_template.module = THIS_MODULE;
        ips_order_controllers();
-       if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
+       if (!ips_detect(&ips_driver_template)) {
                pci_unregister_driver(&ips_pci_driver);
                return -ENODEV;
        }
@@ -7097,7 +6882,6 @@ ips_module_init(void)
 static void __exit
 ips_module_exit(void)
 {
-       IPS_UNREGISTER_HOSTS(&ips_driver_template);
        pci_unregister_driver(&ips_pci_driver);
        unregister_reboot_notifier(&ips_notifier);
 }
@@ -7117,12 +6901,17 @@ module_exit(ips_module_exit);
 static int __devinit
 ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
 {
-       int index;
+       int index = -1;
        int rc;
 
        METHOD_TRACE("ips_insert_device", 1);
-       if (pci_enable_device(pci_dev))
-               return -1;
+       rc = pci_enable_device(pci_dev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pci_dev, "ips");
+       if (rc)
+               goto err_out;
 
        rc = ips_init_phase1(pci_dev, &index);
        if (rc == SUCCESS)
@@ -7138,6 +6927,19 @@ ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
                ips_num_controllers++;
 
        ips_next_controller = ips_num_controllers;
+
+       if (rc < 0) {
+               rc = -ENODEV;
+               goto err_out_regions;
+       }
+
+       pci_set_drvdata(pci_dev, ips_sh[index]);
+       return 0;
+
+err_out_regions:
+       pci_release_regions(pci_dev);
+err_out:
+       pci_disable_device(pci_dev);
        return rc;
 }
 
@@ -7158,11 +6960,8 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
        uint32_t mem_addr;
        uint32_t io_len;
        uint32_t mem_len;
-       uint8_t revision_id;
        uint8_t bus;
        uint8_t func;
-       uint8_t irq;
-       uint16_t subdevice_id;
        int j;
        int index;
        dma_addr_t dma_address;
@@ -7173,7 +6972,7 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
        METHOD_TRACE("ips_init_phase1", 1);
        index = IPS_MAX_ADAPTERS;
        for (j = 0; j < IPS_MAX_ADAPTERS; j++) {
-               if (ips_ha[j] == 0) {
+               if (ips_ha[j] == NULL) {
                        index = j;
                        break;
                }
@@ -7183,7 +6982,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
                return -1;
 
        /* stuff that we get in dev */
-       irq = pci_dev->irq;
        bus = pci_dev->bus->number;
        func = pci_dev->devfn;
 
@@ -7211,56 +7009,30 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
                uint32_t base;
                uint32_t offs;
 
-               if (!request_mem_region(mem_addr, mem_len, "ips")) {
-                       IPS_PRINTK(KERN_WARNING, pci_dev,
-                                  "Couldn't allocate IO Memory space %x len %d.\n",
-                                  mem_addr, mem_len);
-                       return -1;
-               }
-
                base = mem_addr & PAGE_MASK;
                offs = mem_addr - base;
                ioremap_ptr = ioremap(base, PAGE_SIZE);
+               if (!ioremap_ptr)
+                       return -1;
                mem_ptr = ioremap_ptr + offs;
        } else {
                ioremap_ptr = NULL;
                mem_ptr = NULL;
        }
 
-       /* setup I/O mapped area (if applicable) */
-       if (io_addr) {
-               if (!request_region(io_addr, io_len, "ips")) {
-                       IPS_PRINTK(KERN_WARNING, pci_dev,
-                                  "Couldn't allocate IO space %x len %d.\n",
-                                  io_addr, io_len);
-                       return -1;
-               }
-       }
-
-       /* get the revision ID */
-       if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
-               IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
-               return -1;
-       }
-
-       subdevice_id = pci_dev->subsystem_device;
-
        /* found a controller */
-       ha = kmalloc(sizeof (ips_ha_t), GFP_KERNEL);
+       ha = kzalloc(sizeof (ips_ha_t), GFP_KERNEL);
        if (ha == NULL) {
                IPS_PRINTK(KERN_WARNING, pci_dev,
                           "Unable to allocate temporary ha struct\n");
                return -1;
        }
 
-       memset(ha, 0, sizeof (ips_ha_t));
-
        ips_sh[index] = NULL;
        ips_ha[index] = ha;
        ha->active = 1;
 
        /* Store info in HA structure */
-       ha->irq = irq;
        ha->io_addr = io_addr;
        ha->io_len = io_len;
        ha->mem_addr = mem_addr;
@@ -7268,10 +7040,7 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
        ha->mem_ptr = mem_ptr;
        ha->ioremap_ptr = ioremap_ptr;
        ha->host_num = (uint32_t) index;
-       ha->revision_id = revision_id;
        ha->slot_num = PCI_SLOT(pci_dev->devfn);
-       ha->device_id = pci_dev->device;
-       ha->subdevice_id = subdevice_id;
        ha->pcidev = pci_dev;
 
        /*
@@ -7281,10 +7050,10 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
         * are guaranteed to be < 4G.
         */
        if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
-           !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) {
+           !pci_set_dma_mask(ha->pcidev, DMA_BIT_MASK(64))) {
                (ha)->flags |= IPS_HA_ENH_SG;
        } else {
-               if (pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0) {
+               if (pci_set_dma_mask(ha->pcidev, DMA_BIT_MASK(32)) != 0) {
                        printk(KERN_WARNING "Unable to set DMA Mask\n");
                        return ips_abort_init(ha, index);
                }
@@ -7416,7 +7185,7 @@ ips_init_phase2(int index)
        }
 
        /* Install the interrupt handler */
-       if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
+       if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
                IPS_PRINTK(KERN_WARNING, ha->pcidev,
                           "Unable to install interrupt handler\n");
                return ips_abort_init(ha, index);
@@ -7429,14 +7198,14 @@ ips_init_phase2(int index)
        if (!ips_allocatescbs(ha)) {
                IPS_PRINTK(KERN_WARNING, ha->pcidev,
                           "Unable to allocate a CCB\n");
-               free_irq(ha->irq, ha);
+               free_irq(ha->pcidev->irq, ha);
                return ips_abort_init(ha, index);
        }
 
        if (!ips_hainit(ha)) {
                IPS_PRINTK(KERN_WARNING, ha->pcidev,
                           "Unable to initialize controller\n");
-               free_irq(ha->irq, ha);
+               free_irq(ha->pcidev->irq, ha);
                return ips_abort_init(ha, index);
        }
        /* Free the temporary SCB */
@@ -7446,22 +7215,16 @@ ips_init_phase2(int index)
        if (!ips_allocatescbs(ha)) {
                IPS_PRINTK(KERN_WARNING, ha->pcidev,
                           "Unable to allocate CCBs\n");
-               free_irq(ha->irq, ha);
+               free_irq(ha->pcidev->irq, ha);
                return ips_abort_init(ha, index);
        }
 
        return SUCCESS;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
 MODULE_LICENSE("GPL");
-#endif
-
 MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
-
-#ifdef MODULE_VERSION
 MODULE_VERSION(IPS_VER_STRING);
-#endif
 
 
 /*