summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/controller/dwc_otg.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/controller/dwc_otg.c')
-rw-r--r--freebsd/sys/dev/usb/controller/dwc_otg.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.c b/freebsd/sys/dev/usb/controller/dwc_otg.c
index abc23ac6..1332b485 100644
--- a/freebsd/sys/dev/usb/controller/dwc_otg.c
+++ b/freebsd/sys/dev/usb/controller/dwc_otg.c
@@ -1460,6 +1460,8 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
/* check if we are complete */
if (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN) {
goto complete;
+ } else if (td->hcsplt != 0) {
+ goto receive_pkt;
} else {
/* get more packets */
goto busy;
@@ -1518,8 +1520,10 @@ receive_pkt:
if (td->hcsplt != 0) {
delta = td->tt_complete_slot - sc->sc_last_frame_num - 1;
if (td->tt_scheduled == 0 || delta < DWC_OTG_TT_SLOT_MAX) {
- td->state = DWC_CHAN_ST_WAIT_C_PKT;
- goto busy;
+ if (td->ep_type != UE_ISOCHRONOUS) {
+ td->state = DWC_CHAN_ST_WAIT_C_PKT;
+ goto busy;
+ }
}
delta = sc->sc_last_frame_num - td->tt_start_slot;
if (delta > DWC_OTG_TT_SLOT_MAX) {
@@ -1565,12 +1569,23 @@ receive_pkt:
hcchar = td->hcchar;
hcchar |= HCCHAR_EPDIR_IN;
- /* receive complete split ASAP */
- if ((sc->sc_last_frame_num & 1) != 0 &&
- td->ep_type == UE_ISOCHRONOUS)
- hcchar |= HCCHAR_ODDFRM;
- else
+ if (td->ep_type == UE_ISOCHRONOUS) {
+ if (td->hcsplt != 0) {
+ /* continously buffer */
+ if (sc->sc_last_frame_num & 1)
+ hcchar &= ~HCCHAR_ODDFRM;
+ else
+ hcchar |= HCCHAR_ODDFRM;
+ } else {
+ /* multi buffer, if any */
+ if (sc->sc_last_frame_num & 1)
+ hcchar |= HCCHAR_ODDFRM;
+ else
+ hcchar &= ~HCCHAR_ODDFRM;
+ }
+ } else {
hcchar &= ~HCCHAR_ODDFRM;
+ }
/* must enable channel before data can be received */
DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);