Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / scsi / aacraid / aachba.c
index f3fc353..642a3b4 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
 
 #define        INQD_PDT_DMASK  0x1F    /* Peripheral Device Type Mask */
 #define        INQD_PDT_QMASK  0xE0    /* Peripheral Device Qualifer Mask */
 
-#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
-
-#define MAX_DRIVER_SG_SEGMENT_COUNT 17
-
 /*
  *     Sense codes
  */
@@ -137,6 +134,7 @@ struct inquiry_data {
  
 static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
 static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
 #ifdef AAC_DETAILED_STATUS_INFO
 static char *aac_get_status_string(u32 status);
@@ -151,13 +149,20 @@ static int dacmode = -1;
 
 static int commit = -1;
 
-module_param(nondasd, int, 0);
+module_param(nondasd, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
-module_param(dacmode, int, 0);
+module_param(dacmode, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
-module_param(commit, int, 0);
+module_param(commit, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
 
+int numacb = -1;
+module_param(numacb, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid values are 512 and down. Default is to use suggestion from Firmware.");
+
+int acbsize = -1;
+module_param(acbsize, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
 /**
  *     aac_get_config_status   -       check the adapter configuration
  *     @common: adapter to query
@@ -169,10 +174,10 @@ int aac_get_config_status(struct aac_dev *dev)
        int status = 0;
        struct fib * fibptr;
 
-       if (!(fibptr = fib_alloc(dev)))
+       if (!(fibptr = aac_fib_alloc(dev)))
                return -ENOMEM;
 
-       fib_init(fibptr);
+       aac_fib_init(fibptr);
        {
                struct aac_get_config_status *dinfo;
                dinfo = (struct aac_get_config_status *) fib_data(fibptr);
@@ -182,7 +187,7 @@ int aac_get_config_status(struct aac_dev *dev)
                dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));
        }
 
-       status = fib_send(ContainerCommand,
+       status = aac_fib_send(ContainerCommand,
                            fibptr,
                            sizeof (struct aac_get_config_status),
                            FsaNormal,
@@ -205,30 +210,30 @@ int aac_get_config_status(struct aac_dev *dev)
                        status = -EINVAL;
                }
        }
-       fib_complete(fibptr);
+       aac_fib_complete(fibptr);
        /* Send a CT_COMMIT_CONFIG to enable discovery of devices */
        if (status >= 0) {
                if (commit == 1) {
                        struct aac_commit_config * dinfo;
-                       fib_init(fibptr);
+                       aac_fib_init(fibptr);
                        dinfo = (struct aac_commit_config *) fib_data(fibptr);
        
                        dinfo->command = cpu_to_le32(VM_ContainerConfig);
                        dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);
        
-                       status = fib_send(ContainerCommand,
+                       status = aac_fib_send(ContainerCommand,
                                    fibptr,
                                    sizeof (struct aac_commit_config),
                                    FsaNormal,
                                    1, 1,
                                    NULL, NULL);
-                       fib_complete(fibptr);
+                       aac_fib_complete(fibptr);
                } else if (commit == 0) {
                        printk(KERN_WARNING
                          "aac_get_config_status: Foreign device configurations are being ignored\n");
                }
        }
-       fib_free(fibptr);
+       aac_fib_free(fibptr);
        return status;
 }
 
@@ -251,15 +256,15 @@ int aac_get_containers(struct aac_dev *dev)
 
        instance = dev->scsi_host_ptr->unique_id;
 
-       if (!(fibptr = fib_alloc(dev)))
+       if (!(fibptr = aac_fib_alloc(dev)))
                return -ENOMEM;
 
-       fib_init(fibptr);
+       aac_fib_init(fibptr);
        dinfo = (struct aac_get_container_count *) fib_data(fibptr);
        dinfo->command = cpu_to_le32(VM_ContainerConfig);
        dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);
 
-       status = fib_send(ContainerCommand,
+       status = aac_fib_send(ContainerCommand,
                    fibptr,
                    sizeof (struct aac_get_container_count),
                    FsaNormal,
@@ -268,16 +273,15 @@ int aac_get_containers(struct aac_dev *dev)
        if (status >= 0) {
                dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
                maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
-               fib_complete(fibptr);
+               aac_fib_complete(fibptr);
        }
 
        if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
                maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
-
        fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
          sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
        if (!fsa_dev_ptr) {
-               fib_free(fibptr);
+               aac_fib_free(fibptr);
                return -ENOMEM;
        }
        memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
@@ -291,14 +295,14 @@ int aac_get_containers(struct aac_dev *dev)
 
                fsa_dev_ptr[index].devname[0] = '\0';
 
-               fib_init(fibptr);
+               aac_fib_init(fibptr);
                dinfo = (struct aac_query_mount *) fib_data(fibptr);
 
                dinfo->command = cpu_to_le32(VM_NameServe);
                dinfo->count = cpu_to_le32(index);
                dinfo->type = cpu_to_le32(FT_FILESYS);
 
-               status = fib_send(ContainerCommand,
+               status = aac_fib_send(ContainerCommand,
                                    fibptr,
                                    sizeof (struct aac_query_mount),
                                    FsaNormal,
@@ -310,22 +314,41 @@ int aac_get_containers(struct aac_dev *dev)
                }
                dresp = (struct aac_mount *)fib_data(fibptr);
 
+               if ((le32_to_cpu(dresp->status) == ST_OK) &&
+                   (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
+                       dinfo->command = cpu_to_le32(VM_NameServe64);
+                       dinfo->count = cpu_to_le32(index);
+                       dinfo->type = cpu_to_le32(FT_FILESYS);
+
+                       if (aac_fib_send(ContainerCommand,
+                                   fibptr,
+                                   sizeof(struct aac_query_mount),
+                                   FsaNormal,
+                                   1, 1,
+                                   NULL, NULL) < 0)
+                               continue;
+               } else
+                       dresp->mnt[0].capacityhigh = 0;
+
                dprintk ((KERN_DEBUG
-                 "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%u\n",
+                 "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",
                  (int)index, (int)le32_to_cpu(dresp->status),
                  (int)le32_to_cpu(dresp->mnt[0].vol),
                  (int)le32_to_cpu(dresp->mnt[0].state),
-                 (unsigned)le32_to_cpu(dresp->mnt[0].capacity)));
+                 ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+                   (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));
                if ((le32_to_cpu(dresp->status) == ST_OK) &&
                    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
                    (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
                        fsa_dev_ptr[index].valid = 1;
                        fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);
-                       fsa_dev_ptr[index].size = le32_to_cpu(dresp->mnt[0].capacity);
+                       fsa_dev_ptr[index].size
+                         = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+                           (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
                        if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
                                    fsa_dev_ptr[index].ro = 1;
                }
-               fib_complete(fibptr);
+               aac_fib_complete(fibptr);
                /*
                 *      If there are no more containers, then stop asking.
                 */
@@ -333,17 +356,29 @@ int aac_get_containers(struct aac_dev *dev)
                        break;
                }
        }
-       fib_free(fibptr);
+       aac_fib_free(fibptr);
        return status;
 }
 
-static void aac_io_done(struct scsi_cmnd * scsicmd)
+static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
 {
-       unsigned long cpu_flags;
-       struct Scsi_Host *host = scsicmd->device->host;
-       spin_lock_irqsave(host->host_lock, cpu_flags);
-       scsicmd->scsi_done(scsicmd);
-       spin_unlock_irqrestore(host->host_lock, cpu_flags);
+       void *buf;
+       unsigned int transfer_len;
+       struct scatterlist *sg = scsicmd->request_buffer;
+
+       if (scsicmd->use_sg) {
+               buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+               transfer_len = min(sg->length, len + offset);
+       } else {
+               buf = scsicmd->request_buffer;
+               transfer_len = min(scsicmd->request_bufflen, len + offset);
+       }
+
+       memcpy(buf + offset, data, transfer_len - offset);
+
+       if (scsicmd->use_sg) 
+               kunmap_atomic(buf - sg->offset, KM_IRQ0);
+
 }
 
 static void get_container_name_callback(void *context, struct fib * fibptr)
@@ -352,6 +387,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
        struct scsi_cmnd * scsicmd;
 
        scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
        dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
        if (fibptr == NULL)
@@ -361,23 +397,27 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
        /* Failure is irrelevant, using default value instead */
        if ((le32_to_cpu(get_name_reply->status) == CT_OK)
         && (get_name_reply->data[0] != '\0')) {
-               int    count;
-               char * dp;
-               char * sp = get_name_reply->data;
+               char *sp = get_name_reply->data;
                sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
                while (*sp == ' ')
                        ++sp;
-               count = sizeof(((struct inquiry_data *)NULL)->inqd_pid);
-               dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid;
-               if (*sp) do {
-                       *dp++ = (*sp) ? *sp++ : ' ';
-               } while (--count > 0);
+               if (*sp) {
+                       char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+                       int count = sizeof(d);
+                       char *dp = d;
+                       do {
+                               *dp++ = (*sp) ? *sp++ : ' ';
+                       } while (--count > 0);
+                       aac_internal_transfer(scsicmd, d, 
+                         offsetof(struct inquiry_data, inqd_pid), sizeof(d));
+               }
        }
+
        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 
-       fib_complete(fibptr);
-       fib_free(fibptr);
-       aac_io_done(scsicmd);
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
+       scsicmd->scsi_done(scsicmd);
 }
 
 /**
@@ -392,10 +432,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
-       if (!(cmd_fibcontext = fib_alloc(dev)))
+       if (!(cmd_fibcontext = aac_fib_alloc(dev)))
                return -ENOMEM;
 
-       fib_init(cmd_fibcontext);
+       aac_fib_init(cmd_fibcontext);
        dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
 
        dinfo->command = cpu_to_le32(VM_ContainerConfig);
@@ -403,7 +443,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
        dinfo->cid = cpu_to_le32(cid);
        dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
 
-       status = fib_send(ContainerCommand, 
+       status = aac_fib_send(ContainerCommand,
                  cmd_fibcontext, 
                  sizeof (struct aac_get_name),
                  FsaNormal, 
@@ -414,17 +454,19 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS) 
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
+       }
                
-       printk(KERN_WARNING "aac_get_container_name: fib_send failed with status: %d.\n", status);
-       fib_complete(cmd_fibcontext);
-       fib_free(cmd_fibcontext);
+       printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
+       aac_fib_complete(cmd_fibcontext);
+       aac_fib_free(cmd_fibcontext);
        return -1;
 }
 
 /**
- *     probe_container         -       query a logical volume
+ *     aac_probe_container             -       query a logical volume
  *     @dev: device to query
  *     @cid: container identifier
  *
@@ -432,7 +474,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
  *     is updated in the struct fsa_dev_info structure rather than returned.
  */
  
-static int probe_container(struct aac_dev *dev, int cid)
+int aac_probe_container(struct aac_dev *dev, int cid)
 {
        struct fsa_dev_info *fsa_dev_ptr;
        int status;
@@ -444,10 +486,10 @@ static int probe_container(struct aac_dev *dev, int cid)
        fsa_dev_ptr = dev->fsa_dev;
        instance = dev->scsi_host_ptr->unique_id;
 
-       if (!(fibptr = fib_alloc(dev)))
+       if (!(fibptr = aac_fib_alloc(dev)))
                return -ENOMEM;
 
-       fib_init(fibptr);
+       aac_fib_init(fibptr);
 
        dinfo = (struct aac_query_mount *)fib_data(fibptr);
 
@@ -455,32 +497,50 @@ static int probe_container(struct aac_dev *dev, int cid)
        dinfo->count = cpu_to_le32(cid);
        dinfo->type = cpu_to_le32(FT_FILESYS);
 
-       status = fib_send(ContainerCommand,
+       status = aac_fib_send(ContainerCommand,
                            fibptr,
                            sizeof(struct aac_query_mount),
                            FsaNormal,
                            1, 1,
                            NULL, NULL);
        if (status < 0) {
-               printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
+               printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
                goto error;
        }
 
        dresp = (struct aac_mount *) fib_data(fibptr);
 
+       if ((le32_to_cpu(dresp->status) == ST_OK) &&
+           (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
+               dinfo->command = cpu_to_le32(VM_NameServe64);
+               dinfo->count = cpu_to_le32(cid);
+               dinfo->type = cpu_to_le32(FT_FILESYS);
+
+               if (aac_fib_send(ContainerCommand,
+                           fibptr,
+                           sizeof(struct aac_query_mount),
+                           FsaNormal,
+                           1, 1,
+                           NULL, NULL) < 0)
+                       goto error;
+       } else
+               dresp->mnt[0].capacityhigh = 0;
+
        if ((le32_to_cpu(dresp->status) == ST_OK) &&
            (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
            (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
                fsa_dev_ptr[cid].valid = 1;
                fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol);
-               fsa_dev_ptr[cid].size = le32_to_cpu(dresp->mnt[0].capacity);
+               fsa_dev_ptr[cid].size
+                 = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+                   (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
                if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
                        fsa_dev_ptr[cid].ro = 1;
        }
 
 error:
-       fib_complete(fibptr);
-       fib_free(fibptr);
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
 
        return status;
 }
@@ -524,6 +584,11 @@ static char *container_types[] = {
         "V-MIRRORS",          
         "PSEUDO R4",          
        "RAID50",
+       "RAID5D",
+       "RAID5D0",
+       "RAID1E",
+       "RAID6",
+       "RAID60",
         "Unknown"
 };
 
@@ -538,17 +603,43 @@ static char *container_types[] = {
  * files instead of in OS dependant driver source.
  */
 
-static void setinqstr(int devtype, void *data, int tindex)
+static void setinqstr(struct aac_dev *dev, void *data, int tindex)
 {
        struct scsi_inq *str;
-       struct aac_driver_ident *mp;
 
-       mp = aac_get_driver_ident(devtype);
-   
        str = (struct scsi_inq *)(data); /* cast data to scsi inq block */
-
-       inqstrcpy (mp->vname, str->vid); 
-       inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */
+       memset(str, ' ', sizeof(*str));
+
+       if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+               char * cp = dev->supplement_adapter_info.AdapterTypeText;
+               int c = sizeof(str->vid);
+               while (*cp && *cp != ' ' && --c)
+                       ++cp;
+               c = *cp;
+               *cp = '\0';
+               inqstrcpy (dev->supplement_adapter_info.AdapterTypeText,
+                 str->vid); 
+               *cp = c;
+               while (*cp && *cp != ' ')
+                       ++cp;
+               while (*cp == ' ')
+                       ++cp;
+               /* last six chars reserved for vol type */
+               c = 0;
+               if (strlen(cp) > sizeof(str->pid)) {
+                       c = cp[sizeof(str->pid)];
+                       cp[sizeof(str->pid)] = '\0';
+               }
+               inqstrcpy (cp, str->pid);
+               if (c)
+                       cp[sizeof(str->pid)] = c;
+       } else {
+               struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype);
+   
+               inqstrcpy (mp->vname, str->vid); 
+               /* last six chars reserved for vol type */
+               inqstrcpy (mp->model, str->pid);
+       }
 
        if (tindex < (sizeof(container_types)/sizeof(char *))){
                char *findit = str->pid;
@@ -557,15 +648,17 @@ static void setinqstr(int devtype, void *data, int tindex)
                /* RAID is superfluous in the context of a RAID device */
                if (memcmp(findit-4, "RAID", 4) == 0)
                        *(findit -= 4) = ' ';
-               inqstrcpy (container_types[tindex], findit + 1);
+               if (((findit - str->pid) + strlen(container_types[tindex]))
+                < (sizeof(str->pid) + sizeof(str->prl)))
+                       inqstrcpy (container_types[tindex], findit + 1);
        }
        inqstrcpy ("V1.0", str->prl);
 }
 
-void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
-                   u8 a_sense_code, u8 incorrect_length,
-                   u8 bit_pointer, u16 field_pointer,
-                   u32 residue)
+static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
+                     u8 a_sense_code, u8 incorrect_length,
+                     u8 bit_pointer, u16 field_pointer,
+                     u32 residue)
 {
        sense_buf[0] = 0xF0;    /* Sense data valid, err code 70h (current error) */
        sense_buf[1] = 0;       /* Segment number, always zero */
@@ -605,35 +698,95 @@ void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
 int aac_get_adapter_info(struct aac_dev* dev)
 {
        struct fib* fibptr;
-       struct aac_adapter_info* info;
        int rcode;
        u32 tmp;
-       if (!(fibptr = fib_alloc(dev)))
+       struct aac_adapter_info *info;
+       struct aac_bus_info *command;
+       struct aac_bus_info_response *bus_info;
+
+       if (!(fibptr = aac_fib_alloc(dev)))
                return -ENOMEM;
 
-       fib_init(fibptr);
-       info = (struct aac_adapter_info*) fib_data(fibptr);
+       aac_fib_init(fibptr);
+       info = (struct aac_adapter_info *) fib_data(fibptr);
+       memset(info,0,sizeof(*info));
+
+       rcode = aac_fib_send(RequestAdapterInfo,
+                        fibptr, 
+                        sizeof(*info),
+                        FsaNormal, 
+                        -1, 1, /* First `interrupt' command uses special wait */
+                        NULL, 
+                        NULL);
+
+       if (rcode < 0) {
+               aac_fib_complete(fibptr);
+               aac_fib_free(fibptr);
+               return rcode;
+       }
+       memcpy(&dev->adapter_info, info, sizeof(*info));
+
+       if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
+               struct aac_supplement_adapter_info * info;
+
+               aac_fib_init(fibptr);
+
+               info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
 
-       memset(info,0,sizeof(struct aac_adapter_info));
+               memset(info,0,sizeof(*info));
 
-       rcode = fib_send(RequestAdapterInfo,
-                       fibptr, 
-                       sizeof(struct aac_adapter_info),
-                       FsaNormal, 
-                       1, 1, 
-                       NULL, 
-                       NULL);
+               rcode = aac_fib_send(RequestSupplementAdapterInfo,
+                                fibptr,
+                                sizeof(*info),
+                                FsaNormal,
+                                1, 1,
+                                NULL,
+                                NULL);
 
-       memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
+               if (rcode >= 0)
+                       memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
+       }
+
+
+       /* 
+        * GetBusInfo 
+        */
+
+       aac_fib_init(fibptr);
+
+       bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
+
+       memset(bus_info, 0, sizeof(*bus_info));
+
+       command = (struct aac_bus_info *)bus_info;
+
+       command->Command = cpu_to_le32(VM_Ioctl);
+       command->ObjType = cpu_to_le32(FT_DRIVE);
+       command->MethodId = cpu_to_le32(1);
+       command->CtlCmd = cpu_to_le32(GetBusInfo);
+
+       rcode = aac_fib_send(ContainerCommand,
+                        fibptr,
+                        sizeof (*bus_info),
+                        FsaNormal,
+                        1, 1,
+                        NULL, NULL);
+
+       if (rcode >= 0 && le32_to_cpu(bus_info->Status) == ST_OK) {
+               dev->maximum_num_physicals = le32_to_cpu(bus_info->TargetsPerBus);
+               dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount);
+       }
 
        tmp = le32_to_cpu(dev->adapter_info.kernelrev);
-       printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n", 
+       printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", 
                        dev->name, 
                        dev->id,
                        tmp>>24,
                        (tmp>>16)&0xff,
                        tmp&0xff,
-                       le32_to_cpu(dev->adapter_info.kernelbuild));
+                       le32_to_cpu(dev->adapter_info.kernelbuild),
+                       (int)sizeof(dev->supplement_adapter_info.BuildDate),
+                       dev->supplement_adapter_info.BuildDate);
        tmp = le32_to_cpu(dev->adapter_info.monitorrev);
        printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", 
                        dev->name, dev->id,
@@ -692,12 +845,12 @@ int aac_get_adapter_info(struct aac_dev* dev)
                dev->dac_support = (dacmode!=0);
        }
        if(dev->dac_support != 0) {
-               if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL) &&
-                       !pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL)) {
+               if (!pci_set_dma_mask(dev->pdev, DMA_64BIT_MASK) &&
+                       !pci_set_consistent_dma_mask(dev->pdev, DMA_64BIT_MASK)) {
                        printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
                                dev->name, dev->id);
-               } else if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFULL) &&
-                       !pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFULL)) {
+               } else if (!pci_set_dma_mask(dev->pdev, DMA_32BIT_MASK) &&
+                       !pci_set_consistent_dma_mask(dev->pdev, DMA_32BIT_MASK)) {
                        printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n",
                                dev->name, dev->id);
                        dev->dac_support = 0;
