diff options
Diffstat (limited to 'hw/scsi/virtio-scsi.c')
-rw-r--r-- | hw/scsi/virtio-scsi.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 358c0e70b0..6d80730287 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -500,6 +500,51 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req) virtio_scsi_complete_req(req); } +static void virtio_scsi_command_failed(SCSIRequest *r) +{ + VirtIOSCSIReq *req = r->hba_private; + + if (r->io_canceled) { + return; + } + + req->resp.cmd.status = GOOD; + switch (r->host_status) { + case SCSI_HOST_NO_LUN: + req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN; + break; + case SCSI_HOST_BUSY: + req->resp.cmd.response = VIRTIO_SCSI_S_BUSY; + break; + case SCSI_HOST_TIME_OUT: + case SCSI_HOST_ABORTED: + req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED; + break; + case SCSI_HOST_BAD_RESPONSE: + req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; + break; + case SCSI_HOST_RESET: + req->resp.cmd.response = VIRTIO_SCSI_S_RESET; + break; + case SCSI_HOST_TRANSPORT_DISRUPTED: + req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE; + break; + case SCSI_HOST_TARGET_FAILURE: + req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE; + break; + case SCSI_HOST_RESERVATION_ERROR: + req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE; + break; + case SCSI_HOST_ALLOCATION_FAILURE: + case SCSI_HOST_MEDIUM_ERROR: + case SCSI_HOST_ERROR: + default: + req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE; + break; + } + virtio_scsi_complete_cmd_req(req); +} + static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid) { VirtIOSCSIReq *req = r->hba_private; @@ -908,6 +953,7 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = { .max_lun = VIRTIO_SCSI_MAX_LUN, .complete = virtio_scsi_command_complete, + .fail = virtio_scsi_command_failed, .cancel = virtio_scsi_request_cancelled, .change = virtio_scsi_change, .parse_cdb = virtio_scsi_parse_cdb, |