]> Git Repo - qemu.git/blame - hw/scsi-generic.c
PPC: Bump MPIC up to 32 supported CPUs
[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 <[email protected]>
9 *
8e31bf38 10 * This code is licensed under the LGPL.
2cc977e2
TS
11 *
12 */
13
14#include "qemu-common.h"
2f792016 15#include "qemu-error.h"
43b443b6 16#include "scsi.h"
2446333c 17#include "blockdev.h"
2cc977e2 18
d52affa7 19#ifdef __linux__
2cc977e2
TS
20
21//#define DEBUG_SCSI
22
23#ifdef DEBUG_SCSI
001faf32
BS
24#define DPRINTF(fmt, ...) \
25do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2 26#else
001faf32 27#define DPRINTF(fmt, ...) do {} while(0)
2cc977e2
TS
28#endif
29
001faf32
BS
30#define BADF(fmt, ...) \
31do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
2cc977e2
TS
32
33#include <stdio.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <scsi/sg.h>
0d65e1f8 38#include "scsi-defs.h"
2cc977e2 39
a9dd6843 40#define SCSI_SENSE_BUF_SIZE 96
2cc977e2
TS
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
d52affa7
GH
49typedef struct SCSIGenericState SCSIGenericState;
50
4c41d2ef
GH
51typedef struct SCSIGenericReq {
52 SCSIRequest req;
2cc977e2
TS
53 uint8_t *buf;
54 int buflen;
55 int len;
56 sg_io_hdr_t io_header;
4c41d2ef 57} SCSIGenericReq;
2cc977e2 58
d52affa7 59struct SCSIGenericState
2cc977e2 60{
d52affa7 61 SCSIDevice qdev;
428c149b 62 BlockDriverState *bs;
2cc977e2
TS
63};
64
ad2d30f7 65static void scsi_free_request(SCSIRequest *req)
2cc977e2 66{
ad2d30f7
PB
67 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
68
7267c094 69 g_free(r->buf);
2cc977e2
TS
70}
71
2cc977e2
TS
72/* Helper function for command completion. */
73static void scsi_command_complete(void *opaque, int ret)
74{
682a9b21 75 int status;
4c41d2ef 76 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
2cc977e2 77
d33e0ce2 78 r->req.aiocb = NULL;
b45ef674
PB
79 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE)
80 r->req.sense_len = r->io_header.sb_len_wr;
89c0f643 81
a1f0cce2
HR
82 if (ret != 0) {
83 switch (ret) {
2e7cc4d6 84 case -EDOM:
682a9b21 85 status = TASK_SET_FULL;
2e7cc4d6 86 break;
a1f0cce2 87 case -ENOMEM:
682a9b21 88 status = CHECK_CONDITION;
b45ef674 89 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
a1f0cce2
HR
90 break;
91 default:
682a9b21 92 status = CHECK_CONDITION;
b45ef674 93 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
a1f0cce2
HR
94 break;
95 }
96 } else {
b45ef674 97 if (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) {
682a9b21 98 status = BUSY;
2cc977e2 99 BADF("Driver Timeout\n");
682a9b21
PB
100 } else if (r->io_header.status) {
101 status = r->io_header.status;
b45ef674 102 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
682a9b21
PB
103 status = CHECK_CONDITION;
104 } else {
105 status = GOOD;
106 }
2cc977e2 107 }
89c0f643 108 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
682a9b21 109 r, r->req.tag, status);
ed3a34a3 110
682a9b21 111 scsi_req_complete(&r->req, status);
2cc977e2
TS
112}
113
114/* Cancel a pending data transfer. */
5c6c0e51 115static void scsi_cancel_io(SCSIRequest *req)
2cc977e2 116{
5c6c0e51
HR
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);
2cc977e2 122 }
5c6c0e51 123 r->req.aiocb = NULL;
2cc977e2
TS
124}
125
126static int execute_command(BlockDriverState *bdrv,
4c41d2ef 127 SCSIGenericReq *r, int direction,
2cc977e2
TS
128 BlockDriverCompletionFunc *complete)
129{
2cc977e2
TS
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;
29362ebe
GH
134 r->io_header.cmdp = r->req.cmd.buf;
135 r->io_header.cmd_len = r->req.cmd.len;
b45ef674
PB
136 r->io_header.mx_sb_len = sizeof(r->req.sense);
137 r->io_header.sbp = r->req.sense;
2cc977e2
TS
138 r->io_header.timeout = MAX_UINT;
139 r->io_header.usr_ptr = r;
140 r->io_header.flags |= SG_FLAG_DIRECT_IO;
141
4c41d2ef
GH
142 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
143 if (r->req.aiocb == NULL) {
2cc977e2 144 BADF("execute_command: read failed !\n");
a1f0cce2 145 return -ENOMEM;
2cc977e2
TS
146 }
147
148 return 0;
149}
150
151static void scsi_read_complete(void * opaque, int ret)
152{
4c41d2ef 153 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
2cc977e2
TS
154 int len;
155
d33e0ce2 156 r->req.aiocb = NULL;
2cc977e2 157 if (ret) {
aa2b1e89 158 DPRINTF("IO error ret %d\n", ret);
2cc977e2
TS
159 scsi_command_complete(r, ret);
160 return;
161 }
162 len = r->io_header.dxfer_len - r->io_header.resid;
4c41d2ef 163 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
2cc977e2
TS
164
165 r->len = -1;
40f16dd1 166 if (len == 0) {
89c0f643 167 scsi_command_complete(r, 0);
40f16dd1 168 } else {
ab9adc88 169 scsi_req_data(&r->req, len);
40f16dd1 170 }
2cc977e2
TS
171}
172
173/* Read more data from scsi device into buffer. */
5c6c0e51 174static void scsi_read_data(SCSIRequest *req)
2cc977e2 175{
5c6c0e51
HR
176 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
177 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
2cc977e2
TS
178 int ret;
179
5c6c0e51 180 DPRINTF("scsi_read_data 0x%x\n", req->tag);
2cc977e2
TS
181 if (r->len == -1) {
182 scsi_command_complete(r, 0);
183 return;
184 }
185
428c149b 186 ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
a1f0cce2
HR
187 if (ret < 0) {
188 scsi_command_complete(r, ret);
2cc977e2
TS
189 return;
190 }
191}
192
193static void scsi_write_complete(void * opaque, int ret)
194{
4c41d2ef
GH
195 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
196 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
2cc977e2
TS
197
198 DPRINTF("scsi_write_complete() ret = %d\n", ret);
d33e0ce2 199 r->req.aiocb = NULL;
2cc977e2
TS
200 if (ret) {
201 DPRINTF("IO error\n");
202 scsi_command_complete(r, ret);
203 return;
204 }
205
29362ebe 206 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
91376656 207 s->qdev.type == TYPE_TAPE) {
b07995e3 208 s->qdev.blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
aa2b1e89 209 DPRINTF("block size %d\n", s->qdev.blocksize);
89c0f643
AJ
210 }
211
2cc977e2
TS
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. */
42741212 217static void scsi_write_data(SCSIRequest *req)
2cc977e2 218{
5c6c0e51
HR
219 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
220 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
2cc977e2
TS
221 int ret;
222
5c6c0e51 223 DPRINTF("scsi_write_data 0x%x\n", req->tag);
2cc977e2
TS
224 if (r->len == 0) {
225 r->len = r->buflen;
ab9adc88 226 scsi_req_data(&r->req, r->len);
42741212 227 return;
2cc977e2
TS
228 }
229
428c149b 230 ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
a1f0cce2
HR
231 if (ret < 0) {
232 scsi_command_complete(r, ret);
2cc977e2 233 }
2cc977e2
TS
234}
235
236/* Return a pointer to the data buffer. */
5c6c0e51 237static uint8_t *scsi_get_buf(SCSIRequest *req)
2cc977e2 238{
5c6c0e51
HR
239 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
240
2cc977e2
TS
241 return r->buf;
242}
243
2ec749cb 244static void scsi_req_fixup(SCSIRequest *req)
2cc977e2 245{
2ec749cb 246 switch(req->cmd.buf[0]) {
a9dd6843
AL
247 case REWIND:
248 case START_STOP:
2ec749cb
GH
249 if (req->dev->type == TYPE_TAPE) {
250 /* force IMMED, otherwise qemu waits end of command */
251 req->cmd.buf[1] = 0x01;
252 }
a9dd6843 253 break;
a9dd6843 254 }
a9dd6843
AL
255}
256
2cc977e2
TS
257/* Execute a scsi command. Returns the length of the data expected by the
258 command. This will be Positive for data transfers from the device
259 (eg. disk reads), negative for transfers to the device (eg. disk writes),
260 and zero if the command does not transfer any data. */
261
5c6c0e51 262static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
2cc977e2 263{
5c6c0e51
HR
264 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
265 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
2cc977e2
TS
266 int ret;
267
2ec749cb
GH
268 scsi_req_fixup(&r->req);
269
aa2b1e89
BK
270 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
271 r->req.cmd.xfer, cmd[0]);
272
273#ifdef DEBUG_SCSI
274 {
275 int i;
276 for (i = 1; i < r->req.cmd.len; i++) {
277 printf(" 0x%02x", cmd[i]);
278 }
279 printf("\n");
280 }
281#endif
2cc977e2 282
2ec749cb 283 if (r->req.cmd.xfer == 0) {
2cc977e2 284 if (r->buf != NULL)
7267c094 285 g_free(r->buf);
2cc977e2
TS
286 r->buflen = 0;
287 r->buf = NULL;
428c149b 288 ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
a1f0cce2
HR
289 if (ret < 0) {
290 scsi_command_complete(r, ret);
291 return 0;
2cc977e2
TS
292 }
293 return 0;
294 }
295
2ec749cb 296 if (r->buflen != r->req.cmd.xfer) {
2cc977e2 297 if (r->buf != NULL)
7267c094
AL
298 g_free(r->buf);
299 r->buf = g_malloc(r->req.cmd.xfer);
2ec749cb 300 r->buflen = r->req.cmd.xfer;
2cc977e2
TS
301 }
302
303 memset(r->buf, 0, r->buflen);
2ec749cb 304 r->len = r->req.cmd.xfer;
97a06435 305 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
2cc977e2 306 r->len = 0;
5c6c0e51 307 return -r->req.cmd.xfer;
ad2d30f7 308 } else {
5c6c0e51 309 return r->req.cmd.xfer;
2cc977e2 310 }
2cc977e2
TS
311}
312
313static int get_blocksize(BlockDriverState *bdrv)
314{
315 uint8_t cmd[10];
316 uint8_t buf[8];
317 uint8_t sensebuf[8];
318 sg_io_hdr_t io_header;
319 int ret;
320
4f26a486
AL
321 memset(cmd, 0, sizeof(cmd));
322 memset(buf, 0, sizeof(buf));
5e30a07d 323 cmd[0] = READ_CAPACITY_10;
2cc977e2
TS
324
325 memset(&io_header, 0, sizeof(io_header));
326 io_header.interface_id = 'S';
327 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
328 io_header.dxfer_len = sizeof(buf);
329 io_header.dxferp = buf;
330 io_header.cmdp = cmd;
331 io_header.cmd_len = sizeof(cmd);
332 io_header.mx_sb_len = sizeof(sensebuf);
333 io_header.sbp = sensebuf;
334 io_header.timeout = 6000; /* XXX */
335
221f715d 336 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
7d780669 337 if (ret < 0)
2cc977e2
TS
338 return -1;
339
340 return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
341}
342
89c0f643
AJ
343static int get_stream_blocksize(BlockDriverState *bdrv)
344{
345 uint8_t cmd[6];
346 uint8_t buf[12];
347 uint8_t sensebuf[8];
348 sg_io_hdr_t io_header;
349 int ret;
350
351 memset(cmd, 0, sizeof(cmd));
352 memset(buf, 0, sizeof(buf));
353 cmd[0] = MODE_SENSE;
354 cmd[4] = sizeof(buf);
355
356 memset(&io_header, 0, sizeof(io_header));
357 io_header.interface_id = 'S';
358 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
359 io_header.dxfer_len = sizeof(buf);
360 io_header.dxferp = buf;
361 io_header.cmdp = cmd;
362 io_header.cmd_len = sizeof(cmd);
363 io_header.mx_sb_len = sizeof(sensebuf);
364 io_header.sbp = sensebuf;
365 io_header.timeout = 6000; /* XXX */
366
221f715d 367 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
7d780669 368 if (ret < 0)
89c0f643
AJ
369 return -1;
370
371 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
372}
373
f8b6d672
BK
374static void scsi_generic_reset(DeviceState *dev)
375{
376 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev.qdev, dev);
377
c7b48872 378 scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
f8b6d672
BK
379}
380
381static void scsi_destroy(SCSIDevice *d)
382{
383 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
384
c7b48872 385 scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
f8b6cc00 386 blockdev_mark_auto_del(s->qdev.conf.bs);
2cc977e2
TS
387}
388
d52affa7 389static int scsi_generic_initfn(SCSIDevice *dev)
2cc977e2 390{
d52affa7 391 SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
2cc977e2 392 int sg_version;
2cc977e2
TS
393 struct sg_scsi_id scsiid;
394
f8b6cc00 395 if (!s->qdev.conf.bs) {
1ecda02b 396 error_report("scsi-generic: drive property not set");
d52affa7
GH
397 return -1;
398 }
f8b6cc00 399 s->bs = s->qdev.conf.bs;
2cc977e2 400
d52affa7 401 /* check we are really using a /dev/sg* file */
428c149b 402 if (!bdrv_is_sg(s->bs)) {
1ecda02b 403 error_report("scsi-generic: not /dev/sg*");
d52affa7
GH
404 return -1;
405 }
2cc977e2 406
620f862e
MA
407 if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
408 error_report("Device doesn't support drive option werror");
409 return -1;
410 }
411 if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
412 error_report("Device doesn't support drive option rerror");
413 return -1;
414 }
415
2cc977e2 416 /* check we are using a driver managing SG_IO (version 3 and after */
428c149b 417 if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
d52affa7 418 sg_version < 30000) {
1ecda02b 419 error_report("scsi-generic: scsi generic interface too old");
d52affa7
GH
420 return -1;
421 }
2cc977e2
TS
422
423 /* get LUN of the /dev/sg? */
428c149b 424 if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
1ecda02b 425 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
d52affa7
GH
426 return -1;
427 }
2cc977e2
TS
428
429 /* define device state */
91376656
GH
430 s->qdev.type = scsiid.scsi_type;
431 DPRINTF("device type %d\n", s->qdev.type);
432 if (s->qdev.type == TYPE_TAPE) {
428c149b 433 s->qdev.blocksize = get_stream_blocksize(s->bs);
b07995e3
GH
434 if (s->qdev.blocksize == -1)
435 s->qdev.blocksize = 0;
89c0f643 436 } else {
428c149b 437 s->qdev.blocksize = get_blocksize(s->bs);
89c0f643 438 /* removable media returns 0 if not present */
b07995e3 439 if (s->qdev.blocksize <= 0) {
91376656 440 if (s->qdev.type == TYPE_ROM || s->qdev.type == TYPE_WORM)
b07995e3 441 s->qdev.blocksize = 2048;
89c0f643 442 else
b07995e3 443 s->qdev.blocksize = 512;
89c0f643
AJ
444 }
445 }
b07995e3 446 DPRINTF("block size %d\n", s->qdev.blocksize);
d52affa7
GH
447 return 0;
448}
2cc977e2 449
8dbd4574
PB
450static SCSIReqOps scsi_generic_req_ops = {
451 .size = sizeof(SCSIGenericReq),
12010e7b
PB
452 .free_req = scsi_free_request,
453 .send_command = scsi_send_command,
454 .read_data = scsi_read_data,
455 .write_data = scsi_write_data,
456 .cancel_io = scsi_cancel_io,
457 .get_buf = scsi_get_buf,
8dbd4574
PB
458};
459
460static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
461 void *hba_private)
462{
463 SCSIRequest *req;
464
465 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
466 return req;
467}
468
d52affa7
GH
469static SCSIDeviceInfo scsi_generic_info = {
470 .qdev.name = "scsi-generic",
471 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
472 .qdev.size = sizeof(SCSIGenericState),
f8b6d672 473 .qdev.reset = scsi_generic_reset,
d52affa7
GH
474 .init = scsi_generic_initfn,
475 .destroy = scsi_destroy,
5c6c0e51 476 .alloc_req = scsi_new_request,
d52affa7 477 .qdev.props = (Property[]) {
428c149b 478 DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
d52affa7
GH
479 DEFINE_PROP_END_OF_LIST(),
480 },
481};
2cc977e2 482
d52affa7
GH
483static void scsi_generic_register_devices(void)
484{
485 scsi_qdev_register(&scsi_generic_info);
2cc977e2 486}
d52affa7
GH
487device_init(scsi_generic_register_devices)
488
2cc977e2 489#endif /* __linux__ */
This page took 0.609907 seconds and 4 git commands to generate.