1*53ee8cc1Swenshuai.xi //<MStar Software>
2*53ee8cc1Swenshuai.xi //******************************************************************************
3*53ee8cc1Swenshuai.xi // MStar Software
4*53ee8cc1Swenshuai.xi // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5*53ee8cc1Swenshuai.xi // All software, firmware and related documentation herein ("MStar Software") are
6*53ee8cc1Swenshuai.xi // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7*53ee8cc1Swenshuai.xi // law, including, but not limited to, copyright law and international treaties.
8*53ee8cc1Swenshuai.xi // Any use, modification, reproduction, retransmission, or republication of all
9*53ee8cc1Swenshuai.xi // or part of MStar Software is expressly prohibited, unless prior written
10*53ee8cc1Swenshuai.xi // permission has been granted by MStar.
11*53ee8cc1Swenshuai.xi //
12*53ee8cc1Swenshuai.xi // By accessing, browsing and/or using MStar Software, you acknowledge that you
13*53ee8cc1Swenshuai.xi // have read, understood, and agree, to be bound by below terms ("Terms") and to
14*53ee8cc1Swenshuai.xi // comply with all applicable laws and regulations:
15*53ee8cc1Swenshuai.xi //
16*53ee8cc1Swenshuai.xi // 1. MStar shall retain any and all right, ownership and interest to MStar
17*53ee8cc1Swenshuai.xi // Software and any modification/derivatives thereof.
18*53ee8cc1Swenshuai.xi // No right, ownership, or interest to MStar Software and any
19*53ee8cc1Swenshuai.xi // modification/derivatives thereof is transferred to you under Terms.
20*53ee8cc1Swenshuai.xi //
21*53ee8cc1Swenshuai.xi // 2. You understand that MStar Software might include, incorporate or be
22*53ee8cc1Swenshuai.xi // supplied together with third party`s software and the use of MStar
23*53ee8cc1Swenshuai.xi // Software may require additional licenses from third parties.
24*53ee8cc1Swenshuai.xi // Therefore, you hereby agree it is your sole responsibility to separately
25*53ee8cc1Swenshuai.xi // obtain any and all third party right and license necessary for your use of
26*53ee8cc1Swenshuai.xi // such third party`s software.
27*53ee8cc1Swenshuai.xi //
28*53ee8cc1Swenshuai.xi // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29*53ee8cc1Swenshuai.xi // MStar`s confidential information and you agree to keep MStar`s
30*53ee8cc1Swenshuai.xi // confidential information in strictest confidence and not disclose to any
31*53ee8cc1Swenshuai.xi // third party.
32*53ee8cc1Swenshuai.xi //
33*53ee8cc1Swenshuai.xi // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34*53ee8cc1Swenshuai.xi // kind. Any warranties are hereby expressly disclaimed by MStar, including
35*53ee8cc1Swenshuai.xi // without limitation, any warranties of merchantability, non-infringement of
36*53ee8cc1Swenshuai.xi // intellectual property rights, fitness for a particular purpose, error free
37*53ee8cc1Swenshuai.xi // and in conformity with any international standard. You agree to waive any
38*53ee8cc1Swenshuai.xi // claim against MStar for any loss, damage, cost or expense that you may
39*53ee8cc1Swenshuai.xi // incur related to your use of MStar Software.
40*53ee8cc1Swenshuai.xi // In no event shall MStar be liable for any direct, indirect, incidental or
41*53ee8cc1Swenshuai.xi // consequential damages, including without limitation, lost of profit or
42*53ee8cc1Swenshuai.xi // revenues, lost or damage of data, and unauthorized system use.
43*53ee8cc1Swenshuai.xi // You agree that this Section 4 shall still apply without being affected
44*53ee8cc1Swenshuai.xi // even if MStar Software has been modified by MStar in accordance with your
45*53ee8cc1Swenshuai.xi // request or instruction for your use, except otherwise agreed by both
46*53ee8cc1Swenshuai.xi // parties in writing.
47*53ee8cc1Swenshuai.xi //
48*53ee8cc1Swenshuai.xi // 5. If requested, MStar may from time to time provide technical supports or
49*53ee8cc1Swenshuai.xi // services in relation with MStar Software to you for your use of
50*53ee8cc1Swenshuai.xi // MStar Software in conjunction with your or your customer`s product
51*53ee8cc1Swenshuai.xi // ("Services").
52*53ee8cc1Swenshuai.xi // You understand and agree that, except otherwise agreed by both parties in
53*53ee8cc1Swenshuai.xi // writing, Services are provided on an "AS IS" basis and the warranty
54*53ee8cc1Swenshuai.xi // disclaimer set forth in Section 4 above shall apply.
55*53ee8cc1Swenshuai.xi //
56*53ee8cc1Swenshuai.xi // 6. Nothing contained herein shall be construed as by implication, estoppels
57*53ee8cc1Swenshuai.xi // or otherwise:
58*53ee8cc1Swenshuai.xi // (a) conferring any license or right to use MStar name, trademark, service
59*53ee8cc1Swenshuai.xi // mark, symbol or any other identification;
60*53ee8cc1Swenshuai.xi // (b) obligating MStar or any of its affiliates to furnish any person,
61*53ee8cc1Swenshuai.xi // including without limitation, you and your customers, any assistance
62*53ee8cc1Swenshuai.xi // of any kind whatsoever, or any information; or
63*53ee8cc1Swenshuai.xi // (c) conferring any license or right under any intellectual property right.
64*53ee8cc1Swenshuai.xi //
65*53ee8cc1Swenshuai.xi // 7. These terms shall be governed by and construed in accordance with the laws
66*53ee8cc1Swenshuai.xi // of Taiwan, R.O.C., excluding its conflict of law rules.
67*53ee8cc1Swenshuai.xi // Any and all dispute arising out hereof or related hereto shall be finally
68*53ee8cc1Swenshuai.xi // settled by arbitration referred to the Chinese Arbitration Association,
69*53ee8cc1Swenshuai.xi // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70*53ee8cc1Swenshuai.xi // Rules of the Association by three (3) arbitrators appointed in accordance
71*53ee8cc1Swenshuai.xi // with the said Rules.
72*53ee8cc1Swenshuai.xi // The place of arbitration shall be in Taipei, Taiwan and the language shall
73*53ee8cc1Swenshuai.xi // be English.
74*53ee8cc1Swenshuai.xi // The arbitration award shall be final and binding to both parties.
75*53ee8cc1Swenshuai.xi //
76*53ee8cc1Swenshuai.xi //******************************************************************************
77*53ee8cc1Swenshuai.xi //<MStar Software>
78*53ee8cc1Swenshuai.xi
79*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
80*53ee8cc1Swenshuai.xi
81*53ee8cc1Swenshuai.xi int ehci_get_frame (struct usb_hcd *hcd);
82*53ee8cc1Swenshuai.xi
83*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
84*53ee8cc1Swenshuai.xi
85*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
86*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
87*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
88*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
89*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
90*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
91*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
92*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
93*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
94*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
95*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
96*53ee8cc1Swenshuai.xi
97*53ee8cc1Swenshuai.xi static union ehci_shadow *
periodic_next_shadow(union ehci_shadow * periodic,int tag)98*53ee8cc1Swenshuai.xi periodic_next_shadow (union ehci_shadow *periodic, int tag)
99*53ee8cc1Swenshuai.xi {
100*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
101*53ee8cc1Swenshuai.xi switch (tag) {
102*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
103*53ee8cc1Swenshuai.xi case Q_TYPE_QH:
104*53ee8cc1Swenshuai.xi return &periodic->qh->qh_next;
105*53ee8cc1Swenshuai.xi #ifdef have_fstn
106*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
107*53ee8cc1Swenshuai.xi case Q_TYPE_FSTN:
108*53ee8cc1Swenshuai.xi return &periodic->fstn->fstn_next;
109*53ee8cc1Swenshuai.xi #endif
110*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
111*53ee8cc1Swenshuai.xi case Q_TYPE_ITD:
112*53ee8cc1Swenshuai.xi return &periodic->itd->itd_next;
113*53ee8cc1Swenshuai.xi #ifdef have_split_iso
114*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
115*53ee8cc1Swenshuai.xi case Q_TYPE_SITD:
116*53ee8cc1Swenshuai.xi return &periodic->sitd->sitd_next;
117*53ee8cc1Swenshuai.xi #endif
118*53ee8cc1Swenshuai.xi }
119*53ee8cc1Swenshuai.xi dbg ("[periodic_next_shadow] BAD shadow %p tag %d", periodic->ptr, tag);
120*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
121*53ee8cc1Swenshuai.xi return 0;
122*53ee8cc1Swenshuai.xi }
123*53ee8cc1Swenshuai.xi
124*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
periodic_unlink(struct ehci_hcd * ehci,U32 frame,void * ptr)125*53ee8cc1Swenshuai.xi static int periodic_unlink (struct ehci_hcd *ehci, U32 frame, void *ptr)
126*53ee8cc1Swenshuai.xi {
127*53ee8cc1Swenshuai.xi union ehci_shadow *prev_p = &ehci->pshadow [frame];
128*53ee8cc1Swenshuai.xi U32 *hw_p = &ehci->periodic [frame];
129*53ee8cc1Swenshuai.xi union ehci_shadow here = *prev_p;
130*53ee8cc1Swenshuai.xi union ehci_shadow *next_p1;
131*53ee8cc1Swenshuai.xi
132*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
133*53ee8cc1Swenshuai.xi while (here.ptr && here.ptr != ptr) {
134*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
135*53ee8cc1Swenshuai.xi prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
136*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
137*53ee8cc1Swenshuai.xi hw_p = &here.qh->hw_next;
138*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
139*53ee8cc1Swenshuai.xi here = *prev_p;
140*53ee8cc1Swenshuai.xi }
141*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
142*53ee8cc1Swenshuai.xi if (!here.ptr) {
143*53ee8cc1Swenshuai.xi dbg ("[periodic_unlink] entry %p no longer on frame [%d]", ptr, frame);
144*53ee8cc1Swenshuai.xi return 0;
145*53ee8cc1Swenshuai.xi }
146*53ee8cc1Swenshuai.xi // vdbg ("periodic unlink %p from frame %d", ptr, frame);
147*53ee8cc1Swenshuai.xi
148*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
149*53ee8cc1Swenshuai.xi next_p1 = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
150*53ee8cc1Swenshuai.xi *hw_p = here.qh->hw_next;
151*53ee8cc1Swenshuai.xi
152*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
153*53ee8cc1Swenshuai.xi *prev_p = *next_p1;
154*53ee8cc1Swenshuai.xi next_p1->ptr = 0;
155*53ee8cc1Swenshuai.xi
156*53ee8cc1Swenshuai.xi return 1;
157*53ee8cc1Swenshuai.xi }
158*53ee8cc1Swenshuai.xi
159*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
160*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
161*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
162*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
163*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
164*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
165*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
166*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
167*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
168*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
169*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
170*53ee8cc1Swenshuai.xi
171*53ee8cc1Swenshuai.xi static U16
periodic_usecs(struct ehci_hcd * ehci,U32 frame,U32 uframe)172*53ee8cc1Swenshuai.xi periodic_usecs (struct ehci_hcd *ehci, U32 frame, U32 uframe)
173*53ee8cc1Swenshuai.xi {
174*53ee8cc1Swenshuai.xi U32 *hw_p = &ehci->periodic [frame];
175*53ee8cc1Swenshuai.xi union ehci_shadow *q = &ehci->pshadow [frame];
176*53ee8cc1Swenshuai.xi U32 usecs = 0;
177*53ee8cc1Swenshuai.xi
178*53ee8cc1Swenshuai.xi while (q->ptr) {
179*53ee8cc1Swenshuai.xi switch (Q_NEXT_TYPE (*hw_p)) {
180*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
181*53ee8cc1Swenshuai.xi case Q_TYPE_QH:
182*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
183*53ee8cc1Swenshuai.xi if (q->qh->hw_info2 & CPUToLE32 (1 << uframe))
184*53ee8cc1Swenshuai.xi usecs += q->qh->usecs;
185*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
186*53ee8cc1Swenshuai.xi if (q->qh->hw_info2 & CPUToLE32 (1 << (8 + uframe)))
187*53ee8cc1Swenshuai.xi usecs += q->qh->c_usecs;
188*53ee8cc1Swenshuai.xi q = &q->qh->qh_next;
189*53ee8cc1Swenshuai.xi break;
190*53ee8cc1Swenshuai.xi #ifdef have_fstn
191*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
192*53ee8cc1Swenshuai.xi case Q_TYPE_FSTN:
193*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
194*53ee8cc1Swenshuai.xi if (q->fstn->hw_prev != EHCI_LIST_END) {
195*53ee8cc1Swenshuai.xi dbg ("not counting FSTN bandwidth yet ...%s","");
196*53ee8cc1Swenshuai.xi }
197*53ee8cc1Swenshuai.xi q = &q->fstn->fstn_next;
198*53ee8cc1Swenshuai.xi break;
199*53ee8cc1Swenshuai.xi #endif
200*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
201*53ee8cc1Swenshuai.xi case Q_TYPE_ITD:
202*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
203*53ee8cc1Swenshuai.xi if (q->itd->hw_transaction [uframe] != 0)
204*53ee8cc1Swenshuai.xi usecs += q->itd->usecs;
205*53ee8cc1Swenshuai.xi q = &q->itd->itd_next;
206*53ee8cc1Swenshuai.xi break;
207*53ee8cc1Swenshuai.xi #ifdef have_split_iso
208*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
209*53ee8cc1Swenshuai.xi case Q_TYPE_SITD:
210*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
211*53ee8cc1Swenshuai.xi temp = q->sitd->hw_fullspeed_ep &
212*53ee8cc1Swenshuai.xi CPUToLE32 (1 << 31);
213*53ee8cc1Swenshuai.xi
214*53ee8cc1Swenshuai.xi
215*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
216*53ee8cc1Swenshuai.xi if (q->sitd->hw_uframe & CPUToLE32 (1 << uframe)) {
217*53ee8cc1Swenshuai.xi if (temp)
218*53ee8cc1Swenshuai.xi usecs += HS_USECS (188);
219*53ee8cc1Swenshuai.xi else
220*53ee8cc1Swenshuai.xi usecs += HS_USECS (1);
221*53ee8cc1Swenshuai.xi }
222*53ee8cc1Swenshuai.xi
223*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
224*53ee8cc1Swenshuai.xi if (q->sitd->hw_uframe &
225*53ee8cc1Swenshuai.xi CPUToLE32 (1 << (8 + uframe))) {
226*53ee8cc1Swenshuai.xi if (temp)
227*53ee8cc1Swenshuai.xi usecs += HS_USECS (0);
228*53ee8cc1Swenshuai.xi else
229*53ee8cc1Swenshuai.xi usecs += HS_USECS (188);
230*53ee8cc1Swenshuai.xi }
231*53ee8cc1Swenshuai.xi q = &q->sitd->sitd_next;
232*53ee8cc1Swenshuai.xi break;
233*53ee8cc1Swenshuai.xi #endif /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
234*53ee8cc1Swenshuai.xi default:
235*53ee8cc1Swenshuai.xi BUG ();
236*53ee8cc1Swenshuai.xi }
237*53ee8cc1Swenshuai.xi }
238*53ee8cc1Swenshuai.xi #ifdef DEBUG
239*53ee8cc1Swenshuai.xi #ifndef CONFIG_FARADAY_FOTG200
240*53ee8cc1Swenshuai.xi if (usecs > 100)
241*53ee8cc1Swenshuai.xi err ("overallocated uframe %d, periodic is %d usecs",
242*53ee8cc1Swenshuai.xi frame * 8 + uframe, usecs);
243*53ee8cc1Swenshuai.xi #endif
244*53ee8cc1Swenshuai.xi #endif
245*53ee8cc1Swenshuai.xi return usecs;
246*53ee8cc1Swenshuai.xi }
247*53ee8cc1Swenshuai.xi
248*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
249*53ee8cc1Swenshuai.xi
250*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
251*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
252*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
253*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
254*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
255*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
256*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
257*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
258*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
259*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
260*53ee8cc1Swenshuai.xi
enable_periodic(struct ehci_hcd * ehci)261*53ee8cc1Swenshuai.xi static int enable_periodic (struct ehci_hcd *ehci)
262*53ee8cc1Swenshuai.xi {
263*53ee8cc1Swenshuai.xi U32 cmd;
264*53ee8cc1Swenshuai.xi int status;
265*53ee8cc1Swenshuai.xi
266*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
267*53ee8cc1Swenshuai.xi status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
268*53ee8cc1Swenshuai.xi if (status != 0) {
269*53ee8cc1Swenshuai.xi ehci->hcd.state = USB_STATE_HALT;
270*53ee8cc1Swenshuai.xi return status;
271*53ee8cc1Swenshuai.xi }
272*53ee8cc1Swenshuai.xi
273*53ee8cc1Swenshuai.xi cmd = ehci_readl ((U32)&ehci->regs->command) | CMD_PSE;
274*53ee8cc1Swenshuai.xi ehci_writel (cmd, (U32)&ehci->regs->command);
275*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
276*53ee8cc1Swenshuai.xi ehci->hcd.state = USB_STATE_RUNNING;
277*53ee8cc1Swenshuai.xi
278*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
279*53ee8cc1Swenshuai.xi ehci->next_uframe = ehci_readl ((U32)&ehci->regs->frame_index)
280*53ee8cc1Swenshuai.xi % (ehci->periodic_size << 3);
281*53ee8cc1Swenshuai.xi return 0;
282*53ee8cc1Swenshuai.xi }
283*53ee8cc1Swenshuai.xi
disable_periodic(struct ehci_hcd * ehci)284*53ee8cc1Swenshuai.xi static int disable_periodic (struct ehci_hcd *ehci)
285*53ee8cc1Swenshuai.xi {
286*53ee8cc1Swenshuai.xi U32 cmd;
287*53ee8cc1Swenshuai.xi int status;
288*53ee8cc1Swenshuai.xi
289*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
290*53ee8cc1Swenshuai.xi status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
291*53ee8cc1Swenshuai.xi if (status != 0) {
292*53ee8cc1Swenshuai.xi //ehci->hcd.state = USB_STATE_HALT; //Note, Fix me
293*53ee8cc1Swenshuai.xi return status;
294*53ee8cc1Swenshuai.xi }
295*53ee8cc1Swenshuai.xi
296*53ee8cc1Swenshuai.xi cmd = ehci_readl ((U32)&ehci->regs->command) & ~CMD_PSE;
297*53ee8cc1Swenshuai.xi ehci_writel (cmd, (U32)&ehci->regs->command);
298*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
299*53ee8cc1Swenshuai.xi
300*53ee8cc1Swenshuai.xi ehci->next_uframe = -1;
301*53ee8cc1Swenshuai.xi return 0;
302*53ee8cc1Swenshuai.xi }
303*53ee8cc1Swenshuai.xi
304*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
305*53ee8cc1Swenshuai.xi
306*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
307*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
308*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
309*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
310*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
311*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
312*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
313*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
314*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
315*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
316*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
317*53ee8cc1Swenshuai.xi
intr_deschedule(struct ehci_hcd * ehci,struct ehci_qh * qh1,int wait)318*53ee8cc1Swenshuai.xi static void intr_deschedule (
319*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
320*53ee8cc1Swenshuai.xi struct ehci_qh *qh1,
321*53ee8cc1Swenshuai.xi int wait
322*53ee8cc1Swenshuai.xi ) {
323*53ee8cc1Swenshuai.xi int status;
324*53ee8cc1Swenshuai.xi U32 frame = qh1->start;
325*53ee8cc1Swenshuai.xi
326*53ee8cc1Swenshuai.xi do {
327*53ee8cc1Swenshuai.xi periodic_unlink (ehci, frame, qh1);
328*53ee8cc1Swenshuai.xi qh_put (ehci, qh1);
329*53ee8cc1Swenshuai.xi frame += qh1->period;
330*53ee8cc1Swenshuai.xi } while (frame < ehci->periodic_size);
331*53ee8cc1Swenshuai.xi
332*53ee8cc1Swenshuai.xi qh1->qh_state = QH_STATE_UNLINK;
333*53ee8cc1Swenshuai.xi qh1->qh_next.ptr = 0;
334*53ee8cc1Swenshuai.xi ehci->periodic_sched--;
335*53ee8cc1Swenshuai.xi
336*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
337*53ee8cc1Swenshuai.xi if (!ehci->periodic_sched)
338*53ee8cc1Swenshuai.xi status = disable_periodic (ehci);
339*53ee8cc1Swenshuai.xi else {
340*53ee8cc1Swenshuai.xi status = 0;
341*53ee8cc1Swenshuai.xi vdbg ("periodic schedule still enabled%s%s","","");
342*53ee8cc1Swenshuai.xi }
343*53ee8cc1Swenshuai.xi
344*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
345*53ee8cc1Swenshuai.xi if (((ehci_get_frame (&ehci->hcd) - frame) % qh1->period) == 0) {
346*53ee8cc1Swenshuai.xi if (wait) {
347*53ee8cc1Swenshuai.xi udelay (125);
348*53ee8cc1Swenshuai.xi qh1->hw_next = EHCI_LIST_END;
349*53ee8cc1Swenshuai.xi } else {
350*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
351*53ee8cc1Swenshuai.xi vdbg ("intr_deschedule...%s%s","","");
352*53ee8cc1Swenshuai.xi }
353*53ee8cc1Swenshuai.xi } else
354*53ee8cc1Swenshuai.xi qh1->hw_next = EHCI_LIST_END;
355*53ee8cc1Swenshuai.xi
356*53ee8cc1Swenshuai.xi qh1->qh_state = QH_STATE_IDLE;
357*53ee8cc1Swenshuai.xi
358*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
359*53ee8cc1Swenshuai.xi hcd_to_bus (&ehci->hcd)->bandwidth_allocated -=
360*53ee8cc1Swenshuai.xi (qh1->usecs + qh1->c_usecs) / qh1->period;
361*53ee8cc1Swenshuai.xi
362*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
363*53ee8cc1Swenshuai.xi dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d",
364*53ee8cc1Swenshuai.xi qh1, qh1->period, frame,
365*53ee8cc1Swenshuai.xi atomic_read(&qh1->refcount), ehci->periodic_sched);
366*53ee8cc1Swenshuai.xi }
367*53ee8cc1Swenshuai.xi
check_period(struct ehci_hcd * ehci,U32 frame,U32 uframe,U32 period,U32 usecs)368*53ee8cc1Swenshuai.xi static int check_period (
369*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
370*53ee8cc1Swenshuai.xi U32 frame,
371*53ee8cc1Swenshuai.xi U32 uframe,
372*53ee8cc1Swenshuai.xi U32 period,
373*53ee8cc1Swenshuai.xi U32 usecs
374*53ee8cc1Swenshuai.xi ) {
375*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
376*53ee8cc1Swenshuai.xi if (uframe >= 8)
377*53ee8cc1Swenshuai.xi return 0;
378*53ee8cc1Swenshuai.xi
379*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
380*53ee8cc1Swenshuai.xi #ifndef CONFIG_FARADAY_FOTG200
381*53ee8cc1Swenshuai.xi usecs = 100 - usecs;
382*53ee8cc1Swenshuai.xi #else
383*53ee8cc1Swenshuai.xi if ( eCurURBSpeed == USB_SPEED_HIGH )
384*53ee8cc1Swenshuai.xi usecs = 100 - usecs;
385*53ee8cc1Swenshuai.xi else
386*53ee8cc1Swenshuai.xi usecs = 900 - usecs;
387*53ee8cc1Swenshuai.xi #endif
388*53ee8cc1Swenshuai.xi
389*53ee8cc1Swenshuai.xi do {
390*53ee8cc1Swenshuai.xi int claimed;
391*53ee8cc1Swenshuai.xi
392*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
393*53ee8cc1Swenshuai.xi if (ehci->pshadow [frame].ptr)
394*53ee8cc1Swenshuai.xi return 0;
395*53ee8cc1Swenshuai.xi
396*53ee8cc1Swenshuai.xi claimed = periodic_usecs (ehci, frame, uframe);
397*53ee8cc1Swenshuai.xi if ((U32)claimed > usecs)
398*53ee8cc1Swenshuai.xi return 0;
399*53ee8cc1Swenshuai.xi
400*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
401*53ee8cc1Swenshuai.xi } while ((frame += period) < ehci->periodic_size);
402*53ee8cc1Swenshuai.xi
403*53ee8cc1Swenshuai.xi // success!
404*53ee8cc1Swenshuai.xi return 1;
405*53ee8cc1Swenshuai.xi }
406*53ee8cc1Swenshuai.xi
check_intr_schedule(struct ehci_hcd * ehci,U32 frame,U32 uframe,const struct ehci_qh * qh,U32 * c_maskp)407*53ee8cc1Swenshuai.xi static int check_intr_schedule (
408*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
409*53ee8cc1Swenshuai.xi U32 frame,
410*53ee8cc1Swenshuai.xi U32 uframe,
411*53ee8cc1Swenshuai.xi const struct ehci_qh *qh,
412*53ee8cc1Swenshuai.xi U32 *c_maskp
413*53ee8cc1Swenshuai.xi )
414*53ee8cc1Swenshuai.xi {
415*53ee8cc1Swenshuai.xi int retval = -ENOSPC;
416*53ee8cc1Swenshuai.xi
417*53ee8cc1Swenshuai.xi if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
418*53ee8cc1Swenshuai.xi goto done;
419*53ee8cc1Swenshuai.xi #ifndef CONFIG_FARADAY_FOTG200
420*53ee8cc1Swenshuai.xi if (!qh->c_usecs) {
421*53ee8cc1Swenshuai.xi retval = 0;
422*53ee8cc1Swenshuai.xi *c_maskp = CPUToLE32 (0);
423*53ee8cc1Swenshuai.xi goto done;
424*53ee8cc1Swenshuai.xi }
425*53ee8cc1Swenshuai.xi #endif
426*53ee8cc1Swenshuai.xi
427*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
428*53ee8cc1Swenshuai.xi #ifndef CONFIG_FARADAY_FOTG200
429*53ee8cc1Swenshuai.xi if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
430*53ee8cc1Swenshuai.xi qh->period, qh->c_usecs))
431*53ee8cc1Swenshuai.xi goto done;
432*53ee8cc1Swenshuai.xi if (!check_period (ehci, frame, uframe + qh->gap_uf,
433*53ee8cc1Swenshuai.xi qh->period, qh->c_usecs))
434*53ee8cc1Swenshuai.xi goto done;
435*53ee8cc1Swenshuai.xi
436*53ee8cc1Swenshuai.xi *c_maskp = CPUToLE32 (0x03 << (8 + uframe + qh->gap_uf));
437*53ee8cc1Swenshuai.xi #endif
438*53ee8cc1Swenshuai.xi retval = 0;
439*53ee8cc1Swenshuai.xi done:
440*53ee8cc1Swenshuai.xi return retval;
441*53ee8cc1Swenshuai.xi }
442*53ee8cc1Swenshuai.xi
443*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
qh_schedule(struct ehci_hcd * ehci,struct ehci_qh * qh)444*53ee8cc1Swenshuai.xi static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
445*53ee8cc1Swenshuai.xi {
446*53ee8cc1Swenshuai.xi int status;
447*53ee8cc1Swenshuai.xi U32 uframe1;
448*53ee8cc1Swenshuai.xi U32 c_mask1;
449*53ee8cc1Swenshuai.xi U32 frame1;
450*53ee8cc1Swenshuai.xi
451*53ee8cc1Swenshuai.xi qh->hw_next = EHCI_LIST_END;
452*53ee8cc1Swenshuai.xi frame1 = qh->start;
453*53ee8cc1Swenshuai.xi
454*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
455*53ee8cc1Swenshuai.xi if (frame1 < qh->period) {
456*53ee8cc1Swenshuai.xi uframe1 = ffs (LE32ToCPU(qh->hw_info2) & 0x00ff);
457*53ee8cc1Swenshuai.xi status = check_intr_schedule (ehci, frame1, --uframe1,
458*53ee8cc1Swenshuai.xi qh, &c_mask1);
459*53ee8cc1Swenshuai.xi } else {
460*53ee8cc1Swenshuai.xi uframe1 = 0;
461*53ee8cc1Swenshuai.xi c_mask1 = 0;
462*53ee8cc1Swenshuai.xi status = -ENOSPC;
463*53ee8cc1Swenshuai.xi }
464*53ee8cc1Swenshuai.xi
465*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
466*53ee8cc1Swenshuai.xi if (status) {
467*53ee8cc1Swenshuai.xi frame1 = qh->period - 1;
468*53ee8cc1Swenshuai.xi do {
469*53ee8cc1Swenshuai.xi for (uframe1 = 0; uframe1 < 8; uframe1++) {
470*53ee8cc1Swenshuai.xi status = check_intr_schedule (ehci,
471*53ee8cc1Swenshuai.xi frame1, uframe1, qh,
472*53ee8cc1Swenshuai.xi &c_mask1);
473*53ee8cc1Swenshuai.xi if (status == 0)
474*53ee8cc1Swenshuai.xi break;
475*53ee8cc1Swenshuai.xi }
476*53ee8cc1Swenshuai.xi } while (status && frame1--);
477*53ee8cc1Swenshuai.xi if (status)
478*53ee8cc1Swenshuai.xi goto done;
479*53ee8cc1Swenshuai.xi qh->start = frame1;
480*53ee8cc1Swenshuai.xi
481*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
482*53ee8cc1Swenshuai.xi qh->hw_info2 &= ~0xffff;
483*53ee8cc1Swenshuai.xi qh->hw_info2 |= CPUToLE32 (1 << uframe1) | c_mask1;
484*53ee8cc1Swenshuai.xi } else
485*53ee8cc1Swenshuai.xi dbg ("reused previous qh %p schedule", qh);
486*53ee8cc1Swenshuai.xi
487*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
488*53ee8cc1Swenshuai.xi qh->qh_state = QH_STATE_LINKED;
489*53ee8cc1Swenshuai.xi dbg ("[qh_schedule] scheduled qh %p usecs %d/%d period %d.0 starting %d.%d (gap %d)",
490*53ee8cc1Swenshuai.xi qh, qh->usecs, qh->c_usecs,
491*53ee8cc1Swenshuai.xi qh->period, frame1, uframe1, qh->gap_uf);
492*53ee8cc1Swenshuai.xi do {
493*53ee8cc1Swenshuai.xi if (unlikely (ehci->pshadow [frame1].ptr != 0)) {
494*53ee8cc1Swenshuai.xi
495*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
496*53ee8cc1Swenshuai.xi
497*53ee8cc1Swenshuai.xi BUG ();
498*53ee8cc1Swenshuai.xi } else {
499*53ee8cc1Swenshuai.xi ehci->pshadow [frame1].qh = qh_get (qh);
500*53ee8cc1Swenshuai.xi ehci->periodic [frame1] =
501*53ee8cc1Swenshuai.xi QH_NEXT (qh->qh_dma);
502*53ee8cc1Swenshuai.xi }
503*53ee8cc1Swenshuai.xi wmb ();
504*53ee8cc1Swenshuai.xi frame1 += qh->period;
505*53ee8cc1Swenshuai.xi } while (frame1 < ehci->periodic_size);
506*53ee8cc1Swenshuai.xi
507*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
508*53ee8cc1Swenshuai.xi hcd_to_bus (&ehci->hcd)->bandwidth_allocated +=
509*53ee8cc1Swenshuai.xi (qh->usecs + qh->c_usecs) / qh->period;
510*53ee8cc1Swenshuai.xi
511*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
512*53ee8cc1Swenshuai.xi if (!ehci->periodic_sched++)
513*53ee8cc1Swenshuai.xi status = enable_periodic (ehci);
514*53ee8cc1Swenshuai.xi done:
515*53ee8cc1Swenshuai.xi return status;
516*53ee8cc1Swenshuai.xi }
517*53ee8cc1Swenshuai.xi
518*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
519*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
520*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
521*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
522*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
523*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
524*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
525*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
526*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
527*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
528*53ee8cc1Swenshuai.xi
intr_submit(struct ehci_hcd * ehci,struct urb * urb,struct list_head * qtd_list,int mem_flags)529*53ee8cc1Swenshuai.xi static int intr_submit (
530*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
531*53ee8cc1Swenshuai.xi struct urb *urb,
532*53ee8cc1Swenshuai.xi struct list_head *qtd_list,
533*53ee8cc1Swenshuai.xi int mem_flags
534*53ee8cc1Swenshuai.xi ) {
535*53ee8cc1Swenshuai.xi U32 epnum1;
536*53ee8cc1Swenshuai.xi U32 flags;
537*53ee8cc1Swenshuai.xi struct ehci_qh *qh1;
538*53ee8cc1Swenshuai.xi struct hcd_dev *dev;
539*53ee8cc1Swenshuai.xi int is_input;
540*53ee8cc1Swenshuai.xi int status = 0;
541*53ee8cc1Swenshuai.xi struct list_head empty;
542*53ee8cc1Swenshuai.xi
543*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
544*53ee8cc1Swenshuai.xi epnum1 = usb_pipeendpoint (urb->pipe);
545*53ee8cc1Swenshuai.xi is_input = usb_pipein (urb->pipe);
546*53ee8cc1Swenshuai.xi if (is_input)
547*53ee8cc1Swenshuai.xi epnum1 |= 0x10;
548*53ee8cc1Swenshuai.xi
549*53ee8cc1Swenshuai.xi spin_lock_irqsave (&ehci->lock, flags);
550*53ee8cc1Swenshuai.xi dev = (struct hcd_dev *)urb->dev->hcpriv;
551*53ee8cc1Swenshuai.xi
552*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
553*53ee8cc1Swenshuai.xi INIT_LIST_HEAD (&empty);
554*53ee8cc1Swenshuai.xi qh1 = qh_append_tds (ehci, urb, &empty, epnum1, &dev->ep [epnum1]);
555*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
556*53ee8cc1Swenshuai.xi if (qh1 == 0) {
557*53ee8cc1Swenshuai.xi status = -ENOMEM;
558*53ee8cc1Swenshuai.xi goto done;
559*53ee8cc1Swenshuai.xi }
560*53ee8cc1Swenshuai.xi if (qh1->qh_state == QH_STATE_IDLE) {
561*53ee8cc1Swenshuai.xi if ((status = qh_schedule (ehci, qh1)) != 0)
562*53ee8cc1Swenshuai.xi goto done;
563*53ee8cc1Swenshuai.xi }
564*53ee8cc1Swenshuai.xi
565*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
566*53ee8cc1Swenshuai.xi qh1 = qh_append_tds (ehci, urb, qtd_list, epnum1, &dev->ep [epnum1]);
567*53ee8cc1Swenshuai.xi
568*53ee8cc1Swenshuai.xi
569*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
570*53ee8cc1Swenshuai.xi hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++;
571*53ee8cc1Swenshuai.xi
572*53ee8cc1Swenshuai.xi //#ifdef ENABLE_PIPE_FLUSH
573*53ee8cc1Swenshuai.xi Chip_Flush_Memory();
574*53ee8cc1Swenshuai.xi //#endif
575*53ee8cc1Swenshuai.xi
576*53ee8cc1Swenshuai.xi done:
577*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
578*53ee8cc1Swenshuai.xi spin_unlock_irqrestore (&ehci->lock, flags);
579*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
580*53ee8cc1Swenshuai.xi if (status)
581*53ee8cc1Swenshuai.xi qtd_list_free (ehci, urb, qtd_list);
582*53ee8cc1Swenshuai.xi
583*53ee8cc1Swenshuai.xi return status;
584*53ee8cc1Swenshuai.xi }
585*53ee8cc1Swenshuai.xi
586*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
587*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
588*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
589*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
590*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
591*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
592*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
593*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
594*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
595*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
596*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
597*53ee8cc1Swenshuai.xi
598*53ee8cc1Swenshuai.xi static U32
intr_complete(struct ehci_hcd * ehci,U32 frame,struct ehci_qh * qh,struct pt_regs * regs)599*53ee8cc1Swenshuai.xi intr_complete (
600*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
601*53ee8cc1Swenshuai.xi U32 frame,
602*53ee8cc1Swenshuai.xi struct ehci_qh *qh,
603*53ee8cc1Swenshuai.xi struct pt_regs *regs
604*53ee8cc1Swenshuai.xi ) {
605*53ee8cc1Swenshuai.xi U32 count;
606*53ee8cc1Swenshuai.xi
607*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
608*53ee8cc1Swenshuai.xi if (likely ((qh->hw_token & CPUToLE32 (QTD_STS_ACTIVE))
609*53ee8cc1Swenshuai.xi != 0))
610*53ee8cc1Swenshuai.xi return 0;
611*53ee8cc1Swenshuai.xi
612*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
613*53ee8cc1Swenshuai.xi if (unlikely (list_empty (&qh->qtd_list))) {
614*53ee8cc1Swenshuai.xi dbg ("[intr qh] %p no TDs?", qh);
615*53ee8cc1Swenshuai.xi return 0;
616*53ee8cc1Swenshuai.xi }
617*53ee8cc1Swenshuai.xi
618*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
619*53ee8cc1Swenshuai.xi count = qh_completions (ehci, qh, regs);
620*53ee8cc1Swenshuai.xi
621*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
622*53ee8cc1Swenshuai.xi if (unlikely (list_empty (&qh->qtd_list)))
623*53ee8cc1Swenshuai.xi intr_deschedule (ehci, qh, 0);
624*53ee8cc1Swenshuai.xi
625*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
626*53ee8cc1Swenshuai.xi return count;
627*53ee8cc1Swenshuai.xi }
628*53ee8cc1Swenshuai.xi
629*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
630*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
631*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
632*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
633*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
634*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
635*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
636*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
637*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
638*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
639*53ee8cc1Swenshuai.xi
640*53ee8cc1Swenshuai.xi #ifdef have_iso_itd
641*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
642*53ee8cc1Swenshuai.xi static void
itd_free_list(struct ehci_hcd * ehci,struct urb * urb)643*53ee8cc1Swenshuai.xi itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
644*53ee8cc1Swenshuai.xi {
645*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
646*53ee8cc1Swenshuai.xi struct ehci_itd *first_itd = (struct ehci_itd *) urb->hcpriv;
647*53ee8cc1Swenshuai.xi
648*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
649*53ee8cc1Swenshuai.xi while (!list_empty (&first_itd->itd_list)) {
650*53ee8cc1Swenshuai.xi struct ehci_itd *itd;
651*53ee8cc1Swenshuai.xi
652*53ee8cc1Swenshuai.xi itd = list_entry (first_itd->itd_list.next, struct ehci_itd, itd_list);
653*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
654*53ee8cc1Swenshuai.xi list_del (&itd->itd_list);
655*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
656*53ee8cc1Swenshuai.xi pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
657*53ee8cc1Swenshuai.xi }
658*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
659*53ee8cc1Swenshuai.xi pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma);
660*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
661*53ee8cc1Swenshuai.xi urb->hcpriv = 0;
662*53ee8cc1Swenshuai.xi }
663*53ee8cc1Swenshuai.xi
664*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
665*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
666*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
667*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
668*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
669*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
670*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
671*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
672*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
673*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
674*53ee8cc1Swenshuai.xi
675*53ee8cc1Swenshuai.xi static int
itd_fill(struct ehci_hcd * ehci,struct ehci_itd * itd,struct urb * urb,U32 index,dma_addr_t dma)676*53ee8cc1Swenshuai.xi itd_fill (
677*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
678*53ee8cc1Swenshuai.xi struct ehci_itd *itd,
679*53ee8cc1Swenshuai.xi struct urb *urb,
680*53ee8cc1Swenshuai.xi U32 index,
681*53ee8cc1Swenshuai.xi dma_addr_t dma
682*53ee8cc1Swenshuai.xi ) {
683*53ee8cc1Swenshuai.xi cyg_uint64 temp;
684*53ee8cc1Swenshuai.xi U32 buf1;
685*53ee8cc1Swenshuai.xi U32 i, epnum, maxp, multi;
686*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
687*53ee8cc1Swenshuai.xi int length;
688*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
689*53ee8cc1Swenshuai.xi int is_input;
690*53ee8cc1Swenshuai.xi
691*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
692*53ee8cc1Swenshuai.xi itd->hw_next = EHCI_LIST_END;
693*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
694*53ee8cc1Swenshuai.xi itd->urb = urb;
695*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
696*53ee8cc1Swenshuai.xi itd->index = index;
697*53ee8cc1Swenshuai.xi
698*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
699*53ee8cc1Swenshuai.xi length = urb->iso_frame_desc [index].length;
700*53ee8cc1Swenshuai.xi dma += urb->iso_frame_desc [index].offset;
701*53ee8cc1Swenshuai.xi temp = dma & ~0x0fff;
702*53ee8cc1Swenshuai.xi for (i = 0; i < 2; i++) {
703*53ee8cc1Swenshuai.xi itd->hw_bufp [i] = CPUToLE32 ((U32) temp);
704*53ee8cc1Swenshuai.xi itd->hw_bufp_hi [i] = CPUToLE32 ((U32)(temp >> 32));
705*53ee8cc1Swenshuai.xi temp += 0x1000;
706*53ee8cc1Swenshuai.xi }
707*53ee8cc1Swenshuai.xi itd->buf_dma = dma;
708*53ee8cc1Swenshuai.xi
709*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
710*53ee8cc1Swenshuai.xi epnum = usb_pipeendpoint (urb->pipe);
711*53ee8cc1Swenshuai.xi is_input = usb_pipein (urb->pipe);
712*53ee8cc1Swenshuai.xi if (is_input) {
713*53ee8cc1Swenshuai.xi maxp = urb->dev->epmaxpacketin [epnum];
714*53ee8cc1Swenshuai.xi buf1 = (1 << 11);
715*53ee8cc1Swenshuai.xi } else {
716*53ee8cc1Swenshuai.xi maxp = urb->dev->epmaxpacketout [epnum];
717*53ee8cc1Swenshuai.xi buf1 = 0;
718*53ee8cc1Swenshuai.xi }
719*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
720*53ee8cc1Swenshuai.xi buf1 |= (maxp & 0x03ff);
721*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
722*53ee8cc1Swenshuai.xi multi = 1;
723*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
724*53ee8cc1Swenshuai.xi multi += (maxp >> 11) & 0x03;
725*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
726*53ee8cc1Swenshuai.xi maxp &= 0x03ff;
727*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
728*53ee8cc1Swenshuai.xi maxp *= multi;
729*53ee8cc1Swenshuai.xi
730*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
731*53ee8cc1Swenshuai.xi if ( (length < 0) || (maxp < (U32) length) ) {
732*53ee8cc1Swenshuai.xi dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)",
733*53ee8cc1Swenshuai.xi length, maxp, urb, index,
734*53ee8cc1Swenshuai.xi urb->iso_frame_desc [index].length);
735*53ee8cc1Swenshuai.xi return -ENOSPC;
736*53ee8cc1Swenshuai.xi }
737*53ee8cc1Swenshuai.xi itd->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 1, length);
738*53ee8cc1Swenshuai.xi
739*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
740*53ee8cc1Swenshuai.xi itd->hw_bufp [0] |= CPUToLE32 ((epnum << 8) | urb->dev->devnum);
741*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
742*53ee8cc1Swenshuai.xi itd->hw_bufp [1] |= CPUToLE32 (buf1);
743*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
744*53ee8cc1Swenshuai.xi itd->hw_bufp [2] |= CPUToLE32 (multi);
745*53ee8cc1Swenshuai.xi
746*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
747*53ee8cc1Swenshuai.xi itd->transaction = EHCI_ISOC_ACTIVE;
748*53ee8cc1Swenshuai.xi itd->transaction |= dma & 0x0fff;
749*53ee8cc1Swenshuai.xi if ((index + 1) == (U32) urb->number_of_packets)
750*53ee8cc1Swenshuai.xi itd->transaction |= EHCI_ITD_IOC;
751*53ee8cc1Swenshuai.xi itd->transaction |= length << 16;
752*53ee8cc1Swenshuai.xi itd->transaction = CPUToLE32(itd->transaction);
753*53ee8cc1Swenshuai.xi
754*53ee8cc1Swenshuai.xi return 0;
755*53ee8cc1Swenshuai.xi }
756*53ee8cc1Swenshuai.xi
757*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
758*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
759*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
760*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
761*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
762*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
763*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
764*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
765*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
766*53ee8cc1Swenshuai.xi
767*53ee8cc1Swenshuai.xi static int
itd_urb_transaction(struct ehci_hcd * ehci,struct urb * urb,int mem_flags)768*53ee8cc1Swenshuai.xi itd_urb_transaction (
769*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
770*53ee8cc1Swenshuai.xi struct urb *urb,
771*53ee8cc1Swenshuai.xi int mem_flags
772*53ee8cc1Swenshuai.xi ) {
773*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
774*53ee8cc1Swenshuai.xi int frame_index;
775*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
776*53ee8cc1Swenshuai.xi struct ehci_itd *first_itd, *itd;
777*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
778*53ee8cc1Swenshuai.xi int status;
779*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
780*53ee8cc1Swenshuai.xi dma_addr_t itd_dma;
781*53ee8cc1Swenshuai.xi
782*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
783*53ee8cc1Swenshuai.xi for (frame_index = 0, first_itd = 0;
784*53ee8cc1Swenshuai.xi frame_index < urb->number_of_packets;
785*53ee8cc1Swenshuai.xi frame_index++) {
786*53ee8cc1Swenshuai.xi itd = (struct ehci_itd*) pci_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma);
787*53ee8cc1Swenshuai.xi if (!itd) {
788*53ee8cc1Swenshuai.xi status = -ENOMEM;
789*53ee8cc1Swenshuai.xi goto fail;
790*53ee8cc1Swenshuai.xi }
791*53ee8cc1Swenshuai.xi memset (itd, 0, sizeof *itd);
792*53ee8cc1Swenshuai.xi itd->itd_dma = itd_dma;
793*53ee8cc1Swenshuai.xi
794*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
795*53ee8cc1Swenshuai.xi status = itd_fill (ehci, itd, urb, frame_index,
796*53ee8cc1Swenshuai.xi urb->transfer_dma);
797*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
798*53ee8cc1Swenshuai.xi if (status != 0)
799*53ee8cc1Swenshuai.xi goto fail;
800*53ee8cc1Swenshuai.xi
801*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
802*53ee8cc1Swenshuai.xi if (first_itd)
803*53ee8cc1Swenshuai.xi list_add_tail (&itd->itd_list,
804*53ee8cc1Swenshuai.xi &first_itd->itd_list);
805*53ee8cc1Swenshuai.xi else {
806*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
807*53ee8cc1Swenshuai.xi INIT_LIST_HEAD (&itd->itd_list);
808*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
809*53ee8cc1Swenshuai.xi urb->hcpriv = first_itd = itd;
810*53ee8cc1Swenshuai.xi }
811*53ee8cc1Swenshuai.xi }
812*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
813*53ee8cc1Swenshuai.xi urb->error_count = 0;
814*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
815*53ee8cc1Swenshuai.xi return 0;
816*53ee8cc1Swenshuai.xi
817*53ee8cc1Swenshuai.xi fail:
818*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
819*53ee8cc1Swenshuai.xi if (urb->hcpriv)
820*53ee8cc1Swenshuai.xi itd_free_list (ehci, urb);
821*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
822*53ee8cc1Swenshuai.xi return status;
823*53ee8cc1Swenshuai.xi }
824*53ee8cc1Swenshuai.xi
825*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
826*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
827*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
828*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
829*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
830*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
831*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
832*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
833*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
834*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
835*53ee8cc1Swenshuai.xi
836*53ee8cc1Swenshuai.xi static inline void
itd_link(struct ehci_hcd * ehci,U32 frame,struct ehci_itd * itd)837*53ee8cc1Swenshuai.xi itd_link (struct ehci_hcd *ehci, U32 frame, struct ehci_itd *itd)
838*53ee8cc1Swenshuai.xi {
839*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
840*53ee8cc1Swenshuai.xi itd->itd_next = ehci->pshadow [frame];
841*53ee8cc1Swenshuai.xi itd->hw_next = ehci->periodic [frame];
842*53ee8cc1Swenshuai.xi ehci->pshadow [frame].itd = itd;
843*53ee8cc1Swenshuai.xi ehci->periodic [frame] = CPUToLE32 (itd->itd_dma) | Q_TYPE_ITD;
844*53ee8cc1Swenshuai.xi }
845*53ee8cc1Swenshuai.xi
846*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
get_iso_range(struct ehci_hcd * ehci,struct urb * urb,U32 * start,U32 * max,U32 mod)847*53ee8cc1Swenshuai.xi static int get_iso_range (
848*53ee8cc1Swenshuai.xi struct ehci_hcd *ehci,
849*53ee8cc1Swenshuai.xi struct urb *urb,
850*53ee8cc1Swenshuai.xi U32 *start,
851*53ee8cc1Swenshuai.xi U32 *max,
852*53ee8cc1Swenshuai.xi U32 mod
853*53ee8cc1Swenshuai.xi ) {
854*53ee8cc1Swenshuai.xi struct list_head *lh;
855*53ee8cc1Swenshuai.xi struct hcd_dev *dev = (struct hcd_dev*) urb->dev->hcpriv;
856*53ee8cc1Swenshuai.xi int last = -1;
857*53ee8cc1Swenshuai.xi U32 now, span, end;
858*53ee8cc1Swenshuai.xi
859*53ee8cc1Swenshuai.xi span = urb->interval * urb->number_of_packets;
860*53ee8cc1Swenshuai.xi
861*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
862*53ee8cc1Swenshuai.xi list_for_each (lh, &dev->urb_list) {
863*53ee8cc1Swenshuai.xi struct urb *u;
864*53ee8cc1Swenshuai.xi struct ehci_itd *itd;
865*53ee8cc1Swenshuai.xi U32 s;
866*53ee8cc1Swenshuai.xi
867*53ee8cc1Swenshuai.xi u = list_entry (lh, struct urb, urb_list);
868*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
869*53ee8cc1Swenshuai.xi if (u == urb || u->pipe != urb->pipe)
870*53ee8cc1Swenshuai.xi continue;
871*53ee8cc1Swenshuai.xi if (u->interval != urb->interval) {
872*53ee8cc1Swenshuai.xi dbg ("urb %p interval %d ... != %p interval %d",
873*53ee8cc1Swenshuai.xi u, u->interval, urb, urb->interval);
874*53ee8cc1Swenshuai.xi return -EINVAL;
875*53ee8cc1Swenshuai.xi }
876*53ee8cc1Swenshuai.xi
877*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
878*53ee8cc1Swenshuai.xi itd = (struct ehci_itd*) urb->hcpriv;
879*53ee8cc1Swenshuai.xi s = itd->uframe + u->interval * u->number_of_packets;
880*53ee8cc1Swenshuai.xi if (last < 0)
881*53ee8cc1Swenshuai.xi last = s;
882*53ee8cc1Swenshuai.xi else {
883*53ee8cc1Swenshuai.xi
884*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
885*53ee8cc1Swenshuai.xi dbg ("NYET: queue >2 URBs per ISO endpoint%s%s","","");
886*53ee8cc1Swenshuai.xi return -EDOM;
887*53ee8cc1Swenshuai.xi }
888*53ee8cc1Swenshuai.xi }
889*53ee8cc1Swenshuai.xi
890*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
891*53ee8cc1Swenshuai.xi now = ehci_readl ((U32)&ehci->regs->frame_index) + 1;
892*53ee8cc1Swenshuai.xi if (!ehci->periodic_sched)
893*53ee8cc1Swenshuai.xi now += 8;
894*53ee8cc1Swenshuai.xi now %= mod;
895*53ee8cc1Swenshuai.xi end = now + mod;
896*53ee8cc1Swenshuai.xi if (last < 0) {
897*53ee8cc1Swenshuai.xi *start = now + ehci->i_thresh + 1;
898*53ee8cc1Swenshuai.xi *max = end - span;
899*53ee8cc1Swenshuai.xi if (*max < *start + 1)
900*53ee8cc1Swenshuai.xi *max = *start + 1;
901*53ee8cc1Swenshuai.xi } else {
902*53ee8cc1Swenshuai.xi *start = last % mod;
903*53ee8cc1Swenshuai.xi *max = (last + 1) % mod;
904*53ee8cc1Swenshuai.xi }
905*53ee8cc1Swenshuai.xi
906*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
907*53ee8cc1Swenshuai.xi if (!(urb->transfer_flags & URB_ISO_ASAP)) {
908*53ee8cc1Swenshuai.xi U32 temp;
909*53ee8cc1Swenshuai.xi
910*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
911*53ee8cc1Swenshuai.xi urb->start_frame %= ehci->periodic_size;
912*53ee8cc1Swenshuai.xi temp = urb->start_frame << 3;
913*53ee8cc1Swenshuai.xi if (temp < *start)
914*53ee8cc1Swenshuai.xi temp += mod;
915*53ee8cc1Swenshuai.xi if (temp > *max)
916*53ee8cc1Swenshuai.xi return -EDOM;
917*53ee8cc1Swenshuai.xi
918*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
919*53ee8cc1Swenshuai.xi *start = urb->start_frame << 3;
920*53ee8cc1Swenshuai.xi temp += 8;
921*53ee8cc1Swenshuai.xi if (temp < *max)
922*53ee8cc1Swenshuai.xi *max = temp;
923*53ee8cc1Swenshuai.xi }
924*53ee8cc1Swenshuai.xi
925*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
926*53ee8cc1Swenshuai.xi
927*53ee8cc1Swenshuai.xi *max %= ehci->periodic_size;
928*53ee8cc1Swenshuai.xi if ((*start + span) < end)
929*53ee8cc1Swenshuai.xi return 0;
930*53ee8cc1Swenshuai.xi return -EFBIG;
931*53ee8cc1Swenshuai.xi }
932*53ee8cc1Swenshuai.xi
933*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
934*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
935*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
936*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
937*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
938*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
939*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
940*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
941*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
942*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
943*53ee8cc1Swenshuai.xi
944*53ee8cc1Swenshuai.xi static int
itd_schedule(struct ehci_hcd * ehci,struct urb * urb)945*53ee8cc1Swenshuai.xi itd_schedule (struct ehci_hcd *ehci, struct urb *urb)
946*53ee8cc1Swenshuai.xi {
947*53ee8cc1Swenshuai.xi U32 start, max, i;
948*53ee8cc1Swenshuai.xi int status;
949*53ee8cc1Swenshuai.xi U32 mod = ehci->periodic_size << 3;
950*53ee8cc1Swenshuai.xi
951*53ee8cc1Swenshuai.xi for (i = 0; i < (U32) urb->number_of_packets; i++) {
952*53ee8cc1Swenshuai.xi urb->iso_frame_desc [i].status = (U32) -EINPROGRESS;
953*53ee8cc1Swenshuai.xi urb->iso_frame_desc [i].actual_length = 0;
954*53ee8cc1Swenshuai.xi }
955*53ee8cc1Swenshuai.xi
956*53ee8cc1Swenshuai.xi if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0)
957*53ee8cc1Swenshuai.xi return status;
958*53ee8cc1Swenshuai.xi
959*53ee8cc1Swenshuai.xi do {
960*53ee8cc1Swenshuai.xi U32 uframe;
961*53ee8cc1Swenshuai.xi U32 usecs;
962*53ee8cc1Swenshuai.xi struct ehci_itd *itd;
963*53ee8cc1Swenshuai.xi
964*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
965*53ee8cc1Swenshuai.xi itd = (struct ehci_itd*) urb->hcpriv;
966*53ee8cc1Swenshuai.xi uframe = start;
967*53ee8cc1Swenshuai.xi for (i = 0, uframe = start;
968*53ee8cc1Swenshuai.xi i < (U32) urb->number_of_packets;
969*53ee8cc1Swenshuai.xi i++, uframe += urb->interval) {
970*53ee8cc1Swenshuai.xi uframe %= mod;
971*53ee8cc1Swenshuai.xi
972*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
973*53ee8cc1Swenshuai.xi if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
974*53ee8cc1Swenshuai.xi > (100 - itd->usecs)) {
975*53ee8cc1Swenshuai.xi itd = 0;
976*53ee8cc1Swenshuai.xi break;
977*53ee8cc1Swenshuai.xi }
978*53ee8cc1Swenshuai.xi itd = list_entry (itd->itd_list.next, struct ehci_itd, itd_list);
979*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
980*53ee8cc1Swenshuai.xi }
981*53ee8cc1Swenshuai.xi if (!itd)
982*53ee8cc1Swenshuai.xi continue;
983*53ee8cc1Swenshuai.xi
984*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
985*53ee8cc1Swenshuai.xi itd = (struct ehci_itd*) urb->hcpriv;
986*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
987*53ee8cc1Swenshuai.xi urb->start_frame = start >> 3;
988*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
989*53ee8cc1Swenshuai.xi vdbg ("[ISO] urb %p (%d packets period %d) starting %d.%d",
990*53ee8cc1Swenshuai.xi urb, urb->number_of_packets, urb->interval,
991*53ee8cc1Swenshuai.xi urb->start_frame, start & 0x7);
992*53ee8cc1Swenshuai.xi
993*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
994*53ee8cc1Swenshuai.xi for (i = 0, uframe = start, usecs = 0;
995*53ee8cc1Swenshuai.xi i < (U32) urb->number_of_packets;
996*53ee8cc1Swenshuai.xi i++, uframe += urb->interval) {
997*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
998*53ee8cc1Swenshuai.xi uframe %= mod;
999*53ee8cc1Swenshuai.xi
1000*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1001*53ee8cc1Swenshuai.xi itd->uframe = uframe;
1002*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1003*53ee8cc1Swenshuai.xi itd->hw_transaction [uframe & 0x07] = itd->transaction;
1004*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1005*53ee8cc1Swenshuai.xi itd_link (ehci, (uframe >> 3) % ehci->periodic_size,
1006*53ee8cc1Swenshuai.xi itd);
1007*53ee8cc1Swenshuai.xi wmb ();
1008*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1009*53ee8cc1Swenshuai.xi usecs += itd->usecs;
1010*53ee8cc1Swenshuai.xi
1011*53ee8cc1Swenshuai.xi itd = list_entry (itd->itd_list.next, struct ehci_itd, itd_list);
1012*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1013*53ee8cc1Swenshuai.xi }
1014*53ee8cc1Swenshuai.xi
1015*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1016*53ee8cc1Swenshuai.xi usecs /= urb->number_of_packets;
1017*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1018*53ee8cc1Swenshuai.xi usecs /= urb->interval;
1019*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1020*53ee8cc1Swenshuai.xi usecs >>= 3;
1021*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1022*53ee8cc1Swenshuai.xi if (usecs < 1)
1023*53ee8cc1Swenshuai.xi usecs = 1;
1024*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1025*53ee8cc1Swenshuai.xi usb_claim_bandwidth (urb->dev, urb, usecs, 1);
1026*53ee8cc1Swenshuai.xi
1027*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1028*53ee8cc1Swenshuai.xi if (!ehci->periodic_sched++) {
1029*53ee8cc1Swenshuai.xi if ((status = enable_periodic (ehci)) != 0) {
1030*53ee8cc1Swenshuai.xi err ("[itd_schedule], enable = %d", status);
1031*53ee8cc1Swenshuai.xi }
1032*53ee8cc1Swenshuai.xi }
1033*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1034*53ee8cc1Swenshuai.xi return 0;
1035*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1036*53ee8cc1Swenshuai.xi ++start;
1037*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1038*53ee8cc1Swenshuai.xi start %= mod;
1039*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1040*53ee8cc1Swenshuai.xi } while ((start) != max);
1041*53ee8cc1Swenshuai.xi
1042*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1043*53ee8cc1Swenshuai.xi dbg ("[urb] %p, CAN'T SCHEDULE", urb);
1044*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1045*53ee8cc1Swenshuai.xi return -ENOSPC;
1046*53ee8cc1Swenshuai.xi }
1047*53ee8cc1Swenshuai.xi
1048*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
1049*53ee8cc1Swenshuai.xi
1050*53ee8cc1Swenshuai.xi #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
1051*53ee8cc1Swenshuai.xi
1052*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
1053*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1054*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1055*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1056*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1057*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1058*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1059*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1060*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1061*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1062*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1063*53ee8cc1Swenshuai.xi
itd_submit(struct ehci_hcd * ehci,struct urb * urb,int mem_flags)1064*53ee8cc1Swenshuai.xi static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
1065*53ee8cc1Swenshuai.xi {
1066*53ee8cc1Swenshuai.xi int status;
1067*53ee8cc1Swenshuai.xi U32 flags;
1068*53ee8cc1Swenshuai.xi
1069*53ee8cc1Swenshuai.xi dbg ("itd_submit urb %p", urb);
1070*53ee8cc1Swenshuai.xi
1071*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1072*53ee8cc1Swenshuai.xi status = itd_urb_transaction (ehci, urb, mem_flags);
1073*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1074*53ee8cc1Swenshuai.xi if (status < 0)
1075*53ee8cc1Swenshuai.xi return status;
1076*53ee8cc1Swenshuai.xi
1077*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1078*53ee8cc1Swenshuai.xi spin_lock_irqsave (&ehci->lock, flags);
1079*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1080*53ee8cc1Swenshuai.xi status = itd_schedule (ehci, urb);
1081*53ee8cc1Swenshuai.xi
1082*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1083*53ee8cc1Swenshuai.xi Chip_Flush_Memory();
1084*53ee8cc1Swenshuai.xi
1085*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1086*53ee8cc1Swenshuai.xi spin_unlock_irqrestore (&ehci->lock, flags);
1087*53ee8cc1Swenshuai.xi if (status < 0)
1088*53ee8cc1Swenshuai.xi itd_free_list (ehci, urb);
1089*53ee8cc1Swenshuai.xi
1090*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1091*53ee8cc1Swenshuai.xi return status;
1092*53ee8cc1Swenshuai.xi }
1093*53ee8cc1Swenshuai.xi #endif
1094*53ee8cc1Swenshuai.xi
1095*53ee8cc1Swenshuai.xi #ifdef have_split_iso
1096*53ee8cc1Swenshuai.xi
1097*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
1098*53ee8cc1Swenshuai.xi
1099*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1100*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1101*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1102*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1103*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1104*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1105*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1106*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1107*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1108*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1109*53ee8cc1Swenshuai.xi
1110*53ee8cc1Swenshuai.xi #endif
1111*53ee8cc1Swenshuai.xi
1112*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
1113*53ee8cc1Swenshuai.xi
1114*53ee8cc1Swenshuai.xi static void
scan_periodic(struct ehci_hcd * ehci,struct pt_regs * regs)1115*53ee8cc1Swenshuai.xi scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
1116*53ee8cc1Swenshuai.xi {
1117*53ee8cc1Swenshuai.xi U32 frame, clock, now_uframe, mod;
1118*53ee8cc1Swenshuai.xi U32 count = 0;
1119*53ee8cc1Swenshuai.xi
1120*53ee8cc1Swenshuai.xi mod = ehci->periodic_size << 3;
1121*53ee8cc1Swenshuai.xi
1122*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1123*53ee8cc1Swenshuai.xi frame = ehci->next_uframe >> 3;
1124*53ee8cc1Swenshuai.xi if (HCD_IS_RUNNING (ehci->hcd.state))
1125*53ee8cc1Swenshuai.xi now_uframe = ehci_readl ((U32)&ehci->regs->frame_index);
1126*53ee8cc1Swenshuai.xi else
1127*53ee8cc1Swenshuai.xi now_uframe = (frame << 3) - 1;
1128*53ee8cc1Swenshuai.xi now_uframe %= mod;
1129*53ee8cc1Swenshuai.xi clock = now_uframe >> 3;
1130*53ee8cc1Swenshuai.xi
1131*53ee8cc1Swenshuai.xi for (;;) {
1132*53ee8cc1Swenshuai.xi union ehci_shadow q, *q_p;
1133*53ee8cc1Swenshuai.xi U32 type, *hw_p;
1134*53ee8cc1Swenshuai.xi U32 uframes;
1135*53ee8cc1Swenshuai.xi
1136*53ee8cc1Swenshuai.xi restart:
1137*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1138*53ee8cc1Swenshuai.xi if (frame == clock)
1139*53ee8cc1Swenshuai.xi uframes = now_uframe & 0x07;
1140*53ee8cc1Swenshuai.xi else
1141*53ee8cc1Swenshuai.xi uframes = 8;
1142*53ee8cc1Swenshuai.xi
1143*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1144*53ee8cc1Swenshuai.xi q_p = &ehci->pshadow [frame];
1145*53ee8cc1Swenshuai.xi hw_p = &ehci->periodic [frame];
1146*53ee8cc1Swenshuai.xi q.ptr = q_p->ptr;
1147*53ee8cc1Swenshuai.xi type = Q_NEXT_TYPE (*hw_p);
1148*53ee8cc1Swenshuai.xi
1149*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1150*53ee8cc1Swenshuai.xi while (q.ptr != 0) {
1151*53ee8cc1Swenshuai.xi int last;
1152*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1153*53ee8cc1Swenshuai.xi union ehci_shadow temp;
1154*53ee8cc1Swenshuai.xi
1155*53ee8cc1Swenshuai.xi switch (type) {
1156*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1157*53ee8cc1Swenshuai.xi case Q_TYPE_QH:
1158*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1159*53ee8cc1Swenshuai.xi last = (q.qh->hw_next == EHCI_LIST_END);
1160*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1161*53ee8cc1Swenshuai.xi temp = q.qh->qh_next;
1162*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1163*53ee8cc1Swenshuai.xi type = Q_NEXT_TYPE (q.qh->hw_next);
1164*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1165*53ee8cc1Swenshuai.xi count += intr_complete (ehci, frame,
1166*53ee8cc1Swenshuai.xi qh_get (q.qh), regs);
1167*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1168*53ee8cc1Swenshuai.xi qh_put (ehci, q.qh);
1169*53ee8cc1Swenshuai.xi q = temp;
1170*53ee8cc1Swenshuai.xi break;
1171*53ee8cc1Swenshuai.xi #ifdef have_fstn
1172*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1173*53ee8cc1Swenshuai.xi case Q_TYPE_FSTN:
1174*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1175*53ee8cc1Swenshuai.xi last = (q.fstn->hw_next == EHCI_LIST_END);
1176*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1177*53ee8cc1Swenshuai.xi if (q.fstn->hw_prev != EHCI_LIST_END) {
1178*53ee8cc1Swenshuai.xi dbg ("ignoring completions from FSTNs%s%s","","");
1179*53ee8cc1Swenshuai.xi }
1180*53ee8cc1Swenshuai.xi type = Q_NEXT_TYPE (q.fstn->hw_next);
1181*53ee8cc1Swenshuai.xi q = q.fstn->fstn_next;
1182*53ee8cc1Swenshuai.xi break;
1183*53ee8cc1Swenshuai.xi #endif
1184*53ee8cc1Swenshuai.xi #ifdef have_iso
1185*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1186*53ee8cc1Swenshuai.xi case Q_TYPE_ITD:
1187*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1188*53ee8cc1Swenshuai.xi last = (q.itd->hw_next == EHCI_LIST_END);
1189*53ee8cc1Swenshuai.xi
1190*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1191*53ee8cc1Swenshuai.xi for (uf = 0; uf < uframes; uf++) {
1192*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1193*53ee8cc1Swenshuai.xi if (q.itd->hw_transaction [uf] != 0) {
1194*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1195*53ee8cc1Swenshuai.xi temp = q;
1196*53ee8cc1Swenshuai.xi *q_p = q.itd->itd_next;
1197*53ee8cc1Swenshuai.xi *hw_p = q.itd->hw_next;
1198*53ee8cc1Swenshuai.xi type = Q_NEXT_TYPE (*hw_p);
1199*53ee8cc1Swenshuai.xi
1200*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1201*53ee8cc1Swenshuai.xi count += itd_complete (ehci,
1202*53ee8cc1Swenshuai.xi temp.itd, uf, regs);
1203*53ee8cc1Swenshuai.xi break;
1204*53ee8cc1Swenshuai.xi }
1205*53ee8cc1Swenshuai.xi }
1206*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1207*53ee8cc1Swenshuai.xi if (uf == uframes) {
1208*53ee8cc1Swenshuai.xi q_p = &q.itd->itd_next;
1209*53ee8cc1Swenshuai.xi hw_p = &q.itd->hw_next;
1210*53ee8cc1Swenshuai.xi type = Q_NEXT_TYPE (q.itd->hw_next);
1211*53ee8cc1Swenshuai.xi }
1212*53ee8cc1Swenshuai.xi
1213*53ee8cc1Swenshuai.xi q = *q_p;
1214*53ee8cc1Swenshuai.xi break;
1215*53ee8cc1Swenshuai.xi #endif
1216*53ee8cc1Swenshuai.xi #ifdef have_split_iso
1217*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1218*53ee8cc1Swenshuai.xi case Q_TYPE_SITD:
1219*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1220*53ee8cc1Swenshuai.xi last = (q.sitd->hw_next == EHCI_LIST_END);
1221*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1222*53ee8cc1Swenshuai.xi sitd_complete (ehci, q.sitd);
1223*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1224*53ee8cc1Swenshuai.xi type = Q_NEXT_TYPE (q.sitd->hw_next);
1225*53ee8cc1Swenshuai.xi
1226*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1227*53ee8cc1Swenshuai.xi q = q.sitd->sitd_next;
1228*53ee8cc1Swenshuai.xi break;
1229*53ee8cc1Swenshuai.xi #endif
1230*53ee8cc1Swenshuai.xi default:
1231*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1232*53ee8cc1Swenshuai.xi dbg ("corrupt type %d frame %d shadow %p",
1233*53ee8cc1Swenshuai.xi type, frame, q.ptr);
1234*53ee8cc1Swenshuai.xi // BUG ();
1235*53ee8cc1Swenshuai.xi last = 1;
1236*53ee8cc1Swenshuai.xi q.ptr = 0;
1237*53ee8cc1Swenshuai.xi }
1238*53ee8cc1Swenshuai.xi
1239*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1240*53ee8cc1Swenshuai.xi if (unlikely (q.ptr == 0 && !last))
1241*53ee8cc1Swenshuai.xi goto restart;
1242*53ee8cc1Swenshuai.xi }
1243*53ee8cc1Swenshuai.xi
1244*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1245*53ee8cc1Swenshuai.xi if (frame == clock) {
1246*53ee8cc1Swenshuai.xi U32 now;
1247*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1248*53ee8cc1Swenshuai.xi if (!HCD_IS_RUNNING (ehci->hcd.state))
1249*53ee8cc1Swenshuai.xi break;
1250*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1251*53ee8cc1Swenshuai.xi ehci->next_uframe = now_uframe;
1252*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1253*53ee8cc1Swenshuai.xi now = ehci_readl ((U32)&ehci->regs->frame_index) % mod;
1254*53ee8cc1Swenshuai.xi if (now_uframe == now)
1255*53ee8cc1Swenshuai.xi break;
1256*53ee8cc1Swenshuai.xi
1257*53ee8cc1Swenshuai.xi /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
1258*53ee8cc1Swenshuai.xi now_uframe = now;
1259*53ee8cc1Swenshuai.xi clock = now_uframe >> 3;
1260*53ee8cc1Swenshuai.xi } else
1261*53ee8cc1Swenshuai.xi frame = (frame + 1) % ehci->periodic_size;
1262*53ee8cc1Swenshuai.xi }
1263*53ee8cc1Swenshuai.xi }
1264*53ee8cc1Swenshuai.xi
1265