PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
which is used to enable recovery function from USB Drivers.\r
\r
-Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
return Data;\r
}\r
\r
-/**\r
- Read XHCI door bell register.\r
-\r
- @param Xhc The XHCI device.\r
- @param Offset The offset of the door bell register.\r
-\r
- @return The register content read\r
-\r
-**/\r
-UINT32\r
-XhcPeiReadDoorBellReg (\r
- IN PEI_XHC_DEV *Xhc,\r
- IN UINT32 Offset\r
- )\r
-{\r
- UINT32 Data;\r
-\r
- ASSERT (Xhc->DBOff != 0);\r
\r
- Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Xhc->DBOff + Offset);\r
-\r
- return Data;\r
-}\r
\r
/**\r
Write the data to the XHCI door bell register.\r
}\r
\r
XhcPeiSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);\r
+ //\r
+ // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.\r
+ // Otherwise there may have the timeout case happened.\r
+ // The below is a workaround to solve such problem.\r
+ //\r
+ MicroSecondDelay (1000);\r
Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);\r
ON_EXIT:\r
DEBUG ((EFI_D_INFO, "XhcPeiResetHC: %r\n", Status));\r
if (EFI_ERROR(RecoveryStatus)) {\r
DEBUG((EFI_D_ERROR, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));\r
}\r
- goto FREE_URB;\r
+ XhcPeiFreeUrb (Xhc, Urb);\r
+ goto ON_EXIT;\r
} else {\r
if (*TransferResult == EFI_USB_NOERROR) {\r
Status = EFI_SUCCESS;\r
- } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+ } else if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {\r
RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);\r
if (EFI_ERROR (RecoveryStatus)) {\r
DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));\r
}\r
Status = EFI_DEVICE_ERROR;\r
- goto FREE_URB;\r
+ XhcPeiFreeUrb (Xhc, Urb);\r
+ goto ON_EXIT;\r
} else {\r
- goto FREE_URB;\r
+ XhcPeiFreeUrb (Xhc, Urb);\r
+ goto ON_EXIT;\r
}\r
}\r
+ //\r
+ // Unmap data before consume.\r
+ //\r
+ XhcPeiFreeUrb (Xhc, Urb);\r
\r
//\r
// Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.\r
// Store a copy of device scriptor as hub device need this info to configure endpoint.\r
//\r
CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
- if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\r
+ if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {\r
//\r
// If it's a usb3.0 device, then its max packet size is a 2^n.\r
//\r
Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
if (Xhc->UsbDevContext[SlotId].ConfDesc == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
- goto FREE_URB;\r
+ goto ON_EXIT;\r
}\r
if (Xhc->HcCParams.Data.Csz == 0) {\r
Status = XhcPeiEvaluateContext (Xhc, SlotId, MaxPacket0);\r
Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool (*DataLength);\r
if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
- goto FREE_URB;\r
+ goto ON_EXIT;\r
}\r
CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\r
}\r
*(UINT32 *) Data = *(UINT32 *) &PortStatus;\r
}\r
\r
-FREE_URB:\r
- XhcPeiFreeUrb (Xhc, Urb);\r
-\r
ON_EXIT:\r
\r
if (EFI_ERROR (Status)) {\r
} else {\r
if (*TransferResult == EFI_USB_NOERROR) {\r
Status = EFI_SUCCESS;\r
- } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+ } else if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {\r
RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);\r
if (EFI_ERROR (RecoveryStatus)) {\r
DEBUG ((EFI_D_ERROR, "XhcPeiBulkTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ One notified function to stop the Host Controller at the end of PEI\r
+\r
+ @param[in] PeiServices Pointer to PEI Services Table.\r
+ @param[in] NotifyDescriptor Pointer to the descriptor for the Notification event that\r
+ caused this function to execute.\r
+ @param[in] Ppi Pointer to the PPI data associated with this function.\r
+\r
+ @retval EFI_SUCCESS The function completes successfully\r
+ @retval others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcEndOfPei (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
+ IN VOID *Ppi\r
+ )\r
+{\r
+ PEI_XHC_DEV *Xhc;\r
+\r
+ Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY(NotifyDescriptor);\r
+\r
+ XhcPeiHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+\r
+ XhcPeiFreeSched (Xhc);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
@param FileHandle Handle of the file being invoked.\r
@param PeiServices Describes the list of possible PEI Services.\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ IoMmuInit ();\r
+\r
Index = 0;\r
while (TRUE) {\r
Status = UsbControllerPpi->GetUsbController (\r
XhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;\r
XhcDev->PpiDescriptor.Ppi = &XhcDev->Usb2HostControllerPpi;\r
\r
+ XhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
+ XhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;\r
+ XhcDev->EndOfPeiNotifyList.Notify = XhcEndOfPei;\r
+\r
PeiServicesInstallPpi (&XhcDev->PpiDescriptor);\r
+ PeiServicesNotifyPpi (&XhcDev->EndOfPeiNotifyList);\r
\r
Index++;\r
}\r