1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 207e38420SBart Van Assche /* 307e38420SBart Van Assche * SCSI functions used by both the initiator and the target code. 407e38420SBart Van Assche */ 507e38420SBart Van Assche 607e38420SBart Van Assche #include <linux/bug.h> 707e38420SBart Van Assche #include <linux/kernel.h> 807e38420SBart Van Assche #include <linux/string.h> 9f5a8b3a7SSagi Grimberg #include <linux/errno.h> 107708c165SSagi Grimberg #include <asm/unaligned.h> 1107e38420SBart Van Assche #include <scsi/scsi_common.h> 1207e38420SBart Van Assche 13*b69367dfSChristoph Hellwig /* Command group 3 is reserved and should never be used. */ 14*b69367dfSChristoph Hellwig const unsigned char scsi_command_size_tbl[8] = { 15*b69367dfSChristoph Hellwig 6, 10, 10, 12, 16, 12, 10, 10 16*b69367dfSChristoph Hellwig }; 17*b69367dfSChristoph Hellwig EXPORT_SYMBOL(scsi_command_size_tbl); 18*b69367dfSChristoph Hellwig 1907e38420SBart Van Assche /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. 2007e38420SBart Van Assche * You may not alter any existing entry (although adding new ones is 21749a1122SRandy Dunlap * encouraged once assigned by ANSI/INCITS T10). 2207e38420SBart Van Assche */ 2307e38420SBart Van Assche static const char *const scsi_device_types[] = { 2407e38420SBart Van Assche "Direct-Access ", 2507e38420SBart Van Assche "Sequential-Access", 2607e38420SBart Van Assche "Printer ", 2707e38420SBart Van Assche "Processor ", 2807e38420SBart Van Assche "WORM ", 2907e38420SBart Van Assche "CD-ROM ", 3007e38420SBart Van Assche "Scanner ", 3107e38420SBart Van Assche "Optical Device ", 3207e38420SBart Van Assche "Medium Changer ", 3307e38420SBart Van Assche "Communications ", 3407e38420SBart Van Assche "ASC IT8 ", 3507e38420SBart Van Assche "ASC IT8 ", 3607e38420SBart Van Assche "RAID ", 3707e38420SBart Van Assche "Enclosure ", 3807e38420SBart Van Assche "Direct-Access-RBC", 3907e38420SBart Van Assche "Optical card ", 4007e38420SBart Van Assche "Bridge controller", 4107e38420SBart Van Assche "Object storage ", 4207e38420SBart Van Assche "Automation/Drive ", 4307e38420SBart Van Assche "Security Manager ", 4407e38420SBart Van Assche "Direct-Access-ZBC", 4507e38420SBart Van Assche }; 4607e38420SBart Van Assche 4707e38420SBart Van Assche /** 48749a1122SRandy Dunlap * scsi_device_type - Return 17-char string indicating device type. 4907e38420SBart Van Assche * @type: type number to look up 5007e38420SBart Van Assche */ 5107e38420SBart Van Assche const char *scsi_device_type(unsigned type) 5207e38420SBart Van Assche { 5307e38420SBart Van Assche if (type == 0x1e) 5407e38420SBart Van Assche return "Well-known LUN "; 5507e38420SBart Van Assche if (type == 0x1f) 5607e38420SBart Van Assche return "No Device "; 5707e38420SBart Van Assche if (type >= ARRAY_SIZE(scsi_device_types)) 5807e38420SBart Van Assche return "Unknown "; 5907e38420SBart Van Assche return scsi_device_types[type]; 6007e38420SBart Van Assche } 6107e38420SBart Van Assche EXPORT_SYMBOL(scsi_device_type); 6207e38420SBart Van Assche 6307e38420SBart Van Assche /** 6407e38420SBart Van Assche * scsilun_to_int - convert a scsi_lun to an int 6507e38420SBart Van Assche * @scsilun: struct scsi_lun to be converted. 6607e38420SBart Van Assche * 6707e38420SBart Van Assche * Description: 68749a1122SRandy Dunlap * Convert @scsilun from a struct scsi_lun to a four-byte host byte-ordered 6907e38420SBart Van Assche * integer, and return the result. The caller must check for 7007e38420SBart Van Assche * truncation before using this function. 7107e38420SBart Van Assche * 7207e38420SBart Van Assche * Notes: 7307e38420SBart Van Assche * For a description of the LUN format, post SCSI-3 see the SCSI 7407e38420SBart Van Assche * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 7507e38420SBart Van Assche * 7607e38420SBart Van Assche * Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function 7707e38420SBart Van Assche * returns the integer: 0x0b03d204 7807e38420SBart Van Assche * 7907e38420SBart Van Assche * This encoding will return a standard integer LUN for LUNs smaller 8007e38420SBart Van Assche * than 256, which typically use a single level LUN structure with 8107e38420SBart Van Assche * addressing method 0. 8207e38420SBart Van Assche */ 8307e38420SBart Van Assche u64 scsilun_to_int(struct scsi_lun *scsilun) 8407e38420SBart Van Assche { 8507e38420SBart Van Assche int i; 8607e38420SBart Van Assche u64 lun; 8707e38420SBart Van Assche 8807e38420SBart Van Assche lun = 0; 8907e38420SBart Van Assche for (i = 0; i < sizeof(lun); i += 2) 9007e38420SBart Van Assche lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) | 9107e38420SBart Van Assche ((u64)scsilun->scsi_lun[i + 1] << (i * 8))); 9207e38420SBart Van Assche return lun; 9307e38420SBart Van Assche } 9407e38420SBart Van Assche EXPORT_SYMBOL(scsilun_to_int); 9507e38420SBart Van Assche 9607e38420SBart Van Assche /** 9707e38420SBart Van Assche * int_to_scsilun - reverts an int into a scsi_lun 9807e38420SBart Van Assche * @lun: integer to be reverted 9907e38420SBart Van Assche * @scsilun: struct scsi_lun to be set. 10007e38420SBart Van Assche * 10107e38420SBart Van Assche * Description: 10207e38420SBart Van Assche * Reverts the functionality of the scsilun_to_int, which packed 10307e38420SBart Van Assche * an 8-byte lun value into an int. This routine unpacks the int 10407e38420SBart Van Assche * back into the lun value. 10507e38420SBart Van Assche * 10607e38420SBart Van Assche * Notes: 10707e38420SBart Van Assche * Given an integer : 0x0b03d204, this function returns a 10807e38420SBart Van Assche * struct scsi_lun of: d2 04 0b 03 00 00 00 00 10907e38420SBart Van Assche * 11007e38420SBart Van Assche */ 11107e38420SBart Van Assche void int_to_scsilun(u64 lun, struct scsi_lun *scsilun) 11207e38420SBart Van Assche { 11307e38420SBart Van Assche int i; 11407e38420SBart Van Assche 11507e38420SBart Van Assche memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 11607e38420SBart Van Assche 11707e38420SBart Van Assche for (i = 0; i < sizeof(lun); i += 2) { 11807e38420SBart Van Assche scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 11907e38420SBart Van Assche scsilun->scsi_lun[i+1] = lun & 0xFF; 12007e38420SBart Van Assche lun = lun >> 16; 12107e38420SBart Van Assche } 12207e38420SBart Van Assche } 12307e38420SBart Van Assche EXPORT_SYMBOL(int_to_scsilun); 12407e38420SBart Van Assche 12507e38420SBart Van Assche /** 12607e38420SBart Van Assche * scsi_normalize_sense - normalize main elements from either fixed or 12707e38420SBart Van Assche * descriptor sense data format into a common format. 12807e38420SBart Van Assche * 12907e38420SBart Van Assche * @sense_buffer: byte array containing sense data returned by device 13007e38420SBart Van Assche * @sb_len: number of valid bytes in sense_buffer 13107e38420SBart Van Assche * @sshdr: pointer to instance of structure that common 13207e38420SBart Van Assche * elements are written to. 13307e38420SBart Van Assche * 13407e38420SBart Van Assche * Notes: 13507e38420SBart Van Assche * The "main elements" from sense data are: response_code, sense_key, 13607e38420SBart Van Assche * asc, ascq and additional_length (only for descriptor format). 13707e38420SBart Van Assche * 13807e38420SBart Van Assche * Typically this function can be called after a device has 13907e38420SBart Van Assche * responded to a SCSI command with the CHECK_CONDITION status. 14007e38420SBart Van Assche * 14107e38420SBart Van Assche * Return value: 14207e38420SBart Van Assche * true if valid sense data information found, else false; 14307e38420SBart Van Assche */ 14407e38420SBart Van Assche bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, 14507e38420SBart Van Assche struct scsi_sense_hdr *sshdr) 14607e38420SBart Van Assche { 147148cff67SChristoph Hellwig memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); 148148cff67SChristoph Hellwig 14907e38420SBart Van Assche if (!sense_buffer || !sb_len) 15007e38420SBart Van Assche return false; 15107e38420SBart Van Assche 15207e38420SBart Van Assche sshdr->response_code = (sense_buffer[0] & 0x7f); 15307e38420SBart Van Assche 15407e38420SBart Van Assche if (!scsi_sense_valid(sshdr)) 15507e38420SBart Van Assche return false; 15607e38420SBart Van Assche 15707e38420SBart Van Assche if (sshdr->response_code >= 0x72) { 15807e38420SBart Van Assche /* 15907e38420SBart Van Assche * descriptor format 16007e38420SBart Van Assche */ 16107e38420SBart Van Assche if (sb_len > 1) 16207e38420SBart Van Assche sshdr->sense_key = (sense_buffer[1] & 0xf); 16307e38420SBart Van Assche if (sb_len > 2) 16407e38420SBart Van Assche sshdr->asc = sense_buffer[2]; 16507e38420SBart Van Assche if (sb_len > 3) 16607e38420SBart Van Assche sshdr->ascq = sense_buffer[3]; 16707e38420SBart Van Assche if (sb_len > 7) 16807e38420SBart Van Assche sshdr->additional_length = sense_buffer[7]; 16907e38420SBart Van Assche } else { 17007e38420SBart Van Assche /* 17107e38420SBart Van Assche * fixed format 17207e38420SBart Van Assche */ 17307e38420SBart Van Assche if (sb_len > 2) 17407e38420SBart Van Assche sshdr->sense_key = (sense_buffer[2] & 0xf); 17507e38420SBart Van Assche if (sb_len > 7) { 17607e38420SBart Van Assche sb_len = (sb_len < (sense_buffer[7] + 8)) ? 17707e38420SBart Van Assche sb_len : (sense_buffer[7] + 8); 17807e38420SBart Van Assche if (sb_len > 12) 17907e38420SBart Van Assche sshdr->asc = sense_buffer[12]; 18007e38420SBart Van Assche if (sb_len > 13) 18107e38420SBart Van Assche sshdr->ascq = sense_buffer[13]; 18207e38420SBart Van Assche } 18307e38420SBart Van Assche } 18407e38420SBart Van Assche 18507e38420SBart Van Assche return true; 18607e38420SBart Van Assche } 18707e38420SBart Van Assche EXPORT_SYMBOL(scsi_normalize_sense); 1887708c165SSagi Grimberg 1897708c165SSagi Grimberg /** 1907708c165SSagi Grimberg * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. 1917708c165SSagi Grimberg * @sense_buffer: byte array of descriptor format sense data 1927708c165SSagi Grimberg * @sb_len: number of valid bytes in sense_buffer 1937708c165SSagi Grimberg * @desc_type: value of descriptor type to find 1947708c165SSagi Grimberg * (e.g. 0 -> information) 1957708c165SSagi Grimberg * 1967708c165SSagi Grimberg * Notes: 1977708c165SSagi Grimberg * only valid when sense data is in descriptor format 1987708c165SSagi Grimberg * 1997708c165SSagi Grimberg * Return value: 2007708c165SSagi Grimberg * pointer to start of (first) descriptor if found else NULL 2017708c165SSagi Grimberg */ 2027708c165SSagi Grimberg const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, 2037708c165SSagi Grimberg int desc_type) 2047708c165SSagi Grimberg { 2057708c165SSagi Grimberg int add_sen_len, add_len, desc_len, k; 2067708c165SSagi Grimberg const u8 * descp; 2077708c165SSagi Grimberg 2087708c165SSagi Grimberg if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) 2097708c165SSagi Grimberg return NULL; 2107708c165SSagi Grimberg if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) 2117708c165SSagi Grimberg return NULL; 2127708c165SSagi Grimberg add_sen_len = (add_sen_len < (sb_len - 8)) ? 2137708c165SSagi Grimberg add_sen_len : (sb_len - 8); 2147708c165SSagi Grimberg descp = &sense_buffer[8]; 2157708c165SSagi Grimberg for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { 2167708c165SSagi Grimberg descp += desc_len; 2177708c165SSagi Grimberg add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; 2187708c165SSagi Grimberg desc_len = add_len + 2; 2197708c165SSagi Grimberg if (descp[0] == desc_type) 2207708c165SSagi Grimberg return descp; 2217708c165SSagi Grimberg if (add_len < 0) // short descriptor ?? 2227708c165SSagi Grimberg break; 2237708c165SSagi Grimberg } 2247708c165SSagi Grimberg return NULL; 2257708c165SSagi Grimberg } 2267708c165SSagi Grimberg EXPORT_SYMBOL(scsi_sense_desc_find); 2277708c165SSagi Grimberg 2287708c165SSagi Grimberg /** 2297708c165SSagi Grimberg * scsi_build_sense_buffer - build sense data in a buffer 230749a1122SRandy Dunlap * @desc: Sense format (non-zero == descriptor format, 2317708c165SSagi Grimberg * 0 == fixed format) 2327708c165SSagi Grimberg * @buf: Where to build sense data 2337708c165SSagi Grimberg * @key: Sense key 2347708c165SSagi Grimberg * @asc: Additional sense code 2357708c165SSagi Grimberg * @ascq: Additional sense code qualifier 2367708c165SSagi Grimberg * 2377708c165SSagi Grimberg **/ 2387708c165SSagi Grimberg void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) 2397708c165SSagi Grimberg { 2407708c165SSagi Grimberg if (desc) { 2417708c165SSagi Grimberg buf[0] = 0x72; /* descriptor, current */ 2427708c165SSagi Grimberg buf[1] = key; 2437708c165SSagi Grimberg buf[2] = asc; 2447708c165SSagi Grimberg buf[3] = ascq; 2457708c165SSagi Grimberg buf[7] = 0; 2467708c165SSagi Grimberg } else { 2477708c165SSagi Grimberg buf[0] = 0x70; /* fixed, current */ 2487708c165SSagi Grimberg buf[2] = key; 2497708c165SSagi Grimberg buf[7] = 0xa; 2507708c165SSagi Grimberg buf[12] = asc; 2517708c165SSagi Grimberg buf[13] = ascq; 2527708c165SSagi Grimberg } 2537708c165SSagi Grimberg } 2547708c165SSagi Grimberg EXPORT_SYMBOL(scsi_build_sense_buffer); 2557708c165SSagi Grimberg 2567708c165SSagi Grimberg /** 2577708c165SSagi Grimberg * scsi_set_sense_information - set the information field in a 2587708c165SSagi Grimberg * formatted sense data buffer 2597708c165SSagi Grimberg * @buf: Where to build sense data 260f5a8b3a7SSagi Grimberg * @buf_len: buffer length 2617708c165SSagi Grimberg * @info: 64-bit information value to be set 2627708c165SSagi Grimberg * 263f5a8b3a7SSagi Grimberg * Return value: 264749a1122SRandy Dunlap * 0 on success or -EINVAL for invalid sense buffer length 2657708c165SSagi Grimberg **/ 266f5a8b3a7SSagi Grimberg int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) 2677708c165SSagi Grimberg { 2687708c165SSagi Grimberg if ((buf[0] & 0x7f) == 0x72) { 2697708c165SSagi Grimberg u8 *ucp, len; 2707708c165SSagi Grimberg 2717708c165SSagi Grimberg len = buf[7]; 2727708c165SSagi Grimberg ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); 2737708c165SSagi Grimberg if (!ucp) { 27412306b42SSagi Grimberg buf[7] = len + 0xc; 2757708c165SSagi Grimberg ucp = buf + 8 + len; 2767708c165SSagi Grimberg } 277f5a8b3a7SSagi Grimberg 278f5a8b3a7SSagi Grimberg if (buf_len < len + 0xc) 279f5a8b3a7SSagi Grimberg /* Not enough room for info */ 280f5a8b3a7SSagi Grimberg return -EINVAL; 281f5a8b3a7SSagi Grimberg 2827708c165SSagi Grimberg ucp[0] = 0; 2837708c165SSagi Grimberg ucp[1] = 0xa; 2847708c165SSagi Grimberg ucp[2] = 0x80; /* Valid bit */ 2857708c165SSagi Grimberg ucp[3] = 0; 2867708c165SSagi Grimberg put_unaligned_be64(info, &ucp[4]); 2877708c165SSagi Grimberg } else if ((buf[0] & 0x7f) == 0x70) { 288ba083116SHannes Reinecke /* 289ba083116SHannes Reinecke * Only set the 'VALID' bit if we can represent the value 290ba083116SHannes Reinecke * correctly; otherwise just fill out the lower bytes and 291ba083116SHannes Reinecke * clear the 'VALID' flag. 292ba083116SHannes Reinecke */ 293ba083116SHannes Reinecke if (info <= 0xffffffffUL) 2947708c165SSagi Grimberg buf[0] |= 0x80; 295ba083116SHannes Reinecke else 296ba083116SHannes Reinecke buf[0] &= 0x7f; 297ba083116SHannes Reinecke put_unaligned_be32((u32)info, &buf[3]); 2987708c165SSagi Grimberg } 299f5a8b3a7SSagi Grimberg 300f5a8b3a7SSagi Grimberg return 0; 3017708c165SSagi Grimberg } 3027708c165SSagi Grimberg EXPORT_SYMBOL(scsi_set_sense_information); 30378db6e30SHannes Reinecke 30478db6e30SHannes Reinecke /** 30578db6e30SHannes Reinecke * scsi_set_sense_field_pointer - set the field pointer sense key 30678db6e30SHannes Reinecke * specific information in a formatted sense data buffer 30778db6e30SHannes Reinecke * @buf: Where to build sense data 30878db6e30SHannes Reinecke * @buf_len: buffer length 30978db6e30SHannes Reinecke * @fp: field pointer to be set 31078db6e30SHannes Reinecke * @bp: bit pointer to be set 31178db6e30SHannes Reinecke * @cd: command/data bit 31278db6e30SHannes Reinecke * 31378db6e30SHannes Reinecke * Return value: 314749a1122SRandy Dunlap * 0 on success or -EINVAL for invalid sense buffer length 31578db6e30SHannes Reinecke */ 31678db6e30SHannes Reinecke int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd) 31778db6e30SHannes Reinecke { 31878db6e30SHannes Reinecke u8 *ucp, len; 31978db6e30SHannes Reinecke 32078db6e30SHannes Reinecke if ((buf[0] & 0x7f) == 0x72) { 32178db6e30SHannes Reinecke len = buf[7]; 32278db6e30SHannes Reinecke ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2); 32378db6e30SHannes Reinecke if (!ucp) { 32478db6e30SHannes Reinecke buf[7] = len + 8; 32578db6e30SHannes Reinecke ucp = buf + 8 + len; 32678db6e30SHannes Reinecke } 32778db6e30SHannes Reinecke 32878db6e30SHannes Reinecke if (buf_len < len + 8) 32978db6e30SHannes Reinecke /* Not enough room for info */ 33078db6e30SHannes Reinecke return -EINVAL; 33178db6e30SHannes Reinecke 33278db6e30SHannes Reinecke ucp[0] = 2; 33378db6e30SHannes Reinecke ucp[1] = 6; 33478db6e30SHannes Reinecke ucp[4] = 0x80; /* Valid bit */ 33578db6e30SHannes Reinecke if (cd) 33678db6e30SHannes Reinecke ucp[4] |= 0x40; 33778db6e30SHannes Reinecke if (bp < 0x8) 33878db6e30SHannes Reinecke ucp[4] |= 0x8 | bp; 33978db6e30SHannes Reinecke put_unaligned_be16(fp, &ucp[5]); 34078db6e30SHannes Reinecke } else if ((buf[0] & 0x7f) == 0x70) { 34178db6e30SHannes Reinecke len = buf[7]; 34278db6e30SHannes Reinecke if (len < 18) 34378db6e30SHannes Reinecke buf[7] = 18; 34478db6e30SHannes Reinecke 34578db6e30SHannes Reinecke buf[15] = 0x80; 34678db6e30SHannes Reinecke if (cd) 34778db6e30SHannes Reinecke buf[15] |= 0x40; 34878db6e30SHannes Reinecke if (bp < 0x8) 34978db6e30SHannes Reinecke buf[15] |= 0x8 | bp; 35078db6e30SHannes Reinecke put_unaligned_be16(fp, &buf[16]); 35178db6e30SHannes Reinecke } 35278db6e30SHannes Reinecke 35378db6e30SHannes Reinecke return 0; 35478db6e30SHannes Reinecke } 35578db6e30SHannes Reinecke EXPORT_SYMBOL(scsi_set_sense_field_pointer); 356