]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
add SR-IOV support in EDK II.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
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