xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/drvUsbd.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
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 //#include <MsCommon.h> // NUSED
80*53ee8cc1Swenshuai.xi #include  "include/drvConfig.h"
81*53ee8cc1Swenshuai.xi 
82*53ee8cc1Swenshuai.xi #ifdef CONFIG_USB_DEBUG
83*53ee8cc1Swenshuai.xi #define DEBUG
84*53ee8cc1Swenshuai.xi #endif
85*53ee8cc1Swenshuai.xi 
86*53ee8cc1Swenshuai.xi //#include  "include/drvCompiler.h" // NUSED
87*53ee8cc1Swenshuai.xi #include  "include/drvErrno.h"
88*53ee8cc1Swenshuai.xi //#include  "include/drvPorts.h" // NUSED
89*53ee8cc1Swenshuai.xi //#include  "include/drvPCIMEM.h" // NUSED
90*53ee8cc1Swenshuai.xi //#include  "include/drvTimer.h" // NUSED
91*53ee8cc1Swenshuai.xi //#include  "include/drvList.h" // NUSED
92*53ee8cc1Swenshuai.xi //#include  "include/drvCompletion.h" // NUSED
93*53ee8cc1Swenshuai.xi //#include  "include/drvOSAPI.h" // NUSED
94*53ee8cc1Swenshuai.xi //#include  "include/drvKernel.h" // NUSED
95*53ee8cc1Swenshuai.xi //#include  "include/drvBitops.h" // NUSED
96*53ee8cc1Swenshuai.xi //#include <cyg/hal/hal_if.h> // NUSED
97*53ee8cc1Swenshuai.xi //#include <cyg/hal/hal_cache.h> // NUSED
98*53ee8cc1Swenshuai.xi 
99*53ee8cc1Swenshuai.xi // USB related header files
100*53ee8cc1Swenshuai.xi //#include "include/drvUSBHost.h" // NUSED
101*53ee8cc1Swenshuai.xi //#include "drvUsbd.h" // NUSED
102*53ee8cc1Swenshuai.xi #include "drvEHCI.h"
103*53ee8cc1Swenshuai.xi #include "drvUSBHwCtl.h"
104*53ee8cc1Swenshuai.xi //#include "drvMassStor.h" // NUSED
105*53ee8cc1Swenshuai.xi 
106*53ee8cc1Swenshuai.xi extern void ms_ehci_disable_ep (struct usb_hcd *pHcd, struct s_hcd_dev *pDev, int iEp);
107*53ee8cc1Swenshuai.xi extern int ms_hub_status_data (struct usb_hcd *pHcd, char *pBuf);
108*53ee8cc1Swenshuai.xi extern int ms_hub_control (  struct usb_hcd  *pHcd,  U16    typeReq,  U16    u16Value,  U16    u16Index,  char    *pBuf) ;
109*53ee8cc1Swenshuai.xi 
110*53ee8cc1Swenshuai.xi struct list_head usb_bus_list = { &(usb_bus_list), &(usb_bus_list) };
111*53ee8cc1Swenshuai.xi 
112*53ee8cc1Swenshuai.xi #define MS_USB_MAXBUS    32
113*53ee8cc1Swenshuai.xi struct ms_usb_busmap {
114*53ee8cc1Swenshuai.xi   U32 busmap [MS_USB_MAXBUS / (8*sizeof (U32))];
115*53ee8cc1Swenshuai.xi };
116*53ee8cc1Swenshuai.xi static struct ms_usb_busmap busmap;
117*53ee8cc1Swenshuai.xi S32 usb_bus_list_lock;
118*53ee8cc1Swenshuai.xi 
119*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
120*53ee8cc1Swenshuai.xi 
121*53ee8cc1Swenshuai.xi #define KERNEL_REL  1
122*53ee8cc1Swenshuai.xi #define KERNEL_VER  10
123*53ee8cc1Swenshuai.xi 
124*53ee8cc1Swenshuai.xi #define DBG_MSG
125*53ee8cc1Swenshuai.xi #define DBG_WARN
126*53ee8cc1Swenshuai.xi //#define DBG_FUNC
127*53ee8cc1Swenshuai.xi 
128*53ee8cc1Swenshuai.xi #undef  ms_debug_msg
129*53ee8cc1Swenshuai.xi #undef  ms_debug_warn
130*53ee8cc1Swenshuai.xi #undef  ms_debug_func
131*53ee8cc1Swenshuai.xi 
132*53ee8cc1Swenshuai.xi #ifdef DBG_MSG
133*53ee8cc1Swenshuai.xi #define ms_debug_msg(fmt, arg...)    \
134*53ee8cc1Swenshuai.xi         do {diag_printf(fmt, ##arg);} while(0)
135*53ee8cc1Swenshuai.xi #else
136*53ee8cc1Swenshuai.xi #define ms_debug_msg(fmt, arg...) do {} while (0)
137*53ee8cc1Swenshuai.xi #endif
138*53ee8cc1Swenshuai.xi 
139*53ee8cc1Swenshuai.xi #ifdef DBG_WARN
140*53ee8cc1Swenshuai.xi #define ms_debug_warn(fmt, arg...)    \
141*53ee8cc1Swenshuai.xi         do {diag_printf(fmt, ##arg);} while(0)
142*53ee8cc1Swenshuai.xi #else
143*53ee8cc1Swenshuai.xi #define ms_debug_warn(fmt, arg...) do {} while (0)
144*53ee8cc1Swenshuai.xi #endif
145*53ee8cc1Swenshuai.xi 
146*53ee8cc1Swenshuai.xi #ifdef DBG_FUNC
147*53ee8cc1Swenshuai.xi #define ms_debug_func(fmt, arg...)    \
148*53ee8cc1Swenshuai.xi         do {diag_printf(fmt, ##arg);} while(0)
149*53ee8cc1Swenshuai.xi #else
150*53ee8cc1Swenshuai.xi #define ms_debug_func(fmt, arg...) do {} while (0)
151*53ee8cc1Swenshuai.xi #endif
152*53ee8cc1Swenshuai.xi 
153*53ee8cc1Swenshuai.xi 
154*53ee8cc1Swenshuai.xi static const unsigned char hs_rh_dev_descriptor [18] = {
155*53ee8cc1Swenshuai.xi   0x12,
156*53ee8cc1Swenshuai.xi   0x01,
157*53ee8cc1Swenshuai.xi   0x00, 0x02,
158*53ee8cc1Swenshuai.xi 
159*53ee8cc1Swenshuai.xi   0x09,
160*53ee8cc1Swenshuai.xi   0x00,
161*53ee8cc1Swenshuai.xi   0x01,
162*53ee8cc1Swenshuai.xi   0x08,
163*53ee8cc1Swenshuai.xi 
164*53ee8cc1Swenshuai.xi   0x00, 0x00,
165*53ee8cc1Swenshuai.xi   0x00, 0x00,
166*53ee8cc1Swenshuai.xi   KERNEL_VER, KERNEL_REL,
167*53ee8cc1Swenshuai.xi 
168*53ee8cc1Swenshuai.xi   0x03,
169*53ee8cc1Swenshuai.xi   0x02,
170*53ee8cc1Swenshuai.xi   0x01,
171*53ee8cc1Swenshuai.xi   0x01
172*53ee8cc1Swenshuai.xi };
173*53ee8cc1Swenshuai.xi 
174*53ee8cc1Swenshuai.xi static const unsigned char fs_rh_dev_descriptor [18] = {
175*53ee8cc1Swenshuai.xi   0x12,
176*53ee8cc1Swenshuai.xi   0x01,
177*53ee8cc1Swenshuai.xi   0x10, 0x01,
178*53ee8cc1Swenshuai.xi 
179*53ee8cc1Swenshuai.xi   0x09,
180*53ee8cc1Swenshuai.xi   0x00,
181*53ee8cc1Swenshuai.xi   0x00,
182*53ee8cc1Swenshuai.xi   0x08,
183*53ee8cc1Swenshuai.xi 
184*53ee8cc1Swenshuai.xi   0x00, 0x00,
185*53ee8cc1Swenshuai.xi   0x00, 0x00,
186*53ee8cc1Swenshuai.xi   KERNEL_VER, KERNEL_REL,
187*53ee8cc1Swenshuai.xi 
188*53ee8cc1Swenshuai.xi   0x03,
189*53ee8cc1Swenshuai.xi   0x02,
190*53ee8cc1Swenshuai.xi   0x01,
191*53ee8cc1Swenshuai.xi   0x01
192*53ee8cc1Swenshuai.xi };
193*53ee8cc1Swenshuai.xi 
194*53ee8cc1Swenshuai.xi static const unsigned char fs_rh_config_descriptor [] = {
195*53ee8cc1Swenshuai.xi 
196*53ee8cc1Swenshuai.xi   0x09,
197*53ee8cc1Swenshuai.xi   0x02,
198*53ee8cc1Swenshuai.xi   0x19, 0x00,
199*53ee8cc1Swenshuai.xi   0x01,
200*53ee8cc1Swenshuai.xi   0x01,
201*53ee8cc1Swenshuai.xi   0x00,
202*53ee8cc1Swenshuai.xi   0x40,
203*53ee8cc1Swenshuai.xi   0x00,
204*53ee8cc1Swenshuai.xi 
205*53ee8cc1Swenshuai.xi   0x09,
206*53ee8cc1Swenshuai.xi   0x04,
207*53ee8cc1Swenshuai.xi   0x00,
208*53ee8cc1Swenshuai.xi   0x00,
209*53ee8cc1Swenshuai.xi   0x01,
210*53ee8cc1Swenshuai.xi   0x09,
211*53ee8cc1Swenshuai.xi   0x00,
212*53ee8cc1Swenshuai.xi   0x00,
213*53ee8cc1Swenshuai.xi   0x00,
214*53ee8cc1Swenshuai.xi 
215*53ee8cc1Swenshuai.xi   0x07,
216*53ee8cc1Swenshuai.xi   0x05,
217*53ee8cc1Swenshuai.xi   0x81,
218*53ee8cc1Swenshuai.xi   0x03,
219*53ee8cc1Swenshuai.xi   0x02, 0x00,
220*53ee8cc1Swenshuai.xi   0xff
221*53ee8cc1Swenshuai.xi };
222*53ee8cc1Swenshuai.xi 
223*53ee8cc1Swenshuai.xi static const unsigned char hs_rh_config_descriptor [] = {
224*53ee8cc1Swenshuai.xi 
225*53ee8cc1Swenshuai.xi   0x09,
226*53ee8cc1Swenshuai.xi   0x02,
227*53ee8cc1Swenshuai.xi   0x19, 0x00,
228*53ee8cc1Swenshuai.xi   0x01,
229*53ee8cc1Swenshuai.xi   0x01,
230*53ee8cc1Swenshuai.xi   0x00,
231*53ee8cc1Swenshuai.xi   0x40,
232*53ee8cc1Swenshuai.xi   0x00,
233*53ee8cc1Swenshuai.xi   0x09,
234*53ee8cc1Swenshuai.xi   0x04,
235*53ee8cc1Swenshuai.xi   0x00,
236*53ee8cc1Swenshuai.xi   0x00,
237*53ee8cc1Swenshuai.xi   0x01,
238*53ee8cc1Swenshuai.xi   0x09,
239*53ee8cc1Swenshuai.xi   0x00,
240*53ee8cc1Swenshuai.xi   0x00,
241*53ee8cc1Swenshuai.xi   0x00,
242*53ee8cc1Swenshuai.xi   0x07,
243*53ee8cc1Swenshuai.xi   0x05,
244*53ee8cc1Swenshuai.xi   0x81,
245*53ee8cc1Swenshuai.xi   0x03,
246*53ee8cc1Swenshuai.xi   0x02, 0x00,
247*53ee8cc1Swenshuai.xi   0x0c
248*53ee8cc1Swenshuai.xi };
249*53ee8cc1Swenshuai.xi 
250*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
ms_ascii2utf(char * s,unsigned char * pUtf,int iUtfMax)251*53ee8cc1Swenshuai.xi static int ms_ascii2utf (char *s, unsigned char *pUtf, int iUtfMax)
252*53ee8cc1Swenshuai.xi {
253*53ee8cc1Swenshuai.xi   int iRetval;
254*53ee8cc1Swenshuai.xi 
255*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
256*53ee8cc1Swenshuai.xi   for (iRetval = 0; *s && iUtfMax > 1; iUtfMax -= 2, iRetval += 2)
257*53ee8cc1Swenshuai.xi   {
258*53ee8cc1Swenshuai.xi     *pUtf++ = *s++;
259*53ee8cc1Swenshuai.xi     *pUtf++ = 0;
260*53ee8cc1Swenshuai.xi   }
261*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
262*53ee8cc1Swenshuai.xi   return iRetval;
263*53ee8cc1Swenshuai.xi }
264*53ee8cc1Swenshuai.xi 
ms_rh_string(int iId,struct usb_hcd * pHcd,unsigned char * pData,int iLen)265*53ee8cc1Swenshuai.xi static int ms_rh_string (
266*53ee8cc1Swenshuai.xi   int    iId,
267*53ee8cc1Swenshuai.xi   struct usb_hcd  *pHcd,
268*53ee8cc1Swenshuai.xi   unsigned char    *pData,
269*53ee8cc1Swenshuai.xi   int    iLen
270*53ee8cc1Swenshuai.xi )
271*53ee8cc1Swenshuai.xi {
272*53ee8cc1Swenshuai.xi   char pu8Buf [100];
273*53ee8cc1Swenshuai.xi 
274*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
275*53ee8cc1Swenshuai.xi   if (iId == 0)
276*53ee8cc1Swenshuai.xi   {
277*53ee8cc1Swenshuai.xi     *pData++ = 4; *pData++ = 3;
278*53ee8cc1Swenshuai.xi     *pData++ = 0x09; *pData++ = 0x04;
279*53ee8cc1Swenshuai.xi     return 4;
280*53ee8cc1Swenshuai.xi   }
281*53ee8cc1Swenshuai.xi   else if (iId == 1) // Serial number
282*53ee8cc1Swenshuai.xi   {
283*53ee8cc1Swenshuai.xi     strncpy(pu8Buf, pHcd->self.bus_name, sizeof(pu8Buf)-1);
284*53ee8cc1Swenshuai.xi     pu8Buf[sizeof(pu8Buf)-1] = '\0';
285*53ee8cc1Swenshuai.xi   }
286*53ee8cc1Swenshuai.xi   else if (iId == 2) // Product
287*53ee8cc1Swenshuai.xi   {
288*53ee8cc1Swenshuai.xi     strncpy(pu8Buf, pHcd->product_desc, sizeof(pu8Buf));
289*53ee8cc1Swenshuai.xi   }
290*53ee8cc1Swenshuai.xi   else if (iId == 3) // Manufacturer
291*53ee8cc1Swenshuai.xi   {
292*53ee8cc1Swenshuai.xi     USB_sprintf(pu8Buf,"%s %s ehci_hcd", "MStar eCos", "1.0");
293*53ee8cc1Swenshuai.xi   }
294*53ee8cc1Swenshuai.xi   else
295*53ee8cc1Swenshuai.xi     return 0;
296*53ee8cc1Swenshuai.xi   pData [0] = 2 * (strlen(pu8Buf) + 1);
297*53ee8cc1Swenshuai.xi   pData [1] = 3;  /* type == string */
298*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
299*53ee8cc1Swenshuai.xi   return 2 + ms_ascii2utf (pu8Buf, pData + 2, iLen - 2);
300*53ee8cc1Swenshuai.xi }
301*53ee8cc1Swenshuai.xi 
302*53ee8cc1Swenshuai.xi /*
303*53ee8cc1Swenshuai.xi   * @brief             process request from root hub urb
304*53ee8cc1Swenshuai.xi   *
305*53ee8cc1Swenshuai.xi   * @param          struct usb_hcd *hcd
306*53ee8cc1Swenshuai.xi   * @param          struct urb *urb
307*53ee8cc1Swenshuai.xi   *
308*53ee8cc1Swenshuai.xi   * @return           0
309*53ee8cc1Swenshuai.xi   */
310*53ee8cc1Swenshuai.xi 
ms_rh_call_control(struct usb_hcd * pHcd,struct urb * pUrb)311*53ee8cc1Swenshuai.xi static int ms_rh_call_control (struct usb_hcd *pHcd, struct urb *pUrb)
312*53ee8cc1Swenshuai.xi {
313*53ee8cc1Swenshuai.xi     struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) pUrb->pSetupPacket;
314*53ee8cc1Swenshuai.xi     U16    u16TypeReq, u16Value, u16Index, u16Length;
315*53ee8cc1Swenshuai.xi     const unsigned char  *bufp = 0;
316*53ee8cc1Swenshuai.xi     unsigned char    *ubuf = (unsigned char*) pUrb->pTransferBuffer;
317*53ee8cc1Swenshuai.xi     int    iLen = 0;
318*53ee8cc1Swenshuai.xi 
319*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
320*53ee8cc1Swenshuai.xi     pUrb->hcpriv = pHcd;
321*53ee8cc1Swenshuai.xi 
322*53ee8cc1Swenshuai.xi     u16TypeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
323*53ee8cc1Swenshuai.xi     u16Value   = cmd->wValue;
324*53ee8cc1Swenshuai.xi     u16Index   = cmd->wIndex;
325*53ee8cc1Swenshuai.xi     u16Length  = cmd->wLength;
326*53ee8cc1Swenshuai.xi 
327*53ee8cc1Swenshuai.xi     if (u16Length > pUrb->u32TransferBufferLength)
328*53ee8cc1Swenshuai.xi         goto error;
329*53ee8cc1Swenshuai.xi 
330*53ee8cc1Swenshuai.xi     pUrb->s32Status = 0;
331*53ee8cc1Swenshuai.xi     pUrb->u32ActualLength = u16Length;
332*53ee8cc1Swenshuai.xi     switch (u16TypeReq)
333*53ee8cc1Swenshuai.xi     {
334*53ee8cc1Swenshuai.xi         case ReqType_Device | USB_REQ_GET_STATUS:
335*53ee8cc1Swenshuai.xi             ubuf [0] = 1;
336*53ee8cc1Swenshuai.xi             ubuf [1] = 0;
337*53ee8cc1Swenshuai.xi         case ReqType_DeviceOut | USB_REQ_CLEAR_FEATURE:
338*53ee8cc1Swenshuai.xi         case ReqType_DeviceOut | USB_REQ_SET_FEATURE:
339*53ee8cc1Swenshuai.xi             ms_debug_msg ("no device features set yet\n");
340*53ee8cc1Swenshuai.xi             break;
341*53ee8cc1Swenshuai.xi         case ReqType_Device | USB_REQ_GET_CONFIGURATION:
342*53ee8cc1Swenshuai.xi             ubuf [0] = 1;
343*53ee8cc1Swenshuai.xi         case ReqType_DeviceOut | USB_REQ_SET_CONFIGURATION:
344*53ee8cc1Swenshuai.xi             break;
345*53ee8cc1Swenshuai.xi         case ReqType_Device | USB_REQ_GET_DESCRIPTOR:
346*53ee8cc1Swenshuai.xi             switch (u16Value & 0xff00)
347*53ee8cc1Swenshuai.xi             {
348*53ee8cc1Swenshuai.xi                 case USB_DT_DEVICE << 8:
349*53ee8cc1Swenshuai.xi                     if (pHcd->hcd_flags & HCD_HS)
350*53ee8cc1Swenshuai.xi                         bufp = hs_rh_dev_descriptor;
351*53ee8cc1Swenshuai.xi                     else if (pHcd->hcd_flags & HCD_FS)
352*53ee8cc1Swenshuai.xi                         bufp = fs_rh_dev_descriptor;
353*53ee8cc1Swenshuai.xi                     else
354*53ee8cc1Swenshuai.xi                         goto error;
355*53ee8cc1Swenshuai.xi                     iLen = 18;
356*53ee8cc1Swenshuai.xi                     break;
357*53ee8cc1Swenshuai.xi                 case USB_DT_CONFIG << 8:
358*53ee8cc1Swenshuai.xi                     if (pHcd->hcd_flags & HCD_HS)
359*53ee8cc1Swenshuai.xi                     {
360*53ee8cc1Swenshuai.xi                         bufp = hs_rh_config_descriptor;
361*53ee8cc1Swenshuai.xi                         iLen = sizeof hs_rh_config_descriptor;
362*53ee8cc1Swenshuai.xi                     }
363*53ee8cc1Swenshuai.xi                     else
364*53ee8cc1Swenshuai.xi                     {
365*53ee8cc1Swenshuai.xi                         bufp = fs_rh_config_descriptor;
366*53ee8cc1Swenshuai.xi                         iLen = sizeof fs_rh_config_descriptor;
367*53ee8cc1Swenshuai.xi                     }
368*53ee8cc1Swenshuai.xi                     break;
369*53ee8cc1Swenshuai.xi                 case USB_DT_STRING << 8:
370*53ee8cc1Swenshuai.xi                     pUrb->u32ActualLength = ms_rh_string (
371*53ee8cc1Swenshuai.xi                         u16Value & 0xff, pHcd, ubuf, u16Length);
372*53ee8cc1Swenshuai.xi                     break;
373*53ee8cc1Swenshuai.xi                 default:
374*53ee8cc1Swenshuai.xi                   goto error;
375*53ee8cc1Swenshuai.xi             }
376*53ee8cc1Swenshuai.xi             break;
377*53ee8cc1Swenshuai.xi         case ReqType_Device | USB_REQ_GET_INTERFACE:
378*53ee8cc1Swenshuai.xi             ubuf [0] = 0;
379*53ee8cc1Swenshuai.xi         case ReqType_DeviceOut | USB_REQ_SET_INTERFACE:
380*53ee8cc1Swenshuai.xi             break;
381*53ee8cc1Swenshuai.xi         case ReqType_DeviceOut | USB_REQ_SET_ADDRESS:
382*53ee8cc1Swenshuai.xi             ms_debug_msg ("[root hub] device address %d\n", u16Value);
383*53ee8cc1Swenshuai.xi             break;
384*53ee8cc1Swenshuai.xi         case ReqType_Endpoint | USB_REQ_GET_STATUS:
385*53ee8cc1Swenshuai.xi             ubuf [0] = 0;
386*53ee8cc1Swenshuai.xi             ubuf [1] = 0;
387*53ee8cc1Swenshuai.xi         case ReqType_EndpointOut | USB_REQ_CLEAR_FEATURE:
388*53ee8cc1Swenshuai.xi         case ReqType_EndpointOut | USB_REQ_SET_FEATURE:
389*53ee8cc1Swenshuai.xi             ms_debug_msg ("[no endpoint features yet]\n");
390*53ee8cc1Swenshuai.xi             break;
391*53ee8cc1Swenshuai.xi         default:
392*53ee8cc1Swenshuai.xi             pUrb->s32Status = ms_hub_control (pHcd, u16TypeReq, u16Value, u16Index,
393*53ee8cc1Swenshuai.xi               (char*) ubuf);
394*53ee8cc1Swenshuai.xi         break;
395*53ee8cc1Swenshuai.xi error:
396*53ee8cc1Swenshuai.xi         pUrb->s32Status = -EPIPE;
397*53ee8cc1Swenshuai.xi         ms_debug_msg ("[unsupported hub control message] (maxchild %d)\n", (int)pUrb->dev->u32MaxChild);
398*53ee8cc1Swenshuai.xi     }
399*53ee8cc1Swenshuai.xi     if (pUrb->s32Status)
400*53ee8cc1Swenshuai.xi     {
401*53ee8cc1Swenshuai.xi         pUrb->u32ActualLength = 0;
402*53ee8cc1Swenshuai.xi         ms_debug_debug("CTRL: TypeReq=0x%x val=0x%x idx=0x%x iLen=%d ==> %d\n",
403*53ee8cc1Swenshuai.xi           u16TypeReq, u16Value, u16Index, u16Length, (int)pUrb->s32Status);
404*53ee8cc1Swenshuai.xi     }
405*53ee8cc1Swenshuai.xi     if (bufp)
406*53ee8cc1Swenshuai.xi     {
407*53ee8cc1Swenshuai.xi         if (pUrb->u32TransferBufferLength < iLen)
408*53ee8cc1Swenshuai.xi             iLen = pUrb->u32TransferBufferLength;
409*53ee8cc1Swenshuai.xi         pUrb->u32ActualLength = iLen;
410*53ee8cc1Swenshuai.xi         memcpy(ubuf, bufp, iLen);
411*53ee8cc1Swenshuai.xi     }
412*53ee8cc1Swenshuai.xi     osapi_spin_lock_irq(&hcd_root_hub_lock);
413*53ee8cc1Swenshuai.xi     // SMP should unlock hcd_root_hub_lock, but not to enable local irq
414*53ee8cc1Swenshuai.xi     osapi_spin_unlock(&hcd_root_hub_lock);
415*53ee8cc1Swenshuai.xi     ms_usb_hcd_giveback_urb (pUrb, NULL);
416*53ee8cc1Swenshuai.xi     osapi_spin_lock(&hcd_root_hub_lock);
417*53ee8cc1Swenshuai.xi     osapi_spin_unlock_irq (&hcd_root_hub_lock);
418*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
419*53ee8cc1Swenshuai.xi     return 0;
420*53ee8cc1Swenshuai.xi }
421*53ee8cc1Swenshuai.xi 
422*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
423*53ee8cc1Swenshuai.xi /*
424*53ee8cc1Swenshuai.xi   * @brief             check root hub port connect status change and
425*53ee8cc1Swenshuai.xi   *                        run urb's completion funciton
426*53ee8cc1Swenshuai.xi   *
427*53ee8cc1Swenshuai.xi   * @param          struct usb_hcd *pHcd
428*53ee8cc1Swenshuai.xi   *
429*53ee8cc1Swenshuai.xi   * @return           none
430*53ee8cc1Swenshuai.xi   */
431*53ee8cc1Swenshuai.xi 
ms_hcd_poll_rh_status(struct usb_hcd * pHcd)432*53ee8cc1Swenshuai.xi void ms_hcd_poll_rh_status(struct usb_hcd *pHcd)
433*53ee8cc1Swenshuai.xi {
434*53ee8cc1Swenshuai.xi     struct urb	*pUrb;
435*53ee8cc1Swenshuai.xi     int     iLen;
436*53ee8cc1Swenshuai.xi     unsigned long   ulFlags;
437*53ee8cc1Swenshuai.xi     char    aBuf[4];
438*53ee8cc1Swenshuai.xi 
439*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
440*53ee8cc1Swenshuai.xi     if (!pHcd->roothub_registered)
441*53ee8cc1Swenshuai.xi     {
442*53ee8cc1Swenshuai.xi         ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
443*53ee8cc1Swenshuai.xi         return;
444*53ee8cc1Swenshuai.xi     }
445*53ee8cc1Swenshuai.xi     iLen = ms_hub_status_data(pHcd, aBuf);
446*53ee8cc1Swenshuai.xi     if (iLen > 0)
447*53ee8cc1Swenshuai.xi     {
448*53ee8cc1Swenshuai.xi 
449*53ee8cc1Swenshuai.xi         osapi_spin_lock_irqsave(&hcd_root_hub_lock, ulFlags);
450*53ee8cc1Swenshuai.xi         pUrb = pHcd->hcd_status_urb;
451*53ee8cc1Swenshuai.xi         if (pUrb)
452*53ee8cc1Swenshuai.xi         {
453*53ee8cc1Swenshuai.xi             pHcd->hcd_poll_pending = 0;
454*53ee8cc1Swenshuai.xi             pHcd->hcd_status_urb = NULL;
455*53ee8cc1Swenshuai.xi             pUrb->u32ActualLength = iLen;
456*53ee8cc1Swenshuai.xi             pUrb->s32Status = 0; // update status
457*53ee8cc1Swenshuai.xi             pUrb->hcpriv = 0;
458*53ee8cc1Swenshuai.xi             memcpy(pUrb->pTransferBuffer, aBuf, iLen);
459*53ee8cc1Swenshuai.xi             osapi_spin_unlock(&hcd_root_hub_lock);
460*53ee8cc1Swenshuai.xi             ms_usb_hcd_giveback_urb(pUrb, NULL);
461*53ee8cc1Swenshuai.xi             osapi_spin_lock(&hcd_root_hub_lock);
462*53ee8cc1Swenshuai.xi         }
463*53ee8cc1Swenshuai.xi         else
464*53ee8cc1Swenshuai.xi         {
465*53ee8cc1Swenshuai.xi             diag_printf("#### null urb in usb_hcd_poll_rh_status\n");
466*53ee8cc1Swenshuai.xi             iLen = 0;
467*53ee8cc1Swenshuai.xi             pHcd->hcd_poll_pending = 1;
468*53ee8cc1Swenshuai.xi         }
469*53ee8cc1Swenshuai.xi         osapi_spin_unlock_irqrestore(&hcd_root_hub_lock, ulFlags);
470*53ee8cc1Swenshuai.xi     }
471*53ee8cc1Swenshuai.xi 
472*53ee8cc1Swenshuai.xi     /* new polling scheme applied, not to modify timer */
473*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
474*53ee8cc1Swenshuai.xi }
475*53ee8cc1Swenshuai.xi 
476*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
477*53ee8cc1Swenshuai.xi /*
478*53ee8cc1Swenshuai.xi   * @brief             assign urb to hcd and check need report hub status change or not?
479*53ee8cc1Swenshuai.xi   *
480*53ee8cc1Swenshuai.xi   * @param          struct usb_hcd *pHcd
481*53ee8cc1Swenshuai.xi   * @param          struct urb *pUrb
482*53ee8cc1Swenshuai.xi   *
483*53ee8cc1Swenshuai.xi   * @return           error code
484*53ee8cc1Swenshuai.xi   */
485*53ee8cc1Swenshuai.xi 
ms_rh_queue_status(struct usb_hcd * pHcd,struct urb * pUrb)486*53ee8cc1Swenshuai.xi static int ms_rh_queue_status (struct usb_hcd *pHcd, struct urb *pUrb)
487*53ee8cc1Swenshuai.xi {
488*53ee8cc1Swenshuai.xi     int     iRet;
489*53ee8cc1Swenshuai.xi     unsigned long   ulFlags;
490*53ee8cc1Swenshuai.xi     int     iLen = 1 + (pUrb->dev->u32MaxChild / 8);
491*53ee8cc1Swenshuai.xi 
492*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
493*53ee8cc1Swenshuai.xi     osapi_spin_lock_irqsave (&hcd_root_hub_lock, ulFlags);
494*53ee8cc1Swenshuai.xi     if (pHcd->hcd_status_urb || pUrb->u32TransferBufferLength < iLen)
495*53ee8cc1Swenshuai.xi     {
496*53ee8cc1Swenshuai.xi         ms_debug_warn ("not queuing rh status urb\n");
497*53ee8cc1Swenshuai.xi         iRet = -EINVAL;
498*53ee8cc1Swenshuai.xi         goto done;
499*53ee8cc1Swenshuai.xi     }
500*53ee8cc1Swenshuai.xi 
501*53ee8cc1Swenshuai.xi     pHcd->hcd_status_urb = pUrb;
502*53ee8cc1Swenshuai.xi     pUrb->hcpriv = pHcd;
503*53ee8cc1Swenshuai.xi 
504*53ee8cc1Swenshuai.xi     /* quickly report hub status change event */
505*53ee8cc1Swenshuai.xi     if (pHcd->hcd_poll_pending)
506*53ee8cc1Swenshuai.xi         ms_update_timer(&pHcd->roothub_timer, USB_SW_TIMER_TICK, 0);
507*53ee8cc1Swenshuai.xi     iRet = 0;
508*53ee8cc1Swenshuai.xi  done:
509*53ee8cc1Swenshuai.xi     osapi_spin_unlock_irqrestore (&hcd_root_hub_lock, ulFlags);
510*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
511*53ee8cc1Swenshuai.xi     return iRet;
512*53ee8cc1Swenshuai.xi }
513*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
514*53ee8cc1Swenshuai.xi /*
515*53ee8cc1Swenshuai.xi   * @brief             dispatch urb for HW
516*53ee8cc1Swenshuai.xi   *
517*53ee8cc1Swenshuai.xi   * @param          struct usb_hcd *pHcd
518*53ee8cc1Swenshuai.xi   * @param          struct urb *pUrb
519*53ee8cc1Swenshuai.xi   *
520*53ee8cc1Swenshuai.xi   * @return           error code
521*53ee8cc1Swenshuai.xi   */
522*53ee8cc1Swenshuai.xi 
ms_rh_urb_enqueue(struct usb_hcd * pHcd,struct urb * pUrb)523*53ee8cc1Swenshuai.xi static int ms_rh_urb_enqueue (struct usb_hcd *pHcd, struct urb *pUrb)
524*53ee8cc1Swenshuai.xi {
525*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
526*53ee8cc1Swenshuai.xi   if (usb_pipeint (pUrb->u32Pipe))
527*53ee8cc1Swenshuai.xi   {
528*53ee8cc1Swenshuai.xi     int  iRetval;
529*53ee8cc1Swenshuai.xi     //U32  u32Flags;
530*53ee8cc1Swenshuai.xi 
531*53ee8cc1Swenshuai.xi     //osapi_spin_lock_irqsave (&hcd_data_lock, u32Flags);  // unpatch from Linux
532*53ee8cc1Swenshuai.xi     iRetval = ms_rh_queue_status (pHcd, pUrb);
533*53ee8cc1Swenshuai.xi     //osapi_spin_unlock_irqrestore (&hcd_data_lock, u32Flags);
534*53ee8cc1Swenshuai.xi     return iRetval;
535*53ee8cc1Swenshuai.xi   }
536*53ee8cc1Swenshuai.xi   else if (usb_pipecontrol (pUrb->u32Pipe))
537*53ee8cc1Swenshuai.xi   {
538*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
539*53ee8cc1Swenshuai.xi     return ms_rh_call_control (pHcd, pUrb);
540*53ee8cc1Swenshuai.xi   }
541*53ee8cc1Swenshuai.xi   else
542*53ee8cc1Swenshuai.xi   {
543*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
544*53ee8cc1Swenshuai.xi     return -EINVAL;
545*53ee8cc1Swenshuai.xi   }
546*53ee8cc1Swenshuai.xi }
547*53ee8cc1Swenshuai.xi 
548*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
549*53ee8cc1Swenshuai.xi 
ms_rh_status_dequeue(struct usb_hcd * pHcd,struct urb * pUrb)550*53ee8cc1Swenshuai.xi void ms_rh_status_dequeue (struct usb_hcd *pHcd, struct urb *pUrb)
551*53ee8cc1Swenshuai.xi {
552*53ee8cc1Swenshuai.xi    unsigned long   ulFlags;
553*53ee8cc1Swenshuai.xi 
554*53ee8cc1Swenshuai.xi    ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
555*53ee8cc1Swenshuai.xi    osapi_spin_lock_irqsave(&hcd_root_hub_lock, ulFlags);
556*53ee8cc1Swenshuai.xi    if (usb_pipecontrol (pUrb->u32Pipe))
557*53ee8cc1Swenshuai.xi    {       /* Control URB */
558*53ee8cc1Swenshuai.xi        ;   /* Do nothing */
559*53ee8cc1Swenshuai.xi    }
560*53ee8cc1Swenshuai.xi    else
561*53ee8cc1Swenshuai.xi    {
562*53ee8cc1Swenshuai.xi        /* Status URB */
563*53ee8cc1Swenshuai.xi        if (pUrb == pHcd->hcd_status_urb)
564*53ee8cc1Swenshuai.xi        {
565*53ee8cc1Swenshuai.xi            pHcd->hcd_status_urb = NULL;
566*53ee8cc1Swenshuai.xi            // TODO: FIXME
567*53ee8cc1Swenshuai.xi            //usb_hcd_unlink_urb_from_ep(hcd, urb);
568*53ee8cc1Swenshuai.xi 
569*53ee8cc1Swenshuai.xi            osapi_spin_unlock(&hcd_root_hub_lock);
570*53ee8cc1Swenshuai.xi            ms_usb_hcd_giveback_urb(pUrb, NULL);
571*53ee8cc1Swenshuai.xi            osapi_spin_lock(&hcd_root_hub_lock);
572*53ee8cc1Swenshuai.xi        }
573*53ee8cc1Swenshuai.xi    }
574*53ee8cc1Swenshuai.xi    osapi_spin_unlock_irqrestore(&hcd_root_hub_lock, ulFlags);
575*53ee8cc1Swenshuai.xi    ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
576*53ee8cc1Swenshuai.xi }
577*53ee8cc1Swenshuai.xi 
578*53ee8cc1Swenshuai.xi extern void ms_release_OS_Resource_EX(S32 *USBWaitFlg);
579*53ee8cc1Swenshuai.xi extern void ms_ehci_end (struct usb_hcd *hcd);
580*53ee8cc1Swenshuai.xi extern S32 usb_bus_list_lock;
ms_usb_hcd_cpe_ehci_remove(struct usb_hcd * pHcd)581*53ee8cc1Swenshuai.xi void ms_usb_hcd_cpe_ehci_remove (struct usb_hcd *pHcd)
582*53ee8cc1Swenshuai.xi {
583*53ee8cc1Swenshuai.xi     struct usb_device  *pHub;
584*53ee8cc1Swenshuai.xi 
585*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
586*53ee8cc1Swenshuai.xi     ms_debug_msg ("remove: %s, state %x\n", pHcd->self.bus_name, pHcd->state);
587*53ee8cc1Swenshuai.xi     pHub = pHcd->self.root_hub;
588*53ee8cc1Swenshuai.xi     ms_usb_get_dev(pHub); // patch from Linux 2.6.28
589*53ee8cc1Swenshuai.xi     if (HCD_IS_RUNNING (pHcd->state))
590*53ee8cc1Swenshuai.xi         pHcd->state = HCD_STATE_QUIESCING;
591*53ee8cc1Swenshuai.xi 
592*53ee8cc1Swenshuai.xi     osapi_spin_lock_irq (&hcd_root_hub_lock);
593*53ee8cc1Swenshuai.xi     pHcd->roothub_registered = 0;
594*53ee8cc1Swenshuai.xi     osapi_spin_unlock_irq (&hcd_root_hub_lock);
595*53ee8cc1Swenshuai.xi 
596*53ee8cc1Swenshuai.xi     ms_debug_msg ("%s: roothub graceful disconnect\n", pHcd->self.bus_name);
597*53ee8cc1Swenshuai.xi     osapi_mutex_lock(usb_bus_list_lock);
598*53ee8cc1Swenshuai.xi     ms_usb_disconnect (&pHub);
599*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(usb_bus_list_lock);
600*53ee8cc1Swenshuai.xi     ms_debug_msg ("%s: roothub disconnect done\n", pHcd->self.bus_name);
601*53ee8cc1Swenshuai.xi 
602*53ee8cc1Swenshuai.xi     ms_del_timer_sync(&pHcd->roothub_timer);
603*53ee8cc1Swenshuai.xi 
604*53ee8cc1Swenshuai.xi     ms_ehci_end(pHcd); // hcd driver stop
605*53ee8cc1Swenshuai.xi     pHcd->state = HCD_STATE_HALT;
606*53ee8cc1Swenshuai.xi 
607*53ee8cc1Swenshuai.xi     //free_irq (pHcd->irq, pHcd);
608*53ee8cc1Swenshuai.xi     ms_release_OS_Resource_EX(&pHcd->USBWaitFlg);
609*53ee8cc1Swenshuai.xi     ms_hcd_buffer_destroy (pHcd);
610*53ee8cc1Swenshuai.xi     ms_usb_put_dev(pHub); // patch from Linux 2.6.28
611*53ee8cc1Swenshuai.xi     ms_usb_deregister_bus (&pHcd->self);
612*53ee8cc1Swenshuai.xi     kfree (hcd_to_ehci(pHcd));
613*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
614*53ee8cc1Swenshuai.xi }
615*53ee8cc1Swenshuai.xi 
616*53ee8cc1Swenshuai.xi #ifdef CONFIG_PM
ms_usb_hcd_cpe_ehci_suspend(struct usb_hcd * hcd)617*53ee8cc1Swenshuai.xi int ms_usb_hcd_cpe_ehci_suspend (struct usb_hcd *hcd)
618*53ee8cc1Swenshuai.xi {
619*53ee8cc1Swenshuai.xi     int retval = 0;
620*53ee8cc1Swenshuai.xi 
621*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
622*53ee8cc1Swenshuai.xi     switch (hcd->state)
623*53ee8cc1Swenshuai.xi     {
624*53ee8cc1Swenshuai.xi         case HCD_STATE_HALT:
625*53ee8cc1Swenshuai.xi             ms_debug_msg ("halted; hcd not suspended\n");
626*53ee8cc1Swenshuai.xi             break;
627*53ee8cc1Swenshuai.xi         case HCD_STATE_SUSPENDED:
628*53ee8cc1Swenshuai.xi             ms_debug_msg ("hcd already suspended\n");
629*53ee8cc1Swenshuai.xi             break;
630*53ee8cc1Swenshuai.xi         default:
631*53ee8cc1Swenshuai.xi             hcd->state = HCD_STATE_QUIESCING;
632*53ee8cc1Swenshuai.xi             retval = ms_ehci_suspend (hcd, 0);
633*53ee8cc1Swenshuai.xi             if (retval)
634*53ee8cc1Swenshuai.xi                 ms_debug_msg ("suspend fail, retval %d\n", retval);
635*53ee8cc1Swenshuai.xi             break;
636*53ee8cc1Swenshuai.xi     }
637*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
638*53ee8cc1Swenshuai.xi     return retval;
639*53ee8cc1Swenshuai.xi }
ms_usb_hcd_cpe_ehci_resume(struct usb_hcd * hcd)640*53ee8cc1Swenshuai.xi int ms_usb_hcd_cpe_ehci_resume(struct usb_hcd *hcd)
641*53ee8cc1Swenshuai.xi {
642*53ee8cc1Swenshuai.xi     int retval=0;
643*53ee8cc1Swenshuai.xi 
644*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
645*53ee8cc1Swenshuai.xi     if (hcd->state != HCD_STATE_SUSPENDED)
646*53ee8cc1Swenshuai.xi     {
647*53ee8cc1Swenshuai.xi         ms_debug_msg ("can't resume, not suspended!\n");
648*53ee8cc1Swenshuai.xi         ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
649*53ee8cc1Swenshuai.xi         return -46;//return -EL3HLT;
650*53ee8cc1Swenshuai.xi     }
651*53ee8cc1Swenshuai.xi     hcd->state = HCD_STATE_RESUMING;
652*53ee8cc1Swenshuai.xi     /* remote wakeup needs hub->suspend() cooperation */
653*53ee8cc1Swenshuai.xi     retval = ms_ehci_resume (hcd);
654*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
655*53ee8cc1Swenshuai.xi     return retval;
656*53ee8cc1Swenshuai.xi }
657*53ee8cc1Swenshuai.xi 
658*53ee8cc1Swenshuai.xi #endif /* CONFIG_PM */
659*53ee8cc1Swenshuai.xi 
660*53ee8cc1Swenshuai.xi 
661*53ee8cc1Swenshuai.xi // -------------------------------------------------------------------------
ms_rh_timer_func(unsigned long pHcd)662*53ee8cc1Swenshuai.xi inline static void ms_rh_timer_func (unsigned long pHcd)
663*53ee8cc1Swenshuai.xi {
664*53ee8cc1Swenshuai.xi 	ms_hcd_poll_rh_status((struct usb_hcd *) pHcd);
665*53ee8cc1Swenshuai.xi }
666*53ee8cc1Swenshuai.xi 
667*53ee8cc1Swenshuai.xi /*
668*53ee8cc1Swenshuai.xi   * @brief             allocate struct usb_hcd and initial it
669*53ee8cc1Swenshuai.xi   *
670*53ee8cc1Swenshuai.xi   * @param          struct usb_hcd **hcd_out
671*53ee8cc1Swenshuai.xi   * @param          struct cpe_dev *dev
672*53ee8cc1Swenshuai.xi   *
673*53ee8cc1Swenshuai.xi   * @return           error code
674*53ee8cc1Swenshuai.xi   */
675*53ee8cc1Swenshuai.xi extern int ms_ehci_init (struct usb_hcd *pHcd);
676*53ee8cc1Swenshuai.xi extern int ms_urb_enqueue (struct usb_hcd *pHcd, struct urb *pUrb, int iMem_flags);
677*53ee8cc1Swenshuai.xi extern int ms_urb_dequeue (struct usb_hcd *pHcd, struct urb *pUrb);
678*53ee8cc1Swenshuai.xi extern void ms_init_OS_Resource_EX(S32 *USBWaitFlg);
679*53ee8cc1Swenshuai.xi extern int ms_ehci_begin (struct usb_hcd *hcd);
ms_new_usb_hcd(struct usb_hcd ** pHcd_out,struct cpe_dev * pDev)680*53ee8cc1Swenshuai.xi int ms_new_usb_hcd(struct usb_hcd **pHcd_out, struct cpe_dev *pDev)
681*53ee8cc1Swenshuai.xi {
682*53ee8cc1Swenshuai.xi     int iRetVal;
683*53ee8cc1Swenshuai.xi     struct usb_hcd *pHcd = 0;
684*53ee8cc1Swenshuai.xi     struct ehci_hcd *pEhci;
685*53ee8cc1Swenshuai.xi 
686*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
687*53ee8cc1Swenshuai.xi     pEhci = (struct ehci_hcd *)kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL);
688*53ee8cc1Swenshuai.xi     if (pEhci == NULL)
689*53ee8cc1Swenshuai.xi     {
690*53ee8cc1Swenshuai.xi         ms_debug_err ("ehci_hcd allocate failed\n");
691*53ee8cc1Swenshuai.xi         iRetVal = -ENOMEM;
692*53ee8cc1Swenshuai.xi         goto ex_err1;
693*53ee8cc1Swenshuai.xi     }
694*53ee8cc1Swenshuai.xi 
695*53ee8cc1Swenshuai.xi     ms_debug_func("pEhci: %lx\n", (U32) pEhci);
696*53ee8cc1Swenshuai.xi     memset (pEhci, 0, sizeof (struct ehci_hcd));
697*53ee8cc1Swenshuai.xi     strncpy(pEhci->hcd.product_desc, "EHCI Host Controller", sizeof(pEhci->hcd.product_desc));
698*53ee8cc1Swenshuai.xi     pHcd = (struct usb_hcd *)(&pEhci->hcd);
699*53ee8cc1Swenshuai.xi     ms_debug_func("pHcd: %lx\n", (U32)pHcd);
700*53ee8cc1Swenshuai.xi 
701*53ee8cc1Swenshuai.xi     pHcd->host_id = pDev->devid; // chcek the definition
702*53ee8cc1Swenshuai.xi     pHcd->phub_event = pDev->pHubEvent;
703*53ee8cc1Swenshuai.xi     pHcd->ehci_irq = pDev->intNum;
704*53ee8cc1Swenshuai.xi     pHcd->uhc_regs = (U32*) pDev->uhcbase;
705*53ee8cc1Swenshuai.xi     pHcd->self.controller = &pDev->dev;
706*53ee8cc1Swenshuai.xi     pHcd->controller = pHcd->self.controller;
707*53ee8cc1Swenshuai.xi     pHcd->hcd_flags = HCD_HS;
708*53ee8cc1Swenshuai.xi 
709*53ee8cc1Swenshuai.xi     iRetVal = ms_hcd_buffer_create (pHcd);
710*53ee8cc1Swenshuai.xi     if (iRetVal != 0)
711*53ee8cc1Swenshuai.xi     {
712*53ee8cc1Swenshuai.xi         ms_debug_err ("pool alloc fail\n");
713*53ee8cc1Swenshuai.xi         goto ex_err1;
714*53ee8cc1Swenshuai.xi     }
715*53ee8cc1Swenshuai.xi 
716*53ee8cc1Swenshuai.xi     if ((iRetVal = ms_ehci_init(pHcd)) < 0)
717*53ee8cc1Swenshuai.xi     {
718*53ee8cc1Swenshuai.xi         ms_debug_err("can't reset\n");
719*53ee8cc1Swenshuai.xi         goto ex_err2;
720*53ee8cc1Swenshuai.xi     }
721*53ee8cc1Swenshuai.xi 
722*53ee8cc1Swenshuai.xi     ms_debug_msg ("ehci_hcd (CPE_AMBA) at 0x%p, irq %d\n",
723*53ee8cc1Swenshuai.xi         pHcd->uhc_regs, pHcd->ehci_irq);
724*53ee8cc1Swenshuai.xi     ms_usb_bus_init (&pHcd->self);
725*53ee8cc1Swenshuai.xi     //pHcd->self.bus_ops = &ms_usb_hcd_operations;
726*53ee8cc1Swenshuai.xi     pHcd->self.hcpriv = (void *) pHcd;
727*53ee8cc1Swenshuai.xi 
728*53ee8cc1Swenshuai.xi     pHcd->self.bus_name = pDev->bus_name;
729*53ee8cc1Swenshuai.xi     //pHcd->product_desc = pDev->product_desc;
730*53ee8cc1Swenshuai.xi     memcpy(pHcd->product_desc, pDev->product_desc, sizeof(pHcd->product_desc));
731*53ee8cc1Swenshuai.xi 
732*53ee8cc1Swenshuai.xi     ms_init_timer(&pHcd->roothub_timer);
733*53ee8cc1Swenshuai.xi     pHcd->roothub_timer.function = (void *)ms_rh_timer_func;
734*53ee8cc1Swenshuai.xi     pHcd->roothub_timer.data = (unsigned long) pHcd;
735*53ee8cc1Swenshuai.xi 
736*53ee8cc1Swenshuai.xi     pHcd->ms_urb_enqueue = ms_urb_enqueue;
737*53ee8cc1Swenshuai.xi     pHcd->ms_urb_dequeue = ms_urb_dequeue;
738*53ee8cc1Swenshuai.xi 
739*53ee8cc1Swenshuai.xi     //pHcd->pre_sts = 0; // new
740*53ee8cc1Swenshuai.xi     //pHcd->pre_temp = 0; // new
741*53ee8cc1Swenshuai.xi     ms_init_OS_Resource_EX(&pHcd->USBWaitFlg);
742*53ee8cc1Swenshuai.xi     ms_list_init (&pHcd->hcd_dev_list);
743*53ee8cc1Swenshuai.xi     ms_list_init (&pHcd->tt_clear_list);
744*53ee8cc1Swenshuai.xi     ms_usb_register_bus (&pHcd->self);
745*53ee8cc1Swenshuai.xi 
746*53ee8cc1Swenshuai.xi     if ((iRetVal = ms_ehci_begin(pHcd)) < 0) // start HCD
747*53ee8cc1Swenshuai.xi     {
748*53ee8cc1Swenshuai.xi         ms_usb_hcd_cpe_ehci_remove(pHcd);
749*53ee8cc1Swenshuai.xi         return iRetVal;
750*53ee8cc1Swenshuai.xi     }
751*53ee8cc1Swenshuai.xi 
752*53ee8cc1Swenshuai.xi     *pHcd_out = pHcd;
753*53ee8cc1Swenshuai.xi 
754*53ee8cc1Swenshuai.xi     return iRetVal;
755*53ee8cc1Swenshuai.xi 
756*53ee8cc1Swenshuai.xi ex_err2:
757*53ee8cc1Swenshuai.xi     ms_hcd_buffer_destroy (pHcd);
758*53ee8cc1Swenshuai.xi     if (pHcd)
759*53ee8cc1Swenshuai.xi         kfree (hcd_to_ehci (pHcd));
760*53ee8cc1Swenshuai.xi ex_err1:
761*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
762*53ee8cc1Swenshuai.xi     return iRetVal;
763*53ee8cc1Swenshuai.xi }
764*53ee8cc1Swenshuai.xi 
765*53ee8cc1Swenshuai.xi extern void ms_InitUSBIntr_EX(struct usb_hcd *, int);
ms_create_cpe_hcd(struct cpe_dev * dev)766*53ee8cc1Swenshuai.xi int ms_create_cpe_hcd(struct cpe_dev *dev)
767*53ee8cc1Swenshuai.xi {
768*53ee8cc1Swenshuai.xi     struct usb_hcd *hcd = NULL;
769*53ee8cc1Swenshuai.xi     int ret;
770*53ee8cc1Swenshuai.xi 
771*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
772*53ee8cc1Swenshuai.xi     ms_device_initialize(&dev->dev);
773*53ee8cc1Swenshuai.xi     ret = ms_new_usb_hcd(&hcd, dev);
774*53ee8cc1Swenshuai.xi 
775*53ee8cc1Swenshuai.xi     if (ret == 0)
776*53ee8cc1Swenshuai.xi     {
777*53ee8cc1Swenshuai.xi         ms_debug_func("ms_ehci_hcd_cpe_ehci_drv_probe_EX -> allocate usb_hcd\n");
778*53ee8cc1Swenshuai.xi         dev->dev.driver_data = hcd;
779*53ee8cc1Swenshuai.xi         ms_InitUSBIntr_EX(hcd, 0);
780*53ee8cc1Swenshuai.xi     }
781*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
782*53ee8cc1Swenshuai.xi     return ret;
783*53ee8cc1Swenshuai.xi }
784*53ee8cc1Swenshuai.xi 
785*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
ms_usb_bus_init(struct usb_bus * bus)786*53ee8cc1Swenshuai.xi void ms_usb_bus_init (struct usb_bus *bus)
787*53ee8cc1Swenshuai.xi {
788*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
789*53ee8cc1Swenshuai.xi   memset (&bus->devmap, 0, sizeof(struct ms_usb_devmap));
790*53ee8cc1Swenshuai.xi 
791*53ee8cc1Swenshuai.xi   bus->devnum_next = 1;
792*53ee8cc1Swenshuai.xi   bus->root_hub = NULL;
793*53ee8cc1Swenshuai.xi   bus->hcpriv = NULL;
794*53ee8cc1Swenshuai.xi   bus->busnum = -1;
795*53ee8cc1Swenshuai.xi 
796*53ee8cc1Swenshuai.xi   ms_list_init (&bus->bus_list);
797*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
798*53ee8cc1Swenshuai.xi }
799*53ee8cc1Swenshuai.xi 
ms_usb_register_bus(struct usb_bus * pBus)800*53ee8cc1Swenshuai.xi int ms_usb_register_bus(struct usb_bus *pBus)
801*53ee8cc1Swenshuai.xi {
802*53ee8cc1Swenshuai.xi   int iBusNum;
803*53ee8cc1Swenshuai.xi 
804*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, (int)__LINE__);
805*53ee8cc1Swenshuai.xi   //osapi_down (&usb_bus_list_lock);
806*53ee8cc1Swenshuai.xi   osapi_mutex_lock(usb_bus_list_lock);
807*53ee8cc1Swenshuai.xi   iBusNum = find_next_zero_bit (busmap.busmap, MS_USB_MAXBUS, 1);
808*53ee8cc1Swenshuai.xi   if (iBusNum < MS_USB_MAXBUS)
809*53ee8cc1Swenshuai.xi   {
810*53ee8cc1Swenshuai.xi     ms_set_bit (iBusNum, busmap.busmap, U32);
811*53ee8cc1Swenshuai.xi     pBus->busnum = iBusNum;
812*53ee8cc1Swenshuai.xi   }
813*53ee8cc1Swenshuai.xi   else
814*53ee8cc1Swenshuai.xi   {
815*53ee8cc1Swenshuai.xi     ms_debug_warn ("too many buses %s\n", pBus->bus_name);
816*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(usb_bus_list_lock);
817*53ee8cc1Swenshuai.xi     return -MS_ERR_2BIG;
818*53ee8cc1Swenshuai.xi   }
819*53ee8cc1Swenshuai.xi   ms_insert_list_after (&pBus->bus_list, &usb_bus_list);
820*53ee8cc1Swenshuai.xi   //osapi_up (&usb_bus_list_lock);
821*53ee8cc1Swenshuai.xi   osapi_mutex_unlock(usb_bus_list_lock);
822*53ee8cc1Swenshuai.xi 
823*53ee8cc1Swenshuai.xi   ms_debug_msg ("new USB Bus, assigned pBus number %d\n", (int)pBus->busnum);
824*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, (int)__LINE__);
825*53ee8cc1Swenshuai.xi   return 0;
826*53ee8cc1Swenshuai.xi }
827*53ee8cc1Swenshuai.xi 
ms_usb_deregister_bus(struct usb_bus * pBus)828*53ee8cc1Swenshuai.xi void ms_usb_deregister_bus (struct usb_bus *pBus)
829*53ee8cc1Swenshuai.xi {
830*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
831*53ee8cc1Swenshuai.xi   ms_debug_msg ("USB pBus %d deregistered\n", (int)pBus->busnum);
832*53ee8cc1Swenshuai.xi   //osapi_down (&usb_bus_list_lock);
833*53ee8cc1Swenshuai.xi   osapi_mutex_lock(usb_bus_list_lock);
834*53ee8cc1Swenshuai.xi   ms_list_remove (&pBus->bus_list);
835*53ee8cc1Swenshuai.xi   //osapi_up (&usb_bus_list_lock);
836*53ee8cc1Swenshuai.xi   osapi_mutex_unlock(usb_bus_list_lock);
837*53ee8cc1Swenshuai.xi   ms_clear_bit (pBus->busnum, busmap.busmap, U32);
838*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
839*53ee8cc1Swenshuai.xi }
840*53ee8cc1Swenshuai.xi 
ms_register_root_hub(struct usb_hcd * pHcd)841*53ee8cc1Swenshuai.xi int ms_register_root_hub(struct usb_hcd *pHcd)
842*53ee8cc1Swenshuai.xi {
843*53ee8cc1Swenshuai.xi     //struct device *parent_dev = pHcd->self.controller;
844*53ee8cc1Swenshuai.xi     struct device_s *pParent_dev = pHcd->controller;
845*53ee8cc1Swenshuai.xi     struct usb_device *pUsb_dev = pHcd->self.root_hub;
846*53ee8cc1Swenshuai.xi     const int iDevnum = 1;
847*53ee8cc1Swenshuai.xi     int iRetval;
848*53ee8cc1Swenshuai.xi 
849*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
850*53ee8cc1Swenshuai.xi     //pUsb_dev->eState = USB_STATE_DEFAULT;
851*53ee8cc1Swenshuai.xi 
852*53ee8cc1Swenshuai.xi     pUsb_dev->u32DevNum = iDevnum;
853*53ee8cc1Swenshuai.xi     pUsb_dev->bus->devnum_next = iDevnum + 1;
854*53ee8cc1Swenshuai.xi     //ms_set_bit (iDevnum, pUsb_dev->bus->devmap.usb_devicemap, U32);
855*53ee8cc1Swenshuai.xi     ms_devmap_set_bit (iDevnum, pUsb_dev->bus->devmap.usb_devicemap);
856*53ee8cc1Swenshuai.xi     ms_usb_set_device_state(pUsb_dev, USB_STATE_ADDRESS); // patch from Linux 2.6.28
857*53ee8cc1Swenshuai.xi 
858*53ee8cc1Swenshuai.xi     osapi_mutex_lock(usb_bus_list_lock);
859*53ee8cc1Swenshuai.xi 
860*53ee8cc1Swenshuai.xi     iRetval = ms_usb_new_device (pUsb_dev, pParent_dev);
861*53ee8cc1Swenshuai.xi     if (iRetval)
862*53ee8cc1Swenshuai.xi         ms_debug_err ("can't register root hub for %s, %d\n",
863*53ee8cc1Swenshuai.xi           pUsb_dev->dev.bus_id, iRetval);
864*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(usb_bus_list_lock);
865*53ee8cc1Swenshuai.xi 
866*53ee8cc1Swenshuai.xi     if (iRetval == 0)
867*53ee8cc1Swenshuai.xi     {
868*53ee8cc1Swenshuai.xi         osapi_spin_lock_irq (&hcd_root_hub_lock);
869*53ee8cc1Swenshuai.xi         pHcd->roothub_registered = 1;
870*53ee8cc1Swenshuai.xi         osapi_spin_unlock_irq (&hcd_root_hub_lock);
871*53ee8cc1Swenshuai.xi     }
872*53ee8cc1Swenshuai.xi 
873*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
874*53ee8cc1Swenshuai.xi     return iRetval;
875*53ee8cc1Swenshuai.xi }
876*53ee8cc1Swenshuai.xi 
877*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
878*53ee8cc1Swenshuai.xi /*
879*53ee8cc1Swenshuai.xi   * @brief             estimate periodic transaction time in nano-second
880*53ee8cc1Swenshuai.xi   *
881*53ee8cc1Swenshuai.xi   * @param          int iSpeed
882*53ee8cc1Swenshuai.xi   * @param          int is_input
883*53ee8cc1Swenshuai.xi   * @param          int iBytes
884*53ee8cc1Swenshuai.xi   *
885*53ee8cc1Swenshuai.xi   * @return           how many nano-seconds
886*53ee8cc1Swenshuai.xi   */
ms_usb_calc_bus_time(int iSpeed,int is_input,int iBytes)887*53ee8cc1Swenshuai.xi int ms_usb_calc_bus_time (int iSpeed, int is_input, int iBytes)
888*53ee8cc1Swenshuai.xi {
889*53ee8cc1Swenshuai.xi   U32  u32Tmp;
890*53ee8cc1Swenshuai.xi   int  iRet;
891*53ee8cc1Swenshuai.xi 
892*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
893*53ee8cc1Swenshuai.xi   /* support interrupt pipe now */
894*53ee8cc1Swenshuai.xi   switch (iSpeed)
895*53ee8cc1Swenshuai.xi   {
896*53ee8cc1Swenshuai.xi   case USB_LOW_SPEED:
897*53ee8cc1Swenshuai.xi     if (is_input)
898*53ee8cc1Swenshuai.xi     {
899*53ee8cc1Swenshuai.xi       u32Tmp = (67667L * (31L + 10L * ms_CalcBitTime (iBytes))) / 1000L;
900*53ee8cc1Swenshuai.xi       iRet = (64060L + (2 * HUB_BW_LS_SETUP) + EHCI_BW_DELAY + u32Tmp);
901*53ee8cc1Swenshuai.xi     }
902*53ee8cc1Swenshuai.xi     else
903*53ee8cc1Swenshuai.xi     {
904*53ee8cc1Swenshuai.xi       u32Tmp = (66700L * (31L + 10L * ms_CalcBitTime (iBytes))) / 1000L;
905*53ee8cc1Swenshuai.xi       iRet = (64107L + (2 * HUB_BW_LS_SETUP) + EHCI_BW_DELAY + u32Tmp);
906*53ee8cc1Swenshuai.xi     }
907*53ee8cc1Swenshuai.xi     break;
908*53ee8cc1Swenshuai.xi   case USB_FULL_SPEED:
909*53ee8cc1Swenshuai.xi     u32Tmp = (8354L * (31L + 10L * ms_CalcBitTime (iBytes))) / 1000L;
910*53ee8cc1Swenshuai.xi     iRet = (9107L + EHCI_BW_DELAY + u32Tmp);
911*53ee8cc1Swenshuai.xi     break;
912*53ee8cc1Swenshuai.xi   case USB_HIGH_SPEED:
913*53ee8cc1Swenshuai.xi     u32Tmp = HIGHSPEED_NS(iBytes);
914*53ee8cc1Swenshuai.xi     iRet = (int)u32Tmp;
915*53ee8cc1Swenshuai.xi     break;
916*53ee8cc1Swenshuai.xi   default:
917*53ee8cc1Swenshuai.xi     ms_debug_err ("Unknown device iSpeed!\n");
918*53ee8cc1Swenshuai.xi     iRet = -1;
919*53ee8cc1Swenshuai.xi   }
920*53ee8cc1Swenshuai.xi 
921*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
922*53ee8cc1Swenshuai.xi   return iRet;
923*53ee8cc1Swenshuai.xi }
924*53ee8cc1Swenshuai.xi 
925*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
ms_hcd_alloc_dev(struct usb_device * iUdev)926*53ee8cc1Swenshuai.xi int ms_hcd_alloc_dev (struct usb_device *iUdev)
927*53ee8cc1Swenshuai.xi {
928*53ee8cc1Swenshuai.xi   struct s_hcd_dev    *pDev;
929*53ee8cc1Swenshuai.xi   struct usb_hcd    *pHcd;
930*53ee8cc1Swenshuai.xi   U32    u32Flags;
931*53ee8cc1Swenshuai.xi   int    iRet = 0;
932*53ee8cc1Swenshuai.xi 
933*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
934*53ee8cc1Swenshuai.xi   if (!iUdev || iUdev->hcpriv)
935*53ee8cc1Swenshuai.xi     iRet = -EINVAL;
936*53ee8cc1Swenshuai.xi   if (!iUdev->bus || !iUdev->bus->hcpriv)
937*53ee8cc1Swenshuai.xi     iRet = -ENODEV;
938*53ee8cc1Swenshuai.xi   pHcd = (struct usb_hcd*) iUdev->bus->hcpriv;
939*53ee8cc1Swenshuai.xi   if (pHcd->state == HCD_STATE_QUIESCING)
940*53ee8cc1Swenshuai.xi     iRet = -MS_ERR_NOLINK;
941*53ee8cc1Swenshuai.xi 
942*53ee8cc1Swenshuai.xi   pDev = (struct s_hcd_dev *) kmalloc (sizeof *pDev, GFP_KERNEL);
943*53ee8cc1Swenshuai.xi   if (pDev == NULL)
944*53ee8cc1Swenshuai.xi     iRet = -ENOMEM;
945*53ee8cc1Swenshuai.xi   memset (pDev, 0, sizeof *pDev);
946*53ee8cc1Swenshuai.xi 
947*53ee8cc1Swenshuai.xi   ms_list_init (&pDev->dev_list);
948*53ee8cc1Swenshuai.xi   ms_list_init (&pDev->urb_list);
949*53ee8cc1Swenshuai.xi 
950*53ee8cc1Swenshuai.xi   osapi_spin_lock_irqsave (&hcd_data_lock, u32Flags);
951*53ee8cc1Swenshuai.xi   ms_insert_list_after (&pDev->dev_list, &pHcd->hcd_dev_list);
952*53ee8cc1Swenshuai.xi 
953*53ee8cc1Swenshuai.xi   iUdev->hcpriv = pDev;
954*53ee8cc1Swenshuai.xi   osapi_spin_unlock_irqrestore (&hcd_data_lock, u32Flags);
955*53ee8cc1Swenshuai.xi 
956*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
957*53ee8cc1Swenshuai.xi   return iRet;
958*53ee8cc1Swenshuai.xi }
959*53ee8cc1Swenshuai.xi 
960*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
ms_urb_unlink(struct urb * pUrb)961*53ee8cc1Swenshuai.xi void ms_urb_unlink (struct urb *pUrb)
962*53ee8cc1Swenshuai.xi {
963*53ee8cc1Swenshuai.xi   U32    u32Flags;
964*53ee8cc1Swenshuai.xi   struct usb_device  *dev;
965*53ee8cc1Swenshuai.xi 
966*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
967*53ee8cc1Swenshuai.xi   /* clear and release pUrb allocate resource */
968*53ee8cc1Swenshuai.xi   osapi_spin_lock_irqsave (&hcd_data_lock, u32Flags);
969*53ee8cc1Swenshuai.xi   ms_list_remove_and_init (&pUrb->urb_list);
970*53ee8cc1Swenshuai.xi   dev = pUrb->dev;
971*53ee8cc1Swenshuai.xi   osapi_spin_unlock_irqrestore (&hcd_data_lock, u32Flags);
972*53ee8cc1Swenshuai.xi   ms_usb_put_dev (dev);
973*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
974*53ee8cc1Swenshuai.xi }
975*53ee8cc1Swenshuai.xi 
976*53ee8cc1Swenshuai.xi /*
977*53ee8cc1Swenshuai.xi   * @brief             allocate struct usb_hcd and initial it
978*53ee8cc1Swenshuai.xi   *
979*53ee8cc1Swenshuai.xi   * @param          struct urb *urb
980*53ee8cc1Swenshuai.xi   * @param          int mem_flags
981*53ee8cc1Swenshuai.xi   *
982*53ee8cc1Swenshuai.xi   * @return           status
983*53ee8cc1Swenshuai.xi   */
984*53ee8cc1Swenshuai.xi 
ms_hcd_submit_urb(struct urb * pUrb,int iMem_flags)985*53ee8cc1Swenshuai.xi int ms_hcd_submit_urb (struct urb *pUrb, int iMem_flags)
986*53ee8cc1Swenshuai.xi {
987*53ee8cc1Swenshuai.xi   int      iStatus;
988*53ee8cc1Swenshuai.xi   struct usb_hcd    *pHcd = (struct usb_hcd*) pUrb->dev->bus->hcpriv;
989*53ee8cc1Swenshuai.xi   struct s_hcd_dev    *pDev = (struct s_hcd_dev*) pUrb->dev->hcpriv;
990*53ee8cc1Swenshuai.xi   //struct ehci_hcd    *pEhci = hcd_to_ehci (pHcd);
991*53ee8cc1Swenshuai.xi   U32    u32Flags;
992*53ee8cc1Swenshuai.xi 
993*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
994*53ee8cc1Swenshuai.xi   if (!pHcd || !pDev)
995*53ee8cc1Swenshuai.xi   {
996*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
997*53ee8cc1Swenshuai.xi     return -ENODEV;
998*53ee8cc1Swenshuai.xi   }
999*53ee8cc1Swenshuai.xi 
1000*53ee8cc1Swenshuai.xi   //pEhci->uDontSendIAA = 0;	//Set IAA interrupt (default)
1001*53ee8cc1Swenshuai.xi 
1002*53ee8cc1Swenshuai.xi   osapi_spin_lock_irqsave (&hcd_data_lock, u32Flags);
1003*53ee8cc1Swenshuai.xi   // ROOTHUB_INTERRUPT_MODE should adding urb into the list in any condition
1004*53ee8cc1Swenshuai.xi   if ((HCD_IS_RUNNING (pHcd->state) && pHcd->state != HCD_STATE_QUIESCING) || (pUrb->dev == pHcd->self.root_hub))
1005*53ee8cc1Swenshuai.xi   {
1006*53ee8cc1Swenshuai.xi     ms_usb_get_dev (pUrb->dev);
1007*53ee8cc1Swenshuai.xi     ms_insert_list_before (&pUrb->urb_list, &pDev->urb_list);
1008*53ee8cc1Swenshuai.xi     iStatus = 0;
1009*53ee8cc1Swenshuai.xi   }
1010*53ee8cc1Swenshuai.xi   else
1011*53ee8cc1Swenshuai.xi   {
1012*53ee8cc1Swenshuai.xi     ms_list_init (&pUrb->urb_list);
1013*53ee8cc1Swenshuai.xi     ms_debug_func("[ms_hcd_submit_urb] return ESHUTDOWN !!! pHcd->state = %x\n", pHcd->state);
1014*53ee8cc1Swenshuai.xi     iStatus = -ESHUTDOWN;
1015*53ee8cc1Swenshuai.xi   }
1016*53ee8cc1Swenshuai.xi   osapi_spin_unlock_irqrestore (&hcd_data_lock, u32Flags);
1017*53ee8cc1Swenshuai.xi   if (iStatus)
1018*53ee8cc1Swenshuai.xi     return iStatus;
1019*53ee8cc1Swenshuai.xi 
1020*53ee8cc1Swenshuai.xi   pUrb = ms_usb_get_urb (pUrb);
1021*53ee8cc1Swenshuai.xi   if (pUrb->dev == pHcd->self.root_hub)
1022*53ee8cc1Swenshuai.xi   {
1023*53ee8cc1Swenshuai.xi     pUrb->u32TransferFlags |= (MS_FLAG_URB_NO_TRANSFER_DMA_MAP
1024*53ee8cc1Swenshuai.xi           | MS_FLAG_URB_NO_SETUP_DMA_MAP);
1025*53ee8cc1Swenshuai.xi     iStatus = ms_rh_urb_enqueue (pHcd, pUrb);
1026*53ee8cc1Swenshuai.xi     goto done;
1027*53ee8cc1Swenshuai.xi   }
1028*53ee8cc1Swenshuai.xi 
1029*53ee8cc1Swenshuai.xi   if (pHcd->controller->dma_mask)
1030*53ee8cc1Swenshuai.xi   {
1031*53ee8cc1Swenshuai.xi   }
1032*53ee8cc1Swenshuai.xi   else
1033*53ee8cc1Swenshuai.xi   {
1034*53ee8cc1Swenshuai.xi     // Non DMA support
1035*53ee8cc1Swenshuai.xi     if (usb_pipecontrol (pUrb->u32Pipe))
1036*53ee8cc1Swenshuai.xi     {
1037*53ee8cc1Swenshuai.xi         //if ((((U32) pUrb->setup_packet) & 0xF) != 0 || ((sizeof(struct usb_ctrlrequest)  & 0xF) != 0) )
1038*53ee8cc1Swenshuai.xi         if ((((U32) pUrb->pSetupPacket) & CPU_L1_CACHE_BOUND) != 0 || ((sizeof(struct usb_ctrlrequest)  & CPU_L1_CACHE_BOUND) != 0) ) // J
1039*53ee8cc1Swenshuai.xi         {
1040*53ee8cc1Swenshuai.xi             pUrb->SetDMALen = sizeof(struct usb_ctrlrequest);
1041*53ee8cc1Swenshuai.xi             //pUrb->SetDMABuf = Usb_AllocateNonCachedMemory(((pUrb->SetDMALen+15) & ~0xF));
1042*53ee8cc1Swenshuai.xi             pUrb->SetDMABuf = Usb_AllocateNonCachedMemory(((pUrb->SetDMALen+CPU_L1_CACHE_BOUND) & ~CPU_L1_CACHE_BOUND)); // J
1043*53ee8cc1Swenshuai.xi             USB_ASSERT(pUrb->SetDMABuf != NULL, "Allocate SetDMABuf error\n");
1044*53ee8cc1Swenshuai.xi 
1045*53ee8cc1Swenshuai.xi             memcpy(pUrb->SetDMABuf, pUrb->pSetupPacket, pUrb->SetDMALen);
1046*53ee8cc1Swenshuai.xi             //HAL_DCACHE_FLUSH((void*) pUrb->SetDMABuf, pUrb->SetDMALen);
1047*53ee8cc1Swenshuai.xi 
1048*53ee8cc1Swenshuai.xi             pUrb->tSetupDma = (dma_addr_t) USB_VA2PA((U32)pUrb->SetDMABuf);
1049*53ee8cc1Swenshuai.xi             //diag_printf("[1]SetDMA address %x SetDMA length %x\n", pUrb->tSetupDma, pUrb->SetDMALen);
1050*53ee8cc1Swenshuai.xi         }
1051*53ee8cc1Swenshuai.xi         else
1052*53ee8cc1Swenshuai.xi         {
1053*53ee8cc1Swenshuai.xi             if ( pUrb->pSetupPacket != KSEG02KSEG1(pUrb->pSetupPacket) )
1054*53ee8cc1Swenshuai.xi                 MsOS_Dcache_Flush((U32) pUrb->pSetupPacket, sizeof(struct usb_ctrlrequest));
1055*53ee8cc1Swenshuai.xi 
1056*53ee8cc1Swenshuai.xi             pUrb->tSetupDma = (dma_addr_t) USB_VA2PA((U32)pUrb->pSetupPacket);
1057*53ee8cc1Swenshuai.xi             //diag_printf("[2]Setup DMA address %x DMA length %x\n", pUrb->tSetupDma, sizeof(struct usb_ctrlrequest));
1058*53ee8cc1Swenshuai.xi         }
1059*53ee8cc1Swenshuai.xi         USB_ASSERT((pUrb->tSetupDma & 0xF) == 0, "DMA address is not 16 bytes aligned\n");
1060*53ee8cc1Swenshuai.xi 
1061*53ee8cc1Swenshuai.xi    }
1062*53ee8cc1Swenshuai.xi 
1063*53ee8cc1Swenshuai.xi     if (pUrb->u32TransferBufferLength != 0)
1064*53ee8cc1Swenshuai.xi     {
1065*53ee8cc1Swenshuai.xi         {
1066*53ee8cc1Swenshuai.xi             //if ((((U32) pUrb->transfer_buffer) & 0xF) != 0 || ((pUrb->transfer_buffer_length  & 0xF) != 0) )
1067*53ee8cc1Swenshuai.xi             if ((((U32) pUrb->pTransferBuffer) & CPU_L1_CACHE_BOUND) != 0 || ((pUrb->u32TransferBufferLength  & CPU_L1_CACHE_BOUND) != 0) ) // 20161227, for short buffer
1068*53ee8cc1Swenshuai.xi             {
1069*53ee8cc1Swenshuai.xi                 //diag_printf("<ms_hcd_submit_urb> bouncing A[%x], L[%d]\n", pUrb->pTransferBuffer, pUrb->u32TransferBufferLength);
1070*53ee8cc1Swenshuai.xi                 #ifdef DEBUG_PERFORMANCE
1071*53ee8cc1Swenshuai.xi                 if (pUrb->u32TransferBufferLength >= 512)
1072*53ee8cc1Swenshuai.xi                     ms_debug_msg("DMA address %x DMA length %x\n", pUrb->pTransferBuffer, pUrb->u32TransferBufferLength);
1073*53ee8cc1Swenshuai.xi                 #endif
1074*53ee8cc1Swenshuai.xi                 pUrb->TxDMALen= pUrb->u32TransferBufferLength;
1075*53ee8cc1Swenshuai.xi                 //pUrb->TxDMABuf = Usb_AllocateNonCachedMemory(((pUrb->TxDMALen+15) & ~0xF));
1076*53ee8cc1Swenshuai.xi                 pUrb->TxDMABuf = Usb_AllocateNonCachedMemory(((pUrb->TxDMALen+CPU_L1_CACHE_BOUND) & ~CPU_L1_CACHE_BOUND)); // J
1077*53ee8cc1Swenshuai.xi                 USB_ASSERT(pUrb->TxDMABuf != NULL, "Allocate TxDMABuf error\n");
1078*53ee8cc1Swenshuai.xi 
1079*53ee8cc1Swenshuai.xi                 if (!usb_pipein(pUrb->u32Pipe))
1080*53ee8cc1Swenshuai.xi                 {
1081*53ee8cc1Swenshuai.xi                     memcpy(pUrb->TxDMABuf, pUrb->pTransferBuffer, pUrb->u32TransferBufferLength);
1082*53ee8cc1Swenshuai.xi                 }
1083*53ee8cc1Swenshuai.xi 
1084*53ee8cc1Swenshuai.xi                 pUrb->tTransferDma= (dma_addr_t) USB_VA2PA((U32)pUrb->TxDMABuf);
1085*53ee8cc1Swenshuai.xi                 //diag_printf("TxDMA address %x TxDMA length %x\n", pUrb->tTransferDma, pUrb->TxDMALen);
1086*53ee8cc1Swenshuai.xi             }
1087*53ee8cc1Swenshuai.xi             else
1088*53ee8cc1Swenshuai.xi             {
1089*53ee8cc1Swenshuai.xi                 if (  pUrb->pTransferBuffer != KSEG02KSEG1(pUrb->pTransferBuffer) )
1090*53ee8cc1Swenshuai.xi                 {
1091*53ee8cc1Swenshuai.xi                     if (usb_pipein(pUrb->u32Pipe))
1092*53ee8cc1Swenshuai.xi                     {
1093*53ee8cc1Swenshuai.xi                         //MsOS_Dcache_Invalidate((U32) pUrb->transfer_buffer, pUrb->transfer_buffer_length);
1094*53ee8cc1Swenshuai.xi                         MsOS_Dcache_Flush((U32) pUrb->pTransferBuffer, pUrb->u32TransferBufferLength);
1095*53ee8cc1Swenshuai.xi                         //MsOS_Dcache_Invalidate((U32) pUrb->pTransferBuffer, pUrb->u32TransferBufferLength);
1096*53ee8cc1Swenshuai.xi                         /* MsOS_Dcache_Invalidate seems to cause stack crashed... , change to MsOS_Dcache_Flush temporiarly */
1097*53ee8cc1Swenshuai.xi                     }
1098*53ee8cc1Swenshuai.xi                     else
1099*53ee8cc1Swenshuai.xi                         MsOS_Dcache_Flush((U32) pUrb->pTransferBuffer, pUrb->u32TransferBufferLength);
1100*53ee8cc1Swenshuai.xi 
1101*53ee8cc1Swenshuai.xi                 }
1102*53ee8cc1Swenshuai.xi 
1103*53ee8cc1Swenshuai.xi                 pUrb->tTransferDma= (dma_addr_t) USB_VA2PA((U32)pUrb->pTransferBuffer);
1104*53ee8cc1Swenshuai.xi                 //diag_printf("DMA address %x DMA length %x, transfer buffer (%x, %x)\n", pUrb->tTransferDma, pUrb->u32TransferBufferLength, pUrb->pTransferBuffer, KSEG02KSEG1(pUrb->pTransferBuffer));
1105*53ee8cc1Swenshuai.xi             }
1106*53ee8cc1Swenshuai.xi         }
1107*53ee8cc1Swenshuai.xi         USB_ASSERT((pUrb->tTransferDma & 0xF) == 0, "DMA address is not 16 bytes aligned\n");
1108*53ee8cc1Swenshuai.xi     }
1109*53ee8cc1Swenshuai.xi   }
1110*53ee8cc1Swenshuai.xi 
1111*53ee8cc1Swenshuai.xi   iStatus = pHcd->ms_urb_enqueue (pHcd, pUrb, iMem_flags);
1112*53ee8cc1Swenshuai.xi done:
1113*53ee8cc1Swenshuai.xi   if (iStatus)
1114*53ee8cc1Swenshuai.xi   {
1115*53ee8cc1Swenshuai.xi     if (pUrb->SetDMABuf != NULL)
1116*53ee8cc1Swenshuai.xi     {
1117*53ee8cc1Swenshuai.xi         Usb_FreeNonCachedMemory(pUrb->SetDMABuf);
1118*53ee8cc1Swenshuai.xi         pUrb->SetDMABuf = NULL;
1119*53ee8cc1Swenshuai.xi     }
1120*53ee8cc1Swenshuai.xi     if (pUrb->TxDMABuf != NULL)
1121*53ee8cc1Swenshuai.xi     {
1122*53ee8cc1Swenshuai.xi         Usb_FreeNonCachedMemory(pUrb->TxDMABuf);
1123*53ee8cc1Swenshuai.xi         pUrb->TxDMABuf = NULL;
1124*53ee8cc1Swenshuai.xi     }
1125*53ee8cc1Swenshuai.xi     if (!usb_pipecontrol(pUrb->u32Pipe))
1126*53ee8cc1Swenshuai.xi         diag_printf("[UM] submit_urb fail @ done, rval %d\n", iStatus);
1127*53ee8cc1Swenshuai.xi     ms_urb_unlink (pUrb);
1128*53ee8cc1Swenshuai.xi     usb_put_urb (pUrb);
1129*53ee8cc1Swenshuai.xi   }
1130*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1131*53ee8cc1Swenshuai.xi   return iStatus;
1132*53ee8cc1Swenshuai.xi }
1133*53ee8cc1Swenshuai.xi 
1134*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
1135*53ee8cc1Swenshuai.xi int
ms_unlink1(struct usb_hcd * pHcd,struct urb * pUrb)1136*53ee8cc1Swenshuai.xi ms_unlink1 (struct usb_hcd *pHcd, struct urb *pUrb)
1137*53ee8cc1Swenshuai.xi {
1138*53ee8cc1Swenshuai.xi 	int    retval = 0;
1139*53ee8cc1Swenshuai.xi 
1140*53ee8cc1Swenshuai.xi 	ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1141*53ee8cc1Swenshuai.xi 
1142*53ee8cc1Swenshuai.xi 	if (pUrb->dev->parent == NULL)
1143*53ee8cc1Swenshuai.xi 		ms_rh_status_dequeue(pHcd, pUrb);
1144*53ee8cc1Swenshuai.xi 	else
1145*53ee8cc1Swenshuai.xi 	{
1146*53ee8cc1Swenshuai.xi                 retval = pHcd->ms_urb_dequeue(pHcd, pUrb);
1147*53ee8cc1Swenshuai.xi 	}
1148*53ee8cc1Swenshuai.xi 	if (retval != 0)
1149*53ee8cc1Swenshuai.xi 		ms_debug_err("[unlink1] dequeue %p --> %d\n", pUrb, retval);
1150*53ee8cc1Swenshuai.xi 
1151*53ee8cc1Swenshuai.xi 	ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1152*53ee8cc1Swenshuai.xi 	return retval;
1153*53ee8cc1Swenshuai.xi }
1154*53ee8cc1Swenshuai.xi 
1155*53ee8cc1Swenshuai.xi /* create completion splice to add "done" when the completion
1156*53ee8cc1Swenshuai.xi  * function is called, thus urb done is guaranteed
1157*53ee8cc1Swenshuai.xi  */
1158*53ee8cc1Swenshuai.xi struct ms_completion_splice {    // for modified urb context
1159*53ee8cc1Swenshuai.xi   struct stCompletion  done;
1160*53ee8cc1Swenshuai.xi   usb_complete_t    stComplete;
1161*53ee8cc1Swenshuai.xi   void      *pContext;
1162*53ee8cc1Swenshuai.xi };
1163*53ee8cc1Swenshuai.xi 
ms_unlink_complete(struct urb * pUrb,struct stPtRegs * pRegs)1164*53ee8cc1Swenshuai.xi static void ms_unlink_complete (struct urb *pUrb, struct stPtRegs *pRegs)
1165*53ee8cc1Swenshuai.xi {
1166*53ee8cc1Swenshuai.xi   struct ms_completion_splice  *pSplice;
1167*53ee8cc1Swenshuai.xi 
1168*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1169*53ee8cc1Swenshuai.xi   pSplice = (struct ms_completion_splice *) pUrb->pContext;
1170*53ee8cc1Swenshuai.xi   pUrb->complete_func = pSplice->stComplete;
1171*53ee8cc1Swenshuai.xi   pUrb->pContext = pSplice->pContext;
1172*53ee8cc1Swenshuai.xi   pUrb->complete_func (pUrb, pRegs);  //Callback function
1173*53ee8cc1Swenshuai.xi   complete (&pSplice->done);
1174*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1175*53ee8cc1Swenshuai.xi }
1176*53ee8cc1Swenshuai.xi 
ms_hcd_unlink_urb(struct urb * pUrb,int sts)1177*53ee8cc1Swenshuai.xi int ms_hcd_unlink_urb (struct urb *pUrb, int sts)
1178*53ee8cc1Swenshuai.xi {
1179*53ee8cc1Swenshuai.xi   struct s_hcd_dev      *dev;
1180*53ee8cc1Swenshuai.xi   struct usb_hcd      *pHcd = 0;
1181*53ee8cc1Swenshuai.xi   //struct device_s      *pSys = 0;
1182*53ee8cc1Swenshuai.xi   U32      u32Flags;
1183*53ee8cc1Swenshuai.xi   struct ms_completion_splice  stSplice;
1184*53ee8cc1Swenshuai.xi   int        iRetval = 0;
1185*53ee8cc1Swenshuai.xi   U32    u32Cnt = 0;
1186*53ee8cc1Swenshuai.xi 
1187*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1188*53ee8cc1Swenshuai.xi   //if (!pUrb)
1189*53ee8cc1Swenshuai.xi   //{
1190*53ee8cc1Swenshuai.xi   //  ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1191*53ee8cc1Swenshuai.xi   //  return -EINVAL;
1192*53ee8cc1Swenshuai.xi   //}
1193*53ee8cc1Swenshuai.xi 
1194*53ee8cc1Swenshuai.xi   osapi_spin_lock_irqsave (&pUrb->lock, u32Flags);
1195*53ee8cc1Swenshuai.xi   osapi_spin_lock (&hcd_data_lock);
1196*53ee8cc1Swenshuai.xi 
1197*53ee8cc1Swenshuai.xi   if (!pUrb->dev || !pUrb->dev->bus)
1198*53ee8cc1Swenshuai.xi   {
1199*53ee8cc1Swenshuai.xi     iRetval = -ENODEV;
1200*53ee8cc1Swenshuai.xi     goto done;
1201*53ee8cc1Swenshuai.xi   }
1202*53ee8cc1Swenshuai.xi 
1203*53ee8cc1Swenshuai.xi   dev = (struct s_hcd_dev*) pUrb->dev->hcpriv;
1204*53ee8cc1Swenshuai.xi   //pSys = &pUrb->dev->dev;
1205*53ee8cc1Swenshuai.xi   pHcd = (struct usb_hcd*) pUrb->dev->bus->hcpriv;
1206*53ee8cc1Swenshuai.xi   if (!dev || !pHcd)
1207*53ee8cc1Swenshuai.xi   {
1208*53ee8cc1Swenshuai.xi     iRetval = -ENODEV;
1209*53ee8cc1Swenshuai.xi     goto done;
1210*53ee8cc1Swenshuai.xi   }
1211*53ee8cc1Swenshuai.xi 
1212*53ee8cc1Swenshuai.xi   if (!pUrb->hcpriv)
1213*53ee8cc1Swenshuai.xi   {
1214*53ee8cc1Swenshuai.xi     iRetval = -EINVAL;
1215*53ee8cc1Swenshuai.xi     goto done;
1216*53ee8cc1Swenshuai.xi   }
1217*53ee8cc1Swenshuai.xi 
1218*53ee8cc1Swenshuai.xi   if (pUrb->s32Status != -EINPROGRESS)
1219*53ee8cc1Swenshuai.xi   {
1220*53ee8cc1Swenshuai.xi     iRetval = -EBUSY;
1221*53ee8cc1Swenshuai.xi     goto done;
1222*53ee8cc1Swenshuai.xi   }
1223*53ee8cc1Swenshuai.xi 
1224*53ee8cc1Swenshuai.xi   //if (!(pUrb->u32TransferFlags & MS_FLAG_URB_ASYNC_UNLINK))
1225*53ee8cc1Swenshuai.xi   {
1226*53ee8cc1Swenshuai.xi     init_completion (&stSplice.done);
1227*53ee8cc1Swenshuai.xi     stSplice.stComplete = pUrb->complete_func;
1228*53ee8cc1Swenshuai.xi     stSplice.pContext = pUrb->pContext;
1229*53ee8cc1Swenshuai.xi     pUrb->complete_func = ms_unlink_complete;
1230*53ee8cc1Swenshuai.xi     pUrb->pContext = &stSplice;
1231*53ee8cc1Swenshuai.xi     //pUrb->s32Status = -ENOENT;
1232*53ee8cc1Swenshuai.xi   }
1233*53ee8cc1Swenshuai.xi   //else
1234*53ee8cc1Swenshuai.xi   //{
1235*53ee8cc1Swenshuai.xi   //  pUrb->s32Status = -ECONNRESET;
1236*53ee8cc1Swenshuai.xi   //}
1237*53ee8cc1Swenshuai.xi   pUrb->s32Status = sts;
1238*53ee8cc1Swenshuai.xi   osapi_spin_unlock (&hcd_data_lock);
1239*53ee8cc1Swenshuai.xi   osapi_spin_unlock_irqrestore (&pUrb->lock, u32Flags);
1240*53ee8cc1Swenshuai.xi 
1241*53ee8cc1Swenshuai.xi   iRetval = ms_unlink1(pHcd, pUrb);
1242*53ee8cc1Swenshuai.xi   if (iRetval)
1243*53ee8cc1Swenshuai.xi   {
1244*53ee8cc1Swenshuai.xi     ms_debug_err ("<%s> dequeue %p --> %d\n", __FUNCTION__, pUrb, iRetval);
1245*53ee8cc1Swenshuai.xi     if (!(pUrb->u32TransferFlags & MS_FLAG_URB_ASYNC_UNLINK))
1246*53ee8cc1Swenshuai.xi     {
1247*53ee8cc1Swenshuai.xi       osapi_spin_lock_irqsave (&pUrb->lock, u32Flags);
1248*53ee8cc1Swenshuai.xi       pUrb->complete_func = stSplice.stComplete;
1249*53ee8cc1Swenshuai.xi       pUrb->pContext = stSplice.pContext;
1250*53ee8cc1Swenshuai.xi       osapi_spin_unlock_irqrestore (&pUrb->lock, u32Flags);
1251*53ee8cc1Swenshuai.xi     }
1252*53ee8cc1Swenshuai.xi     goto bye;
1253*53ee8cc1Swenshuai.xi   }
1254*53ee8cc1Swenshuai.xi   //if (pUrb == (struct urb *) pHcd->roothub_timer.data)
1255*53ee8cc1Swenshuai.xi   //if (pUrb->dev->parent == NULL)
1256*53ee8cc1Swenshuai.xi   //{
1257*53ee8cc1Swenshuai.xi   //  ms_rh_status_dequeue (pHcd, pUrb);
1258*53ee8cc1Swenshuai.xi   //  iRetval = 0;
1259*53ee8cc1Swenshuai.xi   //}
1260*53ee8cc1Swenshuai.xi   //else
1261*53ee8cc1Swenshuai.xi   //{
1262*53ee8cc1Swenshuai.xi   //  iRetval = pHcd->ms_urb_dequeue (pHcd, pUrb);
1263*53ee8cc1Swenshuai.xi   //
1264*53ee8cc1Swenshuai.xi   //  if (iRetval)
1265*53ee8cc1Swenshuai.xi   //  {
1266*53ee8cc1Swenshuai.xi   //    ms_debug_err ("<%s> dequeue %p --> %d\n", __FUNCTION__, pUrb, iRetval);
1267*53ee8cc1Swenshuai.xi   //    if (!(pUrb->u32TransferFlags & MS_FLAG_URB_ASYNC_UNLINK))
1268*53ee8cc1Swenshuai.xi   //    {
1269*53ee8cc1Swenshuai.xi   //      osapi_spin_lock_irqsave (&pUrb->lock, u32Flags);
1270*53ee8cc1Swenshuai.xi   //      pUrb->complete_func = stSplice.stComplete;
1271*53ee8cc1Swenshuai.xi   //      pUrb->pContext = stSplice.pContext;
1272*53ee8cc1Swenshuai.xi   //      osapi_spin_unlock_irqrestore (&pUrb->lock, u32Flags);
1273*53ee8cc1Swenshuai.xi   //    }
1274*53ee8cc1Swenshuai.xi   //    goto bye;
1275*53ee8cc1Swenshuai.xi   //  }
1276*53ee8cc1Swenshuai.xi   //}
1277*53ee8cc1Swenshuai.xi 
1278*53ee8cc1Swenshuai.xi   if (pUrb->u32TransferFlags & MS_FLAG_URB_ASYNC_UNLINK)
1279*53ee8cc1Swenshuai.xi   {
1280*53ee8cc1Swenshuai.xi     ms_debug_err("<%s> MS_FLAG_URB_ASYNC_UNLINK\n", __FUNCTION__);
1281*53ee8cc1Swenshuai.xi     return -EINPROGRESS;
1282*53ee8cc1Swenshuai.xi   }
1283*53ee8cc1Swenshuai.xi 
1284*53ee8cc1Swenshuai.xi   while ( stSplice.done.done == 0 )
1285*53ee8cc1Swenshuai.xi   {
1286*53ee8cc1Swenshuai.xi     if ( u32Cnt > (U32) 3000)
1287*53ee8cc1Swenshuai.xi     {
1288*53ee8cc1Swenshuai.xi       break;
1289*53ee8cc1Swenshuai.xi     }
1290*53ee8cc1Swenshuai.xi     else
1291*53ee8cc1Swenshuai.xi     {
1292*53ee8cc1Swenshuai.xi       //tick base is 1 ms
1293*53ee8cc1Swenshuai.xi       mdelay(1);
1294*53ee8cc1Swenshuai.xi       //HAL_DELAY_US(1000); // NUSED
1295*53ee8cc1Swenshuai.xi       u32Cnt+=1;
1296*53ee8cc1Swenshuai.xi     }
1297*53ee8cc1Swenshuai.xi   }
1298*53ee8cc1Swenshuai.xi 
1299*53ee8cc1Swenshuai.xi   if (u32Cnt > (U32) 3000)
1300*53ee8cc1Swenshuai.xi   {
1301*53ee8cc1Swenshuai.xi      ms_debug_err("<ms_hcd_unlink_urb> timeout!!!\n");
1302*53ee8cc1Swenshuai.xi      /* restore urb status */
1303*53ee8cc1Swenshuai.xi      osapi_spin_lock_irqsave (&pUrb->lock, u32Flags);
1304*53ee8cc1Swenshuai.xi      pUrb->complete_func = stSplice.stComplete;
1305*53ee8cc1Swenshuai.xi      pUrb->pContext = stSplice.pContext;
1306*53ee8cc1Swenshuai.xi      pUrb->s32Status = -ETIMEDOUT;
1307*53ee8cc1Swenshuai.xi      osapi_spin_unlock_irqrestore (&pUrb->lock, u32Flags);
1308*53ee8cc1Swenshuai.xi      //diag_printf("\n\n\n\n\n\n");
1309*53ee8cc1Swenshuai.xi      //ms_debug_err("<ms_hcd_unlink_urb> timeout!!!\n");
1310*53ee8cc1Swenshuai.xi      //diag_printf("\n\n\n\n\n\n");
1311*53ee8cc1Swenshuai.xi 
1312*53ee8cc1Swenshuai.xi      //ms_debug_err("Reset HC HW\n"); // no effect
1313*53ee8cc1Swenshuai.xi      //ms_ResetMstarUsb(pHcd);
1314*53ee8cc1Swenshuai.xi      return -ETIMEDOUT;
1315*53ee8cc1Swenshuai.xi   }
1316*53ee8cc1Swenshuai.xi 
1317*53ee8cc1Swenshuai.xi   /* Linux code re-assign return-value here */
1318*53ee8cc1Swenshuai.xi   /* 0 -> -EINPROGRESS */
1319*53ee8cc1Swenshuai.xi   return 0;
1320*53ee8cc1Swenshuai.xi 
1321*53ee8cc1Swenshuai.xi done:
1322*53ee8cc1Swenshuai.xi   osapi_spin_unlock (&hcd_data_lock);
1323*53ee8cc1Swenshuai.xi   osapi_spin_unlock_irqrestore (&pUrb->lock, u32Flags);
1324*53ee8cc1Swenshuai.xi bye:
1325*53ee8cc1Swenshuai.xi   if (iRetval/* && pSys && pSys->driver*/)
1326*53ee8cc1Swenshuai.xi     ms_debug_err ("<ms_hcd_unlink_urb> %p fail %d\n", pUrb, iRetval);
1327*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1328*53ee8cc1Swenshuai.xi   return iRetval;
1329*53ee8cc1Swenshuai.xi }
1330*53ee8cc1Swenshuai.xi 
ms_hcd_endpoint_disable(struct usb_device * pUdev,int iEndpoint)1331*53ee8cc1Swenshuai.xi void ms_hcd_endpoint_disable (struct usb_device *pUdev, int iEndpoint)
1332*53ee8cc1Swenshuai.xi {
1333*53ee8cc1Swenshuai.xi   struct s_hcd_dev  *pDev;
1334*53ee8cc1Swenshuai.xi   struct usb_hcd  *pHcd;
1335*53ee8cc1Swenshuai.xi 
1336*53ee8cc1Swenshuai.xi   pDev = (struct s_hcd_dev*) pUdev->hcpriv;
1337*53ee8cc1Swenshuai.xi   pHcd = (struct usb_hcd*) pUdev->bus->hcpriv;
1338*53ee8cc1Swenshuai.xi 
1339*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1340*53ee8cc1Swenshuai.xi 
1341*53ee8cc1Swenshuai.xi   /* move the code to ms_usb_hcd_flush_endpoint() */
1342*53ee8cc1Swenshuai.xi   /* from: osapi_spin_lock_irq(&hcd_data_lock);
1343*53ee8cc1Swenshuai.xi    * to: osapi_spin_unlock_irq(&hcd_data_lock);
1344*53ee8cc1Swenshuai.xi    */
1345*53ee8cc1Swenshuai.xi 
1346*53ee8cc1Swenshuai.xi   ms_ehci_disable_ep(pHcd, pDev, iEndpoint);
1347*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1348*53ee8cc1Swenshuai.xi }
1349*53ee8cc1Swenshuai.xi 
ms_usb_hcd_flush_endpoint(struct usb_device * pUdev,int iEndpoint)1350*53ee8cc1Swenshuai.xi void ms_usb_hcd_flush_endpoint(struct usb_device *pUdev, int iEndpoint)
1351*53ee8cc1Swenshuai.xi {
1352*53ee8cc1Swenshuai.xi     struct list_head *__mptr;
1353*53ee8cc1Swenshuai.xi     struct s_hcd_dev  *pDev = (struct s_hcd_dev*) pUdev->hcpriv;
1354*53ee8cc1Swenshuai.xi     struct usb_hcd  *pHcd = (struct usb_hcd*) pUdev->bus->hcpriv;
1355*53ee8cc1Swenshuai.xi     struct urb  *pUrb;
1356*53ee8cc1Swenshuai.xi     U32  u32Epnum = iEndpoint & USB_ENDPOINT_NUMBER_MASK;
1357*53ee8cc1Swenshuai.xi 
1358*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1359*53ee8cc1Swenshuai.xi 
1360*53ee8cc1Swenshuai.xi     if (iEndpoint & USB_DIR_IN)
1361*53ee8cc1Swenshuai.xi     {
1362*53ee8cc1Swenshuai.xi         //usb_endpoint_halt (pUdev, u32Epnum, 0);
1363*53ee8cc1Swenshuai.xi         pUdev->pEpMaxPacketIn [u32Epnum] = 0;
1364*53ee8cc1Swenshuai.xi     }
1365*53ee8cc1Swenshuai.xi     else
1366*53ee8cc1Swenshuai.xi     {
1367*53ee8cc1Swenshuai.xi         //usb_endpoint_halt (pUdev, u32Epnum, 1);
1368*53ee8cc1Swenshuai.xi         pUdev->pEpMaxPacketOut [u32Epnum] = 0;
1369*53ee8cc1Swenshuai.xi     }
1370*53ee8cc1Swenshuai.xi 
1371*53ee8cc1Swenshuai.xi     osapi_spin_lock_irq(&hcd_data_lock);
1372*53ee8cc1Swenshuai.xi urb_rescan:
1373*53ee8cc1Swenshuai.xi     pUrb = entry_to_container((&pDev->urb_list)->next, struct urb, urb_list);
1374*53ee8cc1Swenshuai.xi     for( ; &(pUrb->urb_list) != &(pDev->urb_list);
1375*53ee8cc1Swenshuai.xi         __mptr = pUrb->urb_list.next,
1376*53ee8cc1Swenshuai.xi         pUrb = (struct urb *)( (char *)__mptr - (char *)offsetof(struct urb,urb_list) )
1377*53ee8cc1Swenshuai.xi     )
1378*53ee8cc1Swenshuai.xi     {
1379*53ee8cc1Swenshuai.xi         int  tmp = pUrb->u32Pipe;
1380*53ee8cc1Swenshuai.xi 
1381*53ee8cc1Swenshuai.xi         ms_debug_debug("[UM-FLUSH] pUrb %p hcpriv %p,pipe %08x ep%d%s, ep type = %d, status = %d\n",
1382*53ee8cc1Swenshuai.xi             pUrb, pUrb->hcpriv, tmp, usb_pipeendpoint (tmp),
1383*53ee8cc1Swenshuai.xi             (tmp & USB_DIR_IN) ? "in" : "out", usb_pipetype (tmp), pUrb->s32Status);
1384*53ee8cc1Swenshuai.xi 
1385*53ee8cc1Swenshuai.xi         if ((U32)usb_pipeendpoint (tmp) != u32Epnum)
1386*53ee8cc1Swenshuai.xi             continue;
1387*53ee8cc1Swenshuai.xi 
1388*53ee8cc1Swenshuai.xi         if (u32Epnum != 0 && ((tmp ^ iEndpoint) & USB_DIR_IN))
1389*53ee8cc1Swenshuai.xi             continue;
1390*53ee8cc1Swenshuai.xi 
1391*53ee8cc1Swenshuai.xi         if (pUrb->s32Status != -EINPROGRESS)
1392*53ee8cc1Swenshuai.xi             continue;
1393*53ee8cc1Swenshuai.xi         ms_usb_get_urb (pUrb);
1394*53ee8cc1Swenshuai.xi         osapi_spin_unlock (&hcd_data_lock);
1395*53ee8cc1Swenshuai.xi 
1396*53ee8cc1Swenshuai.xi         //osapi_spin_lock (&pUrb->lock);
1397*53ee8cc1Swenshuai.xi         //tmp = pUrb->s32Status;
1398*53ee8cc1Swenshuai.xi         //if (tmp == -EINPROGRESS)
1399*53ee8cc1Swenshuai.xi         //    pUrb->s32Status = -ESHUTDOWN;
1400*53ee8cc1Swenshuai.xi         //osapi_spin_unlock (&pUrb->lock);
1401*53ee8cc1Swenshuai.xi 
1402*53ee8cc1Swenshuai.xi         //if (tmp == -EINPROGRESS)
1403*53ee8cc1Swenshuai.xi         {
1404*53ee8cc1Swenshuai.xi             tmp = pUrb->u32Pipe;
1405*53ee8cc1Swenshuai.xi             pUrb->s32Status = -ESHUTDOWN;
1406*53ee8cc1Swenshuai.xi             ms_unlink1 (pHcd, pUrb);
1407*53ee8cc1Swenshuai.xi             ms_debug_debug("<%s> !!! shutdown pUrb %p pipe %08x ep%d%s, ep type = %d\n",
1408*53ee8cc1Swenshuai.xi                 __FUNCTION__, pUrb, tmp, usb_pipeendpoint (tmp),
1409*53ee8cc1Swenshuai.xi                 (tmp & USB_DIR_IN) ? "in" : "out", usb_pipetype (tmp));
1410*53ee8cc1Swenshuai.xi         }
1411*53ee8cc1Swenshuai.xi         usb_put_urb (pUrb);
1412*53ee8cc1Swenshuai.xi 
1413*53ee8cc1Swenshuai.xi         osapi_spin_lock (&hcd_data_lock);
1414*53ee8cc1Swenshuai.xi         goto urb_rescan;
1415*53ee8cc1Swenshuai.xi     }
1416*53ee8cc1Swenshuai.xi     osapi_spin_unlock_irq(&hcd_data_lock);
1417*53ee8cc1Swenshuai.xi 
1418*53ee8cc1Swenshuai.xi     // TODO: nuke all urb? depends on ms_hcd_check_dev_urb()'s result
1419*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1420*53ee8cc1Swenshuai.xi }
1421*53ee8cc1Swenshuai.xi 
ms_hcd_check_dev_urb(struct usb_device * pUdev,int iEndpoint)1422*53ee8cc1Swenshuai.xi void ms_hcd_check_dev_urb (struct usb_device *pUdev, int iEndpoint)
1423*53ee8cc1Swenshuai.xi {
1424*53ee8cc1Swenshuai.xi     struct list_head *__mptr;
1425*53ee8cc1Swenshuai.xi     struct s_hcd_dev  *pDev;
1426*53ee8cc1Swenshuai.xi     //struct usb_hcd  *pHcd;
1427*53ee8cc1Swenshuai.xi     struct urb  *pUrb;
1428*53ee8cc1Swenshuai.xi 
1429*53ee8cc1Swenshuai.xi     pDev = (struct s_hcd_dev*) pUdev->hcpriv;
1430*53ee8cc1Swenshuai.xi     //pHcd = (struct usb_hcd*) pUdev->bus->hcpriv;
1431*53ee8cc1Swenshuai.xi 
1432*53ee8cc1Swenshuai.xi     ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1433*53ee8cc1Swenshuai.xi     ms_debug_func("[UM-DEV-URB] urb %p, epaddr %d\n", pUrb, iEndpoint);
1434*53ee8cc1Swenshuai.xi 
1435*53ee8cc1Swenshuai.xi     osapi_spin_lock_irq(&hcd_data_lock);
1436*53ee8cc1Swenshuai.xi     pUrb = entry_to_container((&pDev->urb_list)->next, struct urb, urb_list);
1437*53ee8cc1Swenshuai.xi     for( ; &(pUrb->urb_list) != &(pDev->urb_list);
1438*53ee8cc1Swenshuai.xi         __mptr = pUrb->urb_list.next,
1439*53ee8cc1Swenshuai.xi         pUrb = (struct urb *)( (char *)__mptr - (char *)offsetof(struct urb,urb_list) )
1440*53ee8cc1Swenshuai.xi     )
1441*53ee8cc1Swenshuai.xi     {
1442*53ee8cc1Swenshuai.xi         int  tmp = pUrb->u32Pipe;
1443*53ee8cc1Swenshuai.xi 
1444*53ee8cc1Swenshuai.xi         diag_printf ("[UM-DEV-URB] pUrb %p (qh %p) pipe %08x ep%d%s, ep type = %d, status = %d\n",
1445*53ee8cc1Swenshuai.xi             pUrb, pUrb->hcpriv, tmp, usb_pipeendpoint (tmp),
1446*53ee8cc1Swenshuai.xi             (tmp & USB_DIR_IN) ? "in" : "out", usb_pipetype (tmp), pUrb->s32Status);
1447*53ee8cc1Swenshuai.xi     }
1448*53ee8cc1Swenshuai.xi     osapi_spin_unlock_irq(&hcd_data_lock);
1449*53ee8cc1Swenshuai.xi     ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1450*53ee8cc1Swenshuai.xi }
1451*53ee8cc1Swenshuai.xi 
1452*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
ms_hcd_free_dev(struct usb_device * pUdev)1453*53ee8cc1Swenshuai.xi int ms_hcd_free_dev (struct usb_device *pUdev)
1454*53ee8cc1Swenshuai.xi {
1455*53ee8cc1Swenshuai.xi   struct s_hcd_dev    *pDev;
1456*53ee8cc1Swenshuai.xi   struct usb_hcd    *pHcd;
1457*53ee8cc1Swenshuai.xi   U32    u32Flags;
1458*53ee8cc1Swenshuai.xi   int iRet = ENOERR;
1459*53ee8cc1Swenshuai.xi 
1460*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1461*53ee8cc1Swenshuai.xi   if (!pUdev || !pUdev->hcpriv)
1462*53ee8cc1Swenshuai.xi   {
1463*53ee8cc1Swenshuai.xi     iRet = -EINVAL;
1464*53ee8cc1Swenshuai.xi     goto hcd_free_dev_err;
1465*53ee8cc1Swenshuai.xi   }
1466*53ee8cc1Swenshuai.xi 
1467*53ee8cc1Swenshuai.xi   if (!pUdev->bus || !pUdev->bus->hcpriv)
1468*53ee8cc1Swenshuai.xi   {
1469*53ee8cc1Swenshuai.xi     iRet = -ENODEV;
1470*53ee8cc1Swenshuai.xi     goto hcd_free_dev_err;
1471*53ee8cc1Swenshuai.xi   }
1472*53ee8cc1Swenshuai.xi 
1473*53ee8cc1Swenshuai.xi   // should pUdev->devnum == -1 ??
1474*53ee8cc1Swenshuai.xi 
1475*53ee8cc1Swenshuai.xi   pDev = (struct s_hcd_dev*) pUdev->hcpriv;
1476*53ee8cc1Swenshuai.xi   pHcd = (struct usb_hcd*) pUdev->bus->hcpriv;
1477*53ee8cc1Swenshuai.xi 
1478*53ee8cc1Swenshuai.xi   if (!ms_is_empty_list (&pDev->urb_list))
1479*53ee8cc1Swenshuai.xi   {
1480*53ee8cc1Swenshuai.xi     ms_debug_err ("free busy pDev, %s devnum %d (bug!)\n",
1481*53ee8cc1Swenshuai.xi       pHcd->self.bus_name, (int)pUdev->u32DevNum);
1482*53ee8cc1Swenshuai.xi     iRet = -EINVAL;
1483*53ee8cc1Swenshuai.xi     goto hcd_free_dev_err;
1484*53ee8cc1Swenshuai.xi   }
1485*53ee8cc1Swenshuai.xi 
1486*53ee8cc1Swenshuai.xi   osapi_spin_lock_irqsave (&hcd_data_lock, u32Flags);
1487*53ee8cc1Swenshuai.xi   ms_list_remove (&pDev->dev_list);
1488*53ee8cc1Swenshuai.xi   pUdev->hcpriv = NULL;
1489*53ee8cc1Swenshuai.xi   osapi_spin_unlock_irqrestore (&hcd_data_lock, u32Flags);
1490*53ee8cc1Swenshuai.xi 
1491*53ee8cc1Swenshuai.xi   kfree (pDev);
1492*53ee8cc1Swenshuai.xi 
1493*53ee8cc1Swenshuai.xi hcd_free_dev_err:
1494*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1495*53ee8cc1Swenshuai.xi   return iRet;
1496*53ee8cc1Swenshuai.xi }
1497*53ee8cc1Swenshuai.xi 
1498*53ee8cc1Swenshuai.xi /* bus op obsolete */
1499*53ee8cc1Swenshuai.xi /*
1500*53ee8cc1Swenshuai.xi //struct ms_usb_bus_ops ms_usb_hcd_operations = {
1501*53ee8cc1Swenshuai.xi //  ms_hcd_alloc_dev,
1502*53ee8cc1Swenshuai.xi //  ms_hcd_free_dev,
1503*53ee8cc1Swenshuai.xi //  ms_hcd_submit_urb,
1504*53ee8cc1Swenshuai.xi //  ms_hcd_unlink_urb,
1505*53ee8cc1Swenshuai.xi //  ms_hcd_buffer_alloc,
1506*53ee8cc1Swenshuai.xi //  ms_hcd_buffer_free,
1507*53ee8cc1Swenshuai.xi //  ms_hcd_endpoint_disable,
1508*53ee8cc1Swenshuai.xi //};
1509*53ee8cc1Swenshuai.xi */
1510*53ee8cc1Swenshuai.xi 
1511*53ee8cc1Swenshuai.xi extern void ms_usb_set_dma_buf(struct urb *request_block);
1512*53ee8cc1Swenshuai.xi extern void ms_usb_set_tx_dma_buf(struct urb *request_block);
1513*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
ms_usb_hcd_giveback_urb(struct urb * urb,struct stPtRegs * regs)1514*53ee8cc1Swenshuai.xi void ms_usb_hcd_giveback_urb (struct urb *urb, struct stPtRegs *regs)
1515*53ee8cc1Swenshuai.xi {
1516*53ee8cc1Swenshuai.xi   ms_debug_func("++[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1517*53ee8cc1Swenshuai.xi   ms_urb_unlink (urb);
1518*53ee8cc1Swenshuai.xi 
1519*53ee8cc1Swenshuai.xi   /* local setup/tx DMA buffer should be dealed with here, complete function may
1520*53ee8cc1Swenshuai.xi     lack of such mechanism */
1521*53ee8cc1Swenshuai.xi   ms_usb_set_dma_buf(urb);
1522*53ee8cc1Swenshuai.xi   ms_usb_set_tx_dma_buf(urb);
1523*53ee8cc1Swenshuai.xi 
1524*53ee8cc1Swenshuai.xi   urb->complete_func (urb, regs);
1525*53ee8cc1Swenshuai.xi   usb_put_urb (urb);
1526*53ee8cc1Swenshuai.xi   ms_debug_func("--[%s] line:[%d]\n", __FUNCTION__, __LINE__);
1527*53ee8cc1Swenshuai.xi }
1528*53ee8cc1Swenshuai.xi /*-------------------------------------------------------------------------*/
1529