3 * - By John Hodge (thePowersGang)
9 #define VERSION VER2(0,1)
17 #define EHCI_MAX_CONTROLLERS 4
20 int EHCI_Initialise(char **Arguments);
21 int EHCI_Cleanup(void);
22 int EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum);
23 void EHCI_InterruptHandler(int IRQ, void *Ptr);
25 void *EHCI_InitInterrupt(void *Ptr, int Endpoint, int bInput, int Period, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length);
26 void *EHCI_InitIsoch (void *Ptr, int Endpoint);
27 void *EHCI_InitControl(void *Ptr, int Endpoint);
28 void *EHCI_InitBulk (void *Ptr, int Endpoint);
29 void EHCI_RemEndpoint(void *Ptr, void *Handle);
30 void *EHCI_SendControl(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData,
32 const void *SetupData, size_t SetupLength,
33 const void *OutData, size_t OutLength,
34 void *InData, size_t InLength
36 void *EHCI_SendBulk(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, int Dir, void *Data, size_t Length);
39 MODULE_DEFINE(0, VERSION, USB_EHCI, EHCI_Initialise, NULL, "USB_Core", NULL);
40 tEHCI_Controller gaEHCI_Controllers[EHCI_MAX_CONTROLLERS];
41 tUSBHostDef gEHCI_HostDef = {
42 .InitInterrupt = EHCI_InitInterrupt,
43 .InitIsoch = EHCI_InitIsoch,
44 .InitBulk = EHCI_InitBulk,
45 .RemEndpoint = EHCI_RemEndpoint,
47 .SendControl = EHCI_SendControl,
48 .SendBulk = EHCI_SendBulk,
53 int EHCI_Initialise(char **Arguments)
55 for( int id = -1; (id = PCI_GetDeviceByClass(0x0C0320, 0xFFFFFF, id)) >= 0; )
57 Uint32 addr = PCI_GetBAR(id, 0);
59 // Oops, PCI BIOS emulation time
61 Uint8 irq = PCI_GetIRQ(id);
66 if( EHCI_InitController(addr, irq) ) {
67 // TODO: Detect other forms of failure than "out of slots"
74 int EHCI_Cleanup(void)
79 // --- Driver Init ---
80 int EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum)
82 tEHCI_Controller *cont = NULL;
84 for( int i = 0; i < EHCI_MAX_CONTROLLERS; i ++ )
86 if( gaEHCI_Controllers[i].PhysBase == 0 ) {
87 cont = &gaEHCI_Controllers[i];
88 cont->PhysBase = BaseAddress;
97 // -- Build up structure --
98 cont->CapRegs = (void*)MM_MapHWPages(BaseAddress, 1);
100 cont->OpRegs = (void*)( (Uint32*)cont->CapRegs + cont->CapRegs->CapLength / 4 );
101 // - Allocate periodic queue
102 cont->PeriodicQueue = (void*)MM_AllocDMA(1, 32, NULL);
106 IRQ_AddHandler(InterruptNum, EHCI_InterruptHandler, cont);
108 // -- Initialisation procedure (from ehci-r10) --
109 // - Reset controller
110 cont->OpRegs->USBCmd = USBCMD_HCReset;
111 // - Set CTRLDSSEGMENT (TODO: 64-bit support)
113 cont->OpRegs->USBIntr = USBINTR_IOC|USBINTR_PortChange|USBINTR_FrameRollover;
114 // - Set PERIODICLIST BASE
115 cont->OpRegs->PeridocListBase = MM_GetPhysAddr( cont->PeriodicQueue );
116 // - Enable controller
117 cont->OpRegs->USBCmd = (0x40 << 16) | USBCMD_PeriodicEnable | USBCMD_Run;
119 cont->OpRegs->ConfigFlag = 1;
124 void EHCI_InterruptHandler(int IRQ, void *Ptr)
126 tEHCI_Controller *cont = Ptr;
127 Uint32 sts = cont->OpRegs->USBSts;
130 cont->OpRegs->USBSts = sts;
132 if( sts & USBINTR_IOC ) {
137 if( sts & USBINTR_PortChange ) {
138 // Port change, determine what port and poke helper thread
139 sts &= ~USBINTR_PortChange;
142 if( sts & USBINTR_FrameRollover ) {
143 // Frame rollover, used to aid timing (trigger per-second operations)
144 sts &= ~USBINTR_FrameRollover;
148 // Unhandled interupt bits
153 // --------------------------------------------------------------------
155 // --------------------------------------------------------------------
156 void *EHCI_InitInterrupt(void *Ptr, int Endpoint, int bInput, int Period,
157 tUSBHostCb Cb, void *CbData, void *Buf, size_t Length)
162 void *EHCI_InitIsoch(void *Ptr, int Endpoint)
166 void *EHCI_InitControl(void *Ptr, int Endpoint)
170 void *EHCI_InitBulk(void *Ptr, int Endpoint)
174 void EHCI_RemEndpoint(void *Ptr, void *Handle);
175 void *EHCI_SendControl(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData,
177 const void *SetupData, size_t SetupLength,
178 const void *OutData, size_t OutLength,
179 void *InData, size_t InLength
181 void *EHCI_SendBulk(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, int Dir, void *Data, size_t Length);