mirror of https://github.com/xqemu/xqemu.git
scsi: add xfer mode
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
ebf4602312
commit
97a0643567
|
@ -258,6 +258,51 @@ static int scsi_req_stream_length(SCSIRequest *req, uint8_t *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scsi_req_xfer_mode(SCSIRequest *req)
|
||||||
|
{
|
||||||
|
switch (req->cmd.buf[0]) {
|
||||||
|
case WRITE_6:
|
||||||
|
case WRITE_10:
|
||||||
|
case WRITE_VERIFY:
|
||||||
|
case WRITE_12:
|
||||||
|
case WRITE_VERIFY_12:
|
||||||
|
case COPY:
|
||||||
|
case COPY_VERIFY:
|
||||||
|
case COMPARE:
|
||||||
|
case CHANGE_DEFINITION:
|
||||||
|
case LOG_SELECT:
|
||||||
|
case MODE_SELECT:
|
||||||
|
case MODE_SELECT_10:
|
||||||
|
case SEND_DIAGNOSTIC:
|
||||||
|
case WRITE_BUFFER:
|
||||||
|
case FORMAT_UNIT:
|
||||||
|
case REASSIGN_BLOCKS:
|
||||||
|
case RESERVE:
|
||||||
|
case SEARCH_EQUAL:
|
||||||
|
case SEARCH_HIGH:
|
||||||
|
case SEARCH_LOW:
|
||||||
|
case UPDATE_BLOCK:
|
||||||
|
case WRITE_LONG:
|
||||||
|
case WRITE_SAME:
|
||||||
|
case SEARCH_HIGH_12:
|
||||||
|
case SEARCH_EQUAL_12:
|
||||||
|
case SEARCH_LOW_12:
|
||||||
|
case SET_WINDOW:
|
||||||
|
case MEDIUM_SCAN:
|
||||||
|
case SEND_VOLUME_TAG:
|
||||||
|
case WRITE_LONG_2:
|
||||||
|
req->cmd.mode = SCSI_XFER_TO_DEV;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (req->cmd.xfer)
|
||||||
|
req->cmd.mode = SCSI_XFER_FROM_DEV;
|
||||||
|
else {
|
||||||
|
req->cmd.mode = SCSI_XFER_NONE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t scsi_req_lba(SCSIRequest *req)
|
static uint64_t scsi_req_lba(SCSIRequest *req)
|
||||||
{
|
{
|
||||||
uint8_t *buf = req->cmd.buf;
|
uint8_t *buf = req->cmd.buf;
|
||||||
|
@ -303,6 +348,7 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
memcpy(req->cmd.buf, buf, req->cmd.len);
|
memcpy(req->cmd.buf, buf, req->cmd.len);
|
||||||
|
scsi_req_xfer_mode(req);
|
||||||
req->cmd.lba = scsi_req_lba(req);
|
req->cmd.lba = scsi_req_lba(req);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,44 +307,6 @@ static void scsi_req_fixup(SCSIRequest *req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_write(int command)
|
|
||||||
{
|
|
||||||
switch (command) {
|
|
||||||
case COPY:
|
|
||||||
case COPY_VERIFY:
|
|
||||||
case COMPARE:
|
|
||||||
case CHANGE_DEFINITION:
|
|
||||||
case LOG_SELECT:
|
|
||||||
case MODE_SELECT:
|
|
||||||
case MODE_SELECT_10:
|
|
||||||
case SEND_DIAGNOSTIC:
|
|
||||||
case WRITE_BUFFER:
|
|
||||||
case FORMAT_UNIT:
|
|
||||||
case REASSIGN_BLOCKS:
|
|
||||||
case RESERVE:
|
|
||||||
case SEARCH_EQUAL:
|
|
||||||
case SEARCH_HIGH:
|
|
||||||
case SEARCH_LOW:
|
|
||||||
case WRITE_6:
|
|
||||||
case WRITE_10:
|
|
||||||
case WRITE_VERIFY:
|
|
||||||
case UPDATE_BLOCK:
|
|
||||||
case WRITE_LONG:
|
|
||||||
case WRITE_SAME:
|
|
||||||
case SEARCH_HIGH_12:
|
|
||||||
case SEARCH_EQUAL_12:
|
|
||||||
case SEARCH_LOW_12:
|
|
||||||
case WRITE_12:
|
|
||||||
case WRITE_VERIFY_12:
|
|
||||||
case SET_WINDOW:
|
|
||||||
case MEDIUM_SCAN:
|
|
||||||
case SEND_VOLUME_TAG:
|
|
||||||
case WRITE_LONG_2:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute a scsi command. Returns the length of the data expected by the
|
/* Execute a scsi command. Returns the length of the data expected by the
|
||||||
command. This will be Positive for data transfers from the device
|
command. This will be Positive for data transfers from the device
|
||||||
(eg. disk reads), negative for transfers to the device (eg. disk writes),
|
(eg. disk reads), negative for transfers to the device (eg. disk writes),
|
||||||
|
@ -415,7 +377,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
|
||||||
|
|
||||||
memset(r->buf, 0, r->buflen);
|
memset(r->buf, 0, r->buflen);
|
||||||
r->len = r->req.cmd.xfer;
|
r->len = r->req.cmd.xfer;
|
||||||
if (is_write(cmd[0])) {
|
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
|
||||||
r->len = 0;
|
r->len = 0;
|
||||||
return -r->req.cmd.xfer;
|
return -r->req.cmd.xfer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,12 @@ typedef struct SCSIDeviceInfo SCSIDeviceInfo;
|
||||||
typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
|
typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
|
||||||
uint32_t arg);
|
uint32_t arg);
|
||||||
|
|
||||||
|
enum SCSIXferMode {
|
||||||
|
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
|
||||||
|
SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
|
||||||
|
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct SCSIRequest {
|
typedef struct SCSIRequest {
|
||||||
SCSIBus *bus;
|
SCSIBus *bus;
|
||||||
SCSIDevice *dev;
|
SCSIDevice *dev;
|
||||||
|
@ -28,6 +34,7 @@ typedef struct SCSIRequest {
|
||||||
int len;
|
int len;
|
||||||
size_t xfer;
|
size_t xfer;
|
||||||
uint64_t lba;
|
uint64_t lba;
|
||||||
|
enum SCSIXferMode mode;
|
||||||
} cmd;
|
} cmd;
|
||||||
BlockDriverAIOCB *aiocb;
|
BlockDriverAIOCB *aiocb;
|
||||||
QTAILQ_ENTRY(SCSIRequest) next;
|
QTAILQ_ENTRY(SCSIRequest) next;
|
||||||
|
|
Loading…
Reference in New Issue