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