return EFI_NOT_FOUND;\r
}\r
\r
+/**\r
+ Locate PciExpress capability register block per capability ID.\r
+\r
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
+ @param CapId The capability ID.\r
+ @param Offset A pointer to the offset returned.\r
+ @param NextRegBlock A pointer to the next block returned.\r
+\r
+ @retval EFI_SUCCESS Successfuly located capability register block.\r
+ @retval EFI_UNSUPPORTED Pci device does not support capability.\r
+ @retval EFI_NOT_FOUND Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocatePciExpressCapabilityRegBlock (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN UINT16 CapId,\r
+ IN OUT UINT32 *Offset,\r
+ OUT UINT32 *NextRegBlock OPTIONAL\r
+ )\r
+{\r
+ UINT32 CapabilityPtr;\r
+ UINT32 CapabilityEntry;\r
+ UINT16 CapabilityID;\r
+\r
+ //\r
+ // To check the capability of this device supports\r
+ //\r
+ if (!PciIoDevice->IsPciExp) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (*Offset != 0) {\r
+ CapabilityPtr = *Offset;\r
+ } else {\r
+ CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;\r
+ }\r
+\r
+ while (CapabilityPtr != 0) {\r
+ //\r
+ // Mask it to DWORD alignment per PCI spec\r
+ //\r
+ CapabilityPtr &= 0xFFC;\r
+ PciIoDevice->PciIo.Pci.Read (\r
+ &PciIoDevice->PciIo,\r
+ EfiPciIoWidthUint32,\r
+ CapabilityPtr,\r
+ 1,\r
+ &CapabilityEntry\r
+ );\r
+\r
+ CapabilityID = (UINT16) CapabilityEntry;\r
+\r
+ if (CapabilityID == CapId) {\r
+ *Offset = CapabilityPtr;\r
+ if (NextRegBlock != NULL) {\r
+ *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r