]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi/scsi-generic.c
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[mirror_qemu.git] / hw / scsi / scsi-generic.c
CommitLineData
2cc977e2
TS
1/*
2 * Generic SCSI Device support
3 *
4 * Copyright (c) 2007 Bull S.A.S.
5 * Based on code by Paul Brook
6 * Based on code by Fabrice Bellard
7 *
8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
9 *
8e31bf38 10 * This code is licensed under the LGPL.
2cc977e2
TS
11 *
12 */
13
a4ab4792 14#include "qemu/osdep.h"
da34e65c 15#include "qapi/error.h"
2cc977e2 16#include "qemu-common.h"
1de7afc9 17#include "qemu/error-report.h"
0d09e41a 18#include "hw/scsi/scsi.h"
3d4a8bf0 19#include "hw/scsi/emulation.h"
4be74634 20#include "sysemu/block-backend.h"
56853498 21#include "trace.h"
2cc977e2 22
d52affa7 23#ifdef __linux__
2cc977e2 24
2cc977e2 25#include <scsi/sg.h>
08e2c9f1 26#include "scsi/constants.h"
2cc977e2 27
2cc977e2
TS
28#ifndef MAX_UINT
29#define MAX_UINT ((unsigned int)-1)
30#endif
31
4c41d2ef
GH
32typedef struct SCSIGenericReq {
33 SCSIRequest req;
2cc977e2
TS
34 uint8_t *buf;
35 int buflen;
36 int len;
37 sg_io_hdr_t io_header;
4c41d2ef 38} SCSIGenericReq;
2cc977e2 39
56b1fc48
PB
40static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
41{
42 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
43
44 qemu_put_sbe32s(f, &r->buflen);
45 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
46 assert(!r->req.sg);
47 qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
48 }
49}
50
51static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
52{
53 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
54
55 qemu_get_sbe32s(f, &r->buflen);
56 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
57 assert(!r->req.sg);
58 qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
59 }
60}
61
ad2d30f7 62static void scsi_free_request(SCSIRequest *req)
2cc977e2 63{
ad2d30f7
PB
64 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
65
7267c094 66 g_free(r->buf);
2cc977e2
TS
67}
68
2cc977e2 69/* Helper function for command completion. */
fa0d653b 70static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
2cc977e2 71{
682a9b21 72 int status;
1ead6b4e 73 SCSISense sense;
2cc977e2 74
fa0d653b
PB
75 assert(r->req.aiocb == NULL);
76
6c25fa6c 77 if (r->req.io_canceled) {
d5776465 78 scsi_req_cancel_complete(&r->req);
6c25fa6c
FZ
79 goto done;
80 }
1ead6b4e
PB
81 status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
82 if (status == CHECK_CONDITION) {
83 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
84 r->req.sense_len = r->io_header.sb_len_wr;
682a9b21 85 } else {
1ead6b4e 86 scsi_req_build_sense(&r->req, sense);
682a9b21 87 }
2cc977e2 88 }
1ead6b4e 89
56853498 90 trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
ed3a34a3 91
682a9b21 92 scsi_req_complete(&r->req, status);
6c25fa6c 93done:
3df9caf8 94 scsi_req_unref(&r->req);
2cc977e2
TS
95}
96
fa0d653b
PB
97static void scsi_command_complete(void *opaque, int ret)
98{
99 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
b9e413dd 100 SCSIDevice *s = r->req.dev;
fa0d653b
PB
101
102 assert(r->req.aiocb != NULL);
103 r->req.aiocb = NULL;
b9e413dd
PB
104
105 aio_context_acquire(blk_get_aio_context(s->conf.blk));
fa0d653b 106 scsi_command_complete_noio(r, ret);
b9e413dd 107 aio_context_release(blk_get_aio_context(s->conf.blk));
fa0d653b
PB
108}
109
4be74634 110static int execute_command(BlockBackend *blk,
4c41d2ef 111 SCSIGenericReq *r, int direction,
097310b5 112 BlockCompletionFunc *complete)
2cc977e2 113{
2cc977e2
TS
114 r->io_header.interface_id = 'S';
115 r->io_header.dxfer_direction = direction;
116 r->io_header.dxferp = r->buf;
117 r->io_header.dxfer_len = r->buflen;
29362ebe
GH
118 r->io_header.cmdp = r->req.cmd.buf;
119 r->io_header.cmd_len = r->req.cmd.len;
b45ef674
PB
120 r->io_header.mx_sb_len = sizeof(r->req.sense);
121 r->io_header.sbp = r->req.sense;
2cc977e2
TS
122 r->io_header.timeout = MAX_UINT;
123 r->io_header.usr_ptr = r;
124 r->io_header.flags |= SG_FLAG_DIRECT_IO;
125
4be74634 126 r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
d836f8d3
PH
127 if (r->req.aiocb == NULL) {
128 return -EIO;
129 }
2cc977e2
TS
130
131 return 0;
132}
133
0a96ca24
DHB
134static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
135{
6c219fc8 136 uint8_t page, page_idx;
a71c775b 137
0a96ca24
DHB
138 /*
139 * EVPD set to zero returns the standard INQUIRY data.
140 *
141 * Check if scsi_version is unset (-1) to avoid re-defining it
142 * each time an INQUIRY with standard data is received.
143 * scsi_version is initialized with -1 in scsi_generic_reset
144 * and scsi_disk_reset, making sure that we'll set the
145 * scsi_version after a reset. If the version field of the
146 * INQUIRY response somehow changes after a guest reboot,
147 * we'll be able to keep track of it.
148 *
149 * On SCSI-2 and older, first 3 bits of byte 2 is the
150 * ANSI-approved version, while on later versions the
151 * whole byte 2 contains the version. Check if we're dealing
152 * with a newer version and, in that case, assign the
153 * whole byte.
154 */
155 if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
156 s->scsi_version = r->buf[2] & 0x07;
157 if (s->scsi_version > 2) {
158 s->scsi_version = r->buf[2];
159 }
160 }
0a96ca24 161
a71c775b
DHB
162 if (s->type == TYPE_DISK && (r->req.cmd.buf[1] & 0x01)) {
163 page = r->req.cmd.buf[2];
164 if (page == 0xb0) {
165 uint32_t max_transfer =
166 blk_get_max_transfer(s->conf.blk) / s->blocksize;
167
168 assert(max_transfer);
169 stl_be_p(&r->buf[8], max_transfer);
170 /* Also take care of the opt xfer len. */
171 stl_be_p(&r->buf[12],
172 MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
e909ff93 173 } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
a71c775b
DHB
174 /*
175 * Now we're capable of supplying the VPD Block Limits
176 * response if the hardware can't. Add it in the INQUIRY
177 * Supported VPD pages response in case we are using the
178 * emulation for this device.
179 *
180 * This way, the guest kernel will be aware of the support
181 * and will use it to proper setup the SCSI device.
6c219fc8
PB
182 *
183 * VPD page numbers must be sorted, so insert 0xb0 at the
e909ff93
PB
184 * right place with an in-place insert. When the while loop
185 * begins the device response is at r[0] to r[page_idx - 1].
a71c775b 186 */
e909ff93
PB
187 page_idx = lduw_be_p(r->buf + 2) + 4;
188 page_idx = MIN(page_idx, r->buflen);
189 while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
6c219fc8
PB
190 if (page_idx < r->buflen) {
191 r->buf[page_idx] = r->buf[page_idx - 1];
192 }
e909ff93
PB
193 page_idx--;
194 }
195 if (page_idx < r->buflen) {
196 r->buf[page_idx] = 0xb0;
6c219fc8 197 }
6c219fc8 198 stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
a71c775b 199 }
0a96ca24
DHB
200 }
201}
202
3d4a8bf0 203static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
a71c775b 204{
3d4a8bf0
PB
205 int len;
206 uint8_t buf[64];
207
208 SCSIBlockLimits bl = {
209 .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize
210 };
211
212 memset(r->buf, 0, r->buflen);
213 stb_p(buf, s->type);
214 stb_p(buf + 1, 0xb0);
215 len = scsi_emulate_block_limits(buf + 4, &bl);
216 assert(len <= sizeof(buf) - 4);
217 stw_be_p(buf + 2, len);
218
219 memcpy(r->buf, buf, MIN(r->buflen, len + 4));
220
a71c775b
DHB
221 r->io_header.sb_len_wr = 0;
222
223 /*
224 * We have valid contents in the reply buffer but the
225 * io_header can report a sense error coming from
226 * the hardware in scsi_command_complete_noio. Clean
227 * up the io_header to avoid reporting it.
228 */
229 r->io_header.driver_status = 0;
230 r->io_header.status = 0;
231
232 return r->buflen;
233}
234
2cc977e2
TS
235static void scsi_read_complete(void * opaque, int ret)
236{
4c41d2ef 237 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
9b6eef8a 238 SCSIDevice *s = r->req.dev;
2cc977e2
TS
239 int len;
240
fa0d653b 241 assert(r->req.aiocb != NULL);
d33e0ce2 242 r->req.aiocb = NULL;
fa0d653b 243
b9e413dd
PB
244 aio_context_acquire(blk_get_aio_context(s->conf.blk));
245
6c25fa6c 246 if (ret || r->req.io_canceled) {
fa0d653b 247 scsi_command_complete_noio(r, ret);
b9e413dd 248 goto done;
2cc977e2 249 }
fa0d653b 250
2cc977e2 251 len = r->io_header.dxfer_len - r->io_header.resid;
56853498 252 trace_scsi_generic_read_complete(r->req.tag, len);
2cc977e2
TS
253
254 r->len = -1;
a71c775b
DHB
255
256 /*
257 * Check if this is a VPD Block Limits request that
258 * resulted in sense error but would need emulation.
259 * In this case, emulate a valid VPD response.
260 */
763c5687
PB
261 if (s->needs_vpd_bl_emulation && ret == 0 &&
262 (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) &&
3d4a8bf0
PB
263 r->req.cmd.buf[0] == INQUIRY &&
264 (r->req.cmd.buf[1] & 0x01) &&
265 r->req.cmd.buf[2] == 0xb0) {
763c5687
PB
266 SCSISense sense =
267 scsi_parse_sense_buf(r->req.sense, r->io_header.sb_len_wr);
268 if (sense.key == ILLEGAL_REQUEST) {
3d4a8bf0 269 len = scsi_generic_emulate_block_limits(r, s);
a71c775b
DHB
270 /*
271 * No need to let scsi_read_complete go on and handle an
272 * INQUIRY VPD BL request we created manually.
273 */
274 goto req_complete;
275 }
276 }
277
40f16dd1 278 if (len == 0) {
fa0d653b 279 scsi_command_complete_noio(r, 0);
b9e413dd 280 goto done;
fa0d653b 281 }
9b6eef8a 282
fa0d653b
PB
283 /* Snoop READ CAPACITY output to set the blocksize. */
284 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
285 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
286 s->blocksize = ldl_be_p(&r->buf[4]);
287 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
288 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
289 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
290 s->blocksize = ldl_be_p(&r->buf[8]);
291 s->max_lba = ldq_be_p(&r->buf[0]);
40f16dd1 292 }
fa0d653b
PB
293 blk_set_guest_block_size(s->conf.blk, s->blocksize);
294
0eb2baeb
PB
295 /* Patch MODE SENSE device specific parameters if the BDS is opened
296 * readonly.
297 */
298 if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) &&
299 blk_is_read_only(s->conf.blk) &&
300 (r->req.cmd.buf[0] == MODE_SENSE ||
301 r->req.cmd.buf[0] == MODE_SENSE_10) &&
302 (r->req.cmd.buf[1] & 0x8) == 0) {
303 if (r->req.cmd.buf[0] == MODE_SENSE) {
304 r->buf[2] |= 0x80;
305 } else {
306 r->buf[3] |= 0x80;
307 }
308 }
29e560f0 309 if (r->req.cmd.buf[0] == INQUIRY) {
0a96ca24 310 scsi_handle_inquiry_reply(r, s);
063143d5 311 }
a71c775b
DHB
312
313req_complete:
fa0d653b
PB
314 scsi_req_data(&r->req, len);
315 scsi_req_unref(&r->req);
b9e413dd
PB
316
317done:
318 aio_context_release(blk_get_aio_context(s->conf.blk));
2cc977e2
TS
319}
320
321/* Read more data from scsi device into buffer. */
5c6c0e51 322static void scsi_read_data(SCSIRequest *req)
2cc977e2 323{
5c6c0e51 324 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 325 SCSIDevice *s = r->req.dev;
2cc977e2
TS
326 int ret;
327
56853498 328 trace_scsi_generic_read_data(req->tag);
c9501c95
PB
329
330 /* The request is used as the AIO opaque value, so add a ref. */
331 scsi_req_ref(&r->req);
2cc977e2 332 if (r->len == -1) {
fa0d653b 333 scsi_command_complete_noio(r, 0);
2cc977e2
TS
334 return;
335 }
336
4be74634
MA
337 ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
338 scsi_read_complete);
a1f0cce2 339 if (ret < 0) {
fa0d653b 340 scsi_command_complete_noio(r, ret);
2cc977e2
TS
341 }
342}
343
344static void scsi_write_complete(void * opaque, int ret)
345{
4c41d2ef 346 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
8869e103 347 SCSIDevice *s = r->req.dev;
2cc977e2 348
56853498 349 trace_scsi_generic_write_complete(ret);
fa0d653b
PB
350
351 assert(r->req.aiocb != NULL);
d33e0ce2 352 r->req.aiocb = NULL;
fa0d653b 353
b9e413dd
PB
354 aio_context_acquire(blk_get_aio_context(s->conf.blk));
355
6c25fa6c 356 if (ret || r->req.io_canceled) {
fa0d653b 357 scsi_command_complete_noio(r, ret);
b9e413dd 358 goto done;
2cc977e2
TS
359 }
360
29362ebe 361 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
8869e103
PB
362 s->type == TYPE_TAPE) {
363 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
56853498 364 trace_scsi_generic_write_complete_blocksize(s->blocksize);
89c0f643
AJ
365 }
366
fa0d653b 367 scsi_command_complete_noio(r, ret);
b9e413dd
PB
368
369done:
370 aio_context_release(blk_get_aio_context(s->conf.blk));
2cc977e2
TS
371}
372
373/* Write data to a scsi device. Returns nonzero on failure.
374 The transfer may complete asynchronously. */
42741212 375static void scsi_write_data(SCSIRequest *req)
2cc977e2 376{
5c6c0e51 377 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 378 SCSIDevice *s = r->req.dev;
2cc977e2
TS
379 int ret;
380
56853498 381 trace_scsi_generic_write_data(req->tag);
2cc977e2
TS
382 if (r->len == 0) {
383 r->len = r->buflen;
ab9adc88 384 scsi_req_data(&r->req, r->len);
42741212 385 return;
2cc977e2
TS
386 }
387
c9501c95
PB
388 /* The request is used as the AIO opaque value, so add a ref. */
389 scsi_req_ref(&r->req);
4be74634 390 ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2 391 if (ret < 0) {
fa0d653b 392 scsi_command_complete_noio(r, ret);
2cc977e2 393 }
2cc977e2
TS
394}
395
396/* Return a pointer to the data buffer. */
5c6c0e51 397static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 398{
5c6c0e51
HR
399 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
400
2cc977e2
TS
401 return r->buf;
402}
403
56853498
LV
404static void scsi_generic_command_dump(uint8_t *cmd, int len)
405{
406 int i;
407 char *line_buffer, *p;
408
409 line_buffer = g_malloc(len * 5 + 1);
410
411 for (i = 0, p = line_buffer; i < len; i++) {
412 p += sprintf(p, " 0x%02x", cmd[i]);
413 }
414 trace_scsi_generic_send_command(line_buffer);
415
416 g_free(line_buffer);
417}
418
2cc977e2
TS
419/* Execute a scsi command. Returns the length of the data expected by the
420 command. This will be Positive for data transfers from the device
421 (eg. disk reads), negative for transfers to the device (eg. disk writes),
422 and zero if the command does not transfer any data. */
423
5c6c0e51 424static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 425{
5c6c0e51 426 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 427 SCSIDevice *s = r->req.dev;
2cc977e2
TS
428 int ret;
429
56853498
LV
430 if (trace_event_get_state_backends(TRACE_SCSI_GENERIC_SEND_COMMAND)) {
431 scsi_generic_command_dump(cmd, r->req.cmd.len);
aa2b1e89 432 }
2cc977e2 433
2ec749cb 434 if (r->req.cmd.xfer == 0) {
1c3381af 435 g_free(r->buf);
2cc977e2
TS
436 r->buflen = 0;
437 r->buf = NULL;
c9501c95
PB
438 /* The request is used as the AIO opaque value, so add a ref. */
439 scsi_req_ref(&r->req);
4be74634
MA
440 ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
441 scsi_command_complete);
a1f0cce2 442 if (ret < 0) {
fa0d653b 443 scsi_command_complete_noio(r, ret);
a1f0cce2 444 return 0;
2cc977e2
TS
445 }
446 return 0;
447 }
448
2ec749cb 449 if (r->buflen != r->req.cmd.xfer) {
1c3381af 450 g_free(r->buf);
7267c094 451 r->buf = g_malloc(r->req.cmd.xfer);
2ec749cb 452 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
453 }
454
455 memset(r->buf, 0, r->buflen);
2ec749cb 456 r->len = r->req.cmd.xfer;
97a06435 457 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 458 r->len = 0;
5c6c0e51 459 return -r->req.cmd.xfer;
ad2d30f7 460 } else {
5c6c0e51 461 return r->req.cmd.xfer;
2cc977e2 462 }
2cc977e2
TS
463}
464
9fd7e859
PB
465static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
466{
467 int i;
468
469 if ((p[1] & 0xF) == 3) {
470 /* NAA designator type */
471 if (p[3] != 8) {
472 return -EINVAL;
473 }
474 *p_wwn = ldq_be_p(p + 4);
475 return 0;
476 }
477
478 if ((p[1] & 0xF) == 8) {
479 /* SCSI name string designator type */
480 if (p[3] < 20 || memcmp(&p[4], "naa.", 4)) {
481 return -EINVAL;
482 }
483 if (p[3] > 20 && p[24] != ',') {
484 return -EINVAL;
485 }
486 *p_wwn = 0;
487 for (i = 8; i < 24; i++) {
95a5befc 488 char c = qemu_toupper(p[i]);
9fd7e859
PB
489 c -= (c >= '0' && c <= '9' ? '0' : 'A' - 10);
490 *p_wwn = (*p_wwn << 4) | c;
491 }
492 return 0;
493 }
494
495 return -EINVAL;
496}
497
a0c7e35b
DHB
498int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
499 uint8_t *buf, uint8_t buf_size)
9fd7e859 500{
9fd7e859 501 sg_io_hdr_t io_header;
a0c7e35b 502 uint8_t sensebuf[8];
9fd7e859 503 int ret;
9fd7e859
PB
504
505 memset(&io_header, 0, sizeof(io_header));
506 io_header.interface_id = 'S';
507 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
a0c7e35b 508 io_header.dxfer_len = buf_size;
9fd7e859
PB
509 io_header.dxferp = buf;
510 io_header.cmdp = cmd;
a0c7e35b 511 io_header.cmd_len = cmd_size;
9fd7e859
PB
512 io_header.mx_sb_len = sizeof(sensebuf);
513 io_header.sbp = sensebuf;
514 io_header.timeout = 6000; /* XXX */
515
a0c7e35b 516 ret = blk_ioctl(blk, SG_IO, &io_header);
9fd7e859 517 if (ret < 0 || io_header.driver_status || io_header.host_status) {
a0c7e35b
DHB
518 return -1;
519 }
520 return 0;
521}
522
a71c775b
DHB
523/*
524 * Executes an INQUIRY request with EVPD set to retrieve the
525 * available VPD pages of the device. If the device does
526 * not support the Block Limits page (page 0xb0), set
527 * the needs_vpd_bl_emulation flag for future use.
528 */
529static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s)
530{
531 uint8_t cmd[6];
532 uint8_t buf[250];
533 uint8_t page_len;
534 int ret, i;
535
536 memset(cmd, 0, sizeof(cmd));
537 memset(buf, 0, sizeof(buf));
538 cmd[0] = INQUIRY;
539 cmd[1] = 1;
540 cmd[2] = 0x00;
541 cmd[4] = sizeof(buf);
542
543 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
544 buf, sizeof(buf));
545 if (ret < 0) {
546 /*
547 * Do not assume anything if we can't retrieve the
548 * INQUIRY response to assert the VPD Block Limits
549 * support.
550 */
551 s->needs_vpd_bl_emulation = false;
552 return;
553 }
554
555 page_len = buf[3];
57dbb58d 556 for (i = 4; i < MIN(sizeof(buf), page_len + 4); i++) {
a71c775b
DHB
557 if (buf[i] == 0xb0) {
558 s->needs_vpd_bl_emulation = false;
559 return;
560 }
561 }
562 s->needs_vpd_bl_emulation = true;
563}
564
565static void scsi_generic_read_device_identification(SCSIDevice *s)
a0c7e35b
DHB
566{
567 uint8_t cmd[6];
568 uint8_t buf[250];
569 int ret;
570 int i, len;
571
572 memset(cmd, 0, sizeof(cmd));
573 memset(buf, 0, sizeof(buf));
574 cmd[0] = INQUIRY;
575 cmd[1] = 1;
576 cmd[2] = 0x83;
577 cmd[4] = sizeof(buf);
578
579 ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
580 buf, sizeof(buf));
581 if (ret < 0) {
9fd7e859
PB
582 return;
583 }
584
585 len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
586 for (i = 0; i + 3 <= len; ) {
587 const uint8_t *p = &buf[i + 4];
588 uint64_t wwn;
589
590 if (i + (p[3] + 4) > len) {
591 break;
592 }
593
594 if ((p[1] & 0x10) == 0) {
595 /* Associated with the logical unit */
596 if (read_naa_id(p, &wwn) == 0) {
597 s->wwn = wwn;
598 }
599 } else if ((p[1] & 0x10) == 0x10) {
600 /* Associated with the target port */
601 if (read_naa_id(p, &wwn) == 0) {
602 s->port_wwn = wwn;
603 }
604 }
605
606 i += p[3] + 4;
607 }
608}
609
a71c775b
DHB
610void scsi_generic_read_device_inquiry(SCSIDevice *s)
611{
612 scsi_generic_read_device_identification(s);
613 if (s->type == TYPE_DISK) {
614 scsi_generic_set_vpd_bl_emulation(s);
615 } else {
616 s->needs_vpd_bl_emulation = false;
617 }
618}
619
4be74634 620static int get_stream_blocksize(BlockBackend *blk)
89c0f643
AJ
621{
622 uint8_t cmd[6];
623 uint8_t buf[12];
89c0f643
AJ
624 int ret;
625
626 memset(cmd, 0, sizeof(cmd));
627 memset(buf, 0, sizeof(buf));
628 cmd[0] = MODE_SENSE;
629 cmd[4] = sizeof(buf);
630
a0c7e35b
DHB
631 ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf));
632 if (ret < 0) {
89c0f643 633 return -1;
fe0ed712 634 }
a0c7e35b 635
89c0f643
AJ
636 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
637}
638
f8b6d672
BK
639static void scsi_generic_reset(DeviceState *dev)
640{
b9eea3e6 641 SCSIDevice *s = SCSI_DEVICE(dev);
f8b6d672 642
2343be0d 643 s->scsi_version = s->default_scsi_version;
8869e103 644 scsi_device_purge_requests(s, SENSE_CODE(RESET));
f8b6d672
BK
645}
646
a818a4b6 647static void scsi_generic_realize(SCSIDevice *s, Error **errp)
2cc977e2 648{
6ee143a0 649 int rc;
2cc977e2 650 int sg_version;
2cc977e2
TS
651 struct sg_scsi_id scsiid;
652
4be74634 653 if (!s->conf.blk) {
a818a4b6
FZ
654 error_setg(errp, "drive property not set");
655 return;
d52affa7 656 }
2cc977e2 657
4be74634 658 if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
a818a4b6
FZ
659 error_setg(errp, "Device doesn't support drive option werror");
660 return;
620f862e 661 }
4be74634 662 if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
a818a4b6
FZ
663 error_setg(errp, "Device doesn't support drive option rerror");
664 return;
620f862e
MA
665 }
666
2cc977e2 667 /* check we are using a driver managing SG_IO (version 3 and after */
4be74634 668 rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
6ee143a0 669 if (rc < 0) {
09c2c6ff
PB
670 error_setg_errno(errp, -rc, "cannot get SG_IO version number");
671 if (rc != -EPERM) {
672 error_append_hint(errp, "Is this a SCSI device?\n");
673 }
a818a4b6 674 return;
98392453
RS
675 }
676 if (sg_version < 30000) {
a818a4b6
FZ
677 error_setg(errp, "scsi generic interface too old");
678 return;
d52affa7 679 }
2cc977e2
TS
680
681 /* get LUN of the /dev/sg? */
4be74634 682 if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
a818a4b6
FZ
683 error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
684 return;
d52affa7 685 }
c6caae55
FZ
686 if (!blkconf_apply_backend_options(&s->conf,
687 blk_is_read_only(s->conf.blk),
688 true, errp)) {
d9bcd6f7
FZ
689 return;
690 }
2cc977e2
TS
691
692 /* define device state */
8869e103 693 s->type = scsiid.scsi_type;
56853498 694 trace_scsi_generic_realize_type(s->type);
28b77657 695
9b6eef8a
PB
696 switch (s->type) {
697 case TYPE_TAPE:
4be74634 698 s->blocksize = get_stream_blocksize(s->conf.blk);
8869e103
PB
699 if (s->blocksize == -1) {
700 s->blocksize = 0;
701 }
9b6eef8a
PB
702 break;
703
704 /* Make a guess for block devices, we'll fix it when the guest sends.
705 * READ CAPACITY. If they don't, they likely would assume these sizes
706 * anyway. (TODO: they could also send MODE SENSE).
707 */
708 case TYPE_ROM:
709 case TYPE_WORM:
710 s->blocksize = 2048;
711 break;
712 default:
713 s->blocksize = 512;
714 break;
89c0f643 715 }
8869e103 716
56853498 717 trace_scsi_generic_realize_blocksize(s->blocksize);
9fd7e859 718
29e560f0
DHB
719 /* Only used by scsi-block, but initialize it nevertheless to be clean. */
720 s->default_scsi_version = -1;
a71c775b 721 scsi_generic_read_device_inquiry(s);
d52affa7 722}
2cc977e2 723
765d1525 724const SCSIReqOps scsi_generic_req_ops = {
8dbd4574 725 .size = sizeof(SCSIGenericReq),
12010e7b
PB
726 .free_req = scsi_free_request,
727 .send_command = scsi_send_command,
728 .read_data = scsi_read_data,
729 .write_data = scsi_write_data,
12010e7b 730 .get_buf = scsi_get_buf,
56b1fc48
PB
731 .load_request = scsi_generic_load_request,
732 .save_request = scsi_generic_save_request,
8dbd4574
PB
733};
734
735static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
63db0f0e 736 uint8_t *buf, void *hba_private)
8dbd4574 737{
9be38598 738 return scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
8dbd4574
PB
739}
740
39bffca2 741static Property scsi_generic_properties[] = {
4be74634 742 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
d9bcd6f7 743 DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
39bffca2
AL
744 DEFINE_PROP_END_OF_LIST(),
745};
746
3e7e180a
PB
747static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
748 uint8_t *buf, void *hba_private)
749{
750 return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
751}
752
b9eea3e6
AL
753static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
754{
39bffca2 755 DeviceClass *dc = DEVICE_CLASS(klass);
b9eea3e6
AL
756 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
757
a818a4b6 758 sc->realize = scsi_generic_realize;
b9eea3e6 759 sc->alloc_req = scsi_new_request;
3e7e180a 760 sc->parse_cdb = scsi_generic_parse_cdb;
39bffca2
AL
761 dc->fw_name = "disk";
762 dc->desc = "pass through generic scsi device (/dev/sg*)";
763 dc->reset = scsi_generic_reset;
764 dc->props = scsi_generic_properties;
56b1fc48 765 dc->vmsd = &vmstate_scsi_device;
b9eea3e6
AL
766}
767
8c43a6f0 768static const TypeInfo scsi_generic_info = {
39bffca2
AL
769 .name = "scsi-generic",
770 .parent = TYPE_SCSI_DEVICE,
771 .instance_size = sizeof(SCSIDevice),
772 .class_init = scsi_generic_class_initfn,
d52affa7 773};
2cc977e2 774
83f7d43a 775static void scsi_generic_register_types(void)
d52affa7 776{
39bffca2 777 type_register_static(&scsi_generic_info);
2cc977e2 778}
83f7d43a
AF
779
780type_init(scsi_generic_register_types)
d52affa7 781
2cc977e2 782#endif /* __linux__ */