]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/aacraid/aachba.c
[ACPI] merge 3549 4320 4485 4588 4980 5483 5651 acpica asus fops pnpacpi branches...
[linux-2.6-omap-h63xx.git] / drivers / scsi / aacraid / aachba.c
index a8e3dfcd0dc758025a388a201f8eaddae5d23d58..7139659dd952e4cf36eb971c8491a5dcd4b42136 100644 (file)
@@ -313,18 +313,37 @@ 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 (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;
                }
@@ -340,15 +359,6 @@ int aac_get_containers(struct aac_dev *dev)
        return status;
 }
 
-static void aac_io_done(struct scsi_cmnd * scsicmd)
-{
-       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);
-}
-
 static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
 {
        void *buf;
@@ -405,7 +415,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
 
        fib_complete(fibptr);
        fib_free(fibptr);
-       aac_io_done(scsicmd);
+       scsicmd->scsi_done(scsicmd);
 }
 
 /**
@@ -460,7 +470,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 probe_container(struct aac_dev *dev, int cid)
 {
        struct fsa_dev_info *fsa_dev_ptr;
        int status;
@@ -496,12 +506,30 @@ static int probe_container(struct aac_dev *dev, int cid)
 
        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 (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;
        }
@@ -571,17 +599,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;
@@ -590,7 +644,9 @@ 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);
 }
@@ -655,7 +711,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
                         fibptr, 
                         sizeof(*info),
                         FsaNormal, 
-                        1, 1, 
+                        -1, 1, /* First `interrupt' command uses special wait */
                         NULL, 
                         NULL);
 
@@ -785,12 +841,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;
@@ -806,8 +862,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
        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 sgmap)) /
-                               sizeof(struct sgmap);
+                       sizeof(struct aac_write) + sizeof(struct sgentry)) /
+                               sizeof(struct sgentry);
                if (dev->dac_support) {
                        /* 
                         * 38 scatter gather elements 
@@ -816,8 +872,8 @@ int aac_get_adapter_info(struct aac_dev* dev)
                                (dev->max_fib_size -
                                sizeof(struct aac_fibhdr) -
                                sizeof(struct aac_write64) +
-                               sizeof(struct sgmap64)) /
-                                       sizeof(struct sgmap64);
+                               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)) {
@@ -854,7 +910,40 @@ static void io_callback(void *context, struct fib * fibptr)
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
 
-       dprintk((KERN_DEBUG "io_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3], 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();
@@ -890,12 +979,12 @@ static void io_callback(void *context, struct fib * fibptr)
        fib_complete(fibptr);
        fib_free(fibptr);
 
-       aac_io_done(scsicmd);
+       scsicmd->scsi_done(scsicmd);
 }
 
 static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 {
-       u32 lba;
+       u64 lba;
        u32 count;
        int status;
 
@@ -907,23 +996,69 @@ static 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 = %u, t = %ld.\n",
+       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;
+       }
        /*
         *      Alocate and initialize a Fib
         */
@@ -936,8 +1071,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
        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(lba);
-               readcmd->block[1] = 0;
+               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);
@@ -964,7 +1099,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
                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; 
 
@@ -989,7 +1124,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
                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);
 
                aac_build_sg(scsicmd, &readcmd->sg);
@@ -1023,7 +1158,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
         *      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);
        return 0;
@@ -1031,7 +1166,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 
 static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 {
-       u32 lba;
+       u64 lba;
        u32 count;
        int status;
        u16 fibsize;
@@ -1048,19 +1183,54 @@ 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))) {
                scsicmd->result = DID_ERROR << 16;
-               aac_io_done(scsicmd);
+               scsicmd->scsi_done(scsicmd);
                return 0;
        }
        fib_init(cmd_fibcontext);
@@ -1068,8 +1238,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
        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(lba);
-               writecmd->block[1] = 0;
+               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; 
@@ -1096,7 +1266,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
                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;
 
@@ -1121,7 +1291,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
                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 */
@@ -1157,7 +1327,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
         *      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);
@@ -1201,7 +1371,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
 
        fib_complete(fibptr);
        fib_free(fibptr);
-       aac_io_done(cmd);
+       cmd->scsi_done(cmd);
 }
 
 static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
@@ -1287,7 +1457,6 @@ 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;
        
        /*
@@ -1295,7 +1464,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
         *      Test does not apply to ID 16, the pseudo id for the controller
         *      itself.
         */
-       if (scsicmd->device->id != host->this_id) {
+       if (scmd_id(scsicmd) != host->this_id) {
                if ((scsicmd->device->channel == 0) ){
                        if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ 
                                scsicmd->result = DID_NO_CONNECT << 16;
@@ -1310,11 +1479,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);
+                                       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;
@@ -1375,7 +1551,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                memset(&inq_data, 0, sizeof (struct inquiry_data));
 
                inq_data.inqd_ver = 2;  /* claim compliance to SCSI-2 */
-               inq_data.inqd_dtq = 0x80;       /* set RMB bit to one indicating that the medium is removable */
                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 */
@@ -1384,26 +1559,71 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                 *      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.inqd_vid), (sizeof(container_types)/sizeof(char *)));
+               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.inqd_vid), fsa_dev_ptr[cid].type);
+               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((unsigned int)scsicmd->cmnd[13], sizeof(cp)));
+               if (sizeof(cp) < scsicmd->cmnd[13]) {
+                       unsigned int len, offset = sizeof(cp);
+
+                       memset(cp, 0, offset);
+                       do {
+                               len = min(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[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;
@@ -1417,6 +1637,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                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);
@@ -1497,6 +1719,8 @@ 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
@@ -1504,17 +1728,19 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                         */
                         
                        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;
 
                case WRITE_6:
                case WRITE_10:
+               case WRITE_12:
+               case WRITE_16:
                        spin_unlock_irq(host->host_lock);
                        ret = aac_write(scsicmd, cid);
                        spin_lock_irq(host->host_lock);
@@ -1726,7 +1952,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                         * the channel is 2
                         */
                        } else if ((dev->raid_scsi_mode) &&
-                                       (scsicmd->device->channel == 2)) {
+                                       (scmd_channel(scsicmd) == 2)) {
                                scsicmd->result = DID_OK << 16 | 
                                                COMMAND_COMPLETE << 8;
                        } else {
@@ -1745,6 +1971,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 {
@@ -1768,7 +1996,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                         * the channel is 2
                         */
                        } else if ((dev->raid_scsi_mode) &&
-                                       (scsicmd->device->channel == 2)) {
+                                       (scmd_channel(scsicmd) == 2)) {
                                scsicmd->result = DID_OK << 16 | 
                                                COMMAND_COMPLETE << 8;
                        } else {
@@ -1850,8 +2078,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);
                
@@ -1863,7 +2091,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
 
        fib_complete(fibptr);
        fib_free(fibptr);
-       aac_io_done(scsicmd);
+       scsicmd->scsi_done(scsicmd);
 }
 
 /**