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