/*
* Service the default endpoint (ep0) as host.
- * return TRUE if more packets are required for this transaction
+ * Return TRUE until it's time to start the status stage.
*/
-static u8 musb_h_ep0_continue(struct musb *pThis,
+static int musb_h_ep0_continue(struct musb *pThis,
u16 wCount, struct urb *pUrb)
{
- u8 bMore = FALSE;
+ int bMore = FALSE;
u8 *pFifoDest = NULL;
u16 wFifoCount = 0;
struct musb_hw_ep *pEnd = pThis->control_ep;
struct musb_qh *qh = pEnd->in_qh;
struct usb_ctrlrequest *pRequest;
- pRequest = (struct usb_ctrlrequest *) pUrb->setup_packet;
- if (MGC_END0_IN == pThis->bEnd0Stage) {
- /* we are receiving from peripheral */
+ switch (pThis->bEnd0Stage) {
+ case MGC_END0_IN:
pFifoDest = pUrb->transfer_buffer + pUrb->actual_length;
wFifoCount = min(wCount, ((u16) (pUrb->transfer_buffer_length
- pUrb->actual_length)));
/* always terminate on short read; it's
* rarely reported as an error.
*/
- if ((pUrb->transfer_flags & URB_SHORT_NOT_OK)
- && (pUrb->actual_length <
- pUrb->transfer_buffer_length))
- pUrb->status = -EREMOTEIO;
} else if (pUrb->actual_length <
pUrb->transfer_buffer_length)
bMore = TRUE;
- } else {
-/*
- DBG(3, "%s hw%d urb %p spd%d dev%d ep%d%s "
- "hub%d port%d%s bytes %d\n",
- is_out ? "-->" : "<--",
- bEnd, pUrb, pUrb->dev->speed,
- bAddress, qh->epnum, is_out ? "out" : "in",
- bHubAddr, bHubPort + 1,
- bIsMulti ? " multi" : "",
- dwLength);
-*/
- if ((MGC_END0_START == pThis->bEnd0Stage)
- && (pRequest->bRequestType & USB_DIR_IN)) {
- /* this means we just did setup; switch to IN */
+ break;
+ case MGC_END0_START:
+ pRequest = (struct usb_ctrlrequest *) pUrb->setup_packet;
+
+ if (!pRequest->wLength) {
+ DBG(4, "start no-DATA\n");
+ break;
+ } else if (pRequest->bRequestType & USB_DIR_IN) {
DBG(4, "start IN-DATA\n");
pThis->bEnd0Stage = MGC_END0_IN;
bMore = TRUE;
-
- } else if (pRequest->wLength
- && (MGC_END0_START == pThis->bEnd0Stage)) {
+ break;
+ } else {
+ DBG(4, "start OUT-DATA\n");
pThis->bEnd0Stage = MGC_END0_OUT;
+ bMore = TRUE;
+ }
+ /* FALLTHROUGH */
+ case MGC_END0_OUT:
+ wFifoCount = min(qh->maxpacket, ((u16)
+ (pUrb->transfer_buffer_length
+ - pUrb->actual_length)));
+
+ if (wFifoCount) {
pFifoDest = (u8 *) (pUrb->transfer_buffer
+ pUrb->actual_length);
- wFifoCount = min(qh->maxpacket, ((u16)
- (pUrb->transfer_buffer_length
- - pUrb->actual_length)));
DBG(3, "Sending %d bytes to %p\n",
wFifoCount, pFifoDest);
musb_write_fifo(pEnd, wFifoCount, pFifoDest);
- qh->segsize = wFifoCount;
pUrb->actual_length += wFifoCount;
- if (pUrb->actual_length
- < pUrb->transfer_buffer_length) {
- bMore = TRUE;
- }
+ bMore = TRUE;
}
+ break;
+ default:
+ ERR("bogus ep0 stage %d\n", pThis->bEnd0Stage);
+ break;
}
return bMore;
MGC_SelectEnd(pBase, 0);
wCsrVal = musb_readw(epio, MGC_O_HDRC_CSR0);
- wCount = musb_readb(epio, MGC_O_HDRC_COUNT0);
+ wCount = (wCsrVal & MGC_M_CSR0_RXPKTRDY)
+ ? musb_readb(epio, MGC_O_HDRC_COUNT0)
+ : 0;
DBG(4, "<== csr0 %04x, qh %p, count %d, urb %p, stage %d\n",
wCsrVal, qh, wCount, pUrb, pThis->bEnd0Stage);
? MGC_M_CSR0_H_REQPKT : MGC_M_CSR0_TXPKTRDY;
} else {
/* data transfer complete; perform status phase */
- wCsrVal = MGC_M_CSR0_H_STATUSPKT
- | (usb_pipeout(pUrb->pipe)
- ? MGC_M_CSR0_H_REQPKT
- : MGC_M_CSR0_TXPKTRDY);
+ if (usb_pipeout(pUrb->pipe)
+ || !pUrb->transfer_buffer_length)
+ wCsrVal = MGC_M_CSR0_H_STATUSPKT
+ | MGC_M_CSR0_H_REQPKT;
+ else
+ wCsrVal = MGC_M_CSR0_H_STATUSPKT
+ | MGC_M_CSR0_TXPKTRDY;
+
/* flag status stage */
pThis->bEnd0Stage = MGC_END0_STATUS;
}
musb_writew(epio, MGC_O_HDRC_CSR0, wCsrVal);
retval = IRQ_HANDLED;
- }
+ } else
+ pThis->bEnd0Stage = MGC_END0_IDLE;
/* call completion handler if done */
if (bComplete)