]> Git Repo - qemu.git/blob - hw/scsi-generic.c
Merge remote-tracking branch 'qemu-kvm-tmp/memory/int128' 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     if (r->req.aiocb == NULL) {
156         BADF("execute_command: read failed !\n");
157         return -ENOMEM;
158     }
159
160     return 0;
161 }
162
163 static void scsi_read_complete(void * opaque, int ret)
164 {
165     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
166     SCSIDevice *s = r->req.dev;
167     int len;
168
169     r->req.aiocb = NULL;
170     if (ret) {
171         DPRINTF("IO error ret %d\n", ret);
172         scsi_command_complete(r, ret);
173         return;
174     }
175     len = r->io_header.dxfer_len - r->io_header.resid;
176     DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
177
178     r->len = -1;
179     if (len == 0) {
180         scsi_command_complete(r, 0);
181     } else {
182         /* Snoop READ CAPACITY output to set the blocksize.  */
183         if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
184             s->blocksize = ldl_be_p(&r->buf[4]);
185             s->max_lba = ldl_be_p(&r->buf[0]);
186         } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
187                    (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
188             s->blocksize = ldl_be_p(&r->buf[8]);
189             s->max_lba = ldq_be_p(&r->buf[0]);
190         }
191         bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
192
193         scsi_req_data(&r->req, len);
194         if (!r->req.io_canceled) {
195             scsi_req_unref(&r->req);
196         }
197     }
198 }
199
200 /* Read more data from scsi device into buffer.  */
201 static void scsi_read_data(SCSIRequest *req)
202 {
203     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
204     SCSIDevice *s = r->req.dev;
205     int ret;
206
207     DPRINTF("scsi_read_data 0x%x\n", req->tag);
208
209     /* The request is used as the AIO opaque value, so add a ref.  */
210     scsi_req_ref(&r->req);
211     if (r->len == -1) {
212         scsi_command_complete(r, 0);
213         return;
214     }
215
216     ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
217     if (ret < 0) {
218         scsi_command_complete(r, ret);
219     }
220 }
221
222 static void scsi_write_complete(void * opaque, int ret)
223 {
224     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
225     SCSIDevice *s = r->req.dev;
226
227     DPRINTF("scsi_write_complete() ret = %d\n", ret);
228     r->req.aiocb = NULL;
229     if (ret) {
230         DPRINTF("IO error\n");
231         scsi_command_complete(r, ret);
232         return;
233     }
234
235     if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
236         s->type == TYPE_TAPE) {
237         s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
238         DPRINTF("block size %d\n", s->blocksize);
239     }
240
241     scsi_command_complete(r, ret);
242 }
243
244 /* Write data to a scsi device.  Returns nonzero on failure.
245    The transfer may complete asynchronously.  */
246 static void scsi_write_data(SCSIRequest *req)
247 {
248     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
249     SCSIDevice *s = r->req.dev;
250     int ret;
251
252     DPRINTF("scsi_write_data 0x%x\n", req->tag);
253     if (r->len == 0) {
254         r->len = r->buflen;
255         scsi_req_data(&r->req, r->len);
256         return;
257     }
258
259     /* The request is used as the AIO opaque value, so add a ref.  */
260     scsi_req_ref(&r->req);
261     ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
262     if (ret < 0) {
263         scsi_command_complete(r, ret);
264     }
265 }
266
267 /* Return a pointer to the data buffer.  */
268 static uint8_t *scsi_get_buf(SCSIRequest *req)
269 {
270     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
271
272     return r->buf;
273 }
274
275 /* Execute a scsi command.  Returns the length of the data expected by the
276    command.  This will be Positive for data transfers from the device
277    (eg. disk reads), negative for transfers to the device (eg. disk writes),
278    and zero if the command does not transfer any data.  */
279
280 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
281 {
282     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
283     SCSIDevice *s = r->req.dev;
284     int ret;
285
286     DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
287             r->req.cmd.xfer, cmd[0]);
288
289 #ifdef DEBUG_SCSI
290     {
291         int i;
292         for (i = 1; i < r->req.cmd.len; i++) {
293             printf(" 0x%02x", cmd[i]);
294         }
295         printf("\n");
296     }
297 #endif
298
299     if (r->req.cmd.xfer == 0) {
300         if (r->buf != NULL)
301             g_free(r->buf);
302         r->buflen = 0;
303         r->buf = NULL;
304         /* The request is used as the AIO opaque value, so add a ref.  */
305         scsi_req_ref(&r->req);
306         ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
307         if (ret < 0) {
308             scsi_command_complete(r, ret);
309             return 0;
310         }
311         return 0;
312     }
313
314     if (r->buflen != r->req.cmd.xfer) {
315         if (r->buf != NULL)
316             g_free(r->buf);
317         r->buf = g_malloc(r->req.cmd.xfer);
318         r->buflen = r->req.cmd.xfer;
319     }
320
321     memset(r->buf, 0, r->buflen);
322     r->len = r->req.cmd.xfer;
323     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
324         r->len = 0;
325         return -r->req.cmd.xfer;
326     } else {
327         return r->req.cmd.xfer;
328     }
329 }
330
331 static int get_stream_blocksize(BlockDriverState *bdrv)
332 {
333     uint8_t cmd[6];
334     uint8_t buf[12];
335     uint8_t sensebuf[8];
336     sg_io_hdr_t io_header;
337     int ret;
338
339     memset(cmd, 0, sizeof(cmd));
340     memset(buf, 0, sizeof(buf));
341     cmd[0] = MODE_SENSE;
342     cmd[4] = sizeof(buf);
343
344     memset(&io_header, 0, sizeof(io_header));
345     io_header.interface_id = 'S';
346     io_header.dxfer_direction = SG_DXFER_FROM_DEV;
347     io_header.dxfer_len = sizeof(buf);
348     io_header.dxferp = buf;
349     io_header.cmdp = cmd;
350     io_header.cmd_len = sizeof(cmd);
351     io_header.mx_sb_len = sizeof(sensebuf);
352     io_header.sbp = sensebuf;
353     io_header.timeout = 6000; /* XXX */
354
355     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
356     if (ret < 0 || io_header.driver_status || io_header.host_status) {
357         return -1;
358     }
359     return (buf[9] << 16) | (buf[10] << 8) | buf[11];
360 }
361
362 static void scsi_generic_reset(DeviceState *dev)
363 {
364     SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
365
366     scsi_device_purge_requests(s, SENSE_CODE(RESET));
367 }
368
369 static void scsi_destroy(SCSIDevice *s)
370 {
371     scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
372     blockdev_mark_auto_del(s->conf.bs);
373 }
374
375 static int scsi_generic_initfn(SCSIDevice *s)
376 {
377     int sg_version;
378     struct sg_scsi_id scsiid;
379
380     if (!s->conf.bs) {
381         error_report("scsi-generic: drive property not set");
382         return -1;
383     }
384
385     /* check we are really using a /dev/sg* file */
386     if (!bdrv_is_sg(s->conf.bs)) {
387         error_report("scsi-generic: not /dev/sg*");
388         return -1;
389     }
390
391     if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
392         error_report("Device doesn't support drive option werror");
393         return -1;
394     }
395     if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
396         error_report("Device doesn't support drive option rerror");
397         return -1;
398     }
399
400     /* check we are using a driver managing SG_IO (version 3 and after */
401     if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
402         sg_version < 30000) {
403         error_report("scsi-generic: scsi generic interface too old");
404         return -1;
405     }
406
407     /* get LUN of the /dev/sg? */
408     if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
409         error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
410         return -1;
411     }
412
413     /* define device state */
414     s->type = scsiid.scsi_type;
415     DPRINTF("device type %d\n", s->type);
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 SCSIDeviceInfo scsi_generic_info = {
461     .qdev.name    = "scsi-generic",
462     .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
463     .qdev.size    = sizeof(SCSIDevice),
464     .qdev.reset   = scsi_generic_reset,
465     .init         = scsi_generic_initfn,
466     .destroy      = scsi_destroy,
467     .alloc_req    = scsi_new_request,
468     .qdev.props   = (Property[]) {
469         DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
470         DEFINE_PROP_END_OF_LIST(),
471     },
472 };
473
474 static void scsi_generic_register_devices(void)
475 {
476     scsi_qdev_register(&scsi_generic_info);
477 }
478 device_init(scsi_generic_register_devices)
479
480 #endif /* __linux__ */
This page took 0.052724 seconds and 4 git commands to generate.