]> git.proxmox.com Git - qemu.git/blame - hw/scsi-generic.c
Make glib mandatory and fixup utils appropriately
[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
TS
41
42#define SG_ERR_DRIVER_TIMEOUT 0x06
43#define SG_ERR_DRIVER_SENSE 0x08
44
45#ifndef MAX_UINT
46#define MAX_UINT ((unsigned int)-1)
47#endif
48
d52affa7
GH
49typedef struct SCSIGenericState SCSIGenericState;
50
4c41d2ef
GH
51typedef struct SCSIGenericReq {
52 SCSIRequest req;
2cc977e2
TS
53 uint8_t *buf;
54 int buflen;
55 int len;
56 sg_io_hdr_t io_header;
4c41d2ef 57} SCSIGenericReq;
2cc977e2 58
d52affa7 59struct SCSIGenericState
2cc977e2 60{
d52affa7 61 SCSIDevice qdev;
428c149b 62 BlockDriverState *bs;
2cc977e2
TS
63};
64
ad2d30f7 65static void scsi_free_request(SCSIRequest *req)
2cc977e2 66{
ad2d30f7
PB
67 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
68
9af99d98 69 qemu_free(r->buf);
2cc977e2
TS
70}
71
2cc977e2
TS
72/* Helper function for command completion. */
73static void scsi_command_complete(void *opaque, int ret)
74{
682a9b21 75 int status;
4c41d2ef 76 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
2cc977e2 77
d33e0ce2 78 r->req.aiocb = NULL;
b45ef674
PB
79 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE)
80 r->req.sense_len = r->io_header.sb_len_wr;
89c0f643 81
a1f0cce2
HR
82 if (ret != 0) {
83 switch (ret) {
2e7cc4d6 84 case -EDOM:
682a9b21 85 status = TASK_SET_FULL;
2e7cc4d6 86 break;
a1f0cce2 87 case -ENOMEM:
682a9b21 88 status = CHECK_CONDITION;
b45ef674 89 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
a1f0cce2
HR
90 break;
91 default:
682a9b21 92 status = CHECK_CONDITION;
b45ef674 93 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
a1f0cce2
HR
94 break;
95 }
96 } else {
b45ef674 97 if (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) {
682a9b21 98 status = BUSY;
2cc977e2 99 BADF("Driver Timeout\n");
682a9b21
PB
100 } else if (r->io_header.status) {
101 status = r->io_header.status;
b45ef674 102 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
682a9b21
PB
103 status = CHECK_CONDITION;
104 } else {
105 status = GOOD;
106 }
2cc977e2 107 }
89c0f643 108 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
682a9b21 109 r, r->req.tag, status);
ed3a34a3 110
682a9b21 111 scsi_req_complete(&r->req, status);
2cc977e2
TS
112}
113
114/* Cancel a pending data transfer. */
5c6c0e51 115static void scsi_cancel_io(SCSIRequest *req)
2cc977e2 116{
5c6c0e51
HR
117 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
118
119 DPRINTF("Cancel tag=0x%x\n", req->tag);
120 if (r->req.aiocb) {
121 bdrv_aio_cancel(r->req.aiocb);
2cc977e2 122 }
5c6c0e51 123 r->req.aiocb = NULL;
2cc977e2
TS
124}
125
126static int execute_command(BlockDriverState *bdrv,
4c41d2ef 127 SCSIGenericReq *r, int direction,
2cc977e2
TS
128 BlockDriverCompletionFunc *complete)
129{
2cc977e2
TS
130 r->io_header.interface_id = 'S';
131 r->io_header.dxfer_direction = direction;
132 r->io_header.dxferp = r->buf;
133 r->io_header.dxfer_len = r->buflen;
29362ebe
GH
134 r->io_header.cmdp = r->req.cmd.buf;
135 r->io_header.cmd_len = r->req.cmd.len;
b45ef674
PB
136 r->io_header.mx_sb_len = sizeof(r->req.sense);
137 r->io_header.sbp = r->req.sense;
2cc977e2
TS
138 r->io_header.timeout = MAX_UINT;
139 r->io_header.usr_ptr = r;
140 r->io_header.flags |= SG_FLAG_DIRECT_IO;
141
4c41d2ef
GH
142 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
143 if (r->req.aiocb == NULL) {
2cc977e2 144 BADF("execute_command: read failed !\n");
a1f0cce2 145 return -ENOMEM;
2cc977e2
TS
146 }
147
148 return 0;
149}
150
151static void scsi_read_complete(void * opaque, int ret)
152{
4c41d2ef 153 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
2cc977e2
TS
154 int len;
155
d33e0ce2 156 r->req.aiocb = NULL;
2cc977e2 157 if (ret) {
aa2b1e89 158 DPRINTF("IO error ret %d\n", ret);
2cc977e2
TS
159 scsi_command_complete(r, ret);
160 return;
161 }
162 len = r->io_header.dxfer_len - r->io_header.resid;
4c41d2ef 163 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
2cc977e2
TS
164
165 r->len = -1;
40f16dd1 166 if (len == 0) {
89c0f643 167 scsi_command_complete(r, 0);
40f16dd1 168 } else {
ab9adc88 169 scsi_req_data(&r->req, len);
40f16dd1 170 }
2cc977e2
TS
171}
172
173/* Read more data from scsi device into buffer. */
5c6c0e51 174static void scsi_read_data(SCSIRequest *req)
2cc977e2 175{
5c6c0e51
HR
176 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
177 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
2cc977e2
TS
178 int ret;
179
5c6c0e51 180 DPRINTF("scsi_read_data 0x%x\n", req->tag);
2cc977e2
TS
181 if (r->len == -1) {
182 scsi_command_complete(r, 0);
183 return;
184 }
185
428c149b 186 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
a1f0cce2
HR
187 if (ret < 0) {
188 scsi_command_complete(r, ret);
2cc977e2
TS
189 return;
190 }
191}
192
193static void scsi_write_complete(void * opaque, int ret)
194{
4c41d2ef
GH
195 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
196 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
2cc977e2
TS
197
198 DPRINTF("scsi_write_complete() ret = %d\n", ret);
d33e0ce2 199 r->req.aiocb = NULL;
2cc977e2
TS
200 if (ret) {
201 DPRINTF("IO error\n");
202 scsi_command_complete(r, ret);
203 return;
204 }
205
29362ebe 206 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
91376656 207 s->qdev.type == TYPE_TAPE) {
b07995e3 208 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
aa2b1e89 209 DPRINTF("block size %d\n", s->qdev.blocksize);
89c0f643
AJ
210 }
211
2cc977e2
TS
212 scsi_command_complete(r, ret);
213}
214
215/* Write data to a scsi device. Returns nonzero on failure.
216 The transfer may complete asynchronously. */
42741212 217static void scsi_write_data(SCSIRequest *req)
2cc977e2 218{
5c6c0e51
HR
219 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
220 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
2cc977e2
TS
221 int ret;
222
5c6c0e51 223 DPRINTF("scsi_write_data 0x%x\n", req->tag);
2cc977e2
TS
224 if (r->len == 0) {
225 r->len = r->buflen;
ab9adc88 226 scsi_req_data(&r->req, r->len);
42741212 227 return;
2cc977e2
TS
228 }
229
428c149b 230 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2
HR
231 if (ret < 0) {
232 scsi_command_complete(r, ret);
2cc977e2 233 }
2cc977e2
TS
234}
235
236/* Return a pointer to the data buffer. */
5c6c0e51 237static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 238{
5c6c0e51
HR
239 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
240
2cc977e2
TS
241 return r->buf;
242}
243
2ec749cb 244static void scsi_req_fixup(SCSIRequest *req)
2cc977e2 245{
2ec749cb 246 switch(req->cmd.buf[0]) {
2cc977e2 247 case WRITE_10:
2ec749cb 248 req->cmd.buf[1] &= ~0x08; /* disable FUA */
2cc977e2
TS
249 break;
250 case READ_10:
2ec749cb 251 req->cmd.buf[1] &= ~0x08; /* disable FUA */
a9dd6843
AL
252 break;
253 case REWIND:
254 case START_STOP:
2ec749cb
GH
255 if (req->dev->type == TYPE_TAPE) {
256 /* force IMMED, otherwise qemu waits end of command */
257 req->cmd.buf[1] = 0x01;
258 }
a9dd6843 259 break;
a9dd6843 260 }
a9dd6843
AL
261}
262
2cc977e2
TS
263/* Execute a scsi command. Returns the length of the data expected by the
264 command. This will be Positive for data transfers from the device
265 (eg. disk reads), negative for transfers to the device (eg. disk writes),
266 and zero if the command does not transfer any data. */
267
5c6c0e51 268static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 269{
5c6c0e51
HR
270 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
271 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
2cc977e2
TS
272 int ret;
273
2ec749cb
GH
274 scsi_req_fixup(&r->req);
275
aa2b1e89
BK
276 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
277 r->req.cmd.xfer, cmd[0]);
278
279#ifdef DEBUG_SCSI
280 {
281 int i;
282 for (i = 1; i < r->req.cmd.len; i++) {
283 printf(" 0x%02x", cmd[i]);
284 }
285 printf("\n");
286 }
287#endif
2cc977e2 288
2ec749cb 289 if (r->req.cmd.xfer == 0) {
2cc977e2 290 if (r->buf != NULL)
e3c916e6 291 qemu_free(r->buf);
2cc977e2
TS
292 r->buflen = 0;
293 r->buf = NULL;
428c149b 294 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
a1f0cce2
HR
295 if (ret < 0) {
296 scsi_command_complete(r, ret);
297 return 0;
2cc977e2
TS
298 }
299 return 0;
300 }
301
2ec749cb 302 if (r->buflen != r->req.cmd.xfer) {
2cc977e2 303 if (r->buf != NULL)
e3c916e6 304 qemu_free(r->buf);
2ec749cb
GH
305 r->buf = qemu_malloc(r->req.cmd.xfer);
306 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
307 }
308
309 memset(r->buf, 0, r->buflen);
2ec749cb 310 r->len = r->req.cmd.xfer;
97a06435 311 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 312 r->len = 0;
5c6c0e51 313 return -r->req.cmd.xfer;
ad2d30f7 314 } else {
5c6c0e51 315 return r->req.cmd.xfer;
2cc977e2 316 }
2cc977e2
TS
317}
318
319static int get_blocksize(BlockDriverState *bdrv)
320{
321 uint8_t cmd[10];
322 uint8_t buf[8];
323 uint8_t sensebuf[8];
324 sg_io_hdr_t io_header;
325 int ret;
326
4f26a486
AL
327 memset(cmd, 0, sizeof(cmd));
328 memset(buf, 0, sizeof(buf));
5e30a07d 329 cmd[0] = READ_CAPACITY_10;
2cc977e2
TS
330
331 memset(&io_header, 0, sizeof(io_header));
332 io_header.interface_id = 'S';
333 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
334 io_header.dxfer_len = sizeof(buf);
335 io_header.dxferp = buf;
336 io_header.cmdp = cmd;
337 io_header.cmd_len = sizeof(cmd);
338 io_header.mx_sb_len = sizeof(sensebuf);
339 io_header.sbp = sensebuf;
340 io_header.timeout = 6000; /* XXX */
341
221f715d 342 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
7d780669 343 if (ret < 0)
2cc977e2
TS
344 return -1;
345
346 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
347}
348
89c0f643
AJ
349static int get_stream_blocksize(BlockDriverState *bdrv)
350{
351 uint8_t cmd[6];
352 uint8_t buf[12];
353 uint8_t sensebuf[8];
354 sg_io_hdr_t io_header;
355 int ret;
356
357 memset(cmd, 0, sizeof(cmd));
358 memset(buf, 0, sizeof(buf));
359 cmd[0] = MODE_SENSE;
360 cmd[4] = sizeof(buf);
361
362 memset(&io_header, 0, sizeof(io_header));
363 io_header.interface_id = 'S';
364 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
365 io_header.dxfer_len = sizeof(buf);
366 io_header.dxferp = buf;
367 io_header.cmdp = cmd;
368 io_header.cmd_len = sizeof(cmd);
369 io_header.mx_sb_len = sizeof(sensebuf);
370 io_header.sbp = sensebuf;
371 io_header.timeout = 6000; /* XXX */
372
221f715d 373 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
7d780669 374 if (ret < 0)
89c0f643
AJ
375 return -1;
376
377 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
378}
379
f8b6d672
BK
380static void scsi_generic_reset(DeviceState *dev)
381{
382 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
383
c7b48872 384 scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
f8b6d672
BK
385}
386
387static void scsi_destroy(SCSIDevice *d)
388{
389 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
390
c7b48872 391 scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
f8b6cc00 392 blockdev_mark_auto_del(s->qdev.conf.bs);
2cc977e2
TS
393}
394
d52affa7 395static int scsi_generic_initfn(SCSIDevice *dev)
2cc977e2 396{
d52affa7 397 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
2cc977e2 398 int sg_version;
2cc977e2
TS
399 struct sg_scsi_id scsiid;
400
f8b6cc00 401 if (!s->qdev.conf.bs) {
1ecda02b 402 error_report("scsi-generic: drive property not set");
d52affa7
GH
403 return -1;
404 }
f8b6cc00 405 s->bs = s->qdev.conf.bs;
2cc977e2 406
d52affa7 407 /* check we are really using a /dev/sg* file */
428c149b 408 if (!bdrv_is_sg(s->bs)) {
1ecda02b 409 error_report("scsi-generic: not /dev/sg*");
d52affa7
GH
410 return -1;
411 }
2cc977e2 412
620f862e
MA
413 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
414 error_report("Device doesn't support drive option werror");
415 return -1;
416 }
417 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
418 error_report("Device doesn't support drive option rerror");
419 return -1;
420 }
421
2cc977e2 422 /* check we are using a driver managing SG_IO (version 3 and after */
428c149b 423 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
d52affa7 424 sg_version < 30000) {
1ecda02b 425 error_report("scsi-generic: scsi generic interface too old");
d52affa7
GH
426 return -1;
427 }
2cc977e2
TS
428
429 /* get LUN of the /dev/sg? */
428c149b 430 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
1ecda02b 431 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
d52affa7
GH
432 return -1;
433 }
2cc977e2
TS
434
435 /* define device state */
91376656
GH
436 s->qdev.type = scsiid.scsi_type;
437 DPRINTF("device type %d\n", s->qdev.type);
438 if (s->qdev.type == TYPE_TAPE) {
428c149b 439 s->qdev.blocksize = get_stream_blocksize(s->bs);
b07995e3
GH
440 if (s->qdev.blocksize == -1)
441 s->qdev.blocksize = 0;
89c0f643 442 } else {
428c149b 443 s->qdev.blocksize = get_blocksize(s->bs);
89c0f643 444 /* removable media returns 0 if not present */
b07995e3 445 if (s->qdev.blocksize <= 0) {
91376656 446 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
b07995e3 447 s->qdev.blocksize = 2048;
89c0f643 448 else
b07995e3 449 s->qdev.blocksize = 512;
89c0f643
AJ
450 }
451 }
b07995e3 452 DPRINTF("block size %d\n", s->qdev.blocksize);
7d0d6950 453 bdrv_set_removable(s->bs, 0);
d52affa7
GH
454 return 0;
455}
2cc977e2 456
8dbd4574
PB
457static SCSIReqOps scsi_generic_req_ops = {
458 .size = sizeof(SCSIGenericReq),
12010e7b
PB
459 .free_req = scsi_free_request,
460 .send_command = scsi_send_command,
461 .read_data = scsi_read_data,
462 .write_data = scsi_write_data,
463 .cancel_io = scsi_cancel_io,
464 .get_buf = scsi_get_buf,
8dbd4574
PB
465};
466
467static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
468 void *hba_private)
469{
470 SCSIRequest *req;
471
472 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
473 return req;
474}
475
d52affa7
GH
476static SCSIDeviceInfo scsi_generic_info = {
477 .qdev.name = "scsi-generic",
478 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
479 .qdev.size = sizeof(SCSIGenericState),
f8b6d672 480 .qdev.reset = scsi_generic_reset,
d52affa7
GH
481 .init = scsi_generic_initfn,
482 .destroy = scsi_destroy,
5c6c0e51 483 .alloc_req = scsi_new_request,
d52affa7 484 .qdev.props = (Property[]) {
428c149b 485 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
d52affa7
GH
486 DEFINE_PROP_END_OF_LIST(),
487 },
488};
2cc977e2 489
d52affa7
GH
490static void scsi_generic_register_devices(void)
491{
492 scsi_qdev_register(&scsi_generic_info);
2cc977e2 493}
d52affa7
GH
494device_init(scsi_generic_register_devices)
495
2cc977e2 496#endif /* __linux__ */