]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi-generic.c
fmopl: Fix spelling in code and comments
[mirror_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
GH
154 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
155 if (r->req.aiocb == NULL) {
2cc977e2 156 BADF("execute_command: read failed !\n");
a1f0cce2 157 return -ENOMEM;
2cc977e2
TS
158 }
159
160 return 0;
161}
162
163static void scsi_read_complete(void * opaque, int ret)
164{
4c41d2ef 165 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
9b6eef8a 166 SCSIDevice *s = r->req.dev;
2cc977e2
TS
167 int len;
168
d33e0ce2 169 r->req.aiocb = NULL;
2cc977e2 170 if (ret) {
aa2b1e89 171 DPRINTF("IO error ret %d\n", ret);
2cc977e2
TS
172 scsi_command_complete(r, ret);
173 return;
174 }
175 len = r->io_header.dxfer_len - r->io_header.resid;
4c41d2ef 176 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
2cc977e2
TS
177
178 r->len = -1;
40f16dd1 179 if (len == 0) {
89c0f643 180 scsi_command_complete(r, 0);
40f16dd1 181 } else {
9b6eef8a
PB
182 /* Snoop READ CAPACITY output to set the blocksize. */
183 if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
184 s->blocksize = ldl_be_p(&r->buf[4]);
7877903a 185 s->max_lba = ldl_be_p(&r->buf[0]);
9b6eef8a
PB
186 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
187 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
188 s->blocksize = ldl_be_p(&r->buf[8]);
7877903a 189 s->max_lba = ldq_be_p(&r->buf[0]);
9b6eef8a
PB
190 }
191 bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
192
ab9adc88 193 scsi_req_data(&r->req, len);
c9501c95
PB
194 if (!r->req.io_canceled) {
195 scsi_req_unref(&r->req);
196 }
40f16dd1 197 }
2cc977e2
TS
198}
199
200/* Read more data from scsi device into buffer. */
5c6c0e51 201static void scsi_read_data(SCSIRequest *req)
2cc977e2 202{
5c6c0e51 203 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 204 SCSIDevice *s = r->req.dev;
2cc977e2
TS
205 int ret;
206
5c6c0e51 207 DPRINTF("scsi_read_data 0x%x\n", req->tag);
c9501c95
PB
208
209 /* The request is used as the AIO opaque value, so add a ref. */
210 scsi_req_ref(&r->req);
2cc977e2
TS
211 if (r->len == -1) {
212 scsi_command_complete(r, 0);
213 return;
214 }
215
8869e103 216 ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
a1f0cce2
HR
217 if (ret < 0) {
218 scsi_command_complete(r, ret);
2cc977e2
TS
219 }
220}
221
222static void scsi_write_complete(void * opaque, int ret)
223{
4c41d2ef 224 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
8869e103 225 SCSIDevice *s = r->req.dev;
2cc977e2
TS
226
227 DPRINTF("scsi_write_complete() ret = %d\n", ret);
d33e0ce2 228 r->req.aiocb = NULL;
2cc977e2
TS
229 if (ret) {
230 DPRINTF("IO error\n");
231 scsi_command_complete(r, ret);
232 return;
233 }
234
29362ebe 235 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
8869e103
PB
236 s->type == TYPE_TAPE) {
237 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
238 DPRINTF("block size %d\n", s->blocksize);
89c0f643
AJ
239 }
240
2cc977e2
TS
241 scsi_command_complete(r, ret);
242}
243
244/* Write data to a scsi device. Returns nonzero on failure.
245 The transfer may complete asynchronously. */
42741212 246static void scsi_write_data(SCSIRequest *req)
2cc977e2 247{
5c6c0e51 248 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 249 SCSIDevice *s = r->req.dev;
2cc977e2
TS
250 int ret;
251
5c6c0e51 252 DPRINTF("scsi_write_data 0x%x\n", req->tag);
2cc977e2
TS
253 if (r->len == 0) {
254 r->len = r->buflen;
ab9adc88 255 scsi_req_data(&r->req, r->len);
42741212 256 return;
2cc977e2
TS
257 }
258
c9501c95
PB
259 /* The request is used as the AIO opaque value, so add a ref. */
260 scsi_req_ref(&r->req);
8869e103 261 ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2
HR
262 if (ret < 0) {
263 scsi_command_complete(r, ret);
2cc977e2 264 }
2cc977e2
TS
265}
266
267/* Return a pointer to the data buffer. */
5c6c0e51 268static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 269{
5c6c0e51
HR
270 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
271
2cc977e2
TS
272 return r->buf;
273}
274
2cc977e2
TS
275/* Execute a scsi command. Returns the length of the data expected by the
276 command. This will be Positive for data transfers from the device
277 (eg. disk reads), negative for transfers to the device (eg. disk writes),
278 and zero if the command does not transfer any data. */
279
5c6c0e51 280static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 281{
5c6c0e51 282 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
8869e103 283 SCSIDevice *s = r->req.dev;
2cc977e2
TS
284 int ret;
285
aa2b1e89
BK
286 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
287 r->req.cmd.xfer, cmd[0]);
288
289#ifdef DEBUG_SCSI
290 {
291 int i;
292 for (i = 1; i < r->req.cmd.len; i++) {
293 printf(" 0x%02x", cmd[i]);
294 }
295 printf("\n");
296 }
297#endif
2cc977e2 298
2ec749cb 299 if (r->req.cmd.xfer == 0) {
2cc977e2 300 if (r->buf != NULL)
7267c094 301 g_free(r->buf);
2cc977e2
TS
302 r->buflen = 0;
303 r->buf = NULL;
c9501c95
PB
304 /* The request is used as the AIO opaque value, so add a ref. */
305 scsi_req_ref(&r->req);
8869e103 306 ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
a1f0cce2
HR
307 if (ret < 0) {
308 scsi_command_complete(r, ret);
309 return 0;
2cc977e2
TS
310 }
311 return 0;
312 }
313
2ec749cb 314 if (r->buflen != r->req.cmd.xfer) {
2cc977e2 315 if (r->buf != NULL)
7267c094
AL
316 g_free(r->buf);
317 r->buf = g_malloc(r->req.cmd.xfer);
2ec749cb 318 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
319 }
320
321 memset(r->buf, 0, r->buflen);
2ec749cb 322 r->len = r->req.cmd.xfer;
97a06435 323 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 324 r->len = 0;
5c6c0e51 325 return -r->req.cmd.xfer;
ad2d30f7 326 } else {
5c6c0e51 327 return r->req.cmd.xfer;
2cc977e2 328 }
2cc977e2
TS
329}
330
89c0f643
AJ
331static int get_stream_blocksize(BlockDriverState *bdrv)
332{
333 uint8_t cmd[6];
334 uint8_t buf[12];
335 uint8_t sensebuf[8];
336 sg_io_hdr_t io_header;
337 int ret;
338
339 memset(cmd, 0, sizeof(cmd));
340 memset(buf, 0, sizeof(buf));
341 cmd[0] = MODE_SENSE;
342 cmd[4] = sizeof(buf);
343
344 memset(&io_header, 0, sizeof(io_header));
345 io_header.interface_id = 'S';
346 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
347 io_header.dxfer_len = sizeof(buf);
348 io_header.dxferp = buf;
349 io_header.cmdp = cmd;
350 io_header.cmd_len = sizeof(cmd);
351 io_header.mx_sb_len = sizeof(sensebuf);
352 io_header.sbp = sensebuf;
353 io_header.timeout = 6000; /* XXX */
354
221f715d 355 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
fe0ed712 356 if (ret < 0 || io_header.driver_status || io_header.host_status) {
89c0f643 357 return -1;
fe0ed712 358 }
89c0f643
AJ
359 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
360}
361
f8b6d672
BK
362static void scsi_generic_reset(DeviceState *dev)
363{
8869e103 364 SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
f8b6d672 365
8869e103 366 scsi_device_purge_requests(s, SENSE_CODE(RESET));
f8b6d672
BK
367}
368
8869e103 369static void scsi_destroy(SCSIDevice *s)
f8b6d672 370{
8869e103
PB
371 scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
372 blockdev_mark_auto_del(s->conf.bs);
2cc977e2
TS
373}
374
8869e103 375static int scsi_generic_initfn(SCSIDevice *s)
2cc977e2
TS
376{
377 int sg_version;
2cc977e2
TS
378 struct sg_scsi_id scsiid;
379
8869e103 380 if (!s->conf.bs) {
1ecda02b 381 error_report("scsi-generic: drive property not set");
d52affa7
GH
382 return -1;
383 }
2cc977e2 384
d52affa7 385 /* check we are really using a /dev/sg* file */
8869e103 386 if (!bdrv_is_sg(s->conf.bs)) {
1ecda02b 387 error_report("scsi-generic: not /dev/sg*");
d52affa7
GH
388 return -1;
389 }
2cc977e2 390
8869e103 391 if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
620f862e
MA
392 error_report("Device doesn't support drive option werror");
393 return -1;
394 }
8869e103 395 if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
620f862e
MA
396 error_report("Device doesn't support drive option rerror");
397 return -1;
398 }
399
2cc977e2 400 /* check we are using a driver managing SG_IO (version 3 and after */
8869e103 401 if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
d52affa7 402 sg_version < 30000) {
1ecda02b 403 error_report("scsi-generic: scsi generic interface too old");
d52affa7
GH
404 return -1;
405 }
2cc977e2
TS
406
407 /* get LUN of the /dev/sg? */
8869e103 408 if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
1ecda02b 409 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
d52affa7
GH
410 return -1;
411 }
2cc977e2
TS
412
413 /* define device state */
8869e103
PB
414 s->type = scsiid.scsi_type;
415 DPRINTF("device type %d\n", s->type);
28b77657
PB
416 if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
417 add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
418 }
419
9b6eef8a
PB
420 switch (s->type) {
421 case TYPE_TAPE:
8869e103
PB
422 s->blocksize = get_stream_blocksize(s->conf.bs);
423 if (s->blocksize == -1) {
424 s->blocksize = 0;
425 }
9b6eef8a
PB
426 break;
427
428 /* Make a guess for block devices, we'll fix it when the guest sends.
429 * READ CAPACITY. If they don't, they likely would assume these sizes
430 * anyway. (TODO: they could also send MODE SENSE).
431 */
432 case TYPE_ROM:
433 case TYPE_WORM:
434 s->blocksize = 2048;
435 break;
436 default:
437 s->blocksize = 512;
438 break;
89c0f643 439 }
8869e103
PB
440
441 DPRINTF("block size %d\n", s->blocksize);
d52affa7
GH
442 return 0;
443}
2cc977e2 444
765d1525 445const SCSIReqOps scsi_generic_req_ops = {
8dbd4574 446 .size = sizeof(SCSIGenericReq),
12010e7b
PB
447 .free_req = scsi_free_request,
448 .send_command = scsi_send_command,
449 .read_data = scsi_read_data,
450 .write_data = scsi_write_data,
451 .cancel_io = scsi_cancel_io,
452 .get_buf = scsi_get_buf,
8dbd4574
PB
453};
454
455static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
63db0f0e 456 uint8_t *buf, void *hba_private)
8dbd4574
PB
457{
458 SCSIRequest *req;
459
460 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
461 return req;
462}
463
d52affa7
GH
464static SCSIDeviceInfo scsi_generic_info = {
465 .qdev.name = "scsi-generic",
28b77657 466 .qdev.fw_name = "disk",
d52affa7 467 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
8869e103 468 .qdev.size = sizeof(SCSIDevice),
f8b6d672 469 .qdev.reset = scsi_generic_reset,
d52affa7
GH
470 .init = scsi_generic_initfn,
471 .destroy = scsi_destroy,
5c6c0e51 472 .alloc_req = scsi_new_request,
d52affa7 473 .qdev.props = (Property[]) {
8869e103 474 DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
d52affa7
GH
475 DEFINE_PROP_END_OF_LIST(),
476 },
477};
2cc977e2 478
d52affa7
GH
479static void scsi_generic_register_devices(void)
480{
481 scsi_qdev_register(&scsi_generic_info);
2cc977e2 482}
d52affa7
GH
483device_init(scsi_generic_register_devices)
484
2cc977e2 485#endif /* __linux__ */