Revision 5c6c0e51 hw/scsi-generic.c
b/hw/scsi-generic.c | ||
---|---|---|
66 | 66 |
uint8_t senselen; |
67 | 67 |
}; |
68 | 68 |
|
69 |
static SCSIGenericReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
|
|
69 |
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
|
|
70 | 70 |
{ |
71 | 71 |
SCSIRequest *req; |
72 | 72 |
|
73 | 73 |
req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun); |
74 |
return DO_UPCAST(SCSIGenericReq, req, req);
|
|
74 |
return req;
|
|
75 | 75 |
} |
76 | 76 |
|
77 | 77 |
static void scsi_free_request(SCSIRequest *req) |
... | ... | |
81 | 81 |
qemu_free(r->buf); |
82 | 82 |
} |
83 | 83 |
|
84 |
static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag) |
|
85 |
{ |
|
86 |
return DO_UPCAST(SCSIGenericReq, req, scsi_req_find(&s->qdev, tag)); |
|
87 |
} |
|
88 |
|
|
89 | 84 |
/* Helper function for command completion. */ |
90 | 85 |
static void scsi_command_complete(void *opaque, int ret) |
91 | 86 |
{ |
... | ... | |
117 | 112 |
} |
118 | 113 |
|
119 | 114 |
/* Cancel a pending data transfer. */ |
120 |
static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
|
|
115 |
static void scsi_cancel_io(SCSIRequest *req)
|
|
121 | 116 |
{ |
122 |
DPRINTF("scsi_cancel_io 0x%x\n", tag); |
|
123 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d); |
|
124 |
SCSIGenericReq *r; |
|
125 |
DPRINTF("Cancel tag=0x%x\n", tag); |
|
126 |
r = scsi_find_request(s, tag); |
|
127 |
if (r) { |
|
128 |
if (r->req.aiocb) |
|
129 |
bdrv_aio_cancel(r->req.aiocb); |
|
130 |
r->req.aiocb = NULL; |
|
131 |
scsi_req_dequeue(&r->req); |
|
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); |
|
132 | 122 |
} |
123 |
r->req.aiocb = NULL; |
|
124 |
scsi_req_dequeue(&r->req); |
|
133 | 125 |
} |
134 | 126 |
|
135 | 127 |
static int execute_command(BlockDriverState *bdrv, |
... | ... | |
182 | 174 |
} |
183 | 175 |
|
184 | 176 |
/* Read more data from scsi device into buffer. */ |
185 |
static void scsi_read_data(SCSIDevice *d, uint32_t tag)
|
|
177 |
static void scsi_read_data(SCSIRequest *req)
|
|
186 | 178 |
{ |
187 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
|
|
188 |
SCSIGenericReq *r;
|
|
179 |
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
|
|
180 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
|
|
189 | 181 |
int ret; |
190 | 182 |
|
191 |
DPRINTF("scsi_read_data 0x%x\n", tag); |
|
192 |
r = scsi_find_request(s, tag); |
|
193 |
if (!r) { |
|
194 |
BADF("Bad read tag 0x%x\n", tag); |
|
195 |
/* ??? This is the wrong error. */ |
|
196 |
scsi_command_complete(r, -EINVAL); |
|
197 |
return; |
|
198 |
} |
|
199 |
|
|
183 |
DPRINTF("scsi_read_data 0x%x\n", req->tag); |
|
200 | 184 |
if (r->len == -1) { |
201 | 185 |
scsi_command_complete(r, 0); |
202 | 186 |
return; |
... | ... | |
249 | 233 |
|
250 | 234 |
/* Write data to a scsi device. Returns nonzero on failure. |
251 | 235 |
The transfer may complete asynchronously. */ |
252 |
static int scsi_write_data(SCSIDevice *d, uint32_t tag)
|
|
236 |
static int scsi_write_data(SCSIRequest *req)
|
|
253 | 237 |
{ |
254 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
|
|
255 |
SCSIGenericReq *r; |
|
238 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
|
|
239 |
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
|
|
256 | 240 |
int ret; |
257 | 241 |
|
258 |
DPRINTF("scsi_write_data 0x%x\n", tag); |
|
259 |
r = scsi_find_request(s, tag); |
|
260 |
if (!r) { |
|
261 |
BADF("Bad write tag 0x%x\n", tag); |
|
262 |
/* ??? This is the wrong error. */ |
|
263 |
scsi_command_complete(r, -EINVAL); |
|
264 |
return 0; |
|
265 |
} |
|
266 |
|
|
242 |
DPRINTF("scsi_write_data 0x%x\n", req->tag); |
|
267 | 243 |
if (r->len == 0) { |
268 | 244 |
r->len = r->buflen; |
269 | 245 |
scsi_req_data(&r->req, r->len); |
... | ... | |
280 | 256 |
} |
281 | 257 |
|
282 | 258 |
/* Return a pointer to the data buffer. */ |
283 |
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
|
|
259 |
static uint8_t *scsi_get_buf(SCSIRequest *req)
|
|
284 | 260 |
{ |
285 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d); |
|
286 |
SCSIGenericReq *r; |
|
287 |
r = scsi_find_request(s, tag); |
|
288 |
if (!r) { |
|
289 |
BADF("Bad buffer tag 0x%x\n", tag); |
|
290 |
return NULL; |
|
291 |
} |
|
261 |
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); |
|
262 |
|
|
292 | 263 |
return r->buf; |
293 | 264 |
} |
294 | 265 |
|
... | ... | |
316 | 287 |
(eg. disk reads), negative for transfers to the device (eg. disk writes), |
317 | 288 |
and zero if the command does not transfer any data. */ |
318 | 289 |
|
319 |
static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, |
|
320 |
uint8_t *cmd, int lun) |
|
290 |
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) |
|
321 | 291 |
{ |
322 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, d);
|
|
323 |
SCSIGenericReq *r; |
|
292 |
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
|
|
293 |
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
|
|
324 | 294 |
SCSIBus *bus; |
325 | 295 |
int ret; |
326 |
int32_t len; |
|
327 | 296 |
|
297 |
scsi_req_enqueue(req); |
|
328 | 298 |
if (cmd[0] != REQUEST_SENSE && |
329 |
(lun != s->lun || (cmd[1] >> 5) != s->lun)) { |
|
330 |
DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
|
|
299 |
(req->lun != s->lun || (cmd[1] >> 5) != s->lun)) {
|
|
300 |
DPRINTF("Unimplemented LUN %d\n", req->lun ? req->lun : cmd[1] >> 5);
|
|
331 | 301 |
|
332 | 302 |
s->sensebuf[0] = 0x70; |
333 | 303 |
s->sensebuf[1] = 0x00; |
... | ... | |
338 | 308 |
s->sensebuf[6] = 0x00; |
339 | 309 |
s->senselen = 7; |
340 | 310 |
s->driver_status = SG_ERR_DRIVER_SENSE; |
341 |
bus = scsi_bus_from_device(d);
|
|
342 |
bus->ops->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION);
|
|
311 |
bus = scsi_bus_from_device(&s->qdev);
|
|
312 |
bus->ops->complete(req, SCSI_REASON_DONE, CHECK_CONDITION);
|
|
343 | 313 |
return 0; |
344 | 314 |
} |
345 | 315 |
|
346 |
r = scsi_find_request(s, tag); |
|
347 |
if (r) { |
|
348 |
BADF("Tag 0x%x already in use %p\n", tag, r); |
|
349 |
scsi_cancel_io(d, tag); |
|
350 |
} |
|
351 |
r = scsi_new_request(d, tag, lun); |
|
352 |
|
|
353 | 316 |
if (-1 == scsi_req_parse(&r->req, cmd)) { |
354 | 317 |
BADF("Unsupported command length, command %x\n", cmd[0]); |
355 | 318 |
scsi_req_dequeue(&r->req); |
... | ... | |
379 | 342 |
ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete); |
380 | 343 |
if (ret == -1) { |
381 | 344 |
scsi_command_complete(r, -EINVAL); |
382 |
scsi_req_unref(&r->req); |
|
383 |
return 0; |
|
384 | 345 |
} |
385 |
scsi_req_unref(&r->req); |
|
386 | 346 |
return 0; |
387 | 347 |
} |
388 | 348 |
|
... | ... | |
397 | 357 |
r->len = r->req.cmd.xfer; |
398 | 358 |
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { |
399 | 359 |
r->len = 0; |
400 |
len = -r->req.cmd.xfer;
|
|
360 |
return -r->req.cmd.xfer;
|
|
401 | 361 |
} else { |
402 |
len = r->req.cmd.xfer;
|
|
362 |
return r->req.cmd.xfer;
|
|
403 | 363 |
} |
404 |
|
|
405 |
scsi_req_unref(&r->req); |
|
406 |
return len; |
|
407 | 364 |
} |
408 | 365 |
|
409 | 366 |
static int get_blocksize(BlockDriverState *bdrv) |
... | ... | |
477 | 434 |
bdrv_aio_cancel(r->req.aiocb); |
478 | 435 |
} |
479 | 436 |
scsi_req_dequeue(&r->req); |
437 |
scsi_req_unref(&r->req); |
|
480 | 438 |
} |
481 | 439 |
} |
482 | 440 |
|
... | ... | |
568 | 526 |
.qdev.reset = scsi_generic_reset, |
569 | 527 |
.init = scsi_generic_initfn, |
570 | 528 |
.destroy = scsi_destroy, |
529 |
.alloc_req = scsi_new_request, |
|
571 | 530 |
.free_req = scsi_free_request, |
572 | 531 |
.send_command = scsi_send_command, |
573 | 532 |
.read_data = scsi_read_data, |
Also available in: Unified diff