107e38420SBart Van Assche /* 207e38420SBart Van Assche * SCSI functions used by both the initiator and the target code. 307e38420SBart Van Assche */ 407e38420SBart Van Assche 507e38420SBart Van Assche #include <linux/bug.h> 607e38420SBart Van Assche #include <linux/kernel.h> 707e38420SBart Van Assche #include <linux/string.h> 87708c165SSagi Grimberg #include <asm/unaligned.h> 907e38420SBart Van Assche #include <scsi/scsi_common.h> 1007e38420SBart Van Assche 1107e38420SBart Van Assche /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. 1207e38420SBart Van Assche * You may not alter any existing entry (although adding new ones is 1307e38420SBart Van Assche * encouraged once assigned by ANSI/INCITS T10 1407e38420SBart Van Assche */ 1507e38420SBart Van Assche static const char *const scsi_device_types[] = { 1607e38420SBart Van Assche "Direct-Access ", 1707e38420SBart Van Assche "Sequential-Access", 1807e38420SBart Van Assche "Printer ", 1907e38420SBart Van Assche "Processor ", 2007e38420SBart Van Assche "WORM ", 2107e38420SBart Van Assche "CD-ROM ", 2207e38420SBart Van Assche "Scanner ", 2307e38420SBart Van Assche "Optical Device ", 2407e38420SBart Van Assche "Medium Changer ", 2507e38420SBart Van Assche "Communications ", 2607e38420SBart Van Assche "ASC IT8 ", 2707e38420SBart Van Assche "ASC IT8 ", 2807e38420SBart Van Assche "RAID ", 2907e38420SBart Van Assche "Enclosure ", 3007e38420SBart Van Assche "Direct-Access-RBC", 3107e38420SBart Van Assche "Optical card ", 3207e38420SBart Van Assche "Bridge controller", 3307e38420SBart Van Assche "Object storage ", 3407e38420SBart Van Assche "Automation/Drive ", 3507e38420SBart Van Assche "Security Manager ", 3607e38420SBart Van Assche "Direct-Access-ZBC", 3707e38420SBart Van Assche }; 3807e38420SBart Van Assche 3907e38420SBart Van Assche /** 4007e38420SBart Van Assche * scsi_device_type - Return 17 char string indicating device type. 4107e38420SBart Van Assche * @type: type number to look up 4207e38420SBart Van Assche */ 4307e38420SBart Van Assche const char *scsi_device_type(unsigned type) 4407e38420SBart Van Assche { 4507e38420SBart Van Assche if (type == 0x1e) 4607e38420SBart Van Assche return "Well-known LUN "; 4707e38420SBart Van Assche if (type == 0x1f) 4807e38420SBart Van Assche return "No Device "; 4907e38420SBart Van Assche if (type >= ARRAY_SIZE(scsi_device_types)) 5007e38420SBart Van Assche return "Unknown "; 5107e38420SBart Van Assche return scsi_device_types[type]; 5207e38420SBart Van Assche } 5307e38420SBart Van Assche EXPORT_SYMBOL(scsi_device_type); 5407e38420SBart Van Assche 5507e38420SBart Van Assche /** 5607e38420SBart Van Assche * scsilun_to_int - convert a scsi_lun to an int 5707e38420SBart Van Assche * @scsilun: struct scsi_lun to be converted. 5807e38420SBart Van Assche * 5907e38420SBart Van Assche * Description: 6007e38420SBart Van Assche * Convert @scsilun from a struct scsi_lun to a four byte host byte-ordered 6107e38420SBart Van Assche * integer, and return the result. The caller must check for 6207e38420SBart Van Assche * truncation before using this function. 6307e38420SBart Van Assche * 6407e38420SBart Van Assche * Notes: 6507e38420SBart Van Assche * For a description of the LUN format, post SCSI-3 see the SCSI 6607e38420SBart Van Assche * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 6707e38420SBart Van Assche * 6807e38420SBart Van Assche * Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function 6907e38420SBart Van Assche * returns the integer: 0x0b03d204 7007e38420SBart Van Assche * 7107e38420SBart Van Assche * This encoding will return a standard integer LUN for LUNs smaller 7207e38420SBart Van Assche * than 256, which typically use a single level LUN structure with 7307e38420SBart Van Assche * addressing method 0. 7407e38420SBart Van Assche */ 7507e38420SBart Van Assche u64 scsilun_to_int(struct scsi_lun *scsilun) 7607e38420SBart Van Assche { 7707e38420SBart Van Assche int i; 7807e38420SBart Van Assche u64 lun; 7907e38420SBart Van Assche 8007e38420SBart Van Assche lun = 0; 8107e38420SBart Van Assche for (i = 0; i < sizeof(lun); i += 2) 8207e38420SBart Van Assche lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) | 8307e38420SBart Van Assche ((u64)scsilun->scsi_lun[i + 1] << (i * 8))); 8407e38420SBart Van Assche return lun; 8507e38420SBart Van Assche } 8607e38420SBart Van Assche EXPORT_SYMBOL(scsilun_to_int); 8707e38420SBart Van Assche 8807e38420SBart Van Assche /** 8907e38420SBart Van Assche * int_to_scsilun - reverts an int into a scsi_lun 9007e38420SBart Van Assche * @lun: integer to be reverted 9107e38420SBart Van Assche * @scsilun: struct scsi_lun to be set. 9207e38420SBart Van Assche * 9307e38420SBart Van Assche * Description: 9407e38420SBart Van Assche * Reverts the functionality of the scsilun_to_int, which packed 9507e38420SBart Van Assche * an 8-byte lun value into an int. This routine unpacks the int 9607e38420SBart Van Assche * back into the lun value. 9707e38420SBart Van Assche * 9807e38420SBart Van Assche * Notes: 9907e38420SBart Van Assche * Given an integer : 0x0b03d204, this function returns a 10007e38420SBart Van Assche * struct scsi_lun of: d2 04 0b 03 00 00 00 00 10107e38420SBart Van Assche * 10207e38420SBart Van Assche */ 10307e38420SBart Van Assche void int_to_scsilun(u64 lun, struct scsi_lun *scsilun) 10407e38420SBart Van Assche { 10507e38420SBart Van Assche int i; 10607e38420SBart Van Assche 10707e38420SBart Van Assche memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 10807e38420SBart Van Assche 10907e38420SBart Van Assche for (i = 0; i < sizeof(lun); i += 2) { 11007e38420SBart Van Assche scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 11107e38420SBart Van Assche scsilun->scsi_lun[i+1] = lun & 0xFF; 11207e38420SBart Van Assche lun = lun >> 16; 11307e38420SBart Van Assche } 11407e38420SBart Van Assche } 11507e38420SBart Van Assche EXPORT_SYMBOL(int_to_scsilun); 11607e38420SBart Van Assche 11707e38420SBart Van Assche /** 11807e38420SBart Van Assche * scsi_normalize_sense - normalize main elements from either fixed or 11907e38420SBart Van Assche * descriptor sense data format into a common format. 12007e38420SBart Van Assche * 12107e38420SBart Van Assche * @sense_buffer: byte array containing sense data returned by device 12207e38420SBart Van Assche * @sb_len: number of valid bytes in sense_buffer 12307e38420SBart Van Assche * @sshdr: pointer to instance of structure that common 12407e38420SBart Van Assche * elements are written to. 12507e38420SBart Van Assche * 12607e38420SBart Van Assche * Notes: 12707e38420SBart Van Assche * The "main elements" from sense data are: response_code, sense_key, 12807e38420SBart Van Assche * asc, ascq and additional_length (only for descriptor format). 12907e38420SBart Van Assche * 13007e38420SBart Van Assche * Typically this function can be called after a device has 13107e38420SBart Van Assche * responded to a SCSI command with the CHECK_CONDITION status. 13207e38420SBart Van Assche * 13307e38420SBart Van Assche * Return value: 13407e38420SBart Van Assche * true if valid sense data information found, else false; 13507e38420SBart Van Assche */ 13607e38420SBart Van Assche bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, 13707e38420SBart Van Assche struct scsi_sense_hdr *sshdr) 13807e38420SBart Van Assche { 13907e38420SBart Van Assche if (!sense_buffer || !sb_len) 14007e38420SBart Van Assche return false; 14107e38420SBart Van Assche 14207e38420SBart Van Assche memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); 14307e38420SBart Van Assche 14407e38420SBart Van Assche sshdr->response_code = (sense_buffer[0] & 0x7f); 14507e38420SBart Van Assche 14607e38420SBart Van Assche if (!scsi_sense_valid(sshdr)) 14707e38420SBart Van Assche return false; 14807e38420SBart Van Assche 14907e38420SBart Van Assche if (sshdr->response_code >= 0x72) { 15007e38420SBart Van Assche /* 15107e38420SBart Van Assche * descriptor format 15207e38420SBart Van Assche */ 15307e38420SBart Van Assche if (sb_len > 1) 15407e38420SBart Van Assche sshdr->sense_key = (sense_buffer[1] & 0xf); 15507e38420SBart Van Assche if (sb_len > 2) 15607e38420SBart Van Assche sshdr->asc = sense_buffer[2]; 15707e38420SBart Van Assche if (sb_len > 3) 15807e38420SBart Van Assche sshdr->ascq = sense_buffer[3]; 15907e38420SBart Van Assche if (sb_len > 7) 16007e38420SBart Van Assche sshdr->additional_length = sense_buffer[7]; 16107e38420SBart Van Assche } else { 16207e38420SBart Van Assche /* 16307e38420SBart Van Assche * fixed format 16407e38420SBart Van Assche */ 16507e38420SBart Van Assche if (sb_len > 2) 16607e38420SBart Van Assche sshdr->sense_key = (sense_buffer[2] & 0xf); 16707e38420SBart Van Assche if (sb_len > 7) { 16807e38420SBart Van Assche sb_len = (sb_len < (sense_buffer[7] + 8)) ? 16907e38420SBart Van Assche sb_len : (sense_buffer[7] + 8); 17007e38420SBart Van Assche if (sb_len > 12) 17107e38420SBart Van Assche sshdr->asc = sense_buffer[12]; 17207e38420SBart Van Assche if (sb_len > 13) 17307e38420SBart Van Assche sshdr->ascq = sense_buffer[13]; 17407e38420SBart Van Assche } 17507e38420SBart Van Assche } 17607e38420SBart Van Assche 17707e38420SBart Van Assche return true; 17807e38420SBart Van Assche } 17907e38420SBart Van Assche EXPORT_SYMBOL(scsi_normalize_sense); 1807708c165SSagi Grimberg 1817708c165SSagi Grimberg /** 1827708c165SSagi Grimberg * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. 1837708c165SSagi Grimberg * @sense_buffer: byte array of descriptor format sense data 1847708c165SSagi Grimberg * @sb_len: number of valid bytes in sense_buffer 1857708c165SSagi Grimberg * @desc_type: value of descriptor type to find 1867708c165SSagi Grimberg * (e.g. 0 -> information) 1877708c165SSagi Grimberg * 1887708c165SSagi Grimberg * Notes: 1897708c165SSagi Grimberg * only valid when sense data is in descriptor format 1907708c165SSagi Grimberg * 1917708c165SSagi Grimberg * Return value: 1927708c165SSagi Grimberg * pointer to start of (first) descriptor if found else NULL 1937708c165SSagi Grimberg */ 1947708c165SSagi Grimberg const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, 1957708c165SSagi Grimberg int desc_type) 1967708c165SSagi Grimberg { 1977708c165SSagi Grimberg int add_sen_len, add_len, desc_len, k; 1987708c165SSagi Grimberg const u8 * descp; 1997708c165SSagi Grimberg 2007708c165SSagi Grimberg if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) 2017708c165SSagi Grimberg return NULL; 2027708c165SSagi Grimberg if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) 2037708c165SSagi Grimberg return NULL; 2047708c165SSagi Grimberg add_sen_len = (add_sen_len < (sb_len - 8)) ? 2057708c165SSagi Grimberg add_sen_len : (sb_len - 8); 2067708c165SSagi Grimberg descp = &sense_buffer[8]; 2077708c165SSagi Grimberg for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { 2087708c165SSagi Grimberg descp += desc_len; 2097708c165SSagi Grimberg add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; 2107708c165SSagi Grimberg desc_len = add_len + 2; 2117708c165SSagi Grimberg if (descp[0] == desc_type) 2127708c165SSagi Grimberg return descp; 2137708c165SSagi Grimberg if (add_len < 0) // short descriptor ?? 2147708c165SSagi Grimberg break; 2157708c165SSagi Grimberg } 2167708c165SSagi Grimberg return NULL; 2177708c165SSagi Grimberg } 2187708c165SSagi Grimberg EXPORT_SYMBOL(scsi_sense_desc_find); 2197708c165SSagi Grimberg 2207708c165SSagi Grimberg /** 2217708c165SSagi Grimberg * scsi_build_sense_buffer - build sense data in a buffer 2227708c165SSagi Grimberg * @desc: Sense format (non zero == descriptor format, 2237708c165SSagi Grimberg * 0 == fixed format) 2247708c165SSagi Grimberg * @buf: Where to build sense data 2257708c165SSagi Grimberg * @key: Sense key 2267708c165SSagi Grimberg * @asc: Additional sense code 2277708c165SSagi Grimberg * @ascq: Additional sense code qualifier 2287708c165SSagi Grimberg * 2297708c165SSagi Grimberg **/ 2307708c165SSagi Grimberg void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) 2317708c165SSagi Grimberg { 2327708c165SSagi Grimberg if (desc) { 2337708c165SSagi Grimberg buf[0] = 0x72; /* descriptor, current */ 2347708c165SSagi Grimberg buf[1] = key; 2357708c165SSagi Grimberg buf[2] = asc; 2367708c165SSagi Grimberg buf[3] = ascq; 2377708c165SSagi Grimberg buf[7] = 0; 2387708c165SSagi Grimberg } else { 2397708c165SSagi Grimberg buf[0] = 0x70; /* fixed, current */ 2407708c165SSagi Grimberg buf[2] = key; 2417708c165SSagi Grimberg buf[7] = 0xa; 2427708c165SSagi Grimberg buf[12] = asc; 2437708c165SSagi Grimberg buf[13] = ascq; 2447708c165SSagi Grimberg } 2457708c165SSagi Grimberg } 2467708c165SSagi Grimberg EXPORT_SYMBOL(scsi_build_sense_buffer); 2477708c165SSagi Grimberg 2487708c165SSagi Grimberg /** 2497708c165SSagi Grimberg * scsi_set_sense_information - set the information field in a 2507708c165SSagi Grimberg * formatted sense data buffer 2517708c165SSagi Grimberg * @buf: Where to build sense data 2527708c165SSagi Grimberg * @info: 64-bit information value to be set 2537708c165SSagi Grimberg * 2547708c165SSagi Grimberg **/ 2557708c165SSagi Grimberg void scsi_set_sense_information(u8 *buf, u64 info) 2567708c165SSagi Grimberg { 2577708c165SSagi Grimberg if ((buf[0] & 0x7f) == 0x72) { 2587708c165SSagi Grimberg u8 *ucp, len; 2597708c165SSagi Grimberg 2607708c165SSagi Grimberg len = buf[7]; 2617708c165SSagi Grimberg ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); 2627708c165SSagi Grimberg if (!ucp) { 26312306b42SSagi Grimberg buf[7] = len + 0xc; 2647708c165SSagi Grimberg ucp = buf + 8 + len; 2657708c165SSagi Grimberg } 2667708c165SSagi Grimberg ucp[0] = 0; 2677708c165SSagi Grimberg ucp[1] = 0xa; 2687708c165SSagi Grimberg ucp[2] = 0x80; /* Valid bit */ 2697708c165SSagi Grimberg ucp[3] = 0; 2707708c165SSagi Grimberg put_unaligned_be64(info, &ucp[4]); 2717708c165SSagi Grimberg } else if ((buf[0] & 0x7f) == 0x70) { 2727708c165SSagi Grimberg buf[0] |= 0x80; 2737708c165SSagi Grimberg put_unaligned_be64(info, &buf[3]); 2747708c165SSagi Grimberg } 2757708c165SSagi Grimberg } 2767708c165SSagi Grimberg EXPORT_SYMBOL(scsi_set_sense_information); 277