]> git.proxmox.com Git - mirror_edk2.git/commitdiff
add SR-IOV support in EDK II.
authorhtao <htao@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 16 Sep 2009 09:32:06 +0000 (09:32 +0000)
committerhtao <htao@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 16 Sep 2009 09:32:06 +0000 (09:32 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9269 6f19259b-4bc3-4df7-8a09-765794883524

IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciBus.h
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciCommand.c
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciCommand.h
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec

index df224d12c493e67545ebf5d44be609476c957d5d..0c1c864bc8b1c1b3144a9b0b1801108ac493de78 100644 (file)
@@ -50,6 +50,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 typedef struct _PCI_IO_DEVICE              PCI_IO_DEVICE;\r
 typedef struct _PCI_BAR                    PCI_BAR;\r
 \r
+#define EFI_PCI_RID(Bus, Device, Function)  (((UINT32)Bus << 8) + ((UINT32)Device << 3) + (UINT32)Function)\r
+#define EFI_PCI_BUS_OF_RID(RID)             ((UINT32)RID >> 8)\r
+\r
+#define     EFI_PCI_IOV_POLICY_ARI           0x0001\r
+#define     EFI_PCI_IOV_POLICY_SRIOV         0x0002\r
+#define     EFI_PCI_IOV_POLICY_MRIOV         0x0004\r
+\r
 typedef enum {\r
   PciBarTypeUnknown = 0,\r
   PciBarTypeIo16,\r
@@ -248,7 +255,17 @@ struct _PCI_IO_DEVICE {
   EFI_HPC_PADDING_ATTRIBUTES                PaddingAttributes;\r
 \r
   BOOLEAN                                   IsPciExp;\r
-\r
+  //\r
+  // For SR-IOV\r
+  //\r
+  UINT8                                     PciExpressCapabilityOffset;\r
+  UINT32                                    AriCapabilityOffset;\r
+  UINT32                                    SrIovCapabilityOffset;\r
+  UINT32                                    MrIovCapabilityOffset;\r
+  PCI_BAR                                   VfPciBar[PCI_MAX_BAR];\r
+  UINT32                                    SystemPageSize;\r
+  UINT16                                    InitialVFs;\r
+  UINT16                                    ReservedBusNum;\r
 };\r
 \r
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \\r
index a3a13d55a0db9875dc1fb72b77ba270416877a54..a0f1e44e280decad655c047cf9f2d543c6dd60a2 100644 (file)
 \r
 [FeaturePcd.common]\r
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSrIovSupport\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdAriSupport\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdMrIovSupport\r
 \r
+[FixedPcd.common]\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize\r
 # [Event]\r
 #   ##\r
 #   # Notify event set by CreateEventForHpc () for PCI Hot Plug controller.\r
index 39f5271e9bc142c172692b2886567475d87e2485..601af309b7c2e76d7aa2b9f2944d39146e7b5ea5 100644 (file)
@@ -179,3 +179,70 @@ LocateCapabilityRegBlock (
   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
index 7019b5ea196479f42c0acb056b9a8245a70c4023..942bea941e308b22e202e567972141e2439465f5 100644 (file)
@@ -118,6 +118,27 @@ LocateCapabilityRegBlock (
   OUT UINT8         *NextRegBlock OPTIONAL\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
 /**\r
   Macro that reads command register.\r
 \r
index baad1ccd720bda1b540d41db5e40b620369cb08c..0eb9f9a9d152ffd519e4cde0d1188e1f26bc7d9e 100644 (file)
@@ -215,6 +215,10 @@ RegisterPciDevice (
   EFI_PCI_IO_PROTOCOL *PciIo;\r
   UINT8               Data8;\r
   BOOLEAN             HasEfiImage;\r
+  PCI_IO_DEVICE       *ParrentPciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL *ParrentPciIo;\r
+  UINT16              Data16;\r
+  UINT32              Data32;\r
 \r
   //\r
   // Install the pciio protocol, device path protocol\r
@@ -251,7 +255,35 @@ RegisterPciDevice (
   PciIo = &(PciIoDevice->PciIo);\r
   Data8 = PCI_INT_LINE_UNKNOWN;\r
   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);\r
+  \r
+  //\r
+  // PCI-IOV programming\r
+  //\r
+  if (((FeaturePcdGet(PcdAriSupport) & EFI_PCI_IOV_POLICY_ARI) != 0) && (PciIoDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport) & EFI_PCI_IOV_POLICY_SRIOV) != 0) &&\r
+      (PciIoDevice->SrIovCapabilityOffset != 0)) {\r
+    //\r
+    // Check its parrent ARI forwarding capability\r
+    //\r
+    ParrentPciIoDevice = PciIoDevice->Parent;\r
+    ParrentPciIo = &(ParrentPciIoDevice->PciIo);\r
+    ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 1, &Data32);\r
+    if (Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) {\r
+      //\r
+      // ARI forward support in bridge, so enable it.\r
+      //\r
+      ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
+      Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;\r
+      ParrentPciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
 \r
+      //\r
+      // Set ARI Capable Hierarchy for device\r
+      //\r
+      PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
+      Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
+    }\r
+  }\r
+  \r
   //\r
   // Process OpRom\r
   //\r
index 2d5408abe0b4687ee34f833b2cf789b4b0a08b97..66183960f16b3aed78476837b869df6b529ebd2b 100644 (file)
@@ -367,6 +367,16 @@ GatherDeviceInfo (
     Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
   }\r
 \r
+  //\r
+  // Parse the SR-IOV VF bars\r
+  //\r
+  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+    for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;\r
+         Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;\r
+         BarIndex++) {\r
+      Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);\r
+    }\r
+  }\r
   return PciIoDevice;\r
 }\r
 \r
@@ -597,6 +607,80 @@ CreatePciDevicePath (
   return PciIoDevice->DevicePath;\r
 }\r
 \r
+/**\r
+  Check whether the PCI IOV VF bar is existed or not.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param Offset            The offset.\r
+  @param BarLengthValue    The bar length value returned.\r
+  @param OriginalBarValue  The original bar value returned.\r
+\r
+  @retval EFI_NOT_FOUND    The bar doesn't exist.\r
+  @retval EFI_SUCCESS      The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+VfBarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT32              OriginalValue;\r
+  UINT32              Value;\r
+  EFI_TPL             OldTpl;\r
+\r
+  //\r
+  // Ensure it is called properly\r
+  //\r
+  ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
+  if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (BarLengthValue != NULL) {\r
+    *BarLengthValue = Value;\r
+  }\r
+\r
+  if (OriginalBarValue != NULL) {\r
+    *OriginalBarValue = OriginalValue;\r
+  }\r
+\r
+  if (Value == 0) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
 /**\r
   Check whether the bar is existed or not.\r
 \r
@@ -1249,6 +1333,207 @@ SetNewAlign (
   return ;\r
 }\r
 \r
+/**\r
+  Parse PCI IOV VF bar information and fill them into PCI device instance.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Offset       Bar offset.\r
+  @param BarIndex     Bar index.\r
+\r
+  @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciIovParseVfBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  )\r
+{\r
+  UINT32      Value;\r
+  UINT64      BarValue64;\r
+  UINT32      OriginalValue;\r
+  UINT32      Mask;\r
+  UINT32      Data;\r
+  UINT8       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Ensure it is called properly\r
+  //\r
+  ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
+  if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
+    return 0;\r
+  }\r
+\r
+  OriginalValue = 0;\r
+  Value         = 0;\r
+  BarValue64    = 0;\r
+\r
+  Status = VfBarExisted (\r
+            PciIoDevice,\r
+            Offset,\r
+            &Value,\r
+            &OriginalValue\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->VfPciBar[BarIndex].Length      = 0;\r
+    PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;\r
+\r
+    //\r
+    // Scan all the BARs anyway\r
+    //\r
+    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+    return Offset + 4;\r
+  }\r
+\r
+  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+  if (Value & 0x01) {\r
+    //\r
+    // Device I/Os. Impossible\r
+    //\r
+    ASSERT (FALSE);\r
+    return Offset + 4;\r
+\r
+  } else {\r
+\r
+    Mask  = 0xfffffff0;\r
+\r
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+    switch (Value & 0x07) {\r
+\r
+    //\r
+    //memory space; anywhere in 32 bit address space\r
+    //\r
+    case 0x00:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;\r
+      } else {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;\r
+      }\r
+\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Adjust Length\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
+      //\r
+      // Adjust Alignment\r
+      //\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // memory space; anywhere in 64 bit address space\r
+    //\r
+    case 0x04:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;\r
+      } else {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;\r
+      }\r
+\r
+      //\r
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+      // is regarded as an extension for the first bar. As a result\r
+      // the sizing will be conducted on combined 64 bit value\r
+      // Here just store the masked first 32bit value for future size\r
+      // calculation\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = Value & Mask;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      //\r
+      // Increment the offset to point to next DWORD\r
+      //\r
+      Offset += 4;\r
+\r
+      Status = VfBarExisted (\r
+                PciIoDevice,\r
+                Offset,\r
+                &Value,\r
+                &OriginalValue\r
+                );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Offset + 4;\r
+      }\r
+\r
+      //\r
+      // Fix the length to support some spefic 64 bit BAR\r
+      //\r
+      Data  = Value;\r
+      Index = 0;\r
+      for (Data = Value; Data != 0; Data >>= 1) {\r
+       Index ++;\r
+      }\r
+      Value |= ((UINT32)(-1) << Index); \r
+\r
+      //\r
+      // Calculate the size of 64bit bar\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Adjust Length\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
+      //\r
+      // Adjust Alignment\r
+      //\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // reserved\r
+    //\r
+    default:\r
+      PciIoDevice->VfPciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      break;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Check the length again so as to keep compatible with some special bars\r
+  //\r
+  if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {\r
+    PciIoDevice->VfPciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;\r
+  }\r
+  \r
+  //\r
+  // Increment number of bar\r
+  //\r
+  return Offset + 4;\r
+}\r
+\r
 /**\r
   Parse PCI bar information and fill them into PCI device instance.\r
 \r
@@ -1349,8 +1634,14 @@ PciParseBar (
       }\r
 \r
       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
-      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
-\r
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+        //\r
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+        //\r
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      }\r
       break;\r
 \r
     //\r
@@ -1386,6 +1677,15 @@ PciParseBar (
                  );\r
 \r
       if (EFI_ERROR (Status)) {\r
+        //\r
+        // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again\r
+        //\r
+        if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+          //\r
+          // some device implement MMIO bar with 0 length, need to treat it as no-bar\r
+          //\r
+          PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+        }\r
         return Offset + 4;\r
       }\r
 \r
@@ -1406,7 +1706,14 @@ PciParseBar (
 \r
       PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
       PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
-      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+        //\r
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+        //\r
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      }\r
 \r
       break;\r
 \r
@@ -1416,8 +1723,14 @@ PciParseBar (
     default:\r
       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
-      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
-\r
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+        //\r
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+        //\r
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      }\r
       break;\r
     }\r
   }\r
@@ -1570,6 +1883,8 @@ CreatePciIoDevice (
   )\r
 {\r
   PCI_IO_DEVICE *PciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL  *PciIo;\r
+  EFI_STATUS           Status;\r
 \r
   PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
   if (PciIoDevice == NULL) {\r
@@ -1607,6 +1922,162 @@ CreatePciIoDevice (
   InitializePciIoInstance (PciIoDevice);\r
   InitializePciDriverOverrideInstance (PciIoDevice);\r
   InitializePciLoadFile2 (PciIoDevice);\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Detect if PCI Express Device\r
+  //\r
+  PciIoDevice->PciExpressCapabilityOffset = 0;\r
+  Status = LocateCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCI_CAPABILITY_ID_PCIEXP,\r
+             &PciIoDevice->PciExpressCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    PciIoDevice->IsPciExp = TRUE;\r
+  }\r
+\r
+  //\r
+  // Initialize for PCI IOV\r
+  //\r
+\r
+  //\r
+  // Check ARI for function 0 only\r
+  //\r
+  Status = LocatePciExpressCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCIE_CAPABILITY_ID_ARI,\r
+             &PciIoDevice->AriCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",\r
+      (UINTN)Bus,\r
+      (UINTN)Device,\r
+      (UINTN)Func,\r
+      (UINTN)PciIoDevice->AriCapabilityOffset\r
+      ));\r
+  }\r
+\r
+  Status = LocatePciExpressCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCIE_CAPABILITY_ID_SRIOV,\r
+             &PciIoDevice->SrIovCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",\r
+      (UINTN)Bus,\r
+      (UINTN)Device,\r
+      (UINTN)Func,\r
+      (UINTN)PciIoDevice->SrIovCapabilityOffset\r
+      ));\r
+  }\r
+\r
+  Status = LocatePciExpressCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCIE_CAPABILITY_ID_MRIOV,\r
+             &PciIoDevice->MrIovCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",\r
+      (UINTN)Bus,\r
+      (UINTN)Device,\r
+      (UINTN)Func,\r
+      (UINTN)PciIoDevice->MrIovCapabilityOffset\r
+      ));\r
+  }\r
+\r
+  //\r
+  // Calculate SystemPageSize\r
+  //\r
+  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
+                 1,\r
+                 &PciIoDevice->SystemPageSize\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+\r
+    PciIoDevice->SystemPageSize = (PcdGet32(PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);\r
+    ASSERT (PciIoDevice->SystemPageSize != 0);\r
+\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,\r
+                 1,\r
+                 &PciIoDevice->SystemPageSize\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+    //\r
+    // Adjust SystemPageSize for Alignment usage later\r
+    //\r
+    PciIoDevice->SystemPageSize <<= 12;\r
+  }\r
+\r
+  // Calculate BusReservation for PCI IOV\r
+  //\r
+  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+    UINT16    VFStride;\r
+    UINT16    FirstVFOffset;\r
+    UINT32    PFRID;\r
+    UINT32    LastVF;\r
+\r
+    //\r
+    // Read First FirstVFOffset, InitialVFs, and VFStride\r
+    //\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,\r
+                 1,\r
+                 &FirstVFOffset\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)FirstVFOffset));\r
+\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
+                 1,\r
+                 &PciIoDevice->InitialVFs\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->InitialVFs));\r
+\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,\r
+                 1,\r
+                 &VFStride\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)VFStride));\r
+\r
+    //\r
+    // Calculate LastVF\r
+    //\r
+    PFRID = EFI_PCI_RID(Bus, Device, Func);\r
+    LastVF = PFRID + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\r
+\r
+    //\r
+    // Calculate ReservedBusNum for this PF\r
+    //\r
+    PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->ReservedBusNum));\r
+  }\r
+\r
 \r
   //\r
   // Initialize the reserved resource list\r
index 6f2f1e6ea50b5c6bf9df02b50f664d39ef50bf01..31238b45cf5b22172b6e35d5a4440a094781531b 100644 (file)
@@ -158,6 +158,26 @@ CreatePciDevicePath (
   IN  PCI_IO_DEVICE            *PciIoDevice\r
   );\r
 \r
+/**\r
+  Check whether the PCI IOV VF bar is existed or not.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param Offset            The offset.\r
+  @param BarLengthValue    The bar length value returned.\r
+  @param OriginalBarValue  The original bar value returned.\r
+\r
+  @retval EFI_NOT_FOUND    The bar doesn't exist.\r
+  @retval EFI_SUCCESS      The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+VfBarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  );\r
+\r
 /**\r
   Check whether the bar is existed or not.\r
 \r
@@ -288,6 +308,23 @@ PciParseBar (
   IN UINTN          BarIndex\r
   );\r
 \r
+/**\r
+  Parse PCI IOV VF bar information and fill them into PCI device instance.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Offset       Bar offset.\r
+  @param BarIndex     Bar index.\r
+\r
+  @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciIovParseVfBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  );\r
+\r
 /**\r
   This routine is used to initialize the bar of a PCI device.\r
 \r
index 16c0cce99aa0b439818b98307e801332ad762c4d..70b28df0b1008091d077b98a9a6895b5f18c43a6 100644 (file)
@@ -706,6 +706,7 @@ PciScanBus (
   UINT16                            BusRange;\r
   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
   BOOLEAN                           BusPadding;\r
+  UINT32                            TempReservedBusNum;\r
 \r
   PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
   SecondBus       = 0;\r
@@ -718,6 +719,7 @@ PciScanBus (
   PciAddress      = 0;\r
 \r
   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+    TempReservedBusNum = 0;\r
     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
 \r
       //\r
@@ -742,7 +744,7 @@ PciScanBus (
         continue;\r
       }\r
 \r
-      DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
+      DEBUG((EFI_D_INFO, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
 \r
       if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
         //\r
@@ -930,7 +932,7 @@ PciScanBus (
             EfiPciBeforeChildBusEnumeration\r
             );\r
 \r
-          DEBUG((EFI_D_ERROR, "Scan  PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber));\r
+          DEBUG((EFI_D_INFO, "Scan  PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber));\r
           Status = PciScanBus (\r
                     PciDevice,\r
                     (UINT8) (SecondBus),\r
@@ -967,6 +969,28 @@ PciScanBus (
                                         1,\r
                                         SubBusNumber\r
                                         );\r
+      } else  {\r
+        //\r
+        // It is device. Check PCI IOV for Bus reservation\r
+        //\r
+\r
+        //\r
+        // Go through each function, just reserve the MAX ReservedBusNum for one device\r
+        //\r
+        if ((PciDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+\r
+          if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
+\r
+            (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
+            TempReservedBusNum = PciDevice->ReservedBusNum;\r
+\r
+            if (Func == 0) {\r
+              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
+            } else {\r
+              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
+            }\r
+          }\r
+        }\r
       }\r
 \r
       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
@@ -1139,7 +1163,7 @@ PciHostBridgeEnumerator (
   //\r
   NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
 \r
-  DEBUG((EFI_D_ERROR, "PCI Bus First Scanning\n"));\r
+  DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
   RootBridgeHandle = NULL;\r
   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
 \r
@@ -1226,7 +1250,7 @@ PciHostBridgeEnumerator (
     //\r
     NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
 \r
-    DEBUG((EFI_D_ERROR, "PCI Bus Second Scanning\n"));\r
+    DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
     RootBridgeHandle = NULL;\r
     while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
 \r
index 40d02354eb665a9bd2c42896a4670871f86c4e8b..17c864029b3d1eec88e95b347993fd3f75a040ca 100644 (file)
@@ -544,6 +544,94 @@ GetResourceFromDevice (
   }\r
 \r
   //\r
+  // Add VF resource\r
+  //\r
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+    switch ((PciDev->VfPciBar)[Index].BarType) {\r
+\r
+    case PciBarTypeMem32:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem32Node,\r
+        Node\r
+        );\r
+\r
+      break;\r
+\r
+    case PciBarTypeMem64:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem64Node,\r
+        Node\r
+        );\r
+\r
+      break;\r
+\r
+    case PciBarTypePMem64:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem64Node,\r
+        Node\r
+        );\r
+\r
+      break;\r
+\r
+    case PciBarTypePMem32:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem32Node,\r
+        Node\r
+        );\r
+      break;\r
+\r
+    case PciBarTypeIo16:\r
+    case PciBarTypeIo32:\r
+      break;\r
+\r
+    case PciBarTypeUnknown:\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
   // If there is no resource requested from this device,\r
   // then we indicate this device has been allocated naturally.\r
   //\r
@@ -599,6 +687,53 @@ CreateResourceNode (
   return Node;\r
 }\r
 \r
+/**\r
+  This function is used to create a IOV VF resource node.\r
+\r
+  @param PciDev       Pci device instance.\r
+  @param Length       Length of Io/Memory resource.\r
+  @param Alignment    Alignment of resource.\r
+  @param Bar          Bar index.\r
+  @param ResType      Type of resource: IO/Memory.\r
+  @param ResUsage     Resource usage.\r
+\r
+  @return PCI resource node created for given VF PCI device.\r
+          NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateVfResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",\r
+    (UINTN)PciDev->BusNumber,\r
+    (UINTN)PciDev->DeviceNumber,\r
+    (UINTN)PciDev->FunctionNumber,\r
+    (UINTN)Bar,\r
+    (UINTN)ResType,\r
+    (UINTN)Length\r
+    ));\r
+\r
+  Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);\r
+  if (Node == NULL) {\r
+    return Node;\r
+  }\r
+\r
+  Node->Virtual = TRUE;\r
+\r
+  return Node;\r
+}\r
+\r
 /**\r
   This function is used to extract resource request from\r
   device node list.\r
@@ -1094,6 +1229,13 @@ ProgramBar (
   UINT64              Address;\r
   UINT32              Address32;\r
 \r
+  //\r
+  // Check VF BAR\r
+  //\r
+  if (Node->Virtual) {\r
+    ProgramVfBar (Base, Node);\r
+  }\r
+\r
   Address = 0;\r
   PciIo   = &(Node->PciDev->PciIo);\r
 \r
@@ -1159,6 +1301,116 @@ ProgramBar (
   }\r
 }\r
 \r
+/**\r
+  Program IOV VF Bar register for PCI device.\r
+\r
+  @param Base  Base address for PCI device resource to be progammed.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramVfBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT32              Address32;\r
+\r
+  ASSERT (Node->Virtual);\r
+  if (!Node->Virtual) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Address = 0;\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate pci bus driver has allocated\r
+  // resource for this device\r
+  // It might be a temporary solution here since\r
+  // pci device could have multiple bar\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {\r
+\r
+  case PciBarTypeMem32:\r
+  case PciBarTypePMem32:\r
+\r
+    PciIo->Pci.Write (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",\r
+      (UINTN)Node->PciDev->BusNumber,\r
+      (UINTN)Node->PciDev->DeviceNumber,\r
+      (UINTN)Node->PciDev->FunctionNumber,\r
+      (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+      (UINTN)Address\r
+      ));\r
+\r
+    break;\r
+\r
+  case PciBarTypeMem64:\r
+  case PciBarTypePMem64:\r
+\r
+    Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+    PciIo->Pci.Write (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+    PciIo->Pci.Write (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",\r
+      (UINTN)Node->PciDev->BusNumber,\r
+      (UINTN)Node->PciDev->DeviceNumber,\r
+      (UINTN)Node->PciDev->FunctionNumber,\r
+      (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+      (UINT64)Address\r
+      ));\r
+\r
+    break;\r
+\r
+  case PciBarTypeIo16:\r
+  case PciBarTypeIo32:\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Program PCI-PCI bridge apperture.\r
 \r
index 96396fe8692d60f4f284cfb23aca0b1c619793eb..faa6c0d60c0248d6f3ed5b5f45f28d9e7057fc47 100644 (file)
@@ -35,6 +35,7 @@ typedef struct {
   UINT64              Length;\r
   BOOLEAN             Reserved;\r
   PCI_RESOURCE_USAGE  ResourceUsage;\r
+  BOOLEAN             Virtual;\r
 } PCI_RESOURCE_NODE;\r
 \r
 #define RESOURCE_NODE_FROM_LINK(a) \\r
@@ -174,6 +175,28 @@ CreateResourceNode (
   IN PCI_RESOURCE_USAGE    ResUsage\r
   );\r
 \r
+/**\r
+  This function is used to extract resource request from\r
+  IOV VF device node list.\r
+\r
+  @param Bridge     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateVfResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  );\r
+\r
 /**\r
   This function is used to extract resource request from\r
   device node list.\r
@@ -287,6 +310,19 @@ ProgramBar (
   IN PCI_RESOURCE_NODE *Node\r
   );\r
 \r
+/**\r
+  Program IOV VF Bar register for PCI device.\r
+\r
+  @param Base  Base address for PCI device resource to be progammed.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramVfBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  );\r
+\r
 /**\r
   Program PCI-PCI bridge apperture.\r
 \r
index e7f496bbed72425a5a78c16a976aeb27514e2342..62225a6be7dea3f8146c3c95f37fb1cbee8369f3 100644 (file)
   ## This PCD specifies whether Serial device use half hand shake.\r
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE|BOOLEAN|0x00010043\r
 \r
+  ## This PCD specifies whether the Single Root I/O virtualization support.\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSrIovSupport|TRUE|BOOLEAN|0x10000044\r
+\r
+  ## This PCD specifies whether the Alternative Routing-ID support.\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdAriSupport|TRUE|BOOLEAN|0x10000045\r
+\r
+  ## This PCD specifies whether the Multi Root I/O virtualization support.\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdMrIovSupport|FALSE|BOOLEAN|0x10000046\r
+\r
+\r
 [PcdsFixedAtBuild]\r
   ## FFS filename to find the default BMP Logo file.\r
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile |{ 0x99, 0x8b, 0xB2, 0x7B, 0xBB, 0x61, 0xD5, 0x11, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }|VOID*|16\r
   #  BIT2 indicates if ISA memory is supported\r
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures|0x05|UINT8|0x00010040\r
 \r
+  ## Single root I/O virtualization virtual function memory BAR alignment\r
+  #  BITN set indicates 2 of n+12 power\r
+  #  BIT0 set indicates 4KB alignment\r
+  #  BIT1 set indicates 8KB alignment\r
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047\r
+\r
 [PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic]\r
   ## PcdStatusCodeMemorySize is used when PcdStatusCodeUseMemory is set to true\r
   #  (PcdStatusCodeMemorySize * KBytes) is the total taken memory size.\r