/* Helper function for command completion. */
static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
{
- int status;
+ uint32_t status;
SCSISense sense;
assert(r->req.aiocb == NULL);
goto done;
}
status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
- if (status == CHECK_CONDITION) {
+ if ((status & 0xff) == CHECK_CONDITION) {
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
r->req.sense_len = r->io_header.sb_len_wr;
} else {
}
}
- trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
+ trace_scsi_generic_command_complete_noio(r, r->req.tag, status & 0xff,
+ (status >> 8) & 0xff);
scsi_req_complete(&r->req, status);
done:
* the hardware in scsi_command_complete_noio. Clean
* up the io_header to avoid reporting it.
*/
+ r->io_header.host_status = 0;
r->io_header.driver_status = 0;
r->io_header.status = 0;
scsi_disk_aio_sgio_command(uint32_t tag, uint8_t cmd, uint64_t lba, int len, uint32_t timeout) "disk aio sgio: tag=0x%x cmd 0x%x (sector %" PRId64 ", count %d) timeout %u"
# scsi-generic.c
-scsi_generic_command_complete_noio(void *req, uint32_t tag, int statuc) "Command complete %p tag=0x%x status=%d"
+scsi_generic_command_complete_noio(void *req, uint32_t tag, uint8_t status, uint8_t host_status) "Command complete %p tag=0x%x status=0x%x host_status=0x%x"
scsi_generic_read_complete(uint32_t tag, int len) "Data ready tag=0x%x len=%d"
scsi_generic_read_data(uint32_t tag, uint32_t timeout) "scsi_read_data tag=0x%x timeout %u"
scsi_generic_write_complete(int ret) "scsi_write_complete() ret = %d"
return;
}
- req->resp.cmd.response = VIRTIO_SCSI_S_OK;
- req->resp.cmd.status = status;
- if (req->resp.cmd.status == GOOD) {
+ switch ((status >> 8) & 0xff) {
+ case SG_ERR_DID_OK:
+ req->resp.cmd.response = VIRTIO_SCSI_S_OK;
+ break;
+ case SG_ERR_DID_ERROR:
+ req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
+ break;
+ case SG_ERR_DID_NO_CONNECT:
+ req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN;
+ break;
+ case SG_ERR_DID_ABORT:
+ case SG_ERR_DID_TIME_OUT:
+ req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
+ break;
+ case SG_ERR_DID_BAD_TARGET:
+ req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
+ break;
+ case SG_ERR_DID_RESET:
+ req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
+ break;
+ case SG_ERR_DID_BUS_BUSY:
+ req->resp.cmd.response = VIRTIO_SCSI_S_BUSY;
+ break;
+ case SG_ERR_DID_TRANSPORT_DISRUPTED:
+ req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE;
+ break;
+ case SG_ERR_DID_TARGET_FAILURE:
+ req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE;
+ break;
+ case SG_ERR_DID_NEXUS_FAILURE:
+ req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE;
+ break;
+ default:
+ req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
+ break;
+ }
+
+ req->resp.cmd.status = (status & 0xff);
+ if (req->resp.cmd.status == GOOD &&
+ req->resp.cmd.response == VIRTIO_SCSI_S_OK) {
req->resp.cmd.resid = virtio_tswap32(vdev, resid);
} else {
req->resp.cmd.resid = 0;
#define SG_ERR_DID_NO_CONNECT 0x01
#define SG_ERR_DID_BUS_BUSY 0x02
#define SG_ERR_DID_TIME_OUT 0x03
-
+#define SG_ERR_DID_BAD_TARGET 0x04
+#define SG_ERR_DID_ABORT 0x05
+#define SG_ERR_DID_ERROR 0x07
+#define SG_ERR_DID_RESET 0x08
+#define SG_ERR_DID_TRANSPORT_DISRUPTED 0x0e
+#define SG_ERR_DID_TARGET_FAILURE 0x10
+#define SG_ERR_DID_NEXUS_FAILURE 0x11
#define SG_ERR_DRIVER_SENSE 0x08
-int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
- SCSISense *sense);
+uint32_t sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
+ SCSISense *sense);
#endif
#endif
PRHelperSGIOData *data = opaque;
struct sg_io_hdr io_hdr;
int ret;
- int status;
+ uint32_t status;
SCSISense sense_code;
memset(data->sense, 0, PR_HELPER_SENSE_SIZE);
ret = ioctl(data->fd, SG_IO, &io_hdr);
status = sg_io_sense_from_errno(ret < 0 ? errno : 0, &io_hdr,
&sense_code);
- if (status == GOOD) {
+ if ((status & 0xff) == GOOD) {
data->sz -= io_hdr.resid;
} else {
data->sz = 0;
}
- if (status == CHECK_CONDITION &&
+ if ((status & 0xff) == CHECK_CONDITION &&
!(io_hdr.driver_status & SG_ERR_DRIVER_SENSE)) {
scsi_build_sense(data->sense, sense_code);
}
}
#ifdef CONFIG_LINUX
-int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
+uint32_t sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
SCSISense *sense)
{
if (errno_value != 0) {
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;
+ uint32_t status = GOOD;
+
+ if (io_hdr->status) {
+ status = io_hdr->status;
} else if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
- return CHECK_CONDITION;
- } else {
- return GOOD;
+ status = CHECK_CONDITION;
}
+ if (io_hdr->host_status)
+ status |= (io_hdr->host_status << 8);
+ return status;
}
}
#endif