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