]> Git Repo - qemu.git/blob - hw/scsi/scsi-generic.c
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
[qemu.git] / hw / scsi / 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 licensed under the LGPL.
11  *
12  */
13
14 #include "qemu-common.h"
15 #include "qemu/error-report.h"
16 #include "hw/scsi/scsi.h"
17 #include "sysemu/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 "block/scsi.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 #define SG_ERR_DID_OK          0x00
46 #define SG_ERR_DID_NO_CONNECT  0x01
47 #define SG_ERR_DID_BUS_BUSY    0x02
48 #define SG_ERR_DID_TIME_OUT    0x03
49
50 #ifndef MAX_UINT
51 #define MAX_UINT ((unsigned int)-1)
52 #endif
53
54 typedef struct SCSIGenericReq {
55     SCSIRequest req;
56     uint8_t *buf;
57     int buflen;
58     int len;
59     sg_io_hdr_t io_header;
60 } SCSIGenericReq;
61
62 static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
63 {
64     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
65
66     qemu_put_sbe32s(f, &r->buflen);
67     if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
68         assert(!r->req.sg);
69         qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
70     }
71 }
72
73 static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
74 {
75     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
76
77     qemu_get_sbe32s(f, &r->buflen);
78     if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
79         assert(!r->req.sg);
80         qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
81     }
82 }
83
84 static void scsi_free_request(SCSIRequest *req)
85 {
86     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
87
88     g_free(r->buf);
89 }
90
91 /* Helper function for command completion.  */
92 static void scsi_command_complete(void *opaque, int ret)
93 {
94     int status;
95     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
96
97     r->req.aiocb = NULL;
98     if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
99         r->req.sense_len = r->io_header.sb_len_wr;
100     }
101
102     if (ret != 0) {
103         switch (ret) {
104         case -EDOM:
105             status = TASK_SET_FULL;
106             break;
107         case -ENOMEM:
108             status = CHECK_CONDITION;
109             scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
110             break;
111         default:
112             status = CHECK_CONDITION;
113             scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
114             break;
115         }
116     } else {
117         if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
118             r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
119             r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
120             (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
121             status = BUSY;
122             BADF("Driver Timeout\n");
123         } else if (r->io_header.host_status) {
124             status = CHECK_CONDITION;
125             scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
126         } else if (r->io_header.status) {
127             status = r->io_header.status;
128         } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
129             status = CHECK_CONDITION;
130         } else {
131             status = GOOD;
132         }
133     }
134     DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
135             r, r->req.tag, status);
136
137     scsi_req_complete(&r->req, status);
138     if (!r->req.io_canceled) {
139         scsi_req_unref(&r->req);
140     }
141 }
142
143 /* Cancel a pending data transfer.  */
144 static void scsi_cancel_io(SCSIRequest *req)
145 {
146     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
147
148     DPRINTF("Cancel tag=0x%x\n", req->tag);
149     if (r->req.aiocb) {
150         bdrv_aio_cancel(r->req.aiocb);
151
152         /* This reference was left in by scsi_*_data.  We take ownership of
153          * it independent of whether bdrv_aio_cancel completes the request
154          * or not.  */
155         scsi_req_unref(&r->req);
156     }
157     r->req.aiocb = NULL;
158 }
159
160 static int execute_command(BlockDriverState *bdrv,
161                            SCSIGenericReq *r, int direction,
162                            BlockDriverCompletionFunc *complete)
163 {
164     r->io_header.interface_id = 'S';
165     r->io_header.dxfer_direction = direction;
166     r->io_header.dxferp = r->buf;
167     r->io_header.dxfer_len = r->buflen;
168     r->io_header.cmdp = r->req.cmd.buf;
169     r->io_header.cmd_len = r->req.cmd.len;
170     r->io_header.mx_sb_len = sizeof(r->req.sense);
171     r->io_header.sbp = r->req.sense;
172     r->io_header.timeout = MAX_UINT;
173     r->io_header.usr_ptr = r;
174     r->io_header.flags |= SG_FLAG_DIRECT_IO;
175
176     r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
177     if (r->req.aiocb == NULL) {
178         return -EIO;
179     }
180
181     return 0;
182 }
183
184 static void scsi_read_complete(void * opaque, int ret)
185 {
186     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
187     SCSIDevice *s = r->req.dev;
188     int len;
189
190     r->req.aiocb = NULL;
191     if (ret) {
192         DPRINTF("IO error ret %d\n", ret);
193         scsi_command_complete(r, ret);
194         return;
195     }
196     len = r->io_header.dxfer_len - r->io_header.resid;
197     DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
198
199     r->len = -1;
200     if (len == 0) {
201         scsi_command_complete(r, 0);
202     } else {
203         /* Snoop READ CAPACITY output to set the blocksize.  */
204         if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
205             (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
206             s->blocksize = ldl_be_p(&r->buf[4]);
207             s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
208         } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
209                    (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
210             s->blocksize = ldl_be_p(&r->buf[8]);
211             s->max_lba = ldq_be_p(&r->buf[0]);
212         }
213         bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
214
215         scsi_req_data(&r->req, len);
216         if (!r->req.io_canceled) {
217             scsi_req_unref(&r->req);
218         }
219     }
220 }
221
222 /* Read more data from scsi device into buffer.  */
223 static void scsi_read_data(SCSIRequest *req)
224 {
225     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
226     SCSIDevice *s = r->req.dev;
227     int ret;
228
229     DPRINTF("scsi_read_data 0x%x\n", req->tag);
230
231     /* The request is used as the AIO opaque value, so add a ref.  */
232     scsi_req_ref(&r->req);
233     if (r->len == -1) {
234         scsi_command_complete(r, 0);
235         return;
236     }
237
238     ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
239     if (ret < 0) {
240         scsi_command_complete(r, ret);
241     }
242 }
243
244 static void scsi_write_complete(void * opaque, int ret)
245 {
246     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
247     SCSIDevice *s = r->req.dev;
248
249     DPRINTF("scsi_write_complete() ret = %d\n", ret);
250     r->req.aiocb = NULL;
251     if (ret) {
252         DPRINTF("IO error\n");
253         scsi_command_complete(r, ret);
254         return;
255     }
256
257     if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
258         s->type == TYPE_TAPE) {
259         s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
260         DPRINTF("block size %d\n", s->blocksize);
261     }
262
263     scsi_command_complete(r, ret);
264 }
265
266 /* Write data to a scsi device.  Returns nonzero on failure.
267    The transfer may complete asynchronously.  */
268 static void scsi_write_data(SCSIRequest *req)
269 {
270     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
271     SCSIDevice *s = r->req.dev;
272     int ret;
273
274     DPRINTF("scsi_write_data 0x%x\n", req->tag);
275     if (r->len == 0) {
276         r->len = r->buflen;
277         scsi_req_data(&r->req, r->len);
278         return;
279     }
280
281     /* The request is used as the AIO opaque value, so add a ref.  */
282     scsi_req_ref(&r->req);
283     ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
284     if (ret < 0) {
285         scsi_command_complete(r, ret);
286     }
287 }
288
289 /* Return a pointer to the data buffer.  */
290 static uint8_t *scsi_get_buf(SCSIRequest *req)
291 {
292     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
293
294     return r->buf;
295 }
296
297 /* Execute a scsi command.  Returns the length of the data expected by the
298    command.  This will be Positive for data transfers from the device
299    (eg. disk reads), negative for transfers to the device (eg. disk writes),
300    and zero if the command does not transfer any data.  */
301
302 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
303 {
304     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
305     SCSIDevice *s = r->req.dev;
306     int ret;
307
308     DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
309             r->req.cmd.xfer, cmd[0]);
310
311 #ifdef DEBUG_SCSI
312     {
313         int i;
314         for (i = 1; i < r->req.cmd.len; i++) {
315             printf(" 0x%02x", cmd[i]);
316         }
317         printf("\n");
318     }
319 #endif
320
321     if (r->req.cmd.xfer == 0) {
322         if (r->buf != NULL)
323             g_free(r->buf);
324         r->buflen = 0;
325         r->buf = NULL;
326         /* The request is used as the AIO opaque value, so add a ref.  */
327         scsi_req_ref(&r->req);
328         ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
329         if (ret < 0) {
330             scsi_command_complete(r, ret);
331             return 0;
332         }
333         return 0;
334     }
335
336     if (r->buflen != r->req.cmd.xfer) {
337         if (r->buf != NULL)
338             g_free(r->buf);
339         r->buf = g_malloc(r->req.cmd.xfer);
340         r->buflen = r->req.cmd.xfer;
341     }
342
343     memset(r->buf, 0, r->buflen);
344     r->len = r->req.cmd.xfer;
345     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
346         r->len = 0;
347         return -r->req.cmd.xfer;
348     } else {
349         return r->req.cmd.xfer;
350     }
351 }
352
353 static int get_stream_blocksize(BlockDriverState *bdrv)
354 {
355     uint8_t cmd[6];
356     uint8_t buf[12];
357     uint8_t sensebuf[8];
358     sg_io_hdr_t io_header;
359     int ret;
360
361     memset(cmd, 0, sizeof(cmd));
362     memset(buf, 0, sizeof(buf));
363     cmd[0] = MODE_SENSE;
364     cmd[4] = sizeof(buf);
365
366     memset(&io_header, 0, sizeof(io_header));
367     io_header.interface_id = 'S';
368     io_header.dxfer_direction = SG_DXFER_FROM_DEV;
369     io_header.dxfer_len = sizeof(buf);
370     io_header.dxferp = buf;
371     io_header.cmdp = cmd;
372     io_header.cmd_len = sizeof(cmd);
373     io_header.mx_sb_len = sizeof(sensebuf);
374     io_header.sbp = sensebuf;
375     io_header.timeout = 6000; /* XXX */
376
377     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
378     if (ret < 0 || io_header.driver_status || io_header.host_status) {
379         return -1;
380     }
381     return (buf[9] << 16) | (buf[10] << 8) | buf[11];
382 }
383
384 static void scsi_generic_reset(DeviceState *dev)
385 {
386     SCSIDevice *s = SCSI_DEVICE(dev);
387
388     scsi_device_purge_requests(s, SENSE_CODE(RESET));
389 }
390
391 static void scsi_destroy(SCSIDevice *s)
392 {
393     scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
394     blockdev_mark_auto_del(s->conf.bs);
395 }
396
397 static int scsi_generic_initfn(SCSIDevice *s)
398 {
399     int sg_version;
400     struct sg_scsi_id scsiid;
401
402     if (!s->conf.bs) {
403         error_report("drive property not set");
404         return -1;
405     }
406
407     if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
408         error_report("Device doesn't support drive option werror");
409         return -1;
410     }
411     if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
412         error_report("Device doesn't support drive option rerror");
413         return -1;
414     }
415
416     /* check we are using a driver managing SG_IO (version 3 and after */
417     if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) {
418         error_report("scsi generic interface not supported");
419         return -1;
420     }
421     if (sg_version < 30000) {
422         error_report("scsi generic interface too old");
423         return -1;
424     }
425
426     /* get LUN of the /dev/sg? */
427     if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
428         error_report("SG_GET_SCSI_ID ioctl failed");
429         return -1;
430     }
431
432     /* define device state */
433     s->type = scsiid.scsi_type;
434     DPRINTF("device type %d\n", s->type);
435     if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
436         add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
437     }
438
439     switch (s->type) {
440     case TYPE_TAPE:
441         s->blocksize = get_stream_blocksize(s->conf.bs);
442         if (s->blocksize == -1) {
443             s->blocksize = 0;
444         }
445         break;
446
447         /* Make a guess for block devices, we'll fix it when the guest sends.
448          * READ CAPACITY.  If they don't, they likely would assume these sizes
449          * anyway. (TODO: they could also send MODE SENSE).
450          */
451     case TYPE_ROM:
452     case TYPE_WORM:
453         s->blocksize = 2048;
454         break;
455     default:
456         s->blocksize = 512;
457         break;
458     }
459
460     DPRINTF("block size %d\n", s->blocksize);
461     return 0;
462 }
463
464 const SCSIReqOps scsi_generic_req_ops = {
465     .size         = sizeof(SCSIGenericReq),
466     .free_req     = scsi_free_request,
467     .send_command = scsi_send_command,
468     .read_data    = scsi_read_data,
469     .write_data   = scsi_write_data,
470     .cancel_io    = scsi_cancel_io,
471     .get_buf      = scsi_get_buf,
472     .load_request = scsi_generic_load_request,
473     .save_request = scsi_generic_save_request,
474 };
475
476 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
477                                      uint8_t *buf, void *hba_private)
478 {
479     SCSIRequest *req;
480
481     req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
482     return req;
483 }
484
485 static Property scsi_generic_properties[] = {
486     DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
487     DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
488     DEFINE_PROP_END_OF_LIST(),
489 };
490
491 static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
492 {
493     DeviceClass *dc = DEVICE_CLASS(klass);
494     SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
495
496     sc->init         = scsi_generic_initfn;
497     sc->destroy      = scsi_destroy;
498     sc->alloc_req    = scsi_new_request;
499     dc->fw_name = "disk";
500     dc->desc = "pass through generic scsi device (/dev/sg*)";
501     dc->reset = scsi_generic_reset;
502     dc->props = scsi_generic_properties;
503     dc->vmsd  = &vmstate_scsi_device;
504 }
505
506 static const TypeInfo scsi_generic_info = {
507     .name          = "scsi-generic",
508     .parent        = TYPE_SCSI_DEVICE,
509     .instance_size = sizeof(SCSIDevice),
510     .class_init    = scsi_generic_class_initfn,
511 };
512
513 static void scsi_generic_register_types(void)
514 {
515     type_register_static(&scsi_generic_info);
516 }
517
518 type_init(scsi_generic_register_types)
519
520 #endif /* __linux__ */
This page took 0.055226 seconds and 4 git commands to generate.