Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d69cff2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI updates from James Bottomley:
 "This is the usual grab bag of driver updates (lpfc, qla2xxx, storvsc,
  aacraid, ipr) plus an assortment of minor updates.  There's also a
  major update to aic1542 which moves the driver into this millenium"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (106 commits)
  change SCSI Maintainer email
  sd, mmc, virtio_blk, string_helpers: fix block size units
  ufs: add support to allow non standard behaviours (quirks)
  ufs-qcom: save controller revision info in internal structure
  qla2xxx: Update driver version to 8.07.00.18-k
  qla2xxx: Restore physical port WWPN only, when port down detected for FA-WWPN port.
  qla2xxx: Fix virtual port configuration, when switch port is disabled/enabled.
  qla2xxx: Prevent multiple firmware dump collection for ISP27XX.
  qla2xxx: Disable Interrupt handshake for ISP27XX.
  qla2xxx: Add debugging info for MBX timeout.
  qla2xxx: Add serdes read/write support for ISP27XX
  qla2xxx: Add udev notification to save fw dump for ISP27XX
  qla2xxx: Add message for sucessful FW dump collected for ISP27XX.
  qla2xxx: Add support to load firmware from file for ISP 26XX/27XX.
  qla2xxx: Fix beacon blink for ISP27XX.
  qla2xxx: Increase the wait time for firmware to be ready for P3P.
  qla2xxx: Fix crash due to wrong casting of reg for ISP27XX.
  qla2xxx: Fix warnings reported by static checker.
  lpfc: Update version to 10.5.0.0 for upstream patch set
  lpfc: Update copyright to 2015
  ...
parents 8fa6f497 0351b8f8
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -8653,11 +8653,9 @@ F: drivers/scsi/sg.c
F:	include/scsi/sg.h

SCSI SUBSYSTEM
M:	"James E.J. Bottomley" <JBottomley@parallels.com>
M:	"James E.J. Bottomley" <JBottomley@odin.com>
L:	linux-scsi@vger.kernel.org
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
S:	Maintained
F:	drivers/scsi/
F:	include/scsi/
+5 −4
Original line number Diff line number Diff line
@@ -342,7 +342,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
	struct request_queue *q = vblk->disk->queue;
	char cap_str_2[10], cap_str_10[10];
	char *envp[] = { "RESIZE=1", NULL };
	u64 capacity, size;
	u64 capacity;

	/* Host must always specify the capacity. */
	virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);
