acpi: fix file size check with -acpitable.
[qemu/lumag.git] / hw / scsi-generic.c
blobaa4f62ae57125c0088b621741ffc0bd40e92fb11
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 licenced 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;
63 int lun;
64 int driver_status;
65 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
66 uint8_t senselen;
69 static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
71 SCSIRequest *req;
73 req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
74 return DO_UPCAST(SCSIGenericReq, req, req);
77 static void scsi_remove_request(SCSIGenericReq *r)
79 qemu_free(r->buf);
80 scsi_req_free(&r->req);
83 static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
85 return DO_UPCAST(SCSIGenericReq, req, scsi_req_find(&s->qdev, tag));
88 /* Helper function for command completion. */
89 static void scsi_command_complete(void *opaque, int ret)
91 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
92 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
94 s->driver_status = r->io_header.driver_status;
95 if (s->driver_status & SG_ERR_DRIVER_SENSE)
96 s->senselen = r->io_header.sb_len_wr;
98 if (ret != 0)
99 r->req.status = BUSY << 1;
100 else {
101 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
102 r->req.status = BUSY << 1;
103 BADF("Driver Timeout\n");
104 } else if (r->io_header.status)
105 r->req.status = r->io_header.status;
106 else if (s->driver_status & SG_ERR_DRIVER_SENSE)
107 r->req.status = CHECK_CONDITION << 1;
108 else
109 r->req.status = GOOD << 1;
111 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
112 r, r->req.tag, r->req.status);
114 scsi_req_complete(&r->req);
115 scsi_remove_request(r);
118 /* Cancel a pending data transfer. */
119 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
121 DPRINTF("scsi_cancel_io 0x%x\n", tag);
122 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
123 SCSIGenericReq *r;
124 DPRINTF("Cancel tag=0x%x\n", tag);
125 r = scsi_find_request(s, tag);
126 if (r) {
127 if (r->req.aiocb)
128 bdrv_aio_cancel(r->req.aiocb);
129 r->req.aiocb = NULL;
130 scsi_remove_request(r);
134 static int execute_command(BlockDriverState *bdrv,
135 SCSIGenericReq *r, int direction,
136 BlockDriverCompletionFunc *complete)
138 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
140 r->io_header.interface_id = 'S';
141 r->io_header.dxfer_direction = direction;
142 r->io_header.dxferp = r->buf;
143 r->io_header.dxfer_len = r->buflen;
144 r->io_header.cmdp = r->req.cmd.buf;
145 r->io_header.cmd_len = r->req.cmd.len;
146 r->io_header.mx_sb_len = sizeof(s->sensebuf);
147 r->io_header.sbp = s->sensebuf;
148 r->io_header.timeout = MAX_UINT;
149 r->io_header.usr_ptr = r;
150 r->io_header.flags |= SG_FLAG_DIRECT_IO;
152 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
153 if (r->req.aiocb == NULL) {
154 BADF("execute_command: read failed !\n");
155 return -1;
158 return 0;
161 static void scsi_read_complete(void * opaque, int ret)
163 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
164 int len;
166 if (ret) {
167 DPRINTF("IO error\n");
168 scsi_command_complete(r, ret);
169 return;
171 len = r->io_header.dxfer_len - r->io_header.resid;
172 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
174 r->len = -1;
175 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
176 if (len == 0)
177 scsi_command_complete(r, 0);
180 /* Read more data from scsi device into buffer. */
181 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
183 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
184 SCSIGenericReq *r;
185 int ret;
187 DPRINTF("scsi_read_data 0x%x\n", tag);
188 r = scsi_find_request(s, tag);
189 if (!r) {
190 BADF("Bad read tag 0x%x\n", tag);
191 /* ??? This is the wrong error. */
192 scsi_command_complete(r, -EINVAL);
193 return;
196 if (r->len == -1) {
197 scsi_command_complete(r, 0);
198 return;
201 if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
203 s->senselen = MIN(r->len, s->senselen);
204 memcpy(r->buf, s->sensebuf, s->senselen);
205 r->io_header.driver_status = 0;
206 r->io_header.status = 0;
207 r->io_header.dxfer_len = s->senselen;
208 r->len = -1;
209 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
210 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
211 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
212 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
213 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, s->senselen);
214 return;
217 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
218 if (ret == -1) {
219 scsi_command_complete(r, -EINVAL);
220 return;
224 static void scsi_write_complete(void * opaque, int ret)
226 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
227 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
229 DPRINTF("scsi_write_complete() ret = %d\n", ret);
230 if (ret) {
231 DPRINTF("IO error\n");
232 scsi_command_complete(r, ret);
233 return;
236 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
237 s->qdev.type == TYPE_TAPE) {
238 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
239 DPRINTF("block size %d\n", s->blocksize);
242 scsi_command_complete(r, ret);
245 /* Write data to a scsi device. Returns nonzero on failure.
246 The transfer may complete asynchronously. */
247 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
249 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
250 SCSIGenericReq *r;
251 int ret;
253 DPRINTF("scsi_write_data 0x%x\n", tag);
254 r = scsi_find_request(s, tag);
255 if (!r) {
256 BADF("Bad write tag 0x%x\n", tag);
257 /* ??? This is the wrong error. */
258 scsi_command_complete(r, -EINVAL);
259 return 0;
262 if (r->len == 0) {
263 r->len = r->buflen;
264 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->len);
265 return 0;
268 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
269 if (ret == -1) {
270 scsi_command_complete(r, -EINVAL);
271 return 1;
274 return 0;
277 /* Return a pointer to the data buffer. */
278 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
280 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
281 SCSIGenericReq *r;
282 r = scsi_find_request(s, tag);
283 if (!r) {
284 BADF("Bad buffer tag 0x%x\n", tag);
285 return NULL;
287 return r->buf;
290 static void scsi_req_fixup(SCSIRequest *req)
292 switch(req->cmd.buf[0]) {
293 case WRITE_10:
294 req->cmd.buf[1] &= ~0x08; /* disable FUA */
295 break;
296 case READ_10:
297 req->cmd.buf[1] &= ~0x08; /* disable FUA */
298 break;
299 case REWIND:
300 case START_STOP:
301 if (req->dev->type == TYPE_TAPE) {
302 /* force IMMED, otherwise qemu waits end of command */
303 req->cmd.buf[1] = 0x01;
305 break;
309 /* Execute a scsi command. Returns the length of the data expected by the
310 command. This will be Positive for data transfers from the device
311 (eg. disk reads), negative for transfers to the device (eg. disk writes),
312 and zero if the command does not transfer any data. */
314 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
315 uint8_t *cmd, int lun)
317 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
318 SCSIGenericReq *r;
319 SCSIBus *bus;
320 int ret;
322 if (cmd[0] != REQUEST_SENSE &&
323 (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
324 DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
326 s->sensebuf[0] = 0x70;
327 s->sensebuf[1] = 0x00;
328 s->sensebuf[2] = ILLEGAL_REQUEST;
329 s->sensebuf[3] = 0x00;
330 s->sensebuf[4] = 0x00;
331 s->sensebuf[5] = 0x00;
332 s->sensebuf[6] = 0x00;
333 s->senselen = 7;
334 s->driver_status = SG_ERR_DRIVER_SENSE;
335 bus = scsi_bus_from_device(d);
336 bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
337 return 0;
340 r = scsi_find_request(s, tag);
341 if (r) {
342 BADF("Tag 0x%x already in use %p\n", tag, r);
343 scsi_cancel_io(d, tag);
345 r = scsi_new_request(d, tag, lun);
347 if (-1 == scsi_req_parse(&r->req, cmd)) {
348 BADF("Unsupported command length, command %x\n", cmd[0]);
349 scsi_remove_request(r);
350 return 0;
352 scsi_req_fixup(&r->req);
354 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
355 cmd[0], r->req.cmd.xfer);
357 if (r->req.cmd.xfer == 0) {
358 if (r->buf != NULL)
359 qemu_free(r->buf);
360 r->buflen = 0;
361 r->buf = NULL;
362 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
363 if (ret == -1) {
364 scsi_command_complete(r, -EINVAL);
365 return 0;
367 return 0;
370 if (r->buflen != r->req.cmd.xfer) {
371 if (r->buf != NULL)
372 qemu_free(r->buf);
373 r->buf = qemu_malloc(r->req.cmd.xfer);
374 r->buflen = r->req.cmd.xfer;
377 memset(r->buf, 0, r->buflen);
378 r->len = r->req.cmd.xfer;
379 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
380 r->len = 0;
381 return -r->req.cmd.xfer;
384 return r->req.cmd.xfer;
387 static int get_blocksize(BlockDriverState *bdrv)
389 uint8_t cmd[10];
390 uint8_t buf[8];
391 uint8_t sensebuf[8];
392 sg_io_hdr_t io_header;
393 int ret;
395 memset(cmd, 0, sizeof(cmd));
396 memset(buf, 0, sizeof(buf));
397 cmd[0] = READ_CAPACITY;
399 memset(&io_header, 0, sizeof(io_header));
400 io_header.interface_id = 'S';
401 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
402 io_header.dxfer_len = sizeof(buf);
403 io_header.dxferp = buf;
404 io_header.cmdp = cmd;
405 io_header.cmd_len = sizeof(cmd);
406 io_header.mx_sb_len = sizeof(sensebuf);
407 io_header.sbp = sensebuf;
408 io_header.timeout = 6000; /* XXX */
410 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
411 if (ret < 0)
412 return -1;
414 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
417 static int get_stream_blocksize(BlockDriverState *bdrv)
419 uint8_t cmd[6];
420 uint8_t buf[12];
421 uint8_t sensebuf[8];
422 sg_io_hdr_t io_header;
423 int ret;
425 memset(cmd, 0, sizeof(cmd));
426 memset(buf, 0, sizeof(buf));
427 cmd[0] = MODE_SENSE;
428 cmd[4] = sizeof(buf);
430 memset(&io_header, 0, sizeof(io_header));
431 io_header.interface_id = 'S';
432 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
433 io_header.dxfer_len = sizeof(buf);
434 io_header.dxferp = buf;
435 io_header.cmdp = cmd;
436 io_header.cmd_len = sizeof(cmd);
437 io_header.mx_sb_len = sizeof(sensebuf);
438 io_header.sbp = sensebuf;
439 io_header.timeout = 6000; /* XXX */
441 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
442 if (ret < 0)
443 return -1;
445 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
448 static void scsi_destroy(SCSIDevice *d)
450 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
451 SCSIGenericReq *r;
453 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
454 r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
455 scsi_remove_request(r);
457 blockdev_mark_auto_del(s->qdev.conf.bs);
460 static int scsi_generic_initfn(SCSIDevice *dev)
462 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
463 int sg_version;
464 struct sg_scsi_id scsiid;
466 if (!s->qdev.conf.bs) {
467 error_report("scsi-generic: drive property not set");
468 return -1;
470 s->bs = s->qdev.conf.bs;
472 /* check we are really using a /dev/sg* file */
473 if (!bdrv_is_sg(s->bs)) {
474 error_report("scsi-generic: not /dev/sg*");
475 return -1;
478 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
479 error_report("Device doesn't support drive option werror");
480 return -1;
482 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
483 error_report("Device doesn't support drive option rerror");
484 return -1;
487 /* check we are using a driver managing SG_IO (version 3 and after */
488 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
489 sg_version < 30000) {
490 error_report("scsi-generic: scsi generic interface too old");
491 return -1;
494 /* get LUN of the /dev/sg? */
495 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
496 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
497 return -1;
500 /* define device state */
501 s->lun = scsiid.lun;
502 DPRINTF("LUN %d\n", s->lun);
503 s->qdev.type = scsiid.scsi_type;
504 DPRINTF("device type %d\n", s->qdev.type);
505 if (s->qdev.type == TYPE_TAPE) {
506 s->qdev.blocksize = get_stream_blocksize(s->bs);
507 if (s->qdev.blocksize == -1)
508 s->qdev.blocksize = 0;
509 } else {
510 s->qdev.blocksize = get_blocksize(s->bs);
511 /* removable media returns 0 if not present */
512 if (s->qdev.blocksize <= 0) {
513 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
514 s->qdev.blocksize = 2048;
515 else
516 s->qdev.blocksize = 512;
519 DPRINTF("block size %d\n", s->qdev.blocksize);
520 s->driver_status = 0;
521 memset(s->sensebuf, 0, sizeof(s->sensebuf));
522 bdrv_set_removable(s->bs, 0);
523 return 0;
526 static SCSIDeviceInfo scsi_generic_info = {
527 .qdev.name = "scsi-generic",
528 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
529 .qdev.size = sizeof(SCSIGenericState),
530 .init = scsi_generic_initfn,
531 .destroy = scsi_destroy,
532 .send_command = scsi_send_command,
533 .read_data = scsi_read_data,
534 .write_data = scsi_write_data,
535 .cancel_io = scsi_cancel_io,
536 .get_buf = scsi_get_buf,
537 .qdev.props = (Property[]) {
538 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
539 DEFINE_PROP_END_OF_LIST(),
543 static void scsi_generic_register_devices(void)
545 scsi_qdev_register(&scsi_generic_info);
547 device_init(scsi_generic_register_devices)
549 #endif /* __linux__ */