Revision 05751d3f hw/spapr_vscsi.c
b/hw/spapr_vscsi.c | ||
---|---|---|
80 | 80 |
int active; |
81 | 81 |
long data_len; |
82 | 82 |
int writing; |
83 |
int sensing; |
|
84 | 83 |
int senselen; |
85 | 84 |
uint8_t sense[SCSI_SENSE_BUF_SIZE]; |
86 | 85 |
|
... | ... | |
436 | 435 |
return 0; |
437 | 436 |
} |
438 | 437 |
|
439 |
static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req) |
|
440 |
{ |
|
441 |
uint8_t *cdb = req->iu.srp.cmd.cdb; |
|
442 |
int n; |
|
443 |
|
|
444 |
n = scsi_req_get_sense(req->sreq, req->sense, sizeof(req->sense)); |
|
445 |
if (n) { |
|
446 |
req->senselen = n; |
|
447 |
vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0); |
|
448 |
vscsi_put_req(req); |
|
449 |
return; |
|
450 |
} |
|
451 |
|
|
452 |
dprintf("VSCSI: Got CHECK_CONDITION, requesting sense...\n"); |
|
453 |
cdb[0] = 3; |
|
454 |
cdb[1] = 0; |
|
455 |
cdb[2] = 0; |
|
456 |
cdb[3] = 0; |
|
457 |
cdb[4] = 96; |
|
458 |
cdb[5] = 0; |
|
459 |
req->sensing = 1; |
|
460 |
n = scsi_req_enqueue(req->sreq, cdb); |
|
461 |
dprintf("VSCSI: Queued request sense tag 0x%x\n", req->qtag); |
|
462 |
if (n < 0) { |
|
463 |
fprintf(stderr, "VSCSI: REQUEST_SENSE wants write data !?!?!?\n"); |
|
464 |
vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0); |
|
465 |
scsi_req_abort(req->sreq, CHECK_CONDITION); |
|
466 |
return; |
|
467 |
} else if (n == 0) { |
|
468 |
return; |
|
469 |
} |
|
470 |
scsi_req_continue(req->sreq); |
|
471 |
} |
|
472 |
|
|
473 | 438 |
/* Callback to indicate that the SCSI layer has completed a transfer. */ |
474 | 439 |
static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len) |
475 | 440 |
{ |
... | ... | |
485 | 450 |
return; |
486 | 451 |
} |
487 | 452 |
|
488 |
if (req->sensing) { |
|
489 |
uint8_t *buf = scsi_req_get_buf(sreq); |
|
490 |
|
|
491 |
len = MIN(len, SCSI_SENSE_BUF_SIZE); |
|
492 |
dprintf("VSCSI: Sense data, %d bytes:\n", len); |
|
493 |
dprintf(" %02x %02x %02x %02x %02x %02x %02x %02x\n", |
|
494 |
buf[0], buf[1], buf[2], buf[3], |
|
495 |
buf[4], buf[5], buf[6], buf[7]); |
|
496 |
dprintf(" %02x %02x %02x %02x %02x %02x %02x %02x\n", |
|
497 |
buf[8], buf[9], buf[10], buf[11], |
|
498 |
buf[12], buf[13], buf[14], buf[15]); |
|
499 |
memcpy(req->sense, buf, len); |
|
500 |
req->senselen = len; |
|
501 |
scsi_req_continue(req->sreq); |
|
502 |
return; |
|
503 |
} |
|
504 |
|
|
505 | 453 |
if (len) { |
506 | 454 |
buf = scsi_req_get_buf(sreq); |
507 | 455 |
rc = vscsi_srp_transfer_data(s, req, req->writing, buf, len); |
... | ... | |
532 | 480 |
return; |
533 | 481 |
} |
534 | 482 |
|
535 |
if (!req->sensing && status == CHECK_CONDITION) { |
|
536 |
vscsi_send_request_sense(s, req); |
|
537 |
return; |
|
483 |
if (status == CHECK_CONDITION) { |
|
484 |
req->senselen = scsi_req_get_sense(req->sreq, req->sense, |
|
485 |
sizeof(req->sense)); |
|
486 |
status = 0; |
|
487 |
dprintf("VSCSI: Sense data, %d bytes:\n", len); |
|
488 |
dprintf(" %02x %02x %02x %02x %02x %02x %02x %02x\n", |
|
489 |
req->sense[0], req->sense[1], req->sense[2], req->sense[3], |
|
490 |
req->sense[4], req->sense[5], req->sense[6], req->sense[7]); |
|
491 |
dprintf(" %02x %02x %02x %02x %02x %02x %02x %02x\n", |
|
492 |
req->sense[8], req->sense[9], req->sense[10], req->sense[11], |
|
493 |
req->sense[12], req->sense[13], req->sense[14], req->sense[15]); |
|
538 | 494 |
} |
539 | 495 |
|
540 |
if (req->sensing) { |
|
541 |
dprintf("VSCSI: Sense done !\n"); |
|
542 |
status = CHECK_CONDITION; |
|
543 |
} else { |
|
544 |
dprintf("VSCSI: Command complete err=%d\n", status); |
|
545 |
if (status == 0) { |
|
546 |
/* We handle overflows, not underflows for normal commands, |
|
547 |
* but hopefully nobody cares |
|
548 |
*/ |
|
549 |
if (req->writing) { |
|
550 |
res_out = req->data_len; |
|
551 |
} else { |
|
552 |
res_in = req->data_len; |
|
553 |
} |
|
496 |
dprintf("VSCSI: Command complete err=%d\n", status); |
|
497 |
if (status == 0) { |
|
498 |
/* We handle overflows, not underflows for normal commands, |
|
499 |
* but hopefully nobody cares |
|
500 |
*/ |
|
501 |
if (req->writing) { |
|
502 |
res_out = req->data_len; |
|
503 |
} else { |
|
504 |
res_in = req->data_len; |
|
554 | 505 |
} |
555 | 506 |
} |
556 |
vscsi_send_rsp(s, req, 0, res_in, res_out);
|
|
507 |
vscsi_send_rsp(s, req, status, res_in, res_out);
|
|
557 | 508 |
vscsi_put_req(req); |
558 | 509 |
} |
559 | 510 |
|
Also available in: Unified diff