]> git.proxmox.com Git - qemu.git/blame - hw/scsi-bus.c
qdev: switch children device list to QTAILQ
[qemu.git] / hw / scsi-bus.c
CommitLineData
d52affa7 1#include "hw.h"
2f792016 2#include "qemu-error.h"
43b443b6 3#include "scsi.h"
2ec749cb 4#include "scsi-defs.h"
d52affa7 5#include "qdev.h"
2446333c 6#include "blockdev.h"
5138efec 7#include "trace.h"
d52affa7 8
db07c0f8 9static char *scsibus_get_fw_dev_path(DeviceState *dev);
afa46c46 10static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
b45ef674
PB
11static int scsi_build_sense(uint8_t *in_buf, int in_len,
12 uint8_t *buf, int len, bool fixed);
db07c0f8 13
d52affa7
GH
14static struct BusInfo scsi_bus_info = {
15 .name = "SCSI",
16 .size = sizeof(SCSIBus),
db07c0f8 17 .get_fw_dev_path = scsibus_get_fw_dev_path,
d52affa7
GH
18 .props = (Property[]) {
19 DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
87dcd1b2 20 DEFINE_PROP_UINT32("lun", SCSIDevice, lun, 0),
d52affa7
GH
21 DEFINE_PROP_END_OF_LIST(),
22 },
23};
24static int next_scsi_bus;
25
26/* Create a scsi bus, and attach devices to it. */
afd4030c 27void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
d52affa7 28{
ca9c39fa 29 qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
d52affa7 30 bus->busnr = next_scsi_bus++;
afd4030c 31 bus->info = info;
cb23117b 32 bus->qbus.allow_hotplug = 1;
d52affa7
GH
33}
34
35static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
36{
37 SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
38 SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
39 SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
01985dcf 40 int rc = -1;
d52affa7
GH
41
42 if (dev->id == -1) {
afd4030c 43 for (dev->id = 0; dev->id < bus->info->ndev; dev->id++) {
d52affa7
GH
44 if (bus->devs[dev->id] == NULL)
45 break;
46 }
47 }
afd4030c 48 if (dev->id >= bus->info->ndev) {
1ecda02b 49 error_report("bad scsi device id: %d", dev->id);
d52affa7
GH
50 goto err;
51 }
52
53 if (bus->devs[dev->id]) {
01985dcf 54 qdev_free(&bus->devs[dev->id]->qdev);
d52affa7
GH
55 }
56 bus->devs[dev->id] = dev;
57
58 dev->info = info;
9af99d98 59 QTAILQ_INIT(&dev->requests);
01985dcf
GH
60 rc = dev->info->init(dev);
61 if (rc != 0) {
62 bus->devs[dev->id] = NULL;
63 }
d52affa7
GH
64
65err:
01985dcf
GH
66 return rc;
67}
68
69static int scsi_qdev_exit(DeviceState *qdev)
70{
71 SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
72 SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
73
74 assert(bus->devs[dev->id] != NULL);
75 if (bus->devs[dev->id]->info->destroy) {
76 bus->devs[dev->id]->info->destroy(bus->devs[dev->id]);
77 }
78 bus->devs[dev->id] = NULL;
79 return 0;
d52affa7
GH
80}
81
82void scsi_qdev_register(SCSIDeviceInfo *info)
83{
84 info->qdev.bus_info = &scsi_bus_info;
85 info->qdev.init = scsi_qdev_init;
cb23117b 86 info->qdev.unplug = qdev_simple_unplug_cb;
01985dcf 87 info->qdev.exit = scsi_qdev_exit;
d52affa7
GH
88 qdev_register(&info->qdev);
89}
90
91/* handle legacy '-drive if=scsi,...' cmd line args */
2d1fd261
SH
92SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
93 int unit, bool removable)
d52affa7
GH
94{
95 const char *driver;
96 DeviceState *dev;
97
f8b6cc00 98 driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
d52affa7
GH
99 dev = qdev_create(&bus->qbus, driver);
100 qdev_prop_set_uint32(dev, "scsi-id", unit);
2d1fd261
SH
101 if (qdev_prop_exists(dev, "removable")) {
102 qdev_prop_set_bit(dev, "removable", removable);
103 }
18846dee
MA
104 if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
105 qdev_free(dev);
106 return NULL;
107 }
33e66b86
MA
108 if (qdev_init(dev) < 0)
109 return NULL;
d52affa7
GH
110 return DO_UPCAST(SCSIDevice, qdev, dev);
111}
112
fa66b909 113int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
d52affa7 114{
42e766a2 115 Location loc;
d52affa7 116 DriveInfo *dinfo;
fa66b909 117 int res = 0, unit;
d52affa7 118
42e766a2 119 loc_push_none(&loc);
afd4030c 120 for (unit = 0; unit < bus->info->ndev; unit++) {
d52affa7
GH
121 dinfo = drive_get(IF_SCSI, bus->busnr, unit);
122 if (dinfo == NULL) {
123 continue;
124 }
42e766a2 125 qemu_opts_loc_restore(dinfo->opts);
2d1fd261 126 if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) {
fa66b909
MA
127 res = -1;
128 break;
129 }
d52affa7 130 }
42e766a2 131 loc_pop(&loc);
fa66b909 132 return res;
d52affa7 133}
89b08ae1 134
afa46c46
PB
135/* SCSIReqOps implementation for invalid commands. */
136
137static int32_t scsi_invalid_command(SCSIRequest *req, uint8_t *buf)
138{
139 scsi_req_build_sense(req, SENSE_CODE(INVALID_OPCODE));
140 scsi_req_complete(req, CHECK_CONDITION);
141 return 0;
142}
143
144struct SCSIReqOps reqops_invalid_opcode = {
145 .size = sizeof(SCSIRequest),
146 .send_command = scsi_invalid_command
147};
148
6dc06f08
PB
149/* SCSIReqOps implementation for unit attention conditions. */
150
151static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
152{
153 if (req->dev && req->dev->unit_attention.key == UNIT_ATTENTION) {
154 scsi_req_build_sense(req, req->dev->unit_attention);
155 } else if (req->bus->unit_attention.key == UNIT_ATTENTION) {
156 scsi_req_build_sense(req, req->bus->unit_attention);
157 }
158 scsi_req_complete(req, CHECK_CONDITION);
159 return 0;
160}
161
162struct SCSIReqOps reqops_unit_attention = {
163 .size = sizeof(SCSIRequest),
164 .send_command = scsi_unit_attention
165};
166
fdaef069
PB
167/* SCSIReqOps implementation for REPORT LUNS and for commands sent to
168 an invalid LUN. */
169
170typedef struct SCSITargetReq SCSITargetReq;
171
172struct SCSITargetReq {
173 SCSIRequest req;
174 int len;
175 uint8_t buf[64];
176};
177
178static void store_lun(uint8_t *outbuf, int lun)
179{
180 if (lun < 256) {
181 outbuf[1] = lun;
182 return;
183 }
184 outbuf[1] = (lun & 255);
185 outbuf[0] = (lun >> 8) | 0x40;
186}
187
188static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
189{
190 int len;
191 if (r->req.cmd.xfer < 16) {
192 return false;
193 }
194 if (r->req.cmd.buf[2] > 2) {
195 return false;
196 }
197 len = MIN(sizeof r->buf, r->req.cmd.xfer);
198 memset(r->buf, 0, len);
199 if (r->req.dev->lun != 0) {
200 r->buf[3] = 16;
201 r->len = 24;
202 store_lun(&r->buf[16], r->req.dev->lun);
203 } else {
204 r->buf[3] = 8;
205 r->len = 16;
206 }
207 return true;
208}
209
210static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
211{
212 assert(r->req.dev->lun != r->req.lun);
213 if (r->req.cmd.buf[1] & 0x2) {
214 /* Command support data - optional, not implemented */
215 return false;
216 }
217
218 if (r->req.cmd.buf[1] & 0x1) {
219 /* Vital product data */
220 uint8_t page_code = r->req.cmd.buf[2];
221 if (r->req.cmd.xfer < 4) {
222 return false;
223 }
224
225 r->buf[r->len++] = page_code ; /* this page */
226 r->buf[r->len++] = 0x00;
227
228 switch (page_code) {
229 case 0x00: /* Supported page codes, mandatory */
230 {
231 int pages;
232 pages = r->len++;
233 r->buf[r->len++] = 0x00; /* list of supported pages (this page) */
234 r->buf[pages] = r->len - pages - 1; /* number of pages */
235 break;
236 }
237 default:
238 return false;
239 }
240 /* done with EVPD */
241 assert(r->len < sizeof(r->buf));
242 r->len = MIN(r->req.cmd.xfer, r->len);
243 return true;
244 }
245
246 /* Standard INQUIRY data */
247 if (r->req.cmd.buf[2] != 0) {
248 return false;
249 }
250
251 /* PAGE CODE == 0 */
252 if (r->req.cmd.xfer < 5) {
253 return -1;
254 }
255
256 r->len = MIN(r->req.cmd.xfer, 36);
257 memset(r->buf, 0, r->len);
258 if (r->req.lun != 0) {
259 r->buf[0] = TYPE_NO_LUN;
260 } else {
261 r->buf[0] = TYPE_NOT_PRESENT | TYPE_INACTIVE;
262 r->buf[2] = 5; /* Version */
263 r->buf[3] = 2 | 0x10; /* HiSup, response data format */
264 r->buf[4] = r->len - 5; /* Additional Length = (Len - 1) - 4 */
afd4030c 265 r->buf[7] = 0x10 | (r->req.bus->info->tcq ? 0x02 : 0); /* Sync, TCQ. */
fdaef069
PB
266 memcpy(&r->buf[8], "QEMU ", 8);
267 memcpy(&r->buf[16], "QEMU TARGET ", 16);
268 strncpy((char *) &r->buf[32], QEMU_VERSION, 4);
269 }
270 return true;
271}
272
273static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
274{
275 SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
276
277 switch (buf[0]) {
278 case REPORT_LUNS:
279 if (!scsi_target_emulate_report_luns(r)) {
280 goto illegal_request;
281 }
282 break;
283 case INQUIRY:
284 if (!scsi_target_emulate_inquiry(r)) {
285 goto illegal_request;
286 }
287 break;
739df215
PB
288 case REQUEST_SENSE:
289 if (req->cmd.xfer < 4) {
290 goto illegal_request;
291 }
8b2a04ee
PB
292 r->len = scsi_device_get_sense(r->req.dev, r->buf,
293 MIN(req->cmd.xfer, sizeof r->buf),
739df215 294 (req->cmd.buf[1] & 1) == 0);
3653d8c4
PB
295 if (r->req.dev->sense_is_ua) {
296 if (r->req.dev->info->unit_attention_reported) {
297 r->req.dev->info->unit_attention_reported(req->dev);
298 }
299 r->req.dev->sense_len = 0;
300 r->req.dev->sense_is_ua = false;
301 }
739df215 302 break;
fdaef069
PB
303 default:
304 scsi_req_build_sense(req, SENSE_CODE(LUN_NOT_SUPPORTED));
305 scsi_req_complete(req, CHECK_CONDITION);
306 return 0;
307 illegal_request:
308 scsi_req_build_sense(req, SENSE_CODE(INVALID_FIELD));
309 scsi_req_complete(req, CHECK_CONDITION);
310 return 0;
311 }
312
313 if (!r->len) {
314 scsi_req_complete(req, GOOD);
315 }
316 return r->len;
317}
318
319static void scsi_target_read_data(SCSIRequest *req)
320{
321 SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
322 uint32_t n;
323
324 n = r->len;
325 if (n > 0) {
326 r->len = 0;
327 scsi_req_data(&r->req, n);
328 } else {
329 scsi_req_complete(&r->req, GOOD);
330 }
331}
332
333static uint8_t *scsi_target_get_buf(SCSIRequest *req)
334{
335 SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
336
337 return r->buf;
338}
339
340struct SCSIReqOps reqops_target_command = {
341 .size = sizeof(SCSITargetReq),
342 .send_command = scsi_target_send_command,
343 .read_data = scsi_target_read_data,
344 .get_buf = scsi_target_get_buf,
345};
346
347
8dbd4574 348SCSIRequest *scsi_req_alloc(SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag,
c5bf71a9 349 uint32_t lun, void *hba_private)
89b08ae1
GH
350{
351 SCSIRequest *req;
352
7267c094 353 req = g_malloc0(reqops->size);
5c6c0e51 354 req->refcount = 1;
89b08ae1
GH
355 req->bus = scsi_bus_from_device(d);
356 req->dev = d;
357 req->tag = tag;
358 req->lun = lun;
c5bf71a9 359 req->hba_private = hba_private;
ed3a34a3 360 req->status = -1;
b45ef674 361 req->sense_len = 0;
8dbd4574 362 req->ops = reqops;
5138efec 363 trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
89b08ae1
GH
364 return req;
365}
366
c5bf71a9 367SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
c39ce112 368 uint8_t *buf, void *hba_private)
43a2b339 369{
6dc06f08 370 SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
c39ce112 371 SCSIRequest *req;
afa46c46
PB
372 SCSICommand cmd;
373
374 if (scsi_req_parse(&cmd, d, buf) != 0) {
375 trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
376 req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
377 } else {
378 trace_scsi_req_parsed(d->id, lun, tag, buf[0],
379 cmd.mode, cmd.xfer);
3b6ffe50 380 if (cmd.lba != -1) {
afa46c46
PB
381 trace_scsi_req_parsed_lba(d->id, lun, tag, buf[0],
382 cmd.lba);
383 }
fdaef069 384
6dc06f08
PB
385 if ((d->unit_attention.key == UNIT_ATTENTION ||
386 bus->unit_attention.key == UNIT_ATTENTION) &&
387 (buf[0] != INQUIRY &&
388 buf[0] != REPORT_LUNS &&
389 buf[0] != GET_CONFIGURATION &&
3653d8c4
PB
390 buf[0] != GET_EVENT_STATUS_NOTIFICATION &&
391
392 /*
393 * If we already have a pending unit attention condition,
394 * report this one before triggering another one.
395 */
396 !(buf[0] == REQUEST_SENSE && d->sense_is_ua))) {
6dc06f08
PB
397 req = scsi_req_alloc(&reqops_unit_attention, d, tag, lun,
398 hba_private);
399 } else if (lun != d->lun ||
739df215
PB
400 buf[0] == REPORT_LUNS ||
401 buf[0] == REQUEST_SENSE) {
fdaef069
PB
402 req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
403 hba_private);
404 } else {
405 req = d->info->alloc_req(d, tag, lun, hba_private);
406 }
afa46c46
PB
407 }
408
409 req->cmd = cmd;
98254542
PB
410 switch (buf[0]) {
411 case INQUIRY:
412 trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]);
413 break;
414 case TEST_UNIT_READY:
415 trace_scsi_test_unit_ready(d->id, lun, tag);
416 break;
417 case REPORT_LUNS:
418 trace_scsi_report_luns(d->id, lun, tag);
419 break;
420 case REQUEST_SENSE:
421 trace_scsi_request_sense(d->id, lun, tag);
422 break;
423 default:
424 break;
425 }
426
c39ce112 427 return req;
43a2b339
PB
428}
429
0c34459b
PB
430uint8_t *scsi_req_get_buf(SCSIRequest *req)
431{
12010e7b 432 return req->ops->get_buf(req);
0c34459b
PB
433}
434
6dc06f08
PB
435static void scsi_clear_unit_attention(SCSIRequest *req)
436{
437 SCSISense *ua;
438 if (req->dev->unit_attention.key != UNIT_ATTENTION &&
439 req->bus->unit_attention.key != UNIT_ATTENTION) {
440 return;
441 }
442
443 /*
444 * If an INQUIRY command enters the enabled command state,
445 * the device server shall [not] clear any unit attention condition;
446 * See also MMC-6, paragraphs 6.5 and 6.6.2.
447 */
448 if (req->cmd.buf[0] == INQUIRY ||
449 req->cmd.buf[0] == GET_CONFIGURATION ||
450 req->cmd.buf[0] == GET_EVENT_STATUS_NOTIFICATION) {
451 return;
452 }
453
454 if (req->dev->unit_attention.key == UNIT_ATTENTION) {
455 ua = &req->dev->unit_attention;
456 } else {
457 ua = &req->bus->unit_attention;
458 }
459
460 /*
461 * If a REPORT LUNS command enters the enabled command state, [...]
462 * the device server shall clear any pending unit attention condition
463 * with an additional sense code of REPORTED LUNS DATA HAS CHANGED.
464 */
465 if (req->cmd.buf[0] == REPORT_LUNS &&
466 !(ua->asc == SENSE_CODE(REPORTED_LUNS_CHANGED).asc &&
467 ua->ascq == SENSE_CODE(REPORTED_LUNS_CHANGED).ascq)) {
468 return;
469 }
470
471 *ua = SENSE_CODE(NO_SENSE);
472}
473
74382217
HR
474int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
475{
6dc06f08
PB
476 int ret;
477
b45ef674
PB
478 assert(len >= 14);
479 if (!req->sense_len) {
74382217
HR
480 return 0;
481 }
6dc06f08
PB
482
483 ret = scsi_build_sense(req->sense, req->sense_len, buf, len, true);
484
485 /*
486 * FIXME: clearing unit attention conditions upon autosense should be done
487 * only if the UA_INTLCK_CTRL field in the Control mode page is set to 00b
488 * (SAM-5, 5.14).
489 *
490 * We assume UA_INTLCK_CTRL to be 00b for HBAs that support autosense, and
491 * 10b for HBAs that do not support it (do not call scsi_req_get_sense).
3653d8c4 492 * Here we handle unit attention clearing for UA_INTLCK_CTRL == 00b.
6dc06f08 493 */
3653d8c4
PB
494 if (req->dev->sense_is_ua) {
495 if (req->dev->info->unit_attention_reported) {
496 req->dev->info->unit_attention_reported(req->dev);
497 }
498 req->dev->sense_len = 0;
499 req->dev->sense_is_ua = false;
500 }
6dc06f08 501 return ret;
b45ef674
PB
502}
503
504int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed)
505{
506 return scsi_build_sense(dev->sense, dev->sense_len, buf, len, fixed);
507}
508
509void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
510{
511 trace_scsi_req_build_sense(req->dev->id, req->lun, req->tag,
512 sense.key, sense.asc, sense.ascq);
513 memset(req->sense, 0, 18);
514 req->sense[0] = 0xf0;
515 req->sense[2] = sense.key;
eae31cb9 516 req->sense[7] = 10;
b45ef674
PB
517 req->sense[12] = sense.asc;
518 req->sense[13] = sense.ascq;
519 req->sense_len = 18;
74382217
HR
520}
521
c39ce112 522int32_t scsi_req_enqueue(SCSIRequest *req)
89b08ae1 523{
fc4f0754
PB
524 int32_t rc;
525
5c6c0e51
HR
526 assert(!req->enqueued);
527 scsi_req_ref(req);
528 req->enqueued = true;
529 QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
fc4f0754
PB
530
531 scsi_req_ref(req);
c39ce112 532 rc = req->ops->send_command(req, req->cmd.buf);
fc4f0754
PB
533 scsi_req_unref(req);
534 return rc;
89b08ae1
GH
535}
536
a1f0cce2 537static void scsi_req_dequeue(SCSIRequest *req)
e8637c90 538{
5138efec 539 trace_scsi_req_dequeue(req->dev->id, req->lun, req->tag);
e8637c90
JK
540 if (req->enqueued) {
541 QTAILQ_REMOVE(&req->dev->requests, req, next);
542 req->enqueued = false;
ad2d30f7 543 scsi_req_unref(req);
e8637c90
JK
544 }
545}
546
2599aece 547static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
2ec749cb 548{
2599aece 549 switch (buf[0] >> 5) {
2ec749cb 550 case 0:
2599aece
PB
551 cmd->xfer = buf[4];
552 cmd->len = 6;
2ec749cb 553 /* length 0 means 256 blocks */
2599aece
PB
554 if (cmd->xfer == 0) {
555 cmd->xfer = 256;
556 }
2ec749cb
GH
557 break;
558 case 1:
559 case 2:
bd5da232 560 cmd->xfer = lduw_be_p(&buf[7]);
2599aece 561 cmd->len = 10;
2ec749cb
GH
562 break;
563 case 4:
bd5da232 564 cmd->xfer = ldl_be_p(&buf[10]);
2599aece 565 cmd->len = 16;
2ec749cb
GH
566 break;
567 case 5:
bd5da232 568 cmd->xfer = ldl_be_p(&buf[6]);
2599aece 569 cmd->len = 12;
2ec749cb
GH
570 break;
571 default:
572 return -1;
573 }
574
2599aece 575 switch (buf[0]) {
2ec749cb 576 case TEST_UNIT_READY:
5e30a07d 577 case REWIND:
2ec749cb
GH
578 case START_STOP:
579 case SEEK_6:
580 case WRITE_FILEMARKS:
581 case SPACE:
a5e3d9ef
BK
582 case RESERVE:
583 case RELEASE:
2ec749cb
GH
584 case ERASE:
585 case ALLOW_MEDIUM_REMOVAL:
5e30a07d 586 case VERIFY_10:
2ec749cb
GH
587 case SEEK_10:
588 case SYNCHRONIZE_CACHE:
589 case LOCK_UNLOCK_CACHE:
590 case LOAD_UNLOAD:
591 case SET_CD_SPEED:
592 case SET_LIMITS:
5e30a07d 593 case WRITE_LONG_10:
2ec749cb
GH
594 case MOVE_MEDIUM:
595 case UPDATE_BLOCK:
2599aece 596 cmd->xfer = 0;
2ec749cb
GH
597 break;
598 case MODE_SENSE:
599 break;
5e30a07d 600 case WRITE_SAME_10:
2599aece 601 cmd->xfer = 1;
2ec749cb 602 break;
5e30a07d 603 case READ_CAPACITY_10:
2599aece 604 cmd->xfer = 8;
2ec749cb
GH
605 break;
606 case READ_BLOCK_LIMITS:
2599aece 607 cmd->xfer = 6;
2ec749cb
GH
608 break;
609 case READ_POSITION:
2599aece 610 cmd->xfer = 20;
2ec749cb
GH
611 break;
612 case SEND_VOLUME_TAG:
2599aece 613 cmd->xfer *= 40;
2ec749cb
GH
614 break;
615 case MEDIUM_SCAN:
2599aece 616 cmd->xfer *= 8;
2ec749cb
GH
617 break;
618 case WRITE_10:
5e30a07d 619 case WRITE_VERIFY_10:
2ec749cb
GH
620 case WRITE_6:
621 case WRITE_12:
622 case WRITE_VERIFY_12:
bd536cf3
GH
623 case WRITE_16:
624 case WRITE_VERIFY_16:
2599aece 625 cmd->xfer *= dev->blocksize;
2ec749cb
GH
626 break;
627 case READ_10:
628 case READ_6:
629 case READ_REVERSE:
630 case RECOVER_BUFFERED_DATA:
631 case READ_12:
bd536cf3 632 case READ_16:
2599aece 633 cmd->xfer *= dev->blocksize;
2ec749cb
GH
634 break;
635 case INQUIRY:
2599aece 636 cmd->xfer = buf[4] | (buf[3] << 8);
2ec749cb 637 break;
c7126d5b
NB
638 case MAINTENANCE_OUT:
639 case MAINTENANCE_IN:
2599aece 640 if (dev->type == TYPE_ROM) {
c7126d5b 641 /* GPCMD_REPORT_KEY and GPCMD_SEND_KEY from multi media commands */
2599aece 642 cmd->xfer = buf[9] | (buf[8] << 8);
c7126d5b
NB
643 }
644 break;
2ec749cb
GH
645 }
646 return 0;
647}
648
2599aece 649static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
2ec749cb 650{
2599aece 651 switch (buf[0]) {
2ec749cb
GH
652 /* stream commands */
653 case READ_6:
654 case READ_REVERSE:
655 case RECOVER_BUFFERED_DATA:
656 case WRITE_6:
2599aece
PB
657 cmd->len = 6;
658 cmd->xfer = buf[4] | (buf[3] << 8) | (buf[2] << 16);
659 if (buf[1] & 0x01) { /* fixed */
660 cmd->xfer *= dev->blocksize;
661 }
2ec749cb
GH
662 break;
663 case REWIND:
664 case START_STOP:
2599aece
PB
665 cmd->len = 6;
666 cmd->xfer = 0;
2ec749cb
GH
667 break;
668 /* generic commands */
669 default:
2599aece 670 return scsi_req_length(cmd, dev, buf);
2ec749cb
GH
671 }
672 return 0;
673}
674
2599aece 675static void scsi_cmd_xfer_mode(SCSICommand *cmd)
97a06435 676{
2599aece 677 switch (cmd->buf[0]) {
97a06435
GH
678 case WRITE_6:
679 case WRITE_10:
5e30a07d 680 case WRITE_VERIFY_10:
97a06435
GH
681 case WRITE_12:
682 case WRITE_VERIFY_12:
bd536cf3
GH
683 case WRITE_16:
684 case WRITE_VERIFY_16:
97a06435
GH
685 case COPY:
686 case COPY_VERIFY:
687 case COMPARE:
688 case CHANGE_DEFINITION:
689 case LOG_SELECT:
690 case MODE_SELECT:
691 case MODE_SELECT_10:
692 case SEND_DIAGNOSTIC:
693 case WRITE_BUFFER:
694 case FORMAT_UNIT:
695 case REASSIGN_BLOCKS:
97a06435
GH
696 case SEARCH_EQUAL:
697 case SEARCH_HIGH:
698 case SEARCH_LOW:
699 case UPDATE_BLOCK:
5e30a07d
HR
700 case WRITE_LONG_10:
701 case WRITE_SAME_10:
97a06435
GH
702 case SEARCH_HIGH_12:
703 case SEARCH_EQUAL_12:
704 case SEARCH_LOW_12:
97a06435
GH
705 case MEDIUM_SCAN:
706 case SEND_VOLUME_TAG:
01bedeba 707 case PERSISTENT_RESERVE_OUT:
c7126d5b 708 case MAINTENANCE_OUT:
2599aece 709 cmd->mode = SCSI_XFER_TO_DEV;
97a06435
GH
710 break;
711 default:
2599aece
PB
712 if (cmd->xfer)
713 cmd->mode = SCSI_XFER_FROM_DEV;
97a06435 714 else {
2599aece 715 cmd->mode = SCSI_XFER_NONE;
97a06435
GH
716 }
717 break;
718 }
719}
720
2599aece 721static uint64_t scsi_cmd_lba(SCSICommand *cmd)
2ec749cb 722{
2599aece 723 uint8_t *buf = cmd->buf;
2ec749cb
GH
724 uint64_t lba;
725
726 switch (buf[0] >> 5) {
727 case 0:
bd5da232 728 lba = ldl_be_p(&buf[0]) & 0x1fffff;
2ec749cb
GH
729 break;
730 case 1:
731 case 2:
bd5da232
PB
732 case 5:
733 lba = ldl_be_p(&buf[2]);
2ec749cb
GH
734 break;
735 case 4:
bd5da232 736 lba = ldq_be_p(&buf[2]);
2ec749cb
GH
737 break;
738 default:
739 lba = -1;
740
741 }
742 return lba;
743}
744
afa46c46 745int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
2ec749cb
GH
746{
747 int rc;
748
afa46c46
PB
749 if (dev->type == TYPE_TAPE) {
750 rc = scsi_req_stream_length(cmd, dev, buf);
2ec749cb 751 } else {
afa46c46 752 rc = scsi_req_length(cmd, dev, buf);
2ec749cb
GH
753 }
754 if (rc != 0)
755 return rc;
756
afa46c46
PB
757 memcpy(cmd->buf, buf, cmd->len);
758 scsi_cmd_xfer_mode(cmd);
759 cmd->lba = scsi_cmd_lba(cmd);
2ec749cb
GH
760 return 0;
761}
ed3a34a3 762
a1f0cce2
HR
763/*
764 * Predefined sense codes
765 */
766
767/* No sense data available */
768const struct SCSISense sense_code_NO_SENSE = {
769 .key = NO_SENSE , .asc = 0x00 , .ascq = 0x00
770};
771
772/* LUN not ready, Manual intervention required */
773const struct SCSISense sense_code_LUN_NOT_READY = {
774 .key = NOT_READY, .asc = 0x04, .ascq = 0x03
775};
776
777/* LUN not ready, Medium not present */
778const struct SCSISense sense_code_NO_MEDIUM = {
779 .key = NOT_READY, .asc = 0x3a, .ascq = 0x00
780};
781
68bb01f3
MA
782/* LUN not ready, medium removal prevented */
783const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = {
784 .key = NOT_READY, .asc = 0x53, .ascq = 0x00
785};
786
a1f0cce2
HR
787/* Hardware error, internal target failure */
788const struct SCSISense sense_code_TARGET_FAILURE = {
789 .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00
790};
791
792/* Illegal request, invalid command operation code */
793const struct SCSISense sense_code_INVALID_OPCODE = {
794 .key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00
795};
796
797/* Illegal request, LBA out of range */
798const struct SCSISense sense_code_LBA_OUT_OF_RANGE = {
799 .key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00
800};
801
802/* Illegal request, Invalid field in CDB */
803const struct SCSISense sense_code_INVALID_FIELD = {
804 .key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00
805};
806
807/* Illegal request, LUN not supported */
808const struct SCSISense sense_code_LUN_NOT_SUPPORTED = {
809 .key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00
810};
811
a872a304
PB
812/* Illegal request, Saving parameters not supported */
813const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = {
814 .key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00
815};
816
817/* Illegal request, Incompatible medium installed */
67cc61e4 818const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = {
a872a304
PB
819 .key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00
820};
821
68bb01f3
MA
822/* Illegal request, medium removal prevented */
823const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = {
824 .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x00
825};
826
a1f0cce2
HR
827/* Command aborted, I/O process terminated */
828const struct SCSISense sense_code_IO_ERROR = {
829 .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
830};
831
832/* Command aborted, I_T Nexus loss occurred */
833const struct SCSISense sense_code_I_T_NEXUS_LOSS = {
834 .key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07
835};
836
837/* Command aborted, Logical Unit failure */
838const struct SCSISense sense_code_LUN_FAILURE = {
839 .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
840};
841
a872a304
PB
842/* Unit attention, Power on, reset or bus device reset occurred */
843const struct SCSISense sense_code_RESET = {
844 .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00
845};
846
8a9c16f6
PB
847/* Unit attention, No medium */
848const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = {
849 .key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00
850};
851
a872a304
PB
852/* Unit attention, Medium may have changed */
853const struct SCSISense sense_code_MEDIUM_CHANGED = {
854 .key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00
855};
856
857/* Unit attention, Reported LUNs data has changed */
858const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = {
859 .key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e
860};
861
862/* Unit attention, Device internal reset */
863const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = {
864 .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04
865};
866
a1f0cce2
HR
867/*
868 * scsi_build_sense
869 *
b45ef674 870 * Convert between fixed and descriptor sense buffers
a1f0cce2 871 */
b45ef674
PB
872int scsi_build_sense(uint8_t *in_buf, int in_len,
873 uint8_t *buf, int len, bool fixed)
a1f0cce2 874{
b45ef674
PB
875 bool fixed_in;
876 SCSISense sense;
a1f0cce2
HR
877 if (!fixed && len < 8) {
878 return 0;
879 }
880
b45ef674
PB
881 if (in_len == 0) {
882 sense.key = NO_SENSE;
883 sense.asc = 0;
884 sense.ascq = 0;
885 } else {
886 fixed_in = (in_buf[0] & 2) == 0;
887
888 if (fixed == fixed_in) {
889 memcpy(buf, in_buf, MIN(len, in_len));
890 return MIN(len, in_len);
891 }
892
893 if (fixed_in) {
894 sense.key = in_buf[2];
895 sense.asc = in_buf[12];
896 sense.ascq = in_buf[13];
897 } else {
898 sense.key = in_buf[1];
899 sense.asc = in_buf[2];
900 sense.ascq = in_buf[3];
901 }
902 }
903
a1f0cce2
HR
904 memset(buf, 0, len);
905 if (fixed) {
906 /* Return fixed format sense buffer */
907 buf[0] = 0xf0;
908 buf[2] = sense.key;
eae31cb9 909 buf[7] = 10;
a1f0cce2
HR
910 buf[12] = sense.asc;
911 buf[13] = sense.ascq;
912 return MIN(len, 18);
913 } else {
914 /* Return descriptor format sense buffer */
915 buf[0] = 0x72;
916 buf[1] = sense.key;
917 buf[2] = sense.asc;
918 buf[3] = sense.ascq;
919 return 8;
920 }
921}
922
ec766865
GH
923static const char *scsi_command_name(uint8_t cmd)
924{
925 static const char *names[] = {
926 [ TEST_UNIT_READY ] = "TEST_UNIT_READY",
5e30a07d 927 [ REWIND ] = "REWIND",
ec766865
GH
928 [ REQUEST_SENSE ] = "REQUEST_SENSE",
929 [ FORMAT_UNIT ] = "FORMAT_UNIT",
930 [ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
931 [ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS",
932 [ READ_6 ] = "READ_6",
933 [ WRITE_6 ] = "WRITE_6",
934 [ SEEK_6 ] = "SEEK_6",
935 [ READ_REVERSE ] = "READ_REVERSE",
936 [ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
937 [ SPACE ] = "SPACE",
938 [ INQUIRY ] = "INQUIRY",
939 [ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
c7126d5b
NB
940 [ MAINTENANCE_IN ] = "MAINTENANCE_IN",
941 [ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
ec766865
GH
942 [ MODE_SELECT ] = "MODE_SELECT",
943 [ RESERVE ] = "RESERVE",
944 [ RELEASE ] = "RELEASE",
945 [ COPY ] = "COPY",
946 [ ERASE ] = "ERASE",
947 [ MODE_SENSE ] = "MODE_SENSE",
948 [ START_STOP ] = "START_STOP",
949 [ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
950 [ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
951 [ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
5e30a07d 952 [ READ_CAPACITY_10 ] = "READ_CAPACITY_10",
ec766865
GH
953 [ READ_10 ] = "READ_10",
954 [ WRITE_10 ] = "WRITE_10",
955 [ SEEK_10 ] = "SEEK_10",
5e30a07d
HR
956 [ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10",
957 [ VERIFY_10 ] = "VERIFY_10",
ec766865
GH
958 [ SEARCH_HIGH ] = "SEARCH_HIGH",
959 [ SEARCH_EQUAL ] = "SEARCH_EQUAL",
960 [ SEARCH_LOW ] = "SEARCH_LOW",
961 [ SET_LIMITS ] = "SET_LIMITS",
962 [ PRE_FETCH ] = "PRE_FETCH",
545557d4 963 /* READ_POSITION and PRE_FETCH use the same operation code */
ec766865
GH
964 [ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
965 [ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
966 [ READ_DEFECT_DATA ] = "READ_DEFECT_DATA",
967 [ MEDIUM_SCAN ] = "MEDIUM_SCAN",
968 [ COMPARE ] = "COMPARE",
969 [ COPY_VERIFY ] = "COPY_VERIFY",
970 [ WRITE_BUFFER ] = "WRITE_BUFFER",
971 [ READ_BUFFER ] = "READ_BUFFER",
972 [ UPDATE_BLOCK ] = "UPDATE_BLOCK",
5e30a07d
HR
973 [ READ_LONG_10 ] = "READ_LONG_10",
974 [ WRITE_LONG_10 ] = "WRITE_LONG_10",
ec766865 975 [ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
5e30a07d
HR
976 [ WRITE_SAME_10 ] = "WRITE_SAME_10",
977 [ UNMAP ] = "UNMAP",
ec766865 978 [ READ_TOC ] = "READ_TOC",
5e30a07d
HR
979 [ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
980 [ GET_CONFIGURATION ] = "GET_CONFIGURATION",
ec766865
GH
981 [ LOG_SELECT ] = "LOG_SELECT",
982 [ LOG_SENSE ] = "LOG_SENSE",
983 [ MODE_SELECT_10 ] = "MODE_SELECT_10",
984 [ RESERVE_10 ] = "RESERVE_10",
985 [ RELEASE_10 ] = "RELEASE_10",
986 [ MODE_SENSE_10 ] = "MODE_SENSE_10",
987 [ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
988 [ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
5e30a07d
HR
989 [ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
990 [ EXTENDED_COPY ] = "EXTENDED_COPY",
991 [ ATA_PASSTHROUGH ] = "ATA_PASSTHROUGH",
992 [ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
993 [ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
994 [ READ_16 ] = "READ_16",
995 [ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE",
996 [ WRITE_16 ] = "WRITE_16",
997 [ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
998 [ VERIFY_16 ] = "VERIFY_16",
999 [ SYNCHRONIZE_CACHE_16 ] = "SYNCHRONIZE_CACHE_16",
1000 [ LOCATE_16 ] = "LOCATE_16",
1001 [ WRITE_SAME_16 ] = "WRITE_SAME_16",
48bb9f53 1002 /* ERASE_16 and WRITE_SAME_16 use the same operation code */
f6515262 1003 [ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
5e30a07d
HR
1004 [ WRITE_LONG_16 ] = "WRITE_LONG_16",
1005 [ REPORT_LUNS ] = "REPORT_LUNS",
1006 [ BLANK ] = "BLANK",
ec766865 1007 [ MOVE_MEDIUM ] = "MOVE_MEDIUM",
5e30a07d 1008 [ LOAD_UNLOAD ] = "LOAD_UNLOAD",
ec766865
GH
1009 [ READ_12 ] = "READ_12",
1010 [ WRITE_12 ] = "WRITE_12",
f6515262 1011 [ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
ec766865 1012 [ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
5e30a07d 1013 [ VERIFY_12 ] = "VERIFY_12",
ec766865
GH
1014 [ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
1015 [ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
1016 [ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
1017 [ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
1018 [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG",
5e30a07d 1019 [ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
ec766865 1020 [ SET_CD_SPEED ] = "SET_CD_SPEED",
ec766865
GH
1021 };
1022
1023 if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
1024 return "*UNKNOWN*";
1025 return names[cmd];
1026}
1027
ad2d30f7
PB
1028SCSIRequest *scsi_req_ref(SCSIRequest *req)
1029{
1030 req->refcount++;
1031 return req;
1032}
1033
1034void scsi_req_unref(SCSIRequest *req)
1035{
1036 if (--req->refcount == 0) {
12010e7b
PB
1037 if (req->ops->free_req) {
1038 req->ops->free_req(req);
ad2d30f7 1039 }
7267c094 1040 g_free(req);
ad2d30f7
PB
1041 }
1042}
1043
ad3376cc
PB
1044/* Tell the device that we finished processing this chunk of I/O. It
1045 will start the next chunk or complete the command. */
1046void scsi_req_continue(SCSIRequest *req)
1047{
1048 trace_scsi_req_continue(req->dev->id, req->lun, req->tag);
1049 if (req->cmd.mode == SCSI_XFER_TO_DEV) {
12010e7b 1050 req->ops->write_data(req);
ad3376cc 1051 } else {
12010e7b 1052 req->ops->read_data(req);
ad3376cc
PB
1053 }
1054}
1055
ab9adc88
PB
1056/* Called by the devices when data is ready for the HBA. The HBA should
1057 start a DMA operation to read or fill the device's data buffer.
ad3376cc 1058 Once it completes, calling scsi_req_continue will restart I/O. */
ab9adc88
PB
1059void scsi_req_data(SCSIRequest *req, int len)
1060{
1061 trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
afd4030c 1062 req->bus->info->transfer_data(req, len);
ab9adc88
PB
1063}
1064
ec766865
GH
1065void scsi_req_print(SCSIRequest *req)
1066{
1067 FILE *fp = stderr;
1068 int i;
1069
1070 fprintf(fp, "[%s id=%d] %s",
1071 req->dev->qdev.parent_bus->name,
1072 req->dev->id,
1073 scsi_command_name(req->cmd.buf[0]));
1074 for (i = 1; i < req->cmd.len; i++) {
1075 fprintf(fp, " 0x%02x", req->cmd.buf[i]);
1076 }
1077 switch (req->cmd.mode) {
1078 case SCSI_XFER_NONE:
1079 fprintf(fp, " - none\n");
1080 break;
1081 case SCSI_XFER_FROM_DEV:
1082 fprintf(fp, " - from-dev len=%zd\n", req->cmd.xfer);
1083 break;
1084 case SCSI_XFER_TO_DEV:
1085 fprintf(fp, " - to-dev len=%zd\n", req->cmd.xfer);
1086 break;
1087 default:
1088 fprintf(fp, " - Oops\n");
1089 break;
1090 }
1091}
1092
682a9b21 1093void scsi_req_complete(SCSIRequest *req, int status)
ed3a34a3 1094{
682a9b21
PB
1095 assert(req->status == -1);
1096 req->status = status;
b45ef674
PB
1097
1098 assert(req->sense_len < sizeof(req->sense));
1099 if (status == GOOD) {
1100 req->sense_len = 0;
1101 }
1102
1103 if (req->sense_len) {
1104 memcpy(req->dev->sense, req->sense, req->sense_len);
3653d8c4
PB
1105 req->dev->sense_len = req->sense_len;
1106 req->dev->sense_is_ua = (req->ops == &reqops_unit_attention);
1107 } else {
1108 req->dev->sense_len = 0;
1109 req->dev->sense_is_ua = false;
b45ef674 1110 }
b45ef674 1111
6dc06f08
PB
1112 /*
1113 * Unit attention state is now stored in the device's sense buffer
1114 * if the HBA didn't do autosense. Clear the pending unit attention
1115 * flags.
1116 */
1117 scsi_clear_unit_attention(req);
1118
ad2d30f7 1119 scsi_req_ref(req);
e8637c90 1120 scsi_req_dequeue(req);
afd4030c 1121 req->bus->info->complete(req, req->status);
ad2d30f7 1122 scsi_req_unref(req);
ed3a34a3 1123}
db07c0f8 1124
94d3f98a
PB
1125void scsi_req_cancel(SCSIRequest *req)
1126{
12010e7b
PB
1127 if (req->ops->cancel_io) {
1128 req->ops->cancel_io(req);
94d3f98a
PB
1129 }
1130 scsi_req_ref(req);
1131 scsi_req_dequeue(req);
afd4030c
PB
1132 if (req->bus->info->cancel) {
1133 req->bus->info->cancel(req);
94d3f98a
PB
1134 }
1135 scsi_req_unref(req);
1136}
1137
19d110ab
PB
1138void scsi_req_abort(SCSIRequest *req, int status)
1139{
12010e7b
PB
1140 if (req->ops->cancel_io) {
1141 req->ops->cancel_io(req);
19d110ab 1142 }
682a9b21 1143 scsi_req_complete(req, status);
19d110ab
PB
1144}
1145
c7b48872 1146void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
c557e889
PB
1147{
1148 SCSIRequest *req;
1149
1150 while (!QTAILQ_EMPTY(&sdev->requests)) {
1151 req = QTAILQ_FIRST(&sdev->requests);
94d3f98a 1152 scsi_req_cancel(req);
c557e889 1153 }
c7b48872 1154 sdev->unit_attention = sense;
c557e889
PB
1155}
1156
db07c0f8
GN
1157static char *scsibus_get_fw_dev_path(DeviceState *dev)
1158{
645a8ad6 1159 SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
db07c0f8
GN
1160 SCSIBus *bus = scsi_bus_from_device(d);
1161 char path[100];
1162 int i;
1163
afd4030c 1164 for (i = 0; i < bus->info->ndev; i++) {
db07c0f8
GN
1165 if (bus->devs[i] == d) {
1166 break;
1167 }
1168 }
1169
afd4030c 1170 assert(i != bus->info->ndev);
db07c0f8
GN
1171
1172 snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
1173
1174 return strdup(path);
1175}