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