xref: /openbmc/linux/drivers/scsi/scsi_common.c (revision b69367df)
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