@@ -354,9 +354,10 @@ static void virtblk_config_changed_work(struct work_struct *work)
		capacity = (sector_t)-1;
	}

	size = capacity * queue_logical_block_size(q);
	string_get_size(size, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
	string_get_size(size, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));
	string_get_size(capacity, queue_logical_block_size(q),
			STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
	string_get_size(capacity, queue_logical_block_size(q),
			STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));

	dev_notice(&vdev->dev,
		  "new size: %llu %d-byte logical blocks (%s/%s)\n",
+2 −2
Original line number Diff line number Diff line
@@ -2230,7 +2230,7 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
	part_md->part_type = part_type;
	list_add(&part_md->part, &md->part);

	string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
	string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2,
			cap_str, sizeof(cap_str));
	pr_info("%s: %s %s partition %u %s\n",
	       part_md->disk->disk_name, mmc_card_id(card),
@@ -2436,7 +2436,7 @@ static int mmc_blk_probe(struct device *dev)
	if (IS_ERR(md))
		return PTR_ERR(md);

	string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
	string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
			cap_str, sizeof(cap_str));
	pr_info("%s: %s %s %s %s\n",
		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
+5 −5
Original line number Diff line number Diff line
@@ -474,11 +474,11 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
 */
#ifndef USLEEP_SLEEP
/* 20 ms (reasonable hard disk speed) */
#define USLEEP_SLEEP (20*HZ/1000)
#define USLEEP_SLEEP msecs_to_jiffies(20)
#endif
/* 300 RPM (floppy speed) */
#ifndef USLEEP_POLL
#define USLEEP_POLL (200*HZ/1000)
#define USLEEP_POLL msecs_to_jiffies(200)
#endif
#ifndef USLEEP_WAITLONG
/* RvC: (reasonable time to wait on select error) */
@@ -576,7 +576,7 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
		if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
			trying_irqs |= mask;

	timeout = jiffies + (250 * HZ / 1000);
	timeout = jiffies + msecs_to_jiffies(250);
	probe_irq = NO_IRQ;

	/*
@@ -634,7 +634,7 @@ static void prepare_info(struct Scsi_Host *instance)
	         "sg_tablesize %d, this_id %d, "
	         "flags { %s%s%s}, "
#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
	         "USLEEP_POLL %d, USLEEP_WAITLONG %d, "
		 "USLEEP_POLL %lu, USLEEP_WAITLONG %lu, "
#endif
	         "options { %s} ",
	         instance->hostt->name, instance->io_port, instance->n_io_port,
@@ -1346,7 +1346,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
	 * selection.
	 */

	timeout = jiffies + (250 * HZ / 1000);
	timeout = jiffies + msecs_to_jiffies(250);

	/* 
	 * XXX very interesting - we're seeing a bounce where the BSY we 
+348 −62
Original line number Diff line number Diff line
@@ -111,6 +111,41 @@
#define BYTE2(x) (unsigned char)((x) >> 16)
#define BYTE3(x) (unsigned char)((x) >> 24)

/* MODE_SENSE data format */
typedef struct {
	struct {
		u8	data_length;
		u8	med_type;
		u8	dev_par;
		u8	bd_length;
	} __attribute__((packed)) hd;
	struct {
		u8	dens_code;
		u8	block_count[3];
		u8	reserved;
		u8	block_length[3];
	} __attribute__((packed)) bd;
		u8	mpc_buf[3];
} __attribute__((packed)) aac_modep_data;

/* MODE_SENSE_10 data format */
typedef struct {
	struct {
		u8	data_length[2];
		u8	med_type;
		u8	dev_par;
		u8	rsrvd[2];
		u8	bd_length[2];
	} __attribute__((packed)) hd;
	struct {
		u8	dens_code;
		u8	block_count[3];
		u8	reserved;
		u8	block_length[3];
	} __attribute__((packed)) bd;
		u8	mpc_buf[3];
} __attribute__((packed)) aac_modep10_data;

/*------------------------------------------------------------------------------
 *              S T R U C T S / T Y P E D E F S
 *----------------------------------------------------------------------------*/
@@ -128,6 +163,48 @@ struct inquiry_data {
	u8 inqd_prl[4];	/* Product Revision Level */
};

/* Added for VPD 0x83 */
typedef struct {
	u8 CodeSet:4;	/* VPD_CODE_SET */
	u8 Reserved:4;
	u8 IdentifierType:4;	/* VPD_IDENTIFIER_TYPE */
	u8 Reserved2:4;
	u8 Reserved3;
	u8 IdentifierLength;
	u8 VendId[8];
	u8 ProductId[16];
	u8 SerialNumber[8];	/* SN in ASCII */

} TVPD_ID_Descriptor_Type_1;

typedef struct {
	u8 CodeSet:4;	/* VPD_CODE_SET */
	u8 Reserved:4;
	u8 IdentifierType:4;	/* VPD_IDENTIFIER_TYPE */
	u8 Reserved2:4;
	u8 Reserved3;
	u8 IdentifierLength;
	struct TEU64Id {
		u32 Serial;
		 /* The serial number supposed to be 40 bits,
		  * bit we only support 32, so make the last byte zero. */
		u8 Reserved;
		u8 VendId[3];
	} EU64Id;

} TVPD_ID_Descriptor_Type_2;

typedef struct {
	u8 DeviceType:5;
	u8 DeviceTypeQualifier:3;
	u8 PageCode;
	u8 Reserved;
	u8 PageLength;
	TVPD_ID_Descriptor_Type_1 IdDescriptorType1;
	TVPD_ID_Descriptor_Type_2 IdDescriptorType2;

} TVPD_Page83;

/*
 *              M O D U L E   G L O B A L S
 */
@@ -385,6 +462,11 @@ 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);
		if (fibptr->dev->supplement_adapter_info.SupportedOptions2 &
		    AAC_OPTION_SUPPORTED_240_VOLUMES) {
			maximum_num_containers =
				le32_to_cpu(dresp->MaxSimpleVolumes);
		}
		aac_fib_complete(fibptr);
	}
	/* FIB should be freed only after getting the response from the F/W */
