162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Functions used by both the SCSI initiator code and the SCSI target code.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef _SCSI_COMMON_H_
762306a36Sopenharmony_ci#define _SCSI_COMMON_H_
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/types.h>
1062306a36Sopenharmony_ci#include <uapi/linux/pr.h>
1162306a36Sopenharmony_ci#include <scsi/scsi_proto.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cienum scsi_pr_type {
1462306a36Sopenharmony_ci	SCSI_PR_WRITE_EXCLUSIVE			= 0x01,
1562306a36Sopenharmony_ci	SCSI_PR_EXCLUSIVE_ACCESS		= 0x03,
1662306a36Sopenharmony_ci	SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY	= 0x05,
1762306a36Sopenharmony_ci	SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY	= 0x06,
1862306a36Sopenharmony_ci	SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS	= 0x07,
1962306a36Sopenharmony_ci	SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS	= 0x08,
2062306a36Sopenharmony_ci};
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cienum scsi_pr_type block_pr_type_to_scsi(enum pr_type type);
2362306a36Sopenharmony_cienum pr_type scsi_pr_type_to_block(enum scsi_pr_type type);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic inline unsigned
2662306a36Sopenharmony_ciscsi_varlen_cdb_length(const void *hdr)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	return ((struct scsi_varlen_cdb_hdr *)hdr)->additional_cdb_length + 8;
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciextern const unsigned char scsi_command_size_tbl[8];
3262306a36Sopenharmony_ci#define COMMAND_SIZE(opcode) scsi_command_size_tbl[((opcode) >> 5) & 7]
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic inline unsigned
3562306a36Sopenharmony_ciscsi_command_size(const unsigned char *cmnd)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
3862306a36Sopenharmony_ci		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic inline unsigned char
4262306a36Sopenharmony_ciscsi_command_control(const unsigned char *cmnd)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	return (cmnd[0] == VARIABLE_LENGTH_CMD) ?
4562306a36Sopenharmony_ci		cmnd[1] : cmnd[COMMAND_SIZE(cmnd[0]) - 1];
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* Returns a human-readable name for the device */
4962306a36Sopenharmony_ciextern const char *scsi_device_type(unsigned type);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciextern void int_to_scsilun(u64, struct scsi_lun *);
5262306a36Sopenharmony_ciextern u64 scsilun_to_int(struct scsi_lun *);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/*
5562306a36Sopenharmony_ci * This is a slightly modified SCSI sense "descriptor" format header.
5662306a36Sopenharmony_ci * The addition is to allow the 0x70 and 0x71 response codes. The idea
5762306a36Sopenharmony_ci * is to place the salient data from either "fixed" or "descriptor" sense
5862306a36Sopenharmony_ci * format into one structure to ease application processing.
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci * The original sense buffer should be kept around for those cases
6162306a36Sopenharmony_ci * in which more information is required (e.g. the LBA of a MEDIUM ERROR).
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_cistruct scsi_sense_hdr {		/* See SPC-3 section 4.5 */
6462306a36Sopenharmony_ci	u8 response_code;	/* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
6562306a36Sopenharmony_ci	u8 sense_key;
6662306a36Sopenharmony_ci	u8 asc;
6762306a36Sopenharmony_ci	u8 ascq;
6862306a36Sopenharmony_ci	u8 byte4;
6962306a36Sopenharmony_ci	u8 byte5;
7062306a36Sopenharmony_ci	u8 byte6;
7162306a36Sopenharmony_ci	u8 additional_length;	/* always 0 for fixed sense format */
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic inline bool scsi_sense_valid(const struct scsi_sense_hdr *sshdr)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	if (!sshdr)
7762306a36Sopenharmony_ci		return false;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return (sshdr->response_code & 0x70) == 0x70;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciextern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
8362306a36Sopenharmony_ci				 struct scsi_sense_hdr *sshdr);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciextern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
8662306a36Sopenharmony_ciint scsi_set_sense_information(u8 *buf, int buf_len, u64 info);
8762306a36Sopenharmony_ciint scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd);
8862306a36Sopenharmony_ciextern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
8962306a36Sopenharmony_ci				       int desc_type);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#endif /* _SCSI_COMMON_H_ */
92