Modules/EHCI - Untested interrupt support
authorJohn Hodge <[email protected]>
Tue, 17 Dec 2013 10:12:31 +0000 (18:12 +0800)
committerJohn Hodge <[email protected]>
Tue, 17 Dec 2013 10:12:31 +0000 (18:12 +0800)
KernelLand/Modules/USB/EHCI/ehci.c
KernelLand/Modules/USB/EHCI/ehci.h

index 512b0d6..db1f3e3 100644 (file)
@@ -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;
index 6933113..9fd66c0 100644 (file)
@@ -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;

UCC git Repository :: git.ucc.asn.au