1 /* pci_aros.c - pci access abstraction for AROS by Chris Hodges
8 #include <aros/symbolsets.h>
10 #include <exec/types.h>
13 #include <devices/timer.h>
15 #include <hidd/hidd.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
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
))
46 struct PCIDevice
*hd
= (struct PCIDevice
*) hook
->h_Data
;
47 struct PCIController
*hc
;
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
));
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
);
90 BOOL
pciInit(struct PCIDevice
*hd
)
92 struct PCIController
*hc
;
93 struct PCIController
*nexthc
;
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"));
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) },
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
},
127 struct Hook findHook
=
129 h_Entry
: (IPTR (*)()) pciEnumerator
,
133 OOP_ObtainAttrBases(attrbases
);
135 KPRINTF(20, ("Searching for xHCI devices...\n"));
137 HIDD_PCI_EnumDevices(hd
->hd_PCIHidd
, &findHook
, (struct TagItem
*) &tags
);
139 KPRINTF(20, ("Unable to create PCIHidd object!\n"));
140 OOP_DisposeObject(hd
->hd_IRQHidd
);
144 while(hd
->hd_TempHCIList
.lh_Head
->ln_Succ
)
146 hu
= AllocPooled(hd
->hd_MemPool
, sizeof(struct PCIUnit
));
149 // actually, we should get rid of the allocated memory first, but I don't care as DeletePool() will take care of this eventually
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
);
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
);
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
++;
176 hc
->hc_FunctionNum
= 0;
178 AddTail(&hu
->hu_Controllers
, &hc
->hc_Node
);
182 AddTail(&hd
->hd_Units
, (struct Node
*) hu
);
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
);
197 return OOP_DoMethod(hc
->hc_PCIDeviceObject
, (OOP_Msg
) &msg
);
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
);
210 OOP_DoMethod(hc
->hc_PCIDeviceObject
, (OOP_Msg
) &msg
);
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
;
224 BOOL complexrouting
= FALSE
;
227 struct TagItem pciActivateMem
[] =
229 { aHidd_PCIDevice_isIO
, TRUE
},
230 { aHidd_PCIDevice_isMEM
, TRUE
},
231 { aHidd_PCIDevice_isMaster
, FALSE
},
235 struct TagItem pciActivateBusmaster
[] =
237 { aHidd_PCIDevice_isIO
, TRUE
},
238 { aHidd_PCIDevice_isMEM
, TRUE
},
239 { aHidd_PCIDevice_isMaster
, TRUE
},
243 KPRINTF(10, ("*** pciAllocUnit(%08lx) ***\n", hu
));
244 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
245 while(hc
->hc_Node
.ln_Succ
)
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
);
258 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
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
)
272 struct UhciQH
*preduqh
;
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
);
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
));
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
;
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
);
318 uqh
->uqh_Succ
= NULL
;
319 memptr
+= sizeof(struct UhciQH
) * UHCI_QH_POOLSIZE
;
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
);
331 utd
->utd_Succ
= NULL
;
332 memptr
+= sizeof(struct UhciTD
) * UHCI_TD_POOLSIZE
;
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
);
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
);
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
);
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);
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
);
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
);
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];
393 if(cnt
& (1UL<<bitcnt
))
395 uqh
= hc
->hc_UhciIntQH
[bitcnt
];
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
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
);
420 uhwDelayMS(10, hu
, hd
);
421 if(!(READREG16_LE(hc
->hc_RegBase
, UHCI_USBCMD
) & UHCF_HCRESET
))
429 KPRINTF(20, ("Reset Timeout!\n"));
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);
439 // Fix for VIA Babble problem
440 cnt
= PCIXReadConfigByte(hc
, 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
);
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
);
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
)));
478 struct OhciED
*predoed
;
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
);
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
));
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
;
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
);
524 oed
->oed_Succ
= NULL
;
525 memptr
+= sizeof(struct OhciED
) * OHCI_ED_POOLSIZE
;
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
);
537 otd
->otd_Succ
= NULL
;
538 memptr
+= sizeof(struct OhciTD
) * OHCI_TD_POOLSIZE
;
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
);
548 hc
->hc_OhciTermTD
= otd
= ohciAllocTD(hc
);
549 otd
->otd_Succ
= NULL
;
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
;
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
;
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
;
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
;
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];
605 if(cnt
& (1UL<<bitcnt
))
607 oed
= hc
->hc_OhciIntED
[bitcnt
];
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
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
),
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
);
638 if(!(READREG32_LE(hc
->hc_RegBase
, OHCI_CMDSTATUS
) & OCSF_HCRESET
))
642 uhwDelayMS(1, hu
, hd
);
647 KPRINTF(20, ("Reset Timeout!\n"));
649 KPRINTF(20, ("Reset finished after %ld ticks\n", 100-cnt
));
652 OOP_SetAttrs(hc
->hc_PCIDeviceObject
, (struct TagItem
*) pciActivateBusmaster
); // enable busmaster
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
);
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
);
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
);
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
);
711 KPRINTF(20, ("HW Init done\n"));
718 struct EhciQH
*predeqh
;
725 volatile APTR pciregbase
;
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
);
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
));
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
;
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
);
769 eqh
->eqh_Succ
= NULL
;
770 memptr
+= sizeof(struct EhciQH
) * EHCI_QH_POOLSIZE
;
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
);
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
);
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
);
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;
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
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];
827 if(cnt
& (1UL<<bitcnt
))
829 eqh
= hc
->hc_EhciIntQH
[bitcnt
];
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
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
);
859 uhwDelayMS(10, hu
, hd
);
860 if(!(READREG32_LE(hc
->hc_RegBase
, EHCI_USBCMD
) & EHUF_HCRESET
))
868 KPRINTF(20, ("Reset Timeout!\n"));
870 KPRINTF(20, ("Reset finished after %ld ticks\n", 100-cnt
));
872 OOP_SetAttrs(hc
->hc_PCIDeviceObject
, (struct TagItem
*) pciActivateBusmaster
); // enable busmaster
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
);
890 for(cnt
= 0; cnt
< hc
->hc_NumPorts
; cnt
++)
892 KPRINTF(100, ("Port %ld maps to controller %ld\n", cnt
, ((portroute
>> (cnt
<<2)) & 0xf)));
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
;
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
);
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
)));
937 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
943 // free previously allocated boards
944 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
945 while(hc
->hc_Node
.ln_Succ
)
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
);
956 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
961 // find all belonging host controllers
964 hc
= (struct PCIController
*) hu
->hu_Controllers
.lh_Head
;
965 while(hc
->hc_Node
.ln_Succ
)
967 if(hc
->hc_HCIType
== HCITYPE_EHCI
)
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
))
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
;
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;
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
));
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
},
1060 KPRINTF(10, ("*** pciFreeUnit(%08lx) ***\n", hu
));
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
)
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
));
1094 uhwDelayMS(50, hu
, hd
);
1095 CONSTWRITEREG32_LE(hc
->hc_RegBase
, EHCI_USBCMD
, 1UL<<EHUS_INTTHRESHOLD
);
1098 uhwDelayMS(10, hu
, hd
);
1100 KPRINTF(20, ("Shutting down EHCI done.\n"));
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
)
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);
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
);
1132 uhwDelayMS(50, hu
, hd
);
1134 KPRINTF(20, ("Shutting down UHCI done.\n"));
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);
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
);
1158 uhwDelayMS(50, hu
, hd
);
1160 KPRINTF(20, ("Shutting down OHCI done.\n"));
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
;
1184 PCIXObtainBoard(hc
->hc_BoardObject
);
1185 hc
->hc_BoardAllocated
= FALSE
;
1186 PCIXSetBoardAttr(hc
->hc_BoardObject
, PCIXTAG_OWNER
, 0);
1187 PCIXReleaseBoard(hc
->hc_BoardObject
);
1189 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1194 /* /// "pciExpunge()" */
1195 void pciExpunge(struct PCIDevice
*hd
)
1197 struct PCIController
*hc
;
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
;
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
},
1228 OOP_ReleaseAttrBases(attrbases
);
1230 OOP_DisposeObject(hd
->hd_PCIHidd
);
1234 OOP_DisposeObject(hd
->hd_IRQHidd
);
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
));