]> Git Repo - qemu.git/blob - hw/scsi-generic.c
scsi: make write_data return void
[qemu.git] / hw / scsi-generic.c
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 <[email protected]>
9  *
10  * This code is licenced under the LGPL.
11  *
12  */
13
14 #include "qemu-common.h"
15 #include "qemu-error.h"
16 #include "scsi.h"
17 #include "blockdev.h"
18
19 #ifdef __linux__
20
21 //#define DEBUG_SCSI
22
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
29
30 #define BADF(fmt, ...) \
31 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
32
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"
39
40 #define SCSI_SENSE_BUF_SIZE 96
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
49 typedef struct SCSIGenericState SCSIGenericState;
50
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;
58
59 struct SCSIGenericState
60 {
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;
67 };
68
69 static void scsi_set_sense(SCSIGenericState *s, SCSISense sense)
70 {
71     s->senselen = scsi_build_sense(sense, s->sensebuf, SCSI_SENSE_BUF_SIZE, 0);
72     s->driver_status = SG_ERR_DRIVER_SENSE;
73 }
74
75 static void scsi_clear_sense(SCSIGenericState *s)
76 {
77     memset(s->sensebuf, 0, SCSI_SENSE_BUF_SIZE);
78     s->senselen = 0;
79     s->driver_status = 0;
80 }
81
82 static int scsi_get_sense(SCSIRequest *req, uint8_t *outbuf, int len)
83 {
84     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
85     int size = SCSI_SENSE_BUF_SIZE;
86
87     if (!(s->driver_status & SG_ERR_DRIVER_SENSE)) {
88         size = scsi_build_sense(SENSE_CODE(NO_SENSE), s->sensebuf,
89                                 SCSI_SENSE_BUF_SIZE, 0);
90     }
91     if (size > len) {
92         size = len;
93     }
94     memcpy(outbuf, s->sensebuf, size);
95
96     return size;
97 }
98
99 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
100 {
101     SCSIRequest *req;
102
103     req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun);
104     return req;
105 }
106
107 static void scsi_free_request(SCSIRequest *req)
108 {
109     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
110
111     qemu_free(r->buf);
112 }
113
114 /* Helper function for command completion.  */
115 static void scsi_command_complete(void *opaque, int ret)
116 {
117     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
118     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
119
120     r->req.aiocb = NULL;
121     s->driver_status = r->io_header.driver_status;
122     if (s->driver_status & SG_ERR_DRIVER_SENSE)
123         s->senselen = r->io_header.sb_len_wr;
124
125     if (ret != 0) {
126         switch (ret) {
127         case -EINVAL:
128             r->req.status = CHECK_CONDITION;
129             scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
130             break;
131         case -ENOMEM:
132             r->req.status = CHECK_CONDITION;
133             scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
134             break;
135         default:
136             r->req.status = CHECK_CONDITION;
137             scsi_set_sense(s, SENSE_CODE(IO_ERROR));
138             break;
139         }
140     } else {
141         if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
142             r->req.status = BUSY;
143             BADF("Driver Timeout\n");
144         } else if (r->io_header.status)
145             r->req.status = r->io_header.status;
146         else if (s->driver_status & SG_ERR_DRIVER_SENSE)
147             r->req.status = CHECK_CONDITION;
148         else
149             r->req.status = GOOD;
150     }
151     DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
152             r, r->req.tag, r->req.status);
153
154     scsi_req_complete(&r->req);
155 }
156
157 /* Cancel a pending data transfer.  */
158 static void scsi_cancel_io(SCSIRequest *req)
159 {
160     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
161
162     DPRINTF("Cancel tag=0x%x\n", req->tag);
163     if (r->req.aiocb) {
164         bdrv_aio_cancel(r->req.aiocb);
165     }
166     r->req.aiocb = NULL;
167 }
168
169 static int execute_command(BlockDriverState *bdrv,
170                            SCSIGenericReq *r, int direction,
171                            BlockDriverCompletionFunc *complete)
172 {
173     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
174
175     r->io_header.interface_id = 'S';
176     r->io_header.dxfer_direction = direction;
177     r->io_header.dxferp = r->buf;
178     r->io_header.dxfer_len = r->buflen;
179     r->io_header.cmdp = r->req.cmd.buf;
180     r->io_header.cmd_len = r->req.cmd.len;
181     r->io_header.mx_sb_len = sizeof(s->sensebuf);
182     r->io_header.sbp = s->sensebuf;
183     r->io_header.timeout = MAX_UINT;
184     r->io_header.usr_ptr = r;
185     r->io_header.flags |= SG_FLAG_DIRECT_IO;
186
187     r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
188     if (r->req.aiocb == NULL) {
189         BADF("execute_command: read failed !\n");
190         return -ENOMEM;
191     }
192
193     return 0;
194 }
195
196 static void scsi_read_complete(void * opaque, int ret)
197 {
198     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
199     int len;
200
201     r->req.aiocb = NULL;
202     if (ret) {
203         DPRINTF("IO error ret %d\n", ret);
204         scsi_command_complete(r, ret);
205         return;
206     }
207     len = r->io_header.dxfer_len - r->io_header.resid;
208     DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
209
210     r->len = -1;
211     if (len == 0) {
212         scsi_command_complete(r, 0);
213     } else {
214         scsi_req_data(&r->req, len);
215     }
216 }
217
218 /* Read more data from scsi device into buffer.  */
219 static void scsi_read_data(SCSIRequest *req)
220 {
221     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
222     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
223     int ret;
224
225     DPRINTF("scsi_read_data 0x%x\n", req->tag);
226     if (r->len == -1) {
227         scsi_command_complete(r, 0);
228         return;
229     }
230
231     if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
232     {
233         s->senselen = MIN(r->len, s->senselen);
234         memcpy(r->buf, s->sensebuf, s->senselen);
235         r->io_header.driver_status = 0;
236         r->io_header.status = 0;
237         r->io_header.dxfer_len  = s->senselen;
238         r->len = -1;
239         DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, s->senselen);
240         DPRINTF("Sense: %d %d %d %d %d %d %d %d\n",
241                 r->buf[0], r->buf[1], r->buf[2], r->buf[3],
242                 r->buf[4], r->buf[5], r->buf[6], r->buf[7]);
243         scsi_req_data(&r->req, s->senselen);
244         /* Clear sensebuf after REQUEST_SENSE */
245         scsi_clear_sense(s);
246         return;
247     }
248
249     ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
250     if (ret < 0) {
251         scsi_command_complete(r, ret);
252         return;
253     }
254 }
255
256 static void scsi_write_complete(void * opaque, int ret)
257 {
258     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
259     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
260
261     DPRINTF("scsi_write_complete() ret = %d\n", ret);
262     r->req.aiocb = NULL;
263     if (ret) {
264         DPRINTF("IO error\n");
265         scsi_command_complete(r, ret);
266         return;
267     }
268
269     if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
270         s->qdev.type == TYPE_TAPE) {
271         s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
272         DPRINTF("block size %d\n", s->qdev.blocksize);
273     }
274
275     scsi_command_complete(r, ret);
276 }
277
278 /* Write data to a scsi device.  Returns nonzero on failure.
279    The transfer may complete asynchronously.  */
280 static void scsi_write_data(SCSIRequest *req)
281 {
282     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
283     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
284     int ret;
285
286     DPRINTF("scsi_write_data 0x%x\n", req->tag);
287     if (r->len == 0) {
288         r->len = r->buflen;
289         scsi_req_data(&r->req, r->len);
290         return;
291     }
292
293     ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
294     if (ret < 0) {
295         scsi_command_complete(r, ret);
296     }
297 }
298
299 /* Return a pointer to the data buffer.  */
300 static uint8_t *scsi_get_buf(SCSIRequest *req)
301 {
302     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
303
304     return r->buf;
305 }
306
307 static void scsi_req_fixup(SCSIRequest *req)
308 {
309     switch(req->cmd.buf[0]) {
310     case WRITE_10:
311         req->cmd.buf[1] &= ~0x08;       /* disable FUA */
312         break;
313     case READ_10:
314         req->cmd.buf[1] &= ~0x08;       /* disable FUA */
315         break;
316     case REWIND:
317     case START_STOP:
318         if (req->dev->type == TYPE_TAPE) {
319             /* force IMMED, otherwise qemu waits end of command */
320             req->cmd.buf[1] = 0x01;
321         }
322         break;
323     }
324 }
325
326 /* Execute a scsi command.  Returns the length of the data expected by the
327    command.  This will be Positive for data transfers from the device
328    (eg. disk reads), negative for transfers to the device (eg. disk writes),
329    and zero if the command does not transfer any data.  */
330
331 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
332 {
333     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
334     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
335     int ret;
336
337     if (cmd[0] != REQUEST_SENSE &&
338         (req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
339         DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
340         scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
341         r->req.status = CHECK_CONDITION;
342         scsi_req_complete(&r->req);
343         return 0;
344     }
345
346     if (-1 == scsi_req_parse(&r->req, cmd)) {
347         BADF("Unsupported command length, command %x\n", cmd[0]);
348         scsi_command_complete(r, -EINVAL);
349         return 0;
350     }
351     scsi_req_fixup(&r->req);
352
353     DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
354             r->req.cmd.xfer, cmd[0]);
355
356 #ifdef DEBUG_SCSI
357     {
358         int i;
359         for (i = 1; i < r->req.cmd.len; i++) {
360             printf(" 0x%02x", cmd[i]);
361         }
362         printf("\n");
363     }
364 #endif
365
366     if (r->req.cmd.xfer == 0) {
367         if (r->buf != NULL)
368             qemu_free(r->buf);
369         r->buflen = 0;
370         r->buf = NULL;
371         ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
372         if (ret < 0) {
373             scsi_command_complete(r, ret);
374             return 0;
375         }
376         return 0;
377     }
378
379     if (r->buflen != r->req.cmd.xfer) {
380         if (r->buf != NULL)
381             qemu_free(r->buf);
382         r->buf = qemu_malloc(r->req.cmd.xfer);
383         r->buflen = r->req.cmd.xfer;
384     }
385
386     memset(r->buf, 0, r->buflen);
387     r->len = r->req.cmd.xfer;
388     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
389         r->len = 0;
390         return -r->req.cmd.xfer;
391     } else {
392         return r->req.cmd.xfer;
393     }
394 }
395
396 static int get_blocksize(BlockDriverState *bdrv)
397 {
398     uint8_t cmd[10];
399     uint8_t buf[8];
400     uint8_t sensebuf[8];
401     sg_io_hdr_t io_header;
402     int ret;
403
404     memset(cmd, 0, sizeof(cmd));
405     memset(buf, 0, sizeof(buf));
406     cmd[0] = READ_CAPACITY;
407
408     memset(&io_header, 0, sizeof(io_header));
409     io_header.interface_id = 'S';
410     io_header.dxfer_direction = SG_DXFER_FROM_DEV;
411     io_header.dxfer_len = sizeof(buf);
412     io_header.dxferp = buf;
413     io_header.cmdp = cmd;
414     io_header.cmd_len = sizeof(cmd);
415     io_header.mx_sb_len = sizeof(sensebuf);
416     io_header.sbp = sensebuf;
417     io_header.timeout = 6000; /* XXX */
418
419     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
420     if (ret < 0)
421         return -1;
422
423     return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
424 }
425
426 static int get_stream_blocksize(BlockDriverState *bdrv)
427 {
428     uint8_t cmd[6];
429     uint8_t buf[12];
430     uint8_t sensebuf[8];
431     sg_io_hdr_t io_header;
432     int ret;
433
434     memset(cmd, 0, sizeof(cmd));
435     memset(buf, 0, sizeof(buf));
436     cmd[0] = MODE_SENSE;
437     cmd[4] = sizeof(buf);
438
439     memset(&io_header, 0, sizeof(io_header));
440     io_header.interface_id = 'S';
441     io_header.dxfer_direction = SG_DXFER_FROM_DEV;
442     io_header.dxfer_len = sizeof(buf);
443     io_header.dxferp = buf;
444     io_header.cmdp = cmd;
445     io_header.cmd_len = sizeof(cmd);
446     io_header.mx_sb_len = sizeof(sensebuf);
447     io_header.sbp = sensebuf;
448     io_header.timeout = 6000; /* XXX */
449
450     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
451     if (ret < 0)
452         return -1;
453
454     return (buf[9] << 16) | (buf[10] << 8) | buf[11];
455 }
456
457 static void scsi_generic_reset(DeviceState *dev)
458 {
459     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
460
461     scsi_device_purge_requests(&s->qdev);
462 }
463
464 static void scsi_destroy(SCSIDevice *d)
465 {
466     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
467
468     scsi_device_purge_requests(&s->qdev);
469     blockdev_mark_auto_del(s->qdev.conf.bs);
470 }
471
472 static int scsi_generic_initfn(SCSIDevice *dev)
473 {
474     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
475     int sg_version;
476     struct sg_scsi_id scsiid;
477
478     if (!s->qdev.conf.bs) {
479         error_report("scsi-generic: drive property not set");
480         return -1;
481     }
482     s->bs = s->qdev.conf.bs;
483
484     /* check we are really using a /dev/sg* file */
485     if (!bdrv_is_sg(s->bs)) {
486         error_report("scsi-generic: not /dev/sg*");
487         return -1;
488     }
489
490     if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
491         error_report("Device doesn't support drive option werror");
492         return -1;
493     }
494     if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
495         error_report("Device doesn't support drive option rerror");
496         return -1;
497     }
498
499     /* check we are using a driver managing SG_IO (version 3 and after */
500     if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
501         sg_version < 30000) {
502         error_report("scsi-generic: scsi generic interface too old");
503         return -1;
504     }
505
506     /* get LUN of the /dev/sg? */
507     if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
508         error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
509         return -1;
510     }
511
512     /* define device state */
513     s->lun = scsiid.lun;
514     DPRINTF("LUN %d\n", s->lun);
515     s->qdev.type = scsiid.scsi_type;
516     DPRINTF("device type %d\n", s->qdev.type);
517     if (s->qdev.type == TYPE_TAPE) {
518         s->qdev.blocksize = get_stream_blocksize(s->bs);
519         if (s->qdev.blocksize == -1)
520             s->qdev.blocksize = 0;
521     } else {
522         s->qdev.blocksize = get_blocksize(s->bs);
523         /* removable media returns 0 if not present */
524         if (s->qdev.blocksize <= 0) {
525             if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
526                 s->qdev.blocksize = 2048;
527             else
528                 s->qdev.blocksize = 512;
529         }
530     }
531     DPRINTF("block size %d\n", s->qdev.blocksize);
532     s->driver_status = 0;
533     memset(s->sensebuf, 0, sizeof(s->sensebuf));
534     bdrv_set_removable(s->bs, 0);
535     return 0;
536 }
537
538 static SCSIDeviceInfo scsi_generic_info = {
539     .qdev.name    = "scsi-generic",
540     .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
541     .qdev.size    = sizeof(SCSIGenericState),
542     .qdev.reset   = scsi_generic_reset,
543     .init         = scsi_generic_initfn,
544     .destroy      = scsi_destroy,
545     .alloc_req    = scsi_new_request,
546     .free_req     = scsi_free_request,
547     .send_command = scsi_send_command,
548     .read_data    = scsi_read_data,
549     .write_data   = scsi_write_data,
550     .cancel_io    = scsi_cancel_io,
551     .get_buf      = scsi_get_buf,
552     .get_sense    = scsi_get_sense,
553     .qdev.props   = (Property[]) {
554         DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
555         DEFINE_PROP_END_OF_LIST(),
556     },
557 };
558
559 static void scsi_generic_register_devices(void)
560 {
561     scsi_qdev_register(&scsi_generic_info);
562 }
563 device_init(scsi_generic_register_devices)
564
565 #endif /* __linux__ */
This page took 0.057261 seconds and 4 git commands to generate.