xref: /qemu/include/scsi/utils.h (revision d7a84021db8eeddcd5d24ab591a1434763caff6c)
1  #ifndef SCSI_UTILS_H
2  #define SCSI_UTILS_H
3  
4  #ifdef CONFIG_LINUX
5  #include <scsi/sg.h>
6  #endif
7  
8  #define SCSI_CMD_BUF_SIZE      16
9  #define SCSI_SENSE_LEN         18
10  #define SCSI_SENSE_LEN_SCANNER 32
11  #define SCSI_INQUIRY_LEN       36
12  
13  enum SCSIXferMode {
14      SCSI_XFER_NONE,      /*  TEST_UNIT_READY, ...            */
15      SCSI_XFER_FROM_DEV,  /*  READ, INQUIRY, MODE_SENSE, ...  */
16      SCSI_XFER_TO_DEV,    /*  WRITE, MODE_SELECT, ...         */
17  };
18  
19  typedef struct SCSICommand {
20      uint8_t buf[SCSI_CMD_BUF_SIZE];
21      int len;
22      size_t xfer;
23      uint64_t lba;
24      enum SCSIXferMode mode;
25  } SCSICommand;
26  
27  typedef struct SCSISense {
28      uint8_t key;
29      uint8_t asc;
30      uint8_t ascq;
31  } SCSISense;
32  
33  int scsi_build_sense(uint8_t *buf, SCSISense sense);
34  SCSISense scsi_parse_sense_buf(const uint8_t *in_buf, int in_len);
35  int scsi_build_sense_buf(uint8_t *buf, size_t max_size, SCSISense sense,
36                           bool fixed_sense);
37  
38  /*
39   * Predefined sense codes
40   */
41  
42  /* No sense data available */
43  extern const struct SCSISense sense_code_NO_SENSE;
44  /* LUN not ready, Manual intervention required */
45  extern const struct SCSISense sense_code_LUN_NOT_READY;
46  /* LUN not ready, Medium not present */
47  extern const struct SCSISense sense_code_NO_MEDIUM;
48  /* LUN not ready, medium removal prevented */
49  extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
50  /* Hardware error, internal target failure */
51  extern const struct SCSISense sense_code_TARGET_FAILURE;
52  /* Illegal request, invalid command operation code */
53  extern const struct SCSISense sense_code_INVALID_OPCODE;
54  /* Illegal request, LBA out of range */
55  extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
56  /* Illegal request, Invalid field in CDB */
57  extern const struct SCSISense sense_code_INVALID_FIELD;
58  /* Illegal request, Invalid field in parameter list */
59  extern const struct SCSISense sense_code_INVALID_PARAM;
60  /* Illegal request, Invalid value in parameter list */
61  extern const struct SCSISense sense_code_INVALID_PARAM_VALUE;
62  /* Illegal request, Parameter list length error */
63  extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
64  /* Illegal request, LUN not supported */
65  extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
66  /* Illegal request, Saving parameters not supported */
67  extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
68  /* Illegal request, Incompatible format */
69  extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
70  /* Illegal request, medium removal prevented */
71  extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
72  /* Illegal request, Invalid Transfer Tag */
73  extern const struct SCSISense sense_code_INVALID_TAG;
74  /* Command aborted, I/O process terminated */
75  extern const struct SCSISense sense_code_IO_ERROR;
76  /* Command aborted, I_T Nexus loss occurred */
77  extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
78  /* Command aborted, Logical Unit failure */
79  extern const struct SCSISense sense_code_LUN_FAILURE;
80  /* Command aborted, LUN Communication failure */
81  extern const struct SCSISense sense_code_LUN_COMM_FAILURE;
82  /* Command aborted, Overlapped Commands Attempted */
83  extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
84  /* Medium error, Unrecovered read error */
85  extern const struct SCSISense sense_code_READ_ERROR;
86  /* LUN not ready, Cause not reportable */
87  extern const struct SCSISense sense_code_NOT_READY;
88  /* Unit attention, Capacity data has changed */
89  extern const struct SCSISense sense_code_CAPACITY_CHANGED;
90  /* Unit attention, SCSI bus reset */
91  extern const struct SCSISense sense_code_SCSI_BUS_RESET;
92  /* LUN not ready, Medium not present */
93  extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
94  /* Unit attention, Power on, reset or bus device reset occurred */
95  extern const struct SCSISense sense_code_RESET;
96  /* Unit attention, Medium may have changed*/
97  extern const struct SCSISense sense_code_MEDIUM_CHANGED;
98  /* Unit attention, Reported LUNs data has changed */
99  extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
100  /* Unit attention, Device internal reset */
101  extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
102  /* Data Protection, Write Protected */
103  extern const struct SCSISense sense_code_WRITE_PROTECTED;
104  /* Data Protection, Space Allocation Failed Write Protect */
105  extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
106  
107  #define SENSE_CODE(x) sense_code_ ## x
108  
109  int scsi_sense_to_errno(int key, int asc, int ascq);
110  int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size);
111  bool scsi_sense_buf_is_guest_recoverable(const uint8_t *sense, size_t sense_size);
112  
113  int scsi_convert_sense(uint8_t *in_buf, int in_len,
114                         uint8_t *buf, int len, bool fixed);
115  const char *scsi_command_name(uint8_t cmd);
116  
117  uint64_t scsi_cmd_lba(SCSICommand *cmd);
118  uint32_t scsi_data_cdb_xfer(uint8_t *buf);
119  uint32_t scsi_cdb_xfer(uint8_t *buf);
120  int scsi_cdb_length(uint8_t *buf);
121  
122  /* Linux SG_IO interface.  */
123  #ifdef CONFIG_LINUX
124  #define SG_ERR_DRIVER_TIMEOUT  0x06
125  #define SG_ERR_DRIVER_SENSE    0x08
126  
127  #define SG_ERR_DID_OK          0x00
128  #define SG_ERR_DID_NO_CONNECT  0x01
129  #define SG_ERR_DID_BUS_BUSY    0x02
130  #define SG_ERR_DID_TIME_OUT    0x03
131  
132  #define SG_ERR_DRIVER_SENSE    0x08
133  
134  int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
135                             SCSISense *sense);
136  #endif
137  
138  int scsi_sense_from_errno(int errno_value, SCSISense *sense);
139  
140  #endif
141