USB - Changed HC API to reflect more advanced features
[tpg/acess2.git] / KernelLand / Modules / USB / EHCI / ehci.c
1 /*
2  * Acess2 EHCI Driver
3  * - By John Hodge (thePowersGang)
4  * 
5  * ehci.c
6  * - Driver Core
7  */
8 #define DEBUG   1
9 #define VERSION VER2(0,1)
10 #include <acess.h>
11 #include <modules.h>
12 #include <usb_host.h>
13 #include "ehci.h"
14 #include <drv_pci.h>
15
16 // === CONSTANTS ===
17 #define EHCI_MAX_CONTROLLERS    4
18
19 // === PROTOTYPES ===
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);
24 // -- API ---
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,
31         int isOutbound,
32         const void *SetupData, size_t SetupLength,
33         const void *OutData, size_t OutLength,
34         void *InData, size_t InLength
35         );
36 void    *EHCI_SendBulk(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, int Dir, void *Data, size_t Length);
37
38 // === GLOBALS ===
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,
46         .SendIsoch   = NULL,
47         .SendControl = EHCI_SendControl,
48         .SendBulk    = EHCI_SendBulk,
49         .FreeOp      = NULL
50         };
51
52 // === CODE ===
53 int EHCI_Initialise(char **Arguments)
54 {
55         for( int id = -1; (id = PCI_GetDeviceByClass(0x0C0320, 0xFFFFFF, id)) >= 0;  )
56         {
57                 Uint32  addr = PCI_GetBAR(id, 0);
58                 if( addr == 0 ) {
59                         // Oops, PCI BIOS emulation time
60                 }
61                 Uint8   irq = PCI_GetIRQ(id);
62                 if( irq == 0 ) {
63                         // TODO: The same
64                 }
65
66                 if( EHCI_InitController(addr, irq) ) {
67                         // TODO: Detect other forms of failure than "out of slots"
68                         break ;
69                 }
70         }
71         return 0;
72 }
73
74 int EHCI_Cleanup(void)
75 {
76         return 0;
77 }
78
79 // --- Driver Init ---
80 int EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum)
81 {
82         tEHCI_Controller        *cont = NULL;
83
84         for( int i = 0; i < EHCI_MAX_CONTROLLERS; i ++ )
85         {
86                 if( gaEHCI_Controllers[i].PhysBase == 0 ) {
87                         cont = &gaEHCI_Controllers[i];
88                         cont->PhysBase = BaseAddress;
89                         break;
90                 }
91         }
92
93         if(!cont) {
94                 return 1;
95         }
96
97         // -- Build up structure --
98         cont->CapRegs = (void*)MM_MapHWPages(BaseAddress, 1);
99         // TODO: Error check
100         cont->OpRegs = (void*)( (Uint32*)cont->CapRegs + cont->CapRegs->CapLength / 4 );
101         // - Allocate periodic queue
102         cont->PeriodicQueue = (void*)MM_AllocDMA(1, 32, NULL);
103         // TODO: Error check
104
105         // -- Bind IRQ --
106         IRQ_AddHandler(InterruptNum, EHCI_InterruptHandler, cont);
107
108         // -- Initialisation procedure (from ehci-r10) --
109         // - Reset controller
110         cont->OpRegs->USBCmd = USBCMD_HCReset;
111         // - Set CTRLDSSEGMENT (TODO: 64-bit support)
112         // - Set USBINTR
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;
118         // - Route all ports
119         cont->OpRegs->ConfigFlag = 1;
120         
121         return 0;
122 }
123
124 void EHCI_InterruptHandler(int IRQ, void *Ptr)
125 {
126         tEHCI_Controller *cont = Ptr;
127         Uint32  sts = cont->OpRegs->USBSts;
128         
129         // Clear interrupts
130         cont->OpRegs->USBSts = sts;     
131
132         if( sts & USBINTR_IOC ) {
133                 // IOC
134                 sts &= ~USBINTR_IOC;
135         }
136
137         if( sts & USBINTR_PortChange ) {
138                 // Port change, determine what port and poke helper thread
139                 sts &= ~USBINTR_PortChange;
140         }
141         
142         if( sts & USBINTR_FrameRollover ) {
143                 // Frame rollover, used to aid timing (trigger per-second operations)
144                 sts &= ~USBINTR_FrameRollover;
145         }
146
147         if( sts ) {
148                 // Unhandled interupt bits
149                 // TODO: Warn
150         }
151 }
152
153 // --------------------------------------------------------------------
154 // USB API
155 // --------------------------------------------------------------------
156 void *EHCI_InitInterrupt(void *Ptr, int Endpoint, int bInput, int Period,
157         tUSBHostCb Cb, void *CbData, void *Buf, size_t Length)
158 {
159         
160 }
161
162 void *EHCI_InitIsoch(void *Ptr, int Endpoint)
163 {
164         return NULL;
165 }
166 void *EHCI_InitControl(void *Ptr, int Endpoint)
167 {
168         return NULL;
169 }
170 void *EHCI_InitBulk(void *Ptr, int Endpoint)
171 {
172         return NULL;
173 }
174 void    EHCI_RemEndpoint(void *Ptr, void *Handle);
175 void    *EHCI_SendControl(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData,
176         int isOutbound,
177         const void *SetupData, size_t SetupLength,
178         const void *OutData, size_t OutLength,
179         void *InData, size_t InLength
180         );
181 void    *EHCI_SendBulk(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, int Dir, void *Data, size_t Length);
182
183

UCC git Repository :: git.ucc.asn.au