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