@@ -707,29 +860,95 @@ int aac_get_adapter_info(struct aac_dev* dev)
                        rcode = -ENOMEM;
                }
        }
+       /* 
+        * 57 scatter gather elements 
+        */
+       if (!(dev->raw_io_interface)) {
+               dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
+                       sizeof(struct aac_fibhdr) -
+                       sizeof(struct aac_write) + sizeof(struct sgentry)) /
+                               sizeof(struct sgentry);
+               if (dev->dac_support) {
+                       /* 
+                        * 38 scatter gather elements 
+                        */
+                       dev->scsi_host_ptr->sg_tablesize =
+                               (dev->max_fib_size -
+                               sizeof(struct aac_fibhdr) -
+                               sizeof(struct aac_write64) +
+                               sizeof(struct sgentry64)) /
+                                       sizeof(struct sgentry64);
+               }
+               dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+               if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+                       /*
+                        * Worst case size that could cause sg overflow when
+                        * we break up SG elements that are larger than 64KB.
+                        * Would be nice if we could tell the SCSI layer what
+                        * the maximum SG element size can be. Worst case is
+                        * (sg_tablesize-1) 4KB elements with one 64KB
+                        * element.
+                        *      32bit -> 468 or 238KB   64bit -> 424 or 212KB
+                        */
+                       dev->scsi_host_ptr->max_sectors =
+                         (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+               }
+       }
 
