Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
https://svn.code.sf.net/p/edk2/code/trunk/edk2/, which are for MinnowBoard MAX open source project. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: David Wei <david.wei@intel.com> Reviewed-by: Mike Wu <mike.wu@intel.com> Reviewed-by: Hot Tian <hot.tian@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16599 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
517
Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c
Normal file
517
Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c
Normal file
@@ -0,0 +1,517 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
|
||||
the terms and conditions of the BSD License that accompanies this distribution.
|
||||
|
||||
The full text of the license may be found at
|
||||
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
|
||||
PciDevice.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Platform Initialization Driver.
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
#include "PlatformDxe.h"
|
||||
#include "Library/DxeServicesTableLib.h"
|
||||
#include "PciBus.h"
|
||||
#include "Guid/PciLanInfo.h"
|
||||
|
||||
extern VOID *mPciLanInfo;
|
||||
extern UINTN mPciLanCount;
|
||||
|
||||
extern EFI_HANDLE mImageHandle;
|
||||
extern SYSTEM_CONFIGURATION mSystemConfiguration;
|
||||
|
||||
|
||||
VOID *mPciRegistration;
|
||||
#define NCR_VENDOR_ID 0x1000
|
||||
#define ATI_VENDOR_ID 0x1002
|
||||
#define INTEL_VENDOR_ID 0x8086
|
||||
#define ATI_RV423_ID 0x5548
|
||||
#define ATI_RV423_ID2 0x5d57
|
||||
#define ATI_RV380_ID 0x3e50
|
||||
#define ATI_RV370_ID 0x5b60
|
||||
#define SI_VENDOR_ID 0x1095
|
||||
#define SI_SISATA_ID 0x3114
|
||||
#define SI_SIRAID_PCIUNL 0x40
|
||||
#define INTEL_82573E_IDER 0x108D
|
||||
|
||||
typedef struct {
|
||||
UINT8 ClassCode;
|
||||
UINT8 SubClassCode;
|
||||
UINT16 VendorId;
|
||||
UINT16 DeviceId;
|
||||
} BAD_DEVICE_TABLE;
|
||||
|
||||
BAD_DEVICE_TABLE BadDeviceTable[] = {
|
||||
{(UINT8)PCI_CLASS_MASS_STORAGE,(UINT8)PCI_CLASS_MASS_STORAGE_SCSI,(UINT16)NCR_VENDOR_ID, (UINT16)0xffff}, // Any NCR cards
|
||||
{(UINT8)PCI_CLASS_MASS_STORAGE,(UINT8)PCI_CLASS_MASS_STORAGE_IDE,(UINT16)INTEL_VENDOR_ID, (UINT16)INTEL_82573E_IDER}, // Intel i82573E Tekoa GBit Lan IDE-R
|
||||
{(UINT8)0xff,(UINT8)0xff,(UINT16)0xffff,(UINT16)0xffff}
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
PciBusDriverHook (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT FilterEvent;
|
||||
|
||||
//
|
||||
// Register for callback to PCI I/O protocol
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
PciBusEvent,
|
||||
NULL,
|
||||
&FilterEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR(Status);
|
||||
|
||||
//
|
||||
// Register for protocol notifications on this event
|
||||
//
|
||||
Status = gBS->RegisterProtocolNotify (
|
||||
&gEfiPciIoProtocolGuid,
|
||||
FilterEvent,
|
||||
&mPciRegistration
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
InitBadBars(
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT16 VendorId,
|
||||
IN UINT16 DeviceId
|
||||
)
|
||||
{
|
||||
|
||||
EFI_STATUS Status;
|
||||
PCI_IO_DEVICE *PciIoDevice;
|
||||
UINT64 BaseAddress = 0;
|
||||
UINT64 TempBaseAddress = 0;
|
||||
UINT8 RevId = 0;
|
||||
UINT32 Bar;
|
||||
UINT64 IoSize;
|
||||
UINT64 MemSize;
|
||||
UINTN MemSizeBits;
|
||||
|
||||
|
||||
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
|
||||
switch ( VendorId) {
|
||||
case ATI_VENDOR_ID:
|
||||
//
|
||||
// ATI fix-ups. At this time all ATI cards in BadDeviceTable
|
||||
// have same problem in that OPROM BAR needs to be increased.
|
||||
//
|
||||
Bar = 0x30 ;
|
||||
//
|
||||
// Get original BAR address
|
||||
//
|
||||
Status = PciIo->Pci.Read (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &BaseAddress
|
||||
);
|
||||
//
|
||||
// Find BAR size
|
||||
//
|
||||
TempBaseAddress = 0xffffffff;
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &TempBaseAddress
|
||||
);
|
||||
Status = PciIo->Pci.Read (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &TempBaseAddress
|
||||
);
|
||||
TempBaseAddress &= 0xfffffffe;
|
||||
MemSize = 1;
|
||||
while ((TempBaseAddress & 0x01) == 0) {
|
||||
TempBaseAddress = TempBaseAddress >> 1;
|
||||
MemSize = MemSize << 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Free up allocated memory memory and re-allocate with increased size.
|
||||
//
|
||||
Status = gDS->FreeMemorySpace (
|
||||
BaseAddress,
|
||||
MemSize
|
||||
);
|
||||
//
|
||||
// Force new alignment
|
||||
//
|
||||
MemSize = 0x8000000;
|
||||
MemSizeBits = 28;
|
||||
|
||||
Status = gDS->AllocateMemorySpace (
|
||||
EfiGcdAllocateAnySearchBottomUp,
|
||||
EfiGcdMemoryTypeMemoryMappedIo,
|
||||
MemSizeBits, // Alignment
|
||||
MemSize,
|
||||
&BaseAddress,
|
||||
mImageHandle,
|
||||
NULL
|
||||
);
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &BaseAddress
|
||||
);
|
||||
|
||||
break;
|
||||
case NCR_VENDOR_ID:
|
||||
#define MIN_NCR_IO_SIZE 0x800
|
||||
#define NCR_GRAN 11 // 2**11 = 0x800
|
||||
//
|
||||
// NCR SCSI cards like 8250S lie about IO needed. Assign as least 0x80.
|
||||
//
|
||||
for (Bar = 0x10; Bar < 0x28; Bar+= 4) {
|
||||
|
||||
Status = PciIo->Pci.Read (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &BaseAddress
|
||||
);
|
||||
if (BaseAddress && 0x01) {
|
||||
TempBaseAddress = 0xffffffff;
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &TempBaseAddress
|
||||
);
|
||||
TempBaseAddress &= 0xfffffffc;
|
||||
IoSize = 1;
|
||||
while ((TempBaseAddress & 0x01) == 0) {
|
||||
TempBaseAddress = TempBaseAddress >> 1;
|
||||
IoSize = IoSize << 1;
|
||||
}
|
||||
if (IoSize < MIN_NCR_IO_SIZE) {
|
||||
Status = gDS->FreeIoSpace (
|
||||
BaseAddress,
|
||||
IoSize
|
||||
);
|
||||
|
||||
Status = gDS->AllocateIoSpace (
|
||||
EfiGcdAllocateAnySearchTopDown,
|
||||
EfiGcdIoTypeIo,
|
||||
NCR_GRAN, // Alignment
|
||||
MIN_NCR_IO_SIZE,
|
||||
&BaseAddress,
|
||||
mImageHandle,
|
||||
NULL
|
||||
);
|
||||
TempBaseAddress = BaseAddress + 1;
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &TempBaseAddress
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case INTEL_VENDOR_ID:
|
||||
if (DeviceId == INTEL_82573E_IDER) {
|
||||
//
|
||||
// Tekoa i82573E IDE-R fix-ups. At this time A2 step and earlier parts do not
|
||||
// support any BARs except BAR0. Other BARS will actualy map to BAR0 so disable
|
||||
// them all for Control Blocks and Bus mastering ops as well as Secondary IDE
|
||||
// Controller.
|
||||
// All Tekoa A2 or earlier step chips for now.
|
||||
//
|
||||
Status = PciIo->Pci.Read (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint8,
|
||||
PCI_REVISION_ID_OFFSET,
|
||||
1,
|
||||
&RevId
|
||||
);
|
||||
if (RevId <= 0x02) {
|
||||
for (Bar = 0x14; Bar < 0x24; Bar+= 4) {
|
||||
//
|
||||
// Maybe want to clean this up a bit later but for now just clear out the secondary
|
||||
// Bars don't worry aboyut freeing up thge allocs.
|
||||
//
|
||||
TempBaseAddress = 0x0;
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
Bar,
|
||||
1,
|
||||
(VOID *) &TempBaseAddress
|
||||
);
|
||||
} // end for
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
//Tekoa A3 or above:
|
||||
//Clear bus master base address (PCI register 0x20)
|
||||
//since Tekoa does not fully support IDE Bus Mastering
|
||||
//
|
||||
TempBaseAddress = 0x0;
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint32,
|
||||
0x20,
|
||||
1,
|
||||
(VOID *) &TempBaseAddress
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
ProgramPciLatency(
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Program Master Latency Timer
|
||||
//
|
||||
if (mSystemConfiguration.PciLatency != 0) {
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint8,
|
||||
PCI_LATENCY_TIMER_OFFSET,
|
||||
1,
|
||||
&mSystemConfiguration.PciLatency
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
During S5 shutdown, we need to program PME in all LAN devices.
|
||||
Here we identify LAN devices and save their bus/dev/func.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SavePciLanAddress(
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN PciSegment,
|
||||
PciBus,
|
||||
PciDevice,
|
||||
PciFunction;
|
||||
VOID *NewBuffer;
|
||||
PCI_LAN_INFO *x;
|
||||
|
||||
Status = PciIo->GetLocation (
|
||||
PciIo,
|
||||
&PciSegment,
|
||||
&PciBus,
|
||||
&PciDevice,
|
||||
&PciFunction
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPciLanCount ++;
|
||||
Status = gBS->AllocatePool (
|
||||
EfiBootServicesData,
|
||||
mPciLanCount * sizeof(PCI_LAN_INFO),
|
||||
&NewBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPciLanCount > 1) {
|
||||
//
|
||||
// copy old data into new, larger buffer
|
||||
//
|
||||
gBS->CopyMem (
|
||||
NewBuffer,
|
||||
mPciLanInfo,
|
||||
(mPciLanCount - 1) * sizeof(PCI_LAN_INFO)
|
||||
);
|
||||
|
||||
//
|
||||
// free the old memory buffer
|
||||
//
|
||||
gBS->FreePool (mPciLanInfo);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// init the new entry
|
||||
//
|
||||
x = (PCI_LAN_INFO *)NewBuffer + (mPciLanCount - 1);
|
||||
x->PciBus = (UINT8)PciBus;
|
||||
x->PciDevice = (UINT8)PciDevice;
|
||||
x->PciFunction = (UINT8)PciFunction;
|
||||
|
||||
mPciLanInfo = NewBuffer;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@param Event the event that is signaled.
|
||||
@param Context not used here.
|
||||
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PciBusEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID* Context
|
||||
)
|
||||
{
|
||||
|
||||
EFI_STATUS Status;
|
||||
UINTN BufferSize;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
PCI_IO_DEVICE *PciIoDevice;
|
||||
UINT64 Supports;
|
||||
UINTN Index;
|
||||
UINT8 mCacheLineSize = 0x10;
|
||||
|
||||
while (TRUE) {
|
||||
BufferSize = sizeof (EFI_HANDLE);
|
||||
Status = gBS->LocateHandle (
|
||||
ByRegisterNotify,
|
||||
NULL,
|
||||
mPciRegistration,
|
||||
&BufferSize,
|
||||
&Handle
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// If no more notification events exist
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
Status = gBS->HandleProtocol (
|
||||
Handle,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(void **)&PciIo
|
||||
);
|
||||
|
||||
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
|
||||
|
||||
//
|
||||
// Enable I/O for bridge so port 0x80 codes will come out
|
||||
//
|
||||
if (PciIoDevice->Pci.Hdr.VendorId == V_PCH_INTEL_VENDOR_ID)
|
||||
{
|
||||
Status = PciIo->Attributes(
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationSupported,
|
||||
0,
|
||||
&Supports
|
||||
);
|
||||
Supports &= EFI_PCI_DEVICE_ENABLE;
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationEnable,
|
||||
Supports,
|
||||
NULL
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Program PCI Latency Timer
|
||||
//
|
||||
ProgramPciLatency(PciIo);
|
||||
|
||||
//
|
||||
// Program Cache Line Size to 64 bytes (0x10 DWORDs)
|
||||
//
|
||||
Status = PciIo->Pci.Write (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint8,
|
||||
PCI_CACHELINE_SIZE_OFFSET,
|
||||
1,
|
||||
&mCacheLineSize
|
||||
);
|
||||
|
||||
//
|
||||
// If PCI LAN device, save bus/dev/func info
|
||||
// so we can program PME during S5 shutdown
|
||||
//
|
||||
if (PciIoDevice->Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
|
||||
SavePciLanAddress(PciIo);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Workaround for cards with bad BARs
|
||||
//
|
||||
Index = 0;
|
||||
while (BadDeviceTable[Index].ClassCode != 0xff) {
|
||||
if (BadDeviceTable[Index].DeviceId == 0xffff) {
|
||||
if ((PciIoDevice->Pci.Hdr.ClassCode[2] == BadDeviceTable[Index].ClassCode) &&
|
||||
(PciIoDevice->Pci.Hdr.ClassCode[1] == BadDeviceTable[Index].SubClassCode) &&
|
||||
(PciIoDevice->Pci.Hdr.VendorId == BadDeviceTable[Index].VendorId)) {
|
||||
InitBadBars(PciIo,BadDeviceTable[Index].VendorId,BadDeviceTable[Index].DeviceId);
|
||||
}
|
||||
} else {
|
||||
if ((PciIoDevice->Pci.Hdr.ClassCode[2] == BadDeviceTable[Index].ClassCode) &&
|
||||
(PciIoDevice->Pci.Hdr.ClassCode[1] == BadDeviceTable[Index].SubClassCode) &&
|
||||
(PciIoDevice->Pci.Hdr.VendorId == BadDeviceTable[Index].VendorId) &&
|
||||
(PciIoDevice->Pci.Hdr.DeviceId == BadDeviceTable[Index].DeviceId)) {
|
||||
|
||||
InitBadBars(PciIo,BadDeviceTable[Index].VendorId,BadDeviceTable[Index].DeviceId);
|
||||
}
|
Reference in New Issue
Block a user