diff --git a/src/machine/usb/msc/msc.go b/src/machine/usb/msc/msc.go index 420a06ed9..91b30eec3 100644 --- a/src/machine/usb/msc/msc.go +++ b/src/machine/usb/msc/msc.go @@ -1,12 +1,12 @@ package msc import ( + "internal/task" "machine" "machine/usb" "machine/usb/descriptor" "machine/usb/msc/csw" "machine/usb/msc/scsi" - "time" ) type mscState uint8 @@ -26,14 +26,14 @@ const ( var MSC *msc type msc struct { - buf []byte // Buffer for incoming/outgoing data - blockCache []byte // Buffer for block read/write data - taskQueued bool // Flag to indicate if the buffer has a task queued - rxStalled bool // Flag to indicate if the RX endpoint is stalled - txStalled bool // Flag to indicate if the TX endpoint is stalled - maxPacketSize uint32 // Maximum packet size for the IN endpoint - respStatus csw.Status // Response status for the last command - sendZLP bool // Flag to indicate if a zero-length packet should be sent before sending CSW + buf []byte // Buffer for incoming/outgoing data + blockCache []byte // Buffer for block read/write data + taskWaiter task.Waiter // Waiter for events outside interrupt context + rxStalled bool // Flag to indicate if the RX endpoint is stalled + txStalled bool // Flag to indicate if the TX endpoint is stalled + maxPacketSize uint32 // Maximum packet size for the IN endpoint + respStatus csw.Status // Response status for the last command + sendZLP bool // Flag to indicate if a zero-length packet should be sent before sending CSW cbw *CBW // Last received Command Block Wrapper queuedBytes uint32 // Number of bytes queued for sending @@ -120,21 +120,21 @@ func newMSC(dev machine.BlockDevice) *msc { func (m *msc) processTasks() { // Process tasks that cannot be done in an interrupt context for { - if m.taskQueued { - cmd := m.cbw.SCSICmd() - switch cmd.CmdType() { - case scsi.CmdWrite: - m.scsiWrite(cmd, m.buf) - case scsi.CmdUnmap: - m.scsiUnmap(m.buf) - } + // Wait for the next task to arrive. + m.taskWaiter.Wait() - // Acknowledge the received data from the host - m.queuedBytes = 0 - m.taskQueued = false - machine.AckUsbOutTransfer(usb.MSC_ENDPOINT_OUT) + cmd := m.cbw.SCSICmd() + switch cmd.CmdType() { + case scsi.CmdWrite: + m.scsiWrite(cmd, m.buf) + case scsi.CmdUnmap: + m.scsiUnmap(m.buf) } - time.Sleep(100 * time.Microsecond) + + // Acknowledge the received data from the host + m.queuedBytes = 0 + m.taskWaiter.Done() + machine.AckUsbOutTransfer(usb.MSC_ENDPOINT_OUT) } } diff --git a/src/machine/usb/msc/scsi.go b/src/machine/usb/msc/scsi.go index 4cec23e2f..3fd5edff1 100644 --- a/src/machine/usb/msc/scsi.go +++ b/src/machine/usb/msc/scsi.go @@ -251,7 +251,7 @@ func (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool { } // Save the incoming data in our buffer for processing outside of interrupt context. - if m.taskQueued { + if m.taskWaiter.Working() { // If we already have a full task queue we can't accept this data m.sendScsiError(csw.StatusFailed, scsi.SenseAbortedCommand, scsi.SenseCodeMsgReject) return true @@ -268,14 +268,14 @@ func (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool { case scsi.CmdWrite: // If we're writing data wait until we have a full write block of data that can be processed. if m.queuedBytes == uint32(cap(m.blockCache)) || (m.sentBytes+m.queuedBytes >= m.transferBytes) { - m.taskQueued = true + m.taskWaiter.Resume() } case scsi.CmdUnmap: - m.taskQueued = true + m.taskWaiter.Resume() } // Don't acknowledge the incoming data until we can process it. - return !m.taskQueued + return !m.taskWaiter.Working() } func (m *msc) sendScsiError(status csw.Status, key scsi.Sense, code scsi.SenseCode) {