-       fib_complete(fibptr);
-       fib_free(fibptr);
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
 
        return rcode;
 }
 
 
-static void read_callback(void *context, struct fib * fibptr)
+static void io_callback(void *context, struct fib * fibptr)
 {
        struct aac_dev *dev;
        struct aac_read_reply *readreply;
        struct scsi_cmnd *scsicmd;
-       u32 lba;
        u32 cid;
 
        scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-       cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+       cid = scmd_id(scsicmd);
 
-       lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
-       dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+       if (nblank(dprintk(x))) {
+               u64 lba;
+               switch (scsicmd->cmnd[0]) {
+               case WRITE_6:
+               case READ_6:
+                       lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
+                           (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
+                       break;
+               case WRITE_16:
+               case READ_16:
+                       lba = ((u64)scsicmd->cmnd[2] << 56) |
+                             ((u64)scsicmd->cmnd[3] << 48) |
+                             ((u64)scsicmd->cmnd[4] << 40) |
+                             ((u64)scsicmd->cmnd[5] << 32) |
+                             ((u64)scsicmd->cmnd[6] << 24) |
+                             (scsicmd->cmnd[7] << 16) |
+                             (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+                       break;
+               case WRITE_12:
+               case READ_12:
+                       lba = ((u64)scsicmd->cmnd[2] << 24) |
+                             (scsicmd->cmnd[3] << 16) |
+                             (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+                       break;
+               default:
+                       lba = ((u64)scsicmd->cmnd[2] << 24) |
+                              (scsicmd->cmnd[3] << 16) |
+                              (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+                       break;
+               }
+               printk(KERN_DEBUG
+                 "io_callback[cpu %d]: lba = %llu, t = %ld.\n",
+                 smp_processor_id(), (unsigned long long)lba, jiffies);
+       }
 
        if (fibptr == NULL)
                BUG();
@@ -747,8 +966,10 @@ static void read_callback(void *context, struct fib * fibptr)
        if (le32_to_cpu(readreply->status) == ST_OK)
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
        else {
-               printk(KERN_WARNING "read_callback: read failed, status = %d\n",
-                               le32_to_cpu(readreply->status));
+#ifdef AAC_DETAILED_STATUS_INFO
+               printk(KERN_WARNING "io_callback: io failed, status = %d\n",
+                 le32_to_cpu(readreply->status));
+#endif
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
                set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
                                    HARDWARE_ERROR,
@@ -760,62 +981,15 @@ static void read_callback(void *context, struct fib * fibptr)
                    ? sizeof(scsicmd->sense_buffer)
                    : sizeof(dev->fsa_dev[cid].sense_data));
        }
-       fib_complete(fibptr);
-       fib_free(fibptr);
-
-       aac_io_done(scsicmd);
-}
-
-static void write_callback(void *context, struct fib * fibptr)
-{
-       struct aac_dev *dev;
-       struct aac_write_reply *writereply;
-       struct scsi_cmnd *scsicmd;
-       u32 lba;
-       u32 cid;
-
-       scsicmd = (struct scsi_cmnd *) context;
-       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-       cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
-
-       lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
-       dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
-       if (fibptr == NULL)
-               BUG();
-
-       if(scsicmd->use_sg)
-               pci_unmap_sg(dev->pdev, 
-                       (struct scatterlist *)scsicmd->buffer,
-                       scsicmd->use_sg,
-                       scsicmd->sc_data_direction);
-       else if(scsicmd->request_bufflen)
-               pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
-                                scsicmd->request_bufflen,
-                                scsicmd->sc_data_direction);
-
-       writereply = (struct aac_write_reply *) fib_data(fibptr);
-       if (le32_to_cpu(writereply->status) == ST_OK)
-               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
-       else {
-               printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
-               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-               set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-                                   HARDWARE_ERROR,
-                                   SENCODE_INTERNAL_TARGET_FAILURE,
-                                   ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-                                   0, 0);
-               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, 
-                               sizeof(struct sense_data));
-       }
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
 
-       fib_complete(fibptr);
-       fib_free(fibptr);
-       aac_io_done(scsicmd);
+       scsicmd->scsi_done(scsicmd);
 }
 
