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