#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
{
// 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 )
// Disconnected
USB_DeviceDisconnected(info->HubPtr, Port);
}
+
+ USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, Port, 0, NULL);
}
}
-
*
* Universal Host Controller Interface
*/
-#define DEBUG 1
+#define DEBUG 0
#define VERSION VER2(0,5)
#include <acess.h>
#include <vfs.h>
// 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;
}
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;