-int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 {
-       u32 lba;
+       u64 lba;
        u32 count;
        int status;
 
@@ -827,38 +1001,110 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
        /*
         *      Get block address and transfer length
         */
-       if (scsicmd->cmnd[0] == READ_6) /* 6 byte command */
-       {
+       switch (scsicmd->cmnd[0]) {
+       case READ_6:
                dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid));
 
-               lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
+               lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | 
+                       (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
                count = scsicmd->cmnd[4];
 
                if (count == 0)
                        count = 256;
-       } else {
+               break;
+       case READ_16:
+               dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid));
+
+               lba =   ((u64)scsicmd->cmnd[2] << 56) |
+                       ((u64)scsicmd->cmnd[3] << 48) |
+                       ((u64)scsicmd->cmnd[4] << 40) |
+                       ((u64)scsicmd->cmnd[5] << 32) |
+                       ((u64)scsicmd->cmnd[6] << 24) | 
+                       (scsicmd->cmnd[7] << 16) |
+                       (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+               count = (scsicmd->cmnd[10] << 24) | 
+                       (scsicmd->cmnd[11] << 16) |
+                       (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+               break;
+       case READ_12:
+               dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid));
+
+               lba = ((u64)scsicmd->cmnd[2] << 24) | 
+                       (scsicmd->cmnd[3] << 16) |
+                       (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+               count = (scsicmd->cmnd[6] << 24) | 
+                       (scsicmd->cmnd[7] << 16) |
+                       (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+               break;
+       default:
                dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid));
 
-               lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+               lba = ((u64)scsicmd->cmnd[2] << 24) | 
+                       (scsicmd->cmnd[3] << 16) | 
+                       (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
+               break;
+       }
+       dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
+         smp_processor_id(), (unsigned long long)lba, jiffies));
+       if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) &&
+               (lba & 0xffffffff00000000LL)) {
+               dprintk((KERN_DEBUG "aac_read: Illegal lba\n"));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 
+                       SAM_STAT_CHECK_CONDITION;
+               set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+                           HARDWARE_ERROR,
+                           SENCODE_INTERNAL_TARGET_FAILURE,
+                           ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+                           0, 0);
+               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+                 (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
+                   ? sizeof(scsicmd->sense_buffer)
+                   : sizeof(dev->fsa_dev[cid].sense_data));
+               scsicmd->scsi_done(scsicmd);
+               return 0;
        }
-       dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
        /*
         *      Alocate and initialize a Fib
         */
-       if (!(cmd_fibcontext = fib_alloc(dev))) {
+       if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
                return -1;
        }
 
-       fib_init(cmd_fibcontext);
+       aac_fib_init(cmd_fibcontext);
 
