]> git.proxmox.com Git - qemu.git/blame - hw/scsi-generic.c
ide: convert to QEMU Object Model
[qemu.git] / hw / 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
14#include "qemu-common.h"
2f792016 15#include "qemu-error.h"
43b443b6 16#include "scsi.h"
2446333c 17#include "blockdev.h"
2cc977e2 18
d52affa7 19#ifdef __linux__
2cc977e2
TS
20
21//#define DEBUG_SCSI
22
23#ifdef DEBUG_SCSI
001faf32
BS
24#define DPRINTF(fmt, ...) \
25do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2 26#else
001faf32 27#define DPRINTF(fmt, ...) do {} while(0)
2cc977e2
TS
28#endif
29
001faf32
BS
30#define BADF(fmt, ...) \
31do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2
TS
32
33#include <stdio.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <scsi/sg.h>
0d65e1f8 38#include "scsi-defs.h"
2cc977e2 39
a9dd6843 40#define SCSI_SENSE_BUF_SIZE 96
2cc977e2 41
a3b16e71
PB
42#define SG_ERR_DRIVER_TIMEOUT 0x06
43#define SG_ERR_DRIVER_SENSE 0x08
44
45#define SG_ERR_DID_OK 0x00
46#define SG_ERR_DID_NO_CONNECT 0x01
47#define SG_ERR_DID_BUS_BUSY 0x02
48#define SG_ERR_DID_TIME_OUT 0x03
2cc977e2
TS
49
50#ifndef MAX_UINT
51#define MAX_UINT ((unsigned int)-1)
52#endif
53
4c41d2ef
GH
54typedef struct SCSIGenericReq {
55 SCSIRequest req;
2cc977e2
TS
56 uint8_t *buf;
57 int buflen;
58 int len;
59 sg_io_hdr_t io_header;
4c41d2ef 60} SCSIGenericReq;
2cc977e2 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
TS
69/* Helper function for command completion. */
70static void scsi_command_complete(void *opaque, int ret)
71{
682a9b21 72 int status;
4c41d2ef 73 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
2cc977e2 74
d33e0ce2 75 r->req.aiocb = NULL;
a3b16e71 76 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
b45ef674 77 r->req.sense_len = r->io_header.sb_len_wr;
a3b16e71 78 }
89c0f643 79
a1f0cce2
HR
80 if (ret != 0) {
81 switch (ret) {
2e7cc4d6 82 case -EDOM:
682a9b21 83 status = TASK_SET_FULL;
2e7cc4d6 84 break;
a1f0cce2 85 case -ENOMEM:
682a9b21 86 status = CHECK_CONDITION;
b45ef674 87 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
a1f0cce2
HR
88 break;
89 default:
682a9b21 90 status = CHECK_CONDITION;
b45ef674 91 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
a1f0cce2
HR
92 break;
93 }
94 } else {
a3b16e71
PB
95 if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
96 r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
97 r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
98 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
682a9b21 99 status = BUSY;
2cc977e2 100 BADF("Driver Timeout\n");
a3b16e71
PB
101 } else if (r->io_header.host_status) {
102 status = CHECK_CONDITION;
103 scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
682a9b21
PB
104 } else if (r->io_header.status) {
105 status = r->io_header.status;
b45ef674 106 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
682a9b21
PB
107 status = CHECK_CONDITION;
108 } else {
109 status = GOOD;
110 }
2cc977e2 111 }
89c0f643 112 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
682a9b21 113 r, r->req.tag, status);
ed3a34a3 114
682a9b21 115 scsi_req_complete(&r->req, status);
c9501c95
PB
116 if (!r->req.io_canceled) {
117 scsi_req_unref(&r->req);
118 }
2cc977e2
TS
119}
120
121/* Cancel a pending data transfer. */
5c6c0e51 122static void scsi_cancel_io(SCSIRequest *req)
2cc977e2 123{
5c6c0e51
HR
124 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
125
126 DPRINTF("Cancel tag=0x%x\n", req->tag);
127 if (r->req.aiocb) {
128 bdrv_aio_cancel(r->req.aiocb);
c9501c95
PB
129
130 /* This reference was left in by scsi_*_data. We take ownership of
131 * it independent of whether bdrv_aio_cancel completes the request
132 * or not. */
133 scsi_req_unref(&r->req);
2cc977e2 134 }
5c6c0e51 135 r->req.aiocb = NULL;
2cc977e2
TS
136}
137
138static int execute_command(BlockDriverState *bdrv,
4c41d2ef 139 SCSIGenericReq *r, int direction,
2cc977e2
TS
140 BlockDriverCompletionFunc *complete)
141{
2cc977e2
TS
142 r->io_header.interface_id = 'S';
143 r->io_header.dxfer_direction = direction;
144 r->io_header.dxferp = r->buf;
145 r->io_header.dxfer_len = r->buflen;
29362ebe
GH
146 r->io_header.cmdp = r->req.cmd.buf;
147 r->io_header.cmd_len = r->req.cmd.len;
b45ef674
PB
148 r->io_header.mx_sb_len = sizeof(r->req.sense);
149 r->io_header.sbp = r->req.sense;
2cc977e2
TS
150 r->io_header.timeout = MAX_UINT;
151 r->io_header.usr_ptr = r;
152 r->io_header.flags |= SG_FLAG_DIRECT_IO;
153
4c41d2ef 154 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
2cc977e2
TS
155
156 return 0;
157}
158
159static void scsi_read_complete(void * opaque, int ret)
160{
4c41d2ef 161 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
9b6eef8a 162 SCSIDevice *s = r->req.dev;
2cc977e2
TS
163 int len;
164
d33e0ce2 165 r->req.aiocb = NULL;
2cc977e2 166 if (ret) {
aa2b1e89 167 DPRINTF("IO error ret %d\n", ret);
2cc977e2
TS
168 scsi_command_complete(r, ret);
169 return;
170 }
171 len = r->io_header.dxfer_len - r->io_header.resid;
4c41d2ef 172 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
2cc977e2
TS
173
174 r->len = -1;
40f16dd1 175 if (len == 0) {
89c0f643 176 scsi_command_complete(r, 0);
40f16dd1 177 } else {
9b6eef8a
PB
178 /* Snoop READ CAPACITY output to set the blocksize. */
179 if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
180 s->blocksize = ldl_be_p(&r->buf[4]);
7877903a 181 s->max_lba = ldl_be_p(&r->buf[0]);
9b6eef8a
PB
182 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
183 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
184 s->blocksize = ldl_be_p(&r->buf[8]);
7877903a 185 s->max_lba = ldq_be_p(&r->buf[0]);
9b6eef8a
PB
186 }
187 bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
188
ab9adc88 189 scsi_req_data(&r->req, len);
c9501c95
PB
190 if (!r->req.io_canceled) {
191 scsi_req_unref(&r->req);
192 }
40f16dd1 193 }
2cc977e2
TS
194}
195
196/* Read more data from scsi device into buffer. */
5c6c0e51 197static void scsi_read_data(SCSIRequest *req)
2cc977e2 198{
5c6c0e51 199 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 200 SCSIDevice *s = r->req.dev;
2cc977e2
TS
201 int ret;
202
5c6c0e51 203 DPRINTF("scsi_read_data 0x%x\n", req->tag);
c9501c95
PB
204
205 /* The request is used as the AIO opaque value, so add a ref. */
206 scsi_req_ref(&r->req);
2cc977e2
TS
207 if (r->len == -1) {
208 scsi_command_complete(r, 0);
209 return;
210 }
211
8869e103 212 ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
a1f0cce2
HR
213 if (ret < 0) {
214 scsi_command_complete(r, ret);
2cc977e2
TS
215 }
216}
217
218static void scsi_write_complete(void * opaque, int ret)
219{
4c41d2ef 220 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
8869e103 221 SCSIDevice *s = r->req.dev;
2cc977e2
TS
222
223 DPRINTF("scsi_write_complete() ret = %d\n", ret);
d33e0ce2 224 r->req.aiocb = NULL;
2cc977e2
TS
225 if (ret) {
226 DPRINTF("IO error\n");
227 scsi_command_complete(r, ret);
228 return;
229 }
230
29362ebe 231 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
8869e103
PB
232 s->type == TYPE_TAPE) {
233 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
234 DPRINTF("block size %d\n", s->blocksize);
89c0f643
AJ
235 }
236
2cc977e2
TS
237 scsi_command_complete(r, ret);
238}
239
240/* Write data to a scsi device. Returns nonzero on failure.
241 The transfer may complete asynchronously. */
42741212 242static void scsi_write_data(SCSIRequest *req)
2cc977e2 243{
5c6c0e51 244 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 245 SCSIDevice *s = r->req.dev;
2cc977e2
TS
246 int ret;
247
5c6c0e51 248 DPRINTF("scsi_write_data 0x%x\n", req->tag);
2cc977e2
TS
249 if (r->len == 0) {
250 r->len = r->buflen;
ab9adc88 251 scsi_req_data(&r->req, r->len);
42741212 252 return;
2cc977e2
TS
253 }
254
c9501c95
PB
255 /* The request is used as the AIO opaque value, so add a ref. */
256 scsi_req_ref(&r->req);
8869e103 257 ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2
HR
258 if (ret < 0) {
259 scsi_command_complete(r, ret);
2cc977e2 260 }
2cc977e2
TS
261}
262
263/* Return a pointer to the data buffer. */
5c6c0e51 264static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 265{
5c6c0e51
HR
266 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
267
2cc977e2
TS
268 return r->buf;
269}
270
2cc977e2
TS
271/* Execute a scsi command. Returns the length of the data expected by the
272 command. This will be Positive for data transfers from the device
273 (eg. disk reads), negative for transfers to the device (eg. disk writes),
274 and zero if the command does not transfer any data. */
275
5c6c0e51 276static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 277{
5c6c0e51 278 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 279 SCSIDevice *s = r->req.dev;
2cc977e2
TS
280 int ret;
281
aa2b1e89
BK
282 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
283 r->req.cmd.xfer, cmd[0]);
284
285#ifdef DEBUG_SCSI
286 {
287 int i;
288 for (i = 1; i < r->req.cmd.len; i++) {
289 printf(" 0x%02x", cmd[i]);
290 }
291 printf("\n");
292 }
293#endif
2cc977e2 294
2ec749cb 295 if (r->req.cmd.xfer == 0) {
2cc977e2 296 if (r->buf != NULL)
7267c094 297 g_free(r->buf);
2cc977e2
TS
298 r->buflen = 0;
299 r->buf = NULL;
c9501c95
PB
300 /* The request is used as the AIO opaque value, so add a ref. */
301 scsi_req_ref(&r->req);
8869e103 302 ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
a1f0cce2
HR
303 if (ret < 0) {
304 scsi_command_complete(r, ret);
305 return 0;
2cc977e2
TS
306 }
307 return 0;
308 }
309
2ec749cb 310 if (r->buflen != r->req.cmd.xfer) {
2cc977e2 311 if (r->buf != NULL)
7267c094
AL
312 g_free(r->buf);
313 r->buf = g_malloc(r->req.cmd.xfer);
2ec749cb 314 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
315 }
316
317 memset(r->buf, 0, r->buflen);
2ec749cb 318 r->len = r->req.cmd.xfer;
97a06435 319 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 320 r->len = 0;
5c6c0e51 321 return -r->req.cmd.xfer;
ad2d30f7 322 } else {
5c6c0e51 323 return r->req.cmd.xfer;
2cc977e2 324 }
2cc977e2
TS
325}
326
89c0f643
AJ
327static int get_stream_blocksize(BlockDriverState *bdrv)
328{
329 uint8_t cmd[6];
330 uint8_t buf[12];
331 uint8_t sensebuf[8];
332 sg_io_hdr_t io_header;
333 int ret;
334
335 memset(cmd, 0, sizeof(cmd));
336 memset(buf, 0, sizeof(buf));
337 cmd[0] = MODE_SENSE;
338 cmd[4] = sizeof(buf);
339
340 memset(&io_header, 0, sizeof(io_header));
341 io_header.interface_id = 'S';
342 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
343 io_header.dxfer_len = sizeof(buf);
344 io_header.dxferp = buf;
345 io_header.cmdp = cmd;
346 io_header.cmd_len = sizeof(cmd);
347 io_header.mx_sb_len = sizeof(sensebuf);
348 io_header.sbp = sensebuf;
349 io_header.timeout = 6000; /* XXX */
350
221f715d 351 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
fe0ed712 352 if (ret < 0 || io_header.driver_status || io_header.host_status) {
89c0f643 353 return -1;
fe0ed712 354 }
89c0f643
AJ
355 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
356}
357
f8b6d672
BK
358static void scsi_generic_reset(DeviceState *dev)
359{
8869e103 360 SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
f8b6d672 361
8869e103 362 scsi_device_purge_requests(s, SENSE_CODE(RESET));
f8b6d672
BK
363}
364
8869e103 365static void scsi_destroy(SCSIDevice *s)
f8b6d672 366{
8869e103
PB
367 scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
368 blockdev_mark_auto_del(s->conf.bs);
2cc977e2
TS
369}
370
8869e103 371static int scsi_generic_initfn(SCSIDevice *s)
2cc977e2
TS
372{
373 int sg_version;
2cc977e2
TS
374 struct sg_scsi_id scsiid;
375
8869e103 376 if (!s->conf.bs) {
6a84cb1f 377 error_report("drive property not set");
d52affa7
GH
378 return -1;
379 }
2cc977e2 380
d52affa7 381 /* check we are really using a /dev/sg* file */
8869e103 382 if (!bdrv_is_sg(s->conf.bs)) {
6a84cb1f 383 error_report("not /dev/sg*");
d52affa7
GH
384 return -1;
385 }
2cc977e2 386
8869e103 387 if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
620f862e
MA
388 error_report("Device doesn't support drive option werror");
389 return -1;
390 }
8869e103 391 if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
620f862e
MA
392 error_report("Device doesn't support drive option rerror");
393 return -1;
394 }
395
2cc977e2 396 /* check we are using a driver managing SG_IO (version 3 and after */
8869e103 397 if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
d52affa7 398 sg_version < 30000) {
6a84cb1f 399 error_report("scsi generic interface too old");
d52affa7
GH
400 return -1;
401 }
2cc977e2
TS
402
403 /* get LUN of the /dev/sg? */
8869e103 404 if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
6a84cb1f 405 error_report("SG_GET_SCSI_ID ioctl failed");
d52affa7
GH
406 return -1;
407 }
2cc977e2
TS
408
409 /* define device state */
8869e103
PB
410 s->type = scsiid.scsi_type;
411 DPRINTF("device type %d\n", s->type);
28b77657
PB
412 if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
413 add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
414 }
415
9b6eef8a
PB
416 switch (s->type) {
417 case TYPE_TAPE:
8869e103
PB
418 s->blocksize = get_stream_blocksize(s->conf.bs);
419 if (s->blocksize == -1) {
420 s->blocksize = 0;
421 }
9b6eef8a
PB
422 break;
423
424 /* Make a guess for block devices, we'll fix it when the guest sends.
425 * READ CAPACITY. If they don't, they likely would assume these sizes
426 * anyway. (TODO: they could also send MODE SENSE).
427 */
428 case TYPE_ROM:
429 case TYPE_WORM:
430 s->blocksize = 2048;
431 break;
432 default:
433 s->blocksize = 512;
434 break;
89c0f643 435 }
8869e103
PB
436
437 DPRINTF("block size %d\n", s->blocksize);
d52affa7
GH
438 return 0;
439}
2cc977e2 440
765d1525 441const SCSIReqOps scsi_generic_req_ops = {
8dbd4574 442 .size = sizeof(SCSIGenericReq),
12010e7b
PB
443 .free_req = scsi_free_request,
444 .send_command = scsi_send_command,
445 .read_data = scsi_read_data,
446 .write_data = scsi_write_data,
447 .cancel_io = scsi_cancel_io,
448 .get_buf = scsi_get_buf,
8dbd4574
PB
449};
450
451static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
63db0f0e 452 uint8_t *buf, void *hba_private)
8dbd4574
PB
453{
454 SCSIRequest *req;
455
456 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
457 return req;
458}
459
d52affa7
GH
460static SCSIDeviceInfo scsi_generic_info = {
461 .qdev.name = "scsi-generic",
28b77657 462 .qdev.fw_name = "disk",
d52affa7 463 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
8869e103 464 .qdev.size = sizeof(SCSIDevice),
f8b6d672 465 .qdev.reset = scsi_generic_reset,
d52affa7
GH
466 .init = scsi_generic_initfn,
467 .destroy = scsi_destroy,
5c6c0e51 468 .alloc_req = scsi_new_request,
d52affa7 469 .qdev.props = (Property[]) {
8869e103 470 DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
d52affa7
GH
471 DEFINE_PROP_END_OF_LIST(),
472 },
473};
2cc977e2 474
d52affa7
GH
475static void scsi_generic_register_devices(void)
476{
477 scsi_qdev_register(&scsi_generic_info);
2cc977e2 478}
d52affa7
GH
479device_init(scsi_generic_register_devices)
480
2cc977e2 481#endif /* __linux__ */