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 #include "include/drvConfig.h"
79 #include "include/drvPorts.h"
80 #include "include/drvKernel.h"
81 #include "include/drvTimer.h"
82 #include "include/drvUSBMsg.h"
83
84 #include "drvHCD.h"
85 #include "drvMassStor.h"
86 #include "include/drvCPE_EHCI.h"
87 #include "MsCommon.h"
88 #include "drvUSB.h"
89 #include "include/drvIO.h"
90 #include "drvUSBHwCtl.h"
91 #include "include/drvCPE_AMBA.h"
92 #include "drvSCSI.h"
93 #include "drvEHCI.h"
94 #if USB_HID_SUPPORT
95 #include "drvHIDDev.h"
96 #endif
97
98 #define USBENT_DEBUG
99 #ifdef USBENT_DEBUG
100 #define USBENT_Dbg diag_printf
101 #else
102 #define USBENT_Dbg(x,...)
103 #endif
104
105 #define USBENT_ERR diag_printf
106
107 MS_BOOL UsbReady_Port2 = FALSE;
108
109 #ifndef MS_NOSAPI
110 /*static*/ MS_U8 u8HubStackBuffer_Port2[HUB_STACK_SIZE];
111 #endif
112
113 extern struct usb_hcd *g_pUsbHcd_Port2;
114 #if USB_HID_SUPPORT
115 extern MS_U32 Invalid_HidDevs;
116 extern U8 Hid_Report_Desc[0x100];
117 extern void usb_hid_parse_report(
118 U8 *start,
119 U16 size,
120 struct button_struct *pButton,
121 struct axis_struct *pAxis,
122 struct key_struct *pKeys);
123 #endif
124 extern struct cpe_dev cpe_ehci_dev_Port2;
125
126 extern void USBCriticalSectionIn(MS_U8 Port);
127 extern void USBCriticalSectionOut(MS_U8 Port);
128
129 extern void hub_poll_Port2(void);
130 extern BOOL has_hub_events_Port2(U16 *pPortStatus);
131 extern int PortReset(unsigned int regUTMI, unsigned int regUHC);
132
133 extern S32 _s32MutexUSB_Port2;
134
135 extern MS_BOOL MDrv_UsbDeviceConnect_EX(struct usb_hcd *hcd);
136 extern void ResetMstarUsb(struct ehci_hcd *ehci); // replace void ResetUsbHardware_Port2(void) and moved to drvUSBHwCtl.c
MDrv_UsbDeviceConnect_Port2(struct usb_hcd * hcd)137 MS_BOOL MDrv_UsbDeviceConnect_Port2(struct usb_hcd *hcd)
138 {
139 if (MDrv_UsbDeviceConnect_EX(hcd))
140 return TRUE;
141 else
142 return(UsbReady_Port2 = FALSE);
143 }
144
145 extern struct s_ChipUsbHostDef *pCurrentChip;
146 extern USBCallback _DrvUSBC_CBFun;
147 extern BOOL usb_get_connected_dev_state(int *pdevstate, unsigned char *pDevClass, struct usb_hcd *hcd);
UsbTask_Port2(MS_U32 argc,VOID * argv)148 void UsbTask_Port2(MS_U32 argc, VOID *argv)
149 {
150 MS_U16 PortStatus;
151 MS_BOOL isExtHubConnect, isFirstEvent, isConnect;
152 int DevState;
153 MS_U8 DevClass, ii, kk;
154 MS_U8 LunSts[MAX_USB_STOR_LUNS];
155 MS_U8 LunPreSts[MAX_USB_STOR_LUNS];
156 MS_BOOL isMSCPlugIn;
157 #if USB_HID_SUPPORT
158 MS_U8 jj;
159 MS_BOOL isHIDPlugIn, isHIDPlugIntoSamePort;
160 MS_U8 isHIDPlugIn_IntfCnt;
161 #endif
162 MS_U8 us_id;
163 struct ehci_hcd *ehci = hcd_to_ehci(g_pUsbHcd_Port2);
164
165 diag_printf("UsbTask 2...\n");
166 while (1)
167 {
168 //UsbReady_Port2=FALSE; //move to MDrv_UsbDeviceConnect_Port2
169 isExtHubConnect = FALSE;
170 isMSCPlugIn = FALSE;
171 #if USB_HID_SUPPORT
172 isHIDPlugIn = FALSE;
173 #endif
174
175 // Waiting for USB port connection
176 while(1)
177 {
178 USBCriticalSectionIn(2);
179 isConnect = MDrv_UsbDeviceConnect_Port2(g_pUsbHcd_Port2);
180 USBCriticalSectionOut(2);
181
182 #if USBC_IP_SUPPORT // USBC IP control
183 {
184 U8 idx = 1;
185
186 if (pCurrentChip->chipID == CHIPID_URANUS4)
187 idx = 2;
188 if ((pCurrentChip->usbc_ip[idx].portNum == idx) && (pCurrentChip->usbc_ip[idx].eventFlag))
189 if (_DrvUSBC_CBFun)
190 {
191 if (pCurrentChip->usbc_ip[idx].eventType)
192 _DrvUSBC_CBFun(USBC_NON_OVER_CURRENT, idx, NULL);
193 else
194 _DrvUSBC_CBFun(USBC_OVER_CURRENT, idx, NULL);
195 pCurrentChip->usbc_ip[idx].eventFlag = 0;
196 }
197 }
198 #endif
199 if(isConnect)
200 break;
201 MsOS_DelayTask(100);
202 }
203
204 //MsOS_DelayTask(1000);
205 //diag_printf("USB Port 2 is connect\n");
206
207 while (1)
208 {
209 if (g_pUsbHcd_Port2->isBadDevice)
210 {
211 diag_printf("A bad device found on port 2\n");
212 break;
213 }
214
215 kk = 0;
216 while(kk<HUB_DEBOUNCE_STABLE)
217 {
218 USBCriticalSectionIn(2);
219 isConnect = MDrv_UsbDeviceConnect_Port2(g_pUsbHcd_Port2);
220 USBCriticalSectionOut(2);
221 if ( !isConnect )
222 {
223 MsOS_DelayTask(600); //By Jonas! for hub event!
224 diag_printf("USB port 2 disconnect\n");
225 //if (isExtHubConnect)
226 hub_poll_Port2(); //for disconnect hub event
227 goto PORT_DISCONNECT;
228 }
229 kk++;
230 MsOS_DelayTask(HUB_DEBOUNCE_STEP);
231 }
232 #if 0
233 if (!MDrv_UsbDeviceConnect_Port2())
234 {
235 hub_poll_Port2(); //for disconnect hub event
236 break;
237 }
238 #endif
239
240 // Device is connecting to the port
241 isFirstEvent = FALSE;
242 if (has_hub_events_Port2(&PortStatus))
243 {
244 //diag_printf("hub event 2\n");
245 isFirstEvent = TRUE;
246 hub_poll_Port2();
247
248 #if 0
249 if ( PortStatus & USB_PORT_STAT_CONNECTION )
250 {
251 usb_get_connected_dev_state(&DevState, &DevClass);
252
253 if (DevClass == 9)
254 {
255 diag_printf("External Hub is connected\n");
256 isExtHubConnect = TRUE;
257 }
258 }
259 #endif
260 }
261
262 if (isExtHubConnect)
263 hub_poll_Port2();
264
265 isMSCPlugIn = FALSE;
266 for (us_id=2*MAX_USTOR; us_id<3*MAX_USTOR; us_id++)
267 {
268 if (Is_Stor_Dev_Info_Valid(us_id)) // Check if we found a Mass Stoarge device.
269 {
270 isMSCPlugIn = TRUE;
271 if (!Is_Stor_Dev_Init(us_id)) // First time after connected
272 {
273 diag_printf("found a Mass Storage device 2, try to init it\n");
274
275 if (bInit_USB_Disk(us_id))
276 {
277 for (ii=0; ii<=Get_Stor_Max_Lun(us_id); ii++)
278 {
279 LunSts[ii] = LunPreSts[ii] = bIsDevValid(us_id, ii);
280 if (LunSts[ii])
281 {
282 diag_printf("LUN %d is init ok\n", ii);
283 }
284 }
285 Set_Stor_Dev_Init(us_id, TRUE);
286 diag_printf("MSC plug in\n");
287 }
288 }
289 else
290 {
291 vChk_USB_LUNs(us_id);
292
293 for (ii=0; ii<=Get_Stor_Max_Lun(us_id); ii++)
294 {
295 LunSts[ii] = bIsDevValid(us_id, ii);
296 if ( LunSts[ii] && (LunSts[ii] != LunPreSts[ii]) )
297 {
298 diag_printf("Chk LUN %d is init ok\n", ii);
299 }
300 LunPreSts[ii] = LunSts[ii];
301 }
302 }
303 }
304 else
305 {
306 #if 0
307 if (isMSCPlugIn)
308 {
309 diag_printf("MSC plug out\n");
310 isMSCPlugIn = FALSE;
311 if ( _DrvUSB_CBFun != NULL )
312 _DrvUSB_CBFun(USB_PLUG_OUT, USB_EVENT_DEV_TYPE_STOR);
313 }
314 #endif
315 }
316
317 }
318
319
320 #if USB_HID_SUPPORT
321 if (Is_Any_Hid_Dev_Info_Valid_EX())
322 {
323 for (ii=0; ii<MAX_HID_DEV_COUNT; ii++) //find the port index
324 {
325 isHIDPlugIntoSamePort = FALSE; //a bool value to indicate that the interface enumeration below is for the same port
326 isHIDPlugIn_IntfCnt = 0;
327 for (jj=0; jj<MAX_HID_INTF_COUNT; jj++) //find the interface index
328 {
329 if(isHIDPlugIntoSamePort==FALSE)
330 isHIDPlugIntoSamePort = TRUE; //for multiple interfaces, using same port
331
332 if ( Is_Hid_Dev_Info_Valid_EX(ii,jj) &&
333 (HID_us[ii][jj]->pusb_dev->bus->hcpriv == cpe_ehci_dev_Port2.dev.driver_data) )
334 {
335 if (!Is_Hid_Dev_Init_EX(ii,jj))
336 {
337 if ((Invalid_HidDevs & ((1 << jj)<<(ii*MAX_HID_INTF_COUNT))) != 0)
338 {
339 continue;;
340 }
341
342 if (usb_get_report_descriptor_EX(ii, jj, Hid_Report_Desc, 0x65) == ENOERR)
343 {
344 /* index 3 of id_Report_Desc is for Local Usage type: 1(Unknown), 2(Mouse),4(Joystick),6(Keyboard)
345 * e.g. of Joystick: 5 1 9 "4" a1 1 85 ...
346 */
347 if(Hid_Report_Desc[3]==Usage_Unkown)
348 {
349 Invalid_HidDevs |= ((1 << jj)<<(ii * MAX_HID_INTF_COUNT));
350 diag_printf("Invalid_HidDevs=%lx\n",Invalid_HidDevs);
351 continue;
352 }
353
354 //hid_parse_report(Hid_Report_Desc, 0x65);
355 usb_hid_parse_report(Hid_Report_Desc, 0x65, &HID_us[ii][jj]->buttons, HID_us[ii][jj]->axis, &HID_us[ii][jj]->keys);
356 diag_printf("HID finished\n");
357 Set_Hid_Dev_Init_EX(ii, jj, TRUE);
358
359 #if 1 //RCC
360 if ((isHIDPlugIn_IntfCnt < MAX_HID_INTF_COUNT)&& (isHIDPlugIntoSamePort == TRUE))
361 {
362 isHIDPlugIn = TRUE;
363 isHIDPlugIn_IntfCnt++;
364 diag_printf("HID plug into Port(%d) Intf(%d)\n", ii, jj);
365 if ( _DrvUSB_CBFun != NULL )
366 _DrvUSB_CBFun(USB_PLUG_IN, USB_EVENT_DEV_TYPE_HID, NULL);
367 }
368 #else
369 if (!isHIDPlugIn)
370 {
371 isHIDPlugIn = TRUE;
372 diag_printf("HID plug in\n");
373 if ( _DrvUSB_CBFun != NULL )
374 _DrvUSB_CBFun(USB_PLUG_IN, USB_EVENT_DEV_TYPE_HID, NULL);
375 }
376 #endif
377 //usb_hid_get_int_ex(0, HID_us[0]->IntPipeBuf, 8);
378 //MsOS_StartTimer(g_Hid_Timer_ID);
379 }
380 }
381 }
382 }
383 }
384 }
385 else
386 {
387 if (isHIDPlugIn)
388 {
389 diag_printf("HID plug out\n");
390 isHIDPlugIn = FALSE;
391 if ( _DrvUSB_CBFun != NULL )
392 _DrvUSB_CBFun(USB_PLUG_OUT, USB_EVENT_DEV_TYPE_HID, NULL);
393 }
394 }
395 #endif
396
397
398 if ( (isMSCPlugIn == FALSE)
399 #if USB_HID_SUPPORT
400 && !Is_Any_Hid_Dev_Info_Valid_EX()
401 #endif
402 && isFirstEvent )
403 {
404 if ( PortStatus & USB_PORT_STAT_CONNECTION )
405 {
406 //if ( usb_get_connected_dev_state(&DevState, &DevClass) && (DevState < USB_STATE_CONFIGURED) )
407 if ( usb_get_connected_dev_state(&DevState, &DevClass, g_pUsbHcd_Port2) )
408 {
409 if (DevState < USB_STATE_CONFIGURED)
410 {
411 diag_printf("P2> Usb device no responding\n");
412 }
413 else
414 {
415 if (DevClass == 0x09)
416 {
417 diag_printf("P2> External Hub is connected\n");
418 isExtHubConnect = TRUE;
419 }
420 else
421 {
422 diag_printf("P2> Usb device not supported\n");
423 if ( _DrvUSB_CBFun != NULL )
424 _DrvUSB_CBFun(USB_PLUG_IN, USB_EVENT_DEV_TYPE_UNKNOW, NULL);
425 }
426 }
427 }
428 }
429
430 }
431
432 #if USBC_IP_SUPPORT // USBC IP control
433 {
434 U8 idx = 1;
435
436 if (pCurrentChip->chipID == CHIPID_URANUS4)
437 idx = 2;
438 if ((pCurrentChip->usbc_ip[idx].portNum == idx) && (pCurrentChip->usbc_ip[idx].eventFlag))
439 if ( PortStatus & USB_PORT_STAT_CONNECTION)
440 if (_DrvUSBC_CBFun)
441 {
442 if (pCurrentChip->usbc_ip[idx].eventType)
443 _DrvUSBC_CBFun(USBC_NON_OVER_CURRENT, idx, NULL);
444 else
445 _DrvUSBC_CBFun(USBC_OVER_CURRENT, idx, NULL);
446 pCurrentChip->usbc_ip[idx].eventFlag = 0;
447 }
448 }
449 #endif
450
451 //MsOS_DelayTask(1000);
452 }
453
454 PORT_DISCONNECT:
455 diag_printf("No device is connecting @ port 2\n");
456 if (has_hub_events_Port2(&PortStatus))
457 {
458 diag_printf("Has hub event 2.. @ port disconnect\n");
459 hub_poll_Port2();
460 }
461
462 #if USB_HID_SUPPORT
463 for (ii=0; ii<MAX_HID_DEV_COUNT; ii++)
464 {
465 for (jj=0; jj<MAX_HID_INTF_COUNT; jj++) //find the interface index
466 {
467 if (Is_Hid_Dev_Info_Valid_EX(ii,jj))
468 {
469 if (HID_us[ii][jj]->pusb_dev->bus->hcpriv == cpe_ehci_dev_Port2.dev.driver_data)
470 {
471 diag_printf("Set HID Port(%d) Intf(%d) not init\n", ii, jj);
472 Set_Hid_Dev_Init_EX(ii, jj, FALSE);
473 }
474 }
475 }
476 }
477 #endif
478
479
480 #if 0
481 if (isMSCPlugIn)
482 {
483 diag_printf("MSC plug out\n");
484 if ( _DrvUSB_CBFun != NULL )
485 _DrvUSB_CBFun(USB_PLUG_OUT, USB_EVENT_DEV_TYPE_STOR);
486 }
487 #endif
488
489 #if 0
490 for (us_id=MAX_USTOR; us_id<MAX_USTOR*2; us_id++)
491 {
492 if (Is_Stor_Dev_Info_Valid(us_id))
493 {
494 diag_printf("!!! Remove device:%d begin..", us_id);
495 vRemove_DISK_LUNs(us_id);
496 //Free memory
497 dissociate_dev(Mass_stor_us[us_id]);
498 usb_stor_release_resources(Mass_stor_us[us_id]);
499 Clr_Stor_Dev_Info(us_id);
500 diag_printf("OK\n");
501 }
502 }
503 #endif
504
505 #if USB_HID_SUPPORT
506 if (isHIDPlugIn)
507 {
508 diag_printf("HID plug out\n");
509 if ( _DrvUSB_CBFun != NULL )
510 _DrvUSB_CBFun(USB_PLUG_OUT, USB_EVENT_DEV_TYPE_HID, NULL);
511 }
512 #endif
513 //if get any Hub device, enter Hub handler
514
515 //if get any MSC device, enter MSC handler
516
517 //device is disconnected
518
519 USBCriticalSectionIn(2);
520 ResetMstarUsb(ehci);
521 USBCriticalSectionOut(2);
522
523 }
524 }
525
USB_Start_Port2(void)526 void USB_Start_Port2(void)
527 {
528 #ifndef MS_NOSAPI
529 MS_U8 *HubStack;
530 int pid;
531 #endif
532
533 diag_printf("Usb 2 start..\n");
534
535 #ifndef MS_NOSAPI
536 HubStack = u8HubStackBuffer_Port2;
537 _s32MutexUSB_Port2 = MsOS_CreateMutex(E_MSOS_FIFO, "USB_MUTEX_PORT2", MSOS_PROCESS_SHARED);
538
539 if (_s32MutexUSB_Port2<0)
540 {
541 GEN_EXCEP;
542 return;
543 }
544 #endif
545
546 #ifndef MS_NOSAPI
547 //Create Task
548 pid = MsOS_CreateTask((TaskEntry) UsbTask_Port2,
549 (MS_U32)NULL,
550 E_TASK_PRI_HIGH,
551 TRUE,
552 HubStack,
553 HUB_STACK_SIZE,
554 "USB Hub Task 2");
555 if (pid < 0)
556 {
557 GEN_EXCEP;
558
559 MsOS_DeleteMutex(_s32MutexUSB_Port2);
560 //MsOS_FreeMemory(HubStack, gs32CachedPoolID);
561 return;
562 }
563 #else
564 //UsbTask();
565 #endif //MS_NOSAPI
566 return;
567 }
568
_DrvUSB_OnInterrupt_Port2(InterruptNum eIntNum)569 static void _DrvUSB_OnInterrupt_Port2(InterruptNum eIntNum)
570 {
571 //MS_U8 OldUSBEchiID;
572
573 //MS_U8 status;
574 //gIntStatus=mwHost20_USBSTS_Rd();
575 //diag_printf("USB INT:%x\n",gIntStatus);
576 //mwHost20_USBSTS_Set(gIntStatus); //clear usb intr status
577 MsOS_DisableInterrupt(gIrqUHC2);
578
579 //OldUSBEchiID = MDrv_USBGetCurntEhciNum();
580 //MDrv_USBSelectEhci(2);
581 g_pUsbHcd_Port2->driver->irq(g_pUsbHcd_Port2, NULL);
582 //MDrv_USBSelectEhci(OldUSBEchiID);
583
584 MsOS_EnableInterrupt(gIrqUHC2);
585 }
586
InitUSBIntr_Port2(struct usb_hcd * hcd)587 void InitUSBIntr_Port2(struct usb_hcd * hcd)
588 {
589 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
590 U32 temp;
591
592 diag_printf("InitUSBIntr_Port2 enter\n");
593 temp = (HOST20_USBINTR_IntOnAsyncAdvance |
594 HOST20_USBINTR_SystemError |
595 #ifdef ROOTHUB_INTERRUPT_MODE
596 HOST20_USBINTR_PortChangeDetect |
597 #endif
598 HOST20_USBINTR_USBError |
599 HOST20_USBINTR_CompletionOfTransaction);
600 ehci_writel (temp, (U32)&ehci->regs->intr_enable);
601
602 temp = ehci_readb((U32)&ehci->regs->status);
603 ehci_writel (temp, (U32)&ehci->regs->status); //clear all pending interrupt
604
605 temp = ehci_readb((U32)&ehci->regs->bus_control);
606 temp|= INT_POLAR;
607 ehci_writel (temp, (U32)&ehci->regs->bus_control); // set interrupt polarity high
608
609 #ifndef MS_NOSAPI
610 //diag_printf("attach usb int\n");
611 MsOS_AttachInterrupt(gIrqUHC2, _DrvUSB_OnInterrupt_Port2);
612 //diag_printf("enable usb int\n");
613 MsOS_EnableInterrupt(gIrqUHC2);
614 //diag_printf("ok");
615 #endif
616 }
617
618