@@ -438,7 +520,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
	if ((le32_to_cpu(get_name_reply->status) == CT_OK)
	 && (get_name_reply->data[0] != '\0')) {
		char *sp = get_name_reply->data;
		sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
		sp[sizeof(((struct aac_get_name_resp *)NULL)->data)] = '\0';
		while (*sp == ' ')
			++sp;
		if (*sp) {
@@ -539,6 +621,14 @@ static void _aac_probe_container2(void * context, struct fib * fibptr)
		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)) {
			if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 &
			    AAC_OPTION_VARIABLE_BLOCK_SIZE)) {
				dresp->mnt[0].fileinfo.bdevinfo.block_size = 0x200;
				fsa_dev_ptr->block_size = 0x200;
			} else {
				fsa_dev_ptr->block_size =
					le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size);
			}
			fsa_dev_ptr->valid = 1;
			/* sense_key holds the current state of the spin-up */
			if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY))
@@ -571,6 +661,8 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
	int status;

	dresp = (struct aac_mount *) fib_data(fibptr);
	if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 &
	    AAC_OPTION_VARIABLE_BLOCK_SIZE))
		dresp->mnt[0].capacityhigh = 0;
	if ((le32_to_cpu(dresp->status) != ST_OK) ||
	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
@@ -586,7 +678,12 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)

	dinfo = (struct aac_query_mount *)fib_data(fibptr);

	if (fibptr->dev->supplement_adapter_info.SupportedOptions2 &
	    AAC_OPTION_VARIABLE_BLOCK_SIZE)
		dinfo->command = cpu_to_le32(VM_NameServeAllBlk);
	else
		dinfo->command = cpu_to_le32(VM_NameServe64);

	dinfo->count = cpu_to_le32(scmd_id(scsicmd));
	dinfo->type = cpu_to_le32(FT_FILESYS);

@@ -621,7 +718,12 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru

		dinfo = (struct aac_query_mount *)fib_data(fibptr);

		if (fibptr->dev->supplement_adapter_info.SupportedOptions2 &
		    AAC_OPTION_VARIABLE_BLOCK_SIZE)
			dinfo->command = cpu_to_le32(VM_NameServeAllBlk);
		else
			dinfo->command = cpu_to_le32(VM_NameServe);

		dinfo->count = cpu_to_le32(scmd_id(scsicmd));
		dinfo->type = cpu_to_le32(FT_FILESYS);
		scsicmd->SCp.ptr = (char *)callback;
