+\r
+EFI_STATUS\r
+SetAndWaitDoorBell (\r
+ IN USB2_HC_DEV *HcDev,\r
+ IN UINTN Timeout\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Set DoorBell and wait it to complete\r
+\r
+Arguments:\r
+\r
+ HcDev - USB2_HC_DEV\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Success\r
+ EFI_DEVICE_ERROR Fail\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 Data;\r
+ UINTN Delay;\r
+\r
+ Status = ReadEhcOperationalReg (\r
+ HcDev,\r
+ USBCMD,\r
+ &Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto exit;\r
+ }\r
+\r
+ Data |= USBCMD_IAAD;\r
+ Status = WriteEhcOperationalReg (\r
+ HcDev,\r
+ USBCMD,\r
+ Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Timeout is in US unit\r
+ //\r
+ Delay = (Timeout / 50) + 1;\r
+ do {\r
+ Status = ReadEhcOperationalReg (\r
+ HcDev,\r
+ USBSTS,\r
+ &Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto exit;\r
+ }\r
+\r
+ if ((Data & USBSTS_IAA) == USBSTS_IAA) {\r
+ break;\r
+ }\r
+\r
+ gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);\r
+\r
+ } while (Delay--);\r
+\r
+ Data = Data & 0xFFFFFFC0;\r
+ Data |= USBSTS_IAA;\r
+ Status = WriteEhcOperationalReg (\r
+ HcDev,\r
+ USBSTS,\r
+ Data\r
+ );\r
+\r
+exit:\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+EFI_STATUS\r
+CreateNULLQH (\r
+ IN USB2_HC_DEV *HcDev\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Create the NULL QH to make it as the Async QH header\r
+\r
+Arguments:\r
+\r
+ HcDev - USB2_HC_DEV\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Success\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EHCI_QH_ENTITY *NULLQhPtr;\r
+ //\r
+ // Allocate memory for Qh structure\r
+ //\r
+ Status = EhciAllocatePool (\r
+ HcDev,\r
+ (UINT8 **) &NULLQhPtr,\r
+ sizeof (EHCI_QH_ENTITY)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ NULLQhPtr->Qh.Status = QTD_STATUS_HALTED;\r
+ NULLQhPtr->Qh.HeadReclamationFlag = 1;\r
+ NULLQhPtr->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(NULLQhPtr->Qh) >> 5));\r
+ NULLQhPtr->Qh.SelectType = QH_SELECT_TYPE;\r
+ NULLQhPtr->Qh.NextQtdTerminate = 1;\r
+\r
+ NULLQhPtr->Next = NULLQhPtr;\r
+ NULLQhPtr->Prev = NULLQhPtr;\r
+\r
+ HcDev->NULLQH = NULLQhPtr;\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+VOID\r
+DestroyNULLQH (\r
+ IN USB2_HC_DEV *HcDev\r
+ )\r
+{\r
+\r
+ if (HcDev->NULLQH != NULL) {\r
+ EhciFreePool (HcDev, (UINT8 *)HcDev->NULLQH, sizeof (EHCI_QH_ENTITY));\r
+ HcDev->NULLQH = NULL;\r
+ }\r
+}\r
+\r
+\r
+\r