X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FUSB%2FUHCI%2Fuhci.c;h=3c2abd9e3d80fdfdd5352afe8a1d40928710be56;hb=0e361ff8d9472885f770a370c0d477c229041572;hp=9fd82303588e2afcabde6dc29968465db25822ab;hpb=3ab2857efdcb81ce34dabf4d07b39ad6f5ab0b4a;p=tpg%2Facess2.git diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c index 9fd82303..3c2abd9e 100644 --- a/Modules/USB/UHCI/uhci.c +++ b/Modules/USB/UHCI/uhci.c @@ -4,7 +4,7 @@ * * Universal Host Controller Interface */ -#define DEBUG 0 +#define DEBUG 1 #define VERSION VER2(0,5) #include #include @@ -22,13 +22,13 @@ void UHCI_Cleanup(); tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont); void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD); -void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, tUSBHostCb Cb, void *Data, size_t Length); -void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length); -void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length); -void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length); +void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length); +void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length); +void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length); +void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length); int UHCI_IsTransferComplete(void *Ptr, void *Handle); int UHCI_Int_InitHost(tUHCI_Controller *Host); -void UHCI_CheckPortUpdate(tUHCI_Controller *Host); +void UHCI_CheckPortUpdate(void *Ptr); void UHCI_InterruptHandler(int IRQ, void *Ptr); // === GLOBALS === @@ -39,7 +39,7 @@ tUSBHostDef gUHCI_HostDef = { .SendIN = UHCI_DataIN, .SendOUT = UHCI_DataOUT, .SendSETUP = UHCI_SendSetup, - .CheckPorts = (void*)UHCI_CheckPortUpdate, + .CheckPorts = UHCI_CheckPortUpdate, .IsOpComplete = UHCI_IsTransferComplete }; @@ -132,15 +132,24 @@ tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont) return NULL; } +tUHCI_TD *UHCI_int_GetTDFromPhys(tPAddr PAddr) +{ + // TODO: Fix this to work with a non-contiguous pool + static tPAddr td_pool_base; + if(!td_pool_base) td_pool_base = MM_GetPhysAddr( (tVAddr)gaUHCI_TDPool ); + return gaUHCI_TDPool + (PAddr - td_pool_base) / sizeof(gaUHCI_TDPool[0]); +} + void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) { int next_frame = (inw(Cont->IOBase + FRNUM) + 2) & (1024-1); - tPAddr td_pool_base = MM_GetPhysAddr( (tVAddr)gaUHCI_TDPool ); tUHCI_TD *prev_td; Uint32 link; // TODO: How to handle FRNUM incrementing while we are in this function? +// LOG("USBINTR = 0x%x", inw(Cont->IOBase + USBINTR)); + // Empty list if( Cont->FrameList[next_frame] & 1 ) { @@ -153,8 +162,7 @@ void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) // Find the end of the list link = Cont->FrameList[next_frame]; do { - // TODO: Fix this to work with a non-contiguous pool - prev_td = gaUHCI_TDPool + (link - td_pool_base) / sizeof(gaUHCI_TDPool[0]); + prev_td = UHCI_int_GetTDFromPhys(link); link = prev_td->Link; } while( !(link & 1) ); @@ -170,7 +178,9 @@ void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) * \param Addr Function Address * 16 + Endpoint * \param bTgl Data toggle value */ -void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, tUSBHostCb Cb, void *Data, size_t Length) +void *UHCI_int_SendTransaction( + tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, + tUSBHostCb Cb, void *CbData, void *Data, size_t Length) { tUHCI_TD *td; @@ -179,7 +189,7 @@ void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int td = UHCI_int_AllocateTD(Cont); if( !td ) { - // + // TODO: Wait for one to free? Log_Error("UHCI", "No avaliable TDs, transaction dropped"); return NULL; } @@ -200,48 +210,54 @@ void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int ); // TODO: Need to enable IOC to copy the data back // td->BufferPointer = + td->_info.bCopyData = 1; return NULL; } else { td->BufferPointer = MM_GetPhysAddr( (tVAddr)Data ); + td->_info.bCopyData = 0; } // 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 - if( Cb != INVLPTR ) - { - Log_Warning("UHCI", "TODO: Support IOC... somehow"); - } + td->_info.CallbackPtr = CbData; } - td->_info.DestPtr = Data; + td->_info.DataPtr = Data; UHCI_int_AppendTD(Cont, td); return td; } -void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length) +void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length) { - return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x69, DataTgl, Cb, Data, Length); + return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x69, DataTgl, Cb, CbData, Buf, Length); } -void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length) +void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length) { - return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0xE1, DataTgl, Cb, Data, Length); + return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0xE1, DataTgl, Cb, CbData, Buf, Length); } -void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length) +void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length) { - return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x2D, DataTgl, Cb, Data, Length); + return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x2D, DataTgl, Cb, CbData, Buf, Length); } int UHCI_IsTransferComplete(void *Ptr, void *Handle) { tUHCI_TD *td = Handle; - return !(td->Control & (1 << 23)); + int ret; + ret = !(td->Control & (1 << 23)); + if(ret) { + td->_info.Callback = NULL; + td->Link = 1; + } + return ret; } // === INTERNAL FUNCTIONS === @@ -291,8 +307,9 @@ int UHCI_Int_InitHost(tUHCI_Controller *Host) return 0; } -void UHCI_CheckPortUpdate(tUHCI_Controller *Host) +void UHCI_CheckPortUpdate(void *Ptr) { + tUHCI_Controller *Host = Ptr; // Enable ports for( int i = 0; i < 2; i ++ ) { @@ -329,13 +346,46 @@ void UHCI_CheckPortUpdate(tUHCI_Controller *Host) void UHCI_InterruptHandler(int IRQ, void *Ptr) { tUHCI_Controller *Host = Ptr; + int frame = ((int)inw(Host->IOBase + FRNUM) & 0x3FF) - 1; Uint16 status = inw(Host->IOBase + USBSTS); - Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x", status); + if(frame < 0) frame += 1024; + Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x, frame = %i", status, frame); + // Interrupt-on-completion if( status & 1 ) { - // Interrupt-on-completion + tPAddr link; + + link = Host->FrameList[frame]; + Host->FrameList[frame] = 1; + while( !(link & 1) ) + { + 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; + } + +// Host->LastCleanedFrame = frame; } + LOG("status = 0x%02x", status); outw(Host->IOBase + USBSTS, status); }