#ifndef _EHCI_H_
#define _EHCI_H_
+#include <threads.h>
+
#define PERIODIC_SIZE 1024
typedef struct sEHCI_CapRegs tEHCI_CapRegs;
* 15 = Asynchronous Schedule Status
* 16:31 = Reserved ?(Zero)
*/
- Uint32 USBSts;
+ volatile Uint32 USBSts;
/**
* USB Interrupt Enable Register
*
*
* Bits 14:3 are used as n index into PeridocListBase
*/
- Uint32 FrIndex;
+ volatile Uint32 FrIndex;
/**
* Control Data Structure Segment Register
*
* 22 = Wake on Over-current Enable
* 23:31 = Reserved (ZERO)
*/
- Uint32 PortSC[15];
+ volatile Uint32 PortSC[15];
};
#define USBCMD_Run 0x0001
#define USBINTR_HostSystemError 0x0010
#define USBINTR_AsyncAdvance 0x0020
+#define PORTSC_CurrentConnectStatus 0x0001
+#define PORTSC_ConnectStatusChange 0x0002
+#define PORTSC_PortEnabled 0x0004
+#define PORTSC_PortEnableChange 0x0008
+#define PORTSC_OvercurrentActive 0x0010
+#define PORTSC_OvercurrentChange 0x0020
+#define PORTSC_ForcePortResume 0x0040
+#define PORTSC_Suspend 0x0080
+#define PORTSC_PortReset 0x0100
+#define PORTSC_Reserved1 0x0200
+#define PORTSC_LineStatus_MASK 0x0C00
+#define PORTSC_LineStatus_SE0 0x0000
+#define PORTSC_LineStatus_Jstate 0x0400
+#define PORTSC_LineStatus_Kstate 0x0800
+#define PORTSC_LineStatus_Undef 0x0C00
+#define PORTSC_PortPower 0x1000
+#define PORTSC_PortOwner 0x2000
+#define PORTSC_PortIndicator_MASK 0xC000
+#define PORTSC_PortIndicator_Off 0x0000
+#define PORTSC_PortIndicator_Amber 0x4000
+#define PORTSC_PortIndicator_Green 0x800
+
// Isochronous (High-Speed) Transfer Descriptor
struct sEHCI_iTD
{
Uint32 Endpoint;
Uint32 EndpointExt;
Uint32 CurrentTD;
- tEHCI_qTD Overlay;
+ struct {
+ Uint32 Link;
+ Uint32 Link2;
+ Uint32 Token;
+ Uint32 Pages[5];
+ } Overlay;
struct {
Uint8 IntOfs;
Uint8 IntPeriodPow;
tEHCI_QH *Next;
} Impl;
} __attribute__((aligned(32)));
-// sizeof = 48 (64)
+// sizeof = 48 (round up to 64)
#define PID_OUT 0
#define PID_IN 1
#define PID_SETUP 2
+#define TD_POOL_SIZE (PAGE_SIZE/sizeof(tEHCI_qTD))
+// - 256 addresses * 16 endpoints
+#define QH_POOL_SIZE (256*16)
+#define QH_POOL_PAGES (QH_POOL_SIZE*sizeof(tEHCI_QH)/PAGE_SIZE)
+#define QH_POOL_NPERPAGE (PAGE_SIZE/sizeof(tEHCI_QH))
+
struct sEHCI_Controller
{
+ tUSBHub *RootHub;
+ tThread *InterruptThread;
+ int nPorts;
+
tPAddr PhysBase;
tEHCI_CapRegs *CapRegs;
tEHCI_OpRegs *OpRegs;
+ tEHCI_qTD *DeadTD;
+
int InterruptLoad[PERIODIC_SIZE];
tEHCI_QH *LastAsyncHead;
- Uint32 *PeriodicQueue;
- tEHCI_QH PeriodicQueueV[PERIODIC_SIZE];
+ tMutex PeriodicListLock;
+ Uint32 *PeriodicQueue;
+ tEHCI_QH *PeriodicQueueV[PERIODIC_SIZE];
- tEHCI_QH *QHPools[(256*16)*sizeof(tEHCI_QH)/PAGE_SIZE]; // [PAGE_SIZE/64]
- tEHCI_qTD *TDPool[PAGE_SIZE/sizeof(tEHCI_qTD)];
+ tMutex QHPoolMutex;
+ tEHCI_QH *QHPools[QH_POOL_PAGES]; // [PAGE_SIZE/64]
+ tMutex TDPoolMutex;
+ tEHCI_qTD *TDPool; // [TD_POOL_SIZE]
};
#endif