Commit 5d910649 authored by Mahesh Rajashekhara's avatar Mahesh Rajashekhara Committed by James Bottomley
Browse files

aacraid: vpd page code 0x83 support

parent 495c0217
Loading
Loading
Loading
Loading
+153 −12
Original line number Diff line number Diff line
@@ -163,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
 */
@@ -890,6 +932,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;
@@ -897,7 +1011,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;
@@ -2309,9 +2425,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));
@@ -2327,7 +2444,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 {
@@ -2482,6 +2608,18 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
				(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;
@@ -2500,9 +2638,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
			mpd.mpc_buf[2] = ((aac_cache & 6) == 2)
				? 0 : 0x04; /* WCE */
			mode_buf_length = sizeof(mpd);
		}

		if (mode_buf_length > scsicmd->cmnd[4])
			mode_buf_length = scsicmd->cmnd[4];
		}
		else
			mode_buf_length = sizeof(mpd);
		scsi_sg_copy_from_buffer(scsicmd,
					 (char *)&mpd,
					 mode_buf_length);