Enhance PciCfg2 driver to handle unaligned Pci access according to PI spec.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7077 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4 2008-12-18 07:40:19 +00:00
parent 165aba19f5
commit 8501ba4c6d
2 changed files with 105 additions and 17 deletions

View File

@ -47,10 +47,3 @@
[Depex]
TRUE
[FixedPcd.common]
##
# Disable ASSERT for unalign PCI IO access according to PI Spec Volume 1
# Spec has not this requirement.
##
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0E

View File

@ -227,9 +227,39 @@ PciCfg2Read (
if (Width == EfiPeiPciCfgWidthUint8) {
*((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
} else if (Width == EfiPeiPciCfgWidthUint16) {
*((UINT16 *) Buffer) = PciRead16 (PciLibAddress);
if ((PciLibAddress & 0x01) == 0) {
//
// Aligned Pci address access
//
WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
} else {
//
// Unaligned Pci address access, break up the request into byte by byte.
//
*((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
*((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);
}
} else if (Width == EfiPeiPciCfgWidthUint32) {
*((UINT32 *) Buffer) = PciRead32 (PciLibAddress);
if ((PciLibAddress & 0x03) == 0) {
//
// Aligned Pci address access
//
WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));
} else if ((PciLibAddress & 0x01) == 0) {
//
// Unaligned Pci address access, break up the request into word by word.
//
WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));
} else {
//
// Unaligned Pci address access, break up the request into byte by byte.
//
*((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
*((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);
*((UINT8 *) Buffer + 2) = PciRead8 (PciLibAddress + 2);
*((UINT8 *) Buffer + 3) = PciRead8 (PciLibAddress + 3);
}
} else {
return EFI_INVALID_PARAMETER;
}
@ -278,9 +308,39 @@ PciCfg2Write (
if (Width == EfiPeiPciCfgWidthUint8) {
PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
} else if (Width == EfiPeiPciCfgWidthUint16) {
PciWrite16 (PciLibAddress, *((UINT16 *) Buffer));
if ((PciLibAddress & 0x01) == 0) {
//
// Aligned Pci address access
//
PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
} else {
//
// Unaligned Pci address access, break up the request into byte by byte.
//
PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1));
}
} else if (Width == EfiPeiPciCfgWidthUint32) {
PciWrite32 (PciLibAddress, *((UINT32 *) Buffer));
if ((PciLibAddress & 0x03) == 0) {
//
// Aligned Pci address access
//
PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));
} else if ((PciLibAddress & 0x01) == 0) {
//
// Unaligned Pci address access, break up the request into word by word.
//
PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));
} else {
//
// Unaligned Pci address access, break up the request into byte by byte.
//
PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1));
PciWrite8 (PciLibAddress + 2, *((UINT8 *) Buffer + 2));
PciWrite8 (PciLibAddress + 3, *((UINT8 *) Buffer + 3));
}
} else {
return EFI_INVALID_PARAMETER;
}
@ -340,13 +400,48 @@ PciCfg2Modify (
if (Width == EfiPeiPciCfgWidthUint8) {
PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
} else if (Width == EfiPeiPciCfgWidthUint16) {
ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
if ((PciLibAddress & 0x01) == 0) {
//
// Aligned Pci address access
//
ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
} else {
//
// Unaligned Pci address access, break up the request into byte by byte.
//
PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));
}
} else if (Width == EfiPeiPciCfgWidthUint32) {
ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));
SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits);
PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);
if ((PciLibAddress & 0x03) == 0) {
//
// Aligned Pci address access
//
ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));
SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits);
PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);
} else if ((PciLibAddress & 0x01) == 0) {
//
// Unaligned Pci address access, break up the request into word by word.
//
ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1));
SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits + 1);
PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);
} else {
//
// Unaligned Pci address access, break up the request into byte by byte.
//
PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));
PciAndThenOr8 (PciLibAddress + 2, (UINT8) (~(*((UINT8 *) ClearBits + 2))), *((UINT8 *) SetBits + 2));
PciAndThenOr8 (PciLibAddress + 3, (UINT8) (~(*((UINT8 *) ClearBits + 3))), *((UINT8 *) SetBits + 3));
}
} else {
return EFI_INVALID_PARAMETER;
}