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