pcie/slot: fix hotplug event
[qemu.git] / hw / scsi-generic.c
blobcb5d4f125d27a86228a637e00b4d82389de49b08
1 /*
2 * Generic SCSI Device support
4 * Copyright (c) 2007 Bull S.A.S.
5 * Based on code by Paul Brook
6 * Based on code by Fabrice Bellard
8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
10 * This code is licensed under the LGPL.
14 #include "qemu-common.h"
15 #include "qemu-error.h"
16 #include "scsi.h"
17 #include "blockdev.h"
19 #ifdef __linux__
21 //#define DEBUG_SCSI
23 #ifdef DEBUG_SCSI
24 #define DPRINTF(fmt, ...) \
25 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
26 #else
27 #define DPRINTF(fmt, ...) do {} while(0)
28 #endif
30 #define BADF(fmt, ...) \
31 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <scsi/sg.h>
38 #include "scsi-defs.h"
40 #define SCSI_SENSE_BUF_SIZE 96
42 #define SG_ERR_DRIVER_TIMEOUT 0x06
43 #define SG_ERR_DRIVER_SENSE 0x08
45 #ifndef MAX_UINT
46 #define MAX_UINT ((unsigned int)-1)
47 #endif
49 typedef struct SCSIGenericState SCSIGenericState;
51 typedef struct SCSIGenericReq {
52 SCSIRequest req;
53 uint8_t *buf;
54 int buflen;
55 int len;
56 sg_io_hdr_t io_header;
57 } SCSIGenericReq;
59 struct SCSIGenericState
61 SCSIDevice qdev;
62 BlockDriverState *bs;
65 static void scsi_free_request(SCSIRequest *req)
67 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
69 g_free(r->buf);
72 /* Helper function for command completion. */
73 static void scsi_command_complete(void *opaque, int ret)
75 int status;
76 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
78 r->req.aiocb = NULL;
79 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE)
80 r->req.sense_len = r->io_header.sb_len_wr;
82 if (ret != 0) {
83 switch (ret) {
84 case -EDOM:
85 status = TASK_SET_FULL;
86 break;
87 case -ENOMEM:
88 status = CHECK_CONDITION;
89 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
90 break;
91 default:
92 status = CHECK_CONDITION;
93 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
94 break;
96 } else {
97 if (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) {
98 status = BUSY;
99 BADF("Driver Timeout\n");
100 } else if (r->io_header.status) {
101 status = r->io_header.status;
102 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
103 status = CHECK_CONDITION;
104 } else {
105 status = GOOD;
108 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
109 r, r->req.tag, status);
111 scsi_req_complete(&r->req, status);
114 /* Cancel a pending data transfer. */
115 static void scsi_cancel_io(SCSIRequest *req)
117 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
119 DPRINTF("Cancel tag=0x%x\n", req->tag);
120 if (r->req.aiocb) {
121 bdrv_aio_cancel(r->req.aiocb);
123 r->req.aiocb = NULL;
126 static int execute_command(BlockDriverState *bdrv,
127 SCSIGenericReq *r, int direction,
128 BlockDriverCompletionFunc *complete)
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;
134 r->io_header.cmdp = r->req.cmd.buf;
135 r->io_header.cmd_len = r->req.cmd.len;
136 r->io_header.mx_sb_len = sizeof(r->req.sense);
137 r->io_header.sbp = r->req.sense;
138 r->io_header.timeout = MAX_UINT;
139 r->io_header.usr_ptr = r;
140 r->io_header.flags |= SG_FLAG_DIRECT_IO;
142 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
143 if (r->req.aiocb == NULL) {
144 BADF("execute_command: read failed !\n");
145 return -ENOMEM;
148 return 0;
151 static void scsi_read_complete(void * opaque, int ret)
153 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
154 int len;
156 r->req.aiocb = NULL;
157 if (ret) {
158 DPRINTF("IO error ret %d\n", ret);
159 scsi_command_complete(r, ret);
160 return;
162 len = r->io_header.dxfer_len - r->io_header.resid;
163 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
165 r->len = -1;
166 if (len == 0) {
167 scsi_command_complete(r, 0);
168 } else {
169 scsi_req_data(&r->req, len);
173 /* Read more data from scsi device into buffer. */
174 static void scsi_read_data(SCSIRequest *req)
176 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
177 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
178 int ret;
180 DPRINTF("scsi_read_data 0x%x\n", req->tag);
181 if (r->len == -1) {
182 scsi_command_complete(r, 0);
183 return;
186 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
187 if (ret < 0) {
188 scsi_command_complete(r, ret);
189 return;
193 static void scsi_write_complete(void * opaque, int ret)
195 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
196 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
198 DPRINTF("scsi_write_complete() ret = %d\n", ret);
199 r->req.aiocb = NULL;
200 if (ret) {
201 DPRINTF("IO error\n");
202 scsi_command_complete(r, ret);
203 return;
206 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
207 s->qdev.type == TYPE_TAPE) {
208 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
209 DPRINTF("block size %d\n", s->qdev.blocksize);
212 scsi_command_complete(r, ret);
215 /* Write data to a scsi device. Returns nonzero on failure.
216 The transfer may complete asynchronously. */
217 static void scsi_write_data(SCSIRequest *req)
219 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
220 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
221 int ret;
223 DPRINTF("scsi_write_data 0x%x\n", req->tag);
224 if (r->len == 0) {
225 r->len = r->buflen;
226 scsi_req_data(&r->req, r->len);
227 return;
230 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
231 if (ret < 0) {
232 scsi_command_complete(r, ret);
236 /* Return a pointer to the data buffer. */
237 static uint8_t *scsi_get_buf(SCSIRequest *req)
239 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
241 return r->buf;
244 static void scsi_req_fixup(SCSIRequest *req)
246 switch(req->cmd.buf[0]) {
247 case WRITE_10:
248 req->cmd.buf[1] &= ~0x08; /* disable FUA */
249 break;
250 case READ_10:
251 req->cmd.buf[1] &= ~0x08; /* disable FUA */
252 break;
253 case REWIND:
254 case START_STOP:
255 if (req->dev->type == TYPE_TAPE) {
256 /* force IMMED, otherwise qemu waits end of command */
257 req->cmd.buf[1] = 0x01;
259 break;
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. */
268 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
270 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
271 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
272 int ret;
274 scsi_req_fixup(&r->req);
276 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
277 r->req.cmd.xfer, cmd[0]);
279 #ifdef DEBUG_SCSI
281 int i;
282 for (i = 1; i < r->req.cmd.len; i++) {
283 printf(" 0x%02x", cmd[i]);
285 printf("\n");
287 #endif
289 if (r->req.cmd.xfer == 0) {
290 if (r->buf != NULL)
291 g_free(r->buf);
292 r->buflen = 0;
293 r->buf = NULL;
294 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
295 if (ret < 0) {
296 scsi_command_complete(r, ret);
297 return 0;
299 return 0;
302 if (r->buflen != r->req.cmd.xfer) {
303 if (r->buf != NULL)
304 g_free(r->buf);
305 r->buf = g_malloc(r->req.cmd.xfer);
306 r->buflen = r->req.cmd.xfer;
309 memset(r->buf, 0, r->buflen);
310 r->len = r->req.cmd.xfer;
311 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
312 r->len = 0;
313 return -r->req.cmd.xfer;
314 } else {
315 return r->req.cmd.xfer;
319 static int get_blocksize(BlockDriverState *bdrv)
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;
327 memset(cmd, 0, sizeof(cmd));
328 memset(buf, 0, sizeof(buf));
329 cmd[0] = READ_CAPACITY_10;
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 */
342 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
343 if (ret < 0)
344 return -1;
346 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
349 static int get_stream_blocksize(BlockDriverState *bdrv)
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;
357 memset(cmd, 0, sizeof(cmd));
358 memset(buf, 0, sizeof(buf));
359 cmd[0] = MODE_SENSE;
360 cmd[4] = sizeof(buf);
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 */
373 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
374 if (ret < 0)
375 return -1;
377 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
380 static void scsi_generic_reset(DeviceState *dev)
382 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
384 scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
387 static void scsi_destroy(SCSIDevice *d)
389 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
391 scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
392 blockdev_mark_auto_del(s->qdev.conf.bs);
395 static int scsi_generic_initfn(SCSIDevice *dev)
397 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
398 int sg_version;
399 struct sg_scsi_id scsiid;
401 if (!s->qdev.conf.bs) {
402 error_report("scsi-generic: drive property not set");
403 return -1;
405 s->bs = s->qdev.conf.bs;
407 /* check we are really using a /dev/sg* file */
408 if (!bdrv_is_sg(s->bs)) {
409 error_report("scsi-generic: not /dev/sg*");
410 return -1;
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;
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;
422 /* check we are using a driver managing SG_IO (version 3 and after */
423 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
424 sg_version < 30000) {
425 error_report("scsi-generic: scsi generic interface too old");
426 return -1;
429 /* get LUN of the /dev/sg? */
430 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
431 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
432 return -1;
435 /* define device state */
436 s->qdev.type = scsiid.scsi_type;
437 DPRINTF("device type %d\n", s->qdev.type);
438 if (s->qdev.type == TYPE_TAPE) {
439 s->qdev.blocksize = get_stream_blocksize(s->bs);
440 if (s->qdev.blocksize == -1)
441 s->qdev.blocksize = 0;
442 } else {
443 s->qdev.blocksize = get_blocksize(s->bs);
444 /* removable media returns 0 if not present */
445 if (s->qdev.blocksize <= 0) {
446 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
447 s->qdev.blocksize = 2048;
448 else
449 s->qdev.blocksize = 512;
452 DPRINTF("block size %d\n", s->qdev.blocksize);
453 bdrv_set_removable(s->bs, 0);
454 return 0;
457 static SCSIReqOps scsi_generic_req_ops = {
458 .size = sizeof(SCSIGenericReq),
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,
467 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
468 void *hba_private)
470 SCSIRequest *req;
472 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
473 return req;
476 static SCSIDeviceInfo scsi_generic_info = {
477 .qdev.name = "scsi-generic",
478 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
479 .qdev.size = sizeof(SCSIGenericState),
480 .qdev.reset = scsi_generic_reset,
481 .init = scsi_generic_initfn,
482 .destroy = scsi_destroy,
483 .alloc_req = scsi_new_request,
484 .qdev.props = (Property[]) {
485 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
486 DEFINE_PROP_END_OF_LIST(),
490 static void scsi_generic_register_devices(void)
492 scsi_qdev_register(&scsi_generic_info);
494 device_init(scsi_generic_register_devices)
496 #endif /* __linux__ */