char *serial;
SCSIDevice *scsi_dev;
uint32_t removable;
- int result;
/* For async completion. */
USBPacket *packet;
} MSDState;
DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
s->residue = s->data_len;
- s->result = status != 0;
s->csw.sig = cpu_to_le32(0x53425355);
s->csw.tag = cpu_to_le32(req->tag);
s->csw.residue = s->residue;
- s->csw.status = s->result;
+ s->csw.status = status != 0;
if (s->packet) {
if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
MSDState *s = (MSDState *)dev;
DPRINTF("Reset\n");
+ if (s->req) {
+ scsi_req_cancel(s->req);
+ }
+ assert(s->req == NULL);
+
+ if (s->packet) {
+ USBPacket *p = s->packet;
+ s->packet = NULL;
+ p->result = USB_RET_STALL;
+ usb_packet_complete(dev, p);
+ }
+
s->mode = USB_MSDM_CBW;
}
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
ret = 0;
break;
- case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
/* Class specific requests. */
case ClassInterfaceOutRequest | MassStorageReset:
/* Reset state ready for the next CBW. */
s->scsi_len = 0;
s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
scsi_req_enqueue(s->req);
- /* ??? Should check that USB and SCSI data transfer
- directions match. */
- if (s->mode != USB_MSDM_CSW && s->residue == 0) {
+ if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
scsi_req_continue(s->req);
}
ret = p->result;
goto fail;
}
- usb_msd_send_status(s, p);
- s->mode = USB_MSDM_CBW;
- ret = 13;
+ if (s->req) {
+ /* still in flight */
+ s->packet = p;
+ ret = USB_RET_ASYNC;
+ } else {
+ usb_msd_send_status(s, p);
+ s->mode = USB_MSDM_CBW;
+ ret = 13;
+ }
break;
case USB_MSDM_DATAIN:
DriveInfo *dinfo;
if (!bs) {
- error_report("usb-msd: drive property not set");
+ error_report("drive property not set");
return -1;
}
usb_desc_init(dev);
scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
- s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
+ s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+ s->conf.bootindex);
if (!s->scsi_dev) {
return -1;
}
}
}
- add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
return 0;
}