-       if(dev->dac_support == 1) {
+       if (dev->raw_io_interface) {
+               struct aac_raw_io *readcmd;
+               readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+               readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+               readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+               readcmd->count = cpu_to_le32(count<<9);
+               readcmd->cid = cpu_to_le16(cid);
+               readcmd->flags = cpu_to_le16(1);
+               readcmd->bpTotal = 0;
+               readcmd->bpComplete = 0;
+               
+               aac_build_sgraw(scsicmd, &readcmd->sg);
+               fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
+               if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+                       BUG();
+               /*
+                *      Now send the Fib to the adapter
+                */
+               status = aac_fib_send(ContainerRawIo,
+                         cmd_fibcontext, 
+                         fibsize, 
+                         FsaNormal, 
+                         0, 1, 
+                         (fib_callback) io_callback, 
+                         (void *) scsicmd);
+       } else if (dev->dac_support == 1) {
                struct aac_read64 *readcmd;
                readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
                readcmd->command = cpu_to_le32(VM_CtHostRead64);
                readcmd->cid = cpu_to_le16(cid);
                readcmd->sector_count = cpu_to_le16(count);
-               readcmd->block = cpu_to_le32(lba);
+               readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
                readcmd->pad   = 0;
                readcmd->flags = 0; 
 
@@ -866,44 +1112,41 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
                fibsize = sizeof(struct aac_read64) + 
                        ((le32_to_cpu(readcmd->sg.count) - 1) * 
                         sizeof (struct sgentry64));
-               BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+               BUG_ON (fibsize > (dev->max_fib_size - 
                                        sizeof(struct aac_fibhdr)));
                /*
                 *      Now send the Fib to the adapter
                 */
-               status = fib_send(ContainerCommand64, 
+               status = aac_fib_send(ContainerCommand64,
                          cmd_fibcontext, 
                          fibsize, 
                          FsaNormal, 
                          0, 1, 
-                         (fib_callback) read_callback, 
+                         (fib_callback) io_callback, 
                          (void *) scsicmd);
        } else {
                struct aac_read *readcmd;
                readcmd = (struct aac_read *) fib_data(cmd_fibcontext);
                readcmd->command = cpu_to_le32(VM_CtBlockRead);
                readcmd->cid = cpu_to_le32(cid);
-               readcmd->block = cpu_to_le32(lba);
+               readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
                readcmd->count = cpu_to_le32(count * 512);
 
-               if (count * 512 > (64 * 1024))
-                       BUG();
-
                aac_build_sg(scsicmd, &readcmd->sg);
                fibsize = sizeof(struct aac_read) + 
                        ((le32_to_cpu(readcmd->sg.count) - 1) * 
                         sizeof (struct sgentry));
-               BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+               BUG_ON (fibsize > (dev->max_fib_size -
                                        sizeof(struct aac_fibhdr)));
                /*
                 *      Now send the Fib to the adapter
                 */
-               status = fib_send(ContainerCommand, 
+               status = aac_fib_send(ContainerCommand,
                          cmd_fibcontext, 
                          fibsize, 
                          FsaNormal, 
                          0, 1, 
-                         (fib_callback) read_callback, 
+                         (fib_callback) io_callback, 
                          (void *) scsicmd);
        }
 
@@ -912,23 +1155,25 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS) 
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
+       }
                
-       printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
+       printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
        /*
         *      For some reason, the Fib didn't queue, return QUEUE_FULL
         */
        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
-       aac_io_done(scsicmd);
-       fib_complete(cmd_fibcontext);
-       fib_free(cmd_fibcontext);
+       scsicmd->scsi_done(scsicmd);
+       aac_fib_complete(cmd_fibcontext);
+       aac_fib_free(cmd_fibcontext);
        return 0;
 }
 
 static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 {
-       u32 lba;
+       u64 lba;
        u32 count;
        int status;
        u16 fibsize;
@@ -945,30 +1190,90 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
                count = scsicmd->cmnd[4];
                if (count == 0)
                        count = 256;
+       } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
+               dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid));
+
+               lba =   ((u64)scsicmd->cmnd[2] << 56) |
+                       ((u64)scsicmd->cmnd[3] << 48) |
+                       ((u64)scsicmd->cmnd[4] << 40) |
+                       ((u64)scsicmd->cmnd[5] << 32) |
+                       ((u64)scsicmd->cmnd[6] << 24) | 
+                       (scsicmd->cmnd[7] << 16) |
+                       (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
+               count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
+                       (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
+       } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
+               dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid));
+
+               lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
+                   | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+               count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
+                     | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
        } else {
                dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid));
-               lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
+               lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
        }
-       dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n",
+       dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
          smp_processor_id(), (unsigned long long)lba, jiffies));
+       if ((!(dev->raw_io_interface) || !(dev->raw_io_64))
+        && (lba & 0xffffffff00000000LL)) {
+               dprintk((KERN_DEBUG "aac_write: Illegal lba\n"));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
+               set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+                           HARDWARE_ERROR,
+                           SENCODE_INTERNAL_TARGET_FAILURE,
+                           ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+                           0, 0);
+               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+                 (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))
+                   ? sizeof(scsicmd->sense_buffer)
+                   : sizeof(dev->fsa_dev[cid].sense_data));
+               scsicmd->scsi_done(scsicmd);
+               return 0;
+       }
        /*
         *      Allocate and initialize a Fib then setup a BlockWrite command
         */
-       if (!(cmd_fibcontext = fib_alloc(dev))) {
+       if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
                scsicmd->result = DID_ERROR << 16;
-               aac_io_done(scsicmd);
+               scsicmd->scsi_done(scsicmd);
                return 0;
        }
-       fib_init(cmd_fibcontext);
-
-       if(dev->dac_support == 1) {
+       aac_fib_init(cmd_fibcontext);
+
+       if (dev->raw_io_interface) {
+               struct aac_raw_io *writecmd;
+               writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext);
+               writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
+               writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
+               writecmd->count = cpu_to_le32(count<<9);
+               writecmd->cid = cpu_to_le16(cid);
+               writecmd->flags = 0; 
+               writecmd->bpTotal = 0;
+               writecmd->bpComplete = 0;
+               
+               aac_build_sgraw(scsicmd, &writecmd->sg);
+               fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
+               if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
+                       BUG();
+               /*
+                *      Now send the Fib to the adapter
+                */
+               status = aac_fib_send(ContainerRawIo,
+                         cmd_fibcontext, 
+                         fibsize, 
+                         FsaNormal, 
+                         0, 1, 
+                         (fib_callback) io_callback, 
+                         (void *) scsicmd);
+       } else if (dev->dac_support == 1) {
                struct aac_write64 *writecmd;
                writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
                writecmd->command = cpu_to_le32(VM_CtHostWrite64);
                writecmd->cid = cpu_to_le16(cid);
                writecmd->sector_count = cpu_to_le16(count); 
-               writecmd->block = cpu_to_le32(lba);
+               writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
                writecmd->pad   = 0;
                writecmd->flags = 0;
 
@@ -976,68 +1281,63 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
                fibsize = sizeof(struct aac_write64) + 
                        ((le32_to_cpu(writecmd->sg.count) - 1) * 
                         sizeof (struct sgentry64));
-               BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+               BUG_ON (fibsize > (dev->max_fib_size -
                                        sizeof(struct aac_fibhdr)));
                /*
                 *      Now send the Fib to the adapter
                 */
-               status = fib_send(ContainerCommand64, 
+               status = aac_fib_send(ContainerCommand64,
                          cmd_fibcontext, 
                          fibsize, 
                          FsaNormal, 
                          0, 1, 
-                         (fib_callback) write_callback, 
+                         (fib_callback) io_callback, 
                          (void *) scsicmd);
        } else {
                struct aac_write *writecmd;
                writecmd = (struct aac_write *) fib_data(cmd_fibcontext);
                writecmd->command = cpu_to_le32(VM_CtBlockWrite);
                writecmd->cid = cpu_to_le32(cid);
-               writecmd->block = cpu_to_le32(lba);
+               writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
                writecmd->count = cpu_to_le32(count * 512);
                writecmd->sg.count = cpu_to_le32(1);
                /* ->stable is not used - it did mean which type of write */
 
-               if (count * 512 > (64 * 1024)) {
-                       BUG();
-               }
-
                aac_build_sg(scsicmd, &writecmd->sg);
                fibsize = sizeof(struct aac_write) + 
                        ((le32_to_cpu(writecmd->sg.count) - 1) * 
                         sizeof (struct sgentry));
-               BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+               BUG_ON (fibsize > (dev->max_fib_size -
                                        sizeof(struct aac_fibhdr)));
                /*
                 *      Now send the Fib to the adapter
                 */
-               status = fib_send(ContainerCommand, 
+               status = aac_fib_send(ContainerCommand,
                          cmd_fibcontext, 
                          fibsize, 
                          FsaNormal, 
                          0, 1, 
-                         (fib_callback) write_callback, 
+                         (fib_callback) io_callback, 
                          (void *) scsicmd);
        }
 
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS)
-       {
-               dprintk("write queued.\n");
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
        }
 
-       printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);
+       printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
        /*
         *      For some reason, the Fib didn't queue, return QUEUE_FULL
         */
        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
-       aac_io_done(scsicmd);
+       scsicmd->scsi_done(scsicmd);
 
