mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 11:53:39 +08:00
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint8_t *buf = req->cmd.buf;
|
||||
@ -303,6 +348,7 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf)
|
||||
return rc;
|
||||
|
||||
memcpy(req->cmd.buf, buf, req->cmd.len);
|
||||
scsi_req_xfer_mode(req);
|
||||
req->cmd.lba = scsi_req_lba(req);
|
||||
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
|
||||
command. This will be Positive for data transfers from the device
|
||||
(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);
|
||||
r->len = r->req.cmd.xfer;
|
||||
if (is_write(cmd[0])) {
|
||||
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
|
||||
r->len = 0;
|
||||
return -r->req.cmd.xfer;
|
||||
}
|
||||
|
@ -18,6 +18,12 @@ typedef struct SCSIDeviceInfo SCSIDeviceInfo;
|
||||
typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
|
||||
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 {
|
||||
SCSIBus *bus;
|
||||
SCSIDevice *dev;
|
||||
@ -28,6 +34,7 @@ typedef struct SCSIRequest {
|
||||
int len;
|
||||
size_t xfer;
|
||||
uint64_t lba;
|
||||
enum SCSIXferMode mode;
|
||||
} cmd;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
QTAILQ_ENTRY(SCSIRequest) next;
|
||||
|
Loading…
Reference in New Issue
Block a user