Another fix proposed by steger. Decreased debug level so interrupts don't cause infin...
[cake.git] / rom / usb / pciusb / pci_aros.c
blob52bf506dfc848bee87778669fe59161b86cd7159
1 /* pci_aros.c - pci access abstraction for AROS by Chris Hodges
2 */
4 #include "uhwcmd.h"
6 #include <inttypes.h>
8 #include <aros/symbolsets.h>
10 #include <exec/types.h>
11 #include <oop/oop.h>
13 #include <devices/timer.h>
15 #include <hidd/hidd.h>
16 #include <hidd/pci.h>
17 #include <hidd/irq.h>
19 #include <usb/usb.h>
21 #include <proto/oop.h>
22 #include <proto/utility.h>
23 #include <proto/exec.h>
25 #define NewList NEWLIST
27 #undef HiddPCIDeviceAttrBase
28 #undef HiddUSBDeviceAttrBase
29 #undef HiddUSBHubAttrBase
30 #undef HiddUSBDrvAttrBase
31 #undef HiddAttrBase
33 #define HiddPCIDeviceAttrBase (hd->hd_HiddPCIDeviceAB)
34 #define HiddUSBDeviceAttrBase (hd->hd_HiddUSBDeviceAB)
35 #define HiddUSBHubAttrBase (hd->hd_HiddUSBHubAB)
36 #define HiddUSBDrvAttrBase (hd->hd_HiddUSBDrvAB)
37 #define HiddAttrBase (hd->hd_HiddAB)
39 AROS_UFH3(void, pciEnumerator,
40 AROS_UFHA(struct Hook *, hook, A0),
41 AROS_UFHA(OOP_Object *, pciDevice, A2),
42 AROS_UFHA(APTR, message, A1))
44 AROS_USERFUNC_INIT
46 struct PCIDevice *hd = (struct PCIDevice *) hook->h_Data;
47 struct PCIController *hc;
48 IPTR hcitype;
49 IPTR dev;
50 IPTR bus;
51 IPTR intline;
52 ULONG devid;
54 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Interface, &hcitype);
55 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Bus, &bus);
56 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Dev, &dev);
57 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &intline);
59 devid = (bus<<16)|dev;
61 if((hcitype == HCITYPE_UHCI) || (hcitype == HCITYPE_OHCI) || (hcitype == HCITYPE_EHCI))
63 KPRINTF(10, ("Found PCI device 0x%lx of type %ld\n", devid, hcitype));
65 hc = AllocPooled(hd->hd_MemPool, sizeof(struct PCIController));
66 if(hc)
68 hc->hc_Device = hd;
69 hc->hc_DevID = devid;
70 hc->hc_HCIType = hcitype;
71 hc->hc_PCIDeviceObject = pciDevice;
72 hc->hc_PCIIntLine = intline;
73 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (IPTR) &hc->hc_PCIDriverObject);
74 NewList(&hc->hc_CtrlXFerQueue);
75 NewList(&hc->hc_IntXFerQueue);
76 NewList(&hc->hc_IsoXFerQueue);
77 NewList(&hc->hc_BulkXFerQueue);
78 NewList(&hc->hc_TDQueue);
79 NewList(&hc->hc_PeriodicTDQueue);
80 NewList(&hc->hc_OhciRetireQueue);
81 AddTail(&hd->hd_TempHCIList, &hc->hc_Node);
85 AROS_USERFUNC_EXIT
89 /* /// "pciInit()" */
90 BOOL pciInit(struct PCIDevice *hd)
92 struct PCIController *hc;
93 struct PCIController *nexthc;
94 struct PCIUnit *hu;
95 ULONG unitno = 0;
96 UWORD ohcicnt;
97 UWORD uhcicnt;
99 KPRINTF(10, ("*** pciInit(%08lx) ***\n", hd));
100 NewList(&hd->hd_TempHCIList);
102 if(!(hd->hd_IRQHidd = OOP_NewObject(NULL, (STRPTR) CLID_Hidd_IRQ, NULL)))
104 KPRINTF(20, ("Unable to create IRQHidd object!\n"));
105 return FALSE;
108 if((hd->hd_PCIHidd = OOP_NewObject(NULL, (STRPTR) CLID_Hidd_PCI, NULL)))
110 struct TagItem tags[] =
112 { tHidd_PCI_Class, (PCI_CLASS_SERIAL_USB>>8) & 0xff },
113 { tHidd_PCI_SubClass, (PCI_CLASS_SERIAL_USB & 0xff) },
114 { TAG_DONE, 0UL }
117 struct OOP_ABDescr attrbases[] =
119 { (STRPTR) IID_Hidd, &hd->hd_HiddAB },
120 { (STRPTR) IID_Hidd_PCIDevice, &hd->hd_HiddPCIDeviceAB },
121 { (STRPTR) IID_Hidd_USBDevice, &hd->hd_HiddUSBDeviceAB },
122 { (STRPTR) IID_Hidd_USBHub, &hd->hd_HiddUSBHubAB },
123 { (STRPTR) IID_Hidd_USBDrv, &hd->hd_HiddUSBDrvAB },
124 { NULL, NULL }
127 struct Hook findHook =
129 h_Entry: (IPTR (*)()) pciEnumerator,
130 h_Data: hd,
133 OOP_ObtainAttrBases(attrbases);
135 KPRINTF(20, ("Searching for xHCI devices...\n"));
137 HIDD_PCI_EnumDevices(hd->hd_PCIHidd, &findHook, (struct TagItem *) &tags);
138 } else {
139 KPRINTF(20, ("Unable to create PCIHidd object!\n"));
140 OOP_DisposeObject(hd->hd_IRQHidd);
141 return FALSE;
144 while(hd->hd_TempHCIList.lh_Head->ln_Succ)
146 hu = AllocPooled(hd->hd_MemPool, sizeof(struct PCIUnit));
147 if(!hu)
149 // actually, we should get rid of the allocated memory first, but I don't care as DeletePool() will take care of this eventually
150 return FALSE;
152 hu->hu_Device = hd;
153 hu->hu_UnitNo = unitno;
154 hu->hu_DevID = ((struct PCIController *) hd->hd_TempHCIList.lh_Head)->hc_DevID;
156 NewList(&hu->hu_Controllers);
157 NewList(&hu->hu_RHIOQueue);
158 ohcicnt = 0;
159 uhcicnt = 0;
160 // find all belonging host controllers
161 hc = (struct PCIController *) hd->hd_TempHCIList.lh_Head;
162 while((nexthc = (struct PCIController *) hc->hc_Node.ln_Succ))
164 if(hc->hc_DevID == hu->hu_DevID)
166 Remove(&hc->hc_Node);
167 hc->hc_Unit = hu;
168 if(hc->hc_HCIType == HCITYPE_UHCI)
170 hc->hc_FunctionNum = uhcicnt++;
172 else if(hc->hc_HCIType == HCITYPE_OHCI)
174 hc->hc_FunctionNum = ohcicnt++;
175 } else {
176 hc->hc_FunctionNum = 0;
178 AddTail(&hu->hu_Controllers, &hc->hc_Node);
180 hc = nexthc;
182 AddTail(&hd->hd_Units, (struct Node *) hu);
183 unitno++;
185 return TRUE;
187 /* \\\ */
189 /* /// "PCIXReadConfigByte()" */
190 UBYTE PCIXReadConfigByte(struct PCIController *hc, UBYTE offset)
192 struct pHidd_PCIDevice_ReadConfigByte msg;
194 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigByte);
195 msg.reg = offset;
197 return OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
199 /* \\\ */
201 /* /// "PCIXWriteConfigByte()" */
202 void PCIXWriteConfigByte(struct PCIController *hc, ULONG offset, UBYTE value)
204 struct pHidd_PCIDevice_WriteConfigByte msg;
206 msg.mID = OOP_GetMethodID(CLID_Hidd_PCIDevice, moHidd_PCIDevice_WriteConfigByte);
207 msg.reg = offset;
208 msg.val = value;
210 OOP_DoMethod(hc->hc_PCIDeviceObject, (OOP_Msg) &msg);
212 /* \\\ */
214 /* /// "pciAllocUnit()" */
215 BOOL pciAllocUnit(struct PCIUnit *hu)
217 struct PCIDevice *hd = hu->hu_Device;
218 struct PCIController *hc;
219 struct PCIController *usb20hc = NULL;
220 BOOL allocgood = TRUE;
221 ULONG usb11ports;
222 ULONG usb20ports;
223 ULONG cnt;
224 BOOL complexrouting = FALSE;
225 ULONG portroute = 0;
227 struct TagItem pciActivateMem[] =
229 { aHidd_PCIDevice_isIO, TRUE },
230 { aHidd_PCIDevice_isMEM, TRUE },
231 { aHidd_PCIDevice_isMaster, FALSE },
232 { TAG_DONE, 0UL },
235 struct TagItem pciActivateBusmaster[] =
237 { aHidd_PCIDevice_isIO, TRUE },
238 { aHidd_PCIDevice_isMEM, TRUE },
239 { aHidd_PCIDevice_isMaster, TRUE },
240 { TAG_DONE, 0UL },
243 KPRINTF(10, ("*** pciAllocUnit(%08lx) ***\n", hu));
244 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
245 while(hc->hc_Node.ln_Succ)
247 #if 0
248 PCIXObtainBoard(hc->hc_BoardObject);
249 hc->hc_BoardAllocated = PCIXSetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER, (ULONG) hd->hd_Library.lib_Node.ln_Name);
250 allocgood &= hc->hc_BoardAllocated;
251 if(!hc->hc_BoardAllocated)
253 KPRINTF(20, ("Couldn't allocate board, already allocated by %s\n", PCIXGetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER)));
255 PCIXReleaseBoard(hc->hc_BoardObject);
256 #endif
258 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
261 if(allocgood)
263 // allocate necessary memory
264 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
265 while(hc->hc_Node.ln_Succ)
267 switch(hc->hc_HCIType)
269 case HCITYPE_UHCI:
271 struct UhciQH *uqh;
272 struct UhciQH *preduqh;
273 struct UhciTD *utd;
274 ULONG *tabptr;
275 UBYTE *memptr;
276 ULONG bitcnt;
278 hc->hc_NumPorts = 2; // UHCI always uses 2 ports per controller
279 KPRINTF(20, ("Found UHCI Controller %08lx FuncNum=%ld with %ld ports\n", hc->hc_PCIDeviceObject, hc->hc_FunctionNum, hc->hc_NumPorts));
280 hc->hc_CompleteInt.is_Node.ln_Type = NT_INTERRUPT;
281 hc->hc_CompleteInt.is_Node.ln_Name = "UHCI CompleteInt";
282 hc->hc_CompleteInt.is_Node.ln_Pri = 0;
283 hc->hc_CompleteInt.is_Data = hc;
284 hc->hc_CompleteInt.is_Code = (void (*)(void)) &uhciCompleteInt;
286 hc->hc_PCIMemSize = sizeof(ULONG) * UHCI_FRAMELIST_SIZE + UHCI_FRAMELIST_ALIGNMENT + 1;
287 hc->hc_PCIMemSize += sizeof(struct UhciQH) * UHCI_QH_POOLSIZE;
288 hc->hc_PCIMemSize += sizeof(struct UhciTD) * UHCI_TD_POOLSIZE;
289 memptr = HIDD_PCIDriver_AllocPCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMemSize);
290 if(!memptr)
292 allocgood = FALSE;
293 break;
295 hc->hc_PCIMem = (APTR) memptr;
296 // PhysicalAddress - VirtualAdjust = VirtualAddress
297 // VirtualAddress + VirtualAdjust = PhysicalAddress
298 hc->hc_PCIVirtualAdjust = ((ULONG) pciGetPhysical(hc, memptr)) - ((ULONG) memptr);
299 KPRINTF(10, ("VirtualAdjust 0x%08lx\n", hc->hc_PCIVirtualAdjust));
301 // align memory
302 memptr = (UBYTE *) ((((ULONG) hc->hc_PCIMem) + UHCI_FRAMELIST_ALIGNMENT) & (~UHCI_FRAMELIST_ALIGNMENT));
303 hc->hc_UhciFrameList = (ULONG *) memptr;
304 KPRINTF(10, ("FrameListBase 0x%08lx\n", hc->hc_UhciFrameList));
305 memptr += sizeof(APTR) * UHCI_FRAMELIST_SIZE;
307 // build up QH pool
308 uqh = (struct UhciQH *) memptr;
309 hc->hc_UhciQHPool = uqh;
310 cnt = UHCI_QH_POOLSIZE - 1;
313 // minimal initalization
314 uqh->uqh_Succ = (struct UhciXX *) (uqh + 1);
315 WRITEMEM32_LE(&uqh->uqh_Self, (ULONG) (&uqh->uqh_Link) + hc->hc_PCIVirtualAdjust + UHCI_QHSELECT);
316 uqh++;
317 } while(--cnt);
318 uqh->uqh_Succ = NULL;
319 memptr += sizeof(struct UhciQH) * UHCI_QH_POOLSIZE;
321 // build up TD pool
322 utd = (struct UhciTD *) memptr;
323 hc->hc_UhciTDPool = utd;
324 cnt = UHCI_TD_POOLSIZE - 1;
327 utd->utd_Succ = (struct UhciXX *) (utd + 1);
328 WRITEMEM32_LE(&utd->utd_Self, (ULONG) (&utd->utd_Link) + hc->hc_PCIVirtualAdjust + UHCI_TDSELECT);
329 utd++;
330 } while(--cnt);
331 utd->utd_Succ = NULL;
332 memptr += sizeof(struct UhciTD) * UHCI_TD_POOLSIZE;
334 // terminating QH
335 hc->hc_UhciTermQH = preduqh = uqh = uhciAllocQH(hc);
336 uqh->uqh_Succ = NULL;
337 CONSTWRITEMEM32_LE(&uqh->uqh_Link, UHCI_TERMINATE);
338 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
340 // dummy Bulk QH
341 hc->hc_UhciBulkQH = uqh = uhciAllocQH(hc);
342 uqh->uqh_Succ = (struct UhciXX *) preduqh;
343 preduqh->uqh_Pred = (struct UhciXX *) uqh;
344 uqh->uqh_Link = preduqh->uqh_Self; // link to terminating QH
345 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
346 preduqh = uqh;
348 // dummy Ctrl QH
349 hc->hc_UhciCtrlQH = uqh = uhciAllocQH(hc);
350 uqh->uqh_Succ = (struct UhciXX *) preduqh;
351 preduqh->uqh_Pred = (struct UhciXX *) uqh;
352 uqh->uqh_Link = preduqh->uqh_Self; // link to Bulk QH
353 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
355 // dummy ISO TD
356 hc->hc_UhciIsoTD = utd = uhciAllocTD(hc);
357 utd->utd_Succ = (struct UhciXX *) uqh;
358 //utd->utd_Pred = NULL; // no certain linkage above this level
359 uqh->uqh_Pred = (struct UhciXX *) utd;
360 utd->utd_Link = uqh->uqh_Self; // link to Ctrl QH
362 CONSTWRITEMEM32_LE(&utd->utd_CtrlStatus, 0);
364 // 1 ms INT QH
365 hc->hc_UhciIntQH[0] = uqh = uhciAllocQH(hc);
366 uqh->uqh_Succ = (struct UhciXX *) utd;
367 uqh->uqh_Pred = NULL; // who knows...
368 //uqh->uqh_Link = utd->utd_Self; // link to ISO
369 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
370 preduqh = uqh;
372 // make 9 levels of QH interrupts
373 for(cnt = 1; cnt < 9; cnt++)
375 hc->hc_UhciIntQH[cnt] = uqh = uhciAllocQH(hc);
376 uqh->uqh_Succ = (struct UhciXX *) preduqh;
377 uqh->uqh_Pred = NULL; // who knows...
378 //uqh->uqh_Link = preduqh->uqh_Self; // link to previous int level
379 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
380 preduqh = uqh;
383 uhciUpdateIntTree(hc);
385 // fill in framelist with IntQH entry points based on interval
386 tabptr = hc->hc_UhciFrameList;
387 for(cnt = 0; cnt < UHCI_FRAMELIST_SIZE; cnt++)
389 uqh = hc->hc_UhciIntQH[8];
390 bitcnt = 0;
393 if(cnt & (1UL<<bitcnt))
395 uqh = hc->hc_UhciIntQH[bitcnt];
396 break;
398 } while(++bitcnt < 9);
399 *tabptr++ = uqh->uqh_Self;
402 // this will cause more PCI memory access, but faster USB transfers aswell
403 //WRITEMEM32_LE(&hc->hc_UhciTermQH->uqh_Link, AROS_LONG2LE(hc->hc_UhciBulkQH->uqh_Self));
405 // time to initialize hardware...
406 OOP_GetAttr(hc->hc_PCIDeviceObject, aHidd_PCIDevice_Base4, (IPTR *) &hc->hc_RegBase);
407 hc->hc_RegBase = (APTR) (((IPTR) hc->hc_RegBase) & (~0xf));
408 KPRINTF(10, ("RegBase = 0x%08lx\n", hc->hc_RegBase));
409 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateMem); // no busmaster yet
410 SYNC;
411 EIEIO;
413 KPRINTF(10, ("Resetting UHCI HC\n"));
414 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET|UHCF_GLOBALRESET);
415 uhwDelayMS(10, hu, hd);
416 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET);
417 cnt = 100;
420 uhwDelayMS(10, hu, hd);
421 if(!(READREG16_LE(hc->hc_RegBase, UHCI_USBCMD) & UHCF_HCRESET))
423 break;
425 } while(--cnt);
427 if(cnt == 0)
429 KPRINTF(20, ("Reset Timeout!\n"));
430 } else {
431 KPRINTF(20, ("Reset finished after %ld ticks\n", 100-cnt));
433 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateBusmaster); // enable busmaster
434 // I've got no idea, why cyfm overwrites the status register with these values, but if it helps...
435 //PCIXWriteConfigLong(hc->hc_BoardObject, PCIXCONFIG_COMMAND, 0x80900007);
436 SYNC;
437 EIEIO;
439 // Fix for VIA Babble problem
440 cnt = PCIXReadConfigByte(hc, 0x40);
441 if(!(cnt & 0x40))
443 KPRINTF(20, ("Applying VIA Babble workaround\n"));
444 PCIXWriteConfigByte(hc, 0x40, cnt|0x40);
447 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_MAXPACKET64|UHCF_CONFIGURE);
449 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_FRAMECOUNT, 0);
451 WRITEREG32_LE(hc->hc_RegBase, UHCI_FRAMELISTADDR, (ULONG) pciGetPhysical(hc, hc->hc_UhciFrameList));
453 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBSTATUS, UHIF_TIMEOUTCRC|UHIF_INTONCOMPLETE|UHIF_SHORTPACKET);
454 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBINTEN, UHIF_TIMEOUTCRC|UHIF_INTONCOMPLETE|UHIF_SHORTPACKET);
456 // add interrupt
457 hc->hc_PCIIntHandler.h_Node.ln_Name = "UHCI PCI (pciusb.device)";
458 hc->hc_PCIIntHandler.h_Node.ln_Pri = 5;
459 hc->hc_PCIIntHandler.h_Code = uhciIntCode;
460 hc->hc_PCIIntHandler.h_Data = hc;
461 HIDD_IRQ_AddHandler(hd->hd_IRQHidd, &hc->hc_PCIIntHandler, hc->hc_PCIIntLine);
463 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_MAXPACKET64|UHCF_CONFIGURE|UHCF_RUNSTOP);
464 SYNC;
465 EIEIO;
466 KPRINTF(20, ("HW Init done\n"));
468 KPRINTF(10, ("HW Regs USBCMD/STS=%08lx\n", READREG32_LE(hc->hc_RegBase, UHCI_USBCMD)));
469 KPRINTF(10, ("HW Regs USBCMD=%04lx\n", READREG16_LE(hc->hc_RegBase, UHCI_USBCMD)));
470 KPRINTF(10, ("HW Regs USBSTS=%04lx\n", READREG16_LE(hc->hc_RegBase, UHCI_USBSTATUS)));
471 KPRINTF(10, ("HW Regs FRAMECOUNT=%04lx\n", READREG16_LE(hc->hc_RegBase, UHCI_FRAMECOUNT)));
472 break;
475 case HCITYPE_OHCI:
477 struct OhciED *oed;
478 struct OhciED *predoed;
479 struct OhciTD *otd;
480 ULONG *tabptr;
481 UBYTE *memptr;
482 ULONG bitcnt;
483 ULONG hubdesca;
484 ULONG frameival;
486 hc->hc_CompleteInt.is_Node.ln_Type = NT_INTERRUPT;
487 hc->hc_CompleteInt.is_Node.ln_Name = "OHCI CompleteInt";
488 hc->hc_CompleteInt.is_Node.ln_Pri = 0;
489 hc->hc_CompleteInt.is_Data = hc;
490 hc->hc_CompleteInt.is_Code = (void (*)(void)) &ohciCompleteInt;
492 hc->hc_PCIMemSize = OHCI_HCCA_SIZE + OHCI_HCCA_ALIGNMENT + 1;
493 hc->hc_PCIMemSize += sizeof(struct OhciED) * OHCI_ED_POOLSIZE;
494 hc->hc_PCIMemSize += sizeof(struct OhciTD) * OHCI_TD_POOLSIZE;
495 memptr = HIDD_PCIDriver_AllocPCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMemSize);
496 if(!memptr)
498 allocgood = FALSE;
499 break;
501 hc->hc_PCIMem = (APTR) memptr;
502 // PhysicalAddress - VirtualAdjust = VirtualAddress
503 // VirtualAddress + VirtualAdjust = PhysicalAddress
504 hc->hc_PCIVirtualAdjust = ((ULONG) pciGetPhysical(hc, memptr)) - ((ULONG) memptr);
505 KPRINTF(10, ("VirtualAdjust 0x%08lx\n", hc->hc_PCIVirtualAdjust));
507 // align memory
508 memptr = (UBYTE *) ((((ULONG) hc->hc_PCIMem) + OHCI_HCCA_ALIGNMENT) & (~OHCI_HCCA_ALIGNMENT));
509 hc->hc_OhciHCCA = (struct OhciHCCA *) memptr;
510 KPRINTF(10, ("HCCA 0x%08lx\n", hc->hc_OhciHCCA));
511 memptr += OHCI_HCCA_SIZE;
513 // build up ED pool
514 oed = (struct OhciED *) memptr;
515 hc->hc_OhciEDPool = oed;
516 cnt = OHCI_ED_POOLSIZE - 1;
519 // minimal initalization
520 oed->oed_Succ = (oed + 1);
521 WRITEMEM32_LE(&oed->oed_Self, (ULONG) (&oed->oed_EPCaps) + hc->hc_PCIVirtualAdjust);
522 oed++;
523 } while(--cnt);
524 oed->oed_Succ = NULL;
525 memptr += sizeof(struct OhciED) * OHCI_ED_POOLSIZE;
527 // build up TD pool
528 otd = (struct OhciTD *) memptr;
529 hc->hc_OhciTDPool = otd;
530 cnt = OHCI_TD_POOLSIZE - 1;
533 otd->otd_Succ = (otd + 1);
534 WRITEMEM32_LE(&otd->otd_Self, (ULONG) (&otd->otd_Ctrl) + hc->hc_PCIVirtualAdjust);
535 otd++;
536 } while(--cnt);
537 otd->otd_Succ = NULL;
538 memptr += sizeof(struct OhciTD) * OHCI_TD_POOLSIZE;
540 // terminating ED
541 hc->hc_OhciTermED = oed = ohciAllocED(hc);
542 oed->oed_Succ = NULL;
543 oed->oed_Pred = NULL;
544 CONSTWRITEMEM32_LE(&oed->oed_EPCaps, OECF_SKIP);
545 oed->oed_NextED = 0;
547 // terminating TD
548 hc->hc_OhciTermTD = otd = ohciAllocTD(hc);
549 otd->otd_Succ = NULL;
550 otd->otd_NextTD = 0;
552 // dummy head & tail Ctrl ED
553 hc->hc_OhciCtrlHeadED = predoed = ohciAllocED(hc);
554 hc->hc_OhciCtrlTailED = oed = ohciAllocED(hc);
555 CONSTWRITEMEM32_LE(&predoed->oed_EPCaps, OECF_SKIP);
556 CONSTWRITEMEM32_LE(&oed->oed_EPCaps, OECF_SKIP);
557 predoed->oed_Succ = oed;
558 predoed->oed_Pred = NULL;
559 predoed->oed_NextED = oed->oed_Self;
560 oed->oed_Succ = NULL;
561 oed->oed_Pred = predoed;
562 oed->oed_NextED = 0;
564 // dummy head & tail Bulk ED
565 hc->hc_OhciBulkHeadED = predoed = ohciAllocED(hc);
566 hc->hc_OhciBulkTailED = oed = ohciAllocED(hc);
567 CONSTWRITEMEM32_LE(&predoed->oed_EPCaps, OECF_SKIP);
568 CONSTWRITEMEM32_LE(&oed->oed_EPCaps, OECF_SKIP);
569 predoed->oed_Succ = oed;
570 predoed->oed_Pred = NULL;
571 predoed->oed_NextED = oed->oed_Self;
572 oed->oed_Succ = NULL;
573 oed->oed_Pred = predoed;
574 oed->oed_NextED = 0;
576 // 1 ms INT QH
577 hc->hc_OhciIntED[0] = oed = ohciAllocED(hc);
578 oed->oed_Succ = hc->hc_OhciTermED;
579 oed->oed_Pred = NULL; // who knows...
580 CONSTWRITEMEM32_LE(&oed->oed_EPCaps, OECF_SKIP);
581 oed->oed_NextED = hc->hc_OhciTermED->oed_Self;
582 predoed = oed;
584 // make 5 levels of QH interrupts
585 for(cnt = 1; cnt < 5; cnt++)
587 hc->hc_OhciIntED[cnt] = oed = ohciAllocED(hc);
588 oed->oed_Succ = predoed;
589 oed->oed_Pred = NULL; // who knows...
590 CONSTWRITEMEM32_LE(&oed->oed_EPCaps, OECF_SKIP);
591 oed->oed_NextED = hc->hc_OhciTermED->oed_Self;
592 predoed = oed;
595 ohciUpdateIntTree(hc);
597 // fill in framelist with IntED entry points based on interval
598 tabptr = hc->hc_OhciHCCA->oha_IntEDs;
599 for(cnt = 0; cnt < 32; cnt++)
601 oed = hc->hc_OhciIntED[4];
602 bitcnt = 0;
605 if(cnt & (1UL<<bitcnt))
607 oed = hc->hc_OhciIntED[bitcnt];
608 break;
610 } while(++bitcnt < 5);
611 *tabptr++ = oed->oed_Self;
614 // time to initialize hardware...
615 OOP_GetAttr(hc->hc_PCIDeviceObject, aHidd_PCIDevice_Base0, (IPTR *) &hc->hc_RegBase);
616 hc->hc_RegBase = (APTR) (((IPTR) hc->hc_RegBase) & (~0xf));
617 KPRINTF(10, ("RegBase = 0x%08lx\n", hc->hc_RegBase));
618 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateMem); // no busmaster yet
619 SYNC;
620 EIEIO;
622 hubdesca = READREG32_LE(hc->hc_RegBase, OHCI_HUBDESCA);
623 hc->hc_NumPorts = (hubdesca & OHAM_NUMPORTS)>>OHAS_NUMPORTS;
624 KPRINTF(20, ("Found OHCI Controller %08lx FuncNum = %ld, Rev %02lx, with %ld ports\n",
625 hc->hc_PCIDeviceObject, hc->hc_FunctionNum,
626 READREG32_LE(hc->hc_RegBase, OHCI_REVISION),
627 hc->hc_NumPorts));
629 KPRINTF(20, ("Powerswitching: %s %s\n",
630 hubdesca & OHAF_NOPOWERSWITCH ? "available" : "always on",
631 hubdesca & OHAF_INDIVIDUALPS ? "per port" : "global"));
633 KPRINTF(10, ("Resetting OHCI HC\n"));
634 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CMDSTATUS, OCSF_HCRESET);
635 cnt = 100;
638 if(!(READREG32_LE(hc->hc_RegBase, OHCI_CMDSTATUS) & OCSF_HCRESET))
640 break;
642 uhwDelayMS(1, hu, hd);
643 } while(--cnt);
645 if(cnt == 0)
647 KPRINTF(20, ("Reset Timeout!\n"));
648 } else {
649 KPRINTF(20, ("Reset finished after %ld ticks\n", 100-cnt));
652 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateBusmaster); // enable busmaster
653 SYNC;
654 EIEIO;
656 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_FRAMECOUNT, 0);
657 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_PERIODICSTART, 10800); // 10% of 12000
658 frameival = READREG32_LE(hc->hc_RegBase, OHCI_FRAMEINTERVAL);
659 KPRINTF(10, ("FrameInterval=%08lx\n", frameival));
660 frameival &= ~OIVM_BITSPERFRAME;
661 frameival |= OHCI_DEF_BITSPERFRAME<<OIVS_BITSPERFRAME;
662 frameival ^= OIVF_TOGGLE;
663 WRITEREG32_LE(hc->hc_RegBase, OHCI_FRAMEINTERVAL, frameival);
665 // make sure nothing is running
666 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_PERIODIC_ED, 0);
667 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CTRL_HEAD_ED, AROS_LONG2LE(hc->hc_OhciCtrlHeadED->oed_Self));
668 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CTRL_ED, 0);
669 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_BULK_HEAD_ED, AROS_LONG2LE(hc->hc_OhciBulkHeadED->oed_Self));
670 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_BULK_ED, 0);
671 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_DONEHEAD, 0);
673 WRITEREG32_LE(hc->hc_RegBase, OHCI_HCCA, (ULONG) pciGetPhysical(hc, hc->hc_OhciHCCA));
675 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_INTSTATUS, OISF_ALL_INTS);
676 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_INTDIS, OISF_ALL_INTS);
677 SYNC;
678 EIEIO;
680 // add interrupt
681 hc->hc_PCIIntHandler.h_Node.ln_Name = "OHCI PCI (pciusb.device)";
682 hc->hc_PCIIntHandler.h_Node.ln_Pri = 5;
683 hc->hc_PCIIntHandler.h_Code = ohciIntCode;
684 hc->hc_PCIIntHandler.h_Data = hc;
685 HIDD_IRQ_AddHandler(hd->hd_IRQHidd, &hc->hc_PCIIntHandler, hc->hc_PCIIntLine);
687 hc->hc_PCIIntEnMask = OISF_SCHEDOVERRUN|OISF_DONEHEAD|OISF_RESUMEDTX|OISF_HOSTERROR|OISF_FRAMECOUNTOVER|OISF_HUBCHANGE;
689 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_INTEN, OISF_SCHEDOVERRUN|OISF_DONEHEAD|OISF_RESUMEDTX|OISF_HOSTERROR|OISF_FRAMECOUNTOVER|OISF_HUBCHANGE|OISF_MASTERENABLE);
691 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CONTROL, OCLF_PERIODICENABLE|OCLF_CTRLENABLE|OCLF_BULKENABLE|OCLF_USBRESET);
692 SYNC;
693 EIEIO;
695 if(!(hubdesca & OHAF_INDIVIDUALPS))
697 KPRINTF(20, ("Individual power switching not available, turning on all ports!\n"));
698 WRITEREG32_LE(hc->hc_RegBase, OHCI_HUBDESCB, 0);
699 WRITEREG32_LE(hc->hc_RegBase, OHCI_HUBSTATUS, OHSF_POWERHUB);
700 } else {
701 KPRINTF(20, ("Enabling individual power switching\n"));
702 WRITEREG32_LE(hc->hc_RegBase, OHCI_HUBDESCB, ((2<<hc->hc_NumPorts)-2)<<OHBS_PORTPOWERCTRL);
703 WRITEREG32_LE(hc->hc_RegBase, OHCI_HUBSTATUS, OHSF_POWERHUB);
706 uhwDelayMS(50, hu, hd);
707 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CONTROL, OCLF_PERIODICENABLE|OCLF_CTRLENABLE|OCLF_BULKENABLE|OCLF_USBOPER);
708 SYNC;
709 EIEIO;
711 KPRINTF(20, ("HW Init done\n"));
712 break;
715 case HCITYPE_EHCI:
717 struct EhciQH *eqh;
718 struct EhciQH *predeqh;
719 struct EhciTD *etd;
720 ULONG *tabptr;
721 UBYTE *memptr;
722 ULONG bitcnt;
723 ULONG hcsparams;
724 ULONG hccparams;
725 volatile APTR pciregbase;
727 usb20hc = hc;
729 hc->hc_CompleteInt.is_Node.ln_Type = NT_INTERRUPT;
730 hc->hc_CompleteInt.is_Node.ln_Name = "EHCI CompleteInt";
731 hc->hc_CompleteInt.is_Node.ln_Pri = 0;
732 hc->hc_CompleteInt.is_Data = hc;
733 hc->hc_CompleteInt.is_Code = (void (*)(void)) &ehciCompleteInt;
735 hc->hc_PCIMemSize = sizeof(ULONG) * EHCI_FRAMELIST_SIZE + EHCI_FRAMELIST_ALIGNMENT + 1;
736 hc->hc_PCIMemSize += sizeof(struct EhciQH) * EHCI_QH_POOLSIZE;
737 hc->hc_PCIMemSize += sizeof(struct EhciTD) * EHCI_TD_POOLSIZE;
738 memptr = HIDD_PCIDriver_AllocPCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMemSize);
739 if(!memptr)
741 allocgood = FALSE;
742 break;
744 hc->hc_PCIMem = (APTR) memptr;
745 // PhysicalAddress - VirtualAdjust = VirtualAddress
746 // VirtualAddress + VirtualAdjust = PhysicalAddress
747 hc->hc_PCIVirtualAdjust = ((ULONG) pciGetPhysical(hc, memptr)) - ((ULONG) memptr);
748 KPRINTF(10, ("VirtualAdjust 0x%08lx\n", hc->hc_PCIVirtualAdjust));
750 // align memory
751 memptr = (UBYTE *) ((((ULONG) hc->hc_PCIMem) + EHCI_FRAMELIST_ALIGNMENT) & (~EHCI_FRAMELIST_ALIGNMENT));
752 hc->hc_EhciFrameList = (ULONG *) memptr;
753 KPRINTF(10, ("FrameListBase 0x%08lx\n", hc->hc_EhciFrameList));
754 memptr += sizeof(APTR) * EHCI_FRAMELIST_SIZE;
756 // build up QH pool
757 eqh = (struct EhciQH *) memptr;
758 hc->hc_EhciQHPool = eqh;
759 cnt = EHCI_QH_POOLSIZE - 1;
762 // minimal initalization
763 eqh->eqh_Succ = (eqh + 1);
764 WRITEMEM32_LE(&eqh->eqh_Self, (ULONG) (&eqh->eqh_NextQH) + hc->hc_PCIVirtualAdjust + EHCI_QUEUEHEAD);
765 CONSTWRITEMEM32_LE(&eqh->eqh_NextTD, EHCI_TERMINATE);
766 CONSTWRITEMEM32_LE(&eqh->eqh_AltNextTD, EHCI_TERMINATE);
767 eqh++;
768 } while(--cnt);
769 eqh->eqh_Succ = NULL;
770 memptr += sizeof(struct EhciQH) * EHCI_QH_POOLSIZE;
772 // build up TD pool
773 etd = (struct EhciTD *) memptr;
774 hc->hc_EhciTDPool = etd;
775 cnt = EHCI_TD_POOLSIZE - 1;
778 etd->etd_Succ = (etd + 1);
779 WRITEMEM32_LE(&etd->etd_Self, (ULONG) (&etd->etd_NextTD) + hc->hc_PCIVirtualAdjust);
780 etd++;
781 } while(--cnt);
782 etd->etd_Succ = NULL;
783 memptr += sizeof(struct EhciTD) * EHCI_TD_POOLSIZE;
785 // empty async queue head
786 hc->hc_EhciAsyncFreeQH = NULL;
787 hc->hc_EhciAsyncQH = eqh = ehciAllocQH(hc);
788 eqh->eqh_Succ = eqh;
789 eqh->eqh_Pred = eqh;
790 CONSTWRITEMEM32_LE(&eqh->eqh_EPCaps, EQEF_RECLAMHEAD);
791 eqh->eqh_NextQH = eqh->eqh_Self;
793 // empty terminating queue head
794 hc->hc_EhciTermQH = eqh = ehciAllocQH(hc);
795 eqh->eqh_Succ = NULL;
796 CONSTWRITEMEM32_LE(&eqh->eqh_NextQH, EHCI_TERMINATE);
797 predeqh = eqh;
799 // 1 ms INT QH
800 hc->hc_EhciIntQH[0] = eqh = ehciAllocQH(hc);
801 eqh->eqh_Succ = predeqh;
802 predeqh->eqh_Pred = eqh;
803 eqh->eqh_Pred = NULL; // who knows...
804 //eqh->eqh_NextQH = predeqh->eqh_Self;
805 predeqh = eqh;
807 // make 11 levels of QH interrupts
808 for(cnt = 1; cnt < 11; cnt++)
810 hc->hc_EhciIntQH[cnt] = eqh = ehciAllocQH(hc);
811 eqh->eqh_Succ = predeqh;
812 eqh->eqh_Pred = NULL; // who knows...
813 //eqh->eqh_NextQH = predeqh->eqh_Self; // link to previous int level
814 predeqh = eqh;
817 ehciUpdateIntTree(hc);
819 // fill in framelist with IntQH entry points based on interval
820 tabptr = hc->hc_EhciFrameList;
821 for(cnt = 0; cnt < EHCI_FRAMELIST_SIZE; cnt++)
823 eqh = hc->hc_EhciIntQH[10];
824 bitcnt = 0;
827 if(cnt & (1UL<<bitcnt))
829 eqh = hc->hc_EhciIntQH[bitcnt];
830 break;
832 } while(++bitcnt < 11);
833 *tabptr++ = eqh->eqh_Self;
836 etd = hc->hc_ShortPktEndTD = ehciAllocTD(hc);
837 etd->etd_Succ = NULL;
838 CONSTWRITEMEM32_LE(&etd->etd_NextTD, EHCI_TERMINATE);
839 CONSTWRITEMEM32_LE(&etd->etd_AltNextTD, EHCI_TERMINATE);
840 CONSTWRITEMEM32_LE(&etd->etd_CtrlStatus, 0);
842 // time to initialize hardware...
843 OOP_GetAttr(hc->hc_PCIDeviceObject, aHidd_PCIDevice_Base0, (IPTR *) &pciregbase);
844 pciregbase = (APTR) (((IPTR) pciregbase) & (~0xf));
845 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateMem); // no busmaster yet
846 SYNC;
847 EIEIO;
849 // we use the operational registers as RegBase.
850 hc->hc_RegBase = (APTR) ((ULONG) pciregbase + READREG16_LE(pciregbase, EHCI_CAPLENGTH));
851 KPRINTF(10, ("RegBase = 0x%08lx\n", hc->hc_RegBase));
853 KPRINTF(10, ("Resetting EHCI HC\n"));
854 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBCMD, EHUF_HCRESET|(1UL<<EHUS_INTTHRESHOLD));
855 uhwDelayMS(10, hu, hd);
856 cnt = 100;
859 uhwDelayMS(10, hu, hd);
860 if(!(READREG32_LE(hc->hc_RegBase, EHCI_USBCMD) & EHUF_HCRESET))
862 break;
864 } while(--cnt);
866 if(cnt == 0)
868 KPRINTF(20, ("Reset Timeout!\n"));
869 } else {
870 KPRINTF(20, ("Reset finished after %ld ticks\n", 100-cnt));
872 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateBusmaster); // enable busmaster
873 SYNC;
874 EIEIO;
876 // Read HCSPARAMS register to obtain number of downstream ports
877 hcsparams = READREG32_LE(pciregbase, EHCI_HCSPARAMS);
878 hccparams = READREG32_LE(pciregbase, EHCI_HCCPARAMS);
880 hc->hc_NumPorts = (hcsparams & EHSM_NUM_PORTS)>>EHSS_NUM_PORTS;
881 KPRINTF(20, ("Found EHCI Controller %08lx with %ld ports (%ld companions with %ld ports each)\n",
882 hc->hc_PCIDeviceObject, hc->hc_NumPorts,
883 (hcsparams & EHSM_NUM_COMPANIONS)>>EHSS_NUM_COMPANIONS,
884 (hcsparams & EHSM_PORTS_PER_COMP)>>EHSS_PORTS_PER_COMP));
885 if(hcsparams & EHSF_EXTPORTROUTING)
887 complexrouting = TRUE;
888 portroute = READREG32_LE(pciregbase, EHCI_HCSPPORTROUTE);
889 #ifdef DEBUG
890 for(cnt = 0; cnt < hc->hc_NumPorts; cnt++)
892 KPRINTF(100, ("Port %ld maps to controller %ld\n", cnt, ((portroute >> (cnt<<2)) & 0xf)));
894 #endif
896 KPRINTF(20, ("HCCParams: 64 Bit=%s, ProgFrameList=%s, AsyncSchedPark=%s\n",
897 (hccparams & EHCF_64BITS) ? "Yes" : "No",
898 (hccparams & EHCF_PROGFRAMELIST) ? "Yes" : "No",
899 (hccparams & EHCF_ASYNCSCHEDPARK) ? "Yes" : "No"));
900 hc->hc_EhciUsbCmd = (1UL<<EHUS_INTTHRESHOLD);
901 if(hccparams & EHCF_ASYNCSCHEDPARK)
903 KPRINTF(20, ("Enabling AsyncSchedParkMode with MULTI_3\n"));
904 hc->hc_EhciUsbCmd |= EHUF_ASYNCSCHEDPARK|(3<<EHUS_ASYNCPARKCOUNT);
906 WRITEREG32_LE(hc->hc_RegBase, EHCI_USBCMD, hc->hc_EhciUsbCmd);
908 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_FRAMECOUNT, 0);
910 WRITEREG32_LE(hc->hc_RegBase, EHCI_PERIODICLIST, (ULONG) pciGetPhysical(hc, hc->hc_EhciFrameList));
911 WRITEREG32_LE(hc->hc_RegBase, EHCI_ASYNCADDR, AROS_LONG2LE(hc->hc_EhciAsyncQH->eqh_Self));
913 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBSTATUS, EHSF_ALL_INTS);
914 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBINTEN, EHSF_ALL_INTS);
915 hc->hc_PCIIntEnMask = EHSF_ALL_INTS;
917 // add interrupt
918 hc->hc_PCIIntHandler.h_Node.ln_Name = "EHCI PCI (pciusb.device)";
919 hc->hc_PCIIntHandler.h_Node.ln_Pri = 5;
920 hc->hc_PCIIntHandler.h_Code = ehciIntCode;
921 hc->hc_PCIIntHandler.h_Data = hc;
922 HIDD_IRQ_AddHandler(hd->hd_IRQHidd, &hc->hc_PCIIntHandler, hc->hc_PCIIntLine);
924 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_CONFIGFLAG, EHCF_CONFIGURED);
925 hc->hc_EhciUsbCmd |= EHUF_RUNSTOP|EHUF_PERIODICENABLE|EHUF_ASYNCENABLE;
926 WRITEREG32_LE(hc->hc_RegBase, EHCI_USBCMD, hc->hc_EhciUsbCmd);
927 SYNC;
928 EIEIO;
929 KPRINTF(20, ("HW Init done\n"));
931 KPRINTF(10, ("HW Regs USBCMD=%04lx\n", READREG32_LE(hc->hc_RegBase, EHCI_USBCMD)));
932 KPRINTF(10, ("HW Regs USBSTS=%04lx\n", READREG32_LE(hc->hc_RegBase, EHCI_USBSTATUS)));
933 KPRINTF(10, ("HW Regs FRAMECOUNT=%04lx\n", READREG32_LE(hc->hc_RegBase, EHCI_FRAMECOUNT)));
934 break;
937 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
941 if(!allocgood)
943 // free previously allocated boards
944 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
945 while(hc->hc_Node.ln_Succ)
947 #if 0
948 PCIXObtainBoard(hc->hc_BoardObject);
949 if(hc->hc_BoardAllocated)
951 hc->hc_BoardAllocated = FALSE;
952 PCIXSetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER, 0);
954 PCIXReleaseBoard(hc->hc_BoardObject);
955 #endif
956 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
958 return FALSE;
961 // find all belonging host controllers
962 usb11ports = 0;
963 usb20ports = 0;
964 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
965 while(hc->hc_Node.ln_Succ)
967 if(hc->hc_HCIType == HCITYPE_EHCI)
969 if(usb20ports)
971 KPRINTF(200, ("WARNING: Two EHCI controllers per Board?!?\n"));
973 usb20ports = hc->hc_NumPorts;
974 for(cnt = 0; cnt < usb20ports; cnt++)
976 hu->hu_PortMap20[cnt] = hc;
977 hc->hc_PortNum20[cnt] = cnt;
980 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
983 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
984 while(hc->hc_Node.ln_Succ)
986 if((hc->hc_HCIType == HCITYPE_UHCI) || (hc->hc_HCIType == HCITYPE_OHCI))
988 if(complexrouting)
990 ULONG locport = 0;
991 for(cnt = 0; cnt < usb20ports; cnt++)
993 if(((portroute >> (cnt<<2)) & 0xf) == hc->hc_FunctionNum)
995 KPRINTF(10, ("CHC %ld Port %ld assigned to global Port %ld\n", hc->hc_FunctionNum, locport, cnt));
996 hu->hu_PortMap11[cnt] = hc;
997 hu->hu_PortNum11[cnt] = locport;
998 hc->hc_PortNum20[locport] = cnt;
999 locport++;
1002 } else {
1003 for(cnt = usb11ports; cnt < usb11ports + hc->hc_NumPorts; cnt++)
1005 hu->hu_PortMap11[cnt] = hc;
1006 hu->hu_PortNum11[cnt] = cnt - usb11ports;
1007 hc->hc_PortNum20[cnt - usb11ports] = cnt;
1010 usb11ports += hc->hc_NumPorts;
1012 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
1014 if((usb11ports != usb20ports) && usb20ports)
1016 KPRINTF(20, ("Warning! #EHCI Ports (%ld) does not match USB 1.1 Ports (%ld)!\n", usb20ports, usb11ports));
1018 hu->hu_RootHub11Ports = usb11ports;
1019 hu->hu_RootHub20Ports = usb20ports;
1020 hu->hu_RootHubPorts = (usb11ports > usb20ports) ? usb11ports : usb20ports;
1022 for(cnt = 0; cnt < hu->hu_RootHubPorts; cnt++)
1024 hu->hu_EhciOwned[cnt] = hu->hu_PortMap20[cnt] ? TRUE : FALSE;
1027 KPRINTF(10, ("Unit %ld: USB Board %08lx has %ld USB1.1 and %ld USB2.0 ports!\n", hu->hu_UnitNo, hu->hu_DevID, hu->hu_RootHub11Ports, hu->hu_RootHub20Ports));
1029 hu->hu_FrameCounter = 1;
1030 hu->hu_RootHubAddr = 0;
1032 // put em online
1033 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1034 while(hc->hc_Node.ln_Succ)
1036 hc->hc_Online = TRUE;
1037 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
1040 KPRINTF(10, ("Unit allocated!\n", hd));
1042 return TRUE;
1044 /* \\\ */
1046 /* /// "pciFreeUnit()" */
1047 void pciFreeUnit(struct PCIUnit *hu)
1049 struct PCIDevice *hd = hu->hu_Device;
1050 struct PCIController *hc;
1052 struct TagItem pciDeactivate[] =
1054 { aHidd_PCIDevice_isIO, FALSE },
1055 { aHidd_PCIDevice_isMEM, FALSE },
1056 { aHidd_PCIDevice_isMaster, FALSE },
1057 { TAG_DONE, 0UL },
1060 KPRINTF(10, ("*** pciFreeUnit(%08lx) ***\n", hu));
1062 // put em offline
1063 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1064 while(hc->hc_Node.ln_Succ)
1066 hc->hc_Online = FALSE;
1067 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
1070 // doing this in three steps to avoid these damn host errors
1071 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1072 while(hc->hc_Node.ln_Succ)
1074 switch(hc->hc_HCIType)
1076 case HCITYPE_EHCI:
1078 UWORD portreg;
1079 UWORD hciport;
1080 KPRINTF(20, ("Shutting down EHCI %08lx\n", hc));
1081 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBINTEN, 0);
1082 // disable all ports
1083 for(hciport = 0; hciport < hc->hc_NumPorts; hciport++)
1085 portreg = EHCI_PORTSC1 + (hciport<<2);
1086 WRITEREG32_LE(hc->hc_RegBase, portreg, 0);
1088 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBCMD, 1UL<<EHUS_INTTHRESHOLD);
1089 uhwDelayMS(10, hu, hd);
1090 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_CONFIGFLAG, 0);
1091 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBCMD, EHUF_HCRESET|(1UL<<EHUS_INTTHRESHOLD));
1092 SYNC;
1093 EIEIO;
1094 uhwDelayMS(50, hu, hd);
1095 CONSTWRITEREG32_LE(hc->hc_RegBase, EHCI_USBCMD, 1UL<<EHUS_INTTHRESHOLD);
1096 SYNC;
1097 EIEIO;
1098 uhwDelayMS(10, hu, hd);
1100 KPRINTF(20, ("Shutting down EHCI done.\n"));
1101 break;
1105 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
1108 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1109 while(hc->hc_Node.ln_Succ)
1111 switch(hc->hc_HCIType)
1113 case HCITYPE_UHCI:
1114 KPRINTF(20, ("Shutting down UHCI %08lx\n", hc));
1115 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBINTEN, 0);
1116 // disable all ports
1117 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_PORT1STSCTRL, 0x0000);
1118 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_PORT2STSCTRL, 0x0000);
1119 uhwDelayMS(50, hu, hd);
1120 //CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_MAXPACKET64|UHCF_CONFIGURE);
1121 //uhwDelayMS(50, hu, hd);
1122 KPRINTF(20, ("Stopping UHCI %08lx\n", hc));
1123 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, 0);
1124 SYNC;
1125 EIEIO;
1126 //KPRINTF(20, ("Reset done UHCI %08lx\n", hc));
1127 uhwDelayMS(10, hu, hd);
1128 KPRINTF(20, ("Resetting UHCI %08lx\n", hc));
1129 CONSTWRITEREG16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET|UHCF_GLOBALRESET);
1130 SYNC;
1131 EIEIO;
1132 uhwDelayMS(50, hu, hd);
1134 KPRINTF(20, ("Shutting down UHCI done.\n"));
1135 break;
1137 case HCITYPE_OHCI:
1138 KPRINTF(20, ("Shutting down OHCI %08lx\n", hc));
1139 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_INTDIS, OISF_ALL_INTS);
1140 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_INTSTATUS, OISF_ALL_INTS);
1142 // disable all ports
1143 WRITEREG32_LE(hc->hc_RegBase, OHCI_HUBDESCB, 0);
1144 WRITEREG32_LE(hc->hc_RegBase, OHCI_HUBSTATUS, OHSF_UNPOWERHUB);
1146 uhwDelayMS(50, hu, hd);
1147 KPRINTF(20, ("Stopping OHCI %08lx\n", hc));
1148 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CONTROL, 0);
1149 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CMDSTATUS, 0);
1150 SYNC;
1151 EIEIO;
1152 //KPRINTF(20, ("Reset done UHCI %08lx\n", hc));
1153 uhwDelayMS(10, hu, hd);
1154 KPRINTF(20, ("Resetting OHCI %08lx\n", hc));
1155 CONSTWRITEREG32_LE(hc->hc_RegBase, OHCI_CMDSTATUS, OCSF_HCRESET);
1156 SYNC;
1157 EIEIO;
1158 uhwDelayMS(50, hu, hd);
1160 KPRINTF(20, ("Shutting down OHCI done.\n"));
1161 break;
1164 if(hc->hc_PCIMem)
1166 HIDD_PCIDriver_FreePCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMem);
1167 hc->hc_PCIMem = NULL;
1169 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
1172 // disable and free board
1173 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1174 while(hc->hc_Node.ln_Succ)
1176 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciDeactivate); // deactivate busmaster and IO/Mem
1177 if(hc->hc_PCIIntHandler.h_Node.ln_Name)
1179 HIDD_IRQ_RemHandler(hd->hd_IRQHidd, &hc->hc_PCIIntHandler);
1180 hc->hc_PCIIntHandler.h_Node.ln_Name = NULL;
1182 #if 0
1184 PCIXObtainBoard(hc->hc_BoardObject);
1185 hc->hc_BoardAllocated = FALSE;
1186 PCIXSetBoardAttr(hc->hc_BoardObject, PCIXTAG_OWNER, 0);
1187 PCIXReleaseBoard(hc->hc_BoardObject);
1188 #endif
1189 hc = (struct PCIController *) hc->hc_Node.ln_Succ;
1192 /* \\\ */
1194 /* /// "pciExpunge()" */
1195 void pciExpunge(struct PCIDevice *hd)
1197 struct PCIController *hc;
1198 struct PCIUnit *hu;
1200 KPRINTF(10, ("*** pciExpunge(%08lx) ***\n", hd));
1202 hu = (struct PCIUnit *) hd->hd_Units.lh_Head;
1203 while(((struct Node *) hu)->ln_Succ)
1205 Remove((struct Node *) hu);
1206 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1207 while(hc->hc_Node.ln_Succ)
1209 Remove(&hc->hc_Node);
1210 FreePooled(hd->hd_MemPool, hc, sizeof(struct PCIController));
1211 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1213 FreePooled(hd->hd_MemPool, hu, sizeof(struct PCIUnit));
1214 hu = (struct PCIUnit *) hd->hd_Units.lh_Head;
1216 if(hd->hd_PCIHidd)
1218 struct OOP_ABDescr attrbases[] =
1220 { (STRPTR) IID_Hidd, &hd->hd_HiddAB },
1221 { (STRPTR) IID_Hidd_PCIDevice, &hd->hd_HiddPCIDeviceAB },
1222 { (STRPTR) IID_Hidd_USBDevice, &hd->hd_HiddUSBDeviceAB },
1223 { (STRPTR) IID_Hidd_USBHub, &hd->hd_HiddUSBHubAB },
1224 { (STRPTR) IID_Hidd_USBDrv, &hd->hd_HiddUSBDrvAB },
1225 { NULL, NULL }
1228 OOP_ReleaseAttrBases(attrbases);
1230 OOP_DisposeObject(hd->hd_PCIHidd);
1232 if(hd->hd_IRQHidd)
1234 OOP_DisposeObject(hd->hd_IRQHidd);
1237 /* \\\ */
1239 /* /// "pciGetPhysical()" */
1240 APTR pciGetPhysical(struct PCIController *hc, APTR virtaddr)
1242 //struct PCIDevice *hd = hc->hc_Device;
1243 return(HIDD_PCIDriver_CPUtoPCI(hc->hc_PCIDriverObject, virtaddr));
1245 /* \\\ */