win32: Add missing function setenv
[qemu/lumag.git] / hw / scsi-generic.c
bloba8b4176d80178b6f06a520c8e759f7b538b9ec0b
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"
18 #ifdef __linux__
20 //#define DEBUG_SCSI
22 #ifdef DEBUG_SCSI
23 #define DPRINTF(fmt, ...) \
24 do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
25 #else
26 #define DPRINTF(fmt, ...) do {} while(0)
27 #endif
29 #define BADF(fmt, ...) \
30 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <scsi/sg.h>
37 #include "scsi-defs.h"
39 #define SCSI_SENSE_BUF_SIZE 96
41 #define SG_ERR_DRIVER_TIMEOUT 0x06
42 #define SG_ERR_DRIVER_SENSE 0x08
44 #ifndef MAX_UINT
45 #define MAX_UINT ((unsigned int)-1)
46 #endif
48 typedef struct SCSIGenericState SCSIGenericState;
50 typedef struct SCSIGenericReq {
51 SCSIRequest req;
52 uint8_t *buf;
53 int buflen;
54 int len;
55 sg_io_hdr_t io_header;
56 } SCSIGenericReq;
58 struct SCSIGenericState
60 SCSIDevice qdev;
61 BlockDriverState *bs;
62 int lun;
63 int driver_status;
64 uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
65 uint8_t senselen;
68 static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
70 SCSIRequest *req;
72 req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
73 return DO_UPCAST(SCSIGenericReq, req, req);
76 static void scsi_remove_request(SCSIGenericReq *r)
78 qemu_free(r->buf);
79 scsi_req_free(&r->req);
82 static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag)
84 return DO_UPCAST(SCSIGenericReq, req, scsi_req_find(&s->qdev, tag));
87 /* Helper function for command completion. */
88 static void scsi_command_complete(void *opaque, int ret)
90 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
91 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
93 s->driver_status = r->io_header.driver_status;
94 if (s->driver_status & SG_ERR_DRIVER_SENSE)
95 s->senselen = r->io_header.sb_len_wr;
97 if (ret != 0)
98 r->req.status = BUSY << 1;
99 else {
100 if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
101 r->req.status = BUSY << 1;
102 BADF("Driver Timeout\n");
103 } else if (r->io_header.status)
104 r->req.status = r->io_header.status;
105 else if (s->driver_status & SG_ERR_DRIVER_SENSE)
106 r->req.status = CHECK_CONDITION << 1;
107 else
108 r->req.status = GOOD << 1;
110 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
111 r, r->req.tag, r->req.status);
113 scsi_req_complete(&r->req);
114 scsi_remove_request(r);
117 /* Cancel a pending data transfer. */
118 static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
120 DPRINTF("scsi_cancel_io 0x%x\n", tag);
121 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
122 SCSIGenericReq *r;
123 DPRINTF("Cancel tag=0x%x\n", tag);
124 r = scsi_find_request(s, tag);
125 if (r) {
126 if (r->req.aiocb)
127 bdrv_aio_cancel(r->req.aiocb);
128 r->req.aiocb = NULL;
129 scsi_remove_request(r);
133 static int execute_command(BlockDriverState *bdrv,
134 SCSIGenericReq *r, int direction,
135 BlockDriverCompletionFunc *complete)
137 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
139 r->io_header.interface_id = 'S';
140 r->io_header.dxfer_direction = direction;
141 r->io_header.dxferp = r->buf;
142 r->io_header.dxfer_len = r->buflen;
143 r->io_header.cmdp = r->req.cmd.buf;
144 r->io_header.cmd_len = r->req.cmd.len;
145 r->io_header.mx_sb_len = sizeof(s->sensebuf);
146 r->io_header.sbp = s->sensebuf;
147 r->io_header.timeout = MAX_UINT;
148 r->io_header.usr_ptr = r;
149 r->io_header.flags |= SG_FLAG_DIRECT_IO;
151 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
152 if (r->req.aiocb == NULL) {
153 BADF("execute_command: read failed !\n");
154 return -1;
157 return 0;
160 static void scsi_read_complete(void * opaque, int ret)
162 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
163 int len;
165 if (ret) {
166 DPRINTF("IO error\n");
167 scsi_command_complete(r, ret);
168 return;
170 len = r->io_header.dxfer_len - r->io_header.resid;
171 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
173 r->len = -1;
174 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
175 if (len == 0)
176 scsi_command_complete(r, 0);
179 /* Read more data from scsi device into buffer. */
180 static void scsi_read_data(SCSIDevice *d, uint32_t tag)
182 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
183 SCSIGenericReq *r;
184 int ret;
186 DPRINTF("scsi_read_data 0x%x\n", tag);
187 r = scsi_find_request(s, tag);
188 if (!r) {
189 BADF("Bad read tag 0x%x\n", tag);
190 /* ??? This is the wrong error. */
191 scsi_command_complete(r, -EINVAL);
192 return;
195 if (r->len == -1) {
196 scsi_command_complete(r, 0);
197 return;
200 if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
202 s->senselen = MIN(r->len, s->senselen);
203 memcpy(r->buf, s->sensebuf, s->senselen);
204 r->io_header.driver_status = 0;
205 r->io_header.status = 0;
206 r->io_header.dxfer_len = s->senselen;
207 r->len = -1;
208 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
209 DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
210 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
211 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
212 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, s->senselen);
213 return;
216 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
217 if (ret == -1) {
218 scsi_command_complete(r, -EINVAL);
219 return;
223 static void scsi_write_complete(void * opaque, int ret)
225 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
226 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
228 DPRINTF("scsi_write_complete() ret = %d\n", ret);
229 if (ret) {
230 DPRINTF("IO error\n");
231 scsi_command_complete(r, ret);
232 return;
235 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
236 s->qdev.type == TYPE_TAPE) {
237 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
238 DPRINTF("block size %d\n", s->blocksize);
241 scsi_command_complete(r, ret);
244 /* Write data to a scsi device. Returns nonzero on failure.
245 The transfer may complete asynchronously. */
246 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
248 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
249 SCSIGenericReq *r;
250 int ret;
252 DPRINTF("scsi_write_data 0x%x\n", tag);
253 r = scsi_find_request(s, tag);
254 if (!r) {
255 BADF("Bad write tag 0x%x\n", tag);
256 /* ??? This is the wrong error. */
257 scsi_command_complete(r, -EINVAL);
258 return 0;
261 if (r->len == 0) {
262 r->len = r->buflen;
263 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->len);
264 return 0;
267 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
268 if (ret == -1) {
269 scsi_command_complete(r, -EINVAL);
270 return 1;
273 return 0;
276 /* Return a pointer to the data buffer. */
277 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
279 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
280 SCSIGenericReq *r;
281 r = scsi_find_request(s, tag);
282 if (!r) {
283 BADF("Bad buffer tag 0x%x\n", tag);
284 return NULL;
286 return r->buf;
289 static void scsi_req_fixup(SCSIRequest *req)
291 switch(req->cmd.buf[0]) {
292 case WRITE_10:
293 req->cmd.buf[1] &= ~0x08; /* disable FUA */
294 break;
295 case READ_10:
296 req->cmd.buf[1] &= ~0x08; /* disable FUA */
297 break;
298 case REWIND:
299 case START_STOP:
300 if (req->dev->type == TYPE_TAPE) {
301 /* force IMMED, otherwise qemu waits end of command */
302 req->cmd.buf[1] = 0x01;
304 break;
308 /* Execute a scsi command. Returns the length of the data expected by the
309 command. This will be Positive for data transfers from the device
310 (eg. disk reads), negative for transfers to the device (eg. disk writes),
311 and zero if the command does not transfer any data. */
313 static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
314 uint8_t *cmd, int lun)
316 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
317 SCSIGenericReq *r;
318 SCSIBus *bus;
319 int ret;
321 if (cmd[0] != REQUEST_SENSE &&
322 (lun != s->lun || (cmd[1] >> 5) != s->lun)) {
323 DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
325 s->sensebuf[0] = 0x70;
326 s->sensebuf[1] = 0x00;
327 s->sensebuf[2] = ILLEGAL_REQUEST;
328 s->sensebuf[3] = 0x00;
329 s->sensebuf[4] = 0x00;
330 s->sensebuf[5] = 0x00;
331 s->sensebuf[6] = 0x00;
332 s->senselen = 7;
333 s->driver_status = SG_ERR_DRIVER_SENSE;
334 bus = scsi_bus_from_device(d);
335 bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
336 return 0;
339 r = scsi_find_request(s, tag);
340 if (r) {
341 BADF("Tag 0x%x already in use %p\n", tag, r);
342 scsi_cancel_io(d, tag);
344 r = scsi_new_request(d, tag, lun);
346 if (-1 == scsi_req_parse(&r->req, cmd)) {
347 BADF("Unsupported command length, command %x\n", cmd[0]);
348 scsi_remove_request(r);
349 return 0;
351 scsi_req_fixup(&r->req);
353 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
354 cmd[0], r->req.cmd.xfer);
356 if (r->req.cmd.xfer == 0) {
357 if (r->buf != NULL)
358 qemu_free(r->buf);
359 r->buflen = 0;
360 r->buf = NULL;
361 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
362 if (ret == -1) {
363 scsi_command_complete(r, -EINVAL);
364 return 0;
366 return 0;
369 if (r->buflen != r->req.cmd.xfer) {
370 if (r->buf != NULL)
371 qemu_free(r->buf);
372 r->buf = qemu_malloc(r->req.cmd.xfer);
373 r->buflen = r->req.cmd.xfer;
376 memset(r->buf, 0, r->buflen);
377 r->len = r->req.cmd.xfer;
378 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
379 r->len = 0;
380 return -r->req.cmd.xfer;
383 return r->req.cmd.xfer;
386 static int get_blocksize(BlockDriverState *bdrv)
388 uint8_t cmd[10];
389 uint8_t buf[8];
390 uint8_t sensebuf[8];
391 sg_io_hdr_t io_header;
392 int ret;
394 memset(cmd, 0, sizeof(cmd));
395 memset(buf, 0, sizeof(buf));
396 cmd[0] = READ_CAPACITY;
398 memset(&io_header, 0, sizeof(io_header));
399 io_header.interface_id = 'S';
400 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
401 io_header.dxfer_len = sizeof(buf);
402 io_header.dxferp = buf;
403 io_header.cmdp = cmd;
404 io_header.cmd_len = sizeof(cmd);
405 io_header.mx_sb_len = sizeof(sensebuf);
406 io_header.sbp = sensebuf;
407 io_header.timeout = 6000; /* XXX */
409 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
410 if (ret < 0)
411 return -1;
413 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
416 static int get_stream_blocksize(BlockDriverState *bdrv)
418 uint8_t cmd[6];
419 uint8_t buf[12];
420 uint8_t sensebuf[8];
421 sg_io_hdr_t io_header;
422 int ret;
424 memset(cmd, 0, sizeof(cmd));
425 memset(buf, 0, sizeof(buf));
426 cmd[0] = MODE_SENSE;
427 cmd[4] = sizeof(buf);
429 memset(&io_header, 0, sizeof(io_header));
430 io_header.interface_id = 'S';
431 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
432 io_header.dxfer_len = sizeof(buf);
433 io_header.dxferp = buf;
434 io_header.cmdp = cmd;
435 io_header.cmd_len = sizeof(cmd);
436 io_header.mx_sb_len = sizeof(sensebuf);
437 io_header.sbp = sensebuf;
438 io_header.timeout = 6000; /* XXX */
440 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
441 if (ret < 0)
442 return -1;
444 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
447 static void scsi_destroy(SCSIDevice *d)
449 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
450 SCSIGenericReq *r;
452 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
453 r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
454 scsi_remove_request(r);
456 blockdev_mark_auto_del(s->qdev.conf.bs);
459 static int scsi_generic_initfn(SCSIDevice *dev)
461 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
462 int sg_version;
463 struct sg_scsi_id scsiid;
465 if (!s->qdev.conf.bs) {
466 error_report("scsi-generic: drive property not set");
467 return -1;
469 s->bs = s->qdev.conf.bs;
471 /* check we are really using a /dev/sg* file */
472 if (!bdrv_is_sg(s->bs)) {
473 error_report("scsi-generic: not /dev/sg*");
474 return -1;
477 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
478 error_report("Device doesn't support drive option werror");
479 return -1;
481 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
482 error_report("Device doesn't support drive option rerror");
483 return -1;
486 /* check we are using a driver managing SG_IO (version 3 and after */
487 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
488 sg_version < 30000) {
489 error_report("scsi-generic: scsi generic interface too old");
490 return -1;
493 /* get LUN of the /dev/sg? */
494 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
495 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
496 return -1;
499 /* define device state */
500 s->lun = scsiid.lun;
501 DPRINTF("LUN %d\n", s->lun);
502 s->qdev.type = scsiid.scsi_type;
503 DPRINTF("device type %d\n", s->qdev.type);
504 if (s->qdev.type == TYPE_TAPE) {
505 s->qdev.blocksize = get_stream_blocksize(s->bs);
506 if (s->qdev.blocksize == -1)
507 s->qdev.blocksize = 0;
508 } else {
509 s->qdev.blocksize = get_blocksize(s->bs);
510 /* removable media returns 0 if not present */
511 if (s->qdev.blocksize <= 0) {
512 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
513 s->qdev.blocksize = 2048;
514 else
515 s->qdev.blocksize = 512;
518 DPRINTF("block size %d\n", s->qdev.blocksize);
519 s->driver_status = 0;
520 memset(s->sensebuf, 0, sizeof(s->sensebuf));
521 bdrv_set_removable(s->bs, 0);
522 return 0;
525 static SCSIDeviceInfo scsi_generic_info = {
526 .qdev.name = "scsi-generic",
527 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
528 .qdev.size = sizeof(SCSIGenericState),
529 .init = scsi_generic_initfn,
530 .destroy = scsi_destroy,
531 .send_command = scsi_send_command,
532 .read_data = scsi_read_data,
533 .write_data = scsi_write_data,
534 .cancel_io = scsi_cancel_io,
535 .get_buf = scsi_get_buf,
536 .qdev.props = (Property[]) {
537 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
538 DEFINE_PROP_END_OF_LIST(),
542 static void scsi_generic_register_devices(void)
544 scsi_qdev_register(&scsi_generic_info);
546 device_init(scsi_generic_register_devices)
548 #endif /* __linux__ */