configure: Flip default of target_nptl
[qemu/ar7.git] / hw / scsi / scsi-generic.c
blob8f195bec00a089d8faf9a08b3abdef65eb03932c
1 /*
2 * Generic SCSI Device support
4 * Copyright (c) 2007 Bull S.A.S.
5 * Based on code by Paul Brook
6 * Based on code by Fabrice Bellard
8 * Written by Laurent Vivier <Laurent.Vivier@bull.net>
10 * This code is licensed under the LGPL.
14 #include "qemu-common.h"
15 #include "qemu/error-report.h"
16 #include "hw/scsi/scsi.h"
17 #include "sysemu/blockdev.h"
19 #ifdef __linux__
21 //#define DEBUG_SCSI
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
30 #define BADF(fmt, ...) \
31 do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
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 "block/scsi.h"
40 #define SCSI_SENSE_BUF_SIZE 96
42 #define SG_ERR_DRIVER_TIMEOUT 0x06
43 #define SG_ERR_DRIVER_SENSE 0x08
45 #define SG_ERR_DID_OK 0x00
46 #define SG_ERR_DID_NO_CONNECT 0x01
47 #define SG_ERR_DID_BUS_BUSY 0x02
48 #define SG_ERR_DID_TIME_OUT 0x03
50 #ifndef MAX_UINT
51 #define MAX_UINT ((unsigned int)-1)
52 #endif
54 typedef struct SCSIGenericReq {
55 SCSIRequest req;
56 uint8_t *buf;
57 int buflen;
58 int len;
59 sg_io_hdr_t io_header;
60 } SCSIGenericReq;
62 static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
64 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
66 qemu_put_sbe32s(f, &r->buflen);
67 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
68 assert(!r->req.sg);
69 qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
73 static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
75 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
77 qemu_get_sbe32s(f, &r->buflen);
78 if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
79 assert(!r->req.sg);
80 qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
84 static void scsi_free_request(SCSIRequest *req)
86 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
88 g_free(r->buf);
91 /* Helper function for command completion. */
92 static void scsi_command_complete(void *opaque, int ret)
94 int status;
95 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
97 r->req.aiocb = NULL;
98 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
99 r->req.sense_len = r->io_header.sb_len_wr;
102 if (ret != 0) {
103 switch (ret) {
104 case -EDOM:
105 status = TASK_SET_FULL;
106 break;
107 case -ENOMEM:
108 status = CHECK_CONDITION;
109 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
110 break;
111 default:
112 status = CHECK_CONDITION;
113 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
114 break;
116 } else {
117 if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
118 r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
119 r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
120 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
121 status = BUSY;
122 BADF("Driver Timeout\n");
123 } else if (r->io_header.host_status) {
124 status = CHECK_CONDITION;
125 scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
126 } else if (r->io_header.status) {
127 status = r->io_header.status;
128 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
129 status = CHECK_CONDITION;
130 } else {
131 status = GOOD;
134 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
135 r, r->req.tag, status);
137 scsi_req_complete(&r->req, status);
138 if (!r->req.io_canceled) {
139 scsi_req_unref(&r->req);
143 /* Cancel a pending data transfer. */
144 static void scsi_cancel_io(SCSIRequest *req)
146 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
148 DPRINTF("Cancel tag=0x%x\n", req->tag);
149 if (r->req.aiocb) {
150 bdrv_aio_cancel(r->req.aiocb);
152 /* This reference was left in by scsi_*_data. We take ownership of
153 * it independent of whether bdrv_aio_cancel completes the request
154 * or not. */
155 scsi_req_unref(&r->req);
157 r->req.aiocb = NULL;
160 static int execute_command(BlockDriverState *bdrv,
161 SCSIGenericReq *r, int direction,
162 BlockDriverCompletionFunc *complete)
164 r->io_header.interface_id = 'S';
165 r->io_header.dxfer_direction = direction;
166 r->io_header.dxferp = r->buf;
167 r->io_header.dxfer_len = r->buflen;
168 r->io_header.cmdp = r->req.cmd.buf;
169 r->io_header.cmd_len = r->req.cmd.len;
170 r->io_header.mx_sb_len = sizeof(r->req.sense);
171 r->io_header.sbp = r->req.sense;
172 r->io_header.timeout = MAX_UINT;
173 r->io_header.usr_ptr = r;
174 r->io_header.flags |= SG_FLAG_DIRECT_IO;
176 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
177 if (r->req.aiocb == NULL) {
178 return -EIO;
181 return 0;
184 static void scsi_read_complete(void * opaque, int ret)
186 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
187 SCSIDevice *s = r->req.dev;
188 int len;
190 r->req.aiocb = NULL;
191 if (ret) {
192 DPRINTF("IO error ret %d\n", ret);
193 scsi_command_complete(r, ret);
194 return;
196 len = r->io_header.dxfer_len - r->io_header.resid;
197 DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len);
199 r->len = -1;
200 if (len == 0) {
201 scsi_command_complete(r, 0);
202 } else {
203 /* Snoop READ CAPACITY output to set the blocksize. */
204 if (r->req.cmd.buf[0] == READ_CAPACITY_10 &&
205 (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) {
206 s->blocksize = ldl_be_p(&r->buf[4]);
207 s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL;
208 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
209 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
210 s->blocksize = ldl_be_p(&r->buf[8]);
211 s->max_lba = ldq_be_p(&r->buf[0]);
213 bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
215 scsi_req_data(&r->req, len);
216 if (!r->req.io_canceled) {
217 scsi_req_unref(&r->req);
222 /* Read more data from scsi device into buffer. */
223 static void scsi_read_data(SCSIRequest *req)
225 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
226 SCSIDevice *s = r->req.dev;
227 int ret;
229 DPRINTF("scsi_read_data 0x%x\n", req->tag);
231 /* The request is used as the AIO opaque value, so add a ref. */
232 scsi_req_ref(&r->req);
233 if (r->len == -1) {
234 scsi_command_complete(r, 0);
235 return;
238 ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
239 if (ret < 0) {
240 scsi_command_complete(r, ret);
244 static void scsi_write_complete(void * opaque, int ret)
246 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
247 SCSIDevice *s = r->req.dev;
249 DPRINTF("scsi_write_complete() ret = %d\n", ret);
250 r->req.aiocb = NULL;
251 if (ret) {
252 DPRINTF("IO error\n");
253 scsi_command_complete(r, ret);
254 return;
257 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
258 s->type == TYPE_TAPE) {
259 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
260 DPRINTF("block size %d\n", s->blocksize);
263 scsi_command_complete(r, ret);
266 /* Write data to a scsi device. Returns nonzero on failure.
267 The transfer may complete asynchronously. */
268 static void scsi_write_data(SCSIRequest *req)
270 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
271 SCSIDevice *s = r->req.dev;
272 int ret;
274 DPRINTF("scsi_write_data 0x%x\n", req->tag);
275 if (r->len == 0) {
276 r->len = r->buflen;
277 scsi_req_data(&r->req, r->len);
278 return;
281 /* The request is used as the AIO opaque value, so add a ref. */
282 scsi_req_ref(&r->req);
283 ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
284 if (ret < 0) {
285 scsi_command_complete(r, ret);
289 /* Return a pointer to the data buffer. */
290 static uint8_t *scsi_get_buf(SCSIRequest *req)
292 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
294 return r->buf;
297 /* Execute a scsi command. Returns the length of the data expected by the
298 command. This will be Positive for data transfers from the device
299 (eg. disk reads), negative for transfers to the device (eg. disk writes),
300 and zero if the command does not transfer any data. */
302 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
304 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
305 SCSIDevice *s = r->req.dev;
306 int ret;
308 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
309 r->req.cmd.xfer, cmd[0]);
311 #ifdef DEBUG_SCSI
313 int i;
314 for (i = 1; i < r->req.cmd.len; i++) {
315 printf(" 0x%02x", cmd[i]);
317 printf("\n");
319 #endif
321 if (r->req.cmd.xfer == 0) {
322 if (r->buf != NULL)
323 g_free(r->buf);
324 r->buflen = 0;
325 r->buf = NULL;
326 /* The request is used as the AIO opaque value, so add a ref. */
327 scsi_req_ref(&r->req);
328 ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
329 if (ret < 0) {
330 scsi_command_complete(r, ret);
331 return 0;
333 return 0;
336 if (r->buflen != r->req.cmd.xfer) {
337 if (r->buf != NULL)
338 g_free(r->buf);
339 r->buf = g_malloc(r->req.cmd.xfer);
340 r->buflen = r->req.cmd.xfer;
343 memset(r->buf, 0, r->buflen);
344 r->len = r->req.cmd.xfer;
345 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
346 r->len = 0;
347 return -r->req.cmd.xfer;
348 } else {
349 return r->req.cmd.xfer;
353 static int get_stream_blocksize(BlockDriverState *bdrv)
355 uint8_t cmd[6];
356 uint8_t buf[12];
357 uint8_t sensebuf[8];
358 sg_io_hdr_t io_header;
359 int ret;
361 memset(cmd, 0, sizeof(cmd));
362 memset(buf, 0, sizeof(buf));
363 cmd[0] = MODE_SENSE;
364 cmd[4] = sizeof(buf);
366 memset(&io_header, 0, sizeof(io_header));
367 io_header.interface_id = 'S';
368 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
369 io_header.dxfer_len = sizeof(buf);
370 io_header.dxferp = buf;
371 io_header.cmdp = cmd;
372 io_header.cmd_len = sizeof(cmd);
373 io_header.mx_sb_len = sizeof(sensebuf);
374 io_header.sbp = sensebuf;
375 io_header.timeout = 6000; /* XXX */
377 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
378 if (ret < 0 || io_header.driver_status || io_header.host_status) {
379 return -1;
381 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
384 static void scsi_generic_reset(DeviceState *dev)
386 SCSIDevice *s = SCSI_DEVICE(dev);
388 scsi_device_purge_requests(s, SENSE_CODE(RESET));
391 static void scsi_destroy(SCSIDevice *s)
393 scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
394 blockdev_mark_auto_del(s->conf.bs);
397 static int scsi_generic_initfn(SCSIDevice *s)
399 int sg_version;
400 struct sg_scsi_id scsiid;
402 if (!s->conf.bs) {
403 error_report("drive property not set");
404 return -1;
407 if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
408 error_report("Device doesn't support drive option werror");
409 return -1;
411 if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
412 error_report("Device doesn't support drive option rerror");
413 return -1;
416 /* check we are using a driver managing SG_IO (version 3 and after */
417 if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) {
418 error_report("scsi generic interface not supported");
419 return -1;
421 if (sg_version < 30000) {
422 error_report("scsi generic interface too old");
423 return -1;
426 /* get LUN of the /dev/sg? */
427 if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
428 error_report("SG_GET_SCSI_ID ioctl failed");
429 return -1;
432 /* define device state */
433 s->type = scsiid.scsi_type;
434 DPRINTF("device type %d\n", s->type);
435 if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
436 add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
439 switch (s->type) {
440 case TYPE_TAPE:
441 s->blocksize = get_stream_blocksize(s->conf.bs);
442 if (s->blocksize == -1) {
443 s->blocksize = 0;
445 break;
447 /* Make a guess for block devices, we'll fix it when the guest sends.
448 * READ CAPACITY. If they don't, they likely would assume these sizes
449 * anyway. (TODO: they could also send MODE SENSE).
451 case TYPE_ROM:
452 case TYPE_WORM:
453 s->blocksize = 2048;
454 break;
455 default:
456 s->blocksize = 512;
457 break;
460 DPRINTF("block size %d\n", s->blocksize);
461 return 0;
464 const SCSIReqOps scsi_generic_req_ops = {
465 .size = sizeof(SCSIGenericReq),
466 .free_req = scsi_free_request,
467 .send_command = scsi_send_command,
468 .read_data = scsi_read_data,
469 .write_data = scsi_write_data,
470 .cancel_io = scsi_cancel_io,
471 .get_buf = scsi_get_buf,
472 .load_request = scsi_generic_load_request,
473 .save_request = scsi_generic_save_request,
476 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
477 uint8_t *buf, void *hba_private)
479 SCSIRequest *req;
481 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
482 return req;
485 static Property scsi_generic_properties[] = {
486 DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
487 DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
488 DEFINE_PROP_END_OF_LIST(),
491 static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
493 DeviceClass *dc = DEVICE_CLASS(klass);
494 SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
496 sc->init = scsi_generic_initfn;
497 sc->destroy = scsi_destroy;
498 sc->alloc_req = scsi_new_request;
499 dc->fw_name = "disk";
500 dc->desc = "pass through generic scsi device (/dev/sg*)";
501 dc->reset = scsi_generic_reset;
502 dc->props = scsi_generic_properties;
503 dc->vmsd = &vmstate_scsi_device;
506 static const TypeInfo scsi_generic_info = {
507 .name = "scsi-generic",
508 .parent = TYPE_SCSI_DEVICE,
509 .instance_size = sizeof(SCSIDevice),
510 .class_init = scsi_generic_class_initfn,
513 static void scsi_generic_register_types(void)
515 type_register_static(&scsi_generic_info);
518 type_init(scsi_generic_register_types)
520 #endif /* __linux__ */