17static void *hcdMemoryBuffer;
19void hcdProcessIntr(
void)
22 volatile HcCA *hcHCCA;
29 ohciRegs = memPool->m_ohciRegs;
30 memPool->m_interruptCounters[0] += 1;
31 hcHCCA = memPool->m_hcHCCA;
32 intrFlags = ohciRegs->HcInterruptStatus & ohciRegs->HcInterruptEnable;
33 if ( (intrFlags & OHCI_INT_SO) != 0 )
35 dbg_printf(
"HC: Scheduling overrun\n");
36 ohciRegs->HcInterruptStatus = OHCI_INT_SO;
37 intrFlags &= ~OHCI_INT_SO;
38 memPool->m_interruptCounters[1] += 1;
40 doneQueue = (
UsbdHcTD_t *)((uiptr)hcHCCA->DoneHead & ~0xF);
44 hcHCCA->DoneHead = NULL;
45 ohciRegs->HcInterruptStatus = OHCI_INT_WDH;
50 next_tmp1 = doneQueue;
51 doneQueue = doneQueue->m_next;
52 next_tmp1->m_next = prev;
55 for ( ; prev; prev = next_tmp2 )
57 next_tmp2 = prev->m_next;
58 if ( prev < memPool->m_hcTdBuf || prev >= memPool->m_hcTdBufEnd )
65 processDoneQueue_GenTd(prev);
68 intrFlags &= ~OHCI_INT_WDH;
69 memPool->m_interruptCounters[2] += 1;
71 if ( (intrFlags & OHCI_INT_SF) != 0 )
73 ohciRegs->HcInterruptStatus = OHCI_INT_SF;
75 intrFlags &= ~OHCI_INT_SF;
76 memPool->m_interruptCounters[3] += 1;
78 if ( (intrFlags & OHCI_INT_RD) != 0 )
80 ohciRegs->HcInterruptStatus = OHCI_INT_RD;
81 intrFlags &= ~OHCI_INT_RD;
82 memPool->m_interruptCounters[4] += 1;
84 if ( (intrFlags & OHCI_INT_UE) != 0 )
86 dbg_printf(
"HC: Unrecoverable error\n");
87 ohciRegs->HcInterruptStatus = OHCI_INT_UE;
88 intrFlags &= ~OHCI_INT_UE;
89 memPool->m_interruptCounters[5] += 1;
91 if ( (intrFlags & OHCI_INT_FNO) != 0 )
93 ohciRegs->HcInterruptStatus = OHCI_INT_FNO;
94 intrFlags &= ~OHCI_INT_FNO;
95 memPool->m_interruptCounters[6] += 1;
97 if ( (intrFlags & OHCI_INT_RHSC) != 0 )
100 ohciRegs->HcInterruptStatus = OHCI_INT_RHSC;
102 intrFlags &= ~OHCI_INT_RHSC;
103 memPool->m_interruptCounters[7] += 1;
105 if ( (intrFlags & OHCI_INT_OC) != 0 )
107 ohciRegs->HcInterruptStatus = OHCI_INT_OC;
108 intrFlags &= ~OHCI_INT_OC;
109 memPool->m_interruptCounters[8] += 1;
111 intrFlags &= ~OHCI_INT_MIE;
114 dbg_printf(
"Disable intr: %d\n", intrFlags);
115 ohciRegs->HcInterruptDisable = intrFlags;
119void PostIntrEnableFunction(
void)
121 volatile int lw_busy;
124 memPool->m_ohciRegs->HcInterruptDisable = OHCI_INT_MIE;
128 val = *((
volatile u32 *)0xBFC00000);
129 __asm__ __volatile__(
" " :
"=r"(val));
131 }
while ( lw_busy > 0 );
132 memPool->m_ohciRegs->HcInterruptEnable = OHCI_INT_MIE;
135static int initHardware(
volatile OhciRegs *ohciRegs)
139 dbg_printf(
"Host Controller...\n");
140 ohciRegs->HcInterruptDisable = ~0;
141 ohciRegs->HcControl &= ~0x3Cu;
143 ohciRegs->HcCommandStatus = OHCI_COM_HCR;
144 ohciRegs->HcControl = 0;
145 for ( i = 1; i < 1000; i += 1 )
147 volatile int lw_busy;
149 if ( (ohciRegs->HcCommandStatus & OHCI_COM_HCR) == 0 )
151 dbg_printf(
"HC reset done\n");
159 val = *((
volatile u32 *)0xBFC00000);
160 __asm__ __volatile__(
" " :
"=r"(val));
162 }
while ( lw_busy > 0 );
167int initHcdStructs(
void)
185 ohciRegs = (
volatile OhciRegs *)OHCI_REG_BASE;
186 if ( initHardware(ohciRegs) < 0 )
188 *(vu32 *)0xBF801570 |= 0x8000000u;
189 *(vu32 *)0xBF801680 = 1;
190 dbg_printf(
"Structs...\n");
191 memSize = 0 + 28 +
sizeof(
HcCA) +
sizeof(
UsbdHcIsoTD_t) * usbConfig.m_maxIsoTransfDesc
192 +
sizeof(
UsbdHcTD_t) * usbConfig.m_maxTransfDesc +
sizeof(
UsbdHcED_t) * usbConfig.m_maxEndpoints
197 + usbConfig.m_maxStaticDescSize * usbConfig.m_maxDevices;
198 memBuf_1 = AllocSysMemoryWrap(memSize);
201 if ( ((uiptr)memBuf_1) & 0xFF )
203 FreeSysMemoryWrap(memBuf_1);
206 hcdMemoryBuffer = memBuf_1;
207 hcCommArea = (
HcCA *)memBuf_1;
208 bzero(memBuf_1, memSize);
209 hcIsoTdBuf = (
UsbdHcIsoTD_t *)(((uiptr)memBuf_1 + (28 +
sizeof(
HcCA) - 1)) & 0xFFFFFFE0);
213 hcTdBuf = (
UsbdHcTD_t *)&hcIsoTdBuf[usbConfig.m_maxIsoTransfDesc];
214 hcEdBufForEndpoint = (
UsbdHcED_t *)&hcTdBuf[usbConfig.m_maxTransfDesc];
215 hcEdBuf = (
UsbdHcED_t *)&hcEdBufForEndpoint[usbConfig.m_maxEndpoints];
218 memPool_unused = memPool;
221 deviceTreeBuf = (
UsbdDevice_t *)&endpointBuf[usbConfig.m_maxEndpoints];
223 hcIsoTdToIoReqLUT = (
UsbdIoRequest_t **)&ioReqBuf[usbConfig.m_maxIoReqs];
224 hcTdToIoReqLUT = &hcIsoTdToIoReqLUT[usbConfig.m_maxIsoTransfDesc];
225 devDescBuf = &hcTdToIoReqLUT[usbConfig.m_maxTransfDesc];
226 usbConfig.m_allocatedSize_unused += memSize;
227 memPool->m_ohciRegs = ohciRegs;
228 memPool->m_hcEdBuf = hcEdBuf;
229 memPool->m_hcIsoTdToIoReqLUT = hcIsoTdToIoReqLUT;
230 memPool->m_hcTdToIoReqLUT = hcTdToIoReqLUT;
231 memPool->m_endpointBuf = endpointBuf;
232 memPool->m_hcHCCA = (
volatile HcCA *)(((uiptr)memBuf_1 & 0x1FFFFFFF) | 0xA0000000);
233 for ( i = 0; i < usbConfig.m_maxEndpoints; i += 1 )
235 endpointBuf[i].m_id = i;
236 endpointBuf[i].m_hcEd = &hcEdBufForEndpoint[i];
237 endpointBuf[i].m_prev = memPool->m_freeEpListEnd;
238 if ( memPool->m_freeEpListEnd )
239 memPool->m_freeEpListEnd->m_next = &endpointBuf[i];
241 memPool->m_freeEpListStart = &endpointBuf[i];
242 endpointBuf[i].m_next = NULL;
243 memPool->m_freeEpListEnd = &endpointBuf[i];
245 memPool->m_tdQueueEnd = NULL;
246 memPool->m_tdQueueStart = NULL;
247 memPool->m_deviceTreeBuf = deviceTreeBuf;
248 for ( i = 0; i < usbConfig.m_maxDevices; i += 1 )
250 deviceTreeBuf[i].m_functionAddress = i;
251 deviceTreeBuf[i].m_id = (u8)i;
252 deviceTreeBuf[i].m_staticDeviceDescPtr = (u8 *)devDescBuf + (usbConfig.m_maxStaticDescSize * i);
253 deviceTreeBuf[i].m_prev = memPool->m_freeDeviceListEnd;
254 if ( memPool->m_freeDeviceListEnd )
255 memPool->m_freeDeviceListEnd->m_next = &deviceTreeBuf[i];
257 memPool->m_freeDeviceListStart = &deviceTreeBuf[i];
258 deviceTreeBuf[i].m_next = NULL;
259 memPool->m_freeDeviceListEnd = &deviceTreeBuf[i];
261 memPool->m_deviceTreeRoot = attachChildDevice(NULL, 0);
262 memPool->m_deviceTreeRoot->m_magicPowerValue = 2;
263 attachChildDevice(memPool->m_deviceTreeRoot, 1u);
264 attachChildDevice(memPool->m_deviceTreeRoot, 2u);
265 memPool->m_ioReqBufPtr = ioReqBuf;
266 for ( i = 0; i < usbConfig.m_maxIoReqs; i += 1 )
268 ioReqBuf[i].m_id = i;
269 ioReqBuf[i].m_prev = memPool->m_freeIoReqListEnd;
270 if ( memPool->m_freeIoReqListEnd )
271 memPool->m_freeIoReqListEnd->m_next = &ioReqBuf[i];
273 memPool->m_freeIoReqList = &ioReqBuf[i];
274 ioReqBuf[i].m_next = NULL;
275 memPool->m_freeIoReqListEnd = &ioReqBuf[i];
277 memPool->m_freeHcTdList = hcTdBuf;
278 memPool->m_hcTdBuf = hcTdBuf;
279 memPool->m_hcTdBufEnd = &hcTdBuf[usbConfig.m_maxTransfDesc];
280 for ( i = 0; i < usbConfig.m_maxTransfDesc - 1; i += 1 )
282 hcTdBuf[i].m_next = &hcTdBuf[i + 1];
284 memPool->m_freeHcIsoTdList = hcIsoTdBuf;
285 memPool->m_hcIsoTdBuf = hcIsoTdBuf;
286 memPool->m_hcIsoTdBufEnd = &hcIsoTdBuf[usbConfig.m_maxIsoTransfDesc];
287 for ( i = 0; i < usbConfig.m_maxIsoTransfDesc - 1; i += 1 )
289 hcIsoTdBuf[i].m_next = &hcIsoTdBuf[i + 1];
292 for ( i = 0; i < 63; i += 1 )
295 hcEdBuf[i].m_hcArea.asu32 = HCED_SKIP;
296 hcEdBuf[i].m_next = (i > 0) ? &hcEdBuf[(i - 1) >> 1] : NULL;
300 intrId = ((intrId & 1) << 4) + ((intrId & 2) << 2) + (intrId & 4) + ((intrId & 8) >> 2) + ((intrId & 0x10) >> 4);
301 hcCommArea->InterruptTable[intrId] = &hcEdBuf[i];
304 hcEdBuf[TYPE_CONTROL].m_hcArea.asu32 = HCED_SKIP;
305 ohciRegs->HcControlHeadEd = &hcEdBuf[TYPE_CONTROL];
306 hcEdBuf[TYPE_BULK].m_hcArea.asu32 = HCED_SKIP;
307 ohciRegs->HcBulkHeadEd = &hcEdBuf[TYPE_BULK];
308 hcEdBuf[TYPE_ISOCHRON].m_hcArea.asu32 = HCED_SKIP;
309 hcEdBuf[0].m_next = &hcEdBuf[TYPE_ISOCHRON];
310 ohciRegs->HcHCCA = hcCommArea;
311 ohciRegs->HcFmInterval = 0x27782EDF;
312 ohciRegs->HcPeriodicStart = 0x2A2F;
313 ohciRegs->HcInterruptEnable = OHCI_INT_SO | OHCI_INT_WDH | OHCI_INT_UE | OHCI_INT_FNO | OHCI_INT_RHSC | OHCI_INT_MIE;
314 ohciRegs->HcControl |=
315 OHCI_CTR_CBSR | OHCI_CTR_PLE | OHCI_CTR_IE | OHCI_CTR_CLE | OHCI_CTR_BLE | OHCI_CTR_USB_OPERATIONAL;
325 initHardware((
OhciRegs *)OHCI_REG_BASE);
326 for ( i = memPool->m_freeDeviceListStart; i; i = i->m_next )
328 for ( hidDescriptorStart = i->m_reportDescriptorStart, next = hidDescriptorStart; next; hidDescriptorStart = next )
330 next = hidDescriptorStart->m_next;
331 FreeSysMemoryWrap(hidDescriptorStart);
334 FreeSysMemoryWrap(hcdMemoryBuffer);