@@ -835,6 +937,78 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
	get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr);
	/* Failure is irrelevant, using default value instead */
	if (le32_to_cpu(get_serial_reply->status) == CT_OK) {
		/*Check to see if it's for VPD 0x83 or 0x80 */
		if (scsicmd->cmnd[2] == 0x83) {
			/* vpd page 0x83 - Device Identification Page */
			int i;
			TVPD_Page83 VPDPage83Data;

			memset(((u8 *)&VPDPage83Data), 0,
			       sizeof(VPDPage83Data));

			/* DIRECT_ACCESS_DEVIC */
			VPDPage83Data.DeviceType = 0;
			/* DEVICE_CONNECTED */
			VPDPage83Data.DeviceTypeQualifier = 0;
			/* VPD_DEVICE_IDENTIFIERS */
			VPDPage83Data.PageCode = 0x83;
			VPDPage83Data.Reserved = 0;
			VPDPage83Data.PageLength =
				sizeof(VPDPage83Data.IdDescriptorType1) +
				sizeof(VPDPage83Data.IdDescriptorType2);

			/* T10 Vendor Identifier Field Format */
			/* VpdCodeSetAscii */
			VPDPage83Data.IdDescriptorType1.CodeSet = 2;
			/* VpdIdentifierTypeVendorId */
			VPDPage83Data.IdDescriptorType1.IdentifierType = 1;
			VPDPage83Data.IdDescriptorType1.IdentifierLength =
				sizeof(VPDPage83Data.IdDescriptorType1) - 4;

			/* "ADAPTEC " for adaptec */
			memcpy(VPDPage83Data.IdDescriptorType1.VendId,
				"ADAPTEC ",
				sizeof(VPDPage83Data.IdDescriptorType1.VendId));
			memcpy(VPDPage83Data.IdDescriptorType1.ProductId,
				"ARRAY           ",
				sizeof(
				VPDPage83Data.IdDescriptorType1.ProductId));

			/* Convert to ascii based serial number.
			 * The LSB is the the end.
			 */
			for (i = 0; i < 8; i++) {
				u8 temp =
					(u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF);
				if (temp  > 0x9) {
					VPDPage83Data.IdDescriptorType1.SerialNumber[i] =
							'A' + (temp - 0xA);
				} else {
					VPDPage83Data.IdDescriptorType1.SerialNumber[i] =
							'0' + temp;
				}
			}

			/* VpdCodeSetBinary */
			VPDPage83Data.IdDescriptorType2.CodeSet = 1;
			/* VpdIdentifierTypeEUI64 */
			VPDPage83Data.IdDescriptorType2.IdentifierType = 2;
			VPDPage83Data.IdDescriptorType2.IdentifierLength =
				sizeof(VPDPage83Data.IdDescriptorType2) - 4;

			VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0;
			VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0;
			VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0;

			VPDPage83Data.IdDescriptorType2.EU64Id.Serial =
							get_serial_reply->uid;
			VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0;

			/* Move the inquiry data to the response buffer. */
			scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data,
						 sizeof(VPDPage83Data));
		} else {
			/* It must be for VPD 0x80 */
			char sp[13];
			/* EVPD bit set */
			sp[0] = INQD_PDT_DA;
@@ -842,7 +1016,9 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
			sp[2] = 0;
			sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
				le32_to_cpu(get_serial_reply->uid));
		scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
			scsi_sg_copy_from_buffer(scsicmd, sp,
						 sizeof(sp));
		}
	}

	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
