From de6091a10d2cdded5e58f25ba3e3db7db726d01d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 17 Dec 2013 18:12:31 +0800 Subject: [PATCH] Modules/EHCI - Untested interrupt support --- KernelLand/Modules/USB/EHCI/ehci.c | 32 ++++++++++++++++++++++++++++++ KernelLand/Modules/USB/EHCI/ehci.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/KernelLand/Modules/USB/EHCI/ehci.c b/KernelLand/Modules/USB/EHCI/ehci.c index 512b0d6e..db1f3e37 100644 --- a/KernelLand/Modules/USB/EHCI/ehci.c +++ b/KernelLand/Modules/USB/EHCI/ehci.c @@ -380,6 +380,8 @@ void *EHCI_InitInterrupt(void *Ptr, int Endpoint, int bOutbound, int Period, int period_pow = _GetClosestPower2(Period); tEHCI_Endpoint *endpt = EHCI_int_AllocateEndpt(Cont, Endpoint, Length, period_pow); + endpt->Next = Cont->FirstInterruptEndpt; + Cont->FirstInterruptEndpt = endpt; // Allocate a QH tEHCI_QH *qh = EHCI_int_AllocateQH(Cont, endpt, Cb, CbData); @@ -801,6 +803,36 @@ void EHCI_int_HandlePortConnectChange(tEHCI_Controller *Cont, int Port) } } +void EHCI_int_CheckInterruptQHs(tEHCI_Controller *Cont) +{ + for( tEHCI_Endpoint *endpt = Cont->FirstInterruptEndpt; endpt; endpt = endpt->Next ) + { + tEHCI_QH *qh = endpt->ActiveQHs; + // Check if the TD of the first QH is active + if( qh->Overlay.Token & QTD_TOKEN_STS_ACTIVE ) + continue ; + // Inactive, fire interrupt and re-trigger + if( !qh->Impl.Callback ) { + // Umm... ? + } + else + { + tEHCI_qTD *last = qh->Impl.LastTD; + size_t remaining_len = (last->Token >> 16) & 0x7FFF; + if( remaining_len > last->Impl.Length ) + remaining_len = last->Impl.Length; + size_t transferred_len = last->Impl.Length - remaining_len; + + LOG("Calling %p(%p) for Intr EndPt %x (%p+0x%x)", + qh->Impl.Callback, qh->Impl.CallbackData, + qh->Impl.Endpt->EndpointID, last->Impl.Ptr, transferred_len); + qh->Impl.Callback(qh->Impl.CallbackData, last->Impl.Ptr, transferred_len); + } + qh->Impl.FirstTD->Token |= QTD_TOKEN_STS_ACTIVE; + qh->Overlay.Token |= QTD_TOKEN_STS_ACTIVE; + } +} + void EHCI_int_RetireQHs(tEHCI_Controller *Cont) { tEHCI_QH *prev = Cont->DeadQH; diff --git a/KernelLand/Modules/USB/EHCI/ehci.h b/KernelLand/Modules/USB/EHCI/ehci.h index 6933113c..9fd66c04 100644 --- a/KernelLand/Modules/USB/EHCI/ehci.h +++ b/KernelLand/Modules/USB/EHCI/ehci.h @@ -55,10 +55,13 @@ struct sEHCI_Controller tEHCI_QH *QHPools[QH_POOL_PAGES]; // [PAGE_SIZE/64] tMutex TDPoolMutex; tEHCI_qTD *TDPool; // [TD_POOL_SIZE] + + tEHCI_Endpoint *FirstInterruptEndpt; // List of interrupt endpoints }; struct sEHCI_Endpoint { + tEHCI_Endpoint *Next; bool NextToggle; Uint16 EndpointID; Sint8 PeriodPow2; -- 2.20.1