summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/aachba.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r--drivers/scsi/aacraid/aachba.c374
1 files changed, 301 insertions, 73 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index a8e3dfcd0dc..7139659dd95 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -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;
@@ -497,11 +507,29 @@ 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);
}
/**