123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- /** @file
- Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
- 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
- )
- {
- UINT64 BaseAddress = 0;
- UINT64 TempBaseAddress = 0;
- UINT8 RevId = 0;
- UINT32 Bar;
- UINT64 IoSize;
- UINT64 MemSize;
- UINTN MemSizeBits;
- 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
- //
- PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- Bar,
- 1,
- (VOID *) &BaseAddress
- );
- //
- // Find BAR size
- //
- TempBaseAddress = 0xffffffff;
- PciIo->Pci.Write (
- PciIo,
- EfiPciIoWidthUint32,
- Bar,
- 1,
- (VOID *) &TempBaseAddress
- );
- 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.
- //
- gDS->FreeMemorySpace (
- BaseAddress,
- MemSize
- );
- //
- // Force new alignment
- //
- MemSize = 0x8000000;
- MemSizeBits = 28;
- gDS->AllocateMemorySpace (
- EfiGcdAllocateAnySearchBottomUp,
- EfiGcdMemoryTypeMemoryMappedIo,
- MemSizeBits, // Alignment
- MemSize,
- &BaseAddress,
- mImageHandle,
- NULL
- );
- 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) {
- PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- Bar,
- 1,
- (VOID *) &BaseAddress
- );
- if (BaseAddress && 0x01) {
- TempBaseAddress = 0xffffffff;
- 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) {
- gDS->FreeIoSpace (
- BaseAddress,
- IoSize
- );
- gDS->AllocateIoSpace (
- EfiGcdAllocateAnySearchTopDown,
- EfiGcdIoTypeIo,
- NCR_GRAN, // Alignment
- MIN_NCR_IO_SIZE,
- &BaseAddress,
- mImageHandle,
- NULL
- );
- TempBaseAddress = BaseAddress + 1;
- 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.
- //
- 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;
- 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;
- PciIo->Pci.Write (
- PciIo,
- EfiPciIoWidthUint32,
- 0x20,
- 1,
- (VOID *) &TempBaseAddress
- );
- }
- }
- break;
- default:
- break;
- }
- return;
- }
- VOID
- ProgramPciLatency(
- IN EFI_PCI_IO_PROTOCOL *PciIo
- )
- {
- //
- // Program Master Latency Timer
- //
- if (mSystemConfiguration.PciLatency != 0) {
- 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);
- }
- }
- ++Index;
- }
- break;
- }
- return;
- }
|