2 Copyright © 2011, The AROS Development Team. All rights reserved
6 #include LC_LIBDEFS_FILE
8 #include <devices/usb_hub.h>
10 #include "pciehci_hci.h"
11 #include "pciehci_uhw.h"
13 APTR
pciGetPhysical(struct ehc_controller
*ehc
, APTR virtaddr
) {
14 //struct PCIDevice *hd = hc->hc_Device;
15 return(HIDD_PCIDriver_CPUtoPCI(ehc
->ehc_pcidriverobject
, virtaddr
));
18 static inline struct EhciQH
* ehciAllocQH(struct ehc_controller
*ehc
) {
19 struct EhciQH
*eqh
= ehc
->ehc_EhciQHPool
;
23 KPRINTF(20, ("Out of QHs!\n"));
27 ehc
->ehc_EhciQHPool
= (struct EhciQH
*) eqh
->eqh_Succ
;
31 static inline void ehciFreeQH(struct ehc_controller
*ehc
, struct EhciQH
*eqh
) {
32 eqh
->eqh_Succ
= ehc
->ehc_EhciQHPool
;
33 ehc
->ehc_EhciQHPool
= eqh
;
36 static inline struct EhciTD
* ehciAllocTD(struct ehc_controller
*ehc
) {
37 struct EhciTD
*etd
= ehc
->ehc_EhciTDPool
;
41 KPRINTF(20, ("Out of TDs!\n"));
45 ehc
->ehc_EhciTDPool
= (struct EhciTD
*) etd
->etd_Succ
;
49 static inline void ehciFreeTD(struct ehc_controller
*ehc
, struct EhciTD
*etd
) {
50 etd
->etd_Succ
= ehc
->ehc_EhciTDPool
;
51 ehc
->ehc_EhciTDPool
= etd
;
54 static AROS_UFH3(void, ehciResetHandler
, AROS_UFHA(struct ehc_controller
*, ehc
, A1
), AROS_UFHA(APTR
, unused
, A5
), AROS_UFHA(struct ExecBase
*, SysBase
, A6
)) {
57 CONSTWRITEREG32_LE(ehc
->ehc_opregbase
, EHCI_USBCMD
, EHUF_HCRESET
|(1UL<<EHUS_INTTHRESHOLD
)); /* Resets the controller */
62 void ehciFreeAsyncContext(struct ehc_controller
*ehc
, struct EhciQH
*eqh
) {
64 KPRINTF(5, ("Unlinking AsyncContext %08lx\n", eqh
));
65 // unlink from schedule
66 eqh
->eqh_Pred
->eqh_NextQH
= eqh
->eqh_Succ
->eqh_Self
;
67 CacheClearE(&eqh
->eqh_Pred
->eqh_NextQH
, 32, CACRF_ClearD
);
70 eqh
->eqh_Succ
->eqh_Pred
= eqh
->eqh_Pred
;
71 eqh
->eqh_Pred
->eqh_Succ
= eqh
->eqh_Succ
;
74 // need to wait until an async schedule rollover before freeing these
76 eqh
->eqh_Succ
= ehc
->ehc_EhciAsyncFreeQH
;
77 ehc
->ehc_EhciAsyncFreeQH
= eqh
;
79 WRITEREG32_LE(ehc
->ehc_opregbase
, EHCI_USBCMD
, ehc
->ehc_EhciUsbCmd
|EHUF_ASYNCDOORBELL
);
83 void ehciFreePeriodicContext(struct ehc_controller
*ehc
, struct EhciQH
*eqh
) {
86 struct EhciTD
*nextetd
;
88 KPRINTF(5, ("Unlinking PeriodicContext %08lx\n", eqh
));
89 // unlink from schedule
90 eqh
->eqh_Pred
->eqh_NextQH
= eqh
->eqh_Succ
->eqh_Self
;
91 CacheClearE(&eqh
->eqh_Pred
->eqh_NextQH
, 32, CACRF_ClearD
);
94 eqh
->eqh_Succ
->eqh_Pred
= eqh
->eqh_Pred
;
95 eqh
->eqh_Pred
->eqh_Succ
= eqh
->eqh_Succ
;
98 Disable(); // avoid race condition with interrupt
99 nextetd
= eqh
->eqh_FirstTD
;
100 while((etd
= nextetd
))
102 KPRINTF(1, ("FreeTD %08lx\n", nextetd
));
103 nextetd
= etd
->etd_Succ
;
104 ehciFreeTD(ehc
, etd
);
106 ehciFreeQH(ehc
, eqh
);
110 void ehciFreeQHandTDs(struct ehc_controller
*ehc
, struct EhciQH
*eqh
) {
112 struct EhciTD
*etd
= NULL
;
113 struct EhciTD
*nextetd
;
115 KPRINTF(5, ("Unlinking QContext %08lx\n", eqh
));
116 nextetd
= eqh
->eqh_FirstTD
;
118 KPRINTF(1, ("FreeTD %08lx\n", nextetd
));
120 nextetd
= (struct EhciTD
*) etd
->etd_Succ
;
121 ehciFreeTD(ehc
, etd
);
124 ehciFreeQH(ehc
, eqh
);
127 void ehciUpdateIntTree(struct ehc_controller
*ehc
) {
130 struct EhciQH
*predeqh
;
131 struct EhciQH
*lastusedeqh
;
134 // optimize linkage between queue heads
135 predeqh
= lastusedeqh
= ehc
->ehc_EhciTermQH
;
136 for(cnt
= 0; cnt
< 11; cnt
++) {
137 eqh
= ehc
->ehc_EhciIntQH
[cnt
];
138 if(eqh
->eqh_Succ
!= predeqh
) {
139 lastusedeqh
= eqh
->eqh_Succ
;
141 eqh
->eqh_NextQH
= lastusedeqh
->eqh_Self
;
142 CacheClearE(&eqh
->eqh_NextQH
, 32, CACRF_ClearD
);
147 BOOL
ehciInit(struct ehc_controller
*ehc
, struct ehu_unit
*ehu
) {