9ce816ecc97405473f27056d65a04197e8f75f4b
[people/mcb30/edk2.git] / edk2 / EdkModulePkg / Bus / Pci / Ehci / Dxe / EhciReg.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                     \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14     Ehchlp.c\r
15     \r
16 Abstract: \r
17     \r
18 \r
19 Revision History\r
20 --*/\r
21 \r
22 #include "Ehci.h"\r
23 \r
24 \r
25 EFI_STATUS\r
26 ReadEhcCapabiltiyReg (\r
27   IN USB2_HC_DEV             *HcDev,\r
28   IN UINT32                  CapabiltiyRegAddr,\r
29   IN OUT UINT32              *Data\r
30   )\r
31 /*++\r
32 \r
33 Routine Description:\r
34 \r
35   Read  Ehc Capabitlity register\r
36   \r
37 Arguments:\r
38 \r
39   HcDev              - USB2_HC_DEV \r
40   CapabiltiyRegAddr  - Ehc Capability register address\r
41   Data               - A pointer to data read from register\r
42   \r
43 Returns:\r
44 \r
45   EFI_SUCCESS        Success\r
46   EFI_DEVICE_ERROR   Fail\r
47     \r
48 --*/\r
49 {\r
50   return HcDev->PciIo->Mem.Read (\r
51                              HcDev->PciIo,\r
52                              EfiPciIoWidthUint32,\r
53                              USB_BAR_INDEX,\r
54                              (UINT64) CapabiltiyRegAddr,\r
55                              1,\r
56                              Data\r
57                              );\r
58 }\r
59 \r
60 EFI_STATUS\r
61 ReadEhcOperationalReg (\r
62   IN USB2_HC_DEV             *HcDev,\r
63   IN UINT32                  OperationalRegAddr,\r
64   IN OUT UINT32              *Data\r
65   )\r
66 /*++\r
67 \r
68 Routine Description:\r
69 \r
70   Read  Ehc Operation register\r
71   \r
72 Arguments:\r
73 \r
74   HcDev                - USB2_HC_DEV \r
75   OperationalRegAddr   - Ehc Operation register address\r
76   Data                 - A pointer to data read from register\r
77   \r
78 Returns:\r
79 \r
80   EFI_SUCCESS        Success\r
81   EFI_DEVICE_ERROR   Fail\r
82     \r
83 --*/\r
84 {\r
85   ASSERT (mUsbCapabilityLen);\r
86   return HcDev->PciIo->Mem.Read (\r
87                              HcDev->PciIo,\r
88                              EfiPciIoWidthUint32,\r
89                              USB_BAR_INDEX,\r
90                              (UINT64) (OperationalRegAddr + mUsbCapabilityLen),\r
91                              1,\r
92                              Data\r
93                              );\r
94 }\r
95 \r
96 EFI_STATUS\r
97 WriteEhcOperationalReg (\r
98   IN USB2_HC_DEV             *HcDev,\r
99   IN UINT32                  OperationalRegAddr,\r
100   IN UINT32                  Data\r
101   )\r
102 /*++\r
103 \r
104 Routine Description:\r
105 \r
106   Write  Ehc Operation register\r
107   \r
108 Arguments:\r
109 \r
110   HcDev                - USB2_HC_DEV \r
111   OperationalRegAddr   - Ehc Operation register address\r
112   Data                 - 32bit write to register\r
113   \r
114 Returns:\r
115 \r
116   EFI_SUCCESS        Success\r
117   EFI_DEVICE_ERROR   Fail\r
118   \r
119 --*/\r
120 {\r
121   ASSERT (mUsbCapabilityLen);\r
122   return HcDev->PciIo->Mem.Write (\r
123                              HcDev->PciIo,\r
124                              EfiPciIoWidthUint32,\r
125                              USB_BAR_INDEX,\r
126                              (UINT64) (OperationalRegAddr + mUsbCapabilityLen),\r
127                              1,\r
128                              &Data\r
129                              );\r
130 }\r
131 \r
132 EFI_STATUS\r
133 GetCapabilityLen (\r
134   IN USB2_HC_DEV     *HcDev\r
135   )\r
136 /*++\r
137 \r
138 Routine Description:\r
139 \r
140   Get the length of capability register\r
141   \r
142 Arguments:\r
143 \r
144   HcDev - USB2_HC_DEV \r
145   \r
146 Returns:\r
147 \r
148   EFI_SUCCESS       Success\r
149   EFI_DEVICE_ERROR  Fail\r
150     \r
151 --*/\r
152 {\r
153   EFI_STATUS  Status;\r
154   UINT32      CapabilityLenAddr;\r
155 \r
156   CapabilityLenAddr = CAPLENGTH;\r
157 \r
158   Status = ReadEhcCapabiltiyReg (\r
159              HcDev,\r
160              CapabilityLenAddr,\r
161              &mUsbCapabilityLen\r
162              );\r
163   mUsbCapabilityLen = (UINT8) mUsbCapabilityLen;\r
164 \r
165   return Status;\r
166 }\r
167 \r
168 EFI_STATUS\r
169 SetFrameListLen (\r
170   IN USB2_HC_DEV     *HcDev,\r
171   IN UINTN           Length\r
172   )\r
173 /*++\r
174 \r
175 Routine Description:\r
176 \r
177   Set the length of Frame List\r
178   \r
179 Arguments:\r
180 \r
181   HcDev    - USB2_HC_DEV \r
182   Length   - the required length of frame list\r
183   \r
184 Returns:\r
185 \r
186   EFI_SUCCESS            Success\r
187   EFI_INVALID_PARAMETER  Invalid parameter\r
188   EFI_DEVICE_ERROR       Fail\r
189   \r
190 --*/\r
191 {\r
192   EFI_STATUS  Status;\r
193   UINT32      UsbCommandAddr;\r
194   UINT32      UsbCommandReg;\r
195 \r
196   UsbCommandAddr = USBCMD;\r
197 \r
198   if (256 != Length && 512 != Length) {\r
199     Status = EFI_INVALID_PARAMETER;\r
200     goto exit;\r
201   }\r
202 \r
203   Status = ReadEhcOperationalReg (\r
204              HcDev,\r
205              UsbCommandAddr,\r
206              &UsbCommandReg\r
207              );\r
208   if (EFI_ERROR (Status)) {\r
209     Status = EFI_DEVICE_ERROR;\r
210     goto exit;\r
211   }\r
212 \r
213   if (256 == Length) {\r
214     UsbCommandReg |= USBCMD_FLS_256;\r
215   } else {\r
216     UsbCommandReg |= USBCMD_FLS_512;\r
217   }\r
218 \r
219   Status = WriteEhcOperationalReg (\r
220              HcDev,\r
221              UsbCommandAddr,\r
222              UsbCommandReg\r
223              );\r
224   if (EFI_ERROR (Status)) {\r
225     Status = EFI_DEVICE_ERROR;\r
226   }\r
227 \r
228 exit:\r
229   return Status;\r
230 }\r
231 \r
232 EFI_STATUS\r
233 SetFrameListBaseAddr (\r
234   IN USB2_HC_DEV     *HcDev,\r
235   IN UINT32          FrameBuffer\r
236   )\r
237 /*++\r
238 \r
239 Routine Description:\r
240 \r
241   Set base address of frame list first entry\r
242   \r
243 Arguments:\r
244 \r
245   HcDev        - USB2_HC_DEV \r
246   FrameBuffer  - base address of first entry of frame list\r
247   \r
248 Returns:\r
249   \r
250 --*/\r
251 {\r
252   EFI_STATUS  Status;\r
253   UINT32      PeriodicListBaseAddr;\r
254   UINT32      PeriodicListBaseReg;\r
255 \r
256   Status                = EFI_SUCCESS;\r
257   PeriodicListBaseAddr  = PERIODICLISTBASE;\r
258   PeriodicListBaseReg   = FrameBuffer & 0xfffff000;\r
259 \r
260   if (IsEhcHalted (HcDev)) {\r
261 \r
262     Status = WriteEhcOperationalReg (\r
263                HcDev,\r
264                PeriodicListBaseAddr,\r
265                PeriodicListBaseReg\r
266                );\r
267     if (EFI_ERROR (Status)) {\r
268       Status = EFI_DEVICE_ERROR;\r
269       goto exit;\r
270     }\r
271 \r
272   }\r
273 \r
274 exit:\r
275   return Status;\r
276 }\r
277 \r
278 EFI_STATUS\r
279 SetAsyncListAddr (\r
280   IN USB2_HC_DEV        *HcDev,\r
281   IN EHCI_QH_ENTITY     *QhPtr\r
282   )\r
283 /*++\r
284 \r
285 Routine Description:\r
286 \r
287   Set address of first Async schedule Qh\r
288   \r
289 Arguments:\r
290 \r
291   HcDev   - USB2_HC_DEV \r
292   QhPtr   - A pointer to first Qh in the Async schedule\r
293   \r
294 Returns:\r
295 \r
296   EFI_SUCCESS       Success\r
297   EFI_DEVICE_ERROR  Fail\r
298     \r
299 --*/\r
300 {\r
301   EFI_STATUS  Status;\r
302   UINT32      AsyncListAddr;\r
303   UINT32      AsyncListReg;\r
304 \r
305   AsyncListAddr = ASYNCLISTADDR;\r
306   AsyncListReg  = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh));\r
307 \r
308   Status = WriteEhcOperationalReg (\r
309              HcDev,\r
310              AsyncListAddr,\r
311              AsyncListReg\r
312              );\r
313 \r
314   return Status;\r
315 }\r
316 \r
317 EFI_STATUS\r
318 SetCtrlDataStructSeg (\r
319   IN USB2_HC_DEV     *HcDev\r
320   )\r
321 /*++\r
322 \r
323 Routine Description:\r
324 \r
325   Set register of control and data structure segment\r
326   \r
327 Arguments:\r
328 \r
329   HcDev  - USB2_HC_DEV \r
330   \r
331 Returns:\r
332 \r
333   EFI_SUCCESS       Success\r
334   EFI_DEVICE_ERROR  Fail\r
335   \r
336 \r
337 --*/\r
338 {\r
339   EFI_STATUS  Status;\r
340   UINT32      CtrlDsSegmentAddr;\r
341   UINT32      CtrlDsSegmentReg;\r
342 \r
343   CtrlDsSegmentAddr = CTRLDSSGMENT;\r
344   CtrlDsSegmentReg  = HcDev->High32BitAddr;\r
345 \r
346   Status = WriteEhcOperationalReg (\r
347              HcDev,\r
348              CtrlDsSegmentAddr,\r
349              CtrlDsSegmentReg\r
350              );\r
351 \r
352   return Status;\r
353 }\r
354 \r
355 EFI_STATUS\r
356 SetPortRoutingEhc (\r
357   IN USB2_HC_DEV     *HcDev\r
358   )\r
359 /*++\r
360 \r
361 Routine Description:\r
362 \r
363   Set Ehc port routing bit\r
364   \r
365 Arguments:\r
366 \r
367   HcDev - USB2_HC_DEV \r
368   \r
369 Returns:\r
370 \r
371   EFI_SUCCESS       Success\r
372   EFI_DEVICE_ERROR  Fail\r
373     \r
374 --*/\r
375 {\r
376   EFI_STATUS  Status;\r
377   UINT32      ConfigFlagAddr;\r
378   UINT32      ConfigFlagReg;\r
379 \r
380   ConfigFlagAddr = CONFIGFLAG;\r
381 \r
382   Status = ReadEhcOperationalReg (\r
383              HcDev,\r
384              ConfigFlagAddr,\r
385              &ConfigFlagReg\r
386              );\r
387   if (EFI_ERROR (Status)) {\r
388     Status = EFI_DEVICE_ERROR;\r
389     goto exit;\r
390   }\r
391 \r
392   ConfigFlagReg |= CONFIGFLAG_CF;\r
393   Status = WriteEhcOperationalReg (\r
394              HcDev,\r
395              ConfigFlagAddr,\r
396              ConfigFlagReg\r
397              );\r
398   if (EFI_ERROR (Status)) {\r
399     Status = EFI_DEVICE_ERROR;\r
400   }\r
401 \r
402 exit:\r
403   return Status;\r
404 }\r
405 \r
406 EFI_STATUS\r
407 SetEhcDoorbell (\r
408   IN  USB2_HC_DEV     *HcDev\r
409   )\r
410 /*++\r
411 \r
412 Routine Description:\r
413 \r
414   Set Ehc door bell bit\r
415   \r
416 Arguments:\r
417 \r
418   HcDev - USB2_HC_DEV \r
419   \r
420 Returns:\r
421 \r
422   EFI_SUCCESS       Success\r
423   EFI_DEVICE_ERROR  Fail\r
424      \r
425 --*/\r
426 {\r
427   EFI_STATUS  Status;\r
428   UINT32      UsbCommandAddr;\r
429   UINT32      UsbCommandReg;\r
430 \r
431   UsbCommandAddr = USBCMD;\r
432 \r
433   Status = ReadEhcOperationalReg (\r
434              HcDev,\r
435              UsbCommandAddr,\r
436              &UsbCommandReg\r
437              );\r
438   if (EFI_ERROR (Status)) {\r
439     Status = EFI_DEVICE_ERROR;\r
440     goto exit;\r
441   }\r
442 \r
443   UsbCommandReg |= USBCMD_IAAD;\r
444   Status = WriteEhcOperationalReg (\r
445              HcDev,\r
446              UsbCommandAddr,\r
447              UsbCommandReg\r
448              );\r
449   if (EFI_ERROR (Status)) {\r
450     Status = EFI_DEVICE_ERROR;\r
451   }\r
452 \r
453 exit:\r
454   return Status;\r
455 }\r
456 \r
457 EFI_STATUS\r
458 ClearEhcAllStatus (\r
459   IN  USB2_HC_DEV     *HcDev\r
460   )\r
461 /*++\r
462 \r
463 Routine Description:\r
464 \r
465   Clear Ehc all status bits\r
466   \r
467 Arguments:\r
468 \r
469   HcDev - USB2_HC_DEV \r
470   \r
471 Returns:\r
472 \r
473   EFI_SUCCESS       Success\r
474   EFI_DEVICE_ERROR  Fail\r
475      \r
476 --*/\r
477 {\r
478   UINT32  UsbStatusAddr;\r
479 \r
480   UsbStatusAddr = USBSTS;\r
481 \r
482   return WriteEhcOperationalReg (\r
483            HcDev,\r
484            UsbStatusAddr,\r
485            0x003F\r
486            );\r
487 }\r
488 \r
489 EFI_STATUS\r
490 EnablePeriodicSchedule (\r
491   IN  USB2_HC_DEV     *HcDev\r
492   )\r
493 /*++\r
494 \r
495 Routine Description:\r
496 \r
497   Enable periodic schedule\r
498   \r
499 Arguments:\r
500 \r
501   HcDev - USB2_HC_DEV \r
502   \r
503 Returns:\r
504 \r
505   EFI_SUCCESS       Success\r
506   EFI_DEVICE_ERROR  Fail\r
507    \r
508 --*/\r
509 {\r
510   EFI_STATUS  Status;\r
511   UINT32      UsbCommandAddr;\r
512   UINT32      UsbCommandReg;\r
513 \r
514   UsbCommandAddr = USBCMD;\r
515 \r
516   Status = ReadEhcOperationalReg (\r
517              HcDev,\r
518              UsbCommandAddr,\r
519              &UsbCommandReg\r
520              );\r
521   if (EFI_ERROR (Status)) {\r
522     Status = EFI_DEVICE_ERROR;\r
523     goto exit;\r
524   }\r
525 \r
526   UsbCommandReg |= USBCMD_PSE;\r
527   Status = WriteEhcOperationalReg (\r
528              HcDev,\r
529              UsbCommandAddr,\r
530              UsbCommandReg\r
531              );\r
532   if (EFI_ERROR (Status)) {\r
533     Status = EFI_DEVICE_ERROR;\r
534   }\r
535 \r
536 exit:\r
537   return Status;\r
538 }\r
539 \r
540 EFI_STATUS\r
541 DisablePeriodicSchedule (\r
542   IN  USB2_HC_DEV     *HcDev\r
543   )\r
544 /*++\r
545 \r
546 Routine Description:\r
547 \r
548   Disable periodic schedule\r
549   \r
550 Arguments:\r
551 \r
552   HcDev - USB2_HC_DEV \r
553   \r
554 Returns:\r
555 \r
556   EFI_SUCCESS       Success\r
557   EFI_DEVICE_ERROR  Fail\r
558    \r
559 --*/\r
560 {\r
561   EFI_STATUS  Status;\r
562   UINT32      UsbCommandAddr;\r
563   UINT32      UsbCommandReg;\r
564 \r
565   UsbCommandAddr = USBCMD;\r
566 \r
567   Status = ReadEhcOperationalReg (\r
568              HcDev,\r
569              UsbCommandAddr,\r
570              &UsbCommandReg\r
571              );\r
572   if (EFI_ERROR (Status)) {\r
573     return EFI_DEVICE_ERROR;\r
574   }\r
575 \r
576   UsbCommandReg &= ~USBCMD_PSE;\r
577   Status = WriteEhcOperationalReg (\r
578              HcDev,\r
579              UsbCommandAddr,\r
580              UsbCommandReg\r
581              );\r
582   if (EFI_ERROR (Status)) {\r
583     return EFI_DEVICE_ERROR;\r
584   }\r
585 \r
586   return Status;\r
587 }\r
588 \r
589 EFI_STATUS\r
590 EnableAsynchronousSchedule (\r
591   IN  USB2_HC_DEV     *HcDev\r
592   )\r
593 /*++\r
594 \r
595 Routine Description:\r
596 \r
597   Enable asynchrounous schedule\r
598   \r
599 Arguments:\r
600 \r
601   HcDev - USB2_HC_DEV \r
602   \r
603 Returns:\r
604 \r
605   EFI_SUCCESS       Success\r
606   EFI_DEVICE_ERROR  Fail\r
607     \r
608 --*/\r
609 {\r
610   EFI_STATUS  Status;\r
611   UINT32      UsbCommandAddr;\r
612   UINT32      UsbCommandReg;\r
613 \r
614   UsbCommandAddr = USBCMD;\r
615 \r
616   Status = ReadEhcOperationalReg (\r
617              HcDev,\r
618              UsbCommandAddr,\r
619              &UsbCommandReg\r
620              );\r
621   if (EFI_ERROR (Status)) {\r
622     Status = EFI_DEVICE_ERROR;\r
623     goto exit;\r
624   }\r
625 \r
626   UsbCommandReg |= USBCMD_ASE;\r
627   Status = WriteEhcOperationalReg (\r
628              HcDev,\r
629              UsbCommandAddr,\r
630              UsbCommandReg\r
631              );\r
632   if (EFI_ERROR (Status)) {\r
633     Status = EFI_DEVICE_ERROR;\r
634   }\r
635 \r
636 exit:\r
637   return Status;\r
638 }\r
639 \r
640 EFI_STATUS\r
641 DisableAsynchronousSchedule (\r
642   IN  USB2_HC_DEV     *HcDev\r
643   )\r
644 /*++\r
645 \r
646 Routine Description:\r
647 \r
648   Disable asynchrounous schedule\r
649   \r
650 Arguments:\r
651 \r
652   HcDev - USB2_HC_DEV \r
653   \r
654 Returns:\r
655 \r
656   EFI_SUCCESS       Success\r
657   EFI_DEVICE_ERROR  Fail\r
658    \r
659 --*/\r
660 {\r
661   EFI_STATUS  Status;\r
662   UINT32      UsbCommandAddr;\r
663   UINT32      UsbCommandReg;\r
664 \r
665   UsbCommandAddr = USBCMD;\r
666 \r
667   Status = ReadEhcOperationalReg (\r
668              HcDev,\r
669              UsbCommandAddr,\r
670              &UsbCommandReg\r
671              );\r
672   if (EFI_ERROR (Status)) {\r
673     return EFI_DEVICE_ERROR;\r
674   }\r
675 \r
676   UsbCommandReg &= ~USBCMD_ASE;\r
677   Status = WriteEhcOperationalReg (\r
678              HcDev,\r
679              UsbCommandAddr,\r
680              UsbCommandReg\r
681              );\r
682   if (EFI_ERROR (Status)) {\r
683     return EFI_DEVICE_ERROR;\r
684   }\r
685 \r
686   return Status;\r
687 }\r
688 \r
689 EFI_STATUS\r
690 ResetEhc (\r
691   IN  USB2_HC_DEV     *HcDev\r
692   )\r
693 /*++\r
694 \r
695 Routine Description:\r
696 \r
697   Reset Ehc\r
698   \r
699 Arguments:\r
700 \r
701   HcDev - USB2_HC_DEV \r
702   \r
703 Returns:\r
704 \r
705   EFI_SUCCESS       Success\r
706   EFI_DEVICE_ERROR  Fail\r
707    \r
708 --*/\r
709 {\r
710   EFI_STATUS  Status;\r
711   UINT32      UsbCommandAddr;\r
712   UINT32      UsbCommandReg;\r
713 \r
714   UsbCommandAddr = USBCMD;\r
715 \r
716   Status = ReadEhcOperationalReg (\r
717              HcDev,\r
718              UsbCommandAddr,\r
719              &UsbCommandReg\r
720              );\r
721   if (EFI_ERROR (Status)) {\r
722     Status = EFI_DEVICE_ERROR;\r
723     goto exit;\r
724   }\r
725 \r
726   UsbCommandReg |= USBCMD_HCRESET;\r
727   Status = WriteEhcOperationalReg (\r
728              HcDev,\r
729              UsbCommandAddr,\r
730              UsbCommandReg\r
731              );\r
732   if (EFI_ERROR (Status)) {\r
733     Status = EFI_DEVICE_ERROR;\r
734   }\r
735 \r
736 exit:\r
737   return Status;\r
738 }\r
739 \r
740 EFI_STATUS\r
741 StartScheduleExecution (\r
742   IN  USB2_HC_DEV     *HcDev\r
743   )\r
744 /*++\r
745 \r
746 Routine Description:\r
747 \r
748   Start Ehc schedule execution\r
749   \r
750 Arguments:\r
751 \r
752   HcDev - USB2_HC_DEV \r
753   \r
754 Returns:\r
755 \r
756   EFI_SUCCESS       Success\r
757   EFI_DEVICE_ERROR  Fail\r
758    \r
759 --*/\r
760 {\r
761   EFI_STATUS  Status;\r
762   UINT32      UsbCommandAddr;\r
763   UINT32      UsbCommandReg;\r
764 \r
765   UsbCommandAddr = USBCMD;\r
766 \r
767   Status = ReadEhcOperationalReg (\r
768              HcDev,\r
769              UsbCommandAddr,\r
770              &UsbCommandReg\r
771              );\r
772   if (EFI_ERROR (Status)) {\r
773     Status = EFI_DEVICE_ERROR;\r
774     goto exit;\r
775   }\r
776 \r
777   UsbCommandReg |= USBCMD_RS;\r
778   Status = WriteEhcOperationalReg (\r
779              HcDev,\r
780              UsbCommandAddr,\r
781              UsbCommandReg\r
782              );\r
783   if (EFI_ERROR (Status)) {\r
784     Status = EFI_DEVICE_ERROR;\r
785   }\r
786 \r
787 exit:\r
788   return Status;\r
789 }\r
790 \r
791 BOOLEAN\r
792 IsFrameListProgrammable (\r
793   IN  USB2_HC_DEV     *HcDev\r
794   )\r
795 /*++\r
796 \r
797 Routine Description:\r
798 \r
799   Whether frame list is programmable\r
800   \r
801 Arguments:\r
802 \r
803   HcDev - USB2_HC_DEV \r
804   \r
805 Returns:\r
806 \r
807   TRUE   Programmable\r
808   FALSE  Unprogrammable\r
809   \r
810 --*/\r
811 {\r
812   BOOLEAN Value;\r
813   UINT32  HcCapParamsAddr;\r
814   UINT32  HcCapParamsReg;\r
815 \r
816   HcCapParamsAddr = HCCPARAMS;\r
817 \r
818   ReadEhcOperationalReg (\r
819     HcDev,\r
820     HcCapParamsAddr,\r
821     &HcCapParamsReg\r
822     );\r
823 \r
824   if (HcCapParamsReg & HCCP_PFLF) {\r
825     Value = TRUE;\r
826   } else {\r
827     Value = FALSE;\r
828   }\r
829 \r
830   return Value;\r
831 }\r
832 \r
833 BOOLEAN\r
834 IsPeriodicScheduleEnabled (\r
835   IN  USB2_HC_DEV     *HcDev\r
836   )\r
837 /*++\r
838 \r
839 Routine Description:\r
840 \r
841   Whether periodic schedule is enabled\r
842   \r
843 Arguments:\r
844 \r
845   HcDev - USB2_HC_DEV \r
846   \r
847 Returns:\r
848 \r
849   TRUE    Enabled\r
850   FALSE   Disabled\r
851   \r
852 --*/\r
853 {\r
854   BOOLEAN Value;\r
855   UINT32  UsbStatusAddr;\r
856   UINT32  UsbStatusReg;\r
857 \r
858   UsbStatusAddr = USBSTS;\r
859 \r
860   ReadEhcOperationalReg (\r
861     HcDev,\r
862     UsbStatusAddr,\r
863     &UsbStatusReg\r
864     );\r
865 \r
866   if (UsbStatusReg & USBSTS_PSS) {\r
867     Value = TRUE;\r
868   } else {\r
869     Value = FALSE;\r
870   }\r
871 \r
872   return Value;\r
873 }\r
874 \r
875 BOOLEAN\r
876 IsAsyncScheduleEnabled (\r
877   IN  USB2_HC_DEV     *HcDev\r
878   )\r
879 /*++\r
880 \r
881 Routine Description:\r
882 \r
883   Whether asynchronous schedule is enabled\r
884   \r
885 Arguments:\r
886 \r
887   HcDev - USB2_HC_DEV \r
888   \r
889 Returns:\r
890 \r
891   TRUE   Enabled\r
892   FALSE  Disabled\r
893   \r
894 --*/\r
895 {\r
896   BOOLEAN Value;\r
897   UINT32  UsbStatusAddr;\r
898   UINT32  UsbStatusReg;\r
899 \r
900   UsbStatusAddr = USBSTS;\r
901 \r
902   ReadEhcOperationalReg (\r
903     HcDev,\r
904     UsbStatusAddr,\r
905     &UsbStatusReg\r
906     );\r
907 \r
908   if (UsbStatusReg & USBSTS_ASS) {\r
909     Value = TRUE;\r
910   } else {\r
911     Value = FALSE;\r
912   }\r
913 \r
914   return Value;\r
915 }\r
916 \r
917 BOOLEAN\r
918 IsEhcPortEnabled (\r
919   IN  USB2_HC_DEV     *HcDev,\r
920   IN  UINT8           PortNum\r
921   )\r
922 /*++\r
923 \r
924 Routine Description:\r
925 \r
926   Whether port is enabled\r
927   \r
928 Arguments:\r
929 \r
930   HcDev - USB2_HC_DEV \r
931   \r
932 Returns:\r
933 \r
934   TRUE   Enabled\r
935   FALSE  Disabled\r
936   \r
937 --*/\r
938 {\r
939   UINT32  PortStatusControlAddr;\r
940   UINT32  PortStatusControlReg;\r
941 \r
942   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));\r
943 \r
944   ReadEhcOperationalReg (\r
945     HcDev,\r
946     PortStatusControlAddr,\r
947     &PortStatusControlReg\r
948     );\r
949 \r
950   return ((PortStatusControlReg & PORTSC_PED) ? TRUE : FALSE);\r
951 }\r
952 \r
953 BOOLEAN\r
954 IsEhcReseted (\r
955   IN  USB2_HC_DEV     *HcDev\r
956   )\r
957 /*++\r
958 \r
959 Routine Description:\r
960 \r
961   Whether Ehc is reseted\r
962   \r
963 Arguments:\r
964 \r
965   HcDev - USB2_HC_DEV \r
966   \r
967 Returns:\r
968 \r
969   TRUE   Reseted\r
970   FALSE  Unreseted\r
971   \r
972 --*/\r
973 {\r
974   BOOLEAN Value;\r
975   UINT32  UsbCommandAddr;\r
976   UINT32  UsbCommandReg;\r
977 \r
978   UsbCommandAddr = USBCMD;\r
979 \r
980   ReadEhcOperationalReg (\r
981     HcDev,\r
982     UsbCommandAddr,\r
983     &UsbCommandReg\r
984     );\r
985 \r
986   if (UsbCommandReg & USBCMD_HCRESET) {\r
987     Value = FALSE;\r
988   } else {\r
989     Value = TRUE;\r
990   }\r
991 \r
992   return Value;\r
993 }\r
994 \r
995 BOOLEAN\r
996 IsEhcHalted (\r
997   IN  USB2_HC_DEV     *HcDev\r
998   )\r
999 /*++\r
1000 \r
1001 Routine Description:\r
1002 \r
1003   Whether Ehc is halted\r
1004   \r
1005 Arguments:\r
1006 \r
1007   HcDev - USB2_HC_DEV \r
1008   \r
1009 Returns:\r
1010 \r
1011   TRUE   Halted\r
1012   FALSE  Not halted\r
1013   \r
1014 --*/\r
1015 {\r
1016   BOOLEAN Value;\r
1017   UINT32  UsbStatusAddr;\r
1018   UINT32  UsbStatusReg;\r
1019 \r
1020   UsbStatusAddr = USBSTS;\r
1021 \r
1022   ReadEhcOperationalReg (\r
1023     HcDev,\r
1024     UsbStatusAddr,\r
1025     &UsbStatusReg\r
1026     );\r
1027 \r
1028   if (UsbStatusReg & USBSTS_HCH) {\r
1029     Value = TRUE;\r
1030   } else {\r
1031     Value = FALSE;\r
1032   }\r
1033 \r
1034   return Value;\r
1035 }\r
1036 \r
1037 BOOLEAN\r
1038 IsEhcSysError (\r
1039   IN  USB2_HC_DEV     *HcDev\r
1040   )\r
1041 /*++\r
1042 \r
1043 Routine Description:\r
1044 \r
1045   Whether Ehc is system error\r
1046   \r
1047 Arguments:\r
1048 \r
1049   HcDev - USB2_HC_DEV \r
1050   \r
1051 Returns:\r
1052 \r
1053   TRUE   System error\r
1054   FALSE  No system error\r
1055   \r
1056 --*/\r
1057 {\r
1058   BOOLEAN Value;\r
1059   UINT32  UsbStatusAddr;\r
1060   UINT32  UsbStatusReg;\r
1061 \r
1062   UsbStatusAddr = USBSTS;\r
1063 \r
1064   ReadEhcOperationalReg (\r
1065     HcDev,\r
1066     UsbStatusAddr,\r
1067     &UsbStatusReg\r
1068     );\r
1069 \r
1070   if (UsbStatusReg & USBSTS_HSE) {\r
1071     Value = TRUE;\r
1072   } else {\r
1073     Value = FALSE;\r
1074   }\r
1075 \r
1076   return Value;\r
1077 }\r
1078 \r
1079 BOOLEAN\r
1080 IsHighSpeedDevice (\r
1081   IN EFI_USB2_HC_PROTOCOL *This,\r
1082   IN UINT8                PortNum \r
1083   )\r
1084 /*++\r
1085 \r
1086 Routine Description:\r
1087 \r
1088   Whether high speed device attached\r
1089   \r
1090 Arguments:\r
1091 \r
1092   HcDev - USB2_HC_DEV \r
1093   \r
1094 Returns:\r
1095 \r
1096   TRUE   High speed\r
1097   FALSE  Full speed\r
1098   \r
1099 --*/\r
1100 {\r
1101   USB2_HC_DEV          *HcDev;\r
1102   UINT32               PortStatusControlAddr;\r
1103   UINT32               PortStatusControlReg;\r
1104   \r
1105   HcDev = USB2_HC_DEV_FROM_THIS (This);\r
1106   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));\r
1107 \r
1108   //\r
1109   // Set port reset bit\r
1110   //\r
1111   ReadEhcOperationalReg (\r
1112     HcDev,\r
1113     PortStatusControlAddr,\r
1114     &PortStatusControlReg\r
1115     );\r
1116   //\r
1117   // Make sure Host Controller not halt before reset it\r
1118   //\r
1119   if (IsEhcHalted (HcDev)) {\r
1120     StartScheduleExecution (HcDev);\r
1121     WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);\r
1122   }\r
1123   PortStatusControlReg &= 0xffffffd5;\r
1124   PortStatusControlReg |= PORTSC_PR;\r
1125   //\r
1126   // Set one to PortReset bit must also set zero to PortEnable bit\r
1127   //\r
1128   PortStatusControlReg &= ~PORTSC_PED;\r
1129   WriteEhcOperationalReg (\r
1130     HcDev,\r
1131     PortStatusControlAddr,\r
1132     PortStatusControlReg\r
1133     );\r
1134 \r
1135   //\r
1136   // Set Port reset recovery time\r
1137   //\r
1138   gBS->Stall (EHCI_SET_PORT_RESET_RECOVERY_TIME);\r
1139 \r
1140   //\r
1141   // Clear port reset bit\r
1142   //\r
1143   ReadEhcOperationalReg (\r
1144     HcDev,\r
1145     PortStatusControlAddr,\r
1146     &PortStatusControlReg\r
1147     );\r
1148   PortStatusControlReg &= 0xffffffd5;\r
1149   PortStatusControlReg &= ~PORTSC_PR;\r
1150   WriteEhcOperationalReg (\r
1151     HcDev,\r
1152     PortStatusControlAddr,\r
1153     PortStatusControlReg\r
1154     );\r
1155 \r
1156   //\r
1157   // Clear port reset recovery time\r
1158   //\r
1159   gBS->Stall (EHCI_CLEAR_PORT_RESET_RECOVERY_TIME);\r
1160 \r
1161   return (IsEhcPortEnabled (HcDev, PortNum) ? TRUE : FALSE);\r
1162 }\r
1163 \r
1164 EFI_STATUS\r
1165 WaitForEhcReset (\r
1166   IN USB2_HC_DEV             *HcDev,\r
1167   IN UINTN                   Timeout\r
1168   )\r
1169 /*++\r
1170 \r
1171 Routine Description:\r
1172 \r
1173   wait for Ehc reset or timeout\r
1174   \r
1175 Arguments:\r
1176 \r
1177   HcDev   - USB2_HC_DEV \r
1178   Timeout - timeout threshold\r
1179   \r
1180 Returns:\r
1181 \r
1182   EFI_SUCCESS    Success\r
1183   EFI_TIMEOUT    Timeout\r
1184   \r
1185 --*/\r
1186 {\r
1187   EFI_STATUS  Status;\r
1188   UINTN       Delay;\r
1189 \r
1190   //\r
1191   // Timeout is in US unit\r
1192   //\r
1193   Delay = (Timeout / 50) + 1;\r
1194   do {\r
1195 \r
1196     if (IsEhcReseted (HcDev)) {\r
1197       Status = EFI_SUCCESS;\r
1198       goto exit;\r
1199     }\r
1200     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1201 \r
1202   } while (Delay--);\r
1203 \r
1204   Status = EFI_TIMEOUT;\r
1205 \r
1206 exit:\r
1207   return Status;\r
1208 }\r
1209 \r
1210 EFI_STATUS\r
1211 WaitForEhcHalt (\r
1212   IN USB2_HC_DEV             *HcDev,\r
1213   IN UINTN                   Timeout\r
1214   )\r
1215 /*++\r
1216 \r
1217 Routine Description:\r
1218 \r
1219   wait for Ehc halt or timeout\r
1220   \r
1221 Arguments:\r
1222 \r
1223   HcDev   - USB2_HC_DEV \r
1224   Timeout - timeout threshold\r
1225   \r
1226 Returns:\r
1227 \r
1228   EFI_SUCCESS    Success\r
1229   EFI_TIMEOUT    Timeout\r
1230   \r
1231 --*/\r
1232 {\r
1233   EFI_STATUS  Status;\r
1234   UINTN       Delay;\r
1235 \r
1236   //\r
1237   // Timeout is in US unit\r
1238   //\r
1239   Delay = (Timeout / 50) + 1;\r
1240   do {\r
1241 \r
1242     if (IsEhcHalted (HcDev)) {\r
1243       Status = EFI_SUCCESS;\r
1244       goto exit;\r
1245     }\r
1246     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1247 \r
1248   } while (Delay--);\r
1249 \r
1250   Status = EFI_TIMEOUT;\r
1251 \r
1252 exit:\r
1253   return Status;\r
1254 }\r
1255 \r
1256 EFI_STATUS\r
1257 WaitForEhcNotHalt (\r
1258   IN USB2_HC_DEV             *HcDev,\r
1259   IN UINTN                   Timeout\r
1260   )\r
1261 /*++\r
1262 \r
1263 Routine Description:\r
1264 \r
1265   wait for Ehc not halt or timeout\r
1266   \r
1267 Arguments:\r
1268 \r
1269   HcDev   - USB2_HC_DEV \r
1270   Timeout - timeout threshold\r
1271   \r
1272 Returns:\r
1273 \r
1274   EFI_SUCCESS    Success\r
1275   EFI_TIMEOUT    Timeout\r
1276   \r
1277 --*/\r
1278 {\r
1279   EFI_STATUS  Status;\r
1280   UINTN       Delay;\r
1281 \r
1282   //\r
1283   // Timeout is in US unit\r
1284   //\r
1285   Delay = (Timeout / 50) + 1;\r
1286   do {\r
1287 \r
1288     if (!IsEhcHalted (HcDev)) {\r
1289       Status = EFI_SUCCESS;\r
1290       goto exit;\r
1291     }\r
1292     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1293 \r
1294   } while (Delay--);\r
1295 \r
1296   Status = EFI_TIMEOUT;\r
1297 \r
1298 exit:\r
1299   return Status;\r
1300 }\r
1301 \r
1302 EFI_STATUS\r
1303 WaitForAsyncScheduleEnable (\r
1304   IN  USB2_HC_DEV            *HcDev,\r
1305   IN UINTN                   Timeout\r
1306   )\r
1307 /*++\r
1308 \r
1309 Routine Description:\r
1310 \r
1311   Wait for Ehc asynchronous schedule enable or timeout\r
1312   \r
1313 Arguments:\r
1314 \r
1315   HcDev   - USB2_HC_DEV \r
1316   Timeout - timeout threshold\r
1317   \r
1318 Returns:\r
1319 \r
1320   EFI_SUCCESS    Success\r
1321   EFI_TIMEOUT    Timeout\r
1322   \r
1323 --*/\r
1324 {\r
1325   EFI_STATUS  Status;\r
1326   UINTN       Delay;\r
1327 \r
1328   //\r
1329   // Timeout is in US unit\r
1330   //\r
1331   Delay = (Timeout / 50) + 1;\r
1332   do {\r
1333 \r
1334     if (IsAsyncScheduleEnabled (HcDev)) {\r
1335       Status = EFI_SUCCESS;\r
1336       goto exit;\r
1337     }\r
1338     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1339 \r
1340   } while (Delay--);\r
1341 \r
1342   Status = EFI_TIMEOUT;\r
1343 \r
1344 exit:\r
1345   return Status;\r
1346 }\r
1347 \r
1348 EFI_STATUS\r
1349 WaitForAsyncScheduleDisable (\r
1350   IN USB2_HC_DEV             *HcDev,\r
1351   IN UINTN                   Timeout\r
1352   )\r
1353 /*++\r
1354 \r
1355 Routine Description:\r
1356 \r
1357   Wait for Ehc asynchronous schedule disable or timeout\r
1358   \r
1359 Arguments:\r
1360 \r
1361   HcDev   - USB2_HC_DEV \r
1362   Timeout - timeout threshold\r
1363   \r
1364 Returns:\r
1365 \r
1366   EFI_SUCCESS    Success\r
1367   EFI_TIMEOUT    Timeout\r
1368   \r
1369 --*/\r
1370 {\r
1371   EFI_STATUS  Status;\r
1372   UINTN       Delay;\r
1373 \r
1374   //\r
1375   // Timeout is in US unit\r
1376   //\r
1377   Delay = (Timeout / 50) + 1;\r
1378   do {\r
1379 \r
1380     if (!IsAsyncScheduleEnabled (HcDev)) {\r
1381       Status = EFI_SUCCESS;\r
1382       goto exit;\r
1383     }\r
1384     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1385 \r
1386   } while (Delay--);\r
1387 \r
1388   Status = EFI_TIMEOUT;\r
1389 \r
1390 exit:\r
1391   return Status;\r
1392 }\r
1393 \r
1394 EFI_STATUS\r
1395 WaitForPeriodicScheduleEnable (\r
1396   IN USB2_HC_DEV             *HcDev,\r
1397   IN UINTN                   Timeout\r
1398   )\r
1399 /*++\r
1400 \r
1401 Routine Description:\r
1402 \r
1403   Wait for Ehc periodic schedule enable or timeout\r
1404   \r
1405 Arguments:\r
1406 \r
1407   HcDev   - USB2_HC_DEV \r
1408   Timeout - timeout threshold\r
1409   \r
1410 Returns:\r
1411 \r
1412   EFI_SUCCESS    Success\r
1413   EFI_TIMEOUT    Timeout\r
1414   \r
1415 --*/\r
1416 {\r
1417   EFI_STATUS  Status;\r
1418   UINTN       Delay;\r
1419 \r
1420   //\r
1421   // Timeout is in US unit\r
1422   //\r
1423   Delay = (Timeout / 50) + 1;\r
1424   do {\r
1425 \r
1426     if (IsPeriodicScheduleEnabled (HcDev)) {\r
1427       Status = EFI_SUCCESS;\r
1428       goto exit;\r
1429     }\r
1430     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1431 \r
1432   } while (Delay--);\r
1433 \r
1434   Status = EFI_TIMEOUT;\r
1435 \r
1436 exit:\r
1437   return Status;\r
1438 }\r
1439 \r
1440 EFI_STATUS\r
1441 WaitForPeriodicScheduleDisable (\r
1442   IN USB2_HC_DEV             *HcDev,\r
1443   IN UINTN                   Timeout\r
1444   )\r
1445 /*++\r
1446 \r
1447 Routine Description:\r
1448 \r
1449   Wait for periodic schedule disable or timeout\r
1450   \r
1451 Arguments:\r
1452 \r
1453   HcDev   - USB2_HC_DEV \r
1454   Timeout - timeout threshold\r
1455   \r
1456 Returns:\r
1457 \r
1458   EFI_SUCCESS    Success\r
1459   EFI_TIMEOUT    Timeout\r
1460   \r
1461 --*/\r
1462 {\r
1463   EFI_STATUS  Status;\r
1464   UINTN       Delay;\r
1465 \r
1466   //\r
1467   // Timeout is in US unit\r
1468   //\r
1469   Delay = (Timeout / 50) + 1;\r
1470   do {\r
1471 \r
1472     if (!IsPeriodicScheduleEnabled (HcDev)) {\r
1473       Status = EFI_SUCCESS;\r
1474       goto exit;\r
1475     }\r
1476     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
1477 \r
1478   } while (Delay--);\r
1479 \r
1480   Status = EFI_TIMEOUT;\r
1481 \r
1482 exit:\r
1483   return Status;\r
1484 }\r
1485 \r
1486 EFI_STATUS\r
1487 WaitForEhcDoorbell (\r
1488   IN USB2_HC_DEV             *HcDev,\r
1489   IN UINTN                   Timeout\r
1490   )\r
1491 /*++\r
1492 \r
1493 Routine Description:\r
1494 \r
1495   Wait for periodic schedule disable or timeout\r
1496 \r
1497 Arguments:\r
1498 \r
1499   HcDev   - USB2_HC_DEV \r
1500   Timeout - timeout threshold\r
1501 \r
1502 Returns:\r
1503 \r
1504   EFI_SUCCESS    Success\r
1505   EFI_TIMEOUT    Timeout\r
1506   \r
1507 --*/\r
1508 {\r
1509   EFI_STATUS  Status;\r
1510   UINT32      UsbCommandAddr;\r
1511   UINT32      UsbCommandReg;\r
1512   UINTN       Delay;\r
1513 \r
1514   UsbCommandAddr  = USBCMD;\r
1515   Delay           = (Timeout / 50) + 1;\r
1516   \r
1517   do {\r
1518     Status = ReadEhcOperationalReg (\r
1519                HcDev,\r
1520                UsbCommandAddr,\r
1521                &UsbCommandReg\r
1522                );\r
1523     if (EFI_ERROR (Status)) {\r
1524       Status = EFI_DEVICE_ERROR;\r
1525       goto exit;\r
1526     }\r
1527     if (!(UsbCommandReg & USBCMD_IAAD)) {\r
1528       break;\r
1529     }\r
1530         \r
1531   } while (--Delay);\r
1532 \r
1533   if (0 == Delay) {\r
1534     Status = EFI_TIMEOUT;\r
1535   }\r
1536 \r
1537 exit:\r
1538   return Status;\r
1539 }\r