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