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