scsi: split command_complete callback in two
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Cc: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
3944966d95
commit
c6df7102f5
18
hw/esp.c
18
hw/esp.c
@ -395,19 +395,20 @@ static void esp_do_dma(ESPState *s)
|
|||||||
esp_dma_done(s);
|
esp_dma_done(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
static void esp_command_complete(SCSIRequest *req, uint32_t arg)
|
||||||
{
|
{
|
||||||
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
|
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
|
||||||
|
|
||||||
if (reason == SCSI_REASON_DONE) {
|
|
||||||
DPRINTF("SCSI Command complete\n");
|
DPRINTF("SCSI Command complete\n");
|
||||||
if (s->ti_size != 0)
|
if (s->ti_size != 0) {
|
||||||
DPRINTF("SCSI command completed unexpectedly\n");
|
DPRINTF("SCSI command completed unexpectedly\n");
|
||||||
|
}
|
||||||
s->ti_size = 0;
|
s->ti_size = 0;
|
||||||
s->dma_left = 0;
|
s->dma_left = 0;
|
||||||
s->async_len = 0;
|
s->async_len = 0;
|
||||||
if (arg)
|
if (arg) {
|
||||||
DPRINTF("Command failed\n");
|
DPRINTF("Command failed\n");
|
||||||
|
}
|
||||||
s->status = arg;
|
s->status = arg;
|
||||||
s->rregs[ESP_RSTAT] = STAT_ST;
|
s->rregs[ESP_RSTAT] = STAT_ST;
|
||||||
esp_dma_done(s);
|
esp_dma_done(s);
|
||||||
@ -416,7 +417,12 @@ static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
|||||||
s->current_req = NULL;
|
s->current_req = NULL;
|
||||||
s->current_dev = NULL;
|
s->current_dev = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
static void esp_transfer_data(SCSIRequest *req, uint32_t arg)
|
||||||
|
{
|
||||||
|
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
|
||||||
|
|
||||||
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
|
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
|
||||||
s->async_len = arg;
|
s->async_len = arg;
|
||||||
s->async_buf = scsi_req_get_buf(req);
|
s->async_buf = scsi_req_get_buf(req);
|
||||||
@ -428,7 +434,6 @@ static void esp_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
|||||||
esp_dma_done(s);
|
esp_dma_done(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_ti(ESPState *s)
|
static void handle_ti(ESPState *s)
|
||||||
{
|
{
|
||||||
@ -725,6 +730,7 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct SCSIBusOps esp_scsi_ops = {
|
static const struct SCSIBusOps esp_scsi_ops = {
|
||||||
|
.transfer_data = esp_transfer_data,
|
||||||
.complete = esp_command_complete,
|
.complete = esp_command_complete,
|
||||||
.cancel = esp_request_cancelled
|
.cancel = esp_request_cancelled
|
||||||
};
|
};
|
||||||
|
@ -711,14 +711,14 @@ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Callback to indicate that the SCSI layer has completed a transfer. */
|
|
||||||
static void lsi_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
/* Callback to indicate that the SCSI layer has completed a command. */
|
||||||
|
static void lsi_command_complete(SCSIRequest *req, uint32_t arg)
|
||||||
{
|
{
|
||||||
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
|
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
|
||||||
int out;
|
int out;
|
||||||
|
|
||||||
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
|
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
|
||||||
if (reason == SCSI_REASON_DONE) {
|
|
||||||
DPRINTF("Command complete status=%d\n", (int)arg);
|
DPRINTF("Command complete status=%d\n", (int)arg);
|
||||||
s->status = arg;
|
s->status = arg;
|
||||||
s->command_complete = 2;
|
s->command_complete = 2;
|
||||||
@ -735,9 +735,14 @@ static void lsi_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
|||||||
s->current = NULL;
|
s->current = NULL;
|
||||||
}
|
}
|
||||||
lsi_resume_script(s);
|
lsi_resume_script(s);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback to indicate that the SCSI layer has completed a transfer. */
|
||||||
|
static void lsi_transfer_data(SCSIRequest *req, uint32_t arg)
|
||||||
|
{
|
||||||
|
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
|
||||||
|
int out;
|
||||||
|
|
||||||
if (s->waiting == 1 || !s->current || req->tag != s->current->tag ||
|
if (s->waiting == 1 || !s->current || req->tag != s->current->tag ||
|
||||||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
|
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
|
||||||
if (lsi_queue_tag(s, req->tag, arg)) {
|
if (lsi_queue_tag(s, req->tag, arg)) {
|
||||||
@ -745,18 +750,20 @@ static void lsi_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
|
||||||
|
|
||||||
/* host adapter (re)connected */
|
/* host adapter (re)connected */
|
||||||
DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, arg);
|
DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, arg);
|
||||||
s->current->dma_len = arg;
|
s->current->dma_len = arg;
|
||||||
s->command_complete = 1;
|
s->command_complete = 1;
|
||||||
if (!s->waiting)
|
if (s->waiting) {
|
||||||
return;
|
|
||||||
if (s->waiting == 1 || s->dbc == 0) {
|
if (s->waiting == 1 || s->dbc == 0) {
|
||||||
lsi_resume_script(s);
|
lsi_resume_script(s);
|
||||||
} else {
|
} else {
|
||||||
lsi_do_dma(s, out);
|
lsi_do_dma(s, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void lsi_do_command(LSIState *s)
|
static void lsi_do_command(LSIState *s)
|
||||||
{
|
{
|
||||||
@ -2239,6 +2246,7 @@ static int lsi_scsi_uninit(PCIDevice *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct SCSIBusOps lsi_scsi_ops = {
|
static const struct SCSIBusOps lsi_scsi_ops = {
|
||||||
|
.transfer_data = lsi_transfer_data,
|
||||||
.complete = lsi_command_complete,
|
.complete = lsi_command_complete,
|
||||||
.cancel = lsi_request_cancelled
|
.cancel = lsi_request_cancelled
|
||||||
};
|
};
|
||||||
|
@ -634,7 +634,7 @@ void scsi_req_continue(SCSIRequest *req)
|
|||||||
void scsi_req_data(SCSIRequest *req, int len)
|
void scsi_req_data(SCSIRequest *req, int len)
|
||||||
{
|
{
|
||||||
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
|
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
|
||||||
req->bus->ops->complete(req, SCSI_REASON_DATA, len);
|
req->bus->ops->transfer_data(req, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scsi_req_print(SCSIRequest *req)
|
void scsi_req_print(SCSIRequest *req)
|
||||||
@ -670,7 +670,7 @@ void scsi_req_complete(SCSIRequest *req)
|
|||||||
assert(req->status != -1);
|
assert(req->status != -1);
|
||||||
scsi_req_ref(req);
|
scsi_req_ref(req);
|
||||||
scsi_req_dequeue(req);
|
scsi_req_dequeue(req);
|
||||||
req->bus->ops->complete(req, SCSI_REASON_DONE, req->status);
|
req->bus->ops->complete(req, req->status);
|
||||||
scsi_req_unref(req);
|
scsi_req_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,12 +9,6 @@
|
|||||||
|
|
||||||
#define SCSI_CMD_BUF_SIZE 16
|
#define SCSI_CMD_BUF_SIZE 16
|
||||||
|
|
||||||
/* scsi-disk.c */
|
|
||||||
enum scsi_reason {
|
|
||||||
SCSI_REASON_DONE, /* Command complete. */
|
|
||||||
SCSI_REASON_DATA /* Transfer complete, more data required. */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct SCSIBus SCSIBus;
|
typedef struct SCSIBus SCSIBus;
|
||||||
typedef struct SCSIBusOps SCSIBusOps;
|
typedef struct SCSIBusOps SCSIBusOps;
|
||||||
typedef struct SCSIDevice SCSIDevice;
|
typedef struct SCSIDevice SCSIDevice;
|
||||||
@ -84,7 +78,8 @@ struct SCSIDeviceInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct SCSIBusOps {
|
struct SCSIBusOps {
|
||||||
void (*complete)(SCSIRequest *req, int reason, uint32_t arg);
|
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
||||||
|
void (*complete)(SCSIRequest *req, uint32_t arg);
|
||||||
void (*cancel)(SCSIRequest *req);
|
void (*cancel)(SCSIRequest *req);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -480,27 +480,21 @@ static void vscsi_send_request_sense(VSCSIState *s, vscsi_req *req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Callback to indicate that the SCSI layer has completed a transfer. */
|
/* Callback to indicate that the SCSI layer has completed a transfer. */
|
||||||
static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
|
static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t arg)
|
||||||
{
|
{
|
||||||
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
|
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
|
||||||
vscsi_req *req = vscsi_find_req(s, sreq);
|
vscsi_req *req = vscsi_find_req(s, sreq);
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int32_t res_in = 0, res_out = 0;
|
|
||||||
int len, rc = 0;
|
int len, rc = 0;
|
||||||
|
|
||||||
dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x arg=0x%x, req=%p\n",
|
dprintf("VSCSI: SCSI xfer complete tag=0x%x arg=0x%x, req=%p\n",
|
||||||
reason, sreq->tag, arg, req);
|
sreq->tag, arg, req);
|
||||||
if (req == NULL) {
|
if (req == NULL) {
|
||||||
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
|
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->sensing) {
|
if (req->sensing) {
|
||||||
if (reason == SCSI_REASON_DONE) {
|
|
||||||
dprintf("VSCSI: Sense done !\n");
|
|
||||||
vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
|
|
||||||
vscsi_put_req(s, req);
|
|
||||||
} else {
|
|
||||||
uint8_t *buf = scsi_req_get_buf(sreq);
|
uint8_t *buf = scsi_req_get_buf(sreq);
|
||||||
|
|
||||||
len = MIN(arg, SCSI_SENSE_BUF_SIZE);
|
len = MIN(arg, SCSI_SENSE_BUF_SIZE);
|
||||||
@ -514,29 +508,6 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
|
|||||||
memcpy(req->sense, buf, len);
|
memcpy(req->sense, buf, len);
|
||||||
req->senselen = len;
|
req->senselen = len;
|
||||||
scsi_req_continue(req->sreq);
|
scsi_req_continue(req->sreq);
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reason == SCSI_REASON_DONE) {
|
|
||||||
dprintf("VSCSI: Command complete err=%d\n", arg);
|
|
||||||
if (arg == 0) {
|
|
||||||
/* We handle overflows, not underflows for normal commands,
|
|
||||||
* but hopefully nobody cares
|
|
||||||
*/
|
|
||||||
if (req->writing) {
|
|
||||||
res_out = req->data_len;
|
|
||||||
} else {
|
|
||||||
res_in = req->data_len;
|
|
||||||
}
|
|
||||||
vscsi_send_rsp(s, req, 0, res_in, res_out);
|
|
||||||
} else if (arg == CHECK_CONDITION) {
|
|
||||||
vscsi_send_request_sense(s, req);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
vscsi_send_rsp(s, req, arg, 0, 0);
|
|
||||||
}
|
|
||||||
vscsi_put_req(s, req);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,6 +530,45 @@ static void vscsi_command_complete(SCSIRequest *sreq, int reason, uint32_t arg)
|
|||||||
scsi_req_continue(sreq);
|
scsi_req_continue(sreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback to indicate that the SCSI layer has completed a transfer. */
|
||||||
|
static void vscsi_command_complete(SCSIRequest *sreq, uint32_t arg)
|
||||||
|
{
|
||||||
|
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
|
||||||
|
vscsi_req *req = vscsi_find_req(s, sreq);
|
||||||
|
int32_t res_in = 0, res_out = 0;
|
||||||
|
|
||||||
|
dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x arg=0x%x, req=%p\n",
|
||||||
|
reason, sreq->tag, arg, req);
|
||||||
|
if (req == NULL) {
|
||||||
|
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!req->sensing && arg == CHECK_CONDITION) {
|
||||||
|
vscsi_send_request_sense(s, req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->sensing) {
|
||||||
|
dprintf("VSCSI: Sense done !\n");
|
||||||
|
arg = CHECK_CONDITION;
|
||||||
|
} else {
|
||||||
|
dprintf("VSCSI: Command complete err=%d\n", arg);
|
||||||
|
if (arg == 0) {
|
||||||
|
/* We handle overflows, not underflows for normal commands,
|
||||||
|
* but hopefully nobody cares
|
||||||
|
*/
|
||||||
|
if (req->writing) {
|
||||||
|
res_out = req->data_len;
|
||||||
|
} else {
|
||||||
|
res_in = req->data_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vscsi_send_rsp(s, req, 0, res_in, res_out);
|
||||||
|
vscsi_put_req(s, req);
|
||||||
|
}
|
||||||
|
|
||||||
static void vscsi_request_cancelled(SCSIRequest *sreq)
|
static void vscsi_request_cancelled(SCSIRequest *sreq)
|
||||||
{
|
{
|
||||||
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
|
VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
|
||||||
@ -916,6 +926,7 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct SCSIBusOps vscsi_scsi_ops = {
|
static const struct SCSIBusOps vscsi_scsi_ops = {
|
||||||
|
.transfer_data = vscsi_transfer_data,
|
||||||
.complete = vscsi_command_complete,
|
.complete = vscsi_command_complete,
|
||||||
.cancel = vscsi_request_cancelled
|
.cancel = vscsi_request_cancelled
|
||||||
};
|
};
|
||||||
|
71
hw/usb-msd.c
71
hw/usb-msd.c
@ -208,7 +208,7 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
|
|||||||
memcpy(p->data, &csw, len);
|
memcpy(p->data, &csw, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_msd_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
static void usb_msd_transfer_data(SCSIRequest *req, uint32_t arg)
|
||||||
{
|
{
|
||||||
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||||
USBPacket *p = s->packet;
|
USBPacket *p = s->packet;
|
||||||
@ -216,35 +216,7 @@ static void usb_msd_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
|||||||
if (req->tag != s->tag) {
|
if (req->tag != s->tag) {
|
||||||
fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
|
fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
|
||||||
}
|
}
|
||||||
if (reason == SCSI_REASON_DONE) {
|
|
||||||
DPRINTF("Command complete %d\n", arg);
|
|
||||||
s->residue = s->data_len;
|
|
||||||
s->result = arg != 0;
|
|
||||||
if (s->packet) {
|
|
||||||
if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
|
|
||||||
/* A deferred packet with no write data remaining must be
|
|
||||||
the status read packet. */
|
|
||||||
usb_msd_send_status(s, p);
|
|
||||||
s->mode = USB_MSDM_CBW;
|
|
||||||
} else {
|
|
||||||
if (s->data_len) {
|
|
||||||
s->data_len -= s->usb_len;
|
|
||||||
if (s->mode == USB_MSDM_DATAIN)
|
|
||||||
memset(s->usb_buf, 0, s->usb_len);
|
|
||||||
s->usb_len = 0;
|
|
||||||
}
|
|
||||||
if (s->data_len == 0)
|
|
||||||
s->mode = USB_MSDM_CSW;
|
|
||||||
}
|
|
||||||
s->packet = NULL;
|
|
||||||
usb_packet_complete(&s->dev, p);
|
|
||||||
} else if (s->data_len == 0) {
|
|
||||||
s->mode = USB_MSDM_CSW;
|
|
||||||
}
|
|
||||||
scsi_req_unref(req);
|
|
||||||
s->req = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
|
assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
|
||||||
s->scsi_len = arg;
|
s->scsi_len = arg;
|
||||||
s->scsi_buf = scsi_req_get_buf(req);
|
s->scsi_buf = scsi_req_get_buf(req);
|
||||||
@ -261,6 +233,44 @@ static void usb_msd_command_complete(SCSIRequest *req, int reason, uint32_t arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void usb_msd_command_complete(SCSIRequest *req, uint32_t arg)
|
||||||
|
{
|
||||||
|
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||||
|
USBPacket *p = s->packet;
|
||||||
|
|
||||||
|
if (req->tag != s->tag) {
|
||||||
|
fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", req->tag);
|
||||||
|
}
|
||||||
|
DPRINTF("Command complete %d\n", arg);
|
||||||
|
s->residue = s->data_len;
|
||||||
|
s->result = arg != 0;
|
||||||
|
if (s->packet) {
|
||||||
|
if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
|
||||||
|
/* A deferred packet with no write data remaining must be
|
||||||
|
the status read packet. */
|
||||||
|
usb_msd_send_status(s, p);
|
||||||
|
s->mode = USB_MSDM_CBW;
|
||||||
|
} else {
|
||||||
|
if (s->data_len) {
|
||||||
|
s->data_len -= s->usb_len;
|
||||||
|
if (s->mode == USB_MSDM_DATAIN) {
|
||||||
|
memset(s->usb_buf, 0, s->usb_len);
|
||||||
|
}
|
||||||
|
s->usb_len = 0;
|
||||||
|
}
|
||||||
|
if (s->data_len == 0) {
|
||||||
|
s->mode = USB_MSDM_CSW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->packet = NULL;
|
||||||
|
usb_packet_complete(&s->dev, p);
|
||||||
|
} else if (s->data_len == 0) {
|
||||||
|
s->mode = USB_MSDM_CSW;
|
||||||
|
}
|
||||||
|
scsi_req_unref(req);
|
||||||
|
s->req = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void usb_msd_request_cancelled(SCSIRequest *req)
|
static void usb_msd_request_cancelled(SCSIRequest *req)
|
||||||
{
|
{
|
||||||
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||||
@ -494,6 +504,7 @@ static void usb_msd_password_cb(void *opaque, int err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct SCSIBusOps usb_msd_scsi_ops = {
|
static const struct SCSIBusOps usb_msd_scsi_ops = {
|
||||||
|
.transfer_data = usb_msd_transfer_data,
|
||||||
.complete = usb_msd_command_complete,
|
.complete = usb_msd_command_complete,
|
||||||
.cancel = usb_msd_request_cancelled
|
.cancel = usb_msd_request_cancelled
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user