X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FUSB%2FUHCI%2Fuhci.c;h=a794d3c879d6457cd05594b452615a21404b3d57;hb=8aad7ffe6c2e7e5dbb06a5baf59ca43ce1c12317;hp=8df6c287e9e84ab416ed8600a5a9b01491632f9a;hpb=89e41793b9d495d98633f90e6595722b8e5979d3;p=tpg%2Facess2.git diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c index 8df6c287..a794d3c8 100644 --- a/Modules/USB/UHCI/uhci.c +++ b/Modules/USB/UHCI/uhci.c @@ -153,6 +153,7 @@ void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) { // TODO: Ensure 32-bit paddr Cont->FrameList[next_frame] = MM_GetPhysAddr( (tVAddr)TD ); + TD->Control |= (1 << 24); // Ensure that there is an interrupt for each used frame LOG("next_frame = %i", next_frame); return; } @@ -219,6 +220,7 @@ void *UHCI_int_SendTransaction( // Interrupt on completion if( Cb ) { td->Control |= (1 << 24); + LOG("IOC Cb=%p CbData=%p", Cb, CbData); td->_info.Callback = Cb; // NOTE: if ERRPTR then the TD is kept allocated until checked td->_info.CallbackPtr = CbData; } @@ -343,43 +345,53 @@ void UHCI_CheckPortUpdate(void *Ptr) void UHCI_InterruptHandler(int IRQ, void *Ptr) { tUHCI_Controller *Host = Ptr; + int frame = ((int)inw(Host->IOBase + FRNUM) - 1) & 0x3FF; Uint16 status = inw(Host->IOBase + USBSTS); - Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x", status); +// Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x, frame = %i", status, frame); // Interrupt-on-completion if( status & 1 ) { tPAddr link; - int frame = inw(Host->IOBase + FRNUM) - 1; - if(frame < 0) frame += 1024; - link = Host->FrameList[frame]; - Host->FrameList[frame] = 1; - while( !(link & 1) ) + for( int i = 0; i < 10; i ++ ) { - tUHCI_TD *td = UHCI_int_GetTDFromPhys(link); - int byte_count = (td->Control&0x7FF)+1; - // Handle non-page aligned destination - // TODO: This will break if the destination is not in global memory - if(td->_info.bCopyData) + link = Host->FrameList[frame]; + Host->FrameList[frame] = 1; + while( !(link & 1) ) { - void *ptr = (void*)MM_MapTemp(td->BufferPointer); - memcpy(td->_info.DataPtr, ptr, byte_count); - MM_FreeTemp((tVAddr)ptr); + tUHCI_TD *td = UHCI_int_GetTDFromPhys(link); + int byte_count = (td->Control&0x7FF)+1; + LOG("link = 0x%x, td = %p, byte_count = %i", link, td, byte_count); + // Handle non-page aligned destination + // TODO: This will break if the destination is not in global memory + if(td->_info.bCopyData) + { + void *ptr = (void*)MM_MapTemp(td->BufferPointer); + memcpy(td->_info.DataPtr, ptr, byte_count); + MM_FreeTemp((tVAddr)ptr); + } + // Callback + if(td->_info.Callback && td->_info.Callback != INVLPTR) + { + LOG("Calling cb %p", td->_info.Callback); + td->_info.Callback(td->_info.CallbackPtr, td->_info.DataPtr, byte_count); + td->_info.Callback = NULL; + } + link = td->Link; + if( td->_info.Callback != INVLPTR ) + td->Link = 1; } - // Callback - if(td->_info.Callback && td->_info.Callback != INVLPTR) - { - td->_info.Callback(td->_info.CallbackPtr, td->_info.DataPtr, byte_count); - td->_info.Callback = NULL; - } - link = td->Link; - if( td->_info.Callback != INVLPTR ) - td->Link = 1; + + if(frame == 0) + frame = 0x3ff; + else + frame --; } // Host->LastCleanedFrame = frame; } + LOG("status = 0x%02x", status); outw(Host->IOBase + USBSTS, status); }