]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/PcatSingleSegmentPciCfgPei/PciCfg.c
Enhance PciCfg2 driver to handle unaligned Pci access according to PI spec.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / PcatSingleSegmentPciCfgPei / PciCfg.c
index 5becfe4701766da497117aa14cf4fb5babb68a8c..aaabfbb58af1b74d38cfe3530aa0045f3749c4cc 100644 (file)
@@ -54,22 +54,47 @@ PciCfgRead (
   UINTN  PciLibAddress;\r
 \r
   PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
-  switch (Width) {\r
-    case EfiPeiPciCfgWidthUint8:\r
-      * (UINT8 *) Buffer = PciRead8 (PciLibAddress);\r
-      break;\r
 \r
-    case EfiPeiPciCfgWidthUint16:\r
-      * (UINT16 *) Buffer = PciRead16 (PciLibAddress);\r
-      break;\r
-\r
-    case EfiPeiPciCfgWidthUint32:\r
-      * (UINT32 *) Buffer = PciRead32 (PciLibAddress);\r
-      break;\r
-\r
-    default:\r
-      return EFI_INVALID_PARAMETER;\r
+  if (Width == EfiPeiPciCfgWidthUint8) {\r
+    *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
+  } else if (Width == EfiPeiPciCfgWidthUint16) {\r
+    if ((PciLibAddress & 0x01) == 0) {\r
+      //\r
+      // Aligned Pci address access\r
+      //\r
+      WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));\r
+    } else {\r
+      //\r
+      // Unaligned Pci address access, break up the request into byte by byte.\r
+      //\r
+      *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
+      *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
+    }\r
+  } else if (Width == EfiPeiPciCfgWidthUint32) {\r
+    if ((PciLibAddress & 0x03) == 0) {\r
+      //\r
+      // Aligned Pci address access\r
+      //\r
+      WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));\r
+    } else if ((PciLibAddress & 0x01) == 0) {\r
+      //\r
+      // Unaligned Pci address access, break up the request into word by word.\r
+      //\r
+      WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));\r
+      WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));\r
+    } else {\r
+      //\r
+      // Unaligned Pci address access, break up the request into byte by byte.\r
+      //\r
+      *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
+      *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
+      *((UINT8 *) Buffer + 2) = PciRead8 (PciLibAddress + 2);\r
+      *((UINT8 *) Buffer + 3) = PciRead8 (PciLibAddress + 3);\r
+    }\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -104,22 +129,47 @@ PciCfgWrite (
   UINTN  PciLibAddress;\r
 \r
   PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
-  switch (Width) {\r
-    case EfiPeiPciCfgWidthUint8:\r
-      PciWrite8 (PciLibAddress, *(UINT8 *) Buffer);\r
-      break;\r
-\r
-    case EfiPeiPciCfgWidthUint16:\r
-      PciWrite16 (PciLibAddress, *(UINT16 *) Buffer);\r
-      break;\r
 \r
-    case EfiPeiPciCfgWidthUint32:\r
-      PciWrite32 (PciLibAddress, *(UINT32 *) Buffer);\r
-      break;\r
-\r
-    default:\r
-      return EFI_INVALID_PARAMETER;\r
+  if (Width == EfiPeiPciCfgWidthUint8) {\r
+    PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
+  } else if (Width == EfiPeiPciCfgWidthUint16) {\r
+    if ((PciLibAddress & 0x01) == 0) {\r
+      //\r
+      // Aligned Pci address access\r
+      //\r
+      PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));\r
+    } else {\r
+      //\r
+      // Unaligned Pci address access, break up the request into byte by byte.\r
+      //\r
+      PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
+      PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); \r
+    }\r
+  } else if (Width == EfiPeiPciCfgWidthUint32) {\r
+    if ((PciLibAddress & 0x03) == 0) {\r
+      //\r
+      // Aligned Pci address access\r
+      //\r
+      PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));\r
+    } else if ((PciLibAddress & 0x01) == 0) {\r
+      //\r
+      // Unaligned Pci address access, break up the request into word by word.\r
+      //\r
+      PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));\r
+      PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));\r
+    } else {\r
+      //\r
+      // Unaligned Pci address access, break up the request into byte by byte.\r
+      //\r
+      PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
+      PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); \r
+      PciWrite8 (PciLibAddress + 2, *((UINT8 *) Buffer + 2)); \r
+      PciWrite8 (PciLibAddress + 3, *((UINT8 *) Buffer + 3)); \r
+    }\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -154,22 +204,46 @@ PciCfgModify (
   UINTN  PciLibAddress;\r
 \r
   PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
-  switch (Width) {\r
-    case EfiPeiPciCfgWidthUint8:\r
-      PciAndThenOr8 (PciLibAddress, (UINT8)~ClearBits, (UINT8)SetBits);\r
-      break;\r
-\r
-    case EfiPeiPciCfgWidthUint16:\r
+  if (Width == EfiPeiPciCfgWidthUint8) {\r
+    PciAndThenOr8 (PciLibAddress, (UINT8)~ClearBits, (UINT8)SetBits);\r
+  } else if (Width == EfiPeiPciCfgWidthUint16) {\r
+    if ((PciLibAddress & 0x01) == 0) {\r
+      //\r
+      // Aligned Pci address access\r
+      //\r
       PciAndThenOr16 (PciLibAddress, (UINT16)~ClearBits, (UINT16)SetBits);\r
-      break;\r
-\r
-    case EfiPeiPciCfgWidthUint32:\r
+    } else {\r
+      //\r
+      // Unaligned Pci address access, break up the request into byte by byte.\r
+      //\r
+      PciAndThenOr8 (PciLibAddress, (UINT8)~ClearBits, (UINT8)SetBits);\r
+      PciAndThenOr8 (PciLibAddress + 1, (UINT8)~(ClearBits >> 8), (UINT8)(SetBits >> 8));\r
+    }\r
+  } else if (Width == EfiPeiPciCfgWidthUint32) {\r
+    if ((PciLibAddress & 0x03) == 0) {\r
+      //\r
+      // Aligned Pci address access\r
+      //\r
       PciAndThenOr32 (PciLibAddress, (UINT32)~ClearBits, (UINT32)SetBits);\r
-      break;\r
-\r
-    default:\r
-      return EFI_INVALID_PARAMETER;\r
+    } else if ((PciLibAddress & 0x01) == 0) {\r
+      //\r
+      // Unaligned Pci address access, break up the request into word by word.\r
+      //\r
+      PciAndThenOr16 (PciLibAddress, (UINT16)~ClearBits, (UINT16)SetBits);\r
+      PciAndThenOr16 (PciLibAddress + 2, (UINT16)~(ClearBits >> 16), (UINT16)(SetBits >> 16));\r
+    } else {\r
+      //\r
+      // Unaligned Pci address access, break up the request into byte by byte.\r
+      //\r
+      PciAndThenOr8 (PciLibAddress, (UINT8)~ClearBits, (UINT8)SetBits);\r
+      PciAndThenOr8 (PciLibAddress + 1, (UINT8)~(ClearBits >> 8), (UINT8)(SetBits >> 8));\r
+      PciAndThenOr8 (PciLibAddress + 2, (UINT8)~(ClearBits >> 16), (UINT8)(SetBits >> 16));\r
+      PciAndThenOr8 (PciLibAddress + 3, (UINT8)~(ClearBits >> 24), (UINT8)(SetBits >> 24));\r
+    }\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r