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