1 e5b5728cSPaolo Bonzini /*
2 e5b5728cSPaolo Bonzini * SCSI helpers
3 e5b5728cSPaolo Bonzini *
4 e5b5728cSPaolo Bonzini * Copyright 2017 Red Hat, Inc.
5 e5b5728cSPaolo Bonzini *
6 e5b5728cSPaolo Bonzini * Authors:
7 e5b5728cSPaolo Bonzini * Fam Zheng <famz@redhat.com>
8 e5b5728cSPaolo Bonzini * Paolo Bonzini <pbonzini@redhat.com>
9 e5b5728cSPaolo Bonzini *
10 e5b5728cSPaolo Bonzini * This program is free software; you can redistribute it and/or modify it
11 e5b5728cSPaolo Bonzini * under the terms of the GNU General Public License as published by the Free
12 e5b5728cSPaolo Bonzini * Software Foundation; either version 2 of the License, or (at your option)
13 e5b5728cSPaolo Bonzini * any later version.
14 e5b5728cSPaolo Bonzini */
15 e5b5728cSPaolo Bonzini
16 e5b5728cSPaolo Bonzini #include "qemu/osdep.h"
17 08e2c9f1SPaolo Bonzini #include "scsi/constants.h"
18 e5b5728cSPaolo Bonzini #include "scsi/utils.h"
19 e5b5728cSPaolo Bonzini #include "qemu/bswap.h"
20 e5b5728cSPaolo Bonzini
scsi_data_cdb_xfer(uint8_t * buf)21 e5b5728cSPaolo Bonzini uint32_t scsi_data_cdb_xfer(uint8_t *buf)
22 e5b5728cSPaolo Bonzini {
23 e5b5728cSPaolo Bonzini if ((buf[0] >> 5) == 0 && buf[4] == 0) {
24 e5b5728cSPaolo Bonzini return 256;
25 e5b5728cSPaolo Bonzini } else {
26 e5b5728cSPaolo Bonzini return scsi_cdb_xfer(buf);
27 e5b5728cSPaolo Bonzini }
28 e5b5728cSPaolo Bonzini }
29 e5b5728cSPaolo Bonzini
scsi_cdb_xfer(uint8_t * buf)30 e5b5728cSPaolo Bonzini uint32_t scsi_cdb_xfer(uint8_t *buf)
31 e5b5728cSPaolo Bonzini {
32 e5b5728cSPaolo Bonzini switch (buf[0] >> 5) {
33 e5b5728cSPaolo Bonzini case 0:
34 e5b5728cSPaolo Bonzini return buf[4];
35 e5b5728cSPaolo Bonzini case 1:
36 e5b5728cSPaolo Bonzini case 2:
37 e5b5728cSPaolo Bonzini return lduw_be_p(&buf[7]);
38 e5b5728cSPaolo Bonzini case 4:
39 e5b5728cSPaolo Bonzini return ldl_be_p(&buf[10]) & 0xffffffffULL;
40 e5b5728cSPaolo Bonzini case 5:
41 e5b5728cSPaolo Bonzini return ldl_be_p(&buf[6]) & 0xffffffffULL;
42 e5b5728cSPaolo Bonzini default:
43 e5b5728cSPaolo Bonzini return -1;
44 e5b5728cSPaolo Bonzini }
45 e5b5728cSPaolo Bonzini }
46 e5b5728cSPaolo Bonzini
scsi_cmd_lba(SCSICommand * cmd)47 e5b5728cSPaolo Bonzini uint64_t scsi_cmd_lba(SCSICommand *cmd)
48 e5b5728cSPaolo Bonzini {
49 e5b5728cSPaolo Bonzini uint8_t *buf = cmd->buf;
50 e5b5728cSPaolo Bonzini uint64_t lba;
51 e5b5728cSPaolo Bonzini
52 e5b5728cSPaolo Bonzini switch (buf[0] >> 5) {
53 e5b5728cSPaolo Bonzini case 0:
54 e5b5728cSPaolo Bonzini lba = ldl_be_p(&buf[0]) & 0x1fffff;
55 e5b5728cSPaolo Bonzini break;
56 e5b5728cSPaolo Bonzini case 1:
57 e5b5728cSPaolo Bonzini case 2:
58 e5b5728cSPaolo Bonzini case 5:
59 e5b5728cSPaolo Bonzini lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
60 e5b5728cSPaolo Bonzini break;
61 e5b5728cSPaolo Bonzini case 4:
62 e5b5728cSPaolo Bonzini lba = ldq_be_p(&buf[2]);
63 e5b5728cSPaolo Bonzini break;
64 e5b5728cSPaolo Bonzini default:
65 e5b5728cSPaolo Bonzini lba = -1;
66 e5b5728cSPaolo Bonzini
67 e5b5728cSPaolo Bonzini }
68 e5b5728cSPaolo Bonzini return lba;
69 e5b5728cSPaolo Bonzini }
70 e5b5728cSPaolo Bonzini
scsi_cdb_length(uint8_t * buf)71 e5b5728cSPaolo Bonzini int scsi_cdb_length(uint8_t *buf)
72 e5b5728cSPaolo Bonzini {
73 e5b5728cSPaolo Bonzini int cdb_len;
74 e5b5728cSPaolo Bonzini
75 e5b5728cSPaolo Bonzini switch (buf[0] >> 5) {
76 e5b5728cSPaolo Bonzini case 0:
77 e5b5728cSPaolo Bonzini cdb_len = 6;
78 e5b5728cSPaolo Bonzini break;
79 e5b5728cSPaolo Bonzini case 1:
80 e5b5728cSPaolo Bonzini case 2:
81 e5b5728cSPaolo Bonzini cdb_len = 10;
82 e5b5728cSPaolo Bonzini break;
83 e5b5728cSPaolo Bonzini case 4:
84 e5b5728cSPaolo Bonzini cdb_len = 16;
85 e5b5728cSPaolo Bonzini break;
86 e5b5728cSPaolo Bonzini case 5:
87 e5b5728cSPaolo Bonzini cdb_len = 12;
88 e5b5728cSPaolo Bonzini break;
89 e5b5728cSPaolo Bonzini default:
90 e5b5728cSPaolo Bonzini cdb_len = -1;
91 e5b5728cSPaolo Bonzini }
92 e5b5728cSPaolo Bonzini return cdb_len;
93 e5b5728cSPaolo Bonzini }
94 e5b5728cSPaolo Bonzini
scsi_parse_sense_buf(const uint8_t * in_buf,int in_len)95 f68d98b2SPaolo Bonzini SCSISense scsi_parse_sense_buf(const uint8_t *in_buf, int in_len)
96 a3760467SPaolo Bonzini {
97 f68d98b2SPaolo Bonzini bool fixed_in;
98 f68d98b2SPaolo Bonzini SCSISense sense;
99 f68d98b2SPaolo Bonzini
100 f68d98b2SPaolo Bonzini assert(in_len > 0);
101 f68d98b2SPaolo Bonzini fixed_in = (in_buf[0] & 2) == 0;
102 f68d98b2SPaolo Bonzini if (fixed_in) {
103 f68d98b2SPaolo Bonzini if (in_len < 14) {
104 f68d98b2SPaolo Bonzini return SENSE_CODE(IO_ERROR);
105 f68d98b2SPaolo Bonzini }
106 f68d98b2SPaolo Bonzini sense.key = in_buf[2];
107 f68d98b2SPaolo Bonzini sense.asc = in_buf[12];
108 f68d98b2SPaolo Bonzini sense.ascq = in_buf[13];
109 f68d98b2SPaolo Bonzini } else {
110 f68d98b2SPaolo Bonzini if (in_len < 4) {
111 f68d98b2SPaolo Bonzini return SENSE_CODE(IO_ERROR);
112 f68d98b2SPaolo Bonzini }
113 f68d98b2SPaolo Bonzini sense.key = in_buf[1];
114 f68d98b2SPaolo Bonzini sense.asc = in_buf[2];
115 f68d98b2SPaolo Bonzini sense.ascq = in_buf[3];
116 f68d98b2SPaolo Bonzini }
117 f68d98b2SPaolo Bonzini
118 f68d98b2SPaolo Bonzini return sense;
119 f68d98b2SPaolo Bonzini }
120 f68d98b2SPaolo Bonzini
scsi_build_sense_buf(uint8_t * out_buf,size_t size,SCSISense sense,bool fixed_sense)121 f68d98b2SPaolo Bonzini int scsi_build_sense_buf(uint8_t *out_buf, size_t size, SCSISense sense,
122 f68d98b2SPaolo Bonzini bool fixed_sense)
123 f68d98b2SPaolo Bonzini {
124 f68d98b2SPaolo Bonzini int len;
125 f68d98b2SPaolo Bonzini uint8_t buf[SCSI_SENSE_LEN] = { 0 };
126 f68d98b2SPaolo Bonzini
127 f68d98b2SPaolo Bonzini if (fixed_sense) {
128 a3760467SPaolo Bonzini buf[0] = 0x70;
129 a3760467SPaolo Bonzini buf[2] = sense.key;
130 a3760467SPaolo Bonzini buf[7] = 10;
131 a3760467SPaolo Bonzini buf[12] = sense.asc;
132 a3760467SPaolo Bonzini buf[13] = sense.ascq;
133 f68d98b2SPaolo Bonzini len = 18;
134 f68d98b2SPaolo Bonzini } else {
135 f68d98b2SPaolo Bonzini buf[0] = 0x72;
136 f68d98b2SPaolo Bonzini buf[1] = sense.key;
137 f68d98b2SPaolo Bonzini buf[2] = sense.asc;
138 f68d98b2SPaolo Bonzini buf[3] = sense.ascq;
139 f68d98b2SPaolo Bonzini len = 8;
140 f68d98b2SPaolo Bonzini }
141 f68d98b2SPaolo Bonzini len = MIN(len, size);
142 f68d98b2SPaolo Bonzini memcpy(out_buf, buf, len);
143 f68d98b2SPaolo Bonzini return len;
144 f68d98b2SPaolo Bonzini }
145 f68d98b2SPaolo Bonzini
scsi_build_sense(uint8_t * buf,SCSISense sense)146 f68d98b2SPaolo Bonzini int scsi_build_sense(uint8_t *buf, SCSISense sense)
147 f68d98b2SPaolo Bonzini {
148 f68d98b2SPaolo Bonzini return scsi_build_sense_buf(buf, SCSI_SENSE_LEN, sense, true);
149 a3760467SPaolo Bonzini }
150 a3760467SPaolo Bonzini
151 e5b5728cSPaolo Bonzini /*
152 e5b5728cSPaolo Bonzini * Predefined sense codes
153 e5b5728cSPaolo Bonzini */
154 e5b5728cSPaolo Bonzini
155 e5b5728cSPaolo Bonzini /* No sense data available */
156 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_NO_SENSE = {
157 e5b5728cSPaolo Bonzini .key = NO_SENSE , .asc = 0x00 , .ascq = 0x00
158 e5b5728cSPaolo Bonzini };
159 e5b5728cSPaolo Bonzini
160 e5b5728cSPaolo Bonzini /* LUN not ready, Manual intervention required */
161 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_LUN_NOT_READY = {
162 e5b5728cSPaolo Bonzini .key = NOT_READY, .asc = 0x04, .ascq = 0x03
163 e5b5728cSPaolo Bonzini };
164 e5b5728cSPaolo Bonzini
165 e5b5728cSPaolo Bonzini /* LUN not ready, Medium not present */
166 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_NO_MEDIUM = {
167 e5b5728cSPaolo Bonzini .key = NOT_READY, .asc = 0x3a, .ascq = 0x00
168 e5b5728cSPaolo Bonzini };
169 e5b5728cSPaolo Bonzini
170 e5b5728cSPaolo Bonzini /* LUN not ready, medium removal prevented */
171 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = {
172 e5b5728cSPaolo Bonzini .key = NOT_READY, .asc = 0x53, .ascq = 0x02
173 e5b5728cSPaolo Bonzini };
174 e5b5728cSPaolo Bonzini
175 e5b5728cSPaolo Bonzini /* Hardware error, internal target failure */
176 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_TARGET_FAILURE = {
177 e5b5728cSPaolo Bonzini .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00
178 e5b5728cSPaolo Bonzini };
179 e5b5728cSPaolo Bonzini
180 e5b5728cSPaolo Bonzini /* Illegal request, invalid command operation code */
181 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_INVALID_OPCODE = {
182 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00
183 e5b5728cSPaolo Bonzini };
184 e5b5728cSPaolo Bonzini
185 e5b5728cSPaolo Bonzini /* Illegal request, LBA out of range */
186 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_LBA_OUT_OF_RANGE = {
187 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00
188 e5b5728cSPaolo Bonzini };
189 e5b5728cSPaolo Bonzini
190 e5b5728cSPaolo Bonzini /* Illegal request, Invalid field in CDB */
191 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_INVALID_FIELD = {
192 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00
193 e5b5728cSPaolo Bonzini };
194 e5b5728cSPaolo Bonzini
195 e5b5728cSPaolo Bonzini /* Illegal request, Invalid field in parameter list */
196 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_INVALID_PARAM = {
197 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00
198 e5b5728cSPaolo Bonzini };
199 e5b5728cSPaolo Bonzini
200 2e8f72acSPhilippe Mathieu-Daudé /* Illegal request, Invalid value in parameter list */
201 2e8f72acSPhilippe Mathieu-Daudé const struct SCSISense sense_code_INVALID_PARAM_VALUE = {
202 2e8f72acSPhilippe Mathieu-Daudé .key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x01
203 2e8f72acSPhilippe Mathieu-Daudé };
204 2e8f72acSPhilippe Mathieu-Daudé
205 e5b5728cSPaolo Bonzini /* Illegal request, Parameter list length error */
206 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_INVALID_PARAM_LEN = {
207 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00
208 e5b5728cSPaolo Bonzini };
209 e5b5728cSPaolo Bonzini
210 e5b5728cSPaolo Bonzini /* Illegal request, LUN not supported */
211 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_LUN_NOT_SUPPORTED = {
212 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00
213 e5b5728cSPaolo Bonzini };
214 e5b5728cSPaolo Bonzini
215 e5b5728cSPaolo Bonzini /* Illegal request, Saving parameters not supported */
216 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = {
217 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00
218 e5b5728cSPaolo Bonzini };
219 e5b5728cSPaolo Bonzini
220 e5b5728cSPaolo Bonzini /* Illegal request, Incompatible medium installed */
221 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = {
222 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00
223 e5b5728cSPaolo Bonzini };
224 e5b5728cSPaolo Bonzini
225 e5b5728cSPaolo Bonzini /* Illegal request, medium removal prevented */
226 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = {
227 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02
228 e5b5728cSPaolo Bonzini };
229 e5b5728cSPaolo Bonzini
230 e5b5728cSPaolo Bonzini /* Illegal request, Invalid Transfer Tag */
231 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_INVALID_TAG = {
232 e5b5728cSPaolo Bonzini .key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01
233 e5b5728cSPaolo Bonzini };
234 e5b5728cSPaolo Bonzini
235 e5b5728cSPaolo Bonzini /* Command aborted, I/O process terminated */
236 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_IO_ERROR = {
237 e5b5728cSPaolo Bonzini .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
238 e5b5728cSPaolo Bonzini };
239 e5b5728cSPaolo Bonzini
240 e5b5728cSPaolo Bonzini /* Command aborted, I_T Nexus loss occurred */
241 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_I_T_NEXUS_LOSS = {
242 e5b5728cSPaolo Bonzini .key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07
243 e5b5728cSPaolo Bonzini };
244 e5b5728cSPaolo Bonzini
245 e5b5728cSPaolo Bonzini /* Command aborted, Logical Unit failure */
246 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_LUN_FAILURE = {
247 e5b5728cSPaolo Bonzini .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
248 e5b5728cSPaolo Bonzini };
249 e5b5728cSPaolo Bonzini
250 e5b5728cSPaolo Bonzini /* Command aborted, Overlapped Commands Attempted */
251 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_OVERLAPPED_COMMANDS = {
252 e5b5728cSPaolo Bonzini .key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00
253 e5b5728cSPaolo Bonzini };
254 e5b5728cSPaolo Bonzini
255 fe8fc5aeSPaolo Bonzini /* Command aborted, LUN Communication Failure */
256 fe8fc5aeSPaolo Bonzini const struct SCSISense sense_code_LUN_COMM_FAILURE = {
257 fe8fc5aeSPaolo Bonzini .key = ABORTED_COMMAND, .asc = 0x08, .ascq = 0x00
258 fe8fc5aeSPaolo Bonzini };
259 fe8fc5aeSPaolo Bonzini
260 db66a15cSHannes Reinecke /* Command aborted, LUN does not respond to selection */
261 db66a15cSHannes Reinecke const struct SCSISense sense_code_LUN_NOT_RESPONDING = {
262 db66a15cSHannes Reinecke .key = ABORTED_COMMAND, .asc = 0x05, .ascq = 0x00
263 db66a15cSHannes Reinecke };
264 db66a15cSHannes Reinecke
265 db66a15cSHannes Reinecke /* Command aborted, Command Timeout during processing */
266 db66a15cSHannes Reinecke const struct SCSISense sense_code_COMMAND_TIMEOUT = {
267 db66a15cSHannes Reinecke .key = ABORTED_COMMAND, .asc = 0x2e, .ascq = 0x02
268 db66a15cSHannes Reinecke };
269 db66a15cSHannes Reinecke
270 db66a15cSHannes Reinecke /* Command aborted, Commands cleared by device server */
271 db66a15cSHannes Reinecke const struct SCSISense sense_code_COMMAND_ABORTED = {
272 db66a15cSHannes Reinecke .key = ABORTED_COMMAND, .asc = 0x2f, .ascq = 0x02
273 db66a15cSHannes Reinecke };
274 db66a15cSHannes Reinecke
275 a4a9b6eaSPaolo Bonzini /* Medium Error, Unrecovered read error */
276 a4a9b6eaSPaolo Bonzini const struct SCSISense sense_code_READ_ERROR = {
277 a4a9b6eaSPaolo Bonzini .key = MEDIUM_ERROR, .asc = 0x11, .ascq = 0x00
278 a4a9b6eaSPaolo Bonzini };
279 a4a9b6eaSPaolo Bonzini
280 a4a9b6eaSPaolo Bonzini /* Not ready, Cause not reportable */
281 a4a9b6eaSPaolo Bonzini const struct SCSISense sense_code_NOT_READY = {
282 a4a9b6eaSPaolo Bonzini .key = NOT_READY, .asc = 0x04, .ascq = 0x00
283 a4a9b6eaSPaolo Bonzini };
284 a4a9b6eaSPaolo Bonzini
285 e5b5728cSPaolo Bonzini /* Unit attention, Capacity data has changed */
286 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_CAPACITY_CHANGED = {
287 e5b5728cSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
288 e5b5728cSPaolo Bonzini };
289 e5b5728cSPaolo Bonzini
290 e5b5728cSPaolo Bonzini /* Unit attention, Power on, reset or bus device reset occurred */
291 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_RESET = {
292 e5b5728cSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00
293 e5b5728cSPaolo Bonzini };
294 e5b5728cSPaolo Bonzini
295 fe8fc5aeSPaolo Bonzini /* Unit attention, SCSI bus reset */
296 fe8fc5aeSPaolo Bonzini const struct SCSISense sense_code_SCSI_BUS_RESET = {
297 fe8fc5aeSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x02
298 fe8fc5aeSPaolo Bonzini };
299 fe8fc5aeSPaolo Bonzini
300 e5b5728cSPaolo Bonzini /* Unit attention, No medium */
301 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = {
302 e5b5728cSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00
303 e5b5728cSPaolo Bonzini };
304 e5b5728cSPaolo Bonzini
305 e5b5728cSPaolo Bonzini /* Unit attention, Medium may have changed */
306 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_MEDIUM_CHANGED = {
307 e5b5728cSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00
308 e5b5728cSPaolo Bonzini };
309 e5b5728cSPaolo Bonzini
310 e5b5728cSPaolo Bonzini /* Unit attention, Reported LUNs data has changed */
311 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = {
312 e5b5728cSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e
313 e5b5728cSPaolo Bonzini };
314 e5b5728cSPaolo Bonzini
315 e5b5728cSPaolo Bonzini /* Unit attention, Device internal reset */
316 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = {
317 e5b5728cSPaolo Bonzini .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04
318 e5b5728cSPaolo Bonzini };
319 e5b5728cSPaolo Bonzini
320 e5b5728cSPaolo Bonzini /* Data Protection, Write Protected */
321 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_WRITE_PROTECTED = {
322 e5b5728cSPaolo Bonzini .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00
323 e5b5728cSPaolo Bonzini };
324 e5b5728cSPaolo Bonzini
325 e5b5728cSPaolo Bonzini /* Data Protection, Space Allocation Failed Write Protect */
326 e5b5728cSPaolo Bonzini const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
327 e5b5728cSPaolo Bonzini .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
328 e5b5728cSPaolo Bonzini };
329 e5b5728cSPaolo Bonzini
330 e5b5728cSPaolo Bonzini /*
331 e5b5728cSPaolo Bonzini * scsi_convert_sense
332 e5b5728cSPaolo Bonzini *
333 e5b5728cSPaolo Bonzini * Convert between fixed and descriptor sense buffers
334 e5b5728cSPaolo Bonzini */
scsi_convert_sense(uint8_t * in_buf,int in_len,uint8_t * buf,int len,bool fixed)335 e5b5728cSPaolo Bonzini int scsi_convert_sense(uint8_t *in_buf, int in_len,
336 e5b5728cSPaolo Bonzini uint8_t *buf, int len, bool fixed)
337 e5b5728cSPaolo Bonzini {
338 e5b5728cSPaolo Bonzini SCSISense sense;
339 f68d98b2SPaolo Bonzini bool fixed_in;
340 e5b5728cSPaolo Bonzini
341 2770c90dSPaolo Bonzini if (in_len == 0) {
342 2770c90dSPaolo Bonzini return scsi_build_sense_buf(buf, len, SENSE_CODE(NO_SENSE), fixed);
343 e5b5728cSPaolo Bonzini }
344 e5b5728cSPaolo Bonzini
345 2770c90dSPaolo Bonzini fixed_in = (in_buf[0] & 2) == 0;
346 2770c90dSPaolo Bonzini if (fixed == fixed_in) {
347 2770c90dSPaolo Bonzini memcpy(buf, in_buf, MIN(len, in_len));
348 2770c90dSPaolo Bonzini return MIN(len, in_len);
349 e5b5728cSPaolo Bonzini } else {
350 f68d98b2SPaolo Bonzini sense = scsi_parse_sense_buf(in_buf, in_len);
351 f68d98b2SPaolo Bonzini return scsi_build_sense_buf(buf, len, sense, fixed);
352 e5b5728cSPaolo Bonzini }
353 2770c90dSPaolo Bonzini }
354 e5b5728cSPaolo Bonzini
scsi_sense_is_guest_recoverable(int key,int asc,int ascq)355 bdf9613bSPaolo Bonzini static bool scsi_sense_is_guest_recoverable(int key, int asc, int ascq)
356 bdf9613bSPaolo Bonzini {
357 bdf9613bSPaolo Bonzini switch (key) {
358 bdf9613bSPaolo Bonzini case NO_SENSE:
359 bdf9613bSPaolo Bonzini case RECOVERED_ERROR:
360 bdf9613bSPaolo Bonzini case UNIT_ATTENTION:
361 bdf9613bSPaolo Bonzini case ABORTED_COMMAND:
362 bdf9613bSPaolo Bonzini return true;
363 bdf9613bSPaolo Bonzini case NOT_READY:
364 bdf9613bSPaolo Bonzini case ILLEGAL_REQUEST:
365 bdf9613bSPaolo Bonzini case DATA_PROTECT:
366 bdf9613bSPaolo Bonzini /* Parse ASCQ */
367 bdf9613bSPaolo Bonzini break;
368 bdf9613bSPaolo Bonzini default:
369 bdf9613bSPaolo Bonzini return false;
370 bdf9613bSPaolo Bonzini }
371 bdf9613bSPaolo Bonzini
372 bdf9613bSPaolo Bonzini switch ((asc << 8) | ascq) {
373 bdf9613bSPaolo Bonzini case 0x1a00: /* PARAMETER LIST LENGTH ERROR */
374 bdf9613bSPaolo Bonzini case 0x2000: /* INVALID OPERATION CODE */
375 bdf9613bSPaolo Bonzini case 0x2400: /* INVALID FIELD IN CDB */
376 bdf9613bSPaolo Bonzini case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */
377 bdf9613bSPaolo Bonzini case 0x2600: /* INVALID FIELD IN PARAMETER LIST */
378 bdf9613bSPaolo Bonzini
379 396ce7b9SPaolo Bonzini case 0x2104: /* UNALIGNED WRITE COMMAND */
380 396ce7b9SPaolo Bonzini case 0x2105: /* WRITE BOUNDARY VIOLATION */
381 396ce7b9SPaolo Bonzini case 0x2106: /* ATTEMPT TO READ INVALID DATA */
382 396ce7b9SPaolo Bonzini case 0x550e: /* INSUFFICIENT ZONE RESOURCES */
383 396ce7b9SPaolo Bonzini
384 bdf9613bSPaolo Bonzini case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
385 bdf9613bSPaolo Bonzini case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
386 bdf9613bSPaolo Bonzini return true;
387 bdf9613bSPaolo Bonzini default:
388 bdf9613bSPaolo Bonzini return false;
389 bdf9613bSPaolo Bonzini }
390 bdf9613bSPaolo Bonzini }
391 bdf9613bSPaolo Bonzini
scsi_sense_to_errno(int key,int asc,int ascq)392 e5b5728cSPaolo Bonzini int scsi_sense_to_errno(int key, int asc, int ascq)
393 e5b5728cSPaolo Bonzini {
394 e5b5728cSPaolo Bonzini switch (key) {
395 9661e208SPaolo Bonzini case NO_SENSE:
396 9661e208SPaolo Bonzini case RECOVERED_ERROR:
397 9661e208SPaolo Bonzini case UNIT_ATTENTION:
398 8c460269SPaolo Bonzini return EAGAIN;
399 9661e208SPaolo Bonzini case ABORTED_COMMAND: /* COMMAND ABORTED */
400 e5b5728cSPaolo Bonzini return ECANCELED;
401 9661e208SPaolo Bonzini case NOT_READY:
402 9661e208SPaolo Bonzini case ILLEGAL_REQUEST:
403 9661e208SPaolo Bonzini case DATA_PROTECT:
404 e5b5728cSPaolo Bonzini /* Parse ASCQ */
405 e5b5728cSPaolo Bonzini break;
406 e5b5728cSPaolo Bonzini default:
407 e5b5728cSPaolo Bonzini return EIO;
408 e5b5728cSPaolo Bonzini }
409 e5b5728cSPaolo Bonzini switch ((asc << 8) | ascq) {
410 e5b5728cSPaolo Bonzini case 0x1a00: /* PARAMETER LIST LENGTH ERROR */
411 e5b5728cSPaolo Bonzini case 0x2000: /* INVALID OPERATION CODE */
412 e5b5728cSPaolo Bonzini case 0x2400: /* INVALID FIELD IN CDB */
413 e5b5728cSPaolo Bonzini case 0x2600: /* INVALID FIELD IN PARAMETER LIST */
414 e5b5728cSPaolo Bonzini return EINVAL;
415 e5b5728cSPaolo Bonzini case 0x2100: /* LBA OUT OF RANGE */
416 e5b5728cSPaolo Bonzini case 0x2707: /* SPACE ALLOC FAILED */
417 e5b5728cSPaolo Bonzini return ENOSPC;
418 e5b5728cSPaolo Bonzini case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */
419 e5b5728cSPaolo Bonzini return ENOTSUP;
420 e5b5728cSPaolo Bonzini case 0x3a00: /* MEDIUM NOT PRESENT */
421 e5b5728cSPaolo Bonzini case 0x3a01: /* MEDIUM NOT PRESENT TRAY CLOSED */
422 e5b5728cSPaolo Bonzini case 0x3a02: /* MEDIUM NOT PRESENT TRAY OPEN */
423 e5b5728cSPaolo Bonzini return ENOMEDIUM;
424 e5b5728cSPaolo Bonzini case 0x2700: /* WRITE PROTECTED */
425 e5b5728cSPaolo Bonzini return EACCES;
426 e5b5728cSPaolo Bonzini case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
427 8c460269SPaolo Bonzini return EINPROGRESS;
428 e5b5728cSPaolo Bonzini case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
429 e5b5728cSPaolo Bonzini return ENOTCONN;
430 e5b5728cSPaolo Bonzini default:
431 e5b5728cSPaolo Bonzini return EIO;
432 e5b5728cSPaolo Bonzini }
433 e5b5728cSPaolo Bonzini }
434 e5b5728cSPaolo Bonzini
scsi_sense_buf_to_errno(const uint8_t * in_buf,size_t in_len)435 f68d98b2SPaolo Bonzini int scsi_sense_buf_to_errno(const uint8_t *in_buf, size_t in_len)
436 e5b5728cSPaolo Bonzini {
437 f68d98b2SPaolo Bonzini SCSISense sense;
438 f68d98b2SPaolo Bonzini if (in_len < 1) {
439 e5b5728cSPaolo Bonzini return EIO;
440 e5b5728cSPaolo Bonzini }
441 f68d98b2SPaolo Bonzini
442 f68d98b2SPaolo Bonzini sense = scsi_parse_sense_buf(in_buf, in_len);
443 f68d98b2SPaolo Bonzini return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq);
444 e5b5728cSPaolo Bonzini }
445 e5b5728cSPaolo Bonzini
scsi_sense_buf_is_guest_recoverable(const uint8_t * in_buf,size_t in_len)446 bdf9613bSPaolo Bonzini bool scsi_sense_buf_is_guest_recoverable(const uint8_t *in_buf, size_t in_len)
447 bdf9613bSPaolo Bonzini {
448 bdf9613bSPaolo Bonzini SCSISense sense;
449 bdf9613bSPaolo Bonzini if (in_len < 1) {
450 bdf9613bSPaolo Bonzini return false;
451 bdf9613bSPaolo Bonzini }
452 bdf9613bSPaolo Bonzini
453 bdf9613bSPaolo Bonzini sense = scsi_parse_sense_buf(in_buf, in_len);
454 bdf9613bSPaolo Bonzini return scsi_sense_is_guest_recoverable(sense.key, sense.asc, sense.ascq);
455 bdf9613bSPaolo Bonzini }
456 bdf9613bSPaolo Bonzini
scsi_command_name(uint8_t cmd)457 e5b5728cSPaolo Bonzini const char *scsi_command_name(uint8_t cmd)
458 e5b5728cSPaolo Bonzini {
459 e5b5728cSPaolo Bonzini static const char *names[] = {
460 e5b5728cSPaolo Bonzini [ TEST_UNIT_READY ] = "TEST_UNIT_READY",
461 e5b5728cSPaolo Bonzini [ REWIND ] = "REWIND",
462 e5b5728cSPaolo Bonzini [ REQUEST_SENSE ] = "REQUEST_SENSE",
463 e5b5728cSPaolo Bonzini [ FORMAT_UNIT ] = "FORMAT_UNIT",
464 e5b5728cSPaolo Bonzini [ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
465 e5b5728cSPaolo Bonzini [ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS",
466 e5b5728cSPaolo Bonzini /* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */
467 e5b5728cSPaolo Bonzini [ READ_6 ] = "READ_6",
468 e5b5728cSPaolo Bonzini [ WRITE_6 ] = "WRITE_6",
469 e5b5728cSPaolo Bonzini [ SET_CAPACITY ] = "SET_CAPACITY",
470 e5b5728cSPaolo Bonzini [ READ_REVERSE ] = "READ_REVERSE",
471 e5b5728cSPaolo Bonzini [ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
472 e5b5728cSPaolo Bonzini [ SPACE ] = "SPACE",
473 e5b5728cSPaolo Bonzini [ INQUIRY ] = "INQUIRY",
474 e5b5728cSPaolo Bonzini [ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
475 e5b5728cSPaolo Bonzini [ MAINTENANCE_IN ] = "MAINTENANCE_IN",
476 e5b5728cSPaolo Bonzini [ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
477 e5b5728cSPaolo Bonzini [ MODE_SELECT ] = "MODE_SELECT",
478 e5b5728cSPaolo Bonzini [ RESERVE ] = "RESERVE",
479 e5b5728cSPaolo Bonzini [ RELEASE ] = "RELEASE",
480 e5b5728cSPaolo Bonzini [ COPY ] = "COPY",
481 e5b5728cSPaolo Bonzini [ ERASE ] = "ERASE",
482 e5b5728cSPaolo Bonzini [ MODE_SENSE ] = "MODE_SENSE",
483 e5b5728cSPaolo Bonzini [ START_STOP ] = "START_STOP/LOAD_UNLOAD",
484 e5b5728cSPaolo Bonzini /* LOAD_UNLOAD and START_STOP use the same operation code */
485 e5b5728cSPaolo Bonzini [ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
486 e5b5728cSPaolo Bonzini [ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
487 e5b5728cSPaolo Bonzini [ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
488 e5b5728cSPaolo Bonzini [ READ_CAPACITY_10 ] = "READ_CAPACITY_10",
489 e5b5728cSPaolo Bonzini [ READ_10 ] = "READ_10",
490 e5b5728cSPaolo Bonzini [ WRITE_10 ] = "WRITE_10",
491 e5b5728cSPaolo Bonzini [ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT",
492 e5b5728cSPaolo Bonzini /* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */
493 e5b5728cSPaolo Bonzini [ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10",
494 e5b5728cSPaolo Bonzini [ VERIFY_10 ] = "VERIFY_10",
495 e5b5728cSPaolo Bonzini [ SEARCH_HIGH ] = "SEARCH_HIGH",
496 e5b5728cSPaolo Bonzini [ SEARCH_EQUAL ] = "SEARCH_EQUAL",
497 e5b5728cSPaolo Bonzini [ SEARCH_LOW ] = "SEARCH_LOW",
498 e5b5728cSPaolo Bonzini [ SET_LIMITS ] = "SET_LIMITS",
499 e5b5728cSPaolo Bonzini [ PRE_FETCH ] = "PRE_FETCH/READ_POSITION",
500 e5b5728cSPaolo Bonzini /* READ_POSITION and PRE_FETCH use the same operation code */
501 e5b5728cSPaolo Bonzini [ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
502 e5b5728cSPaolo Bonzini [ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
503 e5b5728cSPaolo Bonzini [ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE",
504 e5b5728cSPaolo Bonzini /* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */
505 e5b5728cSPaolo Bonzini [ MEDIUM_SCAN ] = "MEDIUM_SCAN",
506 e5b5728cSPaolo Bonzini [ COMPARE ] = "COMPARE",
507 e5b5728cSPaolo Bonzini [ COPY_VERIFY ] = "COPY_VERIFY",
508 e5b5728cSPaolo Bonzini [ WRITE_BUFFER ] = "WRITE_BUFFER",
509 e5b5728cSPaolo Bonzini [ READ_BUFFER ] = "READ_BUFFER",
510 e5b5728cSPaolo Bonzini [ UPDATE_BLOCK ] = "UPDATE_BLOCK",
511 e5b5728cSPaolo Bonzini [ READ_LONG_10 ] = "READ_LONG_10",
512 e5b5728cSPaolo Bonzini [ WRITE_LONG_10 ] = "WRITE_LONG_10",
513 e5b5728cSPaolo Bonzini [ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
514 e5b5728cSPaolo Bonzini [ WRITE_SAME_10 ] = "WRITE_SAME_10",
515 e5b5728cSPaolo Bonzini [ UNMAP ] = "UNMAP",
516 e5b5728cSPaolo Bonzini [ READ_TOC ] = "READ_TOC",
517 e5b5728cSPaolo Bonzini [ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
518 e5b5728cSPaolo Bonzini [ SANITIZE ] = "SANITIZE",
519 e5b5728cSPaolo Bonzini [ GET_CONFIGURATION ] = "GET_CONFIGURATION",
520 e5b5728cSPaolo Bonzini [ LOG_SELECT ] = "LOG_SELECT",
521 e5b5728cSPaolo Bonzini [ LOG_SENSE ] = "LOG_SENSE",
522 e5b5728cSPaolo Bonzini [ MODE_SELECT_10 ] = "MODE_SELECT_10",
523 e5b5728cSPaolo Bonzini [ RESERVE_10 ] = "RESERVE_10",
524 e5b5728cSPaolo Bonzini [ RELEASE_10 ] = "RELEASE_10",
525 e5b5728cSPaolo Bonzini [ MODE_SENSE_10 ] = "MODE_SENSE_10",
526 e5b5728cSPaolo Bonzini [ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
527 e5b5728cSPaolo Bonzini [ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
528 e5b5728cSPaolo Bonzini [ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
529 e5b5728cSPaolo Bonzini [ EXTENDED_COPY ] = "EXTENDED_COPY",
530 e5b5728cSPaolo Bonzini [ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
531 e5b5728cSPaolo Bonzini [ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
532 e5b5728cSPaolo Bonzini [ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
533 e5b5728cSPaolo Bonzini [ READ_16 ] = "READ_16",
534 e5b5728cSPaolo Bonzini [ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE",
535 e5b5728cSPaolo Bonzini [ WRITE_16 ] = "WRITE_16",
536 e5b5728cSPaolo Bonzini [ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
537 e5b5728cSPaolo Bonzini [ VERIFY_16 ] = "VERIFY_16",
538 e5b5728cSPaolo Bonzini [ PRE_FETCH_16 ] = "PRE_FETCH_16",
539 e5b5728cSPaolo Bonzini [ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
540 e5b5728cSPaolo Bonzini /* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
541 e5b5728cSPaolo Bonzini [ LOCATE_16 ] = "LOCATE_16",
542 e5b5728cSPaolo Bonzini [ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16",
543 e5b5728cSPaolo Bonzini /* ERASE_16 and WRITE_SAME_16 use the same operation code */
544 e5b5728cSPaolo Bonzini [ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
545 e5b5728cSPaolo Bonzini [ WRITE_LONG_16 ] = "WRITE_LONG_16",
546 e5b5728cSPaolo Bonzini [ REPORT_LUNS ] = "REPORT_LUNS",
547 e5b5728cSPaolo Bonzini [ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12",
548 e5b5728cSPaolo Bonzini [ MOVE_MEDIUM ] = "MOVE_MEDIUM",
549 e5b5728cSPaolo Bonzini [ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
550 e5b5728cSPaolo Bonzini [ READ_12 ] = "READ_12",
551 e5b5728cSPaolo Bonzini [ WRITE_12 ] = "WRITE_12",
552 e5b5728cSPaolo Bonzini [ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE",
553 e5b5728cSPaolo Bonzini /* ERASE_12 and GET_PERFORMANCE use the same operation code */
554 e5b5728cSPaolo Bonzini [ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
555 e5b5728cSPaolo Bonzini [ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
556 e5b5728cSPaolo Bonzini [ VERIFY_12 ] = "VERIFY_12",
557 e5b5728cSPaolo Bonzini [ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
558 e5b5728cSPaolo Bonzini [ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
559 e5b5728cSPaolo Bonzini [ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
560 e5b5728cSPaolo Bonzini [ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
561 e5b5728cSPaolo Bonzini [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING",
562 e5b5728cSPaolo Bonzini /* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
563 e5b5728cSPaolo Bonzini [ READ_CD ] = "READ_CD",
564 e5b5728cSPaolo Bonzini [ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
565 e5b5728cSPaolo Bonzini [ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE",
566 e5b5728cSPaolo Bonzini [ RESERVE_TRACK ] = "RESERVE_TRACK",
567 e5b5728cSPaolo Bonzini [ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
568 e5b5728cSPaolo Bonzini [ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE",
569 e5b5728cSPaolo Bonzini [ SET_CD_SPEED ] = "SET_CD_SPEED",
570 e5b5728cSPaolo Bonzini [ SET_READ_AHEAD ] = "SET_READ_AHEAD",
571 e5b5728cSPaolo Bonzini [ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE",
572 e5b5728cSPaolo Bonzini [ MECHANISM_STATUS ] = "MECHANISM_STATUS",
573 e5b5728cSPaolo Bonzini [ GET_EVENT_STATUS_NOTIFICATION ] = "GET_EVENT_STATUS_NOTIFICATION",
574 e5b5728cSPaolo Bonzini [ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION",
575 e5b5728cSPaolo Bonzini };
576 e5b5728cSPaolo Bonzini
577 e5b5728cSPaolo Bonzini if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL) {
578 e5b5728cSPaolo Bonzini return "*UNKNOWN*";
579 e5b5728cSPaolo Bonzini }
580 e5b5728cSPaolo Bonzini return names[cmd];
581 e5b5728cSPaolo Bonzini }
582 1ead6b4eSPaolo Bonzini
scsi_sense_from_errno(int errno_value,SCSISense * sense)583 d7a84021SPaolo Bonzini int scsi_sense_from_errno(int errno_value, SCSISense *sense)
584 1ead6b4eSPaolo Bonzini {
585 1ead6b4eSPaolo Bonzini switch (errno_value) {
586 d7a84021SPaolo Bonzini case 0:
587 d7a84021SPaolo Bonzini return GOOD;
588 1ead6b4eSPaolo Bonzini case EDOM:
589 1ead6b4eSPaolo Bonzini return TASK_SET_FULL;
590 d7a84021SPaolo Bonzini #ifdef CONFIG_LINUX
591 d7a84021SPaolo Bonzini /* These errno mapping are specific to Linux. For more information:
592 *dc293f60SPaolo Bonzini * - scsi_check_sense and scsi_decide_disposition in drivers/scsi/scsi_error.c
593 d7a84021SPaolo Bonzini * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c
594 d7a84021SPaolo Bonzini * - blk_errors[] in block/blk-core.c
595 d7a84021SPaolo Bonzini */
596 d7a84021SPaolo Bonzini case EBADE:
597 d7a84021SPaolo Bonzini return RESERVATION_CONFLICT;
598 d7a84021SPaolo Bonzini case ENODATA:
599 d7a84021SPaolo Bonzini *sense = SENSE_CODE(READ_ERROR);
600 d7a84021SPaolo Bonzini return CHECK_CONDITION;
601 d7a84021SPaolo Bonzini case EREMOTEIO:
602 *dc293f60SPaolo Bonzini *sense = SENSE_CODE(TARGET_FAILURE);
603 d7a84021SPaolo Bonzini return CHECK_CONDITION;
604 d7a84021SPaolo Bonzini #endif
605 d7a84021SPaolo Bonzini case ENOMEDIUM:
606 d7a84021SPaolo Bonzini *sense = SENSE_CODE(NO_MEDIUM);
607 d7a84021SPaolo Bonzini return CHECK_CONDITION;
608 1ead6b4eSPaolo Bonzini case ENOMEM:
609 1ead6b4eSPaolo Bonzini *sense = SENSE_CODE(TARGET_FAILURE);
610 1ead6b4eSPaolo Bonzini return CHECK_CONDITION;
611 d7a84021SPaolo Bonzini case EINVAL:
612 d7a84021SPaolo Bonzini *sense = SENSE_CODE(INVALID_FIELD);
613 d7a84021SPaolo Bonzini return CHECK_CONDITION;
614 d7a84021SPaolo Bonzini case ENOSPC:
615 d7a84021SPaolo Bonzini *sense = SENSE_CODE(SPACE_ALLOC_FAILED);
616 d7a84021SPaolo Bonzini return CHECK_CONDITION;
617 1ead6b4eSPaolo Bonzini default:
618 1ead6b4eSPaolo Bonzini *sense = SENSE_CODE(IO_ERROR);
619 1ead6b4eSPaolo Bonzini return CHECK_CONDITION;
620 1ead6b4eSPaolo Bonzini }
621 d7a84021SPaolo Bonzini }
622 d7a84021SPaolo Bonzini
scsi_sense_from_host_status(uint8_t host_status,SCSISense * sense)623 db66a15cSHannes Reinecke int scsi_sense_from_host_status(uint8_t host_status,
624 db66a15cSHannes Reinecke SCSISense *sense)
625 db66a15cSHannes Reinecke {
626 db66a15cSHannes Reinecke switch (host_status) {
627 db66a15cSHannes Reinecke case SCSI_HOST_NO_LUN:
628 db66a15cSHannes Reinecke *sense = SENSE_CODE(LUN_NOT_RESPONDING);
629 db66a15cSHannes Reinecke return CHECK_CONDITION;
630 db66a15cSHannes Reinecke case SCSI_HOST_BUSY:
631 db66a15cSHannes Reinecke return BUSY;
632 db66a15cSHannes Reinecke case SCSI_HOST_TIME_OUT:
633 db66a15cSHannes Reinecke *sense = SENSE_CODE(COMMAND_TIMEOUT);
634 db66a15cSHannes Reinecke return CHECK_CONDITION;
635 db66a15cSHannes Reinecke case SCSI_HOST_BAD_RESPONSE:
636 db66a15cSHannes Reinecke *sense = SENSE_CODE(LUN_COMM_FAILURE);
637 db66a15cSHannes Reinecke return CHECK_CONDITION;
638 db66a15cSHannes Reinecke case SCSI_HOST_ABORTED:
639 db66a15cSHannes Reinecke *sense = SENSE_CODE(COMMAND_ABORTED);
640 db66a15cSHannes Reinecke return CHECK_CONDITION;
641 db66a15cSHannes Reinecke case SCSI_HOST_RESET:
642 db66a15cSHannes Reinecke *sense = SENSE_CODE(RESET);
643 db66a15cSHannes Reinecke return CHECK_CONDITION;
644 db66a15cSHannes Reinecke case SCSI_HOST_TRANSPORT_DISRUPTED:
645 db66a15cSHannes Reinecke *sense = SENSE_CODE(I_T_NEXUS_LOSS);
646 db66a15cSHannes Reinecke return CHECK_CONDITION;
647 db66a15cSHannes Reinecke case SCSI_HOST_TARGET_FAILURE:
648 db66a15cSHannes Reinecke *sense = SENSE_CODE(TARGET_FAILURE);
649 db66a15cSHannes Reinecke return CHECK_CONDITION;
650 db66a15cSHannes Reinecke case SCSI_HOST_RESERVATION_ERROR:
651 db66a15cSHannes Reinecke return RESERVATION_CONFLICT;
652 db66a15cSHannes Reinecke case SCSI_HOST_ALLOCATION_FAILURE:
653 db66a15cSHannes Reinecke *sense = SENSE_CODE(SPACE_ALLOC_FAILED);
654 db66a15cSHannes Reinecke return CHECK_CONDITION;
655 db66a15cSHannes Reinecke case SCSI_HOST_MEDIUM_ERROR:
656 db66a15cSHannes Reinecke *sense = SENSE_CODE(READ_ERROR);
657 db66a15cSHannes Reinecke return CHECK_CONDITION;
658 db66a15cSHannes Reinecke }
659 db66a15cSHannes Reinecke return GOOD;
660 db66a15cSHannes Reinecke }
661