From 8aad7ffe6c2e7e5dbb06a5baf59ca43ce1c12317 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 30 Nov 2011 17:38:58 +0800 Subject: [PATCH] Modules/USB - Bugfixes - Fixed infinite loop in polling - Added proper cleanup (... I think) to UHCI --- Modules/USB/Core/hub.c | 18 ++++++++++- Modules/USB/Core/usb_io.c | 2 +- Modules/USB/Core/usb_poll.c | 1 + Modules/USB/UHCI/uhci.c | 64 ++++++++++++++++++++----------------- Modules/USB/UHCI/uhci.h | 5 +++ 5 files changed, 59 insertions(+), 31 deletions(-) diff --git a/Modules/USB/Core/hub.c b/Modules/USB/Core/hub.c index b737f078..04a9cc52 100644 --- a/Modules/USB/Core/hub.c +++ b/Modules/USB/Core/hub.c @@ -10,13 +10,26 @@ #define MAX_PORTS 32 // Not actually a max, but used for DeviceRemovable + #define GET_STATUS 0 +#define CLEAR_FEATURE 1 +// resvd #define SET_FEATURE 3 #define PORT_CONNECTION 0 #define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 #define PORT_RESET 4 #define PORT_POWER 8 +#define PORT_LOW_SPEED 9 +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 +#define PORT_TEST 21 +#define PORT_INDICATOR 21 struct sHubDescriptor { @@ -124,6 +137,8 @@ void Hub_int_HandleChange(tUSBInterface *Dev, int Port) // Get port status USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status); + + LOG("Port %i: status = {0b%b, 0b%b}", Port, status[0], status[1]); // Handle connections / disconnections if( status[1] & 0x0001 ) @@ -145,6 +160,7 @@ void Hub_int_HandleChange(tUSBInterface *Dev, int Port) // Disconnected USB_DeviceDisconnected(info->HubPtr, Port); } + + USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, Port, 0, NULL); } } - diff --git a/Modules/USB/Core/usb_io.c b/Modules/USB/Core/usb_io.c index 50320c65..cd8fbcd3 100644 --- a/Modules/USB/Core/usb_io.c +++ b/Modules/USB/Core/usb_io.c @@ -5,7 +5,7 @@ * usb_io.c * - High-level IO */ -#define DEBUG 1 +#define DEBUG 0 #include #include "usb.h" diff --git a/Modules/USB/Core/usb_poll.c b/Modules/USB/Core/usb_poll.c index 8fd1b0ce..11afc130 100644 --- a/Modules/USB/Core/usb_poll.c +++ b/Modules/USB/Core/usb_poll.c @@ -107,6 +107,7 @@ int USB_PollThread(void *unused) ep->Next = *newqueue; *newqueue = ep; + ep = prev; } } giUSB_PollPosition ++; diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c index 3c2abd9e..a794d3c8 100644 --- a/Modules/USB/UHCI/uhci.c +++ b/Modules/USB/UHCI/uhci.c @@ -4,7 +4,7 @@ * * Universal Host Controller Interface */ -#define DEBUG 1 +#define DEBUG 0 #define VERSION VER2(0,5) #include #include @@ -148,13 +148,12 @@ void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) // 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 ) { // 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; } @@ -346,41 +345,48 @@ void UHCI_CheckPortUpdate(void *Ptr) void UHCI_InterruptHandler(int IRQ, void *Ptr) { tUHCI_Controller *Host = Ptr; - int frame = ((int)inw(Host->IOBase + FRNUM) & 0x3FF) - 1; + int frame = ((int)inw(Host->IOBase + FRNUM) - 1) & 0x3FF; Uint16 status = inw(Host->IOBase + USBSTS); - if(frame < 0) frame += 1024; - Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x, frame = %i", status, frame); +// Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x, frame = %i", status, frame); // Interrupt-on-completion if( status & 1 ) { tPAddr link; - - 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; - 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) + link = Host->FrameList[frame]; + Host->FrameList[frame] = 1; + while( !(link & 1) ) { - LOG("Calling cb %p", td->_info.Callback); - td->_info.Callback(td->_info.CallbackPtr, td->_info.DataPtr, byte_count); - td->_info.Callback = NULL; + 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; } - link = td->Link; - if( td->_info.Callback != INVLPTR ) - td->Link = 1; + + if(frame == 0) + frame = 0x3ff; + else + frame --; } // Host->LastCleanedFrame = frame; diff --git a/Modules/USB/UHCI/uhci.h b/Modules/USB/UHCI/uhci.h index e67dac3b..ec74174d 100644 --- a/Modules/USB/UHCI/uhci.h +++ b/Modules/USB/UHCI/uhci.h @@ -28,6 +28,11 @@ struct sUHCI_Controller * \brief IRQ Number assigned to the device */ int IRQNum; + + /** + * \brief Number of the last frame to be cleaned + */ + int LastCleanedFrame; /** * \brief Frame list -- 2.20.1