+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- EhciSched.c\r
-\r
-Abstract:\r
-\r
-\r
-Revision History\r
---*/\r
-\r
-#include "Ehci.h"\r
-\r
-STATIC\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
-EFI_STATUS\r
-InitialPeriodicFrameList (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINTN Length\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Initialize Periodic Schedule Frame List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- Length - Frame List Length\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- VOID *CommonBuffer;\r
- EFI_PHYSICAL_ADDRESS FrameBuffer;\r
- VOID *Map;\r
- UINTN BufferSizeInPages;\r
- UINTN BufferSizeInBytes;\r
- UINTN FrameIndex;\r
- FRAME_LIST_ENTRY *FrameEntryPtr;\r
-\r
- //\r
- // The Frame List is a common buffer that will be\r
- // accessed by both the cpu and the usb bus master\r
- // at the same time.\r
- // The Frame List ocupies 4K bytes,\r
- // and must be aligned on 4-Kbyte boundaries.\r
- //\r
- if (EHCI_MAX_FRAME_LIST_LENGTH != Length && IsFrameListProgrammable (HcDev)) {\r
- Status = SetFrameListLen (HcDev, Length);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto exit;\r
- }\r
- }\r
-\r
- BufferSizeInBytes = EFI_PAGE_SIZE;\r
- BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);\r
- Status = HcDev->PciIo->AllocateBuffer (\r
- HcDev->PciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- BufferSizeInPages,\r
- &CommonBuffer,\r
- 0\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: PciIo->AllocateBuffer Failed\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterCommonBuffer,\r
- CommonBuffer,\r
- &BufferSizeInBytes,\r
- &FrameBuffer,\r
- &Map\r
- );\r
- if (EFI_ERROR (Status) || (BufferSizeInBytes != EFI_PAGE_SIZE)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: PciIo->MapBuffer Failed\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto free_buffer;\r
- }\r
-\r
- //\r
- // Put high 32bit into CtrlDataStructSeg reg\r
- // when 64bit addressing range capability\r
- //\r
- if (HcDev->Is64BitCapable != 0) {\r
- HcDev->High32BitAddr = (UINT32) GET_32B_TO_63B (FrameBuffer);\r
-\r
- Status = SetCtrlDataStructSeg (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: SetCtrlDataStructSeg Failed\n"));\r
- Status = EFI_DEVICE_ERROR;\r
- goto unmap_buffer;\r
- }\r
- }\r
-\r
- //\r
- // Tell the Host Controller where the Frame List lies,\r
- // by set the Frame List Base Address Register.\r
- //\r
- Status = SetFrameListBaseAddr (HcDev, (UINT32) FrameBuffer);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto unmap_buffer;\r
- }\r
-\r
- HcDev->PeriodicFrameListLength = Length;\r
- HcDev->PeriodicFrameListBuffer = (VOID *) ((UINTN) FrameBuffer);\r
- HcDev->PeriodicFrameListMap = Map;\r
-\r
- //\r
- // Init Frame List Array fields\r
- //\r
- FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;\r
- for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {\r
- FrameEntryPtr->LinkPointer = 0;\r
- FrameEntryPtr->Rsvd = 0;\r
- FrameEntryPtr->SelectType = 0;\r
- FrameEntryPtr->LinkTerminate = TRUE;\r
- FrameEntryPtr++;\r
- }\r
-\r
- goto exit;\r
-\r
-unmap_buffer:\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Map);\r
-free_buffer:\r
- HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);\r
-exit:\r
- return Status;\r
-}\r
-\r
-VOID\r
-DeinitialPeriodicFrameList (\r
- IN USB2_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Deinitialize Periodic Schedule Frame List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->PeriodicFrameListMap);\r
- HcDev->PciIo->FreeBuffer (HcDev->PciIo, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE), HcDev->PeriodicFrameListBuffer);\r
- return ;\r
-}\r
-\r
-EFI_STATUS\r
-CreatePollingTimer (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EFI_EVENT_NOTIFY NotifyFunction\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Async Request Polling Timer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- NotifyFunction - Timer Notify Function\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- return gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- NotifyFunction,\r
- HcDev,\r
- &HcDev->AsyncRequestEvent\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-DestoryPollingTimer (\r
- IN USB2_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Destory Async Request Polling Timer\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
- return gBS->CloseEvent (HcDev->AsyncRequestEvent);\r
-}\r
-\r
-EFI_STATUS\r
-StartPollingTimer (\r
- IN USB2_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Start Async Request Polling Timer\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
- return gBS->SetTimer (\r
- HcDev->AsyncRequestEvent,\r
- TimerPeriodic,\r
- EHCI_ASYNC_REQUEST_POLLING_TIME\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-StopPollingTimer (\r
- IN USB2_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Stop Async Request Polling Timer\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
- return gBS->SetTimer (\r
- HcDev->AsyncRequestEvent,\r
- TimerCancel,\r
- EHCI_ASYNC_REQUEST_POLLING_TIME\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-CreateQh (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 DeviceAddr,\r
- IN UINT8 Endpoint,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaxPacketLen,\r
- OUT EHCI_QH_ENTITY **QhPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qh Structure and Pre-Initialize\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DeviceAddr - Address of Device\r
- Endpoint - Endpoint Number\r
- DeviceSpeed - Device Speed\r
- MaxPacketLen - Max Length of one Packet\r
- QhPtrPtr - A pointer of pointer to Qh for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EHCI_QH_HW *QhHwPtr;\r
-\r
- ASSERT (HcDev);\r
- ASSERT (QhPtrPtr);\r
-\r
- *QhPtrPtr = NULL;\r
-\r
- //\r
- // Allocate memory for Qh structure\r
- //\r
- Status = EhciAllocatePool (\r
- HcDev,\r
- (UINT8 **) QhPtrPtr,\r
- sizeof (EHCI_QH_ENTITY)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- //\r
- // Software field\r
- //\r
- (*QhPtrPtr)->Next = NULL;\r
- (*QhPtrPtr)->Prev = NULL;\r
- (*QhPtrPtr)->FirstQtdPtr = NULL;\r
- (*QhPtrPtr)->AltQtdPtr = NULL;\r
- (*QhPtrPtr)->LastQtdPtr = NULL;\r
-\r
- //\r
- // Hardware field\r
- //\r
- QhHwPtr = &((*QhPtrPtr)->Qh);\r
- QhHwPtr->QhHorizontalPointer = 0;\r
- QhHwPtr->SelectType = 0;\r
- QhHwPtr->MaxPacketLen = (UINT32) MaxPacketLen;\r
- QhHwPtr->EndpointSpeed = (DeviceSpeed & 0x3);\r
- QhHwPtr->EndpointNum = (Endpoint & 0x0F);\r
- QhHwPtr->DeviceAddr = (DeviceAddr & 0x7F);\r
- QhHwPtr->Multiplier = HIGH_BANDWIDTH_PIPE_MULTIPLIER;\r
- QhHwPtr->Rsvd1 = 0;\r
- QhHwPtr->Rsvd2 = 0;\r
- QhHwPtr->Rsvd3 = 0;\r
- QhHwPtr->Rsvd4 = 0;\r
- QhHwPtr->Rsvd5 = 0;\r
- QhHwPtr->Rsvd6 = 0;\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-VOID\r
-DestoryQh (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_QH_ENTITY *QhPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Destory Qh Structure\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- QhPtr - A pointer to Qh\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- ASSERT (HcDev);\r
- ASSERT (QhPtr);\r
-\r
- EhciFreePool (HcDev, (UINT8 *) QhPtr, sizeof (EHCI_QH_ENTITY));\r
- return ;\r
-}\r
-\r
-EFI_STATUS\r
-CreateControlQh (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 DeviceAddr,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaxPacketLen,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT EHCI_QH_ENTITY **QhPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qh for Control Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DeviceAddr - Address of Device\r
- DeviceSpeed - Device Speed\r
- MaxPacketLen - Max Length of one Packet\r
- Translator - Translator Transaction for SplitX\r
- QhPtrPtr - A pointer of pointer to Qh for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Create and init Control Qh\r
- //\r
- Status = CreateQh (\r
- HcDev,\r
- DeviceAddr,\r
- 0,\r
- DeviceSpeed,\r
- MaxPacketLen,\r
- QhPtrPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
- //\r
- // Software field\r
- //\r
- (*QhPtrPtr)->Next = (*QhPtrPtr);\r
- (*QhPtrPtr)->Prev = (*QhPtrPtr);\r
- (*QhPtrPtr)->TransferType = CONTROL_TRANSFER;\r
-\r
- //\r
- // Hardware field\r
- //\r
- // Control Transfer use DataToggleControl\r
- //\r
- (*QhPtrPtr)->Qh.DataToggleControl = TRUE;\r
- (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);\r
- (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE;\r
- (*QhPtrPtr)->Qh.QhTerminate = FALSE;\r
- if (EFI_USB_SPEED_HIGH != DeviceSpeed) {\r
- (*QhPtrPtr)->Qh.ControlEndpointFlag = TRUE;\r
- }\r
- (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD;\r
- if (NULL != Translator) {\r
- (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;\r
- (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;\r
- (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-CreateBulkQh (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 DeviceAddr,\r
- IN UINT8 EndPointAddr,\r
- IN UINT8 DeviceSpeed,\r
- IN UINT8 DataToggle,\r
- IN UINTN MaxPacketLen,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT EHCI_QH_ENTITY **QhPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qh for Bulk Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DeviceAddr - Address of Device\r
- EndPointAddr - Address of Endpoint\r
- DeviceSpeed - Device Speed\r
- MaxPacketLen - Max Length of one Packet\r
- Translator - Translator Transaction for SplitX\r
- QhPtrPtr - A pointer of pointer to Qh for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Create and init Bulk Qh\r
- //\r
- Status = CreateQh (\r
- HcDev,\r
- DeviceAddr,\r
- EndPointAddr,\r
- DeviceSpeed,\r
- MaxPacketLen,\r
- QhPtrPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- //\r
- // Software fields\r
- //\r
- (*QhPtrPtr)->Next = (*QhPtrPtr);\r
- (*QhPtrPtr)->Prev = (*QhPtrPtr);\r
- (*QhPtrPtr)->TransferType = BULK_TRANSFER;\r
-\r
- //\r
- // Hardware fields\r
- //\r
- // BulkTransfer don't use DataToggleControl\r
- //\r
- (*QhPtrPtr)->Qh.DataToggleControl = FALSE;\r
- (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);\r
- (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE;\r
- (*QhPtrPtr)->Qh.QhTerminate = FALSE;\r
- (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD;\r
- (*QhPtrPtr)->Qh.DataToggle = DataToggle;\r
- if (NULL != Translator) {\r
- (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;\r
- (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;\r
- (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-CreateInterruptQh (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 DeviceAddr,\r
- IN UINT8 EndPointAddr,\r
- IN UINT8 DeviceSpeed,\r
- IN UINT8 DataToggle,\r
- IN UINTN MaxPacketLen,\r
- IN UINTN Interval,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT EHCI_QH_ENTITY **QhPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qh for Control Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DeviceAddr - Address of Device\r
- EndPointAddr - Address of Endpoint\r
- DeviceSpeed - Device Speed\r
- MaxPacketLen - Max Length of one Packet\r
- Interval - value of interval\r
- Translator - Translator Transaction for SplitX\r
- QhPtrPtr - A pointer of pointer to Qh for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Create and init InterruptQh\r
- //\r
- Status = CreateQh (\r
- HcDev,\r
- DeviceAddr,\r
- EndPointAddr,\r
- DeviceSpeed,\r
- MaxPacketLen,\r
- QhPtrPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- //\r
- // Software fields\r
- //\r
- if (Interval == 0) {\r
- (*QhPtrPtr)->TransferType = SYNC_INTERRUPT_TRANSFER;\r
- } else {\r
- (*QhPtrPtr)->TransferType = ASYNC_INTERRUPT_TRANSFER;\r
- }\r
- (*QhPtrPtr)->Interval = GetApproxiOfInterval (Interval);\r
-\r
- //\r
- // Hardware fields\r
- //\r
- // InterruptTranfer don't use DataToggleControl\r
- //\r
- (*QhPtrPtr)->Qh.DataToggleControl = FALSE;\r
- (*QhPtrPtr)->Qh.QhHorizontalPointer = 0;\r
- (*QhPtrPtr)->Qh.QhTerminate = TRUE;\r
- (*QhPtrPtr)->Qh.NakCountReload = 0;\r
- (*QhPtrPtr)->Qh.InerruptScheduleMask = MICRO_FRAME_0_CHANNEL;\r
- (*QhPtrPtr)->Qh.SplitComletionMask = (MICRO_FRAME_2_CHANNEL | MICRO_FRAME_3_CHANNEL | MICRO_FRAME_4_CHANNEL);\r
- (*QhPtrPtr)->Qh.DataToggle = DataToggle;\r
- if (NULL != Translator) {\r
- (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;\r
- (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;\r
- (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-CreateQtd (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 *DataPtr,\r
- IN UINTN DataLen,\r
- IN UINT8 PktId,\r
- IN UINT8 Toggle,\r
- IN UINT8 QtdStatus,\r
- OUT EHCI_QTD_ENTITY **QtdPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtd Structure and Pre-Initialize it\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DataPtr - A pointer to user data buffer to transfer\r
- DataLen - Length of user data to transfer\r
- PktId - Packet Identification of this Qtd\r
- Toggle - Data Toggle of this Qtd\r
- QtdStatus - Default value of status of this Qtd\r
- QtdPtrPtr - A pointer of pointer to Qtd for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EHCI_QTD_HW *QtdHwPtr;\r
-\r
- ASSERT (HcDev);\r
- ASSERT (QtdPtrPtr);\r
-\r
- //\r
- // Create memory for Qtd structure\r
- //\r
- Status = EhciAllocatePool (\r
- HcDev,\r
- (UINT8 **) QtdPtrPtr,\r
- sizeof (EHCI_QTD_ENTITY)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- //\r
- // Software field\r
- //\r
- (*QtdPtrPtr)->TotalBytes = (UINT32) DataLen;\r
- (*QtdPtrPtr)->StaticTotalBytes = (UINT32) DataLen;\r
- (*QtdPtrPtr)->Prev = NULL;\r
- (*QtdPtrPtr)->Next = NULL;\r
-\r
- //\r
- // Hardware field\r
- //\r
- QtdHwPtr = &((*QtdPtrPtr)->Qtd);\r
- QtdHwPtr->NextQtdPointer = 0;\r
- QtdHwPtr->NextQtdTerminate = TRUE;\r
- QtdHwPtr->AltNextQtdPointer = 0;\r
- QtdHwPtr->AltNextQtdTerminate = TRUE;\r
- QtdHwPtr->DataToggle = Toggle;\r
- QtdHwPtr->TotalBytes = (UINT32) DataLen;\r
- QtdHwPtr->CurrentPage = 0;\r
- QtdHwPtr->ErrorCount = QTD_ERROR_COUNTER;\r
- QtdHwPtr->Status = QtdStatus;\r
- QtdHwPtr->Rsvd1 = 0;\r
- QtdHwPtr->Rsvd2 = 0;\r
- QtdHwPtr->Rsvd3 = 0;\r
- QtdHwPtr->Rsvd4 = 0;\r
- QtdHwPtr->Rsvd5 = 0;\r
- QtdHwPtr->Rsvd6 = 0;\r
-\r
- //\r
- // Set PacketID [Setup/Data/Status]\r
- //\r
- switch (PktId) {\r
- case SETUP_PACKET_ID:\r
- QtdHwPtr->PidCode = SETUP_PACKET_PID_CODE;\r
- break;\r
-\r
- case INPUT_PACKET_ID:\r
- QtdHwPtr->PidCode = INPUT_PACKET_PID_CODE;\r
- break;\r
-\r
- case OUTPUT_PACKET_ID:\r
- QtdHwPtr->PidCode = OUTPUT_PACKET_PID_CODE;\r
- break;\r
-\r
- default:\r
- Status = EFI_INVALID_PARAMETER;\r
- goto exit;\r
- }\r
-\r
- //\r
- // Set Data Buffer Pointers\r
- //\r
- if (NULL != DataPtr) {\r
- SetQtdBufferPointer (\r
- QtdHwPtr,\r
- DataPtr,\r
- DataLen\r
- );\r
- (*QtdPtrPtr)->StaticCurrentOffset = QtdHwPtr->CurrentOffset;\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-CreateSetupQtd (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 *DevReqPtr,\r
- OUT EHCI_QTD_ENTITY **QtdPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtd Structure for Setup\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DevReqPtr - A pointer to Device Request Data\r
- QtdPtrPtr - A pointer of pointer to Qtd for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- return CreateQtd (\r
- HcDev,\r
- DevReqPtr,\r
- sizeof (EFI_USB_DEVICE_REQUEST),\r
- SETUP_PACKET_ID,\r
- DATA0,\r
- QTD_STATUS_ACTIVE,\r
- QtdPtrPtr\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-CreateDataQtd (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 *DataPtr,\r
- IN UINTN DataLen,\r
- IN UINT8 PktId,\r
- IN UINT8 Toggle,\r
- OUT EHCI_QTD_ENTITY **QtdPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtd Structure for data\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DataPtr - A pointer to user data buffer to transfer\r
- DataLen - Length of user data to transfer\r
- PktId - Packet Identification of this Qtd\r
- Toggle - Data Toggle of this Qtd\r
- QtdPtrPtr - A pointer of pointer to Qtd for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- return CreateQtd (\r
- HcDev,\r
- DataPtr,\r
- DataLen,\r
- PktId,\r
- Toggle,\r
- QTD_STATUS_ACTIVE,\r
- QtdPtrPtr\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-CreateAltQtd (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 PktId,\r
- OUT EHCI_QTD_ENTITY **QtdPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtd Structure for Alternative\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- PktId - Packet Identification of this Qtd\r
- QtdPtrPtr - A pointer of pointer to Qtd for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- return CreateQtd (\r
- HcDev,\r
- NULL,\r
- 0,\r
- PktId,\r
- 0,\r
- QTD_STATUS_ACTIVE,\r
- QtdPtrPtr\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-CreateStatusQtd (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 PktId,\r
- OUT EHCI_QTD_ENTITY **QtdPtrPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtd Structure for status\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- PktId - Packet Identification of this Qtd\r
- QtdPtrPtr - A pointer of pointer to Qtd for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- return CreateQtd (\r
- HcDev,\r
- NULL,\r
- 0,\r
- PktId,\r
- DATA1,\r
- QTD_STATUS_ACTIVE,\r
- QtdPtrPtr\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-CreateControlQtds (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 DataPktId,\r
- IN UINT8 *RequestCursor,\r
- IN UINT8 *DataCursor,\r
- IN UINTN DataLen,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT EHCI_QTD_ENTITY **ControlQtdsHead\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtds list for Control Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DataPktId - Packet Identification of Data Qtds\r
- RequestCursor - A pointer to request structure buffer to transfer\r
- DataCursor - A pointer to user data buffer to transfer\r
- DataLen - Length of user data to transfer\r
- ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EHCI_QTD_ENTITY *QtdPtr;\r
- EHCI_QTD_ENTITY *PreQtdPtr;\r
- EHCI_QTD_ENTITY *SetupQtdPtr;\r
- EHCI_QTD_ENTITY *FirstDataQtdPtr;\r
- EHCI_QTD_ENTITY *LastDataQtdPtr;\r
- EHCI_QTD_ENTITY *StatusQtdPtr;\r
- UINT8 DataToggle;\r
- UINT8 StatusPktId;\r
- UINTN CapacityOfQtd;\r
- UINTN SizePerQtd;\r
- UINTN DataCount;\r
-\r
- QtdPtr = NULL;\r
- PreQtdPtr = NULL;\r
- SetupQtdPtr = NULL;\r
- FirstDataQtdPtr = NULL;\r
- LastDataQtdPtr = NULL;\r
- StatusQtdPtr = NULL;\r
- CapacityOfQtd = 0;\r
-\r
- //\r
- // Setup Stage of Control Transfer\r
- //\r
- Status = CreateSetupQtd (\r
- HcDev,\r
- RequestCursor,\r
- &SetupQtdPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- //\r
- // Data Stage of Control Transfer\r
- //\r
- DataToggle = 1;\r
- DataCount = DataLen;\r
-\r
- //\r
- // Create Qtd structure and link together\r
- //\r
- while (DataCount > 0) {\r
- //\r
- // PktSize is the data load size that each Qtd.\r
- //\r
- CapacityOfQtd = GetCapacityOfQtd (DataCursor);\r
- SizePerQtd = DataCount;\r
- if (DataCount > CapacityOfQtd) {\r
- SizePerQtd = CapacityOfQtd;\r
- }\r
-\r
- Status = CreateDataQtd (\r
- HcDev,\r
- DataCursor,\r
- SizePerQtd,\r
- DataPktId,\r
- DataToggle,\r
- &QtdPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- if (NULL == FirstDataQtdPtr) {\r
- goto destory_setup_qtd;\r
- } else {\r
- goto destory_qtds;\r
- }\r
- }\r
-\r
- if (NULL == FirstDataQtdPtr) {\r
- FirstDataQtdPtr = QtdPtr;\r
- } else {\r
- LinkQtdToQtd (PreQtdPtr, QtdPtr);\r
- }\r
-\r
- DataToggle ^= 1;\r
-\r
- PreQtdPtr = QtdPtr;\r
- DataCursor += SizePerQtd;\r
- DataCount -= SizePerQtd;\r
- }\r
-\r
- LastDataQtdPtr = QtdPtr;\r
-\r
- //\r
- // Status Stage of Control Transfer\r
- //\r
- if (OUTPUT_PACKET_ID == DataPktId) {\r
- StatusPktId = INPUT_PACKET_ID;\r
- } else {\r
- StatusPktId = OUTPUT_PACKET_ID;\r
- }\r
-\r
- Status = CreateStatusQtd (\r
- HcDev,\r
- StatusPktId,\r
- &StatusQtdPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto destory_qtds;\r
- }\r
-\r
- //\r
- // Link setup Qtd -> data Qtds -> status Qtd\r
- //\r
- if (FirstDataQtdPtr != NULL) {\r
- LinkQtdToQtd (SetupQtdPtr, FirstDataQtdPtr);\r
- LinkQtdToQtd (LastDataQtdPtr, StatusQtdPtr);\r
- } else {\r
- LinkQtdToQtd (SetupQtdPtr, StatusQtdPtr);\r
- }\r
-\r
- *ControlQtdsHead = SetupQtdPtr;\r
-\r
- goto exit;\r
-\r
-destory_qtds:\r
- DestoryQtds (HcDev, FirstDataQtdPtr);\r
-destory_setup_qtd:\r
- DestoryQtds (HcDev, SetupQtdPtr);\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-CreateBulkOrInterruptQtds (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 PktId,\r
- IN UINT8 *DataCursor,\r
- IN UINTN DataLen,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT EHCI_QTD_ENTITY **QtdsHead\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create Qtds list for Bulk or Interrupt Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- PktId - Packet Identification of Qtds\r
- DataCursor - A pointer to user data buffer to transfer\r
- DataLen - Length of user data to transfer\r
- DataToggle - Data Toggle to start\r
- Translator - Translator Transaction for SplitX\r
- QtdsHead - A pointer of pointer to first Qtd for control tranfer for return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_OUT_OF_RESOURCES Cannot allocate resources\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EHCI_QTD_ENTITY *QtdPtr;\r
- EHCI_QTD_ENTITY *PreQtdPtr;\r
- EHCI_QTD_ENTITY *FirstQtdPtr;\r
- EHCI_QTD_ENTITY *AltQtdPtr;\r
- UINTN DataCount;\r
- UINTN CapacityOfQtd;\r
- UINTN SizePerQtd;\r
-\r
- Status = EFI_SUCCESS;\r
- QtdPtr = NULL;\r
- PreQtdPtr = NULL;\r
- FirstQtdPtr = NULL;\r
- AltQtdPtr = NULL;\r
- CapacityOfQtd = 0;\r
-\r
- DataCount = DataLen;\r
- while (DataCount > 0) {\r
-\r
- CapacityOfQtd = GetCapacityOfQtd (DataCursor);\r
- SizePerQtd = DataCount;\r
- if (DataCount > CapacityOfQtd) {\r
- SizePerQtd = CapacityOfQtd;\r
- }\r
-\r
- Status = CreateDataQtd (\r
- HcDev,\r
- DataCursor,\r
- SizePerQtd,\r
- PktId,\r
- 0,\r
- &QtdPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- if (NULL == FirstQtdPtr) {\r
- goto exit;\r
- } else {\r
- goto destory_qtds;\r
- }\r
- }\r
-\r
- if (NULL == FirstQtdPtr) {\r
- FirstQtdPtr = QtdPtr;\r
- } else {\r
- LinkQtdToQtd (PreQtdPtr, QtdPtr);\r
- }\r
-\r
- PreQtdPtr = QtdPtr;\r
- DataCursor += SizePerQtd;\r
- DataCount -= SizePerQtd;\r
- }\r
-\r
- //\r
- // Set Alternate Qtd\r
- //\r
- if (INPUT_PACKET_ID == PktId && 0 < GetNumberOfQtd (FirstQtdPtr)) {\r
- Status = CreateAltQtd (\r
- HcDev,\r
- PktId,\r
- &AltQtdPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto destory_qtds;\r
- }\r
-\r
- LinkQtdsToAltQtd (FirstQtdPtr, AltQtdPtr);\r
- }\r
-\r
- *QtdsHead = FirstQtdPtr;\r
- goto exit;\r
-\r
-destory_qtds:\r
- DestoryQtds (HcDev, FirstQtdPtr);\r
-exit:\r
- return Status;\r
-}\r
-\r
-VOID\r
-DestoryQtds (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_QTD_ENTITY *FirstQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Destory all Qtds in the list\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- FirstQtdPtr - A pointer to first Qtd in the list\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_QTD_ENTITY *PrevQtd;\r
- EHCI_QTD_ENTITY *NextQtd;\r
-\r
- if (!FirstQtdPtr) {\r
- goto exit;\r
- }\r
-\r
- PrevQtd = FirstQtdPtr;\r
-\r
- //\r
- // Delete all the Qtds.\r
- //\r
- do {\r
- NextQtd = PrevQtd->Next;\r
- EhciFreePool (HcDev, (UINT8 *) PrevQtd, sizeof (EHCI_QTD_ENTITY));\r
- PrevQtd = NextQtd;\r
- } while (NULL != PrevQtd);\r
-\r
-exit:\r
- return ;\r
-}\r
-\r
-UINTN\r
-GetNumberOfQtd (\r
- IN EHCI_QTD_ENTITY *FirstQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Number of Qtds in the list\r
-\r
-Arguments:\r
-\r
- FirstQtdPtr - A pointer to first Qtd in the list\r
-\r
-Returns:\r
-\r
- Number of Qtds in the list\r
-\r
---*/\r
-{\r
- UINTN Count;\r
- EHCI_QTD_ENTITY *QtdPtr;\r
- Count = 0;\r
- QtdPtr = FirstQtdPtr;\r
-\r
- while (NULL != QtdPtr) {\r
- Count++;\r
- QtdPtr = QtdPtr->Next;\r
- }\r
-\r
- return Count;\r
-}\r
-\r
-UINTN\r
-GetCapacityOfQtd (\r
- IN UINT8 *BufferCursor\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get Size of First Qtd\r
-\r
-Arguments:\r
-\r
- BufferCursor - BufferCursor of the Qtd\r
-\r
-Returns:\r
-\r
- Size of First Qtd\r
-\r
---*/\r
-{\r
-\r
- if (EFI_PAGE_MASK & GET_0B_TO_31B (BufferCursor)) {\r
- return EFI_PAGE_SIZE * 4;\r
- } else {\r
- return EFI_PAGE_SIZE * 5;\r
- }\r
-\r
-}\r
-\r
-UINTN\r
-GetApproxiOfInterval (\r
- IN UINTN Interval\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get the approximate value in the 2 index sequence\r
-\r
-Arguments:\r
-\r
- Interval - the value of interval\r
-\r
-Returns:\r
-\r
- approximate value of interval in the 2 index sequence\r
-\r
---*/\r
-{\r
- UINTN Orignate;\r
- UINTN Approxi;\r
-\r
- Orignate = Interval;\r
- Approxi = 1;\r
-\r
- while (Orignate != 1 && Orignate != 0) {\r
- Orignate = Orignate >> 1;\r
- Approxi = Approxi << 1;\r
- }\r
-\r
- if (Interval & (Approxi >> 1)) {\r
- Approxi = Approxi << 1;\r
- }\r
-\r
- return Approxi;\r
-}\r
-\r
-EHCI_QTD_HW *\r
-GetQtdAlternateNextPointer (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get Qtd alternate next pointer field\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- A pointer to hardware alternate Qtd\r
-\r
---*/\r
-{\r
- EHCI_QTD_HW *Value;\r
-\r
- Value = NULL;\r
-\r
- if (!HwQtdPtr->AltNextQtdTerminate) {\r
- Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->AltNextQtdPointer << 5);\r
- }\r
-\r
- return Value;\r
-}\r
-\r
-EHCI_QTD_HW *\r
-GetQtdNextPointer (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get Qtd next pointer field\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- A pointer to next hardware Qtd structure\r
-\r
---*/\r
-{\r
- EHCI_QTD_HW *Value;\r
-\r
- Value = NULL;\r
-\r
- if (!HwQtdPtr->NextQtdTerminate) {\r
- Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->NextQtdPointer << 5);\r
- }\r
-\r
- return Value;\r
-}\r
-\r
-VOID\r
-LinkQtdToQtd (\r
- IN EHCI_QTD_ENTITY * PreQtdPtr,\r
- IN EHCI_QTD_ENTITY * QtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link Qtds together\r
-\r
-Arguments:\r
-\r
- PreQtdPtr - A pointer to pre Qtd\r
- QtdPtr - A pointer to next Qtd\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_QTD_HW *QtdHwPtr;\r
-\r
- ASSERT(PreQtdPtr);\r
- ASSERT(QtdPtr);\r
-\r
- //\r
- // Software link\r
- //\r
- PreQtdPtr->Next = QtdPtr;\r
- QtdPtr->Prev = PreQtdPtr;\r
-\r
- //\r
- // Hardware link\r
- //\r
- QtdHwPtr = &(QtdPtr->Qtd);\r
- PreQtdPtr->Qtd.NextQtdPointer = (UINT32) (GET_0B_TO_31B(QtdHwPtr) >> 5);\r
- PreQtdPtr->Qtd.NextQtdTerminate = FALSE;\r
-\r
- return ;\r
-}\r
-\r\r
-\r
-VOID\r
-LinkQtdsToAltQtd (\r
- IN EHCI_QTD_ENTITY * FirstQtdPtr,\r
- IN EHCI_QTD_ENTITY * AltQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link AlterQtds together\r
-\r
-Arguments:\r
-\r
- FirstQtdPtr - A pointer to first Qtd in the list\r
- AltQtdPtr - A pointer to alternative Qtd\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_QTD_ENTITY *QtdPtr;\r
- EHCI_QTD_HW *AltQtdHwPtr;\r
-\r
- ASSERT(FirstQtdPtr);\r
- ASSERT(AltQtdPtr);\r
-\r
- AltQtdHwPtr = &(AltQtdPtr->Qtd);\r
- QtdPtr = FirstQtdPtr;\r
-\r
- while (NULL != QtdPtr) {\r
- //\r
- // Software link\r
- //\r
- QtdPtr->AltNext = AltQtdPtr;\r
- //\r
- // Hardware link\r
- //\r
- QtdPtr->Qtd.AltNextQtdPointer = (UINT32) (GET_0B_TO_31B(AltQtdHwPtr) >> 5);\r
- QtdPtr->Qtd.AltNextQtdTerminate = FALSE;\r
- QtdPtr = QtdPtr->Next;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-LinkQtdToQh (\r
- IN EHCI_QH_ENTITY *QhPtr,\r
- IN EHCI_QTD_ENTITY *QtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link Qtds list to Qh\r
-\r
-Arguments:\r
-\r
- QhPtr - A pointer to Qh\r
- QtdPtr - A pointer to first Qtd in the list\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_QTD_ENTITY *Cursor;\r
- EHCI_QTD_HW *QtdHwPtr;\r
-\r
- ASSERT (QhPtr);\r
- ASSERT (QtdPtr);\r
-\r
- QhPtr->FirstQtdPtr = QtdPtr;\r
- if (NULL != QtdPtr->AltNext) {\r
- QhPtr->AltQtdPtr = QtdPtr->AltNext;\r
- }\r
-\r
- Cursor = QtdPtr;\r
- while (NULL != Cursor) {\r
- Cursor->SelfQh = QhPtr;\r
- if (NULL == Cursor->Next) {\r
- QhPtr->LastQtdPtr = Cursor;\r
- }\r
-\r
- Cursor = Cursor->Next;\r
- }\r
-\r
- QtdHwPtr = &(QtdPtr->Qtd);\r
- QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (QtdHwPtr) >> 5);\r
- QhPtr->Qh.NextQtdTerminate = FALSE;\r
-\r
- QhPtr->Qh.AltNextQtdPointer = 0;\r
- QhPtr->Qh.AltNextQtdTerminate = TRUE;\r
-\r
-\r
- if ((QtdPtr->Qtd.PidCode == OUTPUT_PACKET_PID_CODE) &&\r
- (QhPtr->TransferType == BULK_TRANSFER)) {\r
- //\r
- //Start PING first\r
- //\r
- QhPtr->Qh.Status |= QTD_STATUS_DO_PING;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-EFI_STATUS\r
-LinkQhToAsyncList (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_QH_ENTITY *QhPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link Qh to Async Schedule List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- QhPtr - A pointer to Qh\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- ASSERT (HcDev);\r
- ASSERT (QhPtr);\r
-\r
-\r
- //\r
- // NULL QH created before\r
- //\r
-\r
- HcDev->NULLQH->Next = QhPtr;\r
- HcDev->NULLQH->Prev = QhPtr;\r
-\r
- QhPtr->Next = HcDev->NULLQH;\r
- QhPtr->Prev = HcDev->NULLQH;\r
-\r
-\r
- HcDev->NULLQH->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(QhPtr->Qh) >> 5));\r
- QhPtr->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(HcDev->NULLQH->Qh) >> 5));\r
-\r
-\r
- Status = SetAsyncListAddr (HcDev, HcDev->NULLQH);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- if (!IsAsyncScheduleEnabled (HcDev)) {\r
-\r
- Status = EnableAsynchronousSchedule (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- Status = WaitForAsyncScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCDebugLevel, "EHCI: WaitForAsyncScheduleEnable TimeOut"));\r
- Status = EFI_TIMEOUT;\r
- goto exit;\r
- }\r
-\r
- if (IsEhcHalted (HcDev)) {\r
- Status = StartScheduleExecution (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-UnlinkQhFromAsyncList (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_QH_ENTITY *QhPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unlink Qh from Async Schedule List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- QhPtr - A pointer to Qh\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- ASSERT (HcDev);\r
- ASSERT (QhPtr);\r
-\r
-\r
- HcDev->NULLQH->Next = HcDev->NULLQH;\r
- HcDev->NULLQH->Prev = HcDev->NULLQH;\r
-\r
-\r
- QhPtr->Next = QhPtr;\r
- QhPtr->Prev = QhPtr;\r
-\r
- HcDev->NULLQH->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(HcDev->NULLQH->Qh) >> 5));\r
-\r
-\r
- SetAndWaitDoorBell (HcDev, 2 * EHCI_GENERIC_TIMEOUT);\r
-\r
- QhPtr->Qh.QhTerminate = 1;\r
- QhPtr->Qh.QhHorizontalPointer = 0;\r
-\r
-\r
- Status = DisableAsynchronousSchedule (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- Status = WaitForAsyncScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: WaitForAsyncScheduleDisable TimeOut\n"));\r
- Status = EFI_TIMEOUT;\r
- goto exit;\r
- }\r
-\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-VOID\r
-LinkQhToPeriodicList (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_QH_ENTITY *QhPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link Qh to Periodic Schedule List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- QhPtr - A pointer to Qh\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- FRAME_LIST_ENTRY *FrameEntryPtr;\r
- EHCI_QH_ENTITY *FindQhPtr;\r
- EHCI_QH_HW *FindQhHwPtr;\r
- UINTN FrameIndex;\r
-\r
- ASSERT (HcDev);\r
- ASSERT (QhPtr);\r
-\r
- FindQhPtr = NULL;\r
- FindQhHwPtr = NULL;\r
- FrameIndex = 0;\r
- FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;\r
-\r
- QhPtr->Qh.HeadReclamationFlag = FALSE;\r
-\r
- if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {\r
-\r
- //\r
- // AsyncInterruptTransfer Qh\r
- //\r
-\r
- //\r
- // Link to Frame[0] List\r
- //\r
- if (!FrameEntryPtr->LinkTerminate) {\r
- //\r
- // Not Null FrameList\r
- //\r
- FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);\r
- FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);\r
- //\r
- // FindQh is Left/Right to Qh\r
- //\r
- while ((NULL != FindQhPtr->Next) && (FindQhPtr->Interval > QhPtr->Interval)) {\r
- FindQhPtr = FindQhPtr->Next;\r
- }\r
-\r
- if (FindQhPtr->Interval == QhPtr->Interval) {\r
- //\r
- // Link Qh after FindQh\r
- //\r
- if (NULL != FindQhPtr->Next) {\r
- FindQhPtr->Next->Prev = QhPtr;\r
- QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Next->Qh) >> 5);\r
- QhPtr->Qh.SelectType = QH_SELECT_TYPE;\r
- QhPtr->Qh.QhTerminate = FALSE;\r
- }\r
-\r
- FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;\r
- FindQhPtr->Qh.QhTerminate = FALSE;\r
-\r
- QhPtr->Prev = FindQhPtr;\r
- QhPtr->Next = FindQhPtr->Next;\r
- FindQhPtr->Next = QhPtr;\r
- } else if (FindQhPtr->Interval < QhPtr->Interval) {\r
- //\r
- // Link Qh before FindQh\r
- //\r
- if (NULL == FindQhPtr->Prev) {\r
- //\r
- // Qh is the First one in Frame[0] List\r
- //\r
- FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FrameEntryPtr->SelectType = QH_SELECT_TYPE;\r
- FrameEntryPtr->LinkTerminate = FALSE;\r
- } else {\r
- //\r
- // Qh is not the First one in Frame[0] List\r
- //\r
- FindQhPtr->Prev->Next = QhPtr;\r
- FindQhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;\r
- FindQhPtr->Prev->Qh.QhTerminate = FALSE;\r
- }\r
-\r
- QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Qh) >> 5);\r
- QhPtr->Qh.SelectType = QH_SELECT_TYPE;\r
- QhPtr->Qh.QhTerminate = FALSE;\r
-\r
- QhPtr->Next = FindQhPtr;\r
- QhPtr->Prev = FindQhPtr->Prev;\r
- FindQhPtr->Prev = QhPtr;\r
- } else {\r
- //\r
- // Link Qh after FindQh, Qh is the Last one\r
- //\r
- FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;\r
- FindQhPtr->Qh.QhTerminate = FALSE;\r
-\r
- QhPtr->Prev = FindQhPtr;\r
- QhPtr->Next = NULL;\r
- FindQhPtr->Next = QhPtr;\r
- }\r
- } else {\r
- //\r
- // Null FrameList\r
- //\r
- FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FrameEntryPtr->SelectType = QH_SELECT_TYPE;\r
- FrameEntryPtr->LinkTerminate = FALSE;\r
- }\r
- //\r
- // Other Frame[X]\r
- //\r
- if (NULL == QhPtr->Prev) {\r
- //\r
- // Qh is the First one in Frame[0] List\r
- //\r
- FrameIndex += QhPtr->Interval;\r
- while (FrameIndex < HcDev->PeriodicFrameListLength) {\r
- FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);\r
- FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FrameEntryPtr->SelectType = QH_SELECT_TYPE;\r
- FrameEntryPtr->LinkTerminate = FALSE;\r
- FrameIndex += QhPtr->Interval;\r
- }\r
- } else if (QhPtr->Interval < QhPtr->Prev->Interval) {\r
- //\r
- // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval\r
- //\r
- FrameIndex += QhPtr->Interval;\r
- while (FrameIndex < HcDev->PeriodicFrameListLength) {\r
- FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);\r
- if ((FrameIndex % QhPtr->Prev->Interval) != 0) {\r
- FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FrameEntryPtr->SelectType = QH_SELECT_TYPE;\r
- FrameEntryPtr->LinkTerminate = FALSE;\r
- }\r
-\r
- FrameIndex += QhPtr->Interval;\r
- }\r
- }\r
- } else {\r
-\r
- //\r
- // SyncInterruptTransfer Qh\r
- //\r
-\r
- if (!FrameEntryPtr->LinkTerminate) {\r
- //\r
- // Not Null FrameList\r
- //\r
- FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);\r
- FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);\r
- //\r
- // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh\r
- //\r
- while (NULL != FindQhPtr->Next) {\r
- FindQhPtr = FindQhPtr->Next;\r
- }\r
-\r
- FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;\r
- FindQhPtr->Qh.QhTerminate = FALSE;\r
-\r
- FindQhPtr->Next = QhPtr;\r
- QhPtr->Prev = FindQhPtr;\r
- } else {\r
- //\r
- // Null FrameList\r
- //\r
- FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);\r
- FrameEntryPtr->SelectType = QH_SELECT_TYPE;\r
- FrameEntryPtr->LinkTerminate = FALSE;\r
- }\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-UnlinkQhFromPeriodicList (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_QH_ENTITY *QhPtr,\r
- IN UINTN Interval\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unlink Qh from Periodic Schedule List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- QhPtr - A pointer to Qh\r
- Interval - Interval of this periodic transfer\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- FRAME_LIST_ENTRY *FrameEntryPtr;\r
- UINTN FrameIndex;\r
-\r
- FrameIndex = 0;\r
-\r
- ASSERT (HcDev);\r
- ASSERT (QhPtr);\r
-\r
- FrameIndex = 0;\r
- FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;\r
-\r
- if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {\r
-\r
- //\r
- // AsyncInterruptTransfer Qh\r
- //\r
-\r
- if (NULL == QhPtr->Prev) {\r
- //\r
- // Qh is the First one on Frame[0] List\r
- //\r
- if (NULL == QhPtr->Next) {\r
- //\r
- // Only one on Frame[0] List\r
- //\r
- while (FrameIndex < HcDev->PeriodicFrameListLength) {\r
- FrameEntryPtr->LinkPointer = 0;\r
- FrameEntryPtr->SelectType = 0;\r
- FrameEntryPtr->LinkTerminate = TRUE;\r
- FrameEntryPtr += Interval;\r
- FrameIndex += Interval;\r
- }\r
- } else {\r
- while (FrameIndex < HcDev->PeriodicFrameListLength) {\r
- FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);\r
- FrameEntryPtr->SelectType = QH_SELECT_TYPE;\r
- FrameEntryPtr->LinkTerminate = FALSE;\r
- FrameEntryPtr += Interval;\r
- FrameIndex += Interval;\r
- }\r
- }\r
- } else {\r
-\r
- //\r
- // Not First one on Frame[0] List\r
- //\r
- if (NULL == QhPtr->Next) {\r
- //\r
- // Qh is the Last one on Frame[0] List\r
- //\r
- QhPtr->Prev->Qh.QhHorizontalPointer = 0;\r
- QhPtr->Prev->Qh.SelectType = 0;\r
- QhPtr->Prev->Qh.QhTerminate = TRUE;\r
- } else {\r
- QhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);\r
- QhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;\r
- QhPtr->Prev->Qh.QhTerminate = FALSE;\r
- }\r
-\r
- if (Interval == QhPtr->Prev->Interval) {\r
- //\r
- // Interval is the same as Prev\r
- // Not involed Frame[X]\r
- //\r
- } else {\r
- //\r
- // Other Frame[X]\r
- //\r
- while (FrameIndex < HcDev->PeriodicFrameListLength) {\r
- if ((FrameIndex % QhPtr->Prev->Interval) != 0) {\r
- FrameEntryPtr->LinkPointer = QhPtr->Prev->Qh.QhHorizontalPointer;\r
- FrameEntryPtr->SelectType = QhPtr->Prev->Qh.SelectType;\r
- FrameEntryPtr->LinkTerminate = QhPtr->Prev->Qh.QhTerminate;\r
- }\r
- FrameEntryPtr += Interval;\r
- FrameIndex += Interval;\r
- }\r
- }\r
- }\r
-\r
- if (NULL != QhPtr->Next) {\r
- QhPtr->Next->Prev = QhPtr->Prev;\r
- }\r
-\r
- if (NULL != QhPtr->Prev) {\r
- QhPtr->Prev->Next = QhPtr->Next;\r
- }\r
- } else {\r
- //\r
- // SyncInterruptTransfer Qh\r
- //\r
- if (NULL == QhPtr->Prev) {\r
- //\r
- // Qh is the only one Qh on Frame[0] List\r
- //\r
- FrameEntryPtr->LinkPointer = 0;\r
- FrameEntryPtr->SelectType = 0;\r
- FrameEntryPtr->LinkTerminate = TRUE;\r
- } else {\r
- QhPtr->Prev->Qh.QhHorizontalPointer = 0;\r
- QhPtr->Prev->Qh.SelectType = 0;\r
- QhPtr->Prev->Qh.QhTerminate = TRUE;\r
- }\r
-\r
- if (NULL != QhPtr->Prev) {\r
- QhPtr->Prev->Next = NULL;\r
- }\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-LinkToAsyncReqeust (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_ASYNC_REQUEST *AsyncRequestPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Llink AsyncRequest Entry to Async Request List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- AsyncRequestPtr - A pointer to Async Request Entry\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_ASYNC_REQUEST *CurrentPtr;\r
-\r
- CurrentPtr = HcDev->AsyncRequestList;\r
- HcDev->AsyncRequestList = AsyncRequestPtr;\r
- AsyncRequestPtr->Prev = NULL;\r
- AsyncRequestPtr->Next = CurrentPtr;\r
-\r
- if (NULL != CurrentPtr) {\r
- CurrentPtr->Prev = AsyncRequestPtr;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-UnlinkFromAsyncReqeust (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EHCI_ASYNC_REQUEST *AsyncRequestPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unlink AsyncRequest Entry from Async Request List\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- AsyncRequestPtr - A pointer to Async Request Entry\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- if (NULL == AsyncRequestPtr->Prev) {\r
- HcDev->AsyncRequestList = AsyncRequestPtr->Next;\r
- if (NULL != AsyncRequestPtr->Next) {\r
- AsyncRequestPtr->Next->Prev = NULL;\r
- }\r
- } else {\r
- AsyncRequestPtr->Prev->Next = AsyncRequestPtr->Next;\r
- if (NULL != AsyncRequestPtr->Next) {\r
- AsyncRequestPtr->Next->Prev = AsyncRequestPtr->Prev;\r
- }\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-SetQtdBufferPointer (\r
- IN EHCI_QTD_HW *QtdHwPtr,\r
- IN VOID *DataPtr,\r
- IN UINTN DataLen\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set data buffer pointers in Qtd\r
-\r
-Arguments:\r
-\r
- QtdHwPtr - A pointer to Qtd hardware structure\r
- DataPtr - A pointer to user data buffer\r
- DataLen - Length of the user data buffer\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- UINTN RemainLen;\r
-\r
- ASSERT (QtdHwPtr);\r
- ASSERT (DataLen <= 5 * EFI_PAGE_SIZE);\r
-\r
- RemainLen = DataLen;\r
- //\r
- // Allow buffer address range across 4G.\r
- // But EFI_USB_MAX_BULK_BUFFER_NUM = 1, so don't allow\r
- // seperate buffer array.\r
- //\r
- //\r
- // Set BufferPointer0, ExtBufferPointer0 and Offset\r
- //\r
- QtdHwPtr->BufferPointer0 = (UINT32) (GET_0B_TO_31B (DataPtr) >> EFI_PAGE_SHIFT);\r
- QtdHwPtr->CurrentOffset = (UINT32) (GET_0B_TO_31B (DataPtr) & EFI_PAGE_MASK);\r
-\r
- //\r
- // Set BufferPointer1 and ExtBufferPointer1\r
- //\r
- RemainLen = RemainLen > (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset) ? (RemainLen - (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset)) : 0;\r
- if (RemainLen == 0) {\r
- goto exit;\r
- }\r
-\r
- QtdHwPtr->BufferPointer1 = QtdHwPtr->BufferPointer0 + 1;\r
-\r
- //\r
- // Set BufferPointer2 and ExtBufferPointer2\r
- //\r
- RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;\r
- if (RemainLen == 0) {\r
- goto exit;\r
- }\r
-\r
- QtdHwPtr->BufferPointer2 = QtdHwPtr->BufferPointer1 + 1;\r
-\r
- //\r
- // Set BufferPointer3 and ExtBufferPointer3\r
- //\r
- RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;\r
- if (RemainLen == 0) {\r
- goto exit;\r
- }\r
-\r
- QtdHwPtr->BufferPointer3 = QtdHwPtr->BufferPointer2 + 1;\r
-\r
- //\r
- // Set BufferPointer4 and ExtBufferPointer4\r
- //\r
- RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;\r
- if (RemainLen == 0) {\r
- goto exit;\r
- }\r
-\r
- QtdHwPtr->BufferPointer4 = QtdHwPtr->BufferPointer3 + 1;\r
-\r
-exit:\r
- return ;\r
-}\r
-\r
-BOOLEAN\r
-IsQtdStatusActive (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Whether Qtd status is active or not\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- TRUE Active\r
- FALSE Inactive\r
-\r
---*/\r
-{\r
- UINT8 QtdStatus;\r
- BOOLEAN Value;\r
-\r
- QtdStatus = (UINT8) (HwQtdPtr->Status);\r
- Value = (BOOLEAN) (QtdStatus & QTD_STATUS_ACTIVE);\r
- //DEBUG ((gEHCErrorLevel, "EHCI: IsQtdStatusActive 0x%X, Address = %x\r\n",HwQtdPtr->Status, HwQtdPtr));\r
-\r
- return Value;\r
-}\r
-\r
-BOOLEAN\r
-IsQtdStatusHalted (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Whether Qtd status is halted or not\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- TRUE Halted\r
- FALSE Not halted\r
-\r
---*/\r
-{\r
- UINT8 QtdStatus;\r
- BOOLEAN Value;\r
-\r
- QtdStatus = (UINT8) (HwQtdPtr->Status);\r
- Value = (BOOLEAN) (QtdStatus & QTD_STATUS_HALTED);\r
-\r
- return Value;\r
-}\r
-\r
-BOOLEAN\r
-IsQtdStatusBufferError (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Whether Qtd status is buffer error or not\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- TRUE Buffer error\r
- FALSE No buffer error\r
-\r
---*/\r
-{\r
- UINT8 QtdStatus;\r
- BOOLEAN Value;\r
-\r
- QtdStatus = (UINT8) (HwQtdPtr->Status);\r
- Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BUFFER_ERR);\r
-\r
- return Value;\r
-}\r
-\r
-BOOLEAN\r
-IsQtdStatusBabbleError (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Whether Qtd status is babble error or not\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- TRUE Babble error\r
- FALSE No babble error\r
-\r
---*/\r
-{\r
- UINT8 QtdStatus;\r
- BOOLEAN Value;\r
-\r
- QtdStatus = (UINT8) (HwQtdPtr->Status);\r
- Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BABBLE_ERR);\r
-\r
- return Value;\r
-}\r
-\r
-BOOLEAN\r
-IsQtdStatusTransactionError (\r
- IN EHCI_QTD_HW *HwQtdPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Whether Qtd status is transaction error or not\r
-\r
-Arguments:\r
-\r
- HwQtdPtr - A pointer to hardware Qtd structure\r
-\r
-Returns:\r
-\r
- TRUE Transaction error\r
- FALSE No transaction error\r
-\r
---*/\r
-{\r
- UINT8 QtdStatus;\r
- BOOLEAN Value;\r
-\r
- QtdStatus = (UINT8) (HwQtdPtr->Status);\r
- Value = (BOOLEAN) (QtdStatus & QTD_STATUS_TRANSACTION_ERR);\r
-\r
- return Value;\r
-}\r
-\r
-BOOLEAN\r
-IsDataInTransfer (\r
- IN UINT8 EndPointAddress\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Whether is a DataIn direction transfer\r
-\r
-Arguments:\r
-\r
- EndPointAddress - address of the endpoint\r
-\r
-Returns:\r
-\r
- TRUE DataIn\r
- FALSE DataOut\r
-\r
---*/\r
-{\r
- BOOLEAN Value;\r
-\r
- if (EndPointAddress & 0x80) {\r
- Value = TRUE;\r
- } else {\r
- Value = FALSE;\r
- }\r
-\r
- return Value;\r
-}\r
-\r
-EFI_STATUS\r
-MapDataBuffer (\r
- IN USB2_HC_DEV *HcDev,\r
- IN EFI_USB_DATA_DIRECTION TransferDirection,\r
- IN VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- OUT UINT8 *PktId,\r
- OUT UINT8 **DataCursor,\r
- OUT VOID **DataMap\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Map address of user data buffer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- TransferDirection - direction of transfer\r
- Data - A pointer to user data buffer\r
- DataLength - length of user data\r
- PktId - Packte Identificaion\r
- DataCursor - mapped address to return\r
- DataMap - identificaion of this mapping to return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_PHYSICAL_ADDRESS TempPhysicalAddr;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- switch (TransferDirection) {\r
-\r
- case EfiUsbDataIn:\r
-\r
- *PktId = INPUT_PACKET_ID;\r
- //\r
- // BusMasterWrite means cpu read\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterWrite,\r
- Data,\r
- DataLength,\r
- &TempPhysicalAddr,\r
- DataMap\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCDebugLevel, "EHCI: MapDataBuffer Failed\n"));\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);\r
- break;\r
-\r
- case EfiUsbDataOut:\r
-\r
- *PktId = OUTPUT_PACKET_ID;\r
- //\r
- // BusMasterRead means cpu write\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterRead,\r
- Data,\r
- DataLength,\r
- &TempPhysicalAddr,\r
- DataMap\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);\r
- break;\r
-\r
- case EfiUsbNoData:\r
-\r
- *PktId = OUTPUT_PACKET_ID;\r
- Data = NULL;\r
- *DataLength = 0;\r
- *DataCursor = NULL;\r
- *DataMap = NULL;\r
- break;\r
-\r
- default:\r
-\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-MapRequestBuffer (\r
- IN USB2_HC_DEV *HcDev,\r
- IN OUT VOID *Request,\r
- OUT UINT8 **RequestCursor,\r
- OUT VOID **RequestMap\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Map address of request structure buffer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- Request - A pointer to request structure\r
- RequestCursor - Mapped address of request structure to return\r
- RequestMap - Identificaion of this mapping to return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN RequestLen;\r
- EFI_PHYSICAL_ADDRESS TempPhysicalAddr;\r
-\r
- RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterRead,\r
- (UINT8 *) Request,\r
- (UINTN *) &RequestLen,\r
- &TempPhysicalAddr,\r
- RequestMap\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- *RequestCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-DeleteAsyncRequestTransfer (\r
- IN USB2_HC_DEV *HcDev,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- OUT UINT8 *DataToggle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Delete all asynchronous request transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- DeviceAddress - address of usb device\r
- EndPointAddress - address of endpoint\r
- DataToggle - stored data toggle\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EHCI_ASYNC_REQUEST *AsyncRequestPtr;\r
- EHCI_ASYNC_REQUEST *MatchPtr;\r
- EHCI_QH_HW *QhHwPtr;\r
- UINT8 EndPointNum;\r
-\r
- if (NULL == HcDev->AsyncRequestList) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto exit;\r
- }\r
-\r
- MatchPtr = NULL;\r
- QhHwPtr = NULL;\r
- EndPointNum = (UINT8) (EndPointAddress & 0x0f);\r
- AsyncRequestPtr = HcDev->AsyncRequestList;\r
-\r
- //\r
- // Find QH of AsyncRequest by DeviceAddress and EndPointNum\r
- //\r
- do {\r
-\r
- QhHwPtr = &(AsyncRequestPtr->QhPtr->Qh);\r
- if (QhHwPtr->DeviceAddr == DeviceAddress && QhHwPtr->EndpointNum == EndPointNum) {\r
- MatchPtr = AsyncRequestPtr;\r
- break;\r
- }\r
-\r
- AsyncRequestPtr = AsyncRequestPtr->Next;\r
-\r
- } while (NULL != AsyncRequestPtr);\r
-\r
- if (NULL == MatchPtr) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto exit;\r
- }\r
-\r
- Status = DisablePeriodicSchedule (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: WaitForPeriodicScheduleDisable TimeOut\n"));\r
- Status = EFI_TIMEOUT;\r
- goto exit;\r
- }\r
-\r
- *DataToggle = (UINT8) MatchPtr->QhPtr->Qh.DataToggle;\r
- UnlinkQhFromPeriodicList (HcDev, MatchPtr->QhPtr, MatchPtr->QhPtr->Interval);\r
- UnlinkFromAsyncReqeust (HcDev, MatchPtr);\r
-\r
- if (NULL == HcDev->AsyncRequestList) {\r
-\r
- Status = StopPollingTimer (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- } else {\r
-\r
- Status = EnablePeriodicSchedule (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
-\r
- Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: WaitForPeriodicScheduleEnable TimeOut\n"));\r
- Status = EFI_TIMEOUT;\r
- goto exit;\r
- }\r
-\r
- if (IsEhcHalted (HcDev)) {\r
- Status = StartScheduleExecution (HcDev);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto exit;\r
- }\r
- }\r
-\r
- }\r
-\r
- DestoryQtds (HcDev, MatchPtr->QhPtr->FirstQtdPtr);\r
- DestoryQh (HcDev, MatchPtr->QhPtr);\r
- EhciFreePool (HcDev, (UINT8 *) MatchPtr, sizeof (EHCI_ASYNC_REQUEST));\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r
-VOID\r
-CleanUpAllAsyncRequestTransfer (\r
- IN USB2_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Clean up all asynchronous request transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_ASYNC_REQUEST *AsyncRequestPtr;\r
- EHCI_ASYNC_REQUEST *FreePtr;\r
-\r
- AsyncRequestPtr = NULL;\r
- FreePtr = NULL;\r
-\r
- StopPollingTimer (HcDev);\r
-\r
- AsyncRequestPtr = HcDev->AsyncRequestList;\r
- while (NULL != AsyncRequestPtr) {\r
-\r
- FreePtr = AsyncRequestPtr;\r
- AsyncRequestPtr = AsyncRequestPtr->Next;\r
- UnlinkFromAsyncReqeust (HcDev, FreePtr);\r
- UnlinkQhFromPeriodicList (HcDev, FreePtr->QhPtr, FreePtr->QhPtr->Interval);\r
- DestoryQtds (HcDev, FreePtr->QhPtr->FirstQtdPtr);\r
- DestoryQh (HcDev, FreePtr->QhPtr);\r
- EhciFreePool (HcDev, (UINT8 *) FreePtr, sizeof (EHCI_ASYNC_REQUEST));\r
-\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-ZeroOutQhOverlay (\r
- IN EHCI_QH_ENTITY *QhPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Zero out the fields in Qh structure\r
-\r
-Arguments:\r
-\r
- QhPtr - A pointer to Qh structure\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- QhPtr->Qh.CurrentQtdPointer = 0;\r
- QhPtr->Qh.AltNextQtdPointer = 0;\r
- QhPtr->Qh.NakCount = 0;\r
- QhPtr->Qh.AltNextQtdTerminate = 0;\r
- QhPtr->Qh.TotalBytes = 0;\r
- QhPtr->Qh.InterruptOnComplete = 0;\r
- QhPtr->Qh.CurrentPage = 0;\r
- QhPtr->Qh.ErrorCount = 0;\r
- QhPtr->Qh.PidCode = 0;\r
- QhPtr->Qh.Status = 0;\r
- QhPtr->Qh.BufferPointer0 = 0;\r
- QhPtr->Qh.CurrentOffset = 0;\r
- QhPtr->Qh.BufferPointer1 = 0;\r
- QhPtr->Qh.CompleteSplitMask = 0;\r
- QhPtr->Qh.BufferPointer2 = 0;\r
- QhPtr->Qh.SplitBytes = 0;\r
- QhPtr->Qh.FrameTag = 0;\r
- QhPtr->Qh.BufferPointer3 = 0;\r
- QhPtr->Qh.BufferPointer4 = 0;\r
-}\r
-\r
-VOID\r
-UpdateAsyncRequestTransfer (\r
- IN EHCI_ASYNC_REQUEST *AsyncRequestPtr,\r
- IN UINT32 TransferResult,\r
- IN UINTN ErrQtdPos\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Update asynchronous request transfer\r
-\r
-Arguments:\r
-\r
- AsyncRequestPtr - A pointer to async request\r
- TransferResult - transfer result\r
- ErrQtdPos - postion of error Qtd\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- EHCI_QTD_ENTITY *QtdPtr;\r
-\r
- QtdPtr = NULL;\r
-\r
- if (EFI_USB_NOERROR == TransferResult) {\r
-\r
- //\r
- // Update Qh for next trigger\r
- //\r
-\r
- QtdPtr = AsyncRequestPtr->QhPtr->FirstQtdPtr;\r
-\r
- //\r
- // Update fields in Qh\r
- //\r
-\r
- //\r
- // Get DataToggle from Overlay in Qh\r
- //\r
- // ZeroOut Overlay in Qh except DataToggle, HostController will update this field\r
- //\r
- ZeroOutQhOverlay (AsyncRequestPtr->QhPtr);\r
- AsyncRequestPtr->QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (&(QtdPtr->Qtd)) >> 5);\r
- AsyncRequestPtr->QhPtr->Qh.NextQtdTerminate = FALSE;\r
-\r
- //\r
- // Update fields in Qtd\r
- //\r
- while (NULL != QtdPtr) {\r
- QtdPtr->Qtd.TotalBytes = QtdPtr->StaticTotalBytes;\r
- QtdPtr->Qtd.CurrentOffset = QtdPtr->StaticCurrentOffset;\r
- QtdPtr->Qtd.CurrentPage = 0;\r
- QtdPtr->Qtd.ErrorCount = QTD_ERROR_COUNTER;\r
- QtdPtr->Qtd.Status = QTD_STATUS_ACTIVE;\r
-\r
- QtdPtr->TotalBytes = QtdPtr->StaticTotalBytes;\r
- QtdPtr = QtdPtr->Next;\r
- }\r
- }\r
-\r
- return ;\r
-}\r
-\r
-BOOLEAN\r
-CheckQtdsTransferResult (\r
- IN BOOLEAN IsControl,\r
- IN EHCI_QH_ENTITY *QhPtr,\r
- OUT UINT32 *Result,\r
- OUT UINTN *ErrQtdPos,\r
- OUT UINTN *ActualLen\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check transfer result of Qtds\r
-\r
-Arguments:\r
-\r
- IsControl - Is control transfer or not\r
- QhPtr - A pointer to Qh\r
- Result - Transfer result\r
- ErrQtdPos - Error TD Position\r
- ActualLen - Actual Transfer Size\r
-\r
-Returns:\r
-\r
- TRUE Qtds finished\r
- FALSE Not finish\r
-\r
---*/\r
-{\r
- UINTN ActualLenPerQtd;\r
- EHCI_QTD_ENTITY *QtdPtr;\r
- EHCI_QTD_HW *QtdHwPtr;\r
- BOOLEAN Value;\r
-\r
- ASSERT (QhPtr);\r
- ASSERT (Result);\r
- ASSERT (ErrQtdPos);\r
- ASSERT (ActualLen);\r
-\r
- Value = TRUE;\r
- QtdPtr = QhPtr->FirstQtdPtr;\r
- QtdHwPtr = &(QtdPtr->Qtd);\r
-\r
- while (NULL != QtdHwPtr) {\r
- if (IsQtdStatusActive (QtdHwPtr)) {\r
- *Result |= EFI_USB_ERR_NOTEXECUTE;\r
- }\r
-\r
- if (IsQtdStatusHalted (QtdHwPtr)) {\r
-\r
- DEBUG ((gEHCErrorLevel, "EHCI: QTD_STATUS_HALTED 0x%X\n", QtdHwPtr->Status));\r
- *Result |= EFI_USB_ERR_STALL;\r
- }\r
-\r
- if (IsQtdStatusBufferError (QtdHwPtr)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: QTD_STATUS_BUFFER_ERR 0x%X\n", QtdHwPtr->Status));\r
- *Result |= EFI_USB_ERR_BUFFER;\r
- }\r
-\r
- if (IsQtdStatusBabbleError (QtdHwPtr)) {\r
- DEBUG ((gEHCErrorLevel, "EHCI: StatusBufferError 0x%X\n", QtdHwPtr->Status));\r
- *Result |= EFI_USB_ERR_BABBLE;\r
- }\r
-\r
- if (IsQtdStatusTransactionError (QtdHwPtr)) {\r
-\r
- //\r
- //Exclude Special Case\r
- //\r
- if (((QtdHwPtr->Status & QTD_STATUS_HALTED) == QTD_STATUS_HALTED) ||\r
- ((QtdHwPtr->Status & QTD_STATUS_ACTIVE) == QTD_STATUS_ACTIVE) ||\r
- ((QtdHwPtr->ErrorCount != QTD_ERROR_COUNTER))) {\r
- *Result |= EFI_USB_ERR_TIMEOUT;\r
- DEBUG ((gEHCErrorLevel, "EHCI: QTD_STATUS_TRANSACTION_ERR: 0x%X\n", QtdHwPtr->Status));\r
- }\r
- }\r
-\r
- ActualLenPerQtd = QtdPtr->TotalBytes - QtdHwPtr->TotalBytes;\r
- QtdPtr->TotalBytes = QtdHwPtr->TotalBytes;\r
- //\r
- // Accumulate actual transferred data length in each DataQtd.\r\r
- //\r
- if (SETUP_PACKET_PID_CODE != QtdHwPtr->PidCode) {\r
- *ActualLen += ActualLenPerQtd;\r
- }\r
-\r
- if (*Result) {\r
- Value = FALSE;\r
- break;\r
- }\r
-\r
- if ((INPUT_PACKET_PID_CODE == QtdHwPtr->PidCode)&& (QtdPtr->TotalBytes > 0)) {\r
- //\r
- // Short Packet: IN, Short\r
- //\r
- DEBUG ((gEHCDebugLevel, "EHCI: Short Packet Status: 0x%x\n", QtdHwPtr->Status));\r
- break;\r
- }\r
-\r
- if (QtdPtr->Next != NULL) {\r
- (*ErrQtdPos)++;\r
- QtdPtr = QtdPtr->Next;\r
- QtdHwPtr = &(QtdPtr->Qtd);\r
- } else {\r
- QtdHwPtr = NULL;\r
- }\r
-\r
- }\r
-\r
- return Value;\r
-}\r
-\r
-EFI_STATUS\r
-ExecuteTransfer (\r
- IN USB2_HC_DEV *HcDev,\r
- IN BOOLEAN IsControl,\r
- IN EHCI_QH_ENTITY *QhPtr,\r
- IN OUT UINTN *ActualLen,\r
- OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Execute Bulk or SyncInterrupt Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB2_HC_DEV\r
- IsControl - Is control transfer or not\r
- QhPtr - A pointer to Qh\r
- ActualLen - Actual transfered Len\r
- DataToggle - Data Toggle\r
- TimeOut - TimeOut threshold\r
- TransferResult - Transfer result\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Sucess\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN ErrQtdPos;\r
- UINTN Delay;\r
- BOOLEAN Finished;\r
-\r
- Status = EFI_SUCCESS;\r
- ErrQtdPos = 0;\r
- *TransferResult = EFI_USB_NOERROR;\r
- *ActualLen = 0;\r
- Finished = FALSE;\r
-\r
- Delay = (TimeOut * STALL_1_MILLI_SECOND / 50);\r
-\r
- do {\r
- *TransferResult = 0;\r
- Finished = CheckQtdsTransferResult (\r
- IsControl,\r
- QhPtr,\r
- TransferResult,\r
- &ErrQtdPos,\r
- ActualLen\r
- );\r
- if (Finished) {\r
- break;\r
- }\r
- //\r
- // Qtd is inactive, which means bulk or interrupt transfer's end.\r
- //\r
- if (!(*TransferResult & EFI_USB_ERR_NOTEXECUTE)) {\r
- break;\r
- }\r
-\r
- gBS->Stall (EHCI_SYNC_REQUEST_POLLING_TIME);\r
-\r
- } while (--Delay);\r
-\r
- if (EFI_USB_NOERROR != *TransferResult) {\r
- if (0 == Delay) {\r
- DEBUG((gEHCErrorLevel, "EHCI: QTDS TimeOut\n"));\r
- Status = EFI_TIMEOUT;\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- //\r
- // Special for Bulk and Interrupt Transfer\r
- //\r
- *DataToggle = (UINT8) QhPtr->Qh.DataToggle;\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-AsyncRequestMoniter (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-/*++\r
-Routine Description:\r
-\r
- Interrupt transfer periodic check handler\r
-\r
-Arguments:\r
- Event - Interrupt event\r
- Context - Pointer to USB2_HC_DEV\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Success\r
- EFI_DEVICE_ERROR Fail\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- USB2_HC_DEV *HcDev;\r
- EHCI_ASYNC_REQUEST *AsyncRequestPtr;\r
- EHCI_ASYNC_REQUEST *NextPtr;\r
- EHCI_QTD_HW *QtdHwPtr;\r
- UINTN ErrQtdPos;\r
- UINTN ActualLen;\r
- UINT32 TransferResult;\r
- UINT8 *ReceiveBuffer;\r
- UINT8 *ProcessBuffer;\r
-\r
- Status = EFI_SUCCESS;\r
- QtdHwPtr = NULL;\r
- ReceiveBuffer = NULL;\r
- ProcessBuffer = NULL;\r
- HcDev = (USB2_HC_DEV *) Context;\r
- AsyncRequestPtr = HcDev->AsyncRequestList;\r
-\r
- while (NULL != AsyncRequestPtr) {\r
-\r
- TransferResult = 0;\r
- ErrQtdPos = 0;\r
- ActualLen = 0;\r
-\r
- CheckQtdsTransferResult (\r
- FALSE,\r
- AsyncRequestPtr->QhPtr,\r
- &TransferResult,\r
- &ErrQtdPos,\r
- &ActualLen\r
- );\r
-\r
- if ((TransferResult & EFI_USB_ERR_NAK) || (TransferResult & EFI_USB_ERR_NOTEXECUTE)) {\r
- AsyncRequestPtr = AsyncRequestPtr->Next;\r
- continue;\r
- }\r
- //\r
- // Allocate memory for EHC private data structure\r
- //\r
- ProcessBuffer = AllocateZeroPool (ActualLen);\r
- if (NULL == ProcessBuffer) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto exit;\r
- }\r
-\r
- QtdHwPtr = &(AsyncRequestPtr->QhPtr->FirstQtdPtr->Qtd);\r
- ReceiveBuffer = (UINT8 *) GET_0B_TO_31B ((QtdHwPtr->BufferPointer0 << EFI_PAGE_SHIFT) | AsyncRequestPtr->QhPtr->FirstQtdPtr->StaticCurrentOffset);\r
- CopyMem (\r
- ProcessBuffer,\r
- ReceiveBuffer,\r
- ActualLen\r
- );\r
-\r
- UpdateAsyncRequestTransfer (AsyncRequestPtr, TransferResult, ErrQtdPos);\r
-\r
- NextPtr = AsyncRequestPtr->Next;\r
-\r
- if (EFI_USB_NOERROR == TransferResult) {\r
-\r
- if (AsyncRequestPtr->CallBackFunc != NULL) {\r
- (AsyncRequestPtr->CallBackFunc) (ProcessBuffer, ActualLen, AsyncRequestPtr->Context, TransferResult);\r
- }\r
-\r
- } else {\r
-\r
- //\r
- // leave error recovery to its related device driver. A common case of\r
- // the error recovery is to re-submit the interrupt transfer.\r
- // When an interrupt transfer is re-submitted, its position in the linked\r
- // list is changed. It is inserted to the head of the linked list, while\r
- // this function scans the whole list from head to tail. Thus, the\r
- // re-submitted interrupt transfer's callback function will not be called\r
- // again in this round.\r
- //\r
- if (AsyncRequestPtr->CallBackFunc != NULL) {\r
- (AsyncRequestPtr->CallBackFunc) (NULL, 0, AsyncRequestPtr->Context, TransferResult);\r
- }\r
-\r
- }\r
-\r
- if (NULL != ProcessBuffer) {\r
- gBS->FreePool (ProcessBuffer);\r
- }\r
-\r
- AsyncRequestPtr = NextPtr;\r
- }\r
-\r
-exit:\r
- return Status;\r
-}\r
-\r