Reverted r44762 (removal of USB3.0 and HC driver separation work).
[AROS.git] / rom / usb / pciusbhc / ehci / pciehci_hci.c
blob581c37a2a61b793b66020119f97d1f8b03a1ecdd
1 /*
2 Copyright © 2011, The AROS Development Team. All rights reserved
3 $Id$
4 */
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;
21 if(!eqh) {
22 // out of QHs!
23 KPRINTF(20, ("Out of QHs!\n"));
24 return NULL;
27 ehc->ehc_EhciQHPool = (struct EhciQH *) eqh->eqh_Succ;
28 return(eqh);
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;
39 if(!etd) {
40 // out of TDs!
41 KPRINTF(20, ("Out of TDs!\n"));
42 return NULL;
45 ehc->ehc_EhciTDPool = (struct EhciTD *) etd->etd_Succ;
46 return(etd);
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)) {
55 AROS_USERFUNC_INIT
57 CONSTWRITEREG32_LE(ehc->ehc_opregbase, EHCI_USBCMD, EHUF_HCRESET|(1UL<<EHUS_INTTHRESHOLD)); /* Resets the controller */
59 AROS_USERFUNC_EXIT
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);
68 SYNC;
70 eqh->eqh_Succ->eqh_Pred = eqh->eqh_Pred;
71 eqh->eqh_Pred->eqh_Succ = eqh->eqh_Succ;
72 SYNC;
74 // need to wait until an async schedule rollover before freeing these
75 Disable();
76 eqh->eqh_Succ = ehc->ehc_EhciAsyncFreeQH;
77 ehc->ehc_EhciAsyncFreeQH = eqh;
78 // activate doorbell
79 WRITEREG32_LE(ehc->ehc_opregbase, EHCI_USBCMD, ehc->ehc_EhciUsbCmd|EHUF_ASYNCDOORBELL);
80 Enable();
83 void ehciFreePeriodicContext(struct ehc_controller *ehc, struct EhciQH *eqh) {
85 struct EhciTD *etd;
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);
92 SYNC;
94 eqh->eqh_Succ->eqh_Pred = eqh->eqh_Pred;
95 eqh->eqh_Pred->eqh_Succ = eqh->eqh_Succ;
96 SYNC;
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);
107 Enable();
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;
117 while(nextetd) {
118 KPRINTF(1, ("FreeTD %08lx\n", nextetd));
119 etd = nextetd;
120 nextetd = (struct EhciTD *) etd->etd_Succ;
121 ehciFreeTD(ehc, etd);
124 ehciFreeQH(ehc, eqh);
127 void ehciUpdateIntTree(struct ehc_controller *ehc) {
129 struct EhciQH *eqh;
130 struct EhciQH *predeqh;
131 struct EhciQH *lastusedeqh;
132 UWORD cnt;
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);
143 predeqh = eqh;
147 BOOL ehciInit(struct ehc_controller *ehc, struct ehu_unit *ehu) {