+++ /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
- UhcHlp.c\r
- \r
-Abstract: \r
- \r
-\r
-Revision History\r
---*/\r
-\r
-#include "uhci.h"\r
-\r
-STATIC\r
-EFI_STATUS\r
-USBReadPortW (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 PortOffset,\r
- IN OUT UINT16 *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- USBReadPort Word\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- PortOffset - Port offset\r
- Data - Data to reutrn\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Perform 16bit Read in PCI IO Space\r
- //\r
- return PciIo->Io.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- USB_BAR_INDEX,\r
- (UINT64) PortOffset,\r
- 1,\r
- Data\r
- );\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-USBWritePortW (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 PortOffset,\r
- IN UINT16 Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- USB Write Port Word\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- PortOffset - Port offset\r
- Data - Data to write\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Perform 16bit Write in PCI IO Space\r
- //\r
- return PciIo->Io.Write (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- USB_BAR_INDEX,\r
- (UINT64) PortOffset,\r
- 1,\r
- &Data\r
- );\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-USBWritePortDW (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 PortOffset,\r
- IN UINT32 Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- USB Write Port DWord\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- PortOffset - Port offset\r
- Data - Data to write\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Perform 32bit Write in PCI IO Space\r
- //\r
- return PciIo->Io.Write (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- USB_BAR_INDEX,\r
- (UINT64) PortOffset,\r
- 1,\r
- &Data\r
- );\r
-}\r
-//\r
-// USB register-base helper functions\r
-//\r
-EFI_STATUS\r
-WriteUHCCommandReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 CmdAddrOffset,\r
- IN UINT16 UsbCmd\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Write UHCI Command Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- CmdAddrOffset - Command address offset\r
- UsbCmd - Data to write\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Write to UHC's Command Register\r
- //\r
- return USBWritePortW (PciIo, CmdAddrOffset, UsbCmd);\r
-}\r
-\r
-EFI_STATUS\r
-ReadUHCCommandReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 CmdAddrOffset,\r
- IN OUT UINT16 *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read UHCI Command Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- CmdAddrOffset - Command address offset\r
- Data - Data to return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Read from UHC's Command Register\r
- //\r
- return USBReadPortW (PciIo, CmdAddrOffset, Data);\r
-}\r
-\r
-EFI_STATUS\r
-WriteUHCStatusReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 StatusAddrOffset,\r
- IN UINT16 UsbSts\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Write UHCI Staus Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- StatusAddrOffset - Status address offset\r
- UsbSts - Data to write\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Write to UHC's Status Register\r
- //\r
- return USBWritePortW (PciIo, StatusAddrOffset, UsbSts);\r
-}\r
-\r
-EFI_STATUS\r
-ReadUHCStatusReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 StatusAddrOffset,\r
- IN OUT UINT16 *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read UHCI Staus Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- StatusAddrOffset - Status address offset\r
- UsbSts - Data to return\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Read from UHC's Status Register\r
- //\r
- return USBReadPortW (PciIo, StatusAddrOffset, Data);\r
-}\r
-\r
-\r
-EFI_STATUS\r
-ClearStatusReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 StatusAddrOffset\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Clear the content of UHC's Status Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- StatusAddrOffset - Status address offset\r
- \r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- \r
- return WriteUHCStatusReg (PciIo, StatusAddrOffset, 0x003F);\r
-}\r
-\r
-EFI_STATUS\r
-ReadUHCFrameNumberReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 FrameNumAddrOffset,\r
- IN OUT UINT16 *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read from UHC's Frame Number Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- FrameNumAddrOffset - Frame number register offset\r
- Data - Data to return \r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- \r
- return USBReadPortW (PciIo, FrameNumAddrOffset, Data);\r
-}\r
-\r
-EFI_STATUS\r
-WriteUHCFrameListBaseReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 FlBaseAddrOffset,\r
- IN UINT32 UsbFrameListBaseAddr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Write to UHC's Frame List Base Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- FlBaseAddrOffset - Frame Base address register\r
- UsbFrameListBaseAddr - Address to write\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- \r
- return USBWritePortDW (PciIo, FlBaseAddrOffset, UsbFrameListBaseAddr);\r
-}\r
-\r
-EFI_STATUS\r
-ReadRootPortReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 PortAddrOffset,\r
- IN OUT UINT16 *Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read from UHC's Root Port Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- PortAddrOffset - Port Addrress Offset,\r
- Data - Data to return\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- \r
- return USBReadPortW (PciIo, PortAddrOffset, Data);\r
-}\r
-\r
-EFI_STATUS\r
-WriteRootPortReg (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 PortAddrOffset,\r
- IN UINT16 ControlBits\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Write to UHC's Root Port Register\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- PortAddrOffset - Port Addrress Offset,\r
- ControlBits - Data to write\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- \r
- return USBWritePortW (PciIo, PortAddrOffset, ControlBits);\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-WaitForUHCHalt (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 StatusRegAddr,\r
- IN UINTN Timeout\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Wait until UHCI halt or timeout\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- StatusRegAddr - Status Register Address\r
- Timeout - Time out value in us\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - Unable to read the status register\r
- EFI_TIMEOUT - Time out\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- UINTN Delay;\r
- EFI_STATUS Status;\r
- UINT16 HcStatus;\r
-\r
- //\r
- // Timeout is in us unit\r
- //\r
- Delay = (Timeout / 50) + 1;\r
- do {\r
- Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if ((HcStatus & USBSTS_HCH) == USBSTS_HCH) {\r
- break;\r
- }\r
- //\r
- // Stall for 50 us\r
- //\r
- gBS->Stall (50);\r
-\r
- } while (Delay--);\r
-\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-IsStatusOK (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 StatusRegAddr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Judge whether the host controller operates well\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- StatusRegAddr - Status register address\r
-\r
-Returns:\r
-\r
- TRUE - Status is good\r
- FALSE - Status is bad\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINT16 HcStatus;\r
- //\r
- // Detect whether the interrupt is caused by fatal error.\r
- // see "UHCI Design Guid".\r
- //\r
- Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (HcStatus & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) {\r
- return FALSE;\r
- } else {\r
- return TRUE;\r
- }\r
-\r
-}\r
-\r
-\r
-BOOLEAN \r
-IsHostSysOrProcessErr (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 StatusRegAddr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Judge the status is HostSys,ProcessErr error or good\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- StatusRegAddr - Status register address\r
-\r
-Returns:\r
-\r
- TRUE - Status is good\r
- FALSE - Status is bad\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINT16 HcStatus;\r
- //\r
- // Detect whether the interrupt is caused by serious error.\r
- // see "UHCI Design Guid".\r
- //\r
- Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (HcStatus & (USBSTS_HSE | USBSTS_HCPE)) {\r
- return TRUE;\r
- } else {\r
- return FALSE;\r
- }\r
-}\r
-\r
-\r
-UINT16\r
-GetCurrentFrameNumber (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 FrameNumAddrOffset\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get Current Frame Number\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- FrameNumAddrOffset - FrameNum register AddrOffset\r
-\r
-Returns:\r
-\r
- Frame number \r
-\r
---*/\r
-{\r
- //\r
- // Gets value in the USB frame number register.\r
- //\r
- UINT16 FrameNumber;\r
-\r
- ReadUHCFrameNumberReg (PciIo, FrameNumAddrOffset, &FrameNumber);\r
-\r
- return (UINT16) (FrameNumber & 0x03FF);\r
-}\r
-\r
-EFI_STATUS\r
-SetFrameListBaseAddress (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 FlBaseAddrReg,\r
- IN UINT32 Addr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set FrameListBase Address\r
-\r
-Arguments:\r
-\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- FlBaseAddrReg - FrameListBase register\r
- Addr - Address to set\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- //\r
- // Sets value in the USB Frame List Base Address register.\r
- //\r
- return WriteUHCFrameListBaseReg (PciIo, FlBaseAddrReg, (UINT32) (Addr & 0xFFFFF000));\r
-}\r
-\r
-VOID\r
-EnableMaxPacketSize (\r
- IN USB_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Enable Max Packet Size\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- UINT16 CommandContent;\r
-\r
- ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- (UINT32) (USBCMD),\r
- &CommandContent\r
- );\r
-\r
- if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) {\r
- CommandContent |= USBCMD_MAXP;\r
- WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- (UINT32) (USBCMD),\r
- CommandContent\r
- );\r
- }\r
-\r
- return ;\r
-}\r
-\r
-EFI_STATUS\r
-CreateFrameList (\r
- IN USB_HC_DEV *HcDev,\r
- IN UINT32 FlBaseAddrReg\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- CreateFrameList\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- FlBaseAddrReg - Frame List register\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - Can't allocate memory resources\r
- EFI_UNSUPPORTED - Map memory fail\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- VOID *CommonBuffer;\r
- EFI_PHYSICAL_ADDRESS MappedAddress;\r
- VOID *Mapping;\r
- UINTN BufferSizeInPages;\r
- UINTN BufferSizeInBytes;\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
- BufferSizeInBytes = 4096;\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
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterCommonBuffer,\r
- CommonBuffer,\r
- &BufferSizeInBytes,\r
- &MappedAddress,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) {\r
- HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- HcDev->FrameListEntry = (FRAMELIST_ENTRY *) ((UINTN) MappedAddress);\r
-\r
- HcDev->FrameListMapping = Mapping;\r
-\r
- InitFrameList (HcDev);\r
-\r
- //\r
- // Tell the Host Controller where the Frame List lies,\r
- // by set the Frame List Base Address Register.\r
- //\r
- SetFrameListBaseAddress (\r
- HcDev->PciIo,\r
- FlBaseAddrReg,\r
- (UINT32) ((UINTN) HcDev->FrameListEntry)\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-FreeFrameListEntry (\r
- IN USB_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Free FrameList buffer\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - success\r
-\r
---*/\r
-{\r
- //\r
- // Unmap the common buffer for framelist entry,\r
- // and free the common buffer.\r
- // Uhci's frame list occupy 4k memory.\r
- //\r
- HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->FrameListMapping);\r
- HcDev->PciIo->FreeBuffer (\r
- HcDev->PciIo,\r
- EFI_SIZE_TO_PAGES (4096),\r
- (VOID *) (HcDev->FrameListEntry)\r
- );\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-InitFrameList (\r
- IN USB_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Initialize FrameList\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
-\r
-Returns:\r
- VOID\r
-\r
---*/ \r
-{\r
- FRAMELIST_ENTRY *FrameListPtr;\r
- UINTN Index;\r
-\r
- //\r
- // Validate each Frame List Entry\r
- //\r
- FrameListPtr = HcDev->FrameListEntry;\r
- for (Index = 0; Index < 1024; Index++) {\r
- FrameListPtr->FrameListPtrTerminate = 1;\r
- FrameListPtr->FrameListPtr = 0;\r
- FrameListPtr->FrameListPtrQSelect = 0;\r
- FrameListPtr->FrameListRsvd = 0;\r
- FrameListPtr++;\r
- }\r
-}\r
-//\r
-// //////////////////////////////////////////////////////////////\r
-//\r
-// QH TD related Helper Functions\r
-//\r
-////////////////////////////////////////////////////////////////\r
-//\r
-// functions for QH\r
-//\r
-STATIC\r
-EFI_STATUS\r
-AllocateQHStruct (\r
- IN USB_HC_DEV *HcDev,\r
- OUT QH_STRUCT **ppQHStruct\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Allocate QH Struct\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- ppQHStruct - QH_STRUCT content to return\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- *ppQHStruct = NULL;\r
-\r
- //\r
- // QH must align on 16 bytes alignment,\r
- // since the memory allocated by UhciAllocatePool ()\r
- // is aligned on 32 bytes, it is no need to adjust\r
- // the allocated memory returned.\r
- //\r
- return UhciAllocatePool (HcDev, (UINT8 **) ppQHStruct, sizeof (QH_STRUCT));\r
-}\r
-\r
-\r
-EFI_STATUS\r
-CreateQH (\r
- IN USB_HC_DEV *HcDev,\r
- OUT QH_STRUCT **pptrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- CreateQH\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- ppQHStruct - QH_STRUCT content to return\r
-Returns:\r
-\r
- EFI_SUCCESS - Success\r
- EFI_OUT_OF_RESOURCES - Can't allocate memory\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // allocate align memory for QH_STRUCT\r
- //\r
- Status = AllocateQHStruct (HcDev, pptrQH);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // init each field of the QH_STRUCT\r
- //\r
- //\r
- // Make QH ready\r
- //\r
- SetQHHorizontalValidorInvalid (*pptrQH, FALSE);\r
- SetQHVerticalValidorInvalid (*pptrQH, FALSE);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-SetQHHorizontalLinkPtr (\r
- IN QH_STRUCT *PtrQH,\r
- IN VOID *ptrNext\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set QH Horizontal Link Pointer\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- ptrNext - Data to write \r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Since the QH_STRUCT is aligned on 16-byte boundaries,\r
- // Only the highest 28bit of the address is valid\r
- // (take 32bit address as an example).\r
- //\r
- PtrQH->QH.QHHorizontalPtr = (UINT32) ((UINTN) ptrNext >> 4);\r
-}\r
-\r
-VOID *\r
-GetQHHorizontalLinkPtr (\r
- IN QH_STRUCT *PtrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get QH Horizontal Link Pointer\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- \r
-\r
-Returns:\r
-\r
- Data to return \r
-\r
---*/\r
-{\r
- //\r
- // Restore the 28bit address to 32bit address\r
- // (take 32bit address as an example)\r
- //\r
- return (VOID *) ((UINTN) (PtrQH->QH.QHHorizontalPtr << 4));\r
-}\r
-\r
-VOID\r
-SetQHHorizontalQHorTDSelect (\r
- IN QH_STRUCT *PtrQH,\r
- IN BOOLEAN bQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set QH Horizontal QH or TD \r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- bQH - TRUE is QH FALSE is TD\r
-\r
-Returns:\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // if QH is connected, the specified bit is set,\r
- // if TD is connected, the specified bit is cleared.\r
- //\r
- PtrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0;\r
-}\r
-\r
-\r
-VOID\r
-SetQHHorizontalValidorInvalid (\r
- IN QH_STRUCT *PtrQH,\r
- IN BOOLEAN bValid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set QH Horizontal Valid or Invalid\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- bValid - TRUE is Valid FALSE is Invalid\r
-\r
-Returns:\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Valid means the horizontal link pointer is valid,\r
- // else, it's invalid.\r
- //\r
- PtrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1;\r
-}\r
-\r
-VOID\r
-SetQHVerticalLinkPtr (\r
- IN QH_STRUCT *PtrQH,\r
- IN VOID *ptrNext\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set QH Vertical Link Pointer\r
- \r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- ptrNext - Data to write\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Since the QH_STRUCT is aligned on 16-byte boundaries,\r
- // Only the highest 28bit of the address is valid\r
- // (take 32bit address as an example).\r
- //\r
- PtrQH->QH.QHVerticalPtr = (UINT32) ((UINTN) ptrNext >> 4);\r
-}\r
-\r
-VOID *\r
-GetQHVerticalLinkPtr (\r
- IN QH_STRUCT *PtrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get QH Vertical Link Pointer\r
- \r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- \r
-Returns:\r
-\r
- Data to return\r
-\r
---*/\r
-{\r
- //\r
- // Restore the 28bit address to 32bit address\r
- // (take 32bit address as an example)\r
- //\r
- return (VOID *) ((UINTN) (PtrQH->QH.QHVerticalPtr << 4));\r
-}\r
-\r
-VOID\r
-SetQHVerticalQHorTDSelect (\r
- IN QH_STRUCT *PtrQH,\r
- IN BOOLEAN bQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set QH Vertical QH or TD\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- bQH - TRUE is QH FALSE is TD\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Set the specified bit if the Vertical Link Pointer pointing to a QH,\r
- // Clear the specified bit if the Vertical Link Pointer pointing to a TD.\r
- //\r
- PtrQH->QH.QHVerticalQSelect = bQH ? 1 : 0;\r
-}\r
-\r
-BOOLEAN\r
-IsQHHorizontalQHSelect (\r
- IN QH_STRUCT *PtrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Is QH Horizontal QH Select\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- \r
-Returns:\r
-\r
- TRUE - QH\r
- FALSE - TD\r
-\r
---*/\r
-{\r
- //\r
- // Retrieve the information about whether the Horizontal Link Pointer\r
- // pointing to a QH or TD.\r
- //\r
- return (BOOLEAN) (PtrQH->QH.QHHorizontalQSelect ? TRUE : FALSE);\r
-}\r
-\r
-VOID\r
-SetQHVerticalValidorInvalid (\r
- IN QH_STRUCT *PtrQH,\r
- IN BOOLEAN IsValid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set QH Vertical Valid or Invalid\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- IsValid - TRUE is valid FALSE is invalid\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // If TRUE, indicates the Vertical Link Pointer field is valid,\r
- // else, the field is invalid.\r
- //\r
- PtrQH->QH.QHVerticalTerminate = IsValid ? 0 : 1;\r
-}\r
-\r
-\r
-BOOLEAN\r
-GetQHVerticalValidorInvalid (\r
- IN QH_STRUCT *PtrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get QH Vertical Valid or Invalid\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
-\r
-Returns:\r
-\r
- TRUE - Valid\r
- FALSE - Invalid\r
-\r
---*/\r
-{\r
- //\r
- // If TRUE, indicates the Vertical Link Pointer field is valid,\r
- // else, the field is invalid.\r
- //\r
- return (BOOLEAN) (!(PtrQH->QH.QHVerticalTerminate));\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-GetQHHorizontalValidorInvalid (\r
- IN QH_STRUCT *PtrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get QH Horizontal Valid or Invalid\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
-\r
-Returns:\r
-\r
- TRUE - Valid\r
- FALSE - Invalid\r
-\r
---*/\r
-{\r
- //\r
- // If TRUE, meaning the Horizontal Link Pointer field is valid,\r
- // else, the field is invalid.\r
- //\r
- return (BOOLEAN) (!(PtrQH->QH.QHHorizontalTerminate));\r
-}\r
-//\r
-// functions for TD\r
-//\r
-EFI_STATUS\r
-AllocateTDStruct (\r
- IN USB_HC_DEV *HcDev,\r
- OUT TD_STRUCT **ppTDStruct\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Allocate TD Struct\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- ppTDStruct - place to store TD_STRUCT pointer\r
-Returns:\r
-\r
- EFI_SUCCESS\r
-\r
---*/\r
-{\r
- *ppTDStruct = NULL;\r
-\r
- //\r
- // TD must align on 16 bytes alignment,\r
- // since the memory allocated by UhciAllocatePool ()\r
- // is aligned on 32 bytes, it is no need to adjust\r
- // the allocated memory returned.\r
- //\r
- return UhciAllocatePool (\r
- HcDev,\r
- (UINT8 **) ppTDStruct,\r
- sizeof (TD_STRUCT)\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-CreateTD (\r
- IN USB_HC_DEV *HcDev,\r
- OUT TD_STRUCT **pptrTD\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create TD\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- pptrTD - TD_STRUCT pointer to store\r
-\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - Can't allocate resources\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- //\r
- // create memory for TD_STRUCT, and align the memory.\r
- //\r
- Status = AllocateTDStruct (HcDev, pptrTD);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Make TD ready.\r
- //\r
- SetTDLinkPtrValidorInvalid (*pptrTD, FALSE);\r
-\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GenSetupStageTD (\r
- IN USB_HC_DEV *HcDev,\r
- IN UINT8 DevAddr,\r
- IN UINT8 Endpoint,\r
- IN BOOLEAN bSlow,\r
- IN UINT8 *pDevReq,\r
- IN UINT8 RequestLen,\r
- OUT TD_STRUCT **ppTD\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Generate Setup Stage TD\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- DevAddr - Device address\r
- Endpoint - Endpoint number \r
- bSlow - Full speed or low speed\r
- pDevReq - Device request\r
- RequestLen - Request length\r
- ppTD - TD_STRUCT to return\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - Can't allocate memory\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- TD_STRUCT *pTDStruct;\r
-\r
- Status = CreateTD (HcDev, &pTDStruct);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- SetTDLinkPtr (pTDStruct, NULL);\r
-\r
- //\r
- // Depth first fashion\r
- //\r
- SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE);\r
-\r
- //\r
- // initialize as the last TD in the QH context,\r
- // this field will be updated in the TD linkage process.\r
- //\r
- SetTDLinkPtrValidorInvalid (pTDStruct, FALSE);\r
-\r
- //\r
- // Disable Short Packet Detection by default\r
- //\r
- EnableorDisableTDShortPacket (pTDStruct, FALSE);\r
-\r
- //\r
- // Max error counter is 3, retry 3 times when error encountered.\r
- //\r
- SetTDControlErrorCounter (pTDStruct, 3);\r
-\r
- //\r
- // set device speed attribute\r
- // (TRUE - Slow Device; FALSE - Full Speed Device)\r
- //\r
- SetTDLoworFullSpeedDevice (pTDStruct, bSlow);\r
-\r
- //\r
- // Non isochronous transfer TD\r
- //\r
- SetTDControlIsochronousorNot (pTDStruct, FALSE);\r
-\r
- //\r
- // Interrupt On Complete bit be set to zero,\r
- // Disable IOC interrupt.\r
- //\r
- SetorClearTDControlIOC (pTDStruct, FALSE);\r
-\r
- //\r
- // Set TD Active bit\r
- //\r
- SetTDStatusActiveorInactive (pTDStruct, TRUE);\r
-\r
- SetTDTokenMaxLength (pTDStruct, RequestLen);\r
-\r
- SetTDTokenDataToggle0 (pTDStruct);\r
-\r
- SetTDTokenEndPoint (pTDStruct, Endpoint);\r
-\r
- SetTDTokenDeviceAddress (pTDStruct, DevAddr);\r
-\r
- SetTDTokenPacketID (pTDStruct, SETUP_PACKET_ID);\r
-\r
- pTDStruct->pTDBuffer = (UINT8 *) pDevReq;\r
- pTDStruct->TDBufferLength = RequestLen;\r
- SetTDDataBuffer (pTDStruct);\r
-\r
- *ppTD = pTDStruct;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GenDataTD (\r
- IN USB_HC_DEV *HcDev,\r
- IN UINT8 DevAddr,\r
- IN UINT8 Endpoint,\r
- IN UINT8 *pData,\r
- IN UINT8 Len,\r
- IN UINT8 PktID,\r
- IN UINT8 Toggle,\r
- IN BOOLEAN bSlow,\r
- OUT TD_STRUCT **ppTD\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Generate Data Stage TD\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- DevAddr - Device address\r
- Endpoint - Endpoint number \r
- pData - Data buffer \r
- Len - Data length\r
- PktID - Packet ID\r
- Toggle - Data toggle value\r
- bSlow - Full speed or low speed\r
- ppTD - TD_STRUCT to return\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - Can't allocate memory\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- TD_STRUCT *pTDStruct;\r
- EFI_STATUS Status;\r
-\r
- Status = CreateTD (HcDev, &pTDStruct);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- SetTDLinkPtr (pTDStruct, NULL);\r
-\r
- //\r
- // Depth first fashion\r
- //\r
- SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE);\r
-\r
- //\r
- // Link pointer pointing to TD struct\r
- //\r
- SetTDLinkPtrQHorTDSelect (pTDStruct, FALSE);\r
-\r
- //\r
- // initialize as the last TD in the QH context,\r
- // this field will be updated in the TD linkage process.\r
- //\r
- SetTDLinkPtrValidorInvalid (pTDStruct, FALSE);\r
-\r
- //\r
- // Disable short packet detect\r
- //\r
- EnableorDisableTDShortPacket (pTDStruct, FALSE);\r
- //\r
- // Max error counter is 3\r
- //\r
- SetTDControlErrorCounter (pTDStruct, 3);\r
-\r
- //\r
- // set device speed attribute\r
- // (TRUE - Slow Device; FALSE - Full Speed Device)\r
- //\r
- SetTDLoworFullSpeedDevice (pTDStruct, bSlow);\r
-\r
- //\r
- // Non isochronous transfer TD\r
- //\r
- SetTDControlIsochronousorNot (pTDStruct, FALSE);\r
-\r
- //\r
- // Disable Interrupt On Complete\r
- // Disable IOC interrupt.\r
- //\r
- SetorClearTDControlIOC (pTDStruct, FALSE);\r
-\r
- //\r
- // Set Active bit\r
- //\r
- SetTDStatusActiveorInactive (pTDStruct, TRUE);\r
-\r
- SetTDTokenMaxLength (pTDStruct, Len);\r
-\r
- if (Toggle) {\r
- SetTDTokenDataToggle1 (pTDStruct);\r
- } else {\r
- SetTDTokenDataToggle0 (pTDStruct);\r
- }\r
-\r
- SetTDTokenEndPoint (pTDStruct, Endpoint);\r
-\r
- SetTDTokenDeviceAddress (pTDStruct, DevAddr);\r
-\r
- SetTDTokenPacketID (pTDStruct, PktID);\r
-\r
- pTDStruct->pTDBuffer = (UINT8 *) pData;\r
- pTDStruct->TDBufferLength = Len;\r
- SetTDDataBuffer (pTDStruct);\r
- *ppTD = pTDStruct;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-CreateStatusTD (\r
- IN USB_HC_DEV *HcDev,\r
- IN UINT8 DevAddr,\r
- IN UINT8 Endpoint,\r
- IN UINT8 PktID,\r
- IN BOOLEAN bSlow,\r
- OUT TD_STRUCT **ppTD\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Generate Status Stage TD\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- DevAddr - Device address\r
- Endpoint - Endpoint number \r
- PktID - Packet ID\r
- bSlow - Full speed or low speed\r
- ppTD - TD_STRUCT to return\r
-Returns:\r
-\r
- EFI_OUT_OF_RESOURCES - Can't allocate memory\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- TD_STRUCT *ptrTDStruct;\r
- EFI_STATUS Status;\r
-\r
- Status = CreateTD (HcDev, &ptrTDStruct);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- SetTDLinkPtr (ptrTDStruct, NULL);\r
-\r
- //\r
- // Depth first fashion\r
- //\r
- SetTDLinkPtrDepthorBreadth (ptrTDStruct, TRUE);\r
-\r
- //\r
- // initialize as the last TD in the QH context,\r
- // this field will be updated in the TD linkage process.\r
- //\r
- SetTDLinkPtrValidorInvalid (ptrTDStruct, FALSE);\r
-\r
- //\r
- // Disable short packet detect\r
- //\r
- EnableorDisableTDShortPacket (ptrTDStruct, FALSE);\r
-\r
- //\r
- // Max error counter is 3\r
- //\r
- SetTDControlErrorCounter (ptrTDStruct, 3);\r
-\r
- //\r
- // set device speed attribute\r
- // (TRUE - Slow Device; FALSE - Full Speed Device)\r
- //\r
- SetTDLoworFullSpeedDevice (ptrTDStruct, bSlow);\r
-\r
- //\r
- // Non isochronous transfer TD\r
- //\r
- SetTDControlIsochronousorNot (ptrTDStruct, FALSE);\r
-\r
- //\r
- // Disable Interrupt On Complete\r
- // Disable IOC interrupt.\r
- //\r
- SetorClearTDControlIOC (ptrTDStruct, FALSE);\r
-\r
- //\r
- // Set TD Active bit\r
- //\r
- SetTDStatusActiveorInactive (ptrTDStruct, TRUE);\r
-\r
- SetTDTokenMaxLength (ptrTDStruct, 0);\r
-\r
- SetTDTokenDataToggle1 (ptrTDStruct);\r
-\r
- SetTDTokenEndPoint (ptrTDStruct, Endpoint);\r
-\r
- SetTDTokenDeviceAddress (ptrTDStruct, DevAddr);\r
-\r
- SetTDTokenPacketID (ptrTDStruct, PktID);\r
-\r
- ptrTDStruct->pTDBuffer = NULL;\r
- ptrTDStruct->TDBufferLength = 0;\r
- SetTDDataBuffer (ptrTDStruct);\r
-\r
- *ppTD = ptrTDStruct;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-VOID\r
-SetTDLinkPtrValidorInvalid (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN bValid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set TD Link Pointer Valid or Invalid\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- bValid - TRUE is valid FALSE is invalid\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Valid means the link pointer is valid,\r
- // else, it's invalid.\r
- //\r
- ptrTDStruct->TDData.TDLinkPtrTerminate = (bValid ? 0 : 1);\r
-}\r
-\r
-VOID\r
-SetTDLinkPtrQHorTDSelect (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN bQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set TD Link Pointer QH or TD Select\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- bQH - TRUE is QH FALSE is TD\r
- \r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Indicate whether the Link Pointer pointing to a QH or TD\r
- //\r
- ptrTDStruct->TDData.TDLinkPtrQSelect = (bQH ? 1 : 0);\r
-}\r
-\r
-VOID\r
-SetTDLinkPtrDepthorBreadth (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN bDepth\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set TD Link Pointer depth or bread priority\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- bDepth - TRUE is Depth FALSE is Breadth\r
- \r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // If TRUE, indicating the host controller should process in depth first\r
- // fashion,\r
- // else, the host controller should process in breadth first fashion\r
- //\r
- ptrTDStruct->TDData.TDLinkPtrDepthSelect = (bDepth ? 1 : 0);\r
-}\r
-\r
-VOID\r
-SetTDLinkPtr (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN VOID *ptrNext\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set TD Link Pointer\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- ptrNext - Pointer to set\r
- \r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,\r
- // only the highest 28 bits are valid. (if take 32bit address as an example)\r
- //\r
- ptrTDStruct->TDData.TDLinkPtr = (UINT32) ((UINTN) ptrNext >> 4);\r
-}\r
-\r
-VOID *\r
-GetTDLinkPtr (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get TD Link Pointer\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- \r
-Returns:\r
-\r
- Pointer to get\r
-\r
---*/\r
-{\r
- //\r
- // Get TD Link Pointer. Restore it back to 32bit\r
- // (if take 32bit address as an example)\r
- //\r
- return (VOID *) ((UINTN) (ptrTDStruct->TDData.TDLinkPtr << 4));\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-IsTDLinkPtrQHOrTD (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Is TD Link Pointer is QH Or TD\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TRUE - QH\r
- FALSE - TD \r
-\r
---*/\r
-{\r
- //\r
- // Get the information about whether the Link Pointer field pointing to\r
- // a QH or a TD.\r
- //\r
- return (BOOLEAN) (ptrTDStruct->TDData.TDLinkPtrQSelect);\r
-}\r
-\r
-VOID\r
-EnableorDisableTDShortPacket (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN bEnable\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Enable or Disable TD ShortPacket\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- bEnable - TRUE is Enanble FALSE is Disable\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // TRUE means enable short packet detection mechanism.\r
- //\r
- ptrTDStruct->TDData.TDStatusSPD = (bEnable ? 1 : 0);\r
-}\r
-\r
-VOID\r
-SetTDControlErrorCounter (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN UINT8 nMaxErrors\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set TD Control ErrorCounter\r
-\r
-Arguments:\r
-\r
- ptrTDStruct - TD_STRUCT\r
- nMaxErrors - Error counter number\r
- \r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // valid value of nMaxErrors is 0,1,2,3\r
- //\r
- if (nMaxErrors > 3) {\r
- nMaxErrors = 3;\r
- }\r
-\r
- ptrTDStruct->TDData.TDStatusErr = nMaxErrors;\r
-}\r
-\r
-\r
-VOID\r
-SetTDLoworFullSpeedDevice (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN bLowSpeedDevice\r
- )\r
-{\r
- //\r
- // TRUE means the TD is targeting at a Low-speed device\r
- //\r
- ptrTDStruct->TDData.TDStatusLS = (bLowSpeedDevice ? 1 : 0);\r
-}\r
-\r
-VOID\r
-SetTDControlIsochronousorNot (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN IsIsochronous\r
- )\r
-{\r
- //\r
- // TRUE means the TD belongs to Isochronous transfer type.\r
- //\r
- ptrTDStruct->TDData.TDStatusIOS = (IsIsochronous ? 1 : 0);\r
-}\r
-\r
-VOID\r
-SetorClearTDControlIOC (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN IsSet\r
- )\r
-{\r
- //\r
- // If this bit is set, it indicates that the host controller should issue\r
- // an interrupt on completion of the frame in which this TD is executed.\r
- //\r
- ptrTDStruct->TDData.TDStatusIOC = IsSet ? 1 : 0;\r
-}\r
-\r
-VOID\r
-SetTDStatusActiveorInactive (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN BOOLEAN IsActive\r
- )\r
-{\r
- //\r
- // If this bit is set, it indicates that the TD is active and can be\r
- // executed.\r
- //\r
- if (IsActive) {\r
- ptrTDStruct->TDData.TDStatus |= 0x80;\r
- } else {\r
- ptrTDStruct->TDData.TDStatus &= 0x7F;\r
- }\r
-}\r
-\r
-UINT16\r
-SetTDTokenMaxLength (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN UINT16 MaximumLength\r
- )\r
-{\r
- //\r
- // Specifies the maximum number of data bytes allowed for the transfer.\r
- // the legal value extent is 0 ~ 0x500.\r
- //\r
- if (MaximumLength > 0x500) {\r
- MaximumLength = 0x500;\r
- }\r
- ptrTDStruct->TDData.TDTokenMaxLen = MaximumLength - 1;\r
-\r
- return MaximumLength;\r
-}\r
-\r
-VOID\r
-SetTDTokenDataToggle1 (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Set the data toggle bit to DATA1\r
- //\r
- ptrTDStruct->TDData.TDTokenDataToggle = 1;\r
-}\r
-\r
-VOID\r
-SetTDTokenDataToggle0 (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Set the data toggle bit to DATA0\r
- //\r
- ptrTDStruct->TDData.TDTokenDataToggle = 0;\r
-}\r
-\r
-UINT8\r
-GetTDTokenDataToggle (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Get the data toggle value.\r
- //\r
- return (UINT8) (ptrTDStruct->TDData.TDTokenDataToggle);\r
-}\r
-\r
-VOID\r
-SetTDTokenEndPoint (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN UINTN EndPoint\r
- )\r
-{\r
- //\r
- // Set EndPoint Number the TD is targeting at.\r
- //\r
- ptrTDStruct->TDData.TDTokenEndPt = (UINT8) EndPoint;\r
-}\r
-\r
-VOID\r
-SetTDTokenDeviceAddress (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN UINTN DeviceAddress\r
- )\r
-{\r
- //\r
- // Set Device Address the TD is targeting at.\r
- //\r
- ptrTDStruct->TDData.TDTokenDevAddr = (UINT8) DeviceAddress;\r
-}\r
-\r
-VOID\r
-SetTDTokenPacketID (\r
- IN TD_STRUCT *ptrTDStruct,\r
- IN UINT8 PID\r
- )\r
-{\r
- //\r
- // Set the Packet Identification to be used for this transaction.\r
- //\r
- ptrTDStruct->TDData.TDTokenPID = PID;\r
-}\r
-\r
-VOID\r
-SetTDDataBuffer (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Set the beginning address of the data buffer that will be used\r
- // during the transaction.\r
- //\r
- ptrTDStruct->TDData.TDBufferPtr = (UINT32) ((UINTN) (ptrTDStruct->pTDBuffer));\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusActive (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
-\r
- //\r
- // Detect whether the TD is active.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x80);\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusStalled (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
-\r
- //\r
- // Detect whether the device/endpoint addressed by this TD is stalled.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x40);\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusBufferError (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
- //\r
- // Detect whether Data Buffer Error is happened.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x20);\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusBabbleError (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
-\r
- //\r
- // Detect whether Babble Error is happened.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x10);\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusNAKReceived (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
-\r
- //\r
- // Detect whether NAK is received.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x08);\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusCRCTimeOutError (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
-\r
- //\r
- // Detect whether CRC/Time Out Error is encountered.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x04);\r
-}\r
-\r
-BOOLEAN\r
-IsTDStatusBitStuffError (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- UINT8 TDStatus;\r
-\r
- //\r
- // Detect whether Bitstuff Error is received.\r
- //\r
- TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
- return (BOOLEAN) (TDStatus & 0x02);\r
-}\r
-\r
-UINT16\r
-GetTDStatusActualLength (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the actual number of bytes that were tansferred.\r
- // the value is encoded as n-1. so return the decoded value.\r
- //\r
- return (UINT16) ((ptrTDStruct->TDData.TDStatusActualLength) + 1);\r
-}\r
-\r
-UINT16\r
-GetTDTokenMaxLength (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the maximum number of data bytes allowed for the trnasfer.\r
- //\r
- return (UINT16) ((ptrTDStruct->TDData.TDTokenMaxLen) + 1);\r
-}\r
-\r
-UINT8\r
-GetTDTokenEndPoint (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the endpoint number the transaction is targeting at.\r
- //\r
- return (UINT8) (ptrTDStruct->TDData.TDTokenEndPt);\r
-}\r
-\r
-UINT8\r
-GetTDTokenDeviceAddress (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the device address the transaction is targeting at.\r
- //\r
- return (UINT8) (ptrTDStruct->TDData.TDTokenDevAddr);\r
-}\r
-\r
-UINT8\r
-GetTDTokenPacketID (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the Packet Identification information.\r
- //\r
- return (UINT8) (ptrTDStruct->TDData.TDTokenPID);\r
-}\r
-\r
-UINT8 *\r
-GetTDDataBuffer (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the beginning address of the data buffer\r
- // that involved in this transaction.\r
- //\r
- return ptrTDStruct->pTDBuffer;\r
-}\r
-\r
-BOOLEAN\r
-GetTDLinkPtrValidorInvalid (\r
- IN TD_STRUCT *ptrTDStruct\r
- )\r
-{\r
- //\r
- // Retrieve the information of whether the Link Pointer field\r
- // is valid or not.\r
- //\r
- if (ptrTDStruct->TDData.TDLinkPtrTerminate) {\r
- return FALSE;\r
- } else {\r
- return TRUE;\r
- }\r
-\r
-}\r
-\r
-UINTN\r
-CountTDsNumber (\r
- IN TD_STRUCT *PtrFirstTD\r
- )\r
-{\r
- UINTN Number;\r
- TD_STRUCT *ptr;\r
- //\r
- // Count the queued TDs number.\r
- //\r
- Number = 0;\r
- ptr = PtrFirstTD;\r
- while (ptr) {\r
- ptr = (TD_STRUCT *) ptr->ptrNextTD;\r
- Number++;\r
- }\r
-\r
- return Number;\r
-}\r
-\r
-\r
-\r
-VOID\r
-LinkTDToQH (\r
- IN QH_STRUCT *PtrQH,\r
- IN TD_STRUCT *PtrTD\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link TD To QH\r
-\r
-Arguments:\r
-\r
- PtrQH - QH_STRUCT\r
- PtrTD - TD_STRUCT\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- if (PtrQH == NULL || PtrTD == NULL) {\r
- return ;\r
- }\r
- //\r
- // Validate QH Vertical Ptr field\r
- //\r
- SetQHVerticalValidorInvalid (PtrQH, TRUE);\r
-\r
- //\r
- // Vertical Ptr pointing to TD structure\r
- //\r
- SetQHVerticalQHorTDSelect (PtrQH, FALSE);\r
-\r
- SetQHVerticalLinkPtr (PtrQH, (VOID *) PtrTD);\r
-\r
- PtrQH->ptrDown = (VOID *) PtrTD;\r
-}\r
-\r
-VOID\r
-LinkTDToTD (\r
- IN TD_STRUCT *ptrPreTD,\r
- IN TD_STRUCT *PtrTD\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link TD To TD\r
-\r
-Arguments:\r
-\r
- ptrPreTD - Previous TD_STRUCT to be linked\r
- PtrTD - TD_STRUCT to link\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- if (ptrPreTD == NULL || PtrTD == NULL) {\r
- return ;\r
- }\r
- //\r
- // Depth first fashion\r
- //\r
- SetTDLinkPtrDepthorBreadth (ptrPreTD, TRUE);\r
-\r
- //\r
- // Link pointer pointing to TD struct\r
- //\r
- SetTDLinkPtrQHorTDSelect (ptrPreTD, FALSE);\r
-\r
- //\r
- // Validate the link pointer valid bit\r
- //\r
- SetTDLinkPtrValidorInvalid (ptrPreTD, TRUE);\r
-\r
- SetTDLinkPtr (ptrPreTD, PtrTD);\r
-\r
- ptrPreTD->ptrNextTD = (VOID *) PtrTD;\r
-}\r
-//\r
-// Transfer Schedule related Helper Functions\r
-//\r
-VOID\r
-SetorClearCurFrameListTerminate (\r
- IN FRAMELIST_ENTRY *pCurEntry,\r
- IN BOOLEAN IsSet\r
- )\r
-{\r
- //\r
- // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.\r
- //\r
- pCurEntry->FrameListPtrTerminate = (IsSet ? 1 : 0);\r
-}\r
-\r
-VOID\r
-SetCurFrameListQHorTD (\r
- IN FRAMELIST_ENTRY *pCurEntry,\r
- IN BOOLEAN IsQH\r
- )\r
-{\r
- //\r
- // This bit indicates to the hardware whether the item referenced by the\r
- // link pointer is a TD or a QH.\r
- //\r
- pCurEntry->FrameListPtrQSelect = (IsQH ? 1 : 0);\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-IsCurFrameListQHorTD (\r
- IN FRAMELIST_ENTRY *pCurEntry\r
- )\r
-{\r
- //\r
- // TRUE is QH\r
- // FALSE is TD\r
- //\r
- return (BOOLEAN) (pCurEntry->FrameListPtrQSelect);\r
-}\r
-\r
-BOOLEAN\r
-GetCurFrameListTerminate (\r
- IN FRAMELIST_ENTRY *pCurEntry\r
- )\r
-{\r
- //\r
- // TRUE means the frame is empty,\r
- // FALSE means the link pointer field is valid.\r
- //\r
- return (BOOLEAN) (pCurEntry->FrameListPtrTerminate);\r
-}\r
-\r
-VOID\r
-SetCurFrameListPointer (\r
- IN FRAMELIST_ENTRY *pCurEntry,\r
- IN UINT8 *ptr\r
- )\r
-{\r
- //\r
- // Set the pointer field of the frame.\r
- //\r
- pCurEntry->FrameListPtr = (UINT32) ((UINTN) ptr >> 4);\r
-}\r
-\r
-VOID *\r
-GetCurFrameListPointer (\r
- IN FRAMELIST_ENTRY *pCurEntry\r
- )\r
-{\r
- //\r
- // Get the link pointer of the frame.\r
- //\r
- return (VOID *) ((UINTN) (pCurEntry->FrameListPtr << 4));\r
-\r
-}\r
-\r
-VOID\r
-LinkQHToFrameList (\r
- IN FRAMELIST_ENTRY *pEntry,\r
- IN UINT16 FrameListIndex,\r
- IN QH_STRUCT *PtrQH\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Link QH To Frame List\r
-\r
-Arguments:\r
-\r
- pEntry - FRAMELIST_ENTRY\r
- FrameListIndex - Frame List Index\r
- PtrQH - QH to link \r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- FRAMELIST_ENTRY *pCurFrame;\r
- QH_STRUCT *TempQH;\r
- QH_STRUCT *NextTempQH;\r
- TD_STRUCT *TempTD;\r
- BOOLEAN LINK;\r
-\r
- //\r
- // Get frame list entry that the link process will begin from.\r
- //\r
- pCurFrame = pEntry + FrameListIndex;\r
-\r
- //\r
- // if current frame is empty\r
- // then link the specified QH directly to the Frame List.\r
- //\r
- if (GetCurFrameListTerminate (pCurFrame)) {\r
- \r
- //\r
- // Link new QH to the frame list entry.\r
- //\r
- SetCurFrameListQHorTD (pCurFrame, TRUE);\r
-\r
- SetCurFrameListPointer (pCurFrame, (UINT8 *) PtrQH);\r
-\r
- //\r
- // clear T bit in the Frame List, indicating that the frame list entry\r
- // is no longer empty.\r
- //\r
- SetorClearCurFrameListTerminate (pCurFrame, FALSE);\r
-\r
- return ;\r
-\r
- } else {\r
- //\r
- // current frame list has link pointer\r
- //\r
- if (!IsCurFrameListQHorTD (pCurFrame)) {\r
- //\r
- // a TD is linked to the framelist entry\r
- //\r
- TempTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
-\r
- while (GetTDLinkPtrValidorInvalid (TempTD)) {\r
-\r
- if (IsTDLinkPtrQHOrTD (TempTD)) {\r
- //\r
- // QH linked next to the TD\r
- //\r
- break;\r
- }\r
-\r
- TempTD = (TD_STRUCT *) GetTDLinkPtr (TempTD);\r
- }\r
- \r
- //\r
- // either no ptr linked next to the TD or QH is linked next to the TD\r
- //\r
- if (!GetTDLinkPtrValidorInvalid (TempTD)) {\r
- \r
- //\r
- // no ptr linked next to the TD\r
- //\r
- TempTD->ptrNextQH = PtrQH;\r
- SetTDLinkPtrQHorTDSelect (TempTD, TRUE);\r
- SetTDLinkPtr (TempTD, PtrQH);\r
- SetTDLinkPtrValidorInvalid (TempTD, TRUE);\r
- return ;\r
-\r
- } else {\r
- //\r
- // QH is linked next to the TD\r
- //\r
- TempQH = (QH_STRUCT *) GetTDLinkPtr (TempTD);\r
- }\r
- } else {\r
- //\r
- // a QH is linked to the framelist entry\r
- //\r
- TempQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
- }\r
- \r
- //\r
- // Set up Flag\r
- //\r
- LINK = TRUE;\r
-\r
- //\r
- // Avoid the same qh repeated linking in one frame entry\r
- //\r
- if (TempQH == PtrQH) {\r
- LINK = FALSE;\r
- return ;\r
- }\r
- //\r
- // if current QH has next QH connected\r
- //\r
- while (GetQHHorizontalValidorInvalid (TempQH)) {\r
- //\r
- // Get next QH pointer\r
- //\r
- NextTempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (TempQH);\r
-\r
- //\r
- // Bulk transfer qh may be self-linked,\r
- // so, the code below is to aVOID dead-loop when meeting self-linked qh\r
- //\r
- if (NextTempQH == TempQH) {\r
- LINK = FALSE;\r
- break;\r
- }\r
-\r
- TempQH = NextTempQH;\r
-\r
- //\r
- // Avoid the same qh repeated linking in one frame entry\r
- //\r
- if (TempQH == PtrQH) {\r
- LINK = FALSE;\r
- }\r
- }\r
-\r
- if (LINK) {\r
- TempQH->ptrNext = PtrQH;\r
- SetQHHorizontalQHorTDSelect (TempQH, TRUE);\r
- SetQHHorizontalLinkPtr (TempQH, PtrQH);\r
- SetQHHorizontalValidorInvalid (TempQH, TRUE);\r
- }\r
-\r
- return ;\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-ExecuteControlTransfer (\r
- IN USB_HC_DEV *HcDev,\r
- IN TD_STRUCT *PtrTD,\r
- IN UINT32 wIndex,\r
- OUT UINTN *ActualLen,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Execute Control Transfer\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- PtrTD - TD_STRUCT\r
- wIndex - No use\r
- ActualLen - Actual transfered Len \r
- TimeOut - TimeOut value in milliseconds\r
- TransferResult - Transfer result\r
-Returns:\r
-\r
- EFI_SUCCESS - Sucess\r
- EFI_DEVICE_ERROR - Error\r
- \r
-\r
---*/\r
-{\r
- UINTN ErrTDPos;\r
- UINTN Delay;\r
- UINTN RequiredLen;\r
- BOOLEAN TransferFinished;\r
-\r
- ErrTDPos = 0;\r
- *TransferResult = EFI_USB_NOERROR;\r
- RequiredLen = *ActualLen;\r
- *ActualLen = 0;\r
-\r
- Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;\r
-\r
- do {\r
- TransferFinished = CheckTDsResults (\r
- PtrTD,\r
- RequiredLen,\r
- TransferResult,\r
- &ErrTDPos,\r
- ActualLen\r
- );\r
-\r
- if (TransferFinished) {\r
- break;\r
- }\r
- \r
- //\r
- // TD is inactive, which means the control transfer is end.\r
- //\r
- if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {\r
- break;\r
- } \r
-\r
- gBS->Stall (50);\r
-\r
- } while (Delay--);\r
-\r
- if (*TransferResult != EFI_USB_NOERROR) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-ExecBulkorSyncInterruptTransfer (\r
- IN USB_HC_DEV *HcDev,\r
- IN TD_STRUCT *PtrTD,\r
- IN UINT32 wIndex,\r
- 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 - USB_HC_DEV\r
- PtrTD - TD_STRUCT\r
- wIndex - No use\r
- ActualLen - Actual transfered Len \r
- DataToggle - Data Toggle\r
- TimeOut - TimeOut value in milliseconds\r
- TransferResult - Transfer result\r
-Returns:\r
-\r
- EFI_SUCCESS - Sucess\r
- EFI_DEVICE_ERROR - Error\r
---*/\r
-{\r
- UINTN ErrTDPos;\r
- UINTN ScrollNum;\r
- UINTN Delay;\r
- UINTN RequiredLen;\r
- BOOLEAN TransferFinished;\r
-\r
- ErrTDPos = 0;\r
- *TransferResult = EFI_USB_NOERROR;\r
- RequiredLen = *ActualLen;\r
- *ActualLen = 0;\r
-\r
- Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;\r
-\r
- do {\r
-\r
- TransferFinished = CheckTDsResults (\r
- PtrTD,\r
- RequiredLen,\r
- TransferResult,\r
- &ErrTDPos,\r
- ActualLen\r
- );\r
- \r
- if (TransferFinished) {\r
- break;\r
- }\r
- \r
- //\r
- // TD is inactive, which means bulk or interrupt transfer's end.\r
- // \r
- if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {\r
- break;\r
- }\r
-\r
- gBS->Stall (50);\r
-\r
- } while (Delay--);\r
-\r
- //\r
- // has error\r
- //\r
- if (*TransferResult != EFI_USB_NOERROR) {\r
- \r
- //\r
- // scroll the Data Toggle back to the last success TD\r
- //\r
- ScrollNum = CountTDsNumber (PtrTD) - ErrTDPos;\r
- if (ScrollNum & 0x1) {\r
- *DataToggle ^= 1;\r
- }\r
-\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-DelLinkSingleQH (\r
- IN USB_HC_DEV *HcDev,\r
- IN QH_STRUCT *PtrQH,\r
- IN UINT16 FrameListIndex,\r
- IN BOOLEAN SearchOther,\r
- IN BOOLEAN Delete\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unlink from frame list and delete single QH\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- PtrQH - QH_STRUCT\r
- FrameListIndex - Frame List Index\r
- SearchOther - Search Other QH\r
- Delete - TRUE is to delete the QH\r
-Returns:\r
- VOID\r
---*/\r
-{\r
- FRAMELIST_ENTRY *pCurFrame;\r
- UINTN Index;\r
- UINTN BeginFrame;\r
- UINTN EndFrame;\r
- QH_STRUCT *CurrentQH;\r
- QH_STRUCT *NextQH;\r
- TD_STRUCT *CurrentTD;\r
- VOID *PtrPreQH;\r
- BOOLEAN Found;\r
-\r
- NextQH = NULL;\r
- PtrPreQH = NULL;\r
- Found = FALSE;\r
-\r
- if (PtrQH == NULL) {\r
- return ;\r
- }\r
-\r
- if (SearchOther) {\r
- BeginFrame = 0;\r
- EndFrame = 1024;\r
- } else {\r
- BeginFrame = FrameListIndex;\r
- EndFrame = FrameListIndex + 1;\r
- }\r
-\r
- for (Index = BeginFrame; Index < EndFrame; Index++) {\r
-\r
- pCurFrame = HcDev->FrameListEntry + (Index & 0x3FF);\r
-\r
- if (GetCurFrameListTerminate (pCurFrame)) {\r
- //\r
- // current frame list is empty,search next frame list entry\r
- //\r
- continue;\r
- }\r
-\r
- if (!IsCurFrameListQHorTD (pCurFrame)) {\r
- //\r
- // TD linked to current framelist\r
- //\r
- CurrentTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
-\r
- while (GetTDLinkPtrValidorInvalid (CurrentTD)) {\r
-\r
- if (IsTDLinkPtrQHOrTD (CurrentTD)) {\r
- //\r
- // QH linked next to the TD,break while ()\r
- //\r
- break;\r
- }\r
-\r
- CurrentTD = (TD_STRUCT *) GetTDLinkPtr (CurrentTD);\r
- }\r
-\r
- if (!GetTDLinkPtrValidorInvalid (CurrentTD)) {\r
- //\r
- // no QH linked next to the last TD,\r
- // search next frame list\r
- //\r
- continue;\r
- }\r
- \r
- //\r
- // a QH linked next to the last TD\r
- //\r
- CurrentQH = (QH_STRUCT *) GetTDLinkPtr (CurrentTD);\r
-\r
- PtrPreQH = CurrentTD;\r
-\r
- } else {\r
- //\r
- // a QH linked to current framelist\r
- //\r
- CurrentQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
-\r
- PtrPreQH = NULL;\r
- }\r
-\r
- if (CurrentQH == PtrQH) {\r
-\r
- if (GetQHHorizontalValidorInvalid (PtrQH)) {\r
- //\r
- // there is QH connected after the QH found\r
- //\r
- //\r
- // retrieve nex qh pointer of the qh found.\r
- //\r
- NextQH = GetQHHorizontalLinkPtr (PtrQH);\r
- } else {\r
- NextQH = NULL;\r
- }\r
-\r
- if (PtrPreQH) {\r
- //\r
- // QH linked to a TD struct\r
- //\r
- CurrentTD = (TD_STRUCT *) PtrPreQH;\r
-\r
- SetTDLinkPtrValidorInvalid (CurrentTD, (BOOLEAN) ((NextQH == NULL) ? FALSE : TRUE));\r
- SetTDLinkPtr (CurrentTD, NextQH);\r
- CurrentTD->ptrNextQH = NextQH;\r
-\r
- } else {\r
- //\r
- // QH linked directly to current framelist entry\r
- //\r
- SetorClearCurFrameListTerminate (pCurFrame, (BOOLEAN) ((NextQH == NULL) ? TRUE : FALSE));\r
- SetCurFrameListPointer (pCurFrame, (UINT8 *) NextQH);\r
- }\r
-\r
- Found = TRUE;\r
- //\r
- // search next framelist entry\r
- //\r
- continue;\r
- }\r
-\r
- while (GetQHHorizontalValidorInvalid (CurrentQH)) {\r
-\r
- PtrPreQH = CurrentQH;\r
- //\r
- // Get next horizontal linked QH\r
- //\r
- CurrentQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (CurrentQH);\r
- //\r
- // the qh is found\r
- //\r
- if (CurrentQH == PtrQH) {\r
- break;\r
- }\r
- }\r
- \r
- //\r
- // search next frame list entry\r
- //\r
- if (CurrentQH != PtrQH) {\r
- //\r
- // Not find the QH\r
- //\r
- continue;\r
- }\r
- //\r
- // find the specified qh, then delink it from\r
- // the horizontal QH list in the frame entry.\r
- //\r
- \r
- if (GetQHHorizontalValidorInvalid (PtrQH)) {\r
- //\r
- // there is QH connected after the QH found\r
- //\r
- //\r
- // retrieve nex qh pointer of the qh found.\r
- //\r
- NextQH = GetQHHorizontalLinkPtr (PtrQH);\r
-\r
- } else {\r
- //\r
- // NO QH connected after the QH found\r
- //\r
- NextQH = NULL;\r
- //\r
- // NULL the previous QH's link ptr and set Terminate field.\r
- //\r
- SetQHHorizontalValidorInvalid ((QH_STRUCT *) PtrPreQH, FALSE);\r
- }\r
-\r
- SetQHHorizontalLinkPtr ((QH_STRUCT *) PtrPreQH, NextQH);\r
- ((QH_STRUCT *) PtrPreQH)->ptrNext = NextQH;\r
-\r
- Found = TRUE;\r
- }\r
-\r
- if (Found && Delete) {\r
- //\r
- // free memory once used by the specific QH\r
- //\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- }\r
-\r
- return ;\r
-}\r
-\r
-\r
-VOID\r
-DeleteQueuedTDs (\r
- IN USB_HC_DEV *HcDev,\r
- IN TD_STRUCT *PtrFirstTD\r
- )\r
-/*++\r
-Routine Description:\r
-\r
- Delete Queued TDs\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- PtrFirstTD - TD link list head\r
-\r
-Returns:\r
- VOID\r
-\r
---*/\r
-{\r
- TD_STRUCT *Tptr1;\r
- TD_STRUCT *Tptr2;\r
-\r
- Tptr1 = PtrFirstTD;\r
- //\r
- // Delete all the TDs in a queue.\r
- //\r
- while (Tptr1) {\r
-\r
- Tptr2 = Tptr1;\r
-\r
- if (!GetTDLinkPtrValidorInvalid (Tptr2)) {\r
- Tptr1 = NULL;\r
- } else {\r
-\r
- Tptr1 = GetTDLinkPtr (Tptr2);\r
-\r
- //\r
- // TD link to itself\r
- //\r
- if (Tptr1 == Tptr2) {\r
- Tptr1 = NULL;\r
- }\r
- }\r
-\r
- UhciFreePool (HcDev, (UINT8 *) Tptr2, sizeof (TD_STRUCT));\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-InsertQHTDToINTList (\r
- IN USB_HC_DEV *HcDev,\r
- IN QH_STRUCT *PtrQH,\r
- IN TD_STRUCT *PtrFirstTD,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 DataToggle,\r
- IN UINTN DataLength,\r
- IN UINTN PollingInterval,\r
- IN VOID *Mapping,\r
- IN UINT8 *DataBuffer,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
- IN VOID *Context\r
- )\r
-/*++\r
-Routine Description:\r
- Insert QH and TD To Interrupt List\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- PtrQH - QH_STRUCT\r
- PtrFirstTD - First TD_STRUCT\r
- DeviceAddress - Device Address\r
- EndPointAddress - EndPoint Address\r
- DataToggle - Data Toggle\r
- DataLength - Data length \r
- PollingInterval - Polling Interval when inserted to frame list\r
- Mapping - Mapping alue \r
- DataBuffer - Data buffer\r
- CallBackFunction- CallBackFunction after interrupt transfeer\r
- Context - CallBackFunction Context passed as function parameter\r
-Returns:\r
- EFI_SUCCESS - Sucess\r
- EFI_INVALID_PARAMETER - Paremeter is error \r
-\r
---*/\r
-{\r
- INTERRUPT_LIST *Node;\r
-\r
- Node = AllocatePool (sizeof (INTERRUPT_LIST));\r
- if (Node == NULL) {\r
- return ;\r
- }\r
- \r
- //\r
- // Fill Node field\r
- //\r
- Node->Signature = INTERRUPT_LIST_SIGNATURE;\r
- Node->DevAddr = DeviceAddress;\r
- Node->EndPoint = EndPointAddress;\r
- Node->PtrQH = PtrQH;\r
- Node->PtrFirstTD = PtrFirstTD;\r
- Node->DataToggle = DataToggle;\r
- Node->DataLen = DataLength;\r
- Node->PollInterval = PollingInterval;\r
- Node->Mapping = Mapping;\r
- //\r
- // DataBuffer is allocated host memory, not mapped memory\r
- //\r
- Node->DataBuffer = DataBuffer;\r
- Node->InterruptCallBack = CallBackFunction;\r
- Node->InterruptContext = Context;\r
-\r
- //\r
- // insert the new interrupt transfer to the head of the list.\r
- // The interrupt transfer's monitor function scans the whole list from head\r
- // to tail. The new interrupt transfer MUST be added to the head of the list\r
- // for the sake of error recovery.\r
- //\r
- InsertHeadList (&(HcDev->InterruptListHead), &(Node->Link));\r
-\r
- return ;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-DeleteAsyncINTQHTDs (\r
- IN USB_HC_DEV *HcDev,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- OUT UINT8 *DataToggle\r
- )\r
-/*++\r
-Routine Description:\r
-\r
- Delete Async INT QH and TDs\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- DeviceAddress - Device Address\r
- EndPointAddress - EndPoint Address\r
- DataToggle - Data Toggle\r
-\r
-Returns:\r
- EFI_SUCCESS - Sucess\r
- EFI_INVALID_PARAMETER - Paremeter is error \r
-\r
---*/\r
-{\r
- QH_STRUCT *MatchQH;\r
- QH_STRUCT *ptrNextQH;\r
- TD_STRUCT *MatchTD;\r
- LIST_ENTRY *Link;\r
- INTERRUPT_LIST *MatchList;\r
- INTERRUPT_LIST *PtrList;\r
- BOOLEAN Found;\r
-\r
- UINT32 Result;\r
- UINTN ErrTDPos;\r
- UINTN ActualLen;\r
-\r
- MatchQH = NULL;\r
- MatchTD = NULL;\r
- MatchList = NULL;\r
-\r
- //\r
- // no interrupt transaction exists\r
- //\r
- if (IsListEmpty (&(HcDev->InterruptListHead))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // find the correct QH-TD that need to delete\r
- // (by matching Device address and EndPoint number to match QH-TD )\r
- //\r
- Found = FALSE;\r
- Link = &(HcDev->InterruptListHead);\r
- do {\r
-\r
- Link = Link->ForwardLink;\r
- PtrList = INTERRUPT_LIST_FROM_LINK (Link);\r
-\r
- if ((PtrList->DevAddr == DeviceAddress) && ((PtrList->EndPoint & 0x0f) == (EndPointAddress & 0x0f))) {\r
- MatchList = PtrList;\r
-\r
- Found = TRUE;\r
- break;\r
- }\r
-\r
- } while (Link->ForwardLink != &(HcDev->InterruptListHead));\r
-\r
- if (!Found) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // get current endpoint's data toggle bit and save.\r
- //\r
- ExecuteAsyncINTTDs (HcDev, MatchList, &Result, &ErrTDPos, &ActualLen);\r
- UpdateAsyncINTQHTDs (MatchList, Result, (UINT32) ErrTDPos);\r
- *DataToggle = MatchList->DataToggle;\r
-\r
- MatchTD = MatchList->PtrFirstTD;\r
- MatchQH = MatchList->PtrQH;\r
- //\r
- // find the first matching QH position in the FrameList\r
- //\r
- while (MatchQH) {\r
-\r
- ptrNextQH = MatchQH->ptrNextIntQH;\r
-\r
- //\r
- // Search all the entries\r
- //\r
- DelLinkSingleQH (HcDev, MatchQH, 0, TRUE, TRUE);\r
-\r
- MatchQH = ptrNextQH;\r
- }\r
- \r
- //\r
- // Call PciIo->Unmap() to unmap the busmaster read/write\r
- //\r
- HcDev->PciIo->Unmap (HcDev->PciIo, MatchList->Mapping);\r
-\r
- //\r
- // free host data buffer allocated,\r
- // mapped data buffer is freed by Unmap\r
- //\r
- if (MatchList->DataBuffer != NULL) {\r
- gBS->FreePool (MatchList->DataBuffer);\r
- }\r
- \r
- //\r
- // at last delete the TDs, to aVOID problems\r
- //\r
- DeleteQueuedTDs (HcDev, MatchTD);\r
-\r
- //\r
- // remove Match node from interrupt list\r
- //\r
- RemoveEntryList (&(MatchList->Link));\r
- gBS->FreePool (MatchList);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-CheckTDsResults (\r
- IN TD_STRUCT *PtrTD,\r
- IN UINTN RequiredLen,\r
- OUT UINT32 *Result,\r
- OUT UINTN *ErrTDPos,\r
- OUT UINTN *ActualTransferSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check TDs Results\r
-\r
-Arguments:\r
-\r
- PtrTD - TD_STRUCT to check\r
- RequiredLen - Required Len\r
- Result - Transfer result\r
- ErrTDPos - Error TD Position\r
- ActualTransferSize - Actual Transfer Size\r
-\r
-Returns:\r
-\r
- TRUE - Sucess\r
- FALSE - Fail\r
-\r
---*/\r
-{\r
- UINTN Len;\r
-\r
- *Result = EFI_USB_NOERROR;\r
- *ErrTDPos = 0;\r
-\r
- //\r
- // Init to zero.\r
- //\r
- *ActualTransferSize = 0;\r
-\r
- while (PtrTD) {\r
-\r
- if (IsTDStatusActive (PtrTD)) {\r
- *Result |= EFI_USB_ERR_NOTEXECUTE;\r
- }\r
-\r
- if (IsTDStatusStalled (PtrTD)) {\r
- *Result |= EFI_USB_ERR_STALL;\r
- }\r
-\r
- if (IsTDStatusBufferError (PtrTD)) {\r
- *Result |= EFI_USB_ERR_BUFFER;\r
- }\r
-\r
- if (IsTDStatusBabbleError (PtrTD)) {\r
- *Result |= EFI_USB_ERR_BABBLE;\r
- }\r
-\r
- if (IsTDStatusNAKReceived (PtrTD)) {\r
- *Result |= EFI_USB_ERR_NAK;\r
- }\r
-\r
- if (IsTDStatusCRCTimeOutError (PtrTD)) {\r
- *Result |= EFI_USB_ERR_TIMEOUT;\r
- }\r
-\r
- if (IsTDStatusBitStuffError (PtrTD)) {\r
- *Result |= EFI_USB_ERR_BITSTUFF;\r
- }\r
- \r
- //\r
- // if any error encountered, stop processing the left TDs.\r
- //\r
- if (*Result) {\r
- return FALSE;\r
- }\r
-\r
- Len = GetTDStatusActualLength (PtrTD) & 0x7FF;\r
- *ActualTransferSize += Len;\r
-\r
- if (*ActualTransferSize <= RequiredLen && Len < PtrTD->TDData.TDTokenMaxLen) {\r
- //\r
- // transter finished and actural length less than required length\r
- //\r
- goto Done;\r
- }\r
- //\r
- // Accumulate actual transferred data length in each TD.\r
- //\r
- PtrTD = (TD_STRUCT *) (PtrTD->ptrNextTD);\r
- //\r
- // Record the first Error TD's position in the queue,\r
- // this value is zero-based.\r
- //\r
- (*ErrTDPos)++;\r
- }\r
-\r
-Done:\r
- return TRUE;\r
-}\r
-\r
-\r
-VOID\r
-ExecuteAsyncINTTDs (\r
- IN USB_HC_DEV *HcDev,\r
- IN INTERRUPT_LIST *PtrList,\r
- OUT UINT32 *Result,\r
- OUT UINTN *ErrTDPos,\r
- OUT UINTN *ActualLen\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Execute Async Interrupt TDs\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- PtrList - INTERRUPT_LIST\r
- Result - Transfer result\r
- ErrTDPos - Error TD Position\r
- ActualTransferSize - Actual Transfer Size\r
- \r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- //\r
- // *ErrTDPos is zero-based value, indicating the first error TD's position\r
- // in the TDs' sequence.\r
- // *ErrTDPos value is only valid when *Result is not equal NOERROR.\r
- //\r
- UINTN RequiredLen;\r
-\r
- RequiredLen = *ActualLen;\r
- CheckTDsResults (PtrList->PtrFirstTD, RequiredLen, Result, ErrTDPos, ActualLen);\r
-\r
- return ;\r
-}\r
-\r
-\r
-VOID\r
-UpdateAsyncINTQHTDs (\r
- IN INTERRUPT_LIST *PtrList,\r
- IN UINT32 Result,\r
- IN UINT32 ErrTDPos\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Update Async Interrupt QH and TDs\r
-\r
-Arguments:\r
-\r
- PtrList - INTERRUPT_LIST\r
- Result - Transfer reslut\r
- ErrTDPos - Error TD Position\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- QH_STRUCT *PtrFirstQH;\r
- QH_STRUCT *PtrQH;\r
- TD_STRUCT *PtrFirstTD;\r
- TD_STRUCT *PtrTD;\r
- UINT8 DataToggle;\r
- UINT32 Index;\r
-\r
- PtrFirstQH = PtrList->PtrQH;\r
- PtrFirstTD = PtrList->PtrFirstTD;\r
-\r
- DataToggle = 0;\r
-\r
- if (Result == EFI_USB_NOERROR) {\r
-\r
- PtrTD = PtrFirstTD;\r
- while (PtrTD) {\r
- DataToggle = GetTDTokenDataToggle (PtrTD);\r
- PtrTD = PtrTD->ptrNextTD;\r
- }\r
- \r
- //\r
- // save current DataToggle value to interrupt list.\r
- // this value is used for tracing the interrupt endpoint DataToggle.\r
- // when this interrupt transfer is deleted, the last DataToggle is saved\r
- //\r
- PtrList->DataToggle = DataToggle;\r
-\r
- PtrTD = PtrFirstTD;\r
-\r
- //\r
- // Since DataToggle bit should toggle after each success transaction,\r
- // the First TD's DataToggle bit will be updated to XOR of Last TD's\r
- // DataToggle bit. If the First TD's DataToggle bit is not equal Last\r
- // TD's DataToggle bit, that means it already be the XOR of Last TD's,\r
- // so no update is needed.\r
- //\r
- if (DataToggle == GetTDTokenDataToggle (PtrFirstTD)) {\r
- PtrTD = PtrFirstTD;\r
- while (PtrTD) {\r
-\r
- DataToggle ^= 1;\r
- if (DataToggle) {\r
- SetTDTokenDataToggle1 (PtrTD);\r
- } else {\r
- SetTDTokenDataToggle0 (PtrTD);\r
- }\r
-\r
- PtrTD = PtrTD->ptrNextTD;\r
- }\r
- }\r
- //\r
- // restore Link Pointer of QH to First TD\r
- // (because QH's Link Pointer will change during TD execution)\r
- //\r
- PtrQH = PtrFirstQH;\r
- while (PtrQH) {\r
-\r
- LinkTDToQH (PtrQH, PtrFirstTD);\r
- PtrQH = PtrQH->ptrNextIntQH;\r
- }\r
- \r
- //\r
- // set all the TDs active\r
- //\r
- PtrTD = PtrFirstTD;\r
- while (PtrTD) {\r
- SetTDStatusActiveorInactive (PtrTD, TRUE);\r
- PtrTD = PtrTD->ptrNextTD;\r
- }\r
-\r
- } else if (((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE) ||\r
- ((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK)\r
- ) {\r
- //\r
- // no update\r
- //\r
- } else {\r
- //\r
- // Have Errors\r
- //\r
- PtrTD = PtrFirstTD;\r
- //\r
- // not first TD error\r
- //\r
- if (ErrTDPos != 0) {\r
- //\r
- // get the last success TD\r
- //\r
- for (Index = 1; Index < ErrTDPos; Index++) {\r
- PtrTD = PtrTD->ptrNextTD;\r
- }\r
- //\r
- // update Data Toggle in the interrupt list node\r
- //\r
- PtrList->DataToggle = GetTDTokenDataToggle (PtrTD);\r
-\r
- //\r
- // get the error TD\r
- //\r
- PtrTD = PtrTD->ptrNextTD;\r
-\r
- } else {\r
- PtrList->DataToggle = GetTDTokenDataToggle (PtrTD);\r
- }\r
- //\r
- // do not restore the QH's vertical link pointer,\r
- // let the callback function do the rest of error handling.\r
- //\r
- }\r
-\r
- return ;\r
-}\r
-\r
-VOID\r
-ReleaseInterruptList (\r
- IN USB_HC_DEV *HcDev,\r
- IN LIST_ENTRY *ListHead\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Release Interrupt List\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- ListHead - List head\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *SavedLink;\r
- INTERRUPT_LIST *pNode;\r
- TD_STRUCT *PtrTD;\r
- TD_STRUCT *ptrNextTD;\r
- QH_STRUCT *PtrQH;\r
- QH_STRUCT *SavedQH;\r
-\r
- if (ListHead == NULL) {\r
- return ;\r
- }\r
-\r
- Link = ListHead;\r
-\r
- //\r
- // Free all the resources in the interrupt list\r
- //\r
- SavedLink = Link->ForwardLink;\r
- while (!IsListEmpty (ListHead)) {\r
-\r
- Link = SavedLink;\r
-\r
- SavedLink = Link->ForwardLink;\r
-\r
- pNode = INTERRUPT_LIST_FROM_LINK (Link);\r
-\r
- RemoveEntryList (&pNode->Link);\r
-\r
- SavedQH = pNode->PtrQH;\r
- for (PtrQH = SavedQH; PtrQH != NULL; PtrQH = SavedQH) {\r
- SavedQH = PtrQH->ptrNextIntQH;\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- }\r
-\r
- PtrTD = pNode->PtrFirstTD;\r
- while (PtrTD != NULL) {\r
-\r
- ptrNextTD = PtrTD->ptrNextTD;\r
- UhciFreePool (HcDev, (UINT8 *) PtrTD, sizeof (TD_STRUCT));\r
- PtrTD = ptrNextTD;\r
- }\r
-\r
- gBS->FreePool (pNode);\r
- }\r
-}\r
-\r
-\r
-EFI_STATUS\r
-InitializeMemoryManagement (\r
- IN USB_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Initialize Memory Management\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- MEMORY_MANAGE_HEADER *MemoryHeader;\r
- EFI_STATUS Status;\r
- UINTN MemPages;\r
-\r
- MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
- Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- HcDev->MemoryHeader = MemoryHeader;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-CreateMemoryBlock (\r
- IN USB_HC_DEV *HcDev,\r
- OUT MEMORY_MANAGE_HEADER **MemoryHeader,\r
- IN UINTN MemoryBlockSizeInPages\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Use PciIo->AllocateBuffer to allocate common buffer for the memory block,\r
- and use PciIo->Map to map the common buffer for Bus Master Read/Write.\r
-\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- MemoryHeader - MEMORY_MANAGE_HEADER to output\r
- MemoryBlockSizeInPages - MemoryBlockSizeInPages\r
-Returns:\r
-\r
- EFI_SUCCESS - Success\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- VOID *CommonBuffer;\r
- EFI_PHYSICAL_ADDRESS MappedAddress;\r
- UINTN MemoryBlockSizeInBytes;\r
- VOID *Mapping;\r
-\r
- //\r
- // Allocate memory for MemoryHeader\r
- //\r
- *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));\r
- if (*MemoryHeader == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- (*MemoryHeader)->Next = NULL;\r
-\r
- //\r
- // set Memory block size\r
- //\r
- (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
-\r
- //\r
- // each bit in Bit Array will manage 32 bytes memory in memory block\r
- //\r
- (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8;\r
-\r
- //\r
- // Allocate memory for BitArray\r
- //\r
- (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);\r
- if ((*MemoryHeader)->BitArrayPtr == NULL) {\r
- gBS->FreePool (*MemoryHeader);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- \r
- //\r
- // Memory Block uses MemoryBlockSizeInPages pages,\r
- // and it is allocated as common buffer use.\r
- //\r
- Status = HcDev->PciIo->AllocateBuffer (\r
- HcDev->PciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- MemoryBlockSizeInPages,\r
- &CommonBuffer,\r
- 0\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
- gBS->FreePool (*MemoryHeader);\r
- return Status;\r
- }\r
-\r
- MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterCommonBuffer,\r
- CommonBuffer,\r
- &MemoryBlockSizeInBytes,\r
- &MappedAddress,\r
- &Mapping\r
- );\r
- //\r
- // if returned Mapped size is less than the size we request,do not support.\r
- //\r
- if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {\r
- HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);\r
- gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
- gBS->FreePool (*MemoryHeader);\r
- return EFI_UNSUPPORTED;\r
- }\r
- //\r
- // Set Memory block initial address\r
- //\r
- (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);\r
- (*MemoryHeader)->Mapping = Mapping;\r
-\r
- ZeroMem (\r
- (*MemoryHeader)->MemoryBlockPtr,\r
- EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-FreeMemoryHeader (\r
- IN USB_HC_DEV *HcDev,\r
- IN MEMORY_MANAGE_HEADER *MemoryHeader\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Free Memory Header\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- MemoryHeader - MemoryHeader to be freed\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - Parameter is error\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- if ((MemoryHeader == NULL) || (HcDev == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // unmap the common buffer used by the memory block\r
- //\r
- HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);\r
-\r
- //\r
- // free common buffer\r
- //\r
- HcDev->PciIo->FreeBuffer (\r
- HcDev->PciIo,\r
- EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),\r
- MemoryHeader->MemoryBlockPtr\r
- );\r
- //\r
- // free bit array\r
- //\r
- gBS->FreePool (MemoryHeader->BitArrayPtr);\r
- //\r
- // free memory header\r
- //\r
- gBS->FreePool (MemoryHeader);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-UhciAllocatePool (\r
- IN USB_HC_DEV *HcDev,\r
- OUT UINT8 **Pool,\r
- IN UINTN AllocSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Uhci Allocate Pool\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- Pool - Place to store pointer to the memory buffer\r
- AllocSize - Alloc Size\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- MEMORY_MANAGE_HEADER *MemoryHeader;\r
- MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
- MEMORY_MANAGE_HEADER *NewMemoryHeader;\r
- UINTN RealAllocSize;\r
- UINTN MemoryBlockSizeInPages;\r
- EFI_STATUS Status;\r
-\r
- *Pool = NULL;\r
-\r
- MemoryHeader = HcDev->MemoryHeader;\r
- ASSERT (MemoryHeader != NULL);\r
-\r
- //\r
- // allocate unit is 32 bytes (align on 32 byte)\r
- //\r
- if (AllocSize & 0x1F) {\r
- RealAllocSize = (AllocSize / 32 + 1) * 32;\r
- } else {\r
- RealAllocSize = AllocSize;\r
- }\r
- \r
- //\r
- // There may be linked MemoryHeaders.\r
- // To allocate a free pool in Memory blocks,\r
- // must search in the MemoryHeader link list\r
- // until enough free pool is found.\r
- //\r
- Status = EFI_NOT_FOUND;\r
- for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;\r
- TempHeaderPtr = TempHeaderPtr->Next) {\r
-\r
- Status = AllocMemInMemoryBlock (\r
- TempHeaderPtr,\r
- (VOID **) Pool,\r
- RealAllocSize / 32\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- ZeroMem (*Pool, AllocSize);\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- \r
- //\r
- // There is no enough memory,\r
- // Create a new Memory Block\r
- //\r
- \r
- //\r
- // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,\r
- // just allocate a large enough memory block.\r
- //\r
- if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {\r
- MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;\r
- } else {\r
- MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
- }\r
-\r
- Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- \r
- //\r
- // Link the new Memory Block to the Memory Header list\r
- //\r
- InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);\r
-\r
- Status = AllocMemInMemoryBlock (\r
- NewMemoryHeader,\r
- (VOID **) Pool,\r
- RealAllocSize / 32\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- ZeroMem (*Pool, AllocSize);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-VOID\r
-UhciFreePool (\r
- IN USB_HC_DEV *HcDev,\r
- IN UINT8 *Pool,\r
- IN UINTN AllocSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Uhci Free Pool\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
- Pool - Pool to free\r
- AllocSize - Pool size\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- MEMORY_MANAGE_HEADER *MemoryHeader;\r
- MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
- UINTN StartBytePos;\r
- UINTN Index;\r
- UINT8 StartBitPos;\r
- UINT8 Index2;\r
- UINTN Count;\r
- UINTN RealAllocSize;\r
-\r
- MemoryHeader = HcDev->MemoryHeader;\r
-\r
- //\r
- // allocate unit is 32 byte (align on 32 byte)\r
- //\r
- if (AllocSize & 0x1F) {\r
- RealAllocSize = (AllocSize / 32 + 1) * 32;\r
- } else {\r
- RealAllocSize = AllocSize;\r
- }\r
- //\r
- // scan the memory header linked list for\r
- // the asigned memory to free.\r
- //\r
- for (TempHeaderPtr = MemoryHeader;TempHeaderPtr != NULL;\r
- TempHeaderPtr = TempHeaderPtr->Next) {\r
-\r
- if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&\r
- ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))\r
- ) {\r
- //\r
- // Pool is in the Memory Block area,\r
- // find the start byte and bit in the bit array\r
- //\r
- StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8;\r
- StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7);\r
-\r
- //\r
- // reset associated bits in bit arry\r
- //\r
- for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {\r
-\r
- TempHeaderPtr->BitArrayPtr[Index] = (UINT8) (TempHeaderPtr->BitArrayPtr[Index] ^ bit (Index2));\r
- Index2++;\r
- if (Index2 == 8) {\r
- Index += 1;\r
- Index2 = 0;\r
- }\r
- }\r
- //\r
- // break the loop\r
- //\r
- break;\r
- }\r
- }\r
- \r
- //\r
- // Release emptied memory blocks (only if the memory block is not\r
- // the first one in the memory header list\r
- //\r
- for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
- //\r
- // Debug\r
- //\r
- ASSERT (MemoryHeader->Next != NULL);\r
-\r
- if (IsMemoryBlockEmptied (TempHeaderPtr)) {\r
-\r
- DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);\r
- //\r
- // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
- // the TempHeaderPtr is pointing to nonsense content.\r
- //\r
- FreeMemoryHeader (HcDev, TempHeaderPtr);\r
- //\r
- // reset the TempHeaderPtr, continue search for\r
- // another empty memory block.\r
- //\r
- TempHeaderPtr = MemoryHeader->Next;\r
- continue;\r
- }\r
-\r
- TempHeaderPtr = TempHeaderPtr->Next;\r
- }\r
-}\r
-\r
-VOID\r
-InsertMemoryHeaderToList (\r
- IN MEMORY_MANAGE_HEADER *MemoryHeader,\r
- IN MEMORY_MANAGE_HEADER *NewMemoryHeader\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Insert Memory Header To List\r
-\r
-Arguments:\r
-\r
- MemoryHeader - MEMORY_MANAGE_HEADER\r
- NewMemoryHeader - MEMORY_MANAGE_HEADER\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
-\r
- for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;\r
- TempHeaderPtr = TempHeaderPtr->Next) {\r
- if (TempHeaderPtr->Next == NULL) {\r
- TempHeaderPtr->Next = NewMemoryHeader;\r
- break;\r
- }\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-AllocMemInMemoryBlock (\r
- IN MEMORY_MANAGE_HEADER *MemoryHeader,\r
- OUT VOID **Pool,\r
- IN UINTN NumberOfMemoryUnit\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Alloc Memory In MemoryBlock\r
-\r
-Arguments:\r
-\r
- MemoryHeader - MEMORY_MANAGE_HEADER\r
- Pool - Place to store pointer to memory\r
- NumberOfMemoryUnit - Number Of Memory Unit\r
-\r
-Returns:\r
-\r
- EFI_NOT_FOUND - Can't find the free memory \r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- UINTN TempBytePos;\r
- UINTN FoundBytePos;\r
- UINT8 Index;\r
- UINT8 FoundBitPos;\r
- UINT8 ByteValue;\r
- UINT8 BitValue;\r
- UINTN NumberOfZeros;\r
- UINTN Count;\r
-\r
- FoundBytePos = 0;\r
- FoundBitPos = 0;\r
- ByteValue = MemoryHeader->BitArrayPtr[0];\r
- NumberOfZeros = 0;\r
- Index = 0;\r
-\r
- for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {\r
- \r
- //\r
- // Pop out BitValue from a byte in TempBytePos.\r
- //\r
- BitValue = (UINT8) (ByteValue & 0x1);\r
- //\r
- // right shift the byte\r
- //\r
- ByteValue /= 2;\r
-\r
- if (BitValue == 0) {\r
- //\r
- // Found a free bit, the NumberOfZeros only record the number\r
- // of those consecutive zeros\r
- //\r
- NumberOfZeros++;\r
- //\r
- // Found enough consecutive free space, break the loop\r
- //\r
- if (NumberOfZeros >= NumberOfMemoryUnit) {\r
- break;\r
- }\r
- } else {\r
- //\r
- // Encountering a '1', meant the bit is ocupied.\r
- //\r
- if (NumberOfZeros >= NumberOfMemoryUnit) {\r
- //\r
- // Found enough consecutive free space,break the loop\r
- //\r
- break;\r
- } else {\r
- //\r
- // the NumberOfZeros only record the number of those consecutive zeros,\r
- // so reset the NumberOfZeros to 0 when encountering '1' before finding\r
- // enough consecutive '0's\r
- //\r
- NumberOfZeros = 0;\r
- //\r
- // reset the (FoundBytePos,FoundBitPos) to the position of '1'\r
- //\r
- FoundBytePos = TempBytePos;\r
- FoundBitPos = Index;\r
- }\r
- }\r
- //\r
- // step forward a bit\r
- //\r
- Index++;\r
- if (Index == 8) {\r
- //\r
- // step forward a byte, getting the byte value,\r
- // and reset the bit pos.\r
- //\r
- TempBytePos += 1;\r
- ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];\r
- Index = 0;\r
- }\r
- }\r
-\r
- if (NumberOfZeros < NumberOfMemoryUnit) {\r
- return EFI_NOT_FOUND;\r
- }\r
- \r
- //\r
- // Found enough free space.\r
- //\r
- \r
- //\r
- // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:\r
- // 1)(FoundBytePos,FoundBitPos) record the position\r
- // of the last '1' before the consecutive '0's, it must\r
- // be adjusted to the start position of the consecutive '0's.\r
- // 2)the start address of the consecutive '0's is just the start of\r
- // the bitarray. so no need to adjust the values of\r
- // (FoundBytePos,FoundBitPos).\r
- //\r
- if ((MemoryHeader->BitArrayPtr[0] & bit (0)) != 0) {\r
- FoundBitPos += 1;\r
- }\r
- \r
- //\r
- // Have the (FoundBytePos,FoundBitPos) make sense.\r
- //\r
- if (FoundBitPos > 7) {\r
- FoundBytePos += 1;\r
- FoundBitPos -= 8;\r
- }\r
- \r
- //\r
- // Set the memory as allocated\r
- //\r
- for (TempBytePos = FoundBytePos, Index = FoundBitPos,Count = 0;\r
- Count < NumberOfMemoryUnit; Count ++) {\r
-\r
- MemoryHeader->BitArrayPtr[TempBytePos] = (UINT8) (MemoryHeader->BitArrayPtr[TempBytePos] | bit (Index));\r
- Index++;\r
- if (Index == 8) {\r
- TempBytePos += 1;\r
- Index = 0;\r
- }\r
- }\r
-\r
- *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-IsMemoryBlockEmptied (\r
- IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Is Memory Block Emptied\r
-\r
-Arguments:\r
-\r
- MemoryHeaderPtr - MEMORY_MANAGE_HEADER\r
-\r
-Returns:\r
-\r
- TRUE - Empty\r
- FALSE - Not Empty \r
-\r
---*/\r
-{\r
- UINTN Index;\r
-\r
- for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {\r
- if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-VOID\r
-DelinkMemoryBlock (\r
- IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,\r
- IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Delink Memory Block\r
-\r
-Arguments:\r
-\r
- FirstMemoryHeader - MEMORY_MANAGE_HEADER\r
- NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER\r
-\r
-Returns:\r
-\r
- VOID\r
-\r
---*/\r
-{\r
- MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
-\r
- if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {\r
- return ;\r
- }\r
- for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL;\r
- TempHeaderPtr = TempHeaderPtr->Next) {\r
-\r
- if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {\r
- //\r
- // Link the before and after\r
- //\r
- TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;\r
- break;\r
- }\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-DelMemoryManagement (\r
- IN USB_HC_DEV *HcDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Delete Memory Management\r
-\r
-Arguments:\r
-\r
- HcDev - USB_HC_DEV\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Success\r
-\r
---*/\r
-{\r
- MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
-\r
- for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
-\r
- DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);\r
- //\r
- // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
- // the TempHeaderPtr is pointing to nonsense content.\r
- //\r
- FreeMemoryHeader (HcDev, TempHeaderPtr);\r
- //\r
- // reset the TempHeaderPtr,continue free another memory block.\r
- //\r
- TempHeaderPtr = HcDev->MemoryHeader->Next;\r
- }\r
-\r
- FreeMemoryHeader (HcDev, HcDev->MemoryHeader);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-VOID\r
-CleanUsbTransactions (\r
- IN USB_HC_DEV *HcDev\r
- )\r
-{\r
- //\r
- // only asynchronous interrupt transfers are always alive on the bus\r
- //\r
- ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));\r
-}\r
-\r
-VOID\r
-TurnOffUSBEmulation (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo\r
- )\r
-/*++\r
- \r
- Routine Description:\r
- Disable USB Emulation\r
- Arguments:\r
- PciIo - EFI_PCI_IO_PROTOCOL\r
- Returns:\r
- VOID\r
---*/\r
-{\r
- UINT16 Command;\r
-\r
- //\r
- // Disable USB Emulation\r
- //\r
- Command = 0;\r
- PciIo->Pci.Write (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- USB_EMULATION,\r
- 1,\r
- &Command\r
- );\r
-\r
- return ;\r
-}\r