1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
207e38420SBart Van Assche /*
307e38420SBart Van Assche * Functions used by both the SCSI initiator code and the SCSI target code.
407e38420SBart Van Assche */
507e38420SBart Van Assche
607e38420SBart Van Assche #ifndef _SCSI_COMMON_H_
707e38420SBart Van Assche #define _SCSI_COMMON_H_
807e38420SBart Van Assche
907e38420SBart Van Assche #include <linux/types.h>
100730b163SMike Christie #include <uapi/linux/pr.h>
1107e38420SBart Van Assche #include <scsi/scsi_proto.h>
1207e38420SBart Van Assche
130730b163SMike Christie enum scsi_pr_type {
140730b163SMike Christie SCSI_PR_WRITE_EXCLUSIVE = 0x01,
150730b163SMike Christie SCSI_PR_EXCLUSIVE_ACCESS = 0x03,
160730b163SMike Christie SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY = 0x05,
170730b163SMike Christie SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY = 0x06,
180730b163SMike Christie SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS = 0x07,
190730b163SMike Christie SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS = 0x08,
200730b163SMike Christie };
210730b163SMike Christie
220730b163SMike Christie enum scsi_pr_type block_pr_type_to_scsi(enum pr_type type);
230af7b5e2SMike Christie enum pr_type scsi_pr_type_to_block(enum scsi_pr_type type);
240730b163SMike Christie
2507e38420SBart Van Assche static inline unsigned
scsi_varlen_cdb_length(const void * hdr)2607e38420SBart Van Assche scsi_varlen_cdb_length(const void *hdr)
2707e38420SBart Van Assche {
2807e38420SBart Van Assche return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
2907e38420SBart Van Assche }
3007e38420SBart Van Assche
3107e38420SBart Van Assche extern const unsigned char scsi_command_size_tbl[8];
3207e38420SBart Van Assche #define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
3307e38420SBart Van Assche
3407e38420SBart Van Assche static inline unsigned
scsi_command_size(const unsigned char * cmnd)3507e38420SBart Van Assche scsi_command_size(const unsigned char *cmnd)
3607e38420SBart Van Assche {
3707e38420SBart Van Assche return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
3807e38420SBart Van Assche scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
3907e38420SBart Van Assche }
4007e38420SBart Van Assche
417010645bSRoman Bolshakov static inline unsigned char
scsi_command_control(const unsigned char * cmnd)427010645bSRoman Bolshakov scsi_command_control(const unsigned char *cmnd)
437010645bSRoman Bolshakov {
447010645bSRoman Bolshakov return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
457010645bSRoman Bolshakov cmnd[1] : cmnd[COMMAND_SIZE(cmnd[0]) - 1];
467010645bSRoman Bolshakov }
477010645bSRoman Bolshakov
4807e38420SBart Van Assche /* Returns a human-readable name for the device */
4907e38420SBart Van Assche extern const char *scsi_device_type(unsigned type);
5007e38420SBart Van Assche
5107e38420SBart Van Assche extern void int_to_scsilun(u64, struct scsi_lun *);
5207e38420SBart Van Assche extern u64 scsilun_to_int(struct scsi_lun *);
5307e38420SBart Van Assche
5407e38420SBart Van Assche /*
5507e38420SBart Van Assche * This is a slightly modified SCSI sense "descriptor" format header.
5607e38420SBart Van Assche * The addition is to allow the 0x70 and 0x71 response codes. The idea
5707e38420SBart Van Assche * is to place the salient data from either "fixed" or "descriptor" sense
5807e38420SBart Van Assche * format into one structure to ease application processing.
5907e38420SBart Van Assche *
6007e38420SBart Van Assche * The original sense buffer should be kept around for those cases
6107e38420SBart Van Assche * in which more information is required (e.g. the LBA of a MEDIUM ERROR).
6207e38420SBart Van Assche */
6307e38420SBart Van Assche struct scsi_sense_hdr { /* See SPC-3 section 4.5 */
6407e38420SBart Van Assche u8 response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
6507e38420SBart Van Assche u8 sense_key;
6607e38420SBart Van Assche u8 asc;
6707e38420SBart Van Assche u8 ascq;
6807e38420SBart Van Assche u8 byte4;
6907e38420SBart Van Assche u8 byte5;
7007e38420SBart Van Assche u8 byte6;
7107e38420SBart Van Assche u8 additional_length; /* always 0 for fixed sense format */
7207e38420SBart Van Assche };
7307e38420SBart Van Assche
scsi_sense_valid(const struct scsi_sense_hdr * sshdr)7407e38420SBart Van Assche static inline bool scsi_sense_valid(const struct scsi_sense_hdr *sshdr)
7507e38420SBart Van Assche {
7607e38420SBart Van Assche if (!sshdr)
7707e38420SBart Van Assche return false;
7807e38420SBart Van Assche
7907e38420SBart Van Assche return (sshdr->response_code & 0x70) == 0x70;
8007e38420SBart Van Assche }
8107e38420SBart Van Assche
8207e38420SBart Van Assche extern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
8307e38420SBart Van Assche struct scsi_sense_hdr *sshdr);
8407e38420SBart Van Assche
857708c165SSagi Grimberg extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
86f5a8b3a7SSagi Grimberg int scsi_set_sense_information(u8 *buf, int buf_len, u64 info);
8778db6e30SHannes Reinecke int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd);
887708c165SSagi Grimberg extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
897708c165SSagi Grimberg int desc_type);
907708c165SSagi Grimberg
9107e38420SBart Van Assche #endif /* _SCSI_COMMON_H_ */
92