+GUID gUsb3DbgGuid = USB3_DBG_GUID;\r
+\r
+USB3_DEBUG_PORT_HANDLE *mUsb3Instance = NULL;\r
+\r
+/**\r
+ Creates a named event that can be signaled.\r
+\r
+ This function creates an event using NotifyTpl, NoifyFunction.\r
+ If Name is NULL, then ASSERT().\r
+ If NotifyTpl is not a legal TPL value, then ASSERT().\r
+ If NotifyFunction is NULL, then ASSERT().\r
+\r
+ @param Name Supplies the GUID name of the event.\r
+ @param NotifyTpl Supplies the task priority level of the event notifications.\r
+ @param NotifyFunction Supplies the function to notify when the event is signaled.\r
+ @param Event A pointer to the event created.\r
+\r
+ @retval EFI_SUCCESS A named event was created.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Usb3NamedEventListen (\r
+ IN CONST EFI_GUID *Name,\r
+ IN EFI_TPL NotifyTpl,\r
+ IN EFI_EVENT_NOTIFY NotifyFunction,\r
+ IN EFI_EVENT *Event\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *RegistrationLocal;\r
+\r
+ ASSERT (Name != NULL);\r
+ ASSERT (NotifyFunction != NULL);\r
+ ASSERT (NotifyTpl <= TPL_HIGH_LEVEL);\r
+\r
+ //\r
+ // Create event\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ NotifyTpl,\r
+ NotifyFunction,\r
+ NULL,\r
+ Event\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register for an installation of protocol interface\r
+ //\r
+ Status = gBS->RegisterProtocolNotify (\r
+ (EFI_GUID *) Name,\r
+ *Event,\r
+ &RegistrationLocal\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ USB3 map one DMA buffer.\r
+\r
+ @param Instance Pointer to USB3 debug port instance.\r
+ @param PciIo Pointer to PciIo for USB3 debug port.\r
+ @param Address DMA buffer address to be mapped.\r
+ @param NumberOfBytes Number of bytes to be mapped.\r
+ @param BackupBuffer Backup buffer address.\r
+\r
+**/\r
+VOID\r
+Usb3MapOneDmaBuffer (\r
+ IN USB3_DEBUG_PORT_HANDLE *Instance,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_PHYSICAL_ADDRESS Address,\r
+ IN UINTN NumberOfBytes,\r
+ IN EFI_PHYSICAL_ADDRESS BackupBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *HostAddress;\r
+ EFI_PHYSICAL_ADDRESS DeviceAddress;\r
+ VOID *Mapping;\r
+\r
+ HostAddress = (VOID *) (UINTN) Address;\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ EfiPciIoOperationBusMasterCommonBuffer,\r
+ HostAddress,\r
+ &NumberOfBytes,\r
+ &DeviceAddress,\r
+ &Mapping\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress));\r
+ if (Instance->FromHob) {\r
+ //\r
+ // Reallocate the DMA buffer by AllocateAddress with\r
+ // the memory type accessible by SMM.\r
+ //\r
+ CopyMem ((VOID *) (UINTN) BackupBuffer, (VOID *) (UINTN) Address, NumberOfBytes);\r
+ Status = gBS->FreePages (Address, EFI_SIZE_TO_PAGES (NumberOfBytes));\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->AllocatePages (\r
+ AllocateAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (NumberOfBytes),\r
+ &Address\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ CopyMem ((VOID *) (UINTN) Address, (VOID *) (UINTN) BackupBuffer, NumberOfBytes);\r
+ }\r
+}\r
+\r
+/**\r
+ USB3 map DMA buffers.\r
+\r
+ @param Instance Pointer to USB3 debug port instance.\r
+ @param PciIo Pointer to PciIo for USB3 debug port.\r
+\r
+**/\r
+VOID\r
+Usb3MapDmaBuffers (\r
+ IN USB3_DEBUG_PORT_HANDLE *Instance,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDKII_IOMMU_PROTOCOL *IoMmu;\r
+ EFI_PHYSICAL_ADDRESS BackupBuffer;\r
+ UINTN BackupBufferSize;\r
+\r
+ IoMmu = NULL;\r
+ Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **) &IoMmu);\r
+ if (EFI_ERROR (Status) || (IoMmu == NULL)) {\r
+ //\r
+ // No need to map the DMA buffers.\r
+ //\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Allocate backup buffer for the case that the USB3\r
+ // debug port instance and DMA buffers are from PEI HOB.\r
+ // For this case, the DMA buffers need to be reallocated\r
+ // by AllocateAddress with the memory type accessible by\r
+ // SMM.\r
+ //\r
+ BackupBufferSize = MAX (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE,\r
+ MAX (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER,\r
+ MAX (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER,\r
+ MAX (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER,\r
+ MAX (sizeof (XHC_DC_CONTEXT),\r
+ STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN)))));\r
+\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ EFI_SIZE_TO_PAGES (BackupBufferSize),\r
+ &BackupBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ Instance->UrbIn.Data,\r
+ XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE,\r
+ BackupBuffer\r
+ );\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ Instance->TransferRingIn.RingSeg0,\r
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER,\r
+ BackupBuffer\r
+ );\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ Instance->TransferRingOut.RingSeg0,\r
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER,\r
+ BackupBuffer\r
+ );\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ Instance->EventRing.EventRingSeg0,\r
+ sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER,\r
+ BackupBuffer\r
+ );\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ Instance->EventRing.ERSTBase,\r
+ sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER,\r
+ BackupBuffer\r
+ );\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ Instance->DebugCapabilityContext,\r
+ sizeof (XHC_DC_CONTEXT),\r
+ BackupBuffer\r
+ );\r
+\r
+ Usb3MapOneDmaBuffer (\r
+ Instance,\r
+ PciIo,\r
+ ((XHC_DC_CONTEXT *) (UINTN) Instance->DebugCapabilityContext)->DbcInfoContext.String0DescAddress,\r
+ STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN,\r
+ BackupBuffer\r
+ );\r
+\r
+ gBS->FreePages (BackupBuffer, EFI_SIZE_TO_PAGES (BackupBufferSize));\r
+}\r
+\r
+/**\r
+ Invoke a notification event\r
+\r
+ @param[in] Event Event whose notification function is being invoked.\r
+ @param[in] Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Usb3PciIoNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN PciIoHandleCount;\r
+ EFI_HANDLE *PciIoHandleBuffer;\r
+ UINTN Index;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN PciSegment;\r
+ UINTN PciBusNumber;\r
+ UINTN PciDeviceNumber;\r
+ UINTN PciFunctionNumber;\r
+ UINT32 PciAddress;\r
+\r
+ ASSERT (mUsb3Instance != NULL);\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &PciIoHandleCount,\r
+ &PciIoHandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status) &&\r
+ (PciIoHandleBuffer != NULL) &&\r
+ (PciIoHandleCount != 0)) { \r
+ for (Index = 0; Index < PciIoHandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ PciIoHandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = PciIo->GetLocation (PciIo, &PciSegment, &PciBusNumber, &PciDeviceNumber, &PciFunctionNumber);\r
+ ASSERT_EFI_ERROR (Status);\r
+ PciAddress = (UINT32) ((PciBusNumber << 20) | (PciDeviceNumber << 15) | (PciFunctionNumber << 12));\r
+ if (PciAddress == PcdGet32(PcdUsbXhciPciAddress)) {\r
+ //\r
+ // Found the PciIo for USB3 debug port.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+ mUsb3Instance->InNotify = TRUE;\r
+ Usb3MapDmaBuffers (mUsb3Instance, PciIo);\r
+ mUsb3Instance->InNotify = FALSE;\r
+ gBS->CloseEvent ((EFI_EVENT) (UINTN) mUsb3Instance->PciIoEvent);\r
+ break;\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (PciIoHandleBuffer);\r
+ }\r
+}\r
+\r
+/**\r
+ Return USB3 debug instance address.\r
+\r
+**/ \r
+USB3_DEBUG_PORT_HANDLE *\r
+GetUsb3DebugPortInstance (\r
+ VOID\r
+ )\r
+{\r
+ USB3_DEBUG_PORT_HANDLE *Instance;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+\r
+ Instance = NULL;\r
+\r
+ if (mUsb3Instance != NULL) {\r
+ Instance = mUsb3Instance;\r
+ goto Done;\r
+ }\r
+\r
+ Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);\r
+ if (Hob.Raw != NULL) {\r
+ Instance = GET_GUID_HOB_DATA (Hob.Guid);\r
+ }\r
+\r
+Done:\r
+ if (Instance != NULL) {\r
+ DiscoverInitializeUsbDebugPort (Instance);\r
+ }\r
+ return Instance;\r
+}\r
+\r