TianoCore EDK2 master
Loading...
Searching...
No Matches
EhcPeim.c
Go to the documentation of this file.
1
11#include "EhcPeim.h"
12
13//
14// Two arrays used to translate the EHCI port state (change)
15// to the UEFI protocol's port state (change).
16//
17USB_PORT_STATE_MAP mUsbPortStateMap[] = {
18 { PORTSC_CONN, USB_PORT_STAT_CONNECTION },
19 { PORTSC_ENABLED, USB_PORT_STAT_ENABLE },
20 { PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND },
21 { PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT },
22 { PORTSC_RESET, USB_PORT_STAT_RESET },
23 { PORTSC_POWER, USB_PORT_STAT_POWER },
24 { PORTSC_OWNER, USB_PORT_STAT_OWNER }
25};
26
27USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
28 { PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION },
29 { PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE },
30 { PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT }
31};
32
42UINT32
45 IN UINT32 Offset
46 )
47{
48 UINT32 Data;
49
50 ASSERT (Ehc->CapLen != 0);
51
52 Data = MmioRead32 (Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset);
53
54 return Data;
55}
56
65VOID
68 IN UINT32 Offset,
69 IN UINT32 Data
70 )
71{
72 ASSERT (Ehc->CapLen != 0);
73
74 MmioWrite32 (Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset, Data);
75}
76
85VOID
88 IN UINT32 Offset,
89 IN UINT32 Bit
90 )
91{
92 UINT32 Data;
93
94 Data = EhcReadOpReg (Ehc, Offset);
95 Data |= Bit;
96 EhcWriteOpReg (Ehc, Offset, Data);
97}
98
107VOID
109 IN PEI_USB2_HC_DEV *Ehc,
110 IN UINT32 Offset,
111 IN UINT32 Bit
112 )
113{
114 UINT32 Data;
115
116 Data = EhcReadOpReg (Ehc, Offset);
117 Data &= ~Bit;
118 EhcWriteOpReg (Ehc, Offset, Data);
119}
120
137 IN PEI_USB2_HC_DEV *Ehc,
138 IN UINT32 Offset,
139 IN UINT32 Bit,
140 IN BOOLEAN WaitToSet,
141 IN UINT32 Timeout
142 )
143{
144 UINT32 Index;
145
146 for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) {
147 if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {
148 return EFI_SUCCESS;
149 }
150
151 MicroSecondDelay (EHC_SYNC_POLL_INTERVAL);
152 }
153
154 return EFI_TIMEOUT;
155}
156
166UINT32
168 IN PEI_USB2_HC_DEV *Ehc,
169 IN UINT32 Offset
170 )
171{
172 UINT32 Data;
173
174 Data = MmioRead32 (Ehc->UsbHostControllerBaseAddress + Offset);
175
176 return Data;
177}
178
192 IN PEI_USB2_HC_DEV *Ehc,
193 IN UINT32 Timeout
194 )
195{
196 EFI_STATUS Status;
197 UINT32 Data;
198
199 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD);
200
201 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout);
202
203 //
204 // ACK the IAA bit in USBSTS register. Make sure other
205 // interrupt bits are not ACKed. These bits are WC (Write Clean).
206 //
207 Data = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET);
208 Data &= ~USBSTS_INTACK_MASK;
209 Data |= USBSTS_IAA;
210
211 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data);
212
213 return Status;
214}
215
223VOID
226 )
227{
228 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK);
229}
230
244 IN PEI_USB2_HC_DEV *Ehc,
245 IN UINT32 Timeout
246 )
247{
248 EFI_STATUS Status;
249
250 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
251
252 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout);
253 return Status;
254}
255
268 IN PEI_USB2_HC_DEV *Ehc,
269 IN UINT32 Timeout
270 )
271{
272 EFI_STATUS Status;
273
274 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
275
276 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);
277 return Status;
278}
279
289BOOLEAN
292 )
293{
294 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);
295}
296
306BOOLEAN
309 )
310{
311 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);
312}
313
326 IN PEI_USB2_HC_DEV *Ehc,
327 IN UINT32 Timeout
328 )
329{
330 EFI_STATUS Status;
331
332 //
333 // Host can only be reset when it is halt. If not so, halt it
334 //
335 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
336 Status = EhcHaltHC (Ehc, Timeout);
337
338 if (EFI_ERROR (Status)) {
339 return Status;
340 }
341 }
342
343 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);
344 Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);
345 return Status;
346}
347
360 IN PEI_USB2_HC_DEV *Ehc,
361 IN UINT32 Timeout
362 )
363{
364 EFI_STATUS Status;
365
366 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
367 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);
368 return Status;
369}
370
383 IN PEI_USB2_HC_DEV *Ehc,
384 IN UINT32 Timeout
385 )
386{
387 EFI_STATUS Status;
388
389 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
390 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);
391 return Status;
392}
393
400VOID
403 )
404{
405 UINT8 PortNumber;
406 UINT8 Index;
407 UINT32 RegVal;
408
409 PortNumber = (UINT8)(Ehc->HcStructParams & HCSP_NPORTS);
410 for (Index = 0; Index < PortNumber; Index++) {
411 //
412 // Do not clear port status bits on initialization. Otherwise devices will
413 // not enumerate properly at startup.
414 //
415 RegVal = EhcReadOpReg (Ehc, EHC_PORT_STAT_OFFSET + 4 * Index);
416 RegVal &= ~PORTSC_CHANGE_MASK;
417 RegVal |= PORTSC_POWER;
418 EhcWriteOpReg (Ehc, EHC_PORT_STAT_OFFSET + 4 * Index, RegVal);
419 }
420}
421
440 )
441{
442 EFI_STATUS Status;
443 EFI_PHYSICAL_ADDRESS TempPtr;
444 UINTN PageNumber;
445
446 ASSERT (EhcIsHalt (Ehc));
447
448 //
449 // Allocate the periodic frame and associated memeory
450 // management facilities if not already done.
451 //
452 if (Ehc->PeriodFrame != NULL) {
453 EhcFreeSched (Ehc);
454 }
455
456 PageNumber = sizeof (PEI_URB)/PAGESIZE +1;
457 Status = PeiServicesAllocatePages (
459 PageNumber,
460 &TempPtr
461 );
462 Ehc->Urb = (PEI_URB *)((UINTN)TempPtr);
463 if (Ehc->Urb == NULL) {
464 return Status;
465 }
466
467 EhcPowerOnAllPorts (Ehc);
468 MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
469
470 Status = EhcInitSched (Ehc);
471
472 if (EFI_ERROR (Status)) {
473 return Status;
474 }
475
476 //
477 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
478 //
479 EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, Ehc->High32bitAddr);
480
481 //
482 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
483 //
484 EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
485
486 //
487 // 3. Program periodic frame list, already done in EhcInitSched
488 // 4. Start the Host Controller
489 //
490 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
491
492 //
493 // 5. Set all ports routing to EHC
494 //
495 EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
496
497 //
498 // Wait roothub port power stable
499 //
500 MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
501
502 Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
503
504 if (EFI_ERROR (Status)) {
505 return Status;
506 }
507
508 Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
509
510 if (EFI_ERROR (Status)) {
511 return Status;
512 }
513
514 return EFI_SUCCESS;
515}
516
550EFIAPI
552 IN EFI_PEI_SERVICES **PeiServices,
554 IN UINT8 DeviceAddress,
555 IN UINT8 EndPointAddress,
556 IN UINT8 DeviceSpeed,
557 IN UINTN MaximumPacketLength,
558 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
559 IN OUT UINTN *DataLength,
560 IN OUT UINT8 *DataToggle,
561 IN UINTN TimeOut,
563 OUT UINT32 *TransferResult
564 )
565{
566 PEI_USB2_HC_DEV *Ehc;
567 PEI_URB *Urb;
568 EFI_STATUS Status;
569
570 //
571 // Validate the parameters
572 //
573 if ((DataLength == NULL) || (*DataLength == 0) ||
574 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL))
575 {
576 return EFI_INVALID_PARAMETER;
577 }
578
579 if ((*DataToggle != 0) && (*DataToggle != 1)) {
580 return EFI_INVALID_PARAMETER;
581 }
582
583 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
584 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
585 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)))
586 {
587 return EFI_INVALID_PARAMETER;
588 }
589
590 Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
591 *TransferResult = EFI_USB_ERR_SYSTEM;
592 Status = EFI_DEVICE_ERROR;
593
594 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
595 EhcAckAllInterrupt (Ehc);
596 goto ON_EXIT;
597 }
598
599 EhcAckAllInterrupt (Ehc);
600
601 //
602 // Create a new URB, insert it into the asynchronous
603 // schedule list, then poll the execution status.
604 //
605 Urb = EhcCreateUrb (
606 Ehc,
607 DeviceAddress,
608 EndPointAddress,
609 DeviceSpeed,
610 *DataToggle,
611 MaximumPacketLength,
612 Translator,
613 EHC_BULK_TRANSFER,
614 NULL,
615 Data[0],
616 *DataLength,
617 NULL,
618 NULL,
619 1
620 );
621
622 if (Urb == NULL) {
623 Status = EFI_OUT_OF_RESOURCES;
624 goto ON_EXIT;
625 }
626
627 EhcLinkQhToAsync (Ehc, Urb->Qh);
628 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
629 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
630
631 *TransferResult = Urb->Result;
632 *DataLength = Urb->Completed;
633 *DataToggle = Urb->DataToggle;
634
635 if (*TransferResult == EFI_USB_NOERROR) {
636 Status = EFI_SUCCESS;
637 }
638
639 EhcAckAllInterrupt (Ehc);
640 EhcFreeUrb (Ehc, Urb);
641
642ON_EXIT:
643 return Status;
644}
645
659EFIAPI
661 IN EFI_PEI_SERVICES **PeiServices,
663 OUT UINT8 *PortNumber
664 )
665{
666 PEI_USB2_HC_DEV *EhcDev;
667
668 EhcDev = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
669
670 if (PortNumber == NULL) {
671 return EFI_INVALID_PARAMETER;
672 }
673
674 *PortNumber = (UINT8)(EhcDev->HcStructParams & HCSP_NPORTS);
675 return EFI_SUCCESS;
676}
677
694EFIAPI
696 IN EFI_PEI_SERVICES **PeiServices,
698 IN UINT8 PortNumber,
699 IN EFI_USB_PORT_FEATURE PortFeature
700 )
701{
702 PEI_USB2_HC_DEV *Ehc;
703 UINT32 Offset;
704 UINT32 State;
705 UINT32 TotalPort;
706 EFI_STATUS Status;
707
708 Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
709 Status = EFI_SUCCESS;
710
711 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
712
713 if (PortNumber >= TotalPort) {
714 Status = EFI_INVALID_PARAMETER;
715 goto ON_EXIT;
716 }
717
718 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
719 State = EhcReadOpReg (Ehc, Offset);
720 State &= ~PORTSC_CHANGE_MASK;
721
722 switch (PortFeature) {
723 case EfiUsbPortEnable:
724 //
725 // Clear PORT_ENABLE feature means disable port.
726 //
727 State &= ~PORTSC_ENABLED;
728 EhcWriteOpReg (Ehc, Offset, State);
729 break;
730
731 case EfiUsbPortSuspend:
732 //
733 // A write of zero to this bit is ignored by the host
734 // controller. The host controller will unconditionally
735 // set this bit to a zero when:
736 // 1. software sets the Forct Port Resume bit to a zero from a one.
737 // 2. software sets the Port Reset bit to a one frome a zero.
738 //
739 State &= ~PORSTSC_RESUME;
740 EhcWriteOpReg (Ehc, Offset, State);
741 break;
742
743 case EfiUsbPortReset:
744 //
745 // Clear PORT_RESET means clear the reset signal.
746 //
747 State &= ~PORTSC_RESET;
748 EhcWriteOpReg (Ehc, Offset, State);
749 break;
750
751 case EfiUsbPortOwner:
752 //
753 // Clear port owner means this port owned by EHC
754 //
755 State &= ~PORTSC_OWNER;
756 EhcWriteOpReg (Ehc, Offset, State);
757 break;
758
759 case EfiUsbPortConnectChange:
760 //
761 // Clear connect status change
762 //
763 State |= PORTSC_CONN_CHANGE;
764 EhcWriteOpReg (Ehc, Offset, State);
765 break;
766
767 case EfiUsbPortEnableChange:
768 //
769 // Clear enable status change
770 //
771 State |= PORTSC_ENABLE_CHANGE;
772 EhcWriteOpReg (Ehc, Offset, State);
773 break;
774
775 case EfiUsbPortOverCurrentChange:
776 //
777 // Clear PortOverCurrent change
778 //
779 State |= PORTSC_OVERCUR_CHANGE;
780 EhcWriteOpReg (Ehc, Offset, State);
781 break;
782
783 case EfiUsbPortPower:
784 case EfiUsbPortSuspendChange:
785 case EfiUsbPortResetChange:
786 //
787 // Not supported or not related operation
788 //
789 break;
790
791 default:
792 Status = EFI_INVALID_PARAMETER;
793 break;
794 }
795
796ON_EXIT:
797 return Status;
798}
799
814EFIAPI
816 IN EFI_PEI_SERVICES **PeiServices,
818 IN UINT8 PortNumber,
819 IN EFI_USB_PORT_FEATURE PortFeature
820 )
821{
822 PEI_USB2_HC_DEV *Ehc;
823 UINT32 Offset;
824 UINT32 State;
825 UINT32 TotalPort;
826 EFI_STATUS Status;
827
828 Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
829 Status = EFI_SUCCESS;
830
831 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
832
833 if (PortNumber >= TotalPort) {
834 Status = EFI_INVALID_PARAMETER;
835 goto ON_EXIT;
836 }
837
838 Offset = (UINT32)(EHC_PORT_STAT_OFFSET + (4 * PortNumber));
839 State = EhcReadOpReg (Ehc, Offset);
840
841 //
842 // Mask off the port status change bits, these bits are
843 // write clean bit
844 //
845 State &= ~PORTSC_CHANGE_MASK;
846
847 switch (PortFeature) {
848 case EfiUsbPortEnable:
849 //
850 // Sofeware can't set this bit, Port can only be enable by
851 // EHCI as a part of the reset and enable
852 //
853 State |= PORTSC_ENABLED;
854 EhcWriteOpReg (Ehc, Offset, State);
855 break;
856
857 case EfiUsbPortSuspend:
858 State |= PORTSC_SUSPEND;
859 EhcWriteOpReg (Ehc, Offset, State);
860 break;
861
862 case EfiUsbPortReset:
863 //
864 // Make sure Host Controller not halt before reset it
865 //
866 if (EhcIsHalt (Ehc)) {
867 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
868
869 if (EFI_ERROR (Status)) {
870 break;
871 }
872 }
873
874 //
875 // Set one to PortReset bit must also set zero to PortEnable bit
876 //
877 State |= PORTSC_RESET;
878 State &= ~PORTSC_ENABLED;
879 EhcWriteOpReg (Ehc, Offset, State);
880 break;
881
882 case EfiUsbPortPower:
883 //
884 // Not supported, ignore the operation
885 //
886 Status = EFI_SUCCESS;
887 break;
888
889 case EfiUsbPortOwner:
890 State |= PORTSC_OWNER;
891 EhcWriteOpReg (Ehc, Offset, State);
892 break;
893
894 default:
895 Status = EFI_INVALID_PARAMETER;
896 }
897
898ON_EXIT:
899 return Status;
900}
901
916EFIAPI
918 IN EFI_PEI_SERVICES **PeiServices,
920 IN UINT8 PortNumber,
921 OUT EFI_USB_PORT_STATUS *PortStatus
922 )
923{
924 PEI_USB2_HC_DEV *Ehc;
925 UINT32 Offset;
926 UINT32 State;
927 UINT32 TotalPort;
928 UINTN Index;
929 UINTN MapSize;
930 EFI_STATUS Status;
931
932 if (PortStatus == NULL) {
933 return EFI_INVALID_PARAMETER;
934 }
935
936 Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
937 Status = EFI_SUCCESS;
938
939 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
940
941 if (PortNumber >= TotalPort) {
942 Status = EFI_INVALID_PARAMETER;
943 goto ON_EXIT;
944 }
945
946 Offset = (UINT32)(EHC_PORT_STAT_OFFSET + (4 * PortNumber));
947 PortStatus->PortStatus = 0;
948 PortStatus->PortChangeStatus = 0;
949
950 State = EhcReadOpReg (Ehc, Offset);
951
952 //
953 // Identify device speed. If in K state, it is low speed.
954 // If the port is enabled after reset, the device is of
955 // high speed. The USB bus driver should retrieve the actual
956 // port speed after reset.
957 //
958 if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
959 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
960 } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
961 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
962 }
963
964 //
965 // Convert the EHCI port/port change state to UEFI status
966 //
967 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
968
969 for (Index = 0; Index < MapSize; Index++) {
970 if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
971 PortStatus->PortStatus = (UINT16)(PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
972 }
973 }
974
975 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
976
977 for (Index = 0; Index < MapSize; Index++) {
978 if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
979 PortStatus->PortChangeStatus = (UINT16)(PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
980 }
981 }
982
983ON_EXIT:
984 return Status;
985}
986
1014EFIAPI
1016 IN EFI_PEI_SERVICES **PeiServices,
1018 IN UINT8 DeviceAddress,
1019 IN UINT8 DeviceSpeed,
1020 IN UINTN MaximumPacketLength,
1021 IN EFI_USB_DEVICE_REQUEST *Request,
1022 IN EFI_USB_DATA_DIRECTION TransferDirection,
1023 IN OUT VOID *Data,
1024 IN OUT UINTN *DataLength,
1025 IN UINTN TimeOut,
1027 OUT UINT32 *TransferResult
1028 )
1029{
1030 PEI_USB2_HC_DEV *Ehc;
1031 PEI_URB *Urb;
1032 UINT8 Endpoint;
1033 EFI_STATUS Status;
1034
1035 //
1036 // Validate parameters
1037 //
1038 if ((Request == NULL) || (TransferResult == NULL)) {
1039 return EFI_INVALID_PARAMETER;
1040 }
1041
1042 if ((TransferDirection != EfiUsbDataIn) &&
1043 (TransferDirection != EfiUsbDataOut) &&
1044 (TransferDirection != EfiUsbNoData))
1045 {
1046 return EFI_INVALID_PARAMETER;
1047 }
1048
1049 if ((TransferDirection == EfiUsbNoData) &&
1050 ((Data != NULL) || (*DataLength != 0)))
1051 {
1052 return EFI_INVALID_PARAMETER;
1053 }
1054
1055 if ((TransferDirection != EfiUsbNoData) &&
1056 ((Data == NULL) || (*DataLength == 0)))
1057 {
1058 return EFI_INVALID_PARAMETER;
1059 }
1060
1061 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
1062 (MaximumPacketLength != 32) && (MaximumPacketLength != 64))
1063 {
1064 return EFI_INVALID_PARAMETER;
1065 }
1066
1067 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
1068 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1069 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)))
1070 {
1071 return EFI_INVALID_PARAMETER;
1072 }
1073
1074 Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
1075
1076 Status = EFI_DEVICE_ERROR;
1077 *TransferResult = EFI_USB_ERR_SYSTEM;
1078
1079 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1080 EhcAckAllInterrupt (Ehc);
1081 goto ON_EXIT;
1082 }
1083
1084 EhcAckAllInterrupt (Ehc);
1085
1086 //
1087 // Create a new URB, insert it into the asynchronous
1088 // schedule list, then poll the execution status.
1089 //
1090 //
1091 // Encode the direction in address, although default control
1092 // endpoint is bidirectional. EhcCreateUrb expects this
1093 // combination of Ep addr and its direction.
1094 //
1095 Endpoint = (UINT8)(0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
1096 Urb = EhcCreateUrb (
1097 Ehc,
1098 DeviceAddress,
1099 Endpoint,
1100 DeviceSpeed,
1101 0,
1102 MaximumPacketLength,
1103 Translator,
1104 EHC_CTRL_TRANSFER,
1105 Request,
1106 Data,
1107 *DataLength,
1108 NULL,
1109 NULL,
1110 1
1111 );
1112
1113 if (Urb == NULL) {
1114 Status = EFI_OUT_OF_RESOURCES;
1115 goto ON_EXIT;
1116 }
1117
1118 EhcLinkQhToAsync (Ehc, Urb->Qh);
1119 Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1120 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
1121
1122 //
1123 // Get the status from URB. The result is updated in EhcCheckUrbResult
1124 // which is called by EhcExecTransfer
1125 //
1126 *TransferResult = Urb->Result;
1127 *DataLength = Urb->Completed;
1128
1129 if (*TransferResult == EFI_USB_NOERROR) {
1130 Status = EFI_SUCCESS;
1131 }
1132
1133 EhcAckAllInterrupt (Ehc);
1134 EhcFreeUrb (Ehc, Urb);
1135
1136ON_EXIT:
1137 return Status;
1138}
1139
1152EFIAPI
1154 IN EFI_PEI_SERVICES **PeiServices,
1155 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
1156 IN VOID *Ppi
1157 )
1158{
1159 PEI_USB2_HC_DEV *Ehc;
1160
1161 Ehc = PEI_RECOVERY_USB_EHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor);
1162
1163 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1164
1165 EhcFreeSched (Ehc);
1166
1167 return EFI_SUCCESS;
1168}
1169
1178EFIAPI
1180 IN EFI_PEI_FILE_HANDLE FileHandle,
1181 IN CONST EFI_PEI_SERVICES **PeiServices
1182 )
1183{
1184 PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi;
1185 EFI_STATUS Status;
1186 UINT8 Index;
1187 UINTN ControllerType;
1188 UINTN BaseAddress;
1189 UINTN MemPages;
1190 PEI_USB2_HC_DEV *EhcDev;
1191 EFI_PHYSICAL_ADDRESS TempPtr;
1192
1193 //
1194 // Shadow this PEIM to run from memory
1195 //
1196 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1197 return EFI_SUCCESS;
1198 }
1199
1200 Status = PeiServicesLocatePpi (
1201 &gPeiUsbControllerPpiGuid,
1202 0,
1203 NULL,
1204 (VOID **)&ChipSetUsbControllerPpi
1205 );
1206 if (EFI_ERROR (Status)) {
1207 return EFI_UNSUPPORTED;
1208 }
1209
1210 Index = 0;
1211 while (TRUE) {
1212 Status = ChipSetUsbControllerPpi->GetUsbController (
1213 (EFI_PEI_SERVICES **)PeiServices,
1214 ChipSetUsbControllerPpi,
1215 Index,
1216 &ControllerType,
1217 &BaseAddress
1218 );
1219 //
1220 // When status is error, meant no controller is found
1221 //
1222 if (EFI_ERROR (Status)) {
1223 break;
1224 }
1225
1226 //
1227 // This PEIM is for UHC type controller.
1228 //
1229 if (ControllerType != PEI_EHCI_CONTROLLER) {
1230 Index++;
1231 continue;
1232 }
1233
1234 MemPages = sizeof (PEI_USB2_HC_DEV) / PAGESIZE + 1;
1235 Status = PeiServicesAllocatePages (
1237 MemPages,
1238 &TempPtr
1239 );
1240 if (EFI_ERROR (Status)) {
1241 return EFI_OUT_OF_RESOURCES;
1242 }
1243
1244 ZeroMem ((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
1245 EhcDev = (PEI_USB2_HC_DEV *)((UINTN)TempPtr);
1246
1247 EhcDev->Signature = USB2_HC_DEV_SIGNATURE;
1248
1249 IoMmuInit (&EhcDev->IoMmu);
1250
1251 EhcDev->UsbHostControllerBaseAddress = (UINT32)BaseAddress;
1252
1253 EhcDev->HcStructParams = EhcReadCapRegister (EhcDev, EHC_HCSPARAMS_OFFSET);
1254 EhcDev->HcCapParams = EhcReadCapRegister (EhcDev, EHC_HCCPARAMS_OFFSET);
1255 EhcDev->CapLen = EhcReadCapRegister (EhcDev, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1256 //
1257 // Initialize Uhc's hardware
1258 //
1259 Status = InitializeUsbHC (EhcDev);
1260 if (EFI_ERROR (Status)) {
1261 return Status;
1262 }
1263
1264 EhcDev->Usb2HostControllerPpi.ControlTransfer = EhcControlTransfer;
1265 EhcDev->Usb2HostControllerPpi.BulkTransfer = EhcBulkTransfer;
1266 EhcDev->Usb2HostControllerPpi.GetRootHubPortNumber = EhcGetRootHubPortNumber;
1267 EhcDev->Usb2HostControllerPpi.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1268 EhcDev->Usb2HostControllerPpi.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1269 EhcDev->Usb2HostControllerPpi.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1270
1271 EhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
1272 EhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;
1273 EhcDev->PpiDescriptor.Ppi = &EhcDev->Usb2HostControllerPpi;
1274
1275 Status = PeiServicesInstallPpi (&EhcDev->PpiDescriptor);
1276 if (EFI_ERROR (Status)) {
1277 Index++;
1278 continue;
1279 }
1280
1281 EhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
1282 EhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;
1283 EhcDev->EndOfPeiNotifyList.Notify = EhcEndOfPei;
1284
1285 PeiServicesNotifyPpi (&EhcDev->EndOfPeiNotifyList);
1286
1287 Index++;
1288 }
1289
1290 return EFI_SUCCESS;
1291}
1292
1302 IN PEI_USB2_HC_DEV *EhcDev
1303 )
1304{
1305 EFI_STATUS Status;
1306
1307 EhcResetHC (EhcDev, EHC_RESET_TIMEOUT);
1308
1309 Status = EhcInitHC (EhcDev);
1310
1311 if (EFI_ERROR (Status)) {
1312 return EFI_ABORTED;
1313 }
1314
1315 return EFI_SUCCESS;
1316}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EhcIsHalt(IN PEI_USB2_HC_DEV *Ehc)
Definition: EhcPeim.c:290
EFI_STATUS InitializeUsbHC(IN PEI_USB2_HC_DEV *EhcDev)
Definition: EhcPeim.c:1301
EFI_STATUS EhcHaltHC(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhcPeim.c:359
EFI_STATUS EhcResetHC(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhcPeim.c:325
EFI_STATUS EFIAPI EhcGetRootHubPortStatus(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 PortNumber, OUT EFI_USB_PORT_STATUS *PortStatus)
Definition: EhcPeim.c:917
BOOLEAN EhcIsSysError(IN PEI_USB2_HC_DEV *Ehc)
Definition: EhcPeim.c:307
EFI_STATUS EFIAPI EhcClearRootHubPortFeature(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature)
Definition: EhcPeim.c:695
EFI_STATUS EhcEnablePeriodSchd(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhcPeim.c:243
EFI_STATUS EhcWaitOpRegBit(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit, IN BOOLEAN WaitToSet, IN UINT32 Timeout)
Definition: EhcPeim.c:136
VOID EhcAckAllInterrupt(IN PEI_USB2_HC_DEV *Ehc)
Definition: EhcPeim.c:224
VOID EhcSetOpRegBit(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit)
Definition: EhcPeim.c:86
UINT32 EhcReadCapRegister(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhcPeim.c:167
VOID EhcClearOpRegBit(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit)
Definition: EhcPeim.c:108
VOID EhcWriteOpReg(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Data)
Definition: EhcPeim.c:66
VOID EhcPowerOnAllPorts(IN PEI_USB2_HC_DEV *Ehc)
Definition: EhcPeim.c:401
EFI_STATUS EhcSetAndWaitDoorBell(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhcPeim.c:191
EFI_STATUS EhcRunHC(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhcPeim.c:382
EFI_STATUS EhcInitHC(IN PEI_USB2_HC_DEV *Ehc)
Definition: EhcPeim.c:438
EFI_STATUS EFIAPI EhcEndOfPei(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi)
Definition: EhcPeim.c:1153
EFI_STATUS EhcEnableAsyncSchd(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhcPeim.c:267
UINT32 EhcReadOpReg(IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhcPeim.c:43
EFI_STATUS EFIAPI EhcControlTransfer(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 DeviceAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN EFI_USB_DEVICE_REQUEST *Request, IN EFI_USB_DATA_DIRECTION TransferDirection, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: EhcPeim.c:1015
EFI_STATUS EFIAPI EhcPeimEntry(IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices)
Definition: EhcPeim.c:1179
EFI_STATUS EFIAPI EhcGetRootHubPortNumber(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, OUT UINT8 *PortNumber)
Definition: EhcPeim.c:660
EFI_STATUS EFIAPI EhcBulkTransfer(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN UINT8 DeviceSpeed, IN UINTN MaximumPacketLength, IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], IN OUT UINTN *DataLength, IN OUT UINT8 *DataToggle, IN UINTN TimeOut, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, OUT UINT32 *TransferResult)
Definition: EhcPeim.c:551
EFI_STATUS EFIAPI EhcSetRootHubPortFeature(IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB2_HOST_CONTROLLER_PPI *This, IN UINT8 PortNumber, IN EFI_USB_PORT_FEATURE PortFeature)
Definition: EhcPeim.c:815
EFI_STATUS EhcInitSched(IN USB2_HC_DEV *Ehc)
Definition: EhciSched.c:102
VOID EhcLinkQhToAsync(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
Definition: EhciSched.c:312
VOID EhcFreeSched(IN USB2_HC_DEV *Ehc)
Definition: EhciSched.c:250
EFI_STATUS EhcExecTransfer(IN USB2_HC_DEV *Ehc, IN URB *Urb, IN UINTN TimeOut)
Definition: EhciSched.c:668
VOID EhcUnlinkQhFromAsync(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
Definition: EhciSched.c:345
URB * EhcCreateUrb(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpAddr, IN UINT8 DevSpeed, IN UINT8 Toggle, IN UINTN MaxPacket, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub, IN UINTN Type, IN EFI_USB_DEVICE_REQUEST *Request, IN VOID *Data, IN UINTN DataLen, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, IN UINTN Interval)
Definition: EhciUrb.c:528
VOID EhcFreeUrb(IN USB2_HC_DEV *Ehc, IN URB *Urb)
Definition: EhciUrb.c:313
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
EFI_STATUS EFIAPI PeiServicesNotifyPpi(IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList)
EFI_STATUS EFIAPI PeiServicesAllocatePages(IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT EFI_PHYSICAL_ADDRESS *Memory)
EFI_STATUS EFIAPI PeiServicesInstallPpi(IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList)
EFI_STATUS EFIAPI PeiServicesRegisterForShadow(IN EFI_PEI_FILE_HANDLE FileHandle)
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_USB_PORT_FEATURE
#define USB_PORT_STAT_C_CONNECTION
#define USB_PORT_STAT_CONNECTION
EFI_USB_DATA_DIRECTION
Definition: UsbIo.h:44
VOID IoMmuInit(OUT EDKII_IOMMU_PPI **IoMmu)
Definition: DmaMem.c:238
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
@ EfiBootServicesCode
#define PEI_EHCI_CONTROLLER
Definition: UsbController.h:43
EFI_PEIM_NOTIFY_ENTRY_POINT Notify
Definition: PiPeiCis.h:122