mirror of https://gitee.com/openkylin/qemu.git
scsi: introduce sg_io_sense_from_errno
Move more knowledge of SG_IO out of hw/scsi/scsi-generic.c, for reusability. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
a3760467c6
commit
1ead6b4e24
|
@ -81,6 +81,7 @@ static void scsi_free_request(SCSIRequest *req)
|
|||
static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
|
||||
{
|
||||
int status;
|
||||
SCSISense sense;
|
||||
|
||||
assert(r->req.aiocb == NULL);
|
||||
|
||||
|
@ -88,42 +89,15 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
|
|||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
r->req.sense_len = r->io_header.sb_len_wr;
|
||||
status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
|
||||
if (status == CHECK_CONDITION) {
|
||||
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
r->req.sense_len = r->io_header.sb_len_wr;
|
||||
} else {
|
||||
scsi_req_build_sense(&r->req, sense);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
switch (ret) {
|
||||
case -EDOM:
|
||||
status = TASK_SET_FULL;
|
||||
break;
|
||||
case -ENOMEM:
|
||||
status = CHECK_CONDITION;
|
||||
scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
|
||||
break;
|
||||
default:
|
||||
status = CHECK_CONDITION;
|
||||
scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
|
||||
r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
|
||||
r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
|
||||
(r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
|
||||
status = BUSY;
|
||||
BADF("Driver Timeout\n");
|
||||
} else if (r->io_header.host_status) {
|
||||
status = CHECK_CONDITION;
|
||||
scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
|
||||
} else if (r->io_header.status) {
|
||||
status = r->io_header.status;
|
||||
} else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
status = CHECK_CONDITION;
|
||||
} else {
|
||||
status = GOOD;
|
||||
}
|
||||
}
|
||||
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
|
||||
r, r->req.tag, status);
|
||||
|
||||
|
|
|
@ -116,6 +116,9 @@ int scsi_cdb_length(uint8_t *buf);
|
|||
#define SG_ERR_DID_TIME_OUT 0x03
|
||||
|
||||
#define SG_ERR_DRIVER_SENSE 0x08
|
||||
|
||||
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
|
||||
SCSISense *sense);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
35
scsi/utils.c
35
scsi/utils.c
|
@ -501,3 +501,38 @@ const char *scsi_command_name(uint8_t cmd)
|
|||
}
|
||||
return names[cmd];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
|
||||
SCSISense *sense)
|
||||
{
|
||||
if (errno_value != 0) {
|
||||
switch (errno_value) {
|
||||
case EDOM:
|
||||
return TASK_SET_FULL;
|
||||
case ENOMEM:
|
||||
*sense = SENSE_CODE(TARGET_FAILURE);
|
||||
return CHECK_CONDITION;
|
||||
default:
|
||||
*sense = SENSE_CODE(IO_ERROR);
|
||||
return CHECK_CONDITION;
|
||||
}
|
||||
} else {
|
||||
if (io_hdr->host_status == SG_ERR_DID_NO_CONNECT ||
|
||||
io_hdr->host_status == SG_ERR_DID_BUS_BUSY ||
|
||||
io_hdr->host_status == SG_ERR_DID_TIME_OUT ||
|
||||
(io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT)) {
|
||||
return BUSY;
|
||||
} else if (io_hdr->host_status) {
|
||||
*sense = SENSE_CODE(I_T_NEXUS_LOSS);
|
||||
return CHECK_CONDITION;
|
||||
} else if (io_hdr->status) {
|
||||
return io_hdr->status;
|
||||
} else if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
return CHECK_CONDITION;
|
||||
} else {
|
||||
return GOOD;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue