]> Git Repo - qemu.git/blob - hw/scsi-generic.c
scsi: report unit attention on 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     qemu_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 WRITE_10:
248         req->cmd.buf[1] &= ~0x08;       /* disable FUA */
249         break;
250     case READ_10:
251         req->cmd.buf[1] &= ~0x08;       /* disable FUA */
252         break;
253     case REWIND:
254     case START_STOP:
255         if (req->dev->type == TYPE_TAPE) {
256             /* force IMMED, otherwise qemu waits end of command */
257             req->cmd.buf[1] = 0x01;
258         }
259         break;
260     }
261 }
262
263 /* Execute a scsi command.  Returns the length of the data expected by the
264    command.  This will be Positive for data transfers from the device
265    (eg. disk reads), negative for transfers to the device (eg. disk writes),
266    and zero if the command does not transfer any data.  */
267
268 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
269 {
270     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
271     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
272     int ret;
273
274     scsi_req_fixup(&r->req);
275
276     DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
277             r->req.cmd.xfer, cmd[0]);
278
279 #ifdef DEBUG_SCSI
280     {
281         int i;
282         for (i = 1; i < r->req.cmd.len; i++) {
283             printf(" 0x%02x", cmd[i]);
284         }
285         printf("\n");
286     }
287 #endif
288
289     if (r->req.cmd.xfer == 0) {
290         if (r->buf != NULL)
291             qemu_free(r->buf);
292         r->buflen = 0;
293         r->buf = NULL;
294         ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
295         if (ret < 0) {
296             scsi_command_complete(r, ret);
297             return 0;
298         }
299         return 0;
300     }
301
302     if (r->buflen != r->req.cmd.xfer) {
303         if (r->buf != NULL)
304             qemu_free(r->buf);
305         r->buf = qemu_malloc(r->req.cmd.xfer);
306         r->buflen = r->req.cmd.xfer;
307     }
308
309     memset(r->buf, 0, r->buflen);
310     r->len = r->req.cmd.xfer;
311     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
312         r->len = 0;
313         return -r->req.cmd.xfer;
314     } else {
315         return r->req.cmd.xfer;
316     }
317 }
318
319 static int get_blocksize(BlockDriverState *bdrv)
320 {
321     uint8_t cmd[10];
322     uint8_t buf[8];
323     uint8_t sensebuf[8];
324     sg_io_hdr_t io_header;
325     int ret;
326
327     memset(cmd, 0, sizeof(cmd));
328     memset(buf, 0, sizeof(buf));
329     cmd[0] = READ_CAPACITY_10;
330
331     memset(&io_header, 0, sizeof(io_header));
332     io_header.interface_id = 'S';
333     io_header.dxfer_direction = SG_DXFER_FROM_DEV;
334     io_header.dxfer_len = sizeof(buf);
335     io_header.dxferp = buf;
336     io_header.cmdp = cmd;
337     io_header.cmd_len = sizeof(cmd);
338     io_header.mx_sb_len = sizeof(sensebuf);
339     io_header.sbp = sensebuf;
340     io_header.timeout = 6000; /* XXX */
341
342     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
343     if (ret < 0)
344         return -1;
345
346     return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
347 }
348
349 static int get_stream_blocksize(BlockDriverState *bdrv)
350 {
351     uint8_t cmd[6];
352     uint8_t buf[12];
353     uint8_t sensebuf[8];
354     sg_io_hdr_t io_header;
355     int ret;
356
357     memset(cmd, 0, sizeof(cmd));
358     memset(buf, 0, sizeof(buf));
359     cmd[0] = MODE_SENSE;
360     cmd[4] = sizeof(buf);
361
362     memset(&io_header, 0, sizeof(io_header));
363     io_header.interface_id = 'S';
364     io_header.dxfer_direction = SG_DXFER_FROM_DEV;
365     io_header.dxfer_len = sizeof(buf);
366     io_header.dxferp = buf;
367     io_header.cmdp = cmd;
368     io_header.cmd_len = sizeof(cmd);
369     io_header.mx_sb_len = sizeof(sensebuf);
370     io_header.sbp = sensebuf;
371     io_header.timeout = 6000; /* XXX */
372
373     ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
374     if (ret < 0)
375         return -1;
376
377     return (buf[9] << 16) | (buf[10] << 8) | buf[11];
378 }
379
380 static void scsi_generic_reset(DeviceState *dev)
381 {
382     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
383
384     scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
385 }
386
387 static void scsi_destroy(SCSIDevice *d)
388 {
389     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
390
391     scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
392     blockdev_mark_auto_del(s->qdev.conf.bs);
393 }
394
395 static int scsi_generic_initfn(SCSIDevice *dev)
396 {
397     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
398     int sg_version;
399     struct sg_scsi_id scsiid;
400
401     if (!s->qdev.conf.bs) {
402         error_report("scsi-generic: drive property not set");
403         return -1;
404     }
405     s->bs = s->qdev.conf.bs;
406
407     /* check we are really using a /dev/sg* file */
408     if (!bdrv_is_sg(s->bs)) {
409         error_report("scsi-generic: not /dev/sg*");
410         return -1;
411     }
412
413     if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
414         error_report("Device doesn't support drive option werror");
415         return -1;
416     }
417     if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
418         error_report("Device doesn't support drive option rerror");
419         return -1;
420     }
421
422     /* check we are using a driver managing SG_IO (version 3 and after */
423     if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
424         sg_version < 30000) {
425         error_report("scsi-generic: scsi generic interface too old");
426         return -1;
427     }
428
429     /* get LUN of the /dev/sg? */
430     if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
431         error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
432         return -1;
433     }
434
435     /* define device state */
436     s->qdev.type = scsiid.scsi_type;
437     DPRINTF("device type %d\n", s->qdev.type);
438     if (s->qdev.type == TYPE_TAPE) {
439         s->qdev.blocksize = get_stream_blocksize(s->bs);
440         if (s->qdev.blocksize == -1)
441             s->qdev.blocksize = 0;
442     } else {
443         s->qdev.blocksize = get_blocksize(s->bs);
444         /* removable media returns 0 if not present */
445         if (s->qdev.blocksize <= 0) {
446             if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
447                 s->qdev.blocksize = 2048;
448             else
449                 s->qdev.blocksize = 512;
450         }
451     }
452     DPRINTF("block size %d\n", s->qdev.blocksize);
453     bdrv_set_removable(s->bs, 0);
454     return 0;
455 }
456
457 static SCSIReqOps scsi_generic_req_ops = {
458     .size         = sizeof(SCSIGenericReq),
459     .free_req     = scsi_free_request,
460     .send_command = scsi_send_command,
461     .read_data    = scsi_read_data,
462     .write_data   = scsi_write_data,
463     .cancel_io    = scsi_cancel_io,
464     .get_buf      = scsi_get_buf,
465 };
466
467 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
468                                      void *hba_private)
469 {
470     SCSIRequest *req;
471
472     req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
473     return req;
474 }
475
476 static SCSIDeviceInfo scsi_generic_info = {
477     .qdev.name    = "scsi-generic",
478     .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
479     .qdev.size    = sizeof(SCSIGenericState),
480     .qdev.reset   = scsi_generic_reset,
481     .init         = scsi_generic_initfn,
482     .destroy      = scsi_destroy,
483     .alloc_req    = scsi_new_request,
484     .qdev.props   = (Property[]) {
485         DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
486         DEFINE_PROP_END_OF_LIST(),
487     },
488 };
489
490 static void scsi_generic_register_devices(void)
491 {
492     scsi_qdev_register(&scsi_generic_info);
493 }
494 device_init(scsi_generic_register_devices)
495
496 #endif /* __linux__ */
This page took 0.052833 seconds and 4 git commands to generate.