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