提交 3d5aba97 编写于 作者: P Paolo Bonzini

scsi: add scatter/gather functionality

Scatter/gather functionality uses the newly added DMA helpers.  The
device can choose between doing DMA itself, or calling scsi_req_data
as usual, which will use the newly added DMA helpers to copy piecewise
to/from the destination area(s).
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
上级 01e95455
......@@ -5,6 +5,7 @@
#include "qdev.h"
#include "blockdev.h"
#include "trace.h"
#include "dma.h"
static char *scsibus_get_fw_dev_path(DeviceState *dev);
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
......@@ -651,6 +652,11 @@ int32_t scsi_req_enqueue(SCSIRequest *req)
assert(!req->enqueued);
scsi_req_ref(req);
if (req->bus->info->get_sg_list) {
req->sg = req->bus->info->get_sg_list(req);
} else {
req->sg = NULL;
}
req->enqueued = true;
QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
......@@ -1275,14 +1281,32 @@ void scsi_req_continue(SCSIRequest *req)
Once it completes, calling scsi_req_continue will restart I/O. */
void scsi_req_data(SCSIRequest *req, int len)
{
uint8_t *buf;
if (req->io_canceled) {
trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
return;
}
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
assert(req->cmd.mode != SCSI_XFER_NONE);
req->resid -= len;
req->bus->info->transfer_data(req, len);
if (!req->sg) {
req->resid -= len;
req->bus->info->transfer_data(req, len);
return;
}
/* If the device calls scsi_req_data and the HBA specified a
* scatter/gather list, the transfer has to happen in a single
* step. */
assert(!req->dma_started);
req->dma_started = true;
buf = scsi_req_get_buf(req);
if (req->cmd.mode == SCSI_XFER_FROM_DEV) {
req->resid = dma_buf_read(buf, len, req->sg);
} else {
req->resid = dma_buf_write(buf, len, req->sg);
}
scsi_req_continue(req);
}
void scsi_req_print(SCSIRequest *req)
......
......@@ -49,6 +49,8 @@ struct SCSIRequest {
size_t resid;
SCSICommand cmd;
BlockDriverAIOCB *aiocb;
QEMUSGList *sg;
bool dma_started;
uint8_t sense[SCSI_SENSE_BUF_SIZE];
uint32_t sense_len;
bool enqueued;
......@@ -115,6 +117,7 @@ struct SCSIBusInfo {
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
void (*cancel)(SCSIRequest *req);
QEMUSGList *(*get_sg_list)(SCSIRequest *req);
};
struct SCSIBus {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册