Any SCSI emulation is supposed to return status codes as defined by SAM, not the linux ones which are shifted by one.
Signed-off-by: Hannes Reinecke <h...@suse.de> --- hw/megasas.c | 12 +++++++----- hw/scsi-bus.c | 4 +++- hw/scsi-defs.h | 20 +++++++++++--------- hw/scsi-generic.c | 12 ++++++------ 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/hw/megasas.c b/hw/megasas.c index 6ddb757..bc35566 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -1125,7 +1125,7 @@ static int megasas_handle_scsi(MPTState *s, struct megasas_cmd_t *cmd, int is_lo cmd->frame->header.target_id, cmd->frame->header.lun_id, cmd->frame->header.cdb_len); megasas_build_sense(cmd, SENSE_CODE(INVALID_OPCODE)); - megasas_frame_set_scsi_status(cmd->pa, CHECK_CONDITION << 1); + megasas_frame_set_scsi_status(cmd->pa, CHECK_CONDITION); s->event_count++; return MFI_STAT_SCSI_DONE_WITH_ERROR; } @@ -1177,7 +1177,7 @@ static int megasas_handle_io(MPTState *s, struct megasas_cmd_t *cmd) cmd->frame->header.target_id, cmd->frame->header.lun_id, cmd->frame->header.cdb_len); megasas_build_sense(cmd, SENSE_CODE(INVALID_OPCODE)); - megasas_frame_set_scsi_status(cmd->pa, CHECK_CONDITION << 1); + megasas_frame_set_scsi_status(cmd->pa, CHECK_CONDITION); s->event_count++; return MFI_STAT_SCSI_DONE_WITH_ERROR; } @@ -1236,9 +1236,11 @@ static void megasas_command_complete(SCSIRequest *req) DPRINTF_IO("%s req %p cmd %p lun %p finished with status %x len %u\n", mfi_frame_desc[cmd->frame->header.frame_cmd], req, cmd, cmd->sdev, req->status, (unsigned)req->xferlen); - if (req->status == CHECK_CONDITION << 1) { - megasas_build_sense(cmd, cmd->sdev->sense); + if (req->status != GOOD) { cmd_status = MFI_STAT_SCSI_DONE_WITH_ERROR; + } + if (req->status == CHECK_CONDITION) { + megasas_build_sense(cmd, cmd->sdev->sense); scsi_dev_clear_sense(cmd->sdev); } @@ -1302,7 +1304,7 @@ static void megasas_handle_frame(MPTState *s, target_phys_addr_t frame_addr, cmd = megasas_enqueue_frame(s, frame_addr); if (!cmd) { /* reply queue full */ - megasas_frame_set_scsi_status(frame_addr, BUSY << 1); + megasas_frame_set_scsi_status(frame_addr, BUSY); frame_status = MFI_STAT_SCSI_DONE_WITH_ERROR; s->event_count++; goto frame_done; diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 7d80405..c0e6dd3 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -525,7 +525,9 @@ const char *scsi_status_name(uint8_t status) [ INTERMEDIATE_C_GOOD ] = "INTERMEDIATE_C_GOOD", [ RESERVATION_CONFLICT ] = "RESERVATION_CONFLICT", [ COMMAND_TERMINATED ] = "COMMAND_TERMINATED", - [ QUEUE_FULL ] = "QUEUE_FULL", + [ TASK_SET_FULL ] = "TASK_SET_FULL", + [ ACA_ACTIVE ] = "ACA_ACTIVE", + [ TASK_ABORTED ] = "TASK_ABORTED", }; if (status >= ARRAY_SIZE(names) || names[status] == NULL) diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h index a4a3518..1473ecb 100644 --- a/hw/scsi-defs.h +++ b/hw/scsi-defs.h @@ -111,18 +111,20 @@ #define BLANK 0xa1 /* - * Status codes + * SAM Status codes */ #define GOOD 0x00 -#define CHECK_CONDITION 0x01 -#define CONDITION_GOOD 0x02 -#define BUSY 0x04 -#define INTERMEDIATE_GOOD 0x08 -#define INTERMEDIATE_C_GOOD 0x0a -#define RESERVATION_CONFLICT 0x0c -#define COMMAND_TERMINATED 0x11 -#define QUEUE_FULL 0x14 +#define CHECK_CONDITION 0x02 +#define CONDITION_GOOD 0x04 +#define BUSY 0x08 +#define INTERMEDIATE_GOOD 0x10 +#define INTERMEDIATE_C_GOOD 0x14 +#define RESERVATION_CONFLICT 0x18 +#define COMMAND_TERMINATED 0x22 +#define TASK_SET_FULL 0x28 +#define ACA_ACTIVE 0x30 +#define TASK_ABORTED 0x40 #define STATUS_MASK 0x3e diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index af76826..33d7e52 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -99,7 +99,7 @@ static void scsi_command_complete(void *opaque, int ret) if (ret == -EDOM) { /* sg driver uses EDOM to signal queue busy */ fprintf(stderr, "%s: sg queue busy\n", __FUNCTION__); - r->req.status = QUEUE_FULL << 1; + r->req.status = TASK_SET_FULL; } else { scsi_req_print(&r->req); fprintf(stderr, "%s: ret %d (%s)\n", __FUNCTION__, @@ -107,13 +107,13 @@ static void scsi_command_complete(void *opaque, int ret) s->senselen = scsi_build_sense(SENSE_CODE(INVALID_FIELD), s->sensebuf, SCSI_SENSE_BUF_SIZE, 0); s->driver_status = SG_ERR_DRIVER_SENSE; - r->req.status = CHECK_CONDITION << 1; + r->req.status = CHECK_CONDITION; } } else { if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) { scsi_req_print(&r->req); fprintf(stderr, "%s: timeout\n", __FUNCTION__); - r->req.status = BUSY << 1; + r->req.status = BUSY; } else if (r->io_header.status) { #if 0 scsi_req_print(&r->req); @@ -124,9 +124,9 @@ static void scsi_command_complete(void *opaque, int ret) } else if (s->driver_status & SG_ERR_DRIVER_SENSE) { scsi_req_print(&r->req); fprintf(stderr, "%s: driver sense\n", __FUNCTION__); - r->req.status = CHECK_CONDITION << 1; + r->req.status = CHECK_CONDITION; } else { - r->req.status = GOOD << 1; + r->req.status = GOOD; } } DPRINTF("Command complete 0x%p tag=0x%x status=%d\n", @@ -451,7 +451,7 @@ static int scsi_generic_req_common(SCSIRequest *req, uint8_t *buffer) s->senselen = scsi_build_sense(SENSE_CODE(LUN_NOT_SUPPORTED), s->sensebuf, SCSI_SENSE_BUF_SIZE, 0); s->driver_status = SG_ERR_DRIVER_SENSE; - req->status = CHECK_CONDITION << 1; + req->status = CHECK_CONDITION; return 1; } if (r->req.cmd.buf[0] == REQUEST_SENSE && -- 1.6.6.1