scsi: export scsi_generic_reqops
[qemu/ar7.git] / hw / scsi-generic.c
blob32f50cda3e366f08ae8682b5dfcb9af90852488b
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.h"
16 #include "scsi.h"
17 #include "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 "scsi-defs.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_free_request(SCSIRequest *req)
64 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
66 g_free(r->buf);
69 /* Helper function for command completion. */
70 static void scsi_command_complete(void *opaque, int ret)
72 int status;
73 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
75 r->req.aiocb = NULL;
76 if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
77 r->req.sense_len = r->io_header.sb_len_wr;
80 if (ret != 0) {
81 switch (ret) {
82 case -EDOM:
83 status = TASK_SET_FULL;
84 break;
85 case -ENOMEM:
86 status = CHECK_CONDITION;
87 scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
88 break;
89 default:
90 status = CHECK_CONDITION;
91 scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
92 break;
94 } else {
95 if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
96 r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
97 r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
98 (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
99 status = BUSY;
100 BADF("Driver Timeout\n");
101 } else if (r->io_header.host_status) {
102 status = CHECK_CONDITION;
103 scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
104 } else if (r->io_header.status) {
105 status = r->io_header.status;
106 } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
107 status = CHECK_CONDITION;
108 } else {
109 status = GOOD;
112 DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
113 r, r->req.tag, status);
115 scsi_req_complete(&r->req, status);
118 /* Cancel a pending data transfer. */
119 static void scsi_cancel_io(SCSIRequest *req)
121 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
123 DPRINTF("Cancel tag=0x%x\n", req->tag);
124 if (r->req.aiocb) {
125 bdrv_aio_cancel(r->req.aiocb);
127 r->req.aiocb = NULL;
130 static int execute_command(BlockDriverState *bdrv,
131 SCSIGenericReq *r, int direction,
132 BlockDriverCompletionFunc *complete)
134 r->io_header.interface_id = 'S';
135 r->io_header.dxfer_direction = direction;
136 r->io_header.dxferp = r->buf;
137 r->io_header.dxfer_len = r->buflen;
138 r->io_header.cmdp = r->req.cmd.buf;
139 r->io_header.cmd_len = r->req.cmd.len;
140 r->io_header.mx_sb_len = sizeof(r->req.sense);
141 r->io_header.sbp = r->req.sense;
142 r->io_header.timeout = MAX_UINT;
143 r->io_header.usr_ptr = r;
144 r->io_header.flags |= SG_FLAG_DIRECT_IO;
146 r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
147 if (r->req.aiocb == NULL) {
148 BADF("execute_command: read failed !\n");
149 return -ENOMEM;
152 return 0;
155 static void scsi_read_complete(void * opaque, int ret)
157 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
158 SCSIDevice *s = r->req.dev;
159 int len;
161 r->req.aiocb = NULL;
162 if (ret) {
163 DPRINTF("IO error ret %d\n", ret);
164 scsi_command_complete(r, ret);
165 return;
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);
170 r->len = -1;
171 if (len == 0) {
172 scsi_command_complete(r, 0);
173 } else {
174 /* Snoop READ CAPACITY output to set the blocksize. */
175 if (r->req.cmd.buf[0] == READ_CAPACITY_10) {
176 s->blocksize = ldl_be_p(&r->buf[4]);
177 s->max_lba = ldl_be_p(&r->buf[0]);
178 } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 &&
179 (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
180 s->blocksize = ldl_be_p(&r->buf[8]);
181 s->max_lba = ldq_be_p(&r->buf[0]);
183 bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
185 scsi_req_data(&r->req, len);
189 /* Read more data from scsi device into buffer. */
190 static void scsi_read_data(SCSIRequest *req)
192 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
193 SCSIDevice *s = r->req.dev;
194 int ret;
196 DPRINTF("scsi_read_data 0x%x\n", req->tag);
197 if (r->len == -1) {
198 scsi_command_complete(r, 0);
199 return;
202 ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
203 if (ret < 0) {
204 scsi_command_complete(r, ret);
208 static void scsi_write_complete(void * opaque, int ret)
210 SCSIGenericReq *r = (SCSIGenericReq *)opaque;
211 SCSIDevice *s = r->req.dev;
213 DPRINTF("scsi_write_complete() ret = %d\n", ret);
214 r->req.aiocb = NULL;
215 if (ret) {
216 DPRINTF("IO error\n");
217 scsi_command_complete(r, ret);
218 return;
221 if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
222 s->type == TYPE_TAPE) {
223 s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11];
224 DPRINTF("block size %d\n", s->blocksize);
227 scsi_command_complete(r, ret);
230 /* Write data to a scsi device. Returns nonzero on failure.
231 The transfer may complete asynchronously. */
232 static void scsi_write_data(SCSIRequest *req)
234 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
235 SCSIDevice *s = r->req.dev;
236 int ret;
238 DPRINTF("scsi_write_data 0x%x\n", req->tag);
239 if (r->len == 0) {
240 r->len = r->buflen;
241 scsi_req_data(&r->req, r->len);
242 return;
245 ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
246 if (ret < 0) {
247 scsi_command_complete(r, ret);
251 /* Return a pointer to the data buffer. */
252 static uint8_t *scsi_get_buf(SCSIRequest *req)
254 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
256 return r->buf;
259 /* Execute a scsi command. Returns the length of the data expected by the
260 command. This will be Positive for data transfers from the device
261 (eg. disk reads), negative for transfers to the device (eg. disk writes),
262 and zero if the command does not transfer any data. */
264 static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
266 SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
267 SCSIDevice *s = r->req.dev;
268 int ret;
270 DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
271 r->req.cmd.xfer, cmd[0]);
273 #ifdef DEBUG_SCSI
275 int i;
276 for (i = 1; i < r->req.cmd.len; i++) {
277 printf(" 0x%02x", cmd[i]);
279 printf("\n");
281 #endif
283 if (r->req.cmd.xfer == 0) {
284 if (r->buf != NULL)
285 g_free(r->buf);
286 r->buflen = 0;
287 r->buf = NULL;
288 ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
289 if (ret < 0) {
290 scsi_command_complete(r, ret);
291 return 0;
293 return 0;
296 if (r->buflen != r->req.cmd.xfer) {
297 if (r->buf != NULL)
298 g_free(r->buf);
299 r->buf = g_malloc(r->req.cmd.xfer);
300 r->buflen = r->req.cmd.xfer;
303 memset(r->buf, 0, r->buflen);
304 r->len = r->req.cmd.xfer;
305 if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
306 r->len = 0;
307 return -r->req.cmd.xfer;
308 } else {
309 return r->req.cmd.xfer;
313 static int get_stream_blocksize(BlockDriverState *bdrv)
315 uint8_t cmd[6];
316 uint8_t buf[12];
317 uint8_t sensebuf[8];
318 sg_io_hdr_t io_header;
319 int ret;
321 memset(cmd, 0, sizeof(cmd));
322 memset(buf, 0, sizeof(buf));
323 cmd[0] = MODE_SENSE;
324 cmd[4] = sizeof(buf);
326 memset(&io_header, 0, sizeof(io_header));
327 io_header.interface_id = 'S';
328 io_header.dxfer_direction = SG_DXFER_FROM_DEV;
329 io_header.dxfer_len = sizeof(buf);
330 io_header.dxferp = buf;
331 io_header.cmdp = cmd;
332 io_header.cmd_len = sizeof(cmd);
333 io_header.mx_sb_len = sizeof(sensebuf);
334 io_header.sbp = sensebuf;
335 io_header.timeout = 6000; /* XXX */
337 ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
338 if (ret < 0 || io_header.driver_status || io_header.host_status) {
339 return -1;
341 return (buf[9] << 16) | (buf[10] << 8) | buf[11];
344 static void scsi_generic_reset(DeviceState *dev)
346 SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
348 scsi_device_purge_requests(s, SENSE_CODE(RESET));
351 static void scsi_destroy(SCSIDevice *s)
353 scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
354 blockdev_mark_auto_del(s->conf.bs);
357 static int scsi_generic_initfn(SCSIDevice *s)
359 int sg_version;
360 struct sg_scsi_id scsiid;
362 if (!s->conf.bs) {
363 error_report("scsi-generic: drive property not set");
364 return -1;
367 /* check we are really using a /dev/sg* file */
368 if (!bdrv_is_sg(s->conf.bs)) {
369 error_report("scsi-generic: not /dev/sg*");
370 return -1;
373 if (bdrv_get_on_error(s->conf.bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
374 error_report("Device doesn't support drive option werror");
375 return -1;
377 if (bdrv_get_on_error(s->conf.bs, 1) != BLOCK_ERR_REPORT) {
378 error_report("Device doesn't support drive option rerror");
379 return -1;
382 /* check we are using a driver managing SG_IO (version 3 and after */
383 if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
384 sg_version < 30000) {
385 error_report("scsi-generic: scsi generic interface too old");
386 return -1;
389 /* get LUN of the /dev/sg? */
390 if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
391 error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
392 return -1;
395 /* define device state */
396 s->type = scsiid.scsi_type;
397 DPRINTF("device type %d\n", s->type);
398 switch (s->type) {
399 case TYPE_TAPE:
400 s->blocksize = get_stream_blocksize(s->conf.bs);
401 if (s->blocksize == -1) {
402 s->blocksize = 0;
404 break;
406 /* Make a guess for block devices, we'll fix it when the guest sends.
407 * READ CAPACITY. If they don't, they likely would assume these sizes
408 * anyway. (TODO: they could also send MODE SENSE).
410 case TYPE_ROM:
411 case TYPE_WORM:
412 s->blocksize = 2048;
413 break;
414 default:
415 s->blocksize = 512;
416 break;
419 DPRINTF("block size %d\n", s->blocksize);
420 return 0;
423 const SCSIReqOps scsi_generic_req_ops = {
424 .size = sizeof(SCSIGenericReq),
425 .free_req = scsi_free_request,
426 .send_command = scsi_send_command,
427 .read_data = scsi_read_data,
428 .write_data = scsi_write_data,
429 .cancel_io = scsi_cancel_io,
430 .get_buf = scsi_get_buf,
433 static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
434 void *hba_private)
436 SCSIRequest *req;
438 req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private);
439 return req;
442 static SCSIDeviceInfo scsi_generic_info = {
443 .qdev.name = "scsi-generic",
444 .qdev.desc = "pass through generic scsi device (/dev/sg*)",
445 .qdev.size = sizeof(SCSIDevice),
446 .qdev.reset = scsi_generic_reset,
447 .init = scsi_generic_initfn,
448 .destroy = scsi_destroy,
449 .alloc_req = scsi_new_request,
450 .qdev.props = (Property[]) {
451 DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
452 DEFINE_PROP_END_OF_LIST(),
456 static void scsi_generic_register_devices(void)
458 scsi_qdev_register(&scsi_generic_info);
460 device_init(scsi_generic_register_devices)
462 #endif /* __linux__ */