Merge branch 'master' of git://localhost/acess2
[tpg/acess2.git] / KernelLand / Modules / USB / EHCI / ehci.c
index 512b0d6..d202d06 100644 (file)
@@ -258,11 +258,11 @@ int EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum)
 _error:
        cont->PhysBase = 0;
        if( cont->CapRegs )
-               MM_Deallocate( (tVAddr)cont->CapRegs );
+               MM_Deallocate( cont->CapRegs );
        if( cont->PeriodicQueue )
-               MM_Deallocate( (tVAddr)cont->PeriodicQueue );
+               MM_Deallocate( cont->PeriodicQueue );
        if( cont->TDPool )
-               MM_Deallocate( (tVAddr)cont->TDPool );
+               MM_Deallocate( cont->TDPool );
        LEAVE('i', 2);
        return 2;
 }
@@ -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;
@@ -856,6 +888,8 @@ void EHCI_int_ReclaimQHs(tEHCI_Controller *Cont)
                        LOG("Calling %p(%p) for EndPt %x (%p+0x%x)",
                                qh->Impl.Callback, qh->Impl.CallbackData,
                                qh->Impl.Endpt->EndpointID, last->Impl.Ptr, transferred_len);
+                       //if( last->Impl.Ptr )
+                       //      Debug_HexDump("EHCI Callback Data", last->Impl.Ptr, transferred_len);
                        qh->Impl.Callback(qh->Impl.CallbackData, last->Impl.Ptr, transferred_len);
                }
                
@@ -867,6 +901,7 @@ void EHCI_int_ReclaimQHs(tEHCI_Controller *Cont)
 void EHCI_int_InterruptThread(void *ControllerPtr)
 {
        tEHCI_Controller        *Cont = ControllerPtr;
+       Threads_SetName("EHCI Interrupt Worker");
        while(Cont->OpRegs)
        {
                Uint32  events;
@@ -886,9 +921,8 @@ void EHCI_int_InterruptThread(void *ControllerPtr)
                if( events & EHCI_THREADEVENT_IOC )
                {
                        // IOC, handle completed requests
-                       Log_Warning("EHCI", "%P IOC - TODO: Call registered callbacks and reclaim",
-                               Cont->PhysBase);
                        // Search periodic lists for one that fired
+                       EHCI_int_CheckInterruptQHs(Cont);
                        // Retire QHs
                        // - Remove them from the queue and ask the controller to bell when they're removable
                        EHCI_int_RetireQHs(Cont);

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