root / hw / scsi / scsi-bus.c @ 3d29bcee
History | View | Annotate | Download (53.7 kB)
1 |
#include "hw/hw.h" |
---|---|
2 |
#include "qemu/error-report.h" |
3 |
#include "hw/scsi/scsi.h" |
4 |
#include "block/scsi.h" |
5 |
#include "hw/qdev.h" |
6 |
#include "sysemu/blockdev.h" |
7 |
#include "trace.h" |
8 |
#include "sysemu/dma.h" |
9 |
|
10 |
static char *scsibus_get_dev_path(DeviceState *dev); |
11 |
static char *scsibus_get_fw_dev_path(DeviceState *dev); |
12 |
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf); |
13 |
static void scsi_req_dequeue(SCSIRequest *req); |
14 |
|
15 |
static Property scsi_props[] = {
|
16 |
DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0), |
17 |
DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1), |
18 |
DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1), |
19 |
DEFINE_PROP_END_OF_LIST(), |
20 |
}; |
21 |
|
22 |
static void scsi_bus_class_init(ObjectClass *klass, void *data) |
23 |
{ |
24 |
BusClass *k = BUS_CLASS(klass); |
25 |
|
26 |
k->get_dev_path = scsibus_get_dev_path; |
27 |
k->get_fw_dev_path = scsibus_get_fw_dev_path; |
28 |
} |
29 |
|
30 |
static const TypeInfo scsi_bus_info = { |
31 |
.name = TYPE_SCSI_BUS, |
32 |
.parent = TYPE_BUS, |
33 |
.instance_size = sizeof(SCSIBus),
|
34 |
.class_init = scsi_bus_class_init, |
35 |
}; |
36 |
static int next_scsi_bus; |
37 |
|
38 |
static int scsi_device_init(SCSIDevice *s) |
39 |
{ |
40 |
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); |
41 |
if (sc->init) {
|
42 |
return sc->init(s);
|
43 |
} |
44 |
return 0; |
45 |
} |
46 |
|
47 |
static void scsi_device_destroy(SCSIDevice *s) |
48 |
{ |
49 |
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); |
50 |
if (sc->destroy) {
|
51 |
sc->destroy(s); |
52 |
} |
53 |
} |
54 |
|
55 |
static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t lun,
|
56 |
uint8_t *buf, void *hba_private)
|
57 |
{ |
58 |
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); |
59 |
if (sc->alloc_req) {
|
60 |
return sc->alloc_req(s, tag, lun, buf, hba_private);
|
61 |
} |
62 |
|
63 |
return NULL; |
64 |
} |
65 |
|
66 |
static void scsi_device_unit_attention_reported(SCSIDevice *s) |
67 |
{ |
68 |
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); |
69 |
if (sc->unit_attention_reported) {
|
70 |
sc->unit_attention_reported(s); |
71 |
} |
72 |
} |
73 |
|
74 |
/* Create a scsi bus, and attach devices to it. */
|
75 |
void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info, |
76 |
const char *bus_name) |
77 |
{ |
78 |
qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, bus_name); |
79 |
bus->busnr = next_scsi_bus++; |
80 |
bus->info = info; |
81 |
bus->qbus.allow_hotplug = 1;
|
82 |
} |
83 |
|
84 |
static void scsi_dma_restart_bh(void *opaque) |
85 |
{ |
86 |
SCSIDevice *s = opaque; |
87 |
SCSIRequest *req, *next; |
88 |
|
89 |
qemu_bh_delete(s->bh); |
90 |
s->bh = NULL;
|
91 |
|
92 |
QTAILQ_FOREACH_SAFE(req, &s->requests, next, next) { |
93 |
scsi_req_ref(req); |
94 |
if (req->retry) {
|
95 |
req->retry = false;
|
96 |
switch (req->cmd.mode) {
|
97 |
case SCSI_XFER_FROM_DEV:
|
98 |
case SCSI_XFER_TO_DEV:
|
99 |
scsi_req_continue(req); |
100 |
break;
|
101 |
case SCSI_XFER_NONE:
|
102 |
assert(!req->sg); |
103 |
scsi_req_dequeue(req); |
104 |
scsi_req_enqueue(req); |
105 |
break;
|
106 |
} |
107 |
} |
108 |
scsi_req_unref(req); |
109 |
} |
110 |
} |
111 |
|
112 |
void scsi_req_retry(SCSIRequest *req)
|
113 |
{ |
114 |
/* No need to save a reference, because scsi_dma_restart_bh just
|
115 |
* looks at the request list. */
|
116 |
req->retry = true;
|
117 |
} |
118 |
|
119 |
static void scsi_dma_restart_cb(void *opaque, int running, RunState state) |
120 |
{ |
121 |
SCSIDevice *s = opaque; |
122 |
|
123 |
if (!running) {
|
124 |
return;
|
125 |
} |
126 |
if (!s->bh) {
|
127 |
s->bh = qemu_bh_new(scsi_dma_restart_bh, s); |
128 |
qemu_bh_schedule(s->bh); |
129 |
} |
130 |
} |
131 |
|
132 |
static int scsi_qdev_init(DeviceState *qdev) |
133 |
{ |
134 |
SCSIDevice *dev = SCSI_DEVICE(qdev); |
135 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); |
136 |
SCSIDevice *d; |
137 |
int rc = -1; |
138 |
|
139 |
if (dev->channel > bus->info->max_channel) {
|
140 |
error_report("bad scsi channel id: %d", dev->channel);
|
141 |
goto err;
|
142 |
} |
143 |
if (dev->id != -1 && dev->id > bus->info->max_target) { |
144 |
error_report("bad scsi device id: %d", dev->id);
|
145 |
goto err;
|
146 |
} |
147 |
if (dev->lun != -1 && dev->lun > bus->info->max_lun) { |
148 |
error_report("bad scsi device lun: %d", dev->lun);
|
149 |
goto err;
|
150 |
} |
151 |
|
152 |
if (dev->id == -1) { |
153 |
int id = -1; |
154 |
if (dev->lun == -1) { |
155 |
dev->lun = 0;
|
156 |
} |
157 |
do {
|
158 |
d = scsi_device_find(bus, dev->channel, ++id, dev->lun); |
159 |
} while (d && d->lun == dev->lun && id < bus->info->max_target);
|
160 |
if (d && d->lun == dev->lun) {
|
161 |
error_report("no free target");
|
162 |
goto err;
|
163 |
} |
164 |
dev->id = id; |
165 |
} else if (dev->lun == -1) { |
166 |
int lun = -1; |
167 |
do {
|
168 |
d = scsi_device_find(bus, dev->channel, dev->id, ++lun); |
169 |
} while (d && d->lun == lun && lun < bus->info->max_lun);
|
170 |
if (d && d->lun == lun) {
|
171 |
error_report("no free lun");
|
172 |
goto err;
|
173 |
} |
174 |
dev->lun = lun; |
175 |
} else {
|
176 |
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); |
177 |
assert(d); |
178 |
if (d->lun == dev->lun && dev != d) {
|
179 |
qdev_free(&d->qdev); |
180 |
} |
181 |
} |
182 |
|
183 |
QTAILQ_INIT(&dev->requests); |
184 |
rc = scsi_device_init(dev); |
185 |
if (rc == 0) { |
186 |
dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, |
187 |
dev); |
188 |
} |
189 |
|
190 |
if (bus->info->hotplug) {
|
191 |
bus->info->hotplug(bus, dev); |
192 |
} |
193 |
|
194 |
err:
|
195 |
return rc;
|
196 |
} |
197 |
|
198 |
static int scsi_qdev_exit(DeviceState *qdev) |
199 |
{ |
200 |
SCSIDevice *dev = SCSI_DEVICE(qdev); |
201 |
|
202 |
if (dev->vmsentry) {
|
203 |
qemu_del_vm_change_state_handler(dev->vmsentry); |
204 |
} |
205 |
scsi_device_destroy(dev); |
206 |
return 0; |
207 |
} |
208 |
|
209 |
/* handle legacy '-drive if=scsi,...' cmd line args */
|
210 |
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, |
211 |
int unit, bool removable, int bootindex, |
212 |
const char *serial, Error **errp) |
213 |
{ |
214 |
const char *driver; |
215 |
DeviceState *dev; |
216 |
Error *err = NULL;
|
217 |
|
218 |
driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk"; |
219 |
dev = qdev_create(&bus->qbus, driver); |
220 |
qdev_prop_set_uint32(dev, "scsi-id", unit);
|
221 |
if (bootindex >= 0) { |
222 |
qdev_prop_set_int32(dev, "bootindex", bootindex);
|
223 |
} |
224 |
if (object_property_find(OBJECT(dev), "removable", NULL)) { |
225 |
qdev_prop_set_bit(dev, "removable", removable);
|
226 |
} |
227 |
if (serial) {
|
228 |
qdev_prop_set_string(dev, "serial", serial);
|
229 |
} |
230 |
if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { |
231 |
error_setg(errp, "Setting drive property failed");
|
232 |
qdev_free(dev); |
233 |
return NULL; |
234 |
} |
235 |
object_property_set_bool(OBJECT(dev), true, "realized", &err); |
236 |
if (err != NULL) { |
237 |
error_propagate(errp, err); |
238 |
qdev_free(dev); |
239 |
return NULL; |
240 |
} |
241 |
return SCSI_DEVICE(dev);
|
242 |
} |
243 |
|
244 |
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp)
|
245 |
{ |
246 |
Location loc; |
247 |
DriveInfo *dinfo; |
248 |
int unit;
|
249 |
Error *err = NULL;
|
250 |
|
251 |
loc_push_none(&loc); |
252 |
for (unit = 0; unit <= bus->info->max_target; unit++) { |
253 |
dinfo = drive_get(IF_SCSI, bus->busnr, unit); |
254 |
if (dinfo == NULL) { |
255 |
continue;
|
256 |
} |
257 |
qemu_opts_loc_restore(dinfo->opts); |
258 |
scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL, |
259 |
&err); |
260 |
if (err != NULL) { |
261 |
error_propagate(errp, err); |
262 |
break;
|
263 |
} |
264 |
} |
265 |
loc_pop(&loc); |
266 |
} |
267 |
|
268 |
static int32_t scsi_invalid_field(SCSIRequest *req, uint8_t *buf)
|
269 |
{ |
270 |
scsi_req_build_sense(req, SENSE_CODE(INVALID_FIELD)); |
271 |
scsi_req_complete(req, CHECK_CONDITION); |
272 |
return 0; |
273 |
} |
274 |
|
275 |
static const struct SCSIReqOps reqops_invalid_field = { |
276 |
.size = sizeof(SCSIRequest),
|
277 |
.send_command = scsi_invalid_field |
278 |
}; |
279 |
|
280 |
/* SCSIReqOps implementation for invalid commands. */
|
281 |
|
282 |
static int32_t scsi_invalid_command(SCSIRequest *req, uint8_t *buf)
|
283 |
{ |
284 |
scsi_req_build_sense(req, SENSE_CODE(INVALID_OPCODE)); |
285 |
scsi_req_complete(req, CHECK_CONDITION); |
286 |
return 0; |
287 |
} |
288 |
|
289 |
static const struct SCSIReqOps reqops_invalid_opcode = { |
290 |
.size = sizeof(SCSIRequest),
|
291 |
.send_command = scsi_invalid_command |
292 |
}; |
293 |
|
294 |
/* SCSIReqOps implementation for unit attention conditions. */
|
295 |
|
296 |
static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
|
297 |
{ |
298 |
if (req->dev->unit_attention.key == UNIT_ATTENTION) {
|
299 |
scsi_req_build_sense(req, req->dev->unit_attention); |
300 |
} else if (req->bus->unit_attention.key == UNIT_ATTENTION) { |
301 |
scsi_req_build_sense(req, req->bus->unit_attention); |
302 |
} |
303 |
scsi_req_complete(req, CHECK_CONDITION); |
304 |
return 0; |
305 |
} |
306 |
|
307 |
static const struct SCSIReqOps reqops_unit_attention = { |
308 |
.size = sizeof(SCSIRequest),
|
309 |
.send_command = scsi_unit_attention |
310 |
}; |
311 |
|
312 |
/* SCSIReqOps implementation for REPORT LUNS and for commands sent to
|
313 |
an invalid LUN. */
|
314 |
|
315 |
typedef struct SCSITargetReq SCSITargetReq; |
316 |
|
317 |
struct SCSITargetReq {
|
318 |
SCSIRequest req; |
319 |
int len;
|
320 |
uint8_t buf[2056];
|
321 |
}; |
322 |
|
323 |
static void store_lun(uint8_t *outbuf, int lun) |
324 |
{ |
325 |
if (lun < 256) { |
326 |
outbuf[1] = lun;
|
327 |
return;
|
328 |
} |
329 |
outbuf[1] = (lun & 255); |
330 |
outbuf[0] = (lun >> 8) | 0x40; |
331 |
} |
332 |
|
333 |
static bool scsi_target_emulate_report_luns(SCSITargetReq *r) |
334 |
{ |
335 |
BusChild *kid; |
336 |
int i, len, n;
|
337 |
int channel, id;
|
338 |
bool found_lun0;
|
339 |
|
340 |
if (r->req.cmd.xfer < 16) { |
341 |
return false; |
342 |
} |
343 |
if (r->req.cmd.buf[2] > 2) { |
344 |
return false; |
345 |
} |
346 |
channel = r->req.dev->channel; |
347 |
id = r->req.dev->id; |
348 |
found_lun0 = false;
|
349 |
n = 0;
|
350 |
QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { |
351 |
DeviceState *qdev = kid->child; |
352 |
SCSIDevice *dev = SCSI_DEVICE(qdev); |
353 |
|
354 |
if (dev->channel == channel && dev->id == id) {
|
355 |
if (dev->lun == 0) { |
356 |
found_lun0 = true;
|
357 |
} |
358 |
n += 8;
|
359 |
} |
360 |
} |
361 |
if (!found_lun0) {
|
362 |
n += 8;
|
363 |
} |
364 |
len = MIN(n + 8, r->req.cmd.xfer & ~7); |
365 |
if (len > sizeof(r->buf)) { |
366 |
/* TODO: > 256 LUNs? */
|
367 |
return false; |
368 |
} |
369 |
|
370 |
memset(r->buf, 0, len);
|
371 |
stl_be_p(&r->buf, n); |
372 |
i = found_lun0 ? 8 : 16; |
373 |
QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { |
374 |
DeviceState *qdev = kid->child; |
375 |
SCSIDevice *dev = SCSI_DEVICE(qdev); |
376 |
|
377 |
if (dev->channel == channel && dev->id == id) {
|
378 |
store_lun(&r->buf[i], dev->lun); |
379 |
i += 8;
|
380 |
} |
381 |
} |
382 |
assert(i == n + 8);
|
383 |
r->len = len; |
384 |
return true; |
385 |
} |
386 |
|
387 |
static bool scsi_target_emulate_inquiry(SCSITargetReq *r) |
388 |
{ |
389 |
assert(r->req.dev->lun != r->req.lun); |
390 |
if (r->req.cmd.buf[1] & 0x2) { |
391 |
/* Command support data - optional, not implemented */
|
392 |
return false; |
393 |
} |
394 |
|
395 |
if (r->req.cmd.buf[1] & 0x1) { |
396 |
/* Vital product data */
|
397 |
uint8_t page_code = r->req.cmd.buf[2];
|
398 |
r->buf[r->len++] = page_code ; /* this page */
|
399 |
r->buf[r->len++] = 0x00;
|
400 |
|
401 |
switch (page_code) {
|
402 |
case 0x00: /* Supported page codes, mandatory */ |
403 |
{ |
404 |
int pages;
|
405 |
pages = r->len++; |
406 |
r->buf[r->len++] = 0x00; /* list of supported pages (this page) */ |
407 |
r->buf[pages] = r->len - pages - 1; /* number of pages */ |
408 |
break;
|
409 |
} |
410 |
default:
|
411 |
return false; |
412 |
} |
413 |
/* done with EVPD */
|
414 |
assert(r->len < sizeof(r->buf));
|
415 |
r->len = MIN(r->req.cmd.xfer, r->len); |
416 |
return true; |
417 |
} |
418 |
|
419 |
/* Standard INQUIRY data */
|
420 |
if (r->req.cmd.buf[2] != 0) { |
421 |
return false; |
422 |
} |
423 |
|
424 |
/* PAGE CODE == 0 */
|
425 |
r->len = MIN(r->req.cmd.xfer, 36);
|
426 |
memset(r->buf, 0, r->len);
|
427 |
if (r->req.lun != 0) { |
428 |
r->buf[0] = TYPE_NO_LUN;
|
429 |
} else {
|
430 |
r->buf[0] = TYPE_NOT_PRESENT | TYPE_INACTIVE;
|
431 |
r->buf[2] = 5; /* Version */ |
432 |
r->buf[3] = 2 | 0x10; /* HiSup, response data format */ |
433 |
r->buf[4] = r->len - 5; /* Additional Length = (Len - 1) - 4 */ |
434 |
r->buf[7] = 0x10 | (r->req.bus->info->tcq ? 0x02 : 0); /* Sync, TCQ. */ |
435 |
memcpy(&r->buf[8], "QEMU ", 8); |
436 |
memcpy(&r->buf[16], "QEMU TARGET ", 16); |
437 |
pstrcpy((char *) &r->buf[32], 4, qemu_get_version()); |
438 |
} |
439 |
return true; |
440 |
} |
441 |
|
442 |
static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
|
443 |
{ |
444 |
SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); |
445 |
|
446 |
switch (buf[0]) { |
447 |
case REPORT_LUNS:
|
448 |
if (!scsi_target_emulate_report_luns(r)) {
|
449 |
goto illegal_request;
|
450 |
} |
451 |
break;
|
452 |
case INQUIRY:
|
453 |
if (!scsi_target_emulate_inquiry(r)) {
|
454 |
goto illegal_request;
|
455 |
} |
456 |
break;
|
457 |
case REQUEST_SENSE:
|
458 |
r->len = scsi_device_get_sense(r->req.dev, r->buf, |
459 |
MIN(req->cmd.xfer, sizeof r->buf),
|
460 |
(req->cmd.buf[1] & 1) == 0); |
461 |
if (r->req.dev->sense_is_ua) {
|
462 |
scsi_device_unit_attention_reported(req->dev); |
463 |
r->req.dev->sense_len = 0;
|
464 |
r->req.dev->sense_is_ua = false;
|
465 |
} |
466 |
break;
|
467 |
default:
|
468 |
scsi_req_build_sense(req, SENSE_CODE(LUN_NOT_SUPPORTED)); |
469 |
scsi_req_complete(req, CHECK_CONDITION); |
470 |
return 0; |
471 |
illegal_request:
|
472 |
scsi_req_build_sense(req, SENSE_CODE(INVALID_FIELD)); |
473 |
scsi_req_complete(req, CHECK_CONDITION); |
474 |
return 0; |
475 |
} |
476 |
|
477 |
if (!r->len) {
|
478 |
scsi_req_complete(req, GOOD); |
479 |
} |
480 |
return r->len;
|
481 |
} |
482 |
|
483 |
static void scsi_target_read_data(SCSIRequest *req) |
484 |
{ |
485 |
SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); |
486 |
uint32_t n; |
487 |
|
488 |
n = r->len; |
489 |
if (n > 0) { |
490 |
r->len = 0;
|
491 |
scsi_req_data(&r->req, n); |
492 |
} else {
|
493 |
scsi_req_complete(&r->req, GOOD); |
494 |
} |
495 |
} |
496 |
|
497 |
static uint8_t *scsi_target_get_buf(SCSIRequest *req)
|
498 |
{ |
499 |
SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); |
500 |
|
501 |
return r->buf;
|
502 |
} |
503 |
|
504 |
static const struct SCSIReqOps reqops_target_command = { |
505 |
.size = sizeof(SCSITargetReq),
|
506 |
.send_command = scsi_target_send_command, |
507 |
.read_data = scsi_target_read_data, |
508 |
.get_buf = scsi_target_get_buf, |
509 |
}; |
510 |
|
511 |
|
512 |
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
513 |
uint32_t tag, uint32_t lun, void *hba_private)
|
514 |
{ |
515 |
SCSIRequest *req; |
516 |
SCSIBus *bus = scsi_bus_from_device(d); |
517 |
BusState *qbus = BUS(bus); |
518 |
|
519 |
req = g_malloc0(reqops->size); |
520 |
req->refcount = 1;
|
521 |
req->bus = bus; |
522 |
req->dev = d; |
523 |
req->tag = tag; |
524 |
req->lun = lun; |
525 |
req->hba_private = hba_private; |
526 |
req->status = -1;
|
527 |
req->sense_len = 0;
|
528 |
req->ops = reqops; |
529 |
object_ref(OBJECT(d)); |
530 |
object_ref(OBJECT(qbus->parent)); |
531 |
trace_scsi_req_alloc(req->dev->id, req->lun, req->tag); |
532 |
return req;
|
533 |
} |
534 |
|
535 |
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, |
536 |
uint8_t *buf, void *hba_private)
|
537 |
{ |
538 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus); |
539 |
SCSIRequest *req; |
540 |
SCSICommand cmd; |
541 |
|
542 |
if (scsi_req_parse(&cmd, d, buf) != 0) { |
543 |
trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
|
544 |
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private); |
545 |
} else {
|
546 |
trace_scsi_req_parsed(d->id, lun, tag, buf[0],
|
547 |
cmd.mode, cmd.xfer); |
548 |
if (cmd.lba != -1) { |
549 |
trace_scsi_req_parsed_lba(d->id, lun, tag, buf[0],
|
550 |
cmd.lba); |
551 |
} |
552 |
|
553 |
if (cmd.xfer > INT32_MAX) {
|
554 |
req = scsi_req_alloc(&reqops_invalid_field, d, tag, lun, hba_private); |
555 |
} else if ((d->unit_attention.key == UNIT_ATTENTION || |
556 |
bus->unit_attention.key == UNIT_ATTENTION) && |
557 |
(buf[0] != INQUIRY &&
|
558 |
buf[0] != REPORT_LUNS &&
|
559 |
buf[0] != GET_CONFIGURATION &&
|
560 |
buf[0] != GET_EVENT_STATUS_NOTIFICATION &&
|
561 |
|
562 |
/*
|
563 |
* If we already have a pending unit attention condition,
|
564 |
* report this one before triggering another one.
|
565 |
*/
|
566 |
!(buf[0] == REQUEST_SENSE && d->sense_is_ua))) {
|
567 |
req = scsi_req_alloc(&reqops_unit_attention, d, tag, lun, |
568 |
hba_private); |
569 |
} else if (lun != d->lun || |
570 |
buf[0] == REPORT_LUNS ||
|
571 |
(buf[0] == REQUEST_SENSE && d->sense_len)) {
|
572 |
req = scsi_req_alloc(&reqops_target_command, d, tag, lun, |
573 |
hba_private); |
574 |
} else {
|
575 |
req = scsi_device_alloc_req(d, tag, lun, buf, hba_private); |
576 |
} |
577 |
} |
578 |
|
579 |
req->cmd = cmd; |
580 |
req->resid = req->cmd.xfer; |
581 |
|
582 |
switch (buf[0]) { |
583 |
case INQUIRY:
|
584 |
trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]); |
585 |
break;
|
586 |
case TEST_UNIT_READY:
|
587 |
trace_scsi_test_unit_ready(d->id, lun, tag); |
588 |
break;
|
589 |
case REPORT_LUNS:
|
590 |
trace_scsi_report_luns(d->id, lun, tag); |
591 |
break;
|
592 |
case REQUEST_SENSE:
|
593 |
trace_scsi_request_sense(d->id, lun, tag); |
594 |
break;
|
595 |
default:
|
596 |
break;
|
597 |
} |
598 |
|
599 |
return req;
|
600 |
} |
601 |
|
602 |
uint8_t *scsi_req_get_buf(SCSIRequest *req) |
603 |
{ |
604 |
return req->ops->get_buf(req);
|
605 |
} |
606 |
|
607 |
static void scsi_clear_unit_attention(SCSIRequest *req) |
608 |
{ |
609 |
SCSISense *ua; |
610 |
if (req->dev->unit_attention.key != UNIT_ATTENTION &&
|
611 |
req->bus->unit_attention.key != UNIT_ATTENTION) { |
612 |
return;
|
613 |
} |
614 |
|
615 |
/*
|
616 |
* If an INQUIRY command enters the enabled command state,
|
617 |
* the device server shall [not] clear any unit attention condition;
|
618 |
* See also MMC-6, paragraphs 6.5 and 6.6.2.
|
619 |
*/
|
620 |
if (req->cmd.buf[0] == INQUIRY || |
621 |
req->cmd.buf[0] == GET_CONFIGURATION ||
|
622 |
req->cmd.buf[0] == GET_EVENT_STATUS_NOTIFICATION) {
|
623 |
return;
|
624 |
} |
625 |
|
626 |
if (req->dev->unit_attention.key == UNIT_ATTENTION) {
|
627 |
ua = &req->dev->unit_attention; |
628 |
} else {
|
629 |
ua = &req->bus->unit_attention; |
630 |
} |
631 |
|
632 |
/*
|
633 |
* If a REPORT LUNS command enters the enabled command state, [...]
|
634 |
* the device server shall clear any pending unit attention condition
|
635 |
* with an additional sense code of REPORTED LUNS DATA HAS CHANGED.
|
636 |
*/
|
637 |
if (req->cmd.buf[0] == REPORT_LUNS && |
638 |
!(ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc && |
639 |
ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq)) { |
640 |
return;
|
641 |
} |
642 |
|
643 |
*ua = SENSE_CODE(NO_SENSE); |
644 |
} |
645 |
|
646 |
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len) |
647 |
{ |
648 |
int ret;
|
649 |
|
650 |
assert(len >= 14);
|
651 |
if (!req->sense_len) {
|
652 |
return 0; |
653 |
} |
654 |
|
655 |
ret = scsi_build_sense(req->sense, req->sense_len, buf, len, true);
|
656 |
|
657 |
/*
|
658 |
* FIXME: clearing unit attention conditions upon autosense should be done
|
659 |
* only if the UA_INTLCK_CTRL field in the Control mode page is set to 00b
|
660 |
* (SAM-5, 5.14).
|
661 |
*
|
662 |
* We assume UA_INTLCK_CTRL to be 00b for HBAs that support autosense, and
|
663 |
* 10b for HBAs that do not support it (do not call scsi_req_get_sense).
|
664 |
* Here we handle unit attention clearing for UA_INTLCK_CTRL == 00b.
|
665 |
*/
|
666 |
if (req->dev->sense_is_ua) {
|
667 |
scsi_device_unit_attention_reported(req->dev); |
668 |
req->dev->sense_len = 0;
|
669 |
req->dev->sense_is_ua = false;
|
670 |
} |
671 |
return ret;
|
672 |
} |
673 |
|
674 |
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed) |
675 |
{ |
676 |
return scsi_build_sense(dev->sense, dev->sense_len, buf, len, fixed);
|
677 |
} |
678 |
|
679 |
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
|
680 |
{ |
681 |
trace_scsi_req_build_sense(req->dev->id, req->lun, req->tag, |
682 |
sense.key, sense.asc, sense.ascq); |
683 |
memset(req->sense, 0, 18); |
684 |
req->sense[0] = 0x70; |
685 |
req->sense[2] = sense.key;
|
686 |
req->sense[7] = 10; |
687 |
req->sense[12] = sense.asc;
|
688 |
req->sense[13] = sense.ascq;
|
689 |
req->sense_len = 18;
|
690 |
} |
691 |
|
692 |
static void scsi_req_enqueue_internal(SCSIRequest *req) |
693 |
{ |
694 |
assert(!req->enqueued); |
695 |
scsi_req_ref(req); |
696 |
if (req->bus->info->get_sg_list) {
|
697 |
req->sg = req->bus->info->get_sg_list(req); |
698 |
} else {
|
699 |
req->sg = NULL;
|
700 |
} |
701 |
req->enqueued = true;
|
702 |
QTAILQ_INSERT_TAIL(&req->dev->requests, req, next); |
703 |
} |
704 |
|
705 |
int32_t scsi_req_enqueue(SCSIRequest *req) |
706 |
{ |
707 |
int32_t rc; |
708 |
|
709 |
assert(!req->retry); |
710 |
scsi_req_enqueue_internal(req); |
711 |
scsi_req_ref(req); |
712 |
rc = req->ops->send_command(req, req->cmd.buf); |
713 |
scsi_req_unref(req); |
714 |
return rc;
|
715 |
} |
716 |
|
717 |
static void scsi_req_dequeue(SCSIRequest *req) |
718 |
{ |
719 |
trace_scsi_req_dequeue(req->dev->id, req->lun, req->tag); |
720 |
req->retry = false;
|
721 |
if (req->enqueued) {
|
722 |
QTAILQ_REMOVE(&req->dev->requests, req, next); |
723 |
req->enqueued = false;
|
724 |
scsi_req_unref(req); |
725 |
} |
726 |
} |
727 |
|
728 |
static int scsi_get_performance_length(int num_desc, int type, int data_type) |
729 |
{ |
730 |
/* MMC-6, paragraph 6.7. */
|
731 |
switch (type) {
|
732 |
case 0: |
733 |
if ((data_type & 3) == 0) { |
734 |
/* Each descriptor is as in Table 295 - Nominal performance. */
|
735 |
return 16 * num_desc + 8; |
736 |
} else {
|
737 |
/* Each descriptor is as in Table 296 - Exceptions. */
|
738 |
return 6 * num_desc + 8; |
739 |
} |
740 |
case 1: |
741 |
case 4: |
742 |
case 5: |
743 |
return 8 * num_desc + 8; |
744 |
case 2: |
745 |
return 2048 * num_desc + 8; |
746 |
case 3: |
747 |
return 16 * num_desc + 8; |
748 |
default:
|
749 |
return 8; |
750 |
} |
751 |
} |
752 |
|
753 |
static int ata_passthrough_xfer_unit(SCSIDevice *dev, uint8_t *buf) |
754 |
{ |
755 |
int byte_block = (buf[2] >> 2) & 0x1; |
756 |
int type = (buf[2] >> 4) & 0x1; |
757 |
int xfer_unit;
|
758 |
|
759 |
if (byte_block) {
|
760 |
if (type) {
|
761 |
xfer_unit = dev->blocksize; |
762 |
} else {
|
763 |
xfer_unit = 512;
|
764 |
} |
765 |
} else {
|
766 |
xfer_unit = 1;
|
767 |
} |
768 |
|
769 |
return xfer_unit;
|
770 |
} |
771 |
|
772 |
static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf) |
773 |
{ |
774 |
int length = buf[2] & 0x3; |
775 |
int xfer;
|
776 |
int unit = ata_passthrough_xfer_unit(dev, buf);
|
777 |
|
778 |
switch (length) {
|
779 |
case 0: |
780 |
case 3: /* USB-specific. */ |
781 |
default:
|
782 |
xfer = 0;
|
783 |
break;
|
784 |
case 1: |
785 |
xfer = buf[3];
|
786 |
break;
|
787 |
case 2: |
788 |
xfer = buf[4];
|
789 |
break;
|
790 |
} |
791 |
|
792 |
return xfer * unit;
|
793 |
} |
794 |
|
795 |
static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf) |
796 |
{ |
797 |
int extend = buf[1] & 0x1; |
798 |
int length = buf[2] & 0x3; |
799 |
int xfer;
|
800 |
int unit = ata_passthrough_xfer_unit(dev, buf);
|
801 |
|
802 |
switch (length) {
|
803 |
case 0: |
804 |
case 3: /* USB-specific. */ |
805 |
default:
|
806 |
xfer = 0;
|
807 |
break;
|
808 |
case 1: |
809 |
xfer = buf[4];
|
810 |
xfer |= (extend ? buf[3] << 8 : 0); |
811 |
break;
|
812 |
case 2: |
813 |
xfer = buf[6];
|
814 |
xfer |= (extend ? buf[5] << 8 : 0); |
815 |
break;
|
816 |
} |
817 |
|
818 |
return xfer * unit;
|
819 |
} |
820 |
|
821 |
uint32_t scsi_data_cdb_length(uint8_t *buf) |
822 |
{ |
823 |
if ((buf[0] >> 5) == 0 && buf[4] == 0) { |
824 |
return 256; |
825 |
} else {
|
826 |
return scsi_cdb_length(buf);
|
827 |
} |
828 |
} |
829 |
|
830 |
uint32_t scsi_cdb_length(uint8_t *buf) |
831 |
{ |
832 |
switch (buf[0] >> 5) { |
833 |
case 0: |
834 |
return buf[4]; |
835 |
break;
|
836 |
case 1: |
837 |
case 2: |
838 |
return lduw_be_p(&buf[7]); |
839 |
break;
|
840 |
case 4: |
841 |
return ldl_be_p(&buf[10]) & 0xffffffffULL; |
842 |
break;
|
843 |
case 5: |
844 |
return ldl_be_p(&buf[6]) & 0xffffffffULL; |
845 |
break;
|
846 |
default:
|
847 |
return -1; |
848 |
} |
849 |
} |
850 |
|
851 |
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) |
852 |
{ |
853 |
cmd->xfer = scsi_cdb_length(buf); |
854 |
switch (buf[0]) { |
855 |
case TEST_UNIT_READY:
|
856 |
case REWIND:
|
857 |
case START_STOP:
|
858 |
case SET_CAPACITY:
|
859 |
case WRITE_FILEMARKS:
|
860 |
case WRITE_FILEMARKS_16:
|
861 |
case SPACE:
|
862 |
case RESERVE:
|
863 |
case RELEASE:
|
864 |
case ERASE:
|
865 |
case ALLOW_MEDIUM_REMOVAL:
|
866 |
case VERIFY_10:
|
867 |
case SEEK_10:
|
868 |
case SYNCHRONIZE_CACHE:
|
869 |
case SYNCHRONIZE_CACHE_16:
|
870 |
case LOCATE_16:
|
871 |
case LOCK_UNLOCK_CACHE:
|
872 |
case SET_CD_SPEED:
|
873 |
case SET_LIMITS:
|
874 |
case WRITE_LONG_10:
|
875 |
case UPDATE_BLOCK:
|
876 |
case RESERVE_TRACK:
|
877 |
case SET_READ_AHEAD:
|
878 |
case PRE_FETCH:
|
879 |
case PRE_FETCH_16:
|
880 |
case ALLOW_OVERWRITE:
|
881 |
cmd->xfer = 0;
|
882 |
break;
|
883 |
case MODE_SENSE:
|
884 |
break;
|
885 |
case WRITE_SAME_10:
|
886 |
case WRITE_SAME_16:
|
887 |
cmd->xfer = dev->blocksize; |
888 |
break;
|
889 |
case READ_CAPACITY_10:
|
890 |
cmd->xfer = 8;
|
891 |
break;
|
892 |
case READ_BLOCK_LIMITS:
|
893 |
cmd->xfer = 6;
|
894 |
break;
|
895 |
case SEND_VOLUME_TAG:
|
896 |
/* GPCMD_SET_STREAMING from multimedia commands. */
|
897 |
if (dev->type == TYPE_ROM) {
|
898 |
cmd->xfer = buf[10] | (buf[9] << 8); |
899 |
} else {
|
900 |
cmd->xfer = buf[9] | (buf[8] << 8); |
901 |
} |
902 |
break;
|
903 |
case WRITE_6:
|
904 |
/* length 0 means 256 blocks */
|
905 |
if (cmd->xfer == 0) { |
906 |
cmd->xfer = 256;
|
907 |
} |
908 |
case WRITE_10:
|
909 |
case WRITE_VERIFY_10:
|
910 |
case WRITE_12:
|
911 |
case WRITE_VERIFY_12:
|
912 |
case WRITE_16:
|
913 |
case WRITE_VERIFY_16:
|
914 |
cmd->xfer *= dev->blocksize; |
915 |
break;
|
916 |
case READ_6:
|
917 |
case READ_REVERSE:
|
918 |
/* length 0 means 256 blocks */
|
919 |
if (cmd->xfer == 0) { |
920 |
cmd->xfer = 256;
|
921 |
} |
922 |
case READ_10:
|
923 |
case RECOVER_BUFFERED_DATA:
|
924 |
case READ_12:
|
925 |
case READ_16:
|
926 |
cmd->xfer *= dev->blocksize; |
927 |
break;
|
928 |
case FORMAT_UNIT:
|
929 |
/* MMC mandates the parameter list to be 12-bytes long. Parameters
|
930 |
* for block devices are restricted to the header right now. */
|
931 |
if (dev->type == TYPE_ROM && (buf[1] & 16)) { |
932 |
cmd->xfer = 12;
|
933 |
} else {
|
934 |
cmd->xfer = (buf[1] & 16) == 0 ? 0 : (buf[1] & 32 ? 8 : 4); |
935 |
} |
936 |
break;
|
937 |
case INQUIRY:
|
938 |
case RECEIVE_DIAGNOSTIC:
|
939 |
case SEND_DIAGNOSTIC:
|
940 |
cmd->xfer = buf[4] | (buf[3] << 8); |
941 |
break;
|
942 |
case READ_CD:
|
943 |
case READ_BUFFER:
|
944 |
case WRITE_BUFFER:
|
945 |
case SEND_CUE_SHEET:
|
946 |
cmd->xfer = buf[8] | (buf[7] << 8) | (buf[6] << 16); |
947 |
break;
|
948 |
case PERSISTENT_RESERVE_OUT:
|
949 |
cmd->xfer = ldl_be_p(&buf[5]) & 0xffffffffULL; |
950 |
break;
|
951 |
case ERASE_12:
|
952 |
if (dev->type == TYPE_ROM) {
|
953 |
/* MMC command GET PERFORMANCE. */
|
954 |
cmd->xfer = scsi_get_performance_length(buf[9] | (buf[8] << 8), |
955 |
buf[10], buf[1] & 0x1f); |
956 |
} |
957 |
break;
|
958 |
case MECHANISM_STATUS:
|
959 |
case READ_DVD_STRUCTURE:
|
960 |
case SEND_DVD_STRUCTURE:
|
961 |
case MAINTENANCE_OUT:
|
962 |
case MAINTENANCE_IN:
|
963 |
if (dev->type == TYPE_ROM) {
|
964 |
/* GPCMD_REPORT_KEY and GPCMD_SEND_KEY from multi media commands */
|
965 |
cmd->xfer = buf[9] | (buf[8] << 8); |
966 |
} |
967 |
break;
|
968 |
case ATA_PASSTHROUGH_12:
|
969 |
if (dev->type == TYPE_ROM) {
|
970 |
/* BLANK command of MMC */
|
971 |
cmd->xfer = 0;
|
972 |
} else {
|
973 |
cmd->xfer = ata_passthrough_12_xfer_size(dev, buf); |
974 |
} |
975 |
break;
|
976 |
case ATA_PASSTHROUGH_16:
|
977 |
cmd->xfer = ata_passthrough_16_xfer_size(dev, buf); |
978 |
break;
|
979 |
} |
980 |
return 0; |
981 |
} |
982 |
|
983 |
static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) |
984 |
{ |
985 |
switch (buf[0]) { |
986 |
/* stream commands */
|
987 |
case ERASE_12:
|
988 |
case ERASE_16:
|
989 |
cmd->xfer = 0;
|
990 |
break;
|
991 |
case READ_6:
|
992 |
case READ_REVERSE:
|
993 |
case RECOVER_BUFFERED_DATA:
|
994 |
case WRITE_6:
|
995 |
cmd->xfer = buf[4] | (buf[3] << 8) | (buf[2] << 16); |
996 |
if (buf[1] & 0x01) { /* fixed */ |
997 |
cmd->xfer *= dev->blocksize; |
998 |
} |
999 |
break;
|
1000 |
case READ_16:
|
1001 |
case READ_REVERSE_16:
|
1002 |
case VERIFY_16:
|
1003 |
case WRITE_16:
|
1004 |
cmd->xfer = buf[14] | (buf[13] << 8) | (buf[12] << 16); |
1005 |
if (buf[1] & 0x01) { /* fixed */ |
1006 |
cmd->xfer *= dev->blocksize; |
1007 |
} |
1008 |
break;
|
1009 |
case REWIND:
|
1010 |
case LOAD_UNLOAD:
|
1011 |
cmd->xfer = 0;
|
1012 |
break;
|
1013 |
case SPACE_16:
|
1014 |
cmd->xfer = buf[13] | (buf[12] << 8); |
1015 |
break;
|
1016 |
case READ_POSITION:
|
1017 |
switch (buf[1] & 0x1f) /* operation code */ { |
1018 |
case SHORT_FORM_BLOCK_ID:
|
1019 |
case SHORT_FORM_VENDOR_SPECIFIC:
|
1020 |
cmd->xfer = 20;
|
1021 |
break;
|
1022 |
case LONG_FORM:
|
1023 |
cmd->xfer = 32;
|
1024 |
break;
|
1025 |
case EXTENDED_FORM:
|
1026 |
cmd->xfer = buf[8] | (buf[7] << 8); |
1027 |
break;
|
1028 |
default:
|
1029 |
return -1; |
1030 |
} |
1031 |
|
1032 |
break;
|
1033 |
case FORMAT_UNIT:
|
1034 |
cmd->xfer = buf[4] | (buf[3] << 8); |
1035 |
break;
|
1036 |
/* generic commands */
|
1037 |
default:
|
1038 |
return scsi_req_length(cmd, dev, buf);
|
1039 |
} |
1040 |
return 0; |
1041 |
} |
1042 |
|
1043 |
static int scsi_req_medium_changer_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) |
1044 |
{ |
1045 |
switch (buf[0]) { |
1046 |
/* medium changer commands */
|
1047 |
case EXCHANGE_MEDIUM:
|
1048 |
case INITIALIZE_ELEMENT_STATUS:
|
1049 |
case INITIALIZE_ELEMENT_STATUS_WITH_RANGE:
|
1050 |
case MOVE_MEDIUM:
|
1051 |
case POSITION_TO_ELEMENT:
|
1052 |
cmd->xfer = 0;
|
1053 |
break;
|
1054 |
case READ_ELEMENT_STATUS:
|
1055 |
cmd->xfer = buf[9] | (buf[8] << 8) | (buf[7] << 16); |
1056 |
break;
|
1057 |
|
1058 |
/* generic commands */
|
1059 |
default:
|
1060 |
return scsi_req_length(cmd, dev, buf);
|
1061 |
} |
1062 |
return 0; |
1063 |
} |
1064 |
|
1065 |
|
1066 |
static void scsi_cmd_xfer_mode(SCSICommand *cmd) |
1067 |
{ |
1068 |
if (!cmd->xfer) {
|
1069 |
cmd->mode = SCSI_XFER_NONE; |
1070 |
return;
|
1071 |
} |
1072 |
switch (cmd->buf[0]) { |
1073 |
case WRITE_6:
|
1074 |
case WRITE_10:
|
1075 |
case WRITE_VERIFY_10:
|
1076 |
case WRITE_12:
|
1077 |
case WRITE_VERIFY_12:
|
1078 |
case WRITE_16:
|
1079 |
case WRITE_VERIFY_16:
|
1080 |
case COPY:
|
1081 |
case COPY_VERIFY:
|
1082 |
case COMPARE:
|
1083 |
case CHANGE_DEFINITION:
|
1084 |
case LOG_SELECT:
|
1085 |
case MODE_SELECT:
|
1086 |
case MODE_SELECT_10:
|
1087 |
case SEND_DIAGNOSTIC:
|
1088 |
case WRITE_BUFFER:
|
1089 |
case FORMAT_UNIT:
|
1090 |
case REASSIGN_BLOCKS:
|
1091 |
case SEARCH_EQUAL:
|
1092 |
case SEARCH_HIGH:
|
1093 |
case SEARCH_LOW:
|
1094 |
case UPDATE_BLOCK:
|
1095 |
case WRITE_LONG_10:
|
1096 |
case WRITE_SAME_10:
|
1097 |
case WRITE_SAME_16:
|
1098 |
case UNMAP:
|
1099 |
case SEARCH_HIGH_12:
|
1100 |
case SEARCH_EQUAL_12:
|
1101 |
case SEARCH_LOW_12:
|
1102 |
case MEDIUM_SCAN:
|
1103 |
case SEND_VOLUME_TAG:
|
1104 |
case SEND_CUE_SHEET:
|
1105 |
case SEND_DVD_STRUCTURE:
|
1106 |
case PERSISTENT_RESERVE_OUT:
|
1107 |
case MAINTENANCE_OUT:
|
1108 |
cmd->mode = SCSI_XFER_TO_DEV; |
1109 |
break;
|
1110 |
case ATA_PASSTHROUGH_12:
|
1111 |
case ATA_PASSTHROUGH_16:
|
1112 |
/* T_DIR */
|
1113 |
cmd->mode = (cmd->buf[2] & 0x8) ? |
1114 |
SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV; |
1115 |
break;
|
1116 |
default:
|
1117 |
cmd->mode = SCSI_XFER_FROM_DEV; |
1118 |
break;
|
1119 |
} |
1120 |
} |
1121 |
|
1122 |
static uint64_t scsi_cmd_lba(SCSICommand *cmd)
|
1123 |
{ |
1124 |
uint8_t *buf = cmd->buf; |
1125 |
uint64_t lba; |
1126 |
|
1127 |
switch (buf[0] >> 5) { |
1128 |
case 0: |
1129 |
lba = ldl_be_p(&buf[0]) & 0x1fffff; |
1130 |
break;
|
1131 |
case 1: |
1132 |
case 2: |
1133 |
case 5: |
1134 |
lba = ldl_be_p(&buf[2]) & 0xffffffffULL; |
1135 |
break;
|
1136 |
case 4: |
1137 |
lba = ldq_be_p(&buf[2]);
|
1138 |
break;
|
1139 |
default:
|
1140 |
lba = -1;
|
1141 |
|
1142 |
} |
1143 |
return lba;
|
1144 |
} |
1145 |
|
1146 |
int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
1147 |
{ |
1148 |
int rc;
|
1149 |
|
1150 |
switch (buf[0] >> 5) { |
1151 |
case 0: |
1152 |
cmd->len = 6;
|
1153 |
break;
|
1154 |
case 1: |
1155 |
case 2: |
1156 |
cmd->len = 10;
|
1157 |
break;
|
1158 |
case 4: |
1159 |
cmd->len = 16;
|
1160 |
break;
|
1161 |
case 5: |
1162 |
cmd->len = 12;
|
1163 |
break;
|
1164 |
default:
|
1165 |
return -1; |
1166 |
} |
1167 |
|
1168 |
switch (dev->type) {
|
1169 |
case TYPE_TAPE:
|
1170 |
rc = scsi_req_stream_length(cmd, dev, buf); |
1171 |
break;
|
1172 |
case TYPE_MEDIUM_CHANGER:
|
1173 |
rc = scsi_req_medium_changer_length(cmd, dev, buf); |
1174 |
break;
|
1175 |
default:
|
1176 |
rc = scsi_req_length(cmd, dev, buf); |
1177 |
break;
|
1178 |
} |
1179 |
|
1180 |
if (rc != 0) |
1181 |
return rc;
|
1182 |
|
1183 |
memcpy(cmd->buf, buf, cmd->len); |
1184 |
scsi_cmd_xfer_mode(cmd); |
1185 |
cmd->lba = scsi_cmd_lba(cmd); |
1186 |
return 0; |
1187 |
} |
1188 |
|
1189 |
void scsi_device_report_change(SCSIDevice *dev, SCSISense sense)
|
1190 |
{ |
1191 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); |
1192 |
|
1193 |
scsi_device_set_ua(dev, sense); |
1194 |
if (bus->info->change) {
|
1195 |
bus->info->change(bus, dev, sense); |
1196 |
} |
1197 |
} |
1198 |
|
1199 |
/*
|
1200 |
* Predefined sense codes
|
1201 |
*/
|
1202 |
|
1203 |
/* No sense data available */
|
1204 |
const struct SCSISense sense_code_NO_SENSE = { |
1205 |
.key = NO_SENSE , .asc = 0x00 , .ascq = 0x00 |
1206 |
}; |
1207 |
|
1208 |
/* LUN not ready, Manual intervention required */
|
1209 |
const struct SCSISense sense_code_LUN_NOT_READY = { |
1210 |
.key = NOT_READY, .asc = 0x04, .ascq = 0x03 |
1211 |
}; |
1212 |
|
1213 |
/* LUN not ready, Medium not present */
|
1214 |
const struct SCSISense sense_code_NO_MEDIUM = { |
1215 |
.key = NOT_READY, .asc = 0x3a, .ascq = 0x00 |
1216 |
}; |
1217 |
|
1218 |
/* LUN not ready, medium removal prevented */
|
1219 |
const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = { |
1220 |
.key = NOT_READY, .asc = 0x53, .ascq = 0x02 |
1221 |
}; |
1222 |
|
1223 |
/* Hardware error, internal target failure */
|
1224 |
const struct SCSISense sense_code_TARGET_FAILURE = { |
1225 |
.key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00 |
1226 |
}; |
1227 |
|
1228 |
/* Illegal request, invalid command operation code */
|
1229 |
const struct SCSISense sense_code_INVALID_OPCODE = { |
1230 |
.key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00 |
1231 |
}; |
1232 |
|
1233 |
/* Illegal request, LBA out of range */
|
1234 |
const struct SCSISense sense_code_LBA_OUT_OF_RANGE = { |
1235 |
.key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00 |
1236 |
}; |
1237 |
|
1238 |
/* Illegal request, Invalid field in CDB */
|
1239 |
const struct SCSISense sense_code_INVALID_FIELD = { |
1240 |
.key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00 |
1241 |
}; |
1242 |
|
1243 |
/* Illegal request, Invalid field in parameter list */
|
1244 |
const struct SCSISense sense_code_INVALID_PARAM = { |
1245 |
.key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00 |
1246 |
}; |
1247 |
|
1248 |
/* Illegal request, Parameter list length error */
|
1249 |
const struct SCSISense sense_code_INVALID_PARAM_LEN = { |
1250 |
.key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00 |
1251 |
}; |
1252 |
|
1253 |
/* Illegal request, LUN not supported */
|
1254 |
const struct SCSISense sense_code_LUN_NOT_SUPPORTED = { |
1255 |
.key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00 |
1256 |
}; |
1257 |
|
1258 |
/* Illegal request, Saving parameters not supported */
|
1259 |
const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = { |
1260 |
.key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00 |
1261 |
}; |
1262 |
|
1263 |
/* Illegal request, Incompatible medium installed */
|
1264 |
const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = { |
1265 |
.key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00 |
1266 |
}; |
1267 |
|
1268 |
/* Illegal request, medium removal prevented */
|
1269 |
const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = { |
1270 |
.key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02 |
1271 |
}; |
1272 |
|
1273 |
/* Command aborted, I/O process terminated */
|
1274 |
const struct SCSISense sense_code_IO_ERROR = { |
1275 |
.key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06 |
1276 |
}; |
1277 |
|
1278 |
/* Command aborted, I_T Nexus loss occurred */
|
1279 |
const struct SCSISense sense_code_I_T_NEXUS_LOSS = { |
1280 |
.key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07 |
1281 |
}; |
1282 |
|
1283 |
/* Command aborted, Logical Unit failure */
|
1284 |
const struct SCSISense sense_code_LUN_FAILURE = { |
1285 |
.key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01 |
1286 |
}; |
1287 |
|
1288 |
/* Unit attention, Capacity data has changed */
|
1289 |
const struct SCSISense sense_code_CAPACITY_CHANGED = { |
1290 |
.key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09 |
1291 |
}; |
1292 |
|
1293 |
/* Unit attention, Power on, reset or bus device reset occurred */
|
1294 |
const struct SCSISense sense_code_RESET = { |
1295 |
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00 |
1296 |
}; |
1297 |
|
1298 |
/* Unit attention, No medium */
|
1299 |
const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = { |
1300 |
.key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00 |
1301 |
}; |
1302 |
|
1303 |
/* Unit attention, Medium may have changed */
|
1304 |
const struct SCSISense sense_code_MEDIUM_CHANGED = { |
1305 |
.key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00 |
1306 |
}; |
1307 |
|
1308 |
/* Unit attention, Reported LUNs data has changed */
|
1309 |
const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = { |
1310 |
.key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e |
1311 |
}; |
1312 |
|
1313 |
/* Unit attention, Device internal reset */
|
1314 |
const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = { |
1315 |
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04 |
1316 |
}; |
1317 |
|
1318 |
/* Data Protection, Write Protected */
|
1319 |
const struct SCSISense sense_code_WRITE_PROTECTED = { |
1320 |
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00 |
1321 |
}; |
1322 |
|
1323 |
/*
|
1324 |
* scsi_build_sense
|
1325 |
*
|
1326 |
* Convert between fixed and descriptor sense buffers
|
1327 |
*/
|
1328 |
int scsi_build_sense(uint8_t *in_buf, int in_len, |
1329 |
uint8_t *buf, int len, bool fixed) |
1330 |
{ |
1331 |
bool fixed_in;
|
1332 |
SCSISense sense; |
1333 |
if (!fixed && len < 8) { |
1334 |
return 0; |
1335 |
} |
1336 |
|
1337 |
if (in_len == 0) { |
1338 |
sense.key = NO_SENSE; |
1339 |
sense.asc = 0;
|
1340 |
sense.ascq = 0;
|
1341 |
} else {
|
1342 |
fixed_in = (in_buf[0] & 2) == 0; |
1343 |
|
1344 |
if (fixed == fixed_in) {
|
1345 |
memcpy(buf, in_buf, MIN(len, in_len)); |
1346 |
return MIN(len, in_len);
|
1347 |
} |
1348 |
|
1349 |
if (fixed_in) {
|
1350 |
sense.key = in_buf[2];
|
1351 |
sense.asc = in_buf[12];
|
1352 |
sense.ascq = in_buf[13];
|
1353 |
} else {
|
1354 |
sense.key = in_buf[1];
|
1355 |
sense.asc = in_buf[2];
|
1356 |
sense.ascq = in_buf[3];
|
1357 |
} |
1358 |
} |
1359 |
|
1360 |
memset(buf, 0, len);
|
1361 |
if (fixed) {
|
1362 |
/* Return fixed format sense buffer */
|
1363 |
buf[0] = 0x70; |
1364 |
buf[2] = sense.key;
|
1365 |
buf[7] = 10; |
1366 |
buf[12] = sense.asc;
|
1367 |
buf[13] = sense.ascq;
|
1368 |
return MIN(len, 18); |
1369 |
} else {
|
1370 |
/* Return descriptor format sense buffer */
|
1371 |
buf[0] = 0x72; |
1372 |
buf[1] = sense.key;
|
1373 |
buf[2] = sense.asc;
|
1374 |
buf[3] = sense.ascq;
|
1375 |
return 8; |
1376 |
} |
1377 |
} |
1378 |
|
1379 |
static const char *scsi_command_name(uint8_t cmd) |
1380 |
{ |
1381 |
static const char *names[] = { |
1382 |
[ TEST_UNIT_READY ] = "TEST_UNIT_READY",
|
1383 |
[ REWIND ] = "REWIND",
|
1384 |
[ REQUEST_SENSE ] = "REQUEST_SENSE",
|
1385 |
[ FORMAT_UNIT ] = "FORMAT_UNIT",
|
1386 |
[ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
|
1387 |
[ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS",
|
1388 |
/* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */
|
1389 |
[ READ_6 ] = "READ_6",
|
1390 |
[ WRITE_6 ] = "WRITE_6",
|
1391 |
[ SET_CAPACITY ] = "SET_CAPACITY",
|
1392 |
[ READ_REVERSE ] = "READ_REVERSE",
|
1393 |
[ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
|
1394 |
[ SPACE ] = "SPACE",
|
1395 |
[ INQUIRY ] = "INQUIRY",
|
1396 |
[ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
|
1397 |
[ MAINTENANCE_IN ] = "MAINTENANCE_IN",
|
1398 |
[ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
|
1399 |
[ MODE_SELECT ] = "MODE_SELECT",
|
1400 |
[ RESERVE ] = "RESERVE",
|
1401 |
[ RELEASE ] = "RELEASE",
|
1402 |
[ COPY ] = "COPY",
|
1403 |
[ ERASE ] = "ERASE",
|
1404 |
[ MODE_SENSE ] = "MODE_SENSE",
|
1405 |
[ START_STOP ] = "START_STOP/LOAD_UNLOAD",
|
1406 |
/* LOAD_UNLOAD and START_STOP use the same operation code */
|
1407 |
[ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
|
1408 |
[ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
|
1409 |
[ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
|
1410 |
[ READ_CAPACITY_10 ] = "READ_CAPACITY_10",
|
1411 |
[ READ_10 ] = "READ_10",
|
1412 |
[ WRITE_10 ] = "WRITE_10",
|
1413 |
[ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT",
|
1414 |
/* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */
|
1415 |
[ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10",
|
1416 |
[ VERIFY_10 ] = "VERIFY_10",
|
1417 |
[ SEARCH_HIGH ] = "SEARCH_HIGH",
|
1418 |
[ SEARCH_EQUAL ] = "SEARCH_EQUAL",
|
1419 |
[ SEARCH_LOW ] = "SEARCH_LOW",
|
1420 |
[ SET_LIMITS ] = "SET_LIMITS",
|
1421 |
[ PRE_FETCH ] = "PRE_FETCH/READ_POSITION",
|
1422 |
/* READ_POSITION and PRE_FETCH use the same operation code */
|
1423 |
[ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
|
1424 |
[ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
|
1425 |
[ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE",
|
1426 |
/* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */
|
1427 |
[ MEDIUM_SCAN ] = "MEDIUM_SCAN",
|
1428 |
[ COMPARE ] = "COMPARE",
|
1429 |
[ COPY_VERIFY ] = "COPY_VERIFY",
|
1430 |
[ WRITE_BUFFER ] = "WRITE_BUFFER",
|
1431 |
[ READ_BUFFER ] = "READ_BUFFER",
|
1432 |
[ UPDATE_BLOCK ] = "UPDATE_BLOCK",
|
1433 |
[ READ_LONG_10 ] = "READ_LONG_10",
|
1434 |
[ WRITE_LONG_10 ] = "WRITE_LONG_10",
|
1435 |
[ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
|
1436 |
[ WRITE_SAME_10 ] = "WRITE_SAME_10",
|
1437 |
[ UNMAP ] = "UNMAP",
|
1438 |
[ READ_TOC ] = "READ_TOC",
|
1439 |
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
|
1440 |
[ SANITIZE ] = "SANITIZE",
|
1441 |
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
|
1442 |
[ LOG_SELECT ] = "LOG_SELECT",
|
1443 |
[ LOG_SENSE ] = "LOG_SENSE",
|
1444 |
[ MODE_SELECT_10 ] = "MODE_SELECT_10",
|
1445 |
[ RESERVE_10 ] = "RESERVE_10",
|
1446 |
[ RELEASE_10 ] = "RELEASE_10",
|
1447 |
[ MODE_SENSE_10 ] = "MODE_SENSE_10",
|
1448 |
[ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
|
1449 |
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
|
1450 |
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
|
1451 |
[ EXTENDED_COPY ] = "EXTENDED_COPY",
|
1452 |
[ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
|
1453 |
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
|
1454 |
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
|
1455 |
[ READ_16 ] = "READ_16",
|
1456 |
[ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE",
|
1457 |
[ WRITE_16 ] = "WRITE_16",
|
1458 |
[ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
|
1459 |
[ VERIFY_16 ] = "VERIFY_16",
|
1460 |
[ PRE_FETCH_16 ] = "PRE_FETCH_16",
|
1461 |
[ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
|
1462 |
/* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
|
1463 |
[ LOCATE_16 ] = "LOCATE_16",
|
1464 |
[ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16",
|
1465 |
/* ERASE_16 and WRITE_SAME_16 use the same operation code */
|
1466 |
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
|
1467 |
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
|
1468 |
[ REPORT_LUNS ] = "REPORT_LUNS",
|
1469 |
[ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12",
|
1470 |
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
|
1471 |
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
|
1472 |
[ READ_12 ] = "READ_12",
|
1473 |
[ WRITE_12 ] = "WRITE_12",
|
1474 |
[ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE",
|
1475 |
/* ERASE_12 and GET_PERFORMANCE use the same operation code */
|
1476 |
[ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
|
1477 |
[ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
|
1478 |
[ VERIFY_12 ] = "VERIFY_12",
|
1479 |
[ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
|
1480 |
[ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
|
1481 |
[ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
|
1482 |
[ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
|
1483 |
[ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING",
|
1484 |
/* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
|
1485 |
[ READ_CD ] = "READ_CD",
|
1486 |
[ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
|
1487 |
[ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE",
|
1488 |
[ RESERVE_TRACK ] = "RESERVE_TRACK",
|
1489 |
[ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
|
1490 |
[ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE",
|
1491 |
[ SET_CD_SPEED ] = "SET_CD_SPEED",
|
1492 |
[ SET_READ_AHEAD ] = "SET_READ_AHEAD",
|
1493 |
[ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE",
|
1494 |
[ MECHANISM_STATUS ] = "MECHANISM_STATUS",
|
1495 |
}; |
1496 |
|
1497 |
if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL) |
1498 |
return "*UNKNOWN*"; |
1499 |
return names[cmd];
|
1500 |
} |
1501 |
|
1502 |
SCSIRequest *scsi_req_ref(SCSIRequest *req) |
1503 |
{ |
1504 |
assert(req->refcount > 0);
|
1505 |
req->refcount++; |
1506 |
return req;
|
1507 |
} |
1508 |
|
1509 |
void scsi_req_unref(SCSIRequest *req)
|
1510 |
{ |
1511 |
assert(req->refcount > 0);
|
1512 |
if (--req->refcount == 0) { |
1513 |
BusState *qbus = req->dev->qdev.parent_bus; |
1514 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, qbus); |
1515 |
|
1516 |
if (bus->info->free_request && req->hba_private) {
|
1517 |
bus->info->free_request(bus, req->hba_private); |
1518 |
} |
1519 |
if (req->ops->free_req) {
|
1520 |
req->ops->free_req(req); |
1521 |
} |
1522 |
object_unref(OBJECT(req->dev)); |
1523 |
object_unref(OBJECT(qbus->parent)); |
1524 |
g_free(req); |
1525 |
} |
1526 |
} |
1527 |
|
1528 |
/* Tell the device that we finished processing this chunk of I/O. It
|
1529 |
will start the next chunk or complete the command. */
|
1530 |
void scsi_req_continue(SCSIRequest *req)
|
1531 |
{ |
1532 |
if (req->io_canceled) {
|
1533 |
trace_scsi_req_continue_canceled(req->dev->id, req->lun, req->tag); |
1534 |
return;
|
1535 |
} |
1536 |
trace_scsi_req_continue(req->dev->id, req->lun, req->tag); |
1537 |
if (req->cmd.mode == SCSI_XFER_TO_DEV) {
|
1538 |
req->ops->write_data(req); |
1539 |
} else {
|
1540 |
req->ops->read_data(req); |
1541 |
} |
1542 |
} |
1543 |
|
1544 |
/* Called by the devices when data is ready for the HBA. The HBA should
|
1545 |
start a DMA operation to read or fill the device's data buffer.
|
1546 |
Once it completes, calling scsi_req_continue will restart I/O. */
|
1547 |
void scsi_req_data(SCSIRequest *req, int len) |
1548 |
{ |
1549 |
uint8_t *buf; |
1550 |
if (req->io_canceled) {
|
1551 |
trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len); |
1552 |
return;
|
1553 |
} |
1554 |
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); |
1555 |
assert(req->cmd.mode != SCSI_XFER_NONE); |
1556 |
if (!req->sg) {
|
1557 |
req->resid -= len; |
1558 |
req->bus->info->transfer_data(req, len); |
1559 |
return;
|
1560 |
} |
1561 |
|
1562 |
/* If the device calls scsi_req_data and the HBA specified a
|
1563 |
* scatter/gather list, the transfer has to happen in a single
|
1564 |
* step. */
|
1565 |
assert(!req->dma_started); |
1566 |
req->dma_started = true;
|
1567 |
|
1568 |
buf = scsi_req_get_buf(req); |
1569 |
if (req->cmd.mode == SCSI_XFER_FROM_DEV) {
|
1570 |
req->resid = dma_buf_read(buf, len, req->sg); |
1571 |
} else {
|
1572 |
req->resid = dma_buf_write(buf, len, req->sg); |
1573 |
} |
1574 |
scsi_req_continue(req); |
1575 |
} |
1576 |
|
1577 |
void scsi_req_print(SCSIRequest *req)
|
1578 |
{ |
1579 |
FILE *fp = stderr; |
1580 |
int i;
|
1581 |
|
1582 |
fprintf(fp, "[%s id=%d] %s",
|
1583 |
req->dev->qdev.parent_bus->name, |
1584 |
req->dev->id, |
1585 |
scsi_command_name(req->cmd.buf[0]));
|
1586 |
for (i = 1; i < req->cmd.len; i++) { |
1587 |
fprintf(fp, " 0x%02x", req->cmd.buf[i]);
|
1588 |
} |
1589 |
switch (req->cmd.mode) {
|
1590 |
case SCSI_XFER_NONE:
|
1591 |
fprintf(fp, " - none\n");
|
1592 |
break;
|
1593 |
case SCSI_XFER_FROM_DEV:
|
1594 |
fprintf(fp, " - from-dev len=%zd\n", req->cmd.xfer);
|
1595 |
break;
|
1596 |
case SCSI_XFER_TO_DEV:
|
1597 |
fprintf(fp, " - to-dev len=%zd\n", req->cmd.xfer);
|
1598 |
break;
|
1599 |
default:
|
1600 |
fprintf(fp, " - Oops\n");
|
1601 |
break;
|
1602 |
} |
1603 |
} |
1604 |
|
1605 |
void scsi_req_complete(SCSIRequest *req, int status) |
1606 |
{ |
1607 |
assert(req->status == -1);
|
1608 |
req->status = status; |
1609 |
|
1610 |
assert(req->sense_len <= sizeof(req->sense));
|
1611 |
if (status == GOOD) {
|
1612 |
req->sense_len = 0;
|
1613 |
} |
1614 |
|
1615 |
if (req->sense_len) {
|
1616 |
memcpy(req->dev->sense, req->sense, req->sense_len); |
1617 |
req->dev->sense_len = req->sense_len; |
1618 |
req->dev->sense_is_ua = (req->ops == &reqops_unit_attention); |
1619 |
} else {
|
1620 |
req->dev->sense_len = 0;
|
1621 |
req->dev->sense_is_ua = false;
|
1622 |
} |
1623 |
|
1624 |
/*
|
1625 |
* Unit attention state is now stored in the device's sense buffer
|
1626 |
* if the HBA didn't do autosense. Clear the pending unit attention
|
1627 |
* flags.
|
1628 |
*/
|
1629 |
scsi_clear_unit_attention(req); |
1630 |
|
1631 |
scsi_req_ref(req); |
1632 |
scsi_req_dequeue(req); |
1633 |
req->bus->info->complete(req, req->status, req->resid); |
1634 |
scsi_req_unref(req); |
1635 |
} |
1636 |
|
1637 |
void scsi_req_cancel(SCSIRequest *req)
|
1638 |
{ |
1639 |
trace_scsi_req_cancel(req->dev->id, req->lun, req->tag); |
1640 |
if (!req->enqueued) {
|
1641 |
return;
|
1642 |
} |
1643 |
scsi_req_ref(req); |
1644 |
scsi_req_dequeue(req); |
1645 |
req->io_canceled = true;
|
1646 |
if (req->ops->cancel_io) {
|
1647 |
req->ops->cancel_io(req); |
1648 |
} |
1649 |
if (req->bus->info->cancel) {
|
1650 |
req->bus->info->cancel(req); |
1651 |
} |
1652 |
scsi_req_unref(req); |
1653 |
} |
1654 |
|
1655 |
void scsi_req_abort(SCSIRequest *req, int status) |
1656 |
{ |
1657 |
if (!req->enqueued) {
|
1658 |
return;
|
1659 |
} |
1660 |
scsi_req_ref(req); |
1661 |
scsi_req_dequeue(req); |
1662 |
req->io_canceled = true;
|
1663 |
if (req->ops->cancel_io) {
|
1664 |
req->ops->cancel_io(req); |
1665 |
} |
1666 |
scsi_req_complete(req, status); |
1667 |
scsi_req_unref(req); |
1668 |
} |
1669 |
|
1670 |
static int scsi_ua_precedence(SCSISense sense) |
1671 |
{ |
1672 |
if (sense.key != UNIT_ATTENTION) {
|
1673 |
return INT_MAX;
|
1674 |
} |
1675 |
if (sense.asc == 0x29 && sense.ascq == 0x04) { |
1676 |
/* DEVICE INTERNAL RESET goes with POWER ON OCCURRED */
|
1677 |
return 1; |
1678 |
} else if (sense.asc == 0x3F && sense.ascq == 0x01) { |
1679 |
/* MICROCODE HAS BEEN CHANGED goes with SCSI BUS RESET OCCURRED */
|
1680 |
return 2; |
1681 |
} else if (sense.asc == 0x29 && (sense.ascq == 0x05 || sense.ascq == 0x06)) { |
1682 |
/* These two go with "all others". */
|
1683 |
; |
1684 |
} else if (sense.asc == 0x29 && sense.ascq <= 0x07) { |
1685 |
/* POWER ON, RESET OR BUS DEVICE RESET OCCURRED = 0
|
1686 |
* POWER ON OCCURRED = 1
|
1687 |
* SCSI BUS RESET OCCURRED = 2
|
1688 |
* BUS DEVICE RESET FUNCTION OCCURRED = 3
|
1689 |
* I_T NEXUS LOSS OCCURRED = 7
|
1690 |
*/
|
1691 |
return sense.ascq;
|
1692 |
} else if (sense.asc == 0x2F && sense.ascq == 0x01) { |
1693 |
/* COMMANDS CLEARED BY POWER LOSS NOTIFICATION */
|
1694 |
return 8; |
1695 |
} |
1696 |
return (sense.asc << 8) | sense.ascq; |
1697 |
} |
1698 |
|
1699 |
void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense)
|
1700 |
{ |
1701 |
int prec1, prec2;
|
1702 |
if (sense.key != UNIT_ATTENTION) {
|
1703 |
return;
|
1704 |
} |
1705 |
trace_scsi_device_set_ua(sdev->id, sdev->lun, sense.key, |
1706 |
sense.asc, sense.ascq); |
1707 |
|
1708 |
/*
|
1709 |
* Override a pre-existing unit attention condition, except for a more
|
1710 |
* important reset condition.
|
1711 |
*/
|
1712 |
prec1 = scsi_ua_precedence(sdev->unit_attention); |
1713 |
prec2 = scsi_ua_precedence(sense); |
1714 |
if (prec2 < prec1) {
|
1715 |
sdev->unit_attention = sense; |
1716 |
} |
1717 |
} |
1718 |
|
1719 |
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
|
1720 |
{ |
1721 |
SCSIRequest *req; |
1722 |
|
1723 |
while (!QTAILQ_EMPTY(&sdev->requests)) {
|
1724 |
req = QTAILQ_FIRST(&sdev->requests); |
1725 |
scsi_req_cancel(req); |
1726 |
} |
1727 |
|
1728 |
scsi_device_set_ua(sdev, sense); |
1729 |
} |
1730 |
|
1731 |
static char *scsibus_get_dev_path(DeviceState *dev) |
1732 |
{ |
1733 |
SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev); |
1734 |
DeviceState *hba = dev->parent_bus->parent; |
1735 |
char *id;
|
1736 |
char *path;
|
1737 |
|
1738 |
id = qdev_get_dev_path(hba); |
1739 |
if (id) {
|
1740 |
path = g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun);
|
1741 |
} else {
|
1742 |
path = g_strdup_printf("%d:%d:%d", d->channel, d->id, d->lun);
|
1743 |
} |
1744 |
g_free(id); |
1745 |
return path;
|
1746 |
} |
1747 |
|
1748 |
static char *scsibus_get_fw_dev_path(DeviceState *dev) |
1749 |
{ |
1750 |
SCSIDevice *d = SCSI_DEVICE(dev); |
1751 |
return g_strdup_printf("channel@%x/%s@%x,%x", d->channel, |
1752 |
qdev_fw_name(dev), d->id, d->lun); |
1753 |
} |
1754 |
|
1755 |
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) |
1756 |
{ |
1757 |
BusChild *kid; |
1758 |
SCSIDevice *target_dev = NULL;
|
1759 |
|
1760 |
QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) { |
1761 |
DeviceState *qdev = kid->child; |
1762 |
SCSIDevice *dev = SCSI_DEVICE(qdev); |
1763 |
|
1764 |
if (dev->channel == channel && dev->id == id) {
|
1765 |
if (dev->lun == lun) {
|
1766 |
return dev;
|
1767 |
} |
1768 |
target_dev = dev; |
1769 |
} |
1770 |
} |
1771 |
return target_dev;
|
1772 |
} |
1773 |
|
1774 |
/* SCSI request list. For simplicity, pv points to the whole device */
|
1775 |
|
1776 |
static void put_scsi_requests(QEMUFile *f, void *pv, size_t size) |
1777 |
{ |
1778 |
SCSIDevice *s = pv; |
1779 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus); |
1780 |
SCSIRequest *req; |
1781 |
|
1782 |
QTAILQ_FOREACH(req, &s->requests, next) { |
1783 |
assert(!req->io_canceled); |
1784 |
assert(req->status == -1);
|
1785 |
assert(req->enqueued); |
1786 |
|
1787 |
qemu_put_sbyte(f, req->retry ? 1 : 2); |
1788 |
qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
|
1789 |
qemu_put_be32s(f, &req->tag); |
1790 |
qemu_put_be32s(f, &req->lun); |
1791 |
if (bus->info->save_request) {
|
1792 |
bus->info->save_request(f, req); |
1793 |
} |
1794 |
if (req->ops->save_request) {
|
1795 |
req->ops->save_request(f, req); |
1796 |
} |
1797 |
} |
1798 |
qemu_put_sbyte(f, 0);
|
1799 |
} |
1800 |
|
1801 |
static int get_scsi_requests(QEMUFile *f, void *pv, size_t size) |
1802 |
{ |
1803 |
SCSIDevice *s = pv; |
1804 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus); |
1805 |
int8_t sbyte; |
1806 |
|
1807 |
while ((sbyte = qemu_get_sbyte(f)) > 0) { |
1808 |
uint8_t buf[SCSI_CMD_BUF_SIZE]; |
1809 |
uint32_t tag; |
1810 |
uint32_t lun; |
1811 |
SCSIRequest *req; |
1812 |
|
1813 |
qemu_get_buffer(f, buf, sizeof(buf));
|
1814 |
qemu_get_be32s(f, &tag); |
1815 |
qemu_get_be32s(f, &lun); |
1816 |
req = scsi_req_new(s, tag, lun, buf, NULL);
|
1817 |
req->retry = (sbyte == 1);
|
1818 |
if (bus->info->load_request) {
|
1819 |
req->hba_private = bus->info->load_request(f, req); |
1820 |
} |
1821 |
if (req->ops->load_request) {
|
1822 |
req->ops->load_request(f, req); |
1823 |
} |
1824 |
|
1825 |
/* Just restart it later. */
|
1826 |
scsi_req_enqueue_internal(req); |
1827 |
|
1828 |
/* At this point, the request will be kept alive by the reference
|
1829 |
* added by scsi_req_enqueue_internal, so we can release our reference.
|
1830 |
* The HBA of course will add its own reference in the load_request
|
1831 |
* callback if it needs to hold on the SCSIRequest.
|
1832 |
*/
|
1833 |
scsi_req_unref(req); |
1834 |
} |
1835 |
|
1836 |
return 0; |
1837 |
} |
1838 |
|
1839 |
static int scsi_qdev_unplug(DeviceState *qdev) |
1840 |
{ |
1841 |
SCSIDevice *dev = SCSI_DEVICE(qdev); |
1842 |
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); |
1843 |
|
1844 |
if (bus->info->hot_unplug) {
|
1845 |
bus->info->hot_unplug(bus, dev); |
1846 |
} |
1847 |
return qdev_simple_unplug_cb(qdev);
|
1848 |
} |
1849 |
|
1850 |
static const VMStateInfo vmstate_info_scsi_requests = { |
1851 |
.name = "scsi-requests",
|
1852 |
.get = get_scsi_requests, |
1853 |
.put = put_scsi_requests, |
1854 |
}; |
1855 |
|
1856 |
const VMStateDescription vmstate_scsi_device = {
|
1857 |
.name = "SCSIDevice",
|
1858 |
.version_id = 1,
|
1859 |
.minimum_version_id = 1,
|
1860 |
.minimum_version_id_old = 1,
|
1861 |
.fields = (VMStateField[]) { |
1862 |
VMSTATE_UINT8(unit_attention.key, SCSIDevice), |
1863 |
VMSTATE_UINT8(unit_attention.asc, SCSIDevice), |
1864 |
VMSTATE_UINT8(unit_attention.ascq, SCSIDevice), |
1865 |
VMSTATE_BOOL(sense_is_ua, SCSIDevice), |
1866 |
VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE), |
1867 |
VMSTATE_UINT32(sense_len, SCSIDevice), |
1868 |
{ |
1869 |
.name = "requests",
|
1870 |
.version_id = 0,
|
1871 |
.field_exists = NULL,
|
1872 |
.size = 0, /* ouch */ |
1873 |
.info = &vmstate_info_scsi_requests, |
1874 |
.flags = VMS_SINGLE, |
1875 |
.offset = 0,
|
1876 |
}, |
1877 |
VMSTATE_END_OF_LIST() |
1878 |
} |
1879 |
}; |
1880 |
|
1881 |
static void scsi_device_class_init(ObjectClass *klass, void *data) |
1882 |
{ |
1883 |
DeviceClass *k = DEVICE_CLASS(klass); |
1884 |
set_bit(DEVICE_CATEGORY_STORAGE, k->categories); |
1885 |
k->bus_type = TYPE_SCSI_BUS; |
1886 |
k->init = scsi_qdev_init; |
1887 |
k->unplug = scsi_qdev_unplug; |
1888 |
k->exit = scsi_qdev_exit; |
1889 |
k->props = scsi_props; |
1890 |
} |
1891 |
|
1892 |
static const TypeInfo scsi_device_type_info = { |
1893 |
.name = TYPE_SCSI_DEVICE, |
1894 |
.parent = TYPE_DEVICE, |
1895 |
.instance_size = sizeof(SCSIDevice),
|
1896 |
.abstract = true,
|
1897 |
.class_size = sizeof(SCSIDeviceClass),
|
1898 |
.class_init = scsi_device_class_init, |
1899 |
}; |
1900 |
|
1901 |
static void scsi_register_types(void) |
1902 |
{ |
1903 |
type_register_static(&scsi_bus_info); |
1904 |
type_register_static(&scsi_device_type_info); |
1905 |
} |
1906 |
|
1907 |
type_init(scsi_register_types) |