aboutsummaryrefslogtreecommitdiffstats
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.c140
1 files changed, 139 insertions, 1 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 0b6fd0b654d2..a26baab09dbf 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -751,6 +751,101 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex)
751 inqstrcpy ("V1.0", str->prl); 751 inqstrcpy ("V1.0", str->prl);
752} 752}
753 753
754static void get_container_serial_callback(void *context, struct fib * fibptr)
755{
756 struct aac_get_serial_resp * get_serial_reply;
757 struct scsi_cmnd * scsicmd;
758
759 BUG_ON(fibptr == NULL);
760
761 scsicmd = (struct scsi_cmnd *) context;
762 if (!aac_valid_context(scsicmd, fibptr))
763 return;
764
765 get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr);
766 /* Failure is irrelevant, using default value instead */
767 if (le32_to_cpu(get_serial_reply->status) == CT_OK) {
768 char sp[13];
769 /* EVPD bit set */
770 sp[0] = INQD_PDT_DA;
771 sp[1] = scsicmd->cmnd[2];
772 sp[2] = 0;
773 sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
774 le32_to_cpu(get_serial_reply->uid));
775 aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
776 }
777
778 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
779
780 aac_fib_complete(fibptr);
781 aac_fib_free(fibptr);
782 scsicmd->scsi_done(scsicmd);
783}
784
785/**
786 * aac_get_container_serial - get container serial, none blocking.
787 */
788static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
789{
790 int status;
791 struct aac_get_serial *dinfo;
792 struct fib * cmd_fibcontext;
793 struct aac_dev * dev;
794
795 dev = (struct aac_dev *)scsicmd->device->host->hostdata;
796
797 if (!(cmd_fibcontext = aac_fib_alloc(dev)))
798 return -ENOMEM;
799
800 aac_fib_init(cmd_fibcontext);
801 dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext);
802
803 dinfo->command = cpu_to_le32(VM_ContainerConfig);
804 dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
805 dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
806
807 status = aac_fib_send(ContainerCommand,
808 cmd_fibcontext,
809 sizeof (struct aac_get_serial),
810 FsaNormal,
811 0, 1,
812 (fib_callback) get_container_serial_callback,
813 (void *) scsicmd);
814
815 /*
816 * Check that the command queued to the controller
817 */
818 if (status == -EINPROGRESS) {
819 scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
820 return 0;
821 }
822
823 printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
824 aac_fib_complete(cmd_fibcontext);
825 aac_fib_free(cmd_fibcontext);
826 return -1;
827}
828
829/* Function: setinqserial
830 *
831 * Arguments: [1] pointer to void [1] int
832 *
833 * Purpose: Sets SCSI Unit Serial number.
834 * This is a fake. We should read a proper
835 * serial number from the container. <SuSE>But
836 * without docs it's quite hard to do it :-)
837 * So this will have to do in the meantime.</SuSE>
838 */
839
840static int setinqserial(struct aac_dev *dev, void *data, int cid)
841{
842 /*
843 * This breaks array migration.
844 */
845 return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X",
846 le32_to_cpu(dev->adapter_info.serial[0]), cid);
847}
848
754static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, 849static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
755 u8 a_sense_code, u8 incorrect_length, 850 u8 a_sense_code, u8 incorrect_length,
756 u8 bit_pointer, u16 field_pointer, 851 u8 bit_pointer, u16 field_pointer,
@@ -1798,6 +1893,49 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
1798 dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); 1893 dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
1799 memset(&inq_data, 0, sizeof (struct inquiry_data)); 1894 memset(&inq_data, 0, sizeof (struct inquiry_data));
1800 1895
1896 if (scsicmd->cmnd[1] & 0x1 ) {
1897 char *arr = (char *)&inq_data;
1898
1899 /* EVPD bit set */
1900 arr[0] = (scmd_id(scsicmd) == host->this_id) ?
1901 INQD_PDT_PROC : INQD_PDT_DA;
1902 if (scsicmd->cmnd[2] == 0) {
1903 /* supported vital product data pages */
1904 arr[3] = 2;
1905 arr[4] = 0x0;
1906 arr[5] = 0x80;
1907 arr[1] = scsicmd->cmnd[2];
1908 aac_internal_transfer(scsicmd, &inq_data, 0,
1909 sizeof(inq_data));
1910 scsicmd->result = DID_OK << 16 |
1911 COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1912 } else if (scsicmd->cmnd[2] == 0x80) {
1913 /* unit serial number page */
1914 arr[3] = setinqserial(dev, &arr[4],
1915 scmd_id(scsicmd));
1916 arr[1] = scsicmd->cmnd[2];
1917 aac_internal_transfer(scsicmd, &inq_data, 0,
1918 sizeof(inq_data));
1919 return aac_get_container_serial(scsicmd);
1920 } else {
1921 /* vpd page not implemented */
1922 scsicmd->result = DID_OK << 16 |
1923 COMMAND_COMPLETE << 8 |
1924 SAM_STAT_CHECK_CONDITION;
1925 set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
1926 ILLEGAL_REQUEST,
1927 SENCODE_INVALID_CDB_FIELD,
1928 ASENCODE_NO_SENSE, 0, 7, 2, 0);
1929 memcpy(scsicmd->sense_buffer,
1930 &dev->fsa_dev[cid].sense_data,
1931 (sizeof(dev->fsa_dev[cid].sense_data) >
1932 sizeof(scsicmd->sense_buffer))
1933 ? sizeof(scsicmd->sense_buffer)
1934 : sizeof(dev->fsa_dev[cid].sense_data));
1935 }
1936 scsicmd->scsi_done(scsicmd);
1937 return 0;
1938 }
1801 inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ 1939 inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
1802 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 */ 1940 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 */
1803 inq_data.inqd_len = 31; 1941 inq_data.inqd_len = 31;
@@ -2070,7 +2208,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
2070 } 2208 }
2071 else return -EINVAL; 2209 else return -EINVAL;
2072 2210
2073 qd.valid = fsa_dev_ptr[qd.cnum].valid; 2211 qd.valid = fsa_dev_ptr[qd.cnum].valid != 0;
2074 qd.locked = fsa_dev_ptr[qd.cnum].locked; 2212 qd.locked = fsa_dev_ptr[qd.cnum].locked;
2075 qd.deleted = fsa_dev_ptr[qd.cnum].deleted; 2213 qd.deleted = fsa_dev_ptr[qd.cnum].deleted;
2076 2214