3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 Platform Initialization Driver.
27 #include "PlatformDxe.h"
28 #include "Library/DxeServicesTableLib.h"
30 #include "Guid/PciLanInfo.h"
32 extern VOID
*mPciLanInfo
;
33 extern UINTN mPciLanCount
;
35 extern EFI_HANDLE mImageHandle
;
36 extern SYSTEM_CONFIGURATION mSystemConfiguration
;
39 VOID
*mPciRegistration
;
40 #define NCR_VENDOR_ID 0x1000
41 #define ATI_VENDOR_ID 0x1002
42 #define INTEL_VENDOR_ID 0x8086
43 #define ATI_RV423_ID 0x5548
44 #define ATI_RV423_ID2 0x5d57
45 #define ATI_RV380_ID 0x3e50
46 #define ATI_RV370_ID 0x5b60
47 #define SI_VENDOR_ID 0x1095
48 #define SI_SISATA_ID 0x3114
49 #define SI_SIRAID_PCIUNL 0x40
50 #define INTEL_82573E_IDER 0x108D
59 BAD_DEVICE_TABLE BadDeviceTable
[] = {
60 {(UINT8
)PCI_CLASS_MASS_STORAGE
,(UINT8
)PCI_CLASS_MASS_STORAGE_SCSI
,(UINT16
)NCR_VENDOR_ID
, (UINT16
)0xffff}, // Any NCR cards
61 {(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
62 {(UINT8
)0xff,(UINT8
)0xff,(UINT16
)0xffff,(UINT16
)0xffff}
70 EFI_EVENT FilterEvent
;
73 // Register for callback to PCI I/O protocol
75 Status
= gBS
->CreateEvent (
82 ASSERT_EFI_ERROR(Status
);
85 // Register for protocol notifications on this event
87 Status
= gBS
->RegisterProtocolNotify (
88 &gEfiPciIoProtocolGuid
,
92 ASSERT_EFI_ERROR (Status
);
99 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
106 PCI_IO_DEVICE
*PciIoDevice
;
107 UINT64 BaseAddress
= 0;
108 UINT64 TempBaseAddress
= 0;
116 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
120 // ATI fix-ups. At this time all ATI cards in BadDeviceTable
121 // have same problem in that OPROM BAR needs to be increased.
125 // Get original BAR address
127 Status
= PciIo
->Pci
.Read (
132 (VOID
*) &BaseAddress
137 TempBaseAddress
= 0xffffffff;
138 Status
= PciIo
->Pci
.Write (
143 (VOID
*) &TempBaseAddress
145 Status
= PciIo
->Pci
.Read (
150 (VOID
*) &TempBaseAddress
152 TempBaseAddress
&= 0xfffffffe;
154 while ((TempBaseAddress
& 0x01) == 0) {
155 TempBaseAddress
= TempBaseAddress
>> 1;
156 MemSize
= MemSize
<< 1;
160 // Free up allocated memory memory and re-allocate with increased size.
162 Status
= gDS
->FreeMemorySpace (
167 // Force new alignment
172 Status
= gDS
->AllocateMemorySpace (
173 EfiGcdAllocateAnySearchBottomUp
,
174 EfiGcdMemoryTypeMemoryMappedIo
,
175 MemSizeBits
, // Alignment
181 Status
= PciIo
->Pci
.Write (
186 (VOID
*) &BaseAddress
191 #define MIN_NCR_IO_SIZE 0x800
192 #define NCR_GRAN 11 // 2**11 = 0x800
194 // NCR SCSI cards like 8250S lie about IO needed. Assign as least 0x80.
196 for (Bar
= 0x10; Bar
< 0x28; Bar
+= 4) {
198 Status
= PciIo
->Pci
.Read (
203 (VOID
*) &BaseAddress
205 if (BaseAddress
&& 0x01) {
206 TempBaseAddress
= 0xffffffff;
207 Status
= PciIo
->Pci
.Write (
212 (VOID
*) &TempBaseAddress
214 TempBaseAddress
&= 0xfffffffc;
216 while ((TempBaseAddress
& 0x01) == 0) {
217 TempBaseAddress
= TempBaseAddress
>> 1;
218 IoSize
= IoSize
<< 1;
220 if (IoSize
< MIN_NCR_IO_SIZE
) {
221 Status
= gDS
->FreeIoSpace (
226 Status
= gDS
->AllocateIoSpace (
227 EfiGcdAllocateAnySearchTopDown
,
229 NCR_GRAN
, // Alignment
235 TempBaseAddress
= BaseAddress
+ 1;
236 Status
= PciIo
->Pci
.Write (
241 (VOID
*) &TempBaseAddress
249 case INTEL_VENDOR_ID
:
250 if (DeviceId
== INTEL_82573E_IDER
) {
252 // Tekoa i82573E IDE-R fix-ups. At this time A2 step and earlier parts do not
253 // support any BARs except BAR0. Other BARS will actualy map to BAR0 so disable
254 // them all for Control Blocks and Bus mastering ops as well as Secondary IDE
256 // All Tekoa A2 or earlier step chips for now.
258 Status
= PciIo
->Pci
.Read (
261 PCI_REVISION_ID_OFFSET
,
266 for (Bar
= 0x14; Bar
< 0x24; Bar
+= 4) {
268 // Maybe want to clean this up a bit later but for now just clear out the secondary
269 // Bars don't worry aboyut freeing up thge allocs.
271 TempBaseAddress
= 0x0;
272 Status
= PciIo
->Pci
.Write (
277 (VOID
*) &TempBaseAddress
285 //Clear bus master base address (PCI register 0x20)
286 //since Tekoa does not fully support IDE Bus Mastering
288 TempBaseAddress
= 0x0;
289 Status
= PciIo
->Pci
.Write (
294 (VOID
*) &TempBaseAddress
308 IN EFI_PCI_IO_PROTOCOL
*PciIo
314 // Program Master Latency Timer
316 if (mSystemConfiguration
.PciLatency
!= 0) {
317 Status
= PciIo
->Pci
.Write (
320 PCI_LATENCY_TIMER_OFFSET
,
322 &mSystemConfiguration
.PciLatency
329 During S5 shutdown, we need to program PME in all LAN devices.
330 Here we identify LAN devices and save their bus/dev/func.
335 IN EFI_PCI_IO_PROTOCOL
*PciIo
346 Status
= PciIo
->GetLocation (
353 if (EFI_ERROR (Status
)) {
358 Status
= gBS
->AllocatePool (
360 mPciLanCount
* sizeof(PCI_LAN_INFO
),
363 if (EFI_ERROR (Status
)) {
367 if (mPciLanCount
> 1) {
369 // copy old data into new, larger buffer
374 (mPciLanCount
- 1) * sizeof(PCI_LAN_INFO
)
378 // free the old memory buffer
380 gBS
->FreePool (mPciLanInfo
);
385 // init the new entry
387 x
= (PCI_LAN_INFO
*)NewBuffer
+ (mPciLanCount
- 1);
388 x
->PciBus
= (UINT8
)PciBus
;
389 x
->PciDevice
= (UINT8
)PciDevice
;
390 x
->PciFunction
= (UINT8
)PciFunction
;
392 mPciLanInfo
= NewBuffer
;
398 @param Event the event that is signaled.
399 @param Context not used here.
414 EFI_PCI_IO_PROTOCOL
*PciIo
;
415 PCI_IO_DEVICE
*PciIoDevice
;
418 UINT8 mCacheLineSize
= 0x10;
421 BufferSize
= sizeof (EFI_HANDLE
);
422 Status
= gBS
->LocateHandle (
429 if (EFI_ERROR (Status
)) {
431 // If no more notification events exist
436 Status
= gBS
->HandleProtocol (
438 &gEfiPciIoProtocolGuid
,
442 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
445 // Enable I/O for bridge so port 0x80 codes will come out
447 if (PciIoDevice
->Pci
.Hdr
.VendorId
== V_PCH_INTEL_VENDOR_ID
)
449 Status
= PciIo
->Attributes(
451 EfiPciIoAttributeOperationSupported
,
455 Supports
&= EFI_PCI_DEVICE_ENABLE
;
456 Status
= PciIo
->Attributes (
458 EfiPciIoAttributeOperationEnable
,
466 // Program PCI Latency Timer
468 ProgramPciLatency(PciIo
);
471 // Program Cache Line Size to 64 bytes (0x10 DWORDs)
473 Status
= PciIo
->Pci
.Write (
476 PCI_CACHELINE_SIZE_OFFSET
,
482 // If PCI LAN device, save bus/dev/func info
483 // so we can program PME during S5 shutdown
485 if (PciIoDevice
->Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_NETWORK
) {
486 SavePciLanAddress(PciIo
);
491 // Workaround for cards with bad BARs
494 while (BadDeviceTable
[Index
].ClassCode
!= 0xff) {
495 if (BadDeviceTable
[Index
].DeviceId
== 0xffff) {
496 if ((PciIoDevice
->Pci
.Hdr
.ClassCode
[2] == BadDeviceTable
[Index
].ClassCode
) &&
497 (PciIoDevice
->Pci
.Hdr
.ClassCode
[1] == BadDeviceTable
[Index
].SubClassCode
) &&
498 (PciIoDevice
->Pci
.Hdr
.VendorId
== BadDeviceTable
[Index
].VendorId
)) {
499 InitBadBars(PciIo
,BadDeviceTable
[Index
].VendorId
,BadDeviceTable
[Index
].DeviceId
);
502 if ((PciIoDevice
->Pci
.Hdr
.ClassCode
[2] == BadDeviceTable
[Index
].ClassCode
) &&
503 (PciIoDevice
->Pci
.Hdr
.ClassCode
[1] == BadDeviceTable
[Index
].SubClassCode
) &&
504 (PciIoDevice
->Pci
.Hdr
.VendorId
== BadDeviceTable
[Index
].VendorId
) &&
505 (PciIoDevice
->Pci
.Hdr
.DeviceId
== BadDeviceTable
[Index
].DeviceId
)) {
507 InitBadBars(PciIo
,BadDeviceTable
[Index
].VendorId
,BadDeviceTable
[Index
].DeviceId
);