@@ -982,7 +1158,8 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
		memset(readcmd2, 0, sizeof(struct aac_raw_io2));
		readcmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff));
		readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
		readcmd2->byteCount = cpu_to_le32(count<<9);
		readcmd2->byteCount = cpu_to_le32(count *
			dev->fsa_dev[scmd_id(cmd)].block_size);
		readcmd2->cid = cpu_to_le16(scmd_id(cmd));
		readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ);
		ret = aac_build_sgraw2(cmd, readcmd2,
@@ -997,7 +1174,8 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
		readcmd = (struct aac_raw_io *) fib_data(fib);
		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->count = cpu_to_le32(count *
			dev->fsa_dev[scmd_id(cmd)].block_size);
		readcmd->cid = cpu_to_le16(scmd_id(cmd));
		readcmd->flags = cpu_to_le16(RIO_TYPE_READ);
		readcmd->bpTotal = 0;
@@ -1062,6 +1240,7 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
{
	u16 fibsize;
	struct aac_read *readcmd;
	struct aac_dev *dev = fib->dev;
	long ret;

	aac_fib_init(fib);
@@ -1069,7 +1248,8 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
	readcmd->command = cpu_to_le32(VM_CtBlockRead);
	readcmd->cid = cpu_to_le32(scmd_id(cmd));
	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
	readcmd->count = cpu_to_le32(count * 512);
	readcmd->count = cpu_to_le32(count *
		dev->fsa_dev[scmd_id(cmd)].block_size);

	ret = aac_build_sg(cmd, &readcmd->sg);
	if (ret < 0)
@@ -1104,7 +1284,8 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
		memset(writecmd2, 0, sizeof(struct aac_raw_io2));
		writecmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff));
		writecmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
		writecmd2->byteCount = cpu_to_le32(count<<9);
		writecmd2->byteCount = cpu_to_le32(count *
			dev->fsa_dev[scmd_id(cmd)].block_size);
		writecmd2->cid = cpu_to_le16(scmd_id(cmd));
		writecmd2->flags = (fua && ((aac_cache & 5) != 1) &&
						   (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
@@ -1122,7 +1303,8 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
		writecmd = (struct aac_raw_io *) fib_data(fib);
		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->count = cpu_to_le32(count *
			dev->fsa_dev[scmd_id(cmd)].block_size);
		writecmd->cid = cpu_to_le16(scmd_id(cmd));
		writecmd->flags = (fua && ((aac_cache & 5) != 1) &&
						   (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
@@ -1190,6 +1372,7 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
{
	u16 fibsize;
	struct aac_write *writecmd;
	struct aac_dev *dev = fib->dev;
	long ret;

	aac_fib_init(fib);
@@ -1197,7 +1380,8 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
	writecmd->command = cpu_to_le32(VM_CtBlockWrite);
	writecmd->cid = cpu_to_le32(scmd_id(cmd));
	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
	writecmd->count = cpu_to_le32(count * 512);
	writecmd->count = cpu_to_le32(count *
		dev->fsa_dev[scmd_id(cmd)].block_size);
	writecmd->sg.count = cpu_to_le32(1);
	/* ->stable is not used - it did mean which type of write */

@@ -2246,9 +2430,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
			  INQD_PDT_PROC : INQD_PDT_DA;
			if (scsicmd->cmnd[2] == 0) {
				/* supported vital product data pages */
				arr[3] = 2;
				arr[3] = 3;
				arr[4] = 0x0;
				arr[5] = 0x80;
				arr[6] = 0x83;
				arr[1] = scsicmd->cmnd[2];
				scsi_sg_copy_from_buffer(scsicmd, &inq_data,
							 sizeof(inq_data));
@@ -2264,7 +2449,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
				if (aac_wwn != 2)
					return aac_get_container_serial(
						scsicmd);
				/* SLES 10 SP1 special */
				scsicmd->result = DID_OK << 16 |
				  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
			} else if (scsicmd->cmnd[2] == 0x83) {
				/* vpd page 0x83 - Device Identification Page */
				char *sno = (char *)&inq_data;
				sno[3] = setinqserial(dev, &sno[4],
						      scmd_id(scsicmd));
				if (aac_wwn != 2)
					return aac_get_container_serial(
						scsicmd);
				scsicmd->result = DID_OK << 16 |
				  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
			} else {
@@ -2329,10 +2523,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
		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[8] = (fsa_dev_ptr[cid].block_size >> 24) & 0xff;
		cp[9] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff;
		cp[10] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff;
		cp[11] = (fsa_dev_ptr[cid].block_size) & 0xff;
		cp[12] = 0;

		alloc_len = ((scsicmd->cmnd[10] << 24)
@@ -2369,10 +2563,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
		cp[1] = (capacity >> 16) & 0xff;
		cp[2] = (capacity >> 8) & 0xff;
		cp[3] = (capacity >> 0) & 0xff;
		cp[4] = 0;
		cp[5] = 0;
		cp[6] = 2;
		cp[7] = 0;
		cp[4] = (fsa_dev_ptr[cid].block_size >> 24) & 0xff;
		cp[5] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff;
		cp[6] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff;
		cp[7] = (fsa_dev_ptr[cid].block_size) & 0xff;
		scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
		/* Do not cache partition table for arrays */
		scsicmd->device->removable = 1;
@@ -2385,30 +2579,79 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)

	case MODE_SENSE:
	{
		char mode_buf[7];
		int mode_buf_length = 4;
		u32 capacity;
		aac_modep_data mpd;

		if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
			capacity = fsa_dev_ptr[cid].size - 1;
		else
			capacity = (u32)-1;

		dprintk((KERN_DEBUG "MODE SENSE command.\n"));
		mode_buf[0] = 3;	/* Mode data length */
		mode_buf[1] = 0;	/* Medium type - default */
		mode_buf[2] = 0;	/* Device-specific param,
		memset((char *)&mpd, 0, sizeof(aac_modep_data));

		/* Mode data length */
		mpd.hd.data_length = sizeof(mpd.hd) - 1;
		/* Medium type - default */
		mpd.hd.med_type = 0;
		/* Device-specific param,
		   bit 8: 0/1 = write enabled/protected
		   bit 4: 0/1 = FUA enabled */
		mpd.hd.dev_par = 0;

		if (dev->raw_io_interface && ((aac_cache & 5) != 1))
			mode_buf[2] = 0x10;
		mode_buf[3] = 0;	/* Block descriptor length */
			mpd.hd.dev_par = 0x10;
		if (scsicmd->cmnd[1] & 0x8)
			mpd.hd.bd_length = 0;	/* Block descriptor length */
		else {
			mpd.hd.bd_length = sizeof(mpd.bd);
			mpd.hd.data_length += mpd.hd.bd_length;
			mpd.bd.block_length[0] =
				(fsa_dev_ptr[cid].block_size >> 16) & 0xff;
			mpd.bd.block_length[1] =
				(fsa_dev_ptr[cid].block_size >> 8) &  0xff;
			mpd.bd.block_length[2] =
				fsa_dev_ptr[cid].block_size  & 0xff;

			mpd.mpc_buf[0] = scsicmd->cmnd[2];
			if (scsicmd->cmnd[2] == 0x1C) {
				/* page length */
				mpd.mpc_buf[1] = 0xa;
				/* Mode data length */
				mpd.hd.data_length = 23;
			} else {
				/* Mode data length */
				mpd.hd.data_length = 15;
			}

			if (capacity > 0xffffff) {
				mpd.bd.block_count[0] = 0xff;
				mpd.bd.block_count[1] = 0xff;
				mpd.bd.block_count[2] = 0xff;
			} else {
				mpd.bd.block_count[0] = (capacity >> 16) & 0xff;
				mpd.bd.block_count[1] = (capacity >> 8) & 0xff;
				mpd.bd.block_count[2] = capacity  & 0xff;
			}
		}
		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
			mode_buf[0] = 6;
			mode_buf[4] = 8;
			mode_buf[5] = 1;
			mode_buf[6] = ((aac_cache & 6) == 2)
			mpd.hd.data_length += 3;
			mpd.mpc_buf[0] = 8;
			mpd.mpc_buf[1] = 1;
			mpd.mpc_buf[2] = ((aac_cache & 6) == 2)
				? 0 : 0x04; /* WCE */
			mode_buf_length = 7;
			mode_buf_length = sizeof(mpd);
		}

		if (mode_buf_length > scsicmd->cmnd[4])
			mode_buf_length = scsicmd->cmnd[4];
		}
		scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
		else
			mode_buf_length = sizeof(mpd);
		scsi_sg_copy_from_buffer(scsicmd,
					 (char *)&mpd,
					 mode_buf_length);
		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
		scsicmd->scsi_done(scsicmd);

@@ -2416,34 +2659,77 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
	}
	case MODE_SENSE_10:
	{
		char mode_buf[11];
		u32 capacity;
		int mode_buf_length = 8;
		aac_modep10_data mpd10;

		if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
			capacity = fsa_dev_ptr[cid].size - 1;
		else
			capacity = (u32)-1;

		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
		mode_buf[0] = 0;	/* Mode data length (MSB) */
		mode_buf[1] = 6;	/* Mode data length (LSB) */
		mode_buf[2] = 0;	/* Medium type - default */
		mode_buf[3] = 0;	/* Device-specific param,
		memset((char *)&mpd10, 0, sizeof(aac_modep10_data));
		/* Mode data length (MSB) */
		mpd10.hd.data_length[0] = 0;
		/* Mode data length (LSB) */
		mpd10.hd.data_length[1] = sizeof(mpd10.hd) - 1;
		/* Medium type - default */
		mpd10.hd.med_type = 0;
		/* Device-specific param,
		   bit 8: 0/1 = write enabled/protected
		   bit 4: 0/1 = FUA enabled */
		mpd10.hd.dev_par = 0;

		if (dev->raw_io_interface && ((aac_cache & 5) != 1))
			mode_buf[3] = 0x10;
		mode_buf[4] = 0;	/* reserved */
		mode_buf[5] = 0;	/* reserved */
		mode_buf[6] = 0;	/* Block descriptor length (MSB) */
		mode_buf[7] = 0;	/* Block descriptor length (LSB) */
			mpd10.hd.dev_par = 0x10;
		mpd10.hd.rsrvd[0] = 0;	/* reserved */
		mpd10.hd.rsrvd[1] = 0;	/* reserved */
		if (scsicmd->cmnd[1] & 0x8) {
			/* Block descriptor length (MSB) */
			mpd10.hd.bd_length[0] = 0;
			/* Block descriptor length (LSB) */
			mpd10.hd.bd_length[1] = 0;
		} else {
			mpd10.hd.bd_length[0] = 0;
			mpd10.hd.bd_length[1] = sizeof(mpd10.bd);

			mpd10.hd.data_length[1] += mpd10.hd.bd_length[1];

			mpd10.bd.block_length[0] =
				(fsa_dev_ptr[cid].block_size >> 16) & 0xff;
			mpd10.bd.block_length[1] =
				(fsa_dev_ptr[cid].block_size >> 8) & 0xff;
			mpd10.bd.block_length[2] =
				fsa_dev_ptr[cid].block_size  & 0xff;

			if (capacity > 0xffffff) {
				mpd10.bd.block_count[0] = 0xff;
				mpd10.bd.block_count[1] = 0xff;
				mpd10.bd.block_count[2] = 0xff;
			} else {
				mpd10.bd.block_count[0] =
					(capacity >> 16) & 0xff;
				mpd10.bd.block_count[1] =
					(capacity >> 8) & 0xff;
				mpd10.bd.block_count[2] =
					capacity  & 0xff;
			}
		}
		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
			mode_buf[1] = 9;
			mode_buf[8] = 8;
			mode_buf[9] = 1;
			mode_buf[10] = ((aac_cache & 6) == 2)
			mpd10.hd.data_length[1] += 3;
			mpd10.mpc_buf[0] = 8;
			mpd10.mpc_buf[1] = 1;
			mpd10.mpc_buf[2] = ((aac_cache & 6) == 2)
				? 0 : 0x04; /* WCE */
			mode_buf_length = 11;
			mode_buf_length = sizeof(mpd10);
			if (mode_buf_length > scsicmd->cmnd[8])
				mode_buf_length = scsicmd->cmnd[8];
		}
		scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
		scsi_sg_copy_from_buffer(scsicmd,
					 (char *)&mpd10,
					 mode_buf_length);

		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
		scsicmd->scsi_done(scsicmd);
Loading