-       fib_complete(cmd_fibcontext);
-       fib_free(cmd_fibcontext);
+       aac_fib_complete(cmd_fibcontext);
+       aac_fib_free(cmd_fibcontext);
        return 0;
 }
 
@@ -1047,6 +1347,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
        struct scsi_cmnd *cmd;
 
        cmd = context;
+       cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
        dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 
                                smp_processor_id(), jiffies));
@@ -1060,7 +1361,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
        else {
                struct scsi_device *sdev = cmd->device;
                struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
-               u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
+               u32 cid = sdev_id(sdev);
                printk(KERN_WARNING 
                     "synchronize_callback: synchronize failed, status = %d\n",
                     le32_to_cpu(synchronizereply->status));
@@ -1076,9 +1377,9 @@ static void synchronize_callback(void *context, struct fib *fibptr)
                          sizeof(cmd->sense_buffer)));
        }
 
-       fib_complete(fibptr);
-       fib_free(fibptr);
-       aac_io_done(cmd);
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
+       cmd->scsi_done(cmd);
 }
 
 static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
@@ -1092,12 +1393,12 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
        unsigned long flags;
 
        /*
-        * Wait for all commands to complete to this specific
-        * target (block).
+        * Wait for all outstanding queued commands to complete to this
+        * specific target (block).
         */
        spin_lock_irqsave(&sdev->list_lock, flags);
        list_for_each_entry(cmd, &sdev->cmd_list, list)
-               if (cmd != scsicmd && cmd->serial_number != 0) {
+               if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
                        ++active;
                        break;
                }
@@ -1111,13 +1412,13 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
                return SCSI_MLQUEUE_DEVICE_BUSY;
 
        /*
-        *      Alocate and initialize a Fib
+        *      Allocate and initialize a Fib
         */
        if (!(cmd_fibcontext = 
-           fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) 
+           aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
                return SCSI_MLQUEUE_HOST_BUSY;
 
-       fib_init(cmd_fibcontext);
+       aac_fib_init(cmd_fibcontext);
 
        synchronizecmd = fib_data(cmd_fibcontext);
        synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
@@ -1129,7 +1430,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
        /*
         *      Now send the Fib to the adapter
         */
-       status = fib_send(ContainerCommand,
+       status = aac_fib_send(ContainerCommand,
                  cmd_fibcontext,
                  sizeof(struct aac_synchronize),
                  FsaNormal,
@@ -1140,13 +1441,15 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS)
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
+       }
 
        printk(KERN_WARNING 
-               "aac_synchronize: fib_send failed with status: %d.\n", status);
-       fib_complete(cmd_fibcontext);
-       fib_free(cmd_fibcontext);
+               "aac_synchronize: aac_fib_send failed with status: %d.\n", status);
+       aac_fib_complete(cmd_fibcontext);
+       aac_fib_free(cmd_fibcontext);
        return SCSI_MLQUEUE_HOST_BUSY;
 }
 
@@ -1164,22 +1467,21 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        struct Scsi_Host *host = scsicmd->device->host;
        struct aac_dev *dev = (struct aac_dev *)host->hostdata;
        struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
-       int cardtype = dev->cardtype;
-       int ret;
        
        /*
         *      If the bus, id or lun is out of range, return fail
         *      Test does not apply to ID 16, the pseudo id for the controller
         *      itself.
         */
-       if (scsicmd->device->id != host->this_id) {
-               if ((scsicmd->device->channel == 0) ){
-                       if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ 
+       if (scmd_id(scsicmd) != host->this_id) {
+               if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
+                       if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
+                                       (scsicmd->device->lun != 0)) {
                                scsicmd->result = DID_NO_CONNECT << 16;
                                scsicmd->scsi_done(scsicmd);
                                return 0;
                        }
-                       cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+                       cid = scmd_id(scsicmd);
 
                        /*
                         *      If the target container doesn't exist, it may have
@@ -1187,11 +1489,18 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                         */
                        if ((fsa_dev_ptr[cid].valid & 1) == 0) {
                                switch (scsicmd->cmnd[0]) {
+                               case SERVICE_ACTION_IN:
+                                       if (!(dev->raw_io_interface) ||
+                                           !(dev->raw_io_64) ||
+                                           ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+                                               break;
                                case INQUIRY:
                                case READ_CAPACITY:
                                case TEST_UNIT_READY:
                                        spin_unlock_irq(host->host_lock);
-                                       probe_container(dev, cid);
+                                       aac_probe_container(dev, cid);
+                                       if ((fsa_dev_ptr[cid].valid & 1) == 0)
+                                               fsa_dev_ptr[cid].valid = 0;
                                        spin_lock_irq(host->host_lock);
                                        if (fsa_dev_ptr[cid].valid == 0) {
                                                scsicmd->result = DID_NO_CONNECT << 16;
@@ -1246,44 +1555,90 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        switch (scsicmd->cmnd[0]) {
        case INQUIRY:
        {
-               struct inquiry_data *inq_data_ptr;
+               struct inquiry_data inq_data;
 
-               dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
-               inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
-               memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
+               dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
+               memset(&inq_data, 0, sizeof (struct inquiry_data));
 
-               inq_data_ptr->inqd_ver = 2;     /* claim compliance to SCSI-2 */
-               inq_data_ptr->inqd_dtq = 0x80;  /* set RMB bit to one indicating that the medium is removable */
-               inq_data_ptr->inqd_rdf = 2;     /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
-               inq_data_ptr->inqd_len = 31;
+               inq_data.inqd_ver = 2;  /* claim compliance to SCSI-2 */
+               inq_data.inqd_rdf = 2;  /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
+               inq_data.inqd_len = 31;
                /*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
-               inq_data_ptr->inqd_pad2= 0x32 ;  /*WBus16|Sync|CmdQue */
+               inq_data.inqd_pad2= 0x32 ;       /*WBus16|Sync|CmdQue */
                /*
                 *      Set the Vendor, Product, and Revision Level
                 *      see: <vendor>.c i.e. aac.c
                 */
-               if (scsicmd->device->id == host->this_id) {
-                       setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *)));
-                       inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */
+               if (scmd_id(scsicmd) == host->this_id) {
+                       setinqstr(dev, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
+                       inq_data.inqd_pdt = INQD_PDT_PROC;      /* Processor device */
+                       aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
                        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                        scsicmd->scsi_done(scsicmd);
                        return 0;
                }
-               setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type);
-               inq_data_ptr->inqd_pdt = INQD_PDT_DA;   /* Direct/random access device */
+               setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+               inq_data.inqd_pdt = INQD_PDT_DA;        /* Direct/random access device */
+               aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
                return aac_get_container_name(scsicmd, cid);
        }
+       case SERVICE_ACTION_IN:
+               if (!(dev->raw_io_interface) ||
+                   !(dev->raw_io_64) ||
+                   ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+                       break;
+       {
+               u64 capacity;
+               char cp[13];
+
+               dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
+               capacity = fsa_dev_ptr[cid].size - 1;
+               cp[0] = (capacity >> 56) & 0xff;
+               cp[1] = (capacity >> 48) & 0xff;
+               cp[2] = (capacity >> 40) & 0xff;
+               cp[3] = (capacity >> 32) & 0xff;
+               cp[4] = (capacity >> 24) & 0xff;
+               cp[5] = (capacity >> 16) & 0xff;
+               cp[6] = (capacity >> 8) & 0xff;
+               cp[7] = (capacity >> 0) & 0xff;
+               cp[8] = 0;
+               cp[9] = 0;
+               cp[10] = 2;
+               cp[11] = 0;
+               cp[12] = 0;
+               aac_internal_transfer(scsicmd, cp, 0,
+                 min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
+               if (sizeof(cp) < scsicmd->cmnd[13]) {
+                       unsigned int len, offset = sizeof(cp);
+
+                       memset(cp, 0, offset);
+                       do {
+                               len = min_t(size_t, scsicmd->cmnd[13] - offset,
+                                               sizeof(cp));
+                               aac_internal_transfer(scsicmd, cp, offset, len);
+                       } while ((offset += len) < scsicmd->cmnd[13]);
+               }
+
+               /* Do not cache partition table for arrays */
+               scsicmd->device->removable = 1;
+
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+               scsicmd->scsi_done(scsicmd);
+
+               return 0;
+       }
+
        case READ_CAPACITY:
        {
                u32 capacity;
-               char *cp;
+               char cp[8];
 
                dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
-               if (fsa_dev_ptr[cid].size <= 0x100000000LL)
+               if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
                        capacity = fsa_dev_ptr[cid].size - 1;
                else
                        capacity = (u32)-1;
-               cp = scsicmd->request_buffer;
+
                cp[0] = (capacity >> 24) & 0xff;
                cp[1] = (capacity >> 16) & 0xff;
                cp[2] = (capacity >> 8) & 0xff;
@@ -1292,6 +1647,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                cp[5] = 0;
                cp[6] = 2;
                cp[7] = 0;
+               aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
+               /* Do not cache partition table for arrays */
+               scsicmd->device->removable = 1;
 
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);
@@ -1301,15 +1659,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
 
        case MODE_SENSE:
        {
-               char *mode_buf;
+               char mode_buf[4];
 
                dprintk((KERN_DEBUG "MODE SENSE command.\n"));
-               mode_buf = scsicmd->request_buffer;
                mode_buf[0] = 3;        /* Mode data length */
                mode_buf[1] = 0;        /* Medium type - default */
                mode_buf[2] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
                mode_buf[3] = 0;        /* Block descriptor length */
 
+               aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);
 
@@ -1317,10 +1675,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        }
        case MODE_SENSE_10:
        {
-               char *mode_buf;
+               char mode_buf[8];
 
                dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
-               mode_buf = scsicmd->request_buffer;
                mode_buf[0] = 0;        /* Mode data length (MSB) */
                mode_buf[1] = 6;        /* Mode data length (LSB) */
                mode_buf[2] = 0;        /* Medium type - default */
@@ -1329,6 +1686,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                mode_buf[5] = 0;        /* reserved */
                mode_buf[6] = 0;        /* Block descriptor length (MSB) */
                mode_buf[7] = 0;        /* Block descriptor length (LSB) */
+               aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf));
 
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);
@@ -1372,28 +1730,27 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        {
                case READ_6:
                case READ_10:
+               case READ_12:
+               case READ_16:
                        /*
                         *      Hack to keep track of ordinal number of the device that
                         *      corresponds to a container. Needed to convert
                         *      containers to /dev/sd device names
                         */
                         
-                       spin_unlock_irq(host->host_lock);
-                       if  (scsicmd->request->rq_disk)
-                               memcpy(fsa_dev_ptr[cid].devname,
-                                       scsicmd->request->rq_disk->disk_name,
-                                       8);
+                       if (scsicmd->request->rq_disk)
+                               strlcpy(fsa_dev_ptr[cid].devname,
+                               scsicmd->request->rq_disk->disk_name,
+                               min(sizeof(fsa_dev_ptr[cid].devname),
+                               sizeof(scsicmd->request->rq_disk->disk_name) + 1));
 
-                       ret = aac_read(scsicmd, cid);
-                       spin_lock_irq(host->host_lock);
-                       return ret;
+                       return aac_read(scsicmd, cid);
 
                case WRITE_6:
                case WRITE_10:
-                       spin_unlock_irq(host->host_lock);
-                       ret = aac_write(scsicmd, cid);
-                       spin_lock_irq(host->host_lock);
-                       return ret;
+               case WRITE_12:
+               case WRITE_16:
+                       return aac_write(scsicmd, cid);
 
                case SYNCHRONIZE_CACHE:
                        /* Issue FIB to tell Firmware to flush it's cache */
@@ -1403,7 +1760,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        /*
                         *      Unhandled commands
                         */
-                       printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]);
+                       dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
                        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
                        set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
                                ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
@@ -1426,7 +1783,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
        if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
                return -EFAULT;
        if (qd.cnum == -1)
-               qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);
+               qd.cnum = qd.id;
        else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) 
        {
                if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)
@@ -1538,6 +1895,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
        struct scsi_cmnd *scsicmd;
 
        scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
        if (fibptr == NULL)
@@ -1584,33 +1942,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
        case SRB_STATUS_ERROR_RECOVERY:
        case SRB_STATUS_PENDING:
        case SRB_STATUS_SUCCESS:
-               if(scsicmd->cmnd[0] == INQUIRY ){
-                       u8 b;
-                       u8 b1;
-                       /* We can't expose disk devices because we can't tell whether they
-                        * are the raw container drives or stand alone drives.  If they have
-                        * the removable bit set then we should expose them though.
-                        */
-                       b = (*(u8*)scsicmd->buffer)&0x1f;
-                       b1 = ((u8*)scsicmd->buffer)[1];
-                       if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER 
-                                       || (b==TYPE_DISK && (b1&0x80)) ){
-                               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
-                       /*
-                        * We will allow disk devices if in RAID/SCSI mode and
-                        * the channel is 2
-                        */
-                       } else if ((dev->raid_scsi_mode) &&
-                                       (scsicmd->device->channel == 2)) {
-                               scsicmd->result = DID_OK << 16 | 
-                                               COMMAND_COMPLETE << 8;
-                       } else {
-                               scsicmd->result = DID_NO_CONNECT << 16 | 
-                                               COMMAND_COMPLETE << 8;
-                       }
-               } else {
-                       scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
-               }
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                break;
        case SRB_STATUS_DATA_OVERRUN:
                switch(scsicmd->cmnd[0]){
@@ -1620,6 +1952,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                case  WRITE_10:
                case  READ_12:
                case  WRITE_12:
+               case  READ_16:
+               case  WRITE_16:
                        if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) {
                                printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
                        } else {
@@ -1628,28 +1962,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                        scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
                        break;
                case INQUIRY: {
-                       u8 b;
-                       u8 b1;
-                       /* We can't expose disk devices because we can't tell whether they
-                       * are the raw container drives or stand alone drives
-                       */
-                       b = (*(u8*)scsicmd->buffer)&0x0f;
-                       b1 = ((u8*)scsicmd->buffer)[1];
-                       if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
-                                       || (b==TYPE_DISK && (b1&0x80)) ){
-                               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
-                       /*
-                        * We will allow disk devices if in RAID/SCSI mode and
-                        * the channel is 2
-                        */
-                       } else if ((dev->raid_scsi_mode) &&
-                                       (scsicmd->device->channel == 2)) {
-                               scsicmd->result = DID_OK << 16 | 
-                                               COMMAND_COMPLETE << 8;
-                       } else {
-                               scsicmd->result = DID_NO_CONNECT << 16 | 
-                                               COMMAND_COMPLETE << 8;
-                       }
+                       scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        break;
                }
                default:
@@ -1725,8 +2038,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                                sizeof(scsicmd->sense_buffer) :
                                le32_to_cpu(srbreply->sense_data_size);
 #ifdef AAC_DETAILED_STATUS_INFO
-               dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", 
-                                       le32_to_cpu(srbreply->status), len));
+               printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
+                                       le32_to_cpu(srbreply->status), len);
 #endif
                memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
                
@@ -1736,9 +2049,9 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
         */
        scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
 
-       fib_complete(fibptr);
-       fib_free(fibptr);
-       aac_io_done(scsicmd);
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
+       scsicmd->scsi_done(scsicmd);
 }
 
 /**
@@ -1760,13 +2073,14 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
        u32 flag;
        u32 timeout;
 
-       if( scsicmd->device->id > 15 || scsicmd->device->lun > 7) {
+       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+       if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
+                       scsicmd->device->lun > 7) {
                scsicmd->result = DID_NO_CONNECT << 16;
                scsicmd->scsi_done(scsicmd);
                return 0;
        }
 
-       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        switch(scsicmd->sc_data_direction){
        case DMA_TO_DEVICE:
                flag = SRB_DataOut;
@@ -1787,18 +2101,18 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
        /*
         *      Allocate and initialize a Fib then setup a BlockWrite command
         */
-       if (!(cmd_fibcontext = fib_alloc(dev))) {
+       if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
                return -1;
        }
-       fib_init(cmd_fibcontext);
+       aac_fib_init(cmd_fibcontext);
 
        srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
        srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
-       srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel));
-       srbcmd->id   = cpu_to_le32(scsicmd->device->id);
+       srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd)));
+       srbcmd->id   = cpu_to_le32(scmd_id(scsicmd));
        srbcmd->lun      = cpu_to_le32(scsicmd->device->lun);
        srbcmd->flags    = cpu_to_le32(flag);
-       timeout = (scsicmd->timeout-jiffies)/HZ;
+       timeout = scsicmd->timeout_per_command/HZ;
        if(timeout == 0){
                timeout = 1;
        }
@@ -1818,13 +2132,13 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
                fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
                        ((le32_to_cpu(srbcmd->sg.count) & 0xff) * 
                         sizeof (struct sgentry64));
-               BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+               BUG_ON (fibsize > (dev->max_fib_size -
                                        sizeof(struct aac_fibhdr)));
 
                /*
                 *      Now send the Fib to the adapter
                 */
-               status = fib_send(ScsiPortCommand64, cmd_fibcontext, 
+               status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext,
                                fibsize, FsaNormal, 0, 1,
                                  (fib_callback) aac_srb_callback, 
                                  (void *) scsicmd);
@@ -1840,25 +2154,26 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
                fibsize = sizeof (struct aac_srb) + 
                        (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
                         sizeof (struct sgentry));
-               BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+               BUG_ON (fibsize > (dev->max_fib_size -
                                        sizeof(struct aac_fibhdr)));
 
                /*
                 *      Now send the Fib to the adapter
                 */
-               status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
+               status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
                                  (fib_callback) aac_srb_callback, (void *) scsicmd);
        }
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS){
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
        }
 
-       printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);
-       fib_complete(cmd_fibcontext);
-       fib_free(cmd_fibcontext);
+       printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
+       aac_fib_complete(cmd_fibcontext);
+       aac_fib_free(cmd_fibcontext);
 
        return -1;
 }
@@ -1883,8 +2198,6 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
                        scsicmd->sc_data_direction);
                psg->count = cpu_to_le32(sg_count);
 
-               byte_count = 0;
-
                for (i = 0; i < sg_count; i++) {
                        psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
                        psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
@@ -1893,7 +2206,9 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
                }
                /* hba wants the size to be exact */
                if(byte_count > scsicmd->request_bufflen){
-                       psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+                               (byte_count - scsicmd->request_bufflen);
+                       psg->sg[i-1].count = cpu_to_le32(temp);
                        byte_count = scsicmd->request_bufflen;
                }
                /* Check for command underflow */
@@ -1922,7 +2237,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
 {
        struct aac_dev *dev;
        unsigned long byte_count = 0;
-       u64 le_addr;
+       u64 addr;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        // Get rid of old data
@@ -1938,21 +2253,86 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
 
                sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
                        scsicmd->sc_data_direction);
+
+               for (i = 0; i < sg_count; i++) {
+                       int count = sg_dma_len(sg);
+                       addr = sg_dma_address(sg);
+                       psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+                       psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+                       psg->sg[i].count = cpu_to_le32(count);
+                       byte_count += count;
+                       sg++;
+               }
                psg->count = cpu_to_le32(sg_count);
+               /* hba wants the size to be exact */
+               if(byte_count > scsicmd->request_bufflen){
+                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+                               (byte_count - scsicmd->request_bufflen);
+                       psg->sg[i-1].count = cpu_to_le32(temp);
+                       byte_count = scsicmd->request_bufflen;
+               }
+               /* Check for command underflow */
+               if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
+                       printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+                                       byte_count, scsicmd->underflow);
+               }
+       }
+       else if(scsicmd->request_bufflen) {
+               scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
+                               scsicmd->request_buffer,
+                               scsicmd->request_bufflen,
+                               scsicmd->sc_data_direction);
+               addr = scsicmd->SCp.dma_handle;
+               psg->count = cpu_to_le32(1);
+               psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
+               psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
+               psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
+               byte_count = scsicmd->request_bufflen;
+       }
+       return byte_count;
+}
+
+static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+{
+       struct Scsi_Host *host = scsicmd->device->host;
+       struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+       unsigned long byte_count = 0;
+
+       // Get rid of old data
+       psg->count = 0;
+       psg->sg[0].next = 0;
+       psg->sg[0].prev = 0;
+       psg->sg[0].addr[0] = 0;
+       psg->sg[0].addr[1] = 0;
+       psg->sg[0].count = 0;
+       psg->sg[0].flags = 0;
+       if (scsicmd->use_sg) {
+               struct scatterlist *sg;
+               int i;
+               int sg_count;
+               sg = (struct scatterlist *) scsicmd->request_buffer;
 
-               byte_count = 0;
+               sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
+                       scsicmd->sc_data_direction);
 
                for (i = 0; i < sg_count; i++) {
-                       le_addr = cpu_to_le64(sg_dma_address(sg));
-                       psg->sg[i].addr[1] = (u32)(le_addr>>32);
-                       psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
-                       psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
-                       byte_count += sg_dma_len(sg);
+                       int count = sg_dma_len(sg);
+                       u64 addr = sg_dma_address(sg);
+                       psg->sg[i].next = 0;
+                       psg->sg[i].prev = 0;
+                       psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
+                       psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+                       psg->sg[i].count = cpu_to_le32(count);
+                       psg->sg[i].flags = 0;
+                       byte_count += count;
                        sg++;
                }
+               psg->count = cpu_to_le32(sg_count);
                /* hba wants the size to be exact */
                if(byte_count > scsicmd->request_bufflen){
-                       psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+                       u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+                               (byte_count - scsicmd->request_bufflen);
+                       psg->sg[i-1].count = cpu_to_le32(temp);
                        byte_count = scsicmd->request_bufflen;
                }
                /* Check for command underflow */
@@ -1962,17 +2342,21 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
                }
        }
        else if(scsicmd->request_bufflen) {
-               dma_addr_t addr; 
-               addr = pci_map_single(dev->pdev,
+               int count;
+               u64 addr;
+               scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
                                scsicmd->request_buffer,
                                scsicmd->request_bufflen,
                                scsicmd->sc_data_direction);
+               addr = scsicmd->SCp.dma_handle;
+               count = scsicmd->request_bufflen;
                psg->count = cpu_to_le32(1);
-               le_addr = cpu_to_le64(addr);
-               psg->sg[0].addr[1] = (u32)(le_addr>>32);
-               psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
-               psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-               scsicmd->SCp.dma_handle = addr;
+               psg->sg[0].next = 0;
+               psg->sg[0].prev = 0;
+               psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32));
+               psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+               psg->sg[0].count = cpu_to_le32(count);
+               psg->sg[0].flags = 0;
                byte_count = scsicmd->request_bufflen;
        }
        return byte_count;