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