3 Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 EFI PC-AT PCI Root Bridge Controller
21 #include "PcatPciRootBridge.h"
24 EFI_CPU_IO2_PROTOCOL
*gCpuIo
;
28 InitializePcatPciRootBridge (
29 IN EFI_HANDLE ImageHandle
,
30 IN EFI_SYSTEM_TABLE
*SystemTable
35 Initializes the PCI Root Bridge Controller
47 PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
48 UINTN PciSegmentIndex
;
49 UINTN PciRootBridgeIndex
;
50 UINTN PrimaryBusIndex
;
51 UINTN NumberOfPciRootBridges
;
52 UINTN NumberOfPciDevices
;
56 PCI_TYPE01 PciConfigurationHeader
;
63 // Initialize gCpuIo now since the chipset init code requires it.
65 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**)&gCpuIo
);
66 ASSERT_EFI_ERROR (Status
);
69 // Initialize variables required to search all PCI segments for PCI devices
72 PciRootBridgeIndex
= 0;
73 NumberOfPciRootBridges
= 0;
76 while (PciSegmentIndex
<= PCI_MAX_SEGMENT
) {
79 Status
= gBS
->AllocatePool(
81 sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE
),
84 if (EFI_ERROR (Status
)) {
88 ZeroMem (PrivateData
, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE
));
91 // Initialize the signature of the private data structure
93 PrivateData
->Signature
= PCAT_PCI_ROOT_BRIDGE_SIGNATURE
;
94 PrivateData
->Handle
= NULL
;
95 PrivateData
->DevicePath
= NULL
;
96 InitializeListHead (&PrivateData
->MapInfo
);
99 // Initialize the PCI root bridge number and the bus range for that root bridge
101 PrivateData
->RootBridgeNumber
= (UINT32
)PciRootBridgeIndex
;
102 PrivateData
->PrimaryBus
= (UINT32
)PrimaryBusIndex
;
103 PrivateData
->SubordinateBus
= (UINT32
)PrimaryBusIndex
;
105 PrivateData
->IoBase
= 0xffffffff;
106 PrivateData
->MemBase
= 0xffffffff;
107 PrivateData
->Mem32Base
= 0xffffffffffffffffULL
;
108 PrivateData
->Pmem32Base
= 0xffffffffffffffffULL
;
109 PrivateData
->Mem64Base
= 0xffffffffffffffffULL
;
110 PrivateData
->Pmem64Base
= 0xffffffffffffffffULL
;
113 // The default mechanism for performing PCI Configuration cycles is to
114 // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32.
115 // IPF uses SAL calls to perform PCI COnfiguration cycles
117 PrivateData
->PciAddress
= 0xCF8;
118 PrivateData
->PciData
= 0xCFC;
121 // Get the physical I/O base for performing PCI I/O cycles
122 // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
123 // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
125 Status
= PcatRootBridgeIoGetIoPortMapping (
126 &PrivateData
->PhysicalIoBase
,
127 &PrivateData
->PhysicalMemoryBase
129 if (EFI_ERROR (Status
)) {
134 // Get PCI Express Base Address
136 PrivateData
->PciExpressBaseAddress
= GetPciExpressBaseAddressForRootBridge (PciSegmentIndex
, PciRootBridgeIndex
);
137 if (PrivateData
->PciExpressBaseAddress
!= 0) {
138 DEBUG ((EFI_D_ERROR
, "PCIE Base - 0x%lx\n", PrivateData
->PciExpressBaseAddress
));
142 // Create a lock for performing PCI Configuration cycles
144 EfiInitializeLock (&PrivateData
->PciLock
, TPL_HIGH_LEVEL
);
147 // Initialize the attributes for this PCI root bridge
149 PrivateData
->Attributes
= 0;
152 // Build the EFI Device Path Protocol instance for this PCI Root Bridge
154 Status
= PcatRootBridgeDevicePathConstructor (&PrivateData
->DevicePath
, PciRootBridgeIndex
, (BOOLEAN
)((PrivateData
->PciExpressBaseAddress
!= 0) ? TRUE
: FALSE
));
155 if (EFI_ERROR (Status
)) {
160 // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
162 Status
= PcatRootBridgeIoConstructor (&PrivateData
->Io
, PciSegmentIndex
);
163 if (EFI_ERROR (Status
)) {
168 // Scan all the PCI devices on the primary bus of the PCI root bridge
170 for (Device
= 0, NumberOfPciDevices
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
172 for (Function
= 0; Function
<= PCI_MAX_FUNC
; Function
++) {
175 // Compute the PCI configuration address of the PCI device to probe
177 Address
= EFI_PCI_ADDRESS (PrimaryBusIndex
, Device
, Function
, 0);
180 // Read the Vendor ID from the PCI Configuration Header
182 Status
= PrivateData
->Io
.Pci
.Read (
186 sizeof (VendorId
) / sizeof (UINT16
),
189 if ((EFI_ERROR (Status
)) || ((VendorId
== 0xffff) && (Function
== 0))) {
191 // If the PCI Configuration Read fails, or a PCI device does not exist, then
192 // skip this entire PCI device
196 if (VendorId
== 0xffff) {
198 // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
204 // Read the entire PCI Configuration Header
206 Status
= PrivateData
->Io
.Pci
.Read (
210 sizeof (PciConfigurationHeader
) / sizeof (UINT16
),
211 &PciConfigurationHeader
213 if (EFI_ERROR (Status
)) {
215 // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
222 // Increment the number of PCI device found on the primary bus of the PCI root bridge
224 NumberOfPciDevices
++;
227 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
229 if (PciConfigurationHeader
.Hdr
.Command
& 0x20) {
230 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
234 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
236 if (IS_PCI_BRIDGE(&PciConfigurationHeader
)) {
238 // Get the Bus range that the PPB is decoding
240 if (PciConfigurationHeader
.Bridge
.SubordinateBus
> PrivateData
->SubordinateBus
) {
242 // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
243 // current subordinate bus number, then update the PCI root bridge's subordinate bus number
245 PrivateData
->SubordinateBus
= PciConfigurationHeader
.Bridge
.SubordinateBus
;
249 // Get the I/O range that the PPB is decoding
251 Value
= PciConfigurationHeader
.Bridge
.IoBase
& 0x0f;
252 Base
= ((UINT32
)PciConfigurationHeader
.Bridge
.IoBase
& 0xf0) << 8;
253 Limit
= (((UINT32
)PciConfigurationHeader
.Bridge
.IoLimit
& 0xf0) << 8) | 0x0fff;
255 Base
|= ((UINT32
)PciConfigurationHeader
.Bridge
.IoBaseUpper16
<< 16);
256 Limit
|= ((UINT32
)PciConfigurationHeader
.Bridge
.IoLimitUpper16
<< 16);
259 if (PrivateData
->IoBase
> Base
) {
260 PrivateData
->IoBase
= Base
;
262 if (PrivateData
->IoLimit
< Limit
) {
263 PrivateData
->IoLimit
= Limit
;
268 // Get the Memory range that the PPB is decoding
270 Base
= ((UINT32
)PciConfigurationHeader
.Bridge
.MemoryBase
& 0xfff0) << 16;
271 Limit
= (((UINT32
)PciConfigurationHeader
.Bridge
.MemoryLimit
& 0xfff0) << 16) | 0xfffff;
273 if (PrivateData
->MemBase
> Base
) {
274 PrivateData
->MemBase
= Base
;
276 if (PrivateData
->MemLimit
< Limit
) {
277 PrivateData
->MemLimit
= Limit
;
279 if (PrivateData
->Mem32Base
> Base
) {
280 PrivateData
->Mem32Base
= Base
;
282 if (PrivateData
->Mem32Limit
< Limit
) {
283 PrivateData
->Mem32Limit
= Limit
;
288 // Get the Prefetchable Memory range that the PPB is decoding
290 Value
= PciConfigurationHeader
.Bridge
.PrefetchableMemoryBase
& 0x0f;
291 Base
= ((UINT32
)PciConfigurationHeader
.Bridge
.PrefetchableMemoryBase
& 0xfff0) << 16;
292 Limit
= (((UINT32
)PciConfigurationHeader
.Bridge
.PrefetchableMemoryLimit
& 0xfff0) << 16) | 0xffffff;
294 Base
|= LShiftU64((UINT64
)PciConfigurationHeader
.Bridge
.PrefetchableBaseUpper32
,32);
295 Limit
|= LShiftU64((UINT64
)PciConfigurationHeader
.Bridge
.PrefetchableLimitUpper32
,32);
298 if (PrivateData
->MemBase
> Base
) {
299 PrivateData
->MemBase
= Base
;
301 if (PrivateData
->MemLimit
< Limit
) {
302 PrivateData
->MemLimit
= Limit
;
305 if (PrivateData
->Pmem32Base
> Base
) {
306 PrivateData
->Pmem32Base
= Base
;
308 if (PrivateData
->Pmem32Limit
< Limit
) {
309 PrivateData
->Pmem32Limit
= Limit
;
313 if (PrivateData
->Pmem64Base
> Base
) {
314 PrivateData
->Pmem64Base
= Base
;
316 if (PrivateData
->Pmem64Limit
< Limit
) {
317 PrivateData
->Pmem64Limit
= Limit
;
323 // Look at the PPB Configuration for legacy decoding attributes
325 if (PciConfigurationHeader
.Bridge
.BridgeControl
& 0x04) {
326 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
327 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
329 if (PciConfigurationHeader
.Bridge
.BridgeControl
& 0x08) {
330 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
331 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
332 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
337 // Parse the BARs of the PCI device to determine what I/O Ranges,
338 // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
340 if ((PciConfigurationHeader
.Hdr
.HeaderType
& HEADER_LAYOUT_CODE
) == HEADER_TYPE_DEVICE
) {
341 Status
= PcatPciRootBridgeParseBars (
343 PciConfigurationHeader
.Hdr
.Command
,
351 // See if the PCI device is an IDE controller
353 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x01 &&
354 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ) {
355 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x80) {
356 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
357 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
359 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x01) {
360 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
362 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x04) {
363 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
368 // See if the PCI device is a legacy VGA controller
370 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x00 &&
371 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ) {
372 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
373 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
374 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
378 // See if the PCI device is a standard VGA controller
380 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x03 &&
381 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x00 ) {
382 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
383 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
384 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
388 // See if the PCI Device is a PCI - ISA or PCI - EISA
389 // or ISA_POSITIVIE_DECODE Bridge device
391 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x06) {
392 if (PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ||
393 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x02 ||
394 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x80 ) {
395 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
396 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
398 if (PrivateData
->MemBase
> 0xa0000) {
399 PrivateData
->MemBase
= 0xa0000;
401 if (PrivateData
->MemLimit
< 0xbffff) {
402 PrivateData
->MemLimit
= 0xbffff;
409 // If this device is not a multi function device, then skip the rest of this PCI device
411 if (Function
== 0 && !(PciConfigurationHeader
.Hdr
.HeaderType
& HEADER_TYPE_MULTI_FUNCTION
)) {
418 // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
419 // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
422 PrimaryBusIndex
= PrivateData
->SubordinateBus
+ 1;
425 // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
428 if (NumberOfPciDevices
> 0) {
431 // Adjust the I/O range used for bounds checking for the legacy decoding attributed
433 if (PrivateData
->Attributes
& 0x7f) {
434 PrivateData
->IoBase
= 0;
435 if (PrivateData
->IoLimit
< 0xffff) {
436 PrivateData
->IoLimit
= 0xffff;
441 // Adjust the Memory range used for bounds checking for the legacy decoding attributed
443 if (PrivateData
->Attributes
& EFI_PCI_ATTRIBUTE_VGA_MEMORY
) {
444 if (PrivateData
->MemBase
> 0xa0000) {
445 PrivateData
->MemBase
= 0xa0000;
447 if (PrivateData
->MemLimit
< 0xbffff) {
448 PrivateData
->MemLimit
= 0xbffff;
453 // Build ACPI descriptors for the resources on the PCI Root Bridge
455 Status
= ConstructConfiguration(PrivateData
);
456 ASSERT_EFI_ERROR (Status
);
459 // Create the handle for this PCI Root Bridge
461 Status
= gBS
->InstallMultipleProtocolInterfaces (
462 &PrivateData
->Handle
,
463 &gEfiDevicePathProtocolGuid
,
464 PrivateData
->DevicePath
,
465 &gEfiPciRootBridgeIoProtocolGuid
,
469 ASSERT_EFI_ERROR (Status
);
472 // Contruct DeviceIoProtocol
474 Status
= DeviceIoConstructor (
477 PrivateData
->DevicePath
,
478 (UINT16
)PrivateData
->PrimaryBus
,
479 (UINT16
)PrivateData
->SubordinateBus
481 ASSERT_EFI_ERROR (Status
);
484 // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
486 Status
= ScanPciRootBridgeForRoms(&PrivateData
->Io
);
489 // Increment the index for the next PCI Root Bridge
491 PciRootBridgeIndex
++;
496 // If no PCI Root Bridges were found on the current PCI segment, then exit
498 if (NumberOfPciRootBridges
== 0) {
499 Status
= EFI_SUCCESS
;
506 // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
507 // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
508 // Otherwise, the search is continued on the next PCI Root Bridge
510 if (PrimaryBusIndex
> PCI_MAX_BUS
) {
512 NumberOfPciRootBridges
= 0;
515 NumberOfPciRootBridges
++;
524 // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
527 if (PrivateData
->DevicePath
) {
528 gBS
->FreePool(PrivateData
->DevicePath
);
530 gBS
->FreePool (PrivateData
);
534 // If no PCI Root Bridges were discovered, then return the error condition from scanning the
535 // first PCI Root Bridge
537 if (PciRootBridgeIndex
== 0) {
545 ConstructConfiguration(
546 IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
563 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
564 EFI_ACPI_END_TAG_DESCRIPTOR
*ConfigurationEnd
;
567 PrivateData
->Configuration
= NULL
;
569 if (PrivateData
->SubordinateBus
>= PrivateData
->PrimaryBus
) {
572 if (PrivateData
->IoLimit
>= PrivateData
->IoBase
) {
575 if (PrivateData
->Mem32Limit
>= PrivateData
->Mem32Base
) {
578 if (PrivateData
->Pmem32Limit
>= PrivateData
->Pmem32Base
) {
581 if (PrivateData
->Mem64Limit
>= PrivateData
->Mem64Base
) {
584 if (PrivateData
->Pmem64Limit
>= PrivateData
->Pmem64Base
) {
588 if ( NumConfig
== 0 ) {
591 // If there is no resource request
593 Status
= gBS
->AllocatePool (
595 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
),
596 (VOID
**)&PrivateData
->Configuration
598 if (EFI_ERROR (Status
)) {
602 Configuration
= PrivateData
->Configuration
;
606 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
609 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
610 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
613 ConfigurationEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Configuration
);
614 ConfigurationEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
615 ConfigurationEnd
->Checksum
= 0;
619 // If there is at least one type of resource request,
620 // allocate a acpi resource node
622 Status
= gBS
->AllocatePool (
624 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
),
625 (VOID
**)&PrivateData
->Configuration
627 if (EFI_ERROR (Status
)) {
631 Configuration
= PrivateData
->Configuration
;
635 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
638 if (PrivateData
->SubordinateBus
>= PrivateData
->PrimaryBus
) {
639 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
640 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
641 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
642 Configuration
->SpecificFlag
= 0;
643 Configuration
->AddrRangeMin
= PrivateData
->PrimaryBus
;
644 Configuration
->AddrRangeMax
= PrivateData
->SubordinateBus
;
645 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
649 // Deal with io aperture
651 if (PrivateData
->IoLimit
>= PrivateData
->IoBase
) {
652 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
653 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
654 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
655 Configuration
->SpecificFlag
= 1; //non ISA range
656 Configuration
->AddrRangeMin
= PrivateData
->IoBase
;
657 Configuration
->AddrRangeMax
= PrivateData
->IoLimit
;
658 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
663 // Deal with mem32 aperture
665 if (PrivateData
->Mem32Limit
>= PrivateData
->Mem32Base
) {
666 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
667 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
668 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
669 Configuration
->SpecificFlag
= 0; //Nonprefechable
670 Configuration
->AddrSpaceGranularity
= 32; //32 bit
671 Configuration
->AddrRangeMin
= PrivateData
->Mem32Base
;
672 Configuration
->AddrRangeMax
= PrivateData
->Mem32Limit
;
673 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
678 // Deal with Pmem32 aperture
680 if (PrivateData
->Pmem32Limit
>= PrivateData
->Pmem32Base
) {
681 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
682 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
683 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
684 Configuration
->SpecificFlag
= 0x6; //prefechable
685 Configuration
->AddrSpaceGranularity
= 32; //32 bit
686 Configuration
->AddrRangeMin
= PrivateData
->Pmem32Base
;
687 Configuration
->AddrRangeMax
= PrivateData
->Pmem32Limit
;
688 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
693 // Deal with mem64 aperture
695 if (PrivateData
->Mem64Limit
>= PrivateData
->Mem64Base
) {
696 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
697 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
698 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
699 Configuration
->SpecificFlag
= 0; //nonprefechable
700 Configuration
->AddrSpaceGranularity
= 64; //32 bit
701 Configuration
->AddrRangeMin
= PrivateData
->Mem64Base
;
702 Configuration
->AddrRangeMax
= PrivateData
->Mem64Limit
;
703 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
708 // Deal with Pmem64 aperture
710 if (PrivateData
->Pmem64Limit
>= PrivateData
->Pmem64Base
) {
711 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
712 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
713 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
714 Configuration
->SpecificFlag
= 0x06; //prefechable
715 Configuration
->AddrSpaceGranularity
= 64; //32 bit
716 Configuration
->AddrRangeMin
= PrivateData
->Pmem64Base
;
717 Configuration
->AddrRangeMax
= PrivateData
->Pmem64Limit
;
718 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
725 ConfigurationEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Configuration
);
726 ConfigurationEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
727 ConfigurationEnd
->Checksum
= 0;
733 PcatPciRootBridgeBarExisted (
734 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
,
736 OUT UINT32
*OriginalValue
,
756 // Preserve the original value
758 Status
= PrivateData
->Io
.Pci
.Read (
767 // Raise TPL to high level to disable timer interrupt while the BAR is probed
769 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
771 AllOnes
= 0xffffffff;
773 Status
= PrivateData
->Io
.Pci
.Write (
780 Status
= PrivateData
->Io
.Pci
.Read (
789 //Write back the original value
791 Status
= PrivateData
->Io
.Pci
.Write (
800 // Restore TPL to its original level
802 gBS
->RestoreTPL (OldTpl
);
805 return EFI_DEVICE_ERROR
;
811 PcatPciRootBridgeParseBars (
812 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
,
832 UINT32 OriginalValue
;
834 UINT32 OriginalUpperValue
;
842 for (Offset
= 0x10; Offset
< 0x28; Offset
+= 4) {
843 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, Offset
);
844 Status
= PcatPciRootBridgeBarExisted (
851 if (!EFI_ERROR (Status
)) {
852 if ( Value
& 0x01 ) {
853 if (Command
& 0x0001) {
858 Base
= OriginalValue
& Mask
;
859 Length
= ((~(Value
& Mask
)) & Mask
) + 0x04;
860 if (!(Value
& 0xFFFF0000)){
861 Length
&= 0x0000FFFF;
863 Limit
= Base
+ Length
- 1;
866 if (PrivateData
->IoBase
> Base
) {
867 PrivateData
->IoBase
= (UINT32
)Base
;
869 if (PrivateData
->IoLimit
< Limit
) {
870 PrivateData
->IoLimit
= (UINT32
)Limit
;
877 if (Command
& 0x0002) {
880 Base
= OriginalValue
& Mask
;
881 Length
= Value
& Mask
;
883 if ((Value
& 0x07) != 0x04) {
884 Length
= ((~Length
) + 1) & 0xffffffff;
887 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, Offset
);
889 Status
= PcatPciRootBridgeBarExisted (
896 Base
= Base
| LShiftU64((UINT64
)OriginalUpperValue
,32);
897 Length
= Length
| LShiftU64((UINT64
)UpperValue
,32);
898 Length
= (~Length
) + 1;
901 Limit
= Base
+ Length
- 1;
904 if (PrivateData
->MemBase
> Base
) {
905 PrivateData
->MemBase
= Base
;
907 if (PrivateData
->MemLimit
< Limit
) {
908 PrivateData
->MemLimit
= Limit
;
911 switch (Value
&0x07) {
912 case 0x00: ////memory space; anywhere in 32 bit address space
914 if (PrivateData
->Pmem32Base
> Base
) {
915 PrivateData
->Pmem32Base
= Base
;
917 if (PrivateData
->Pmem32Limit
< Limit
) {
918 PrivateData
->Pmem32Limit
= Limit
;
921 if (PrivateData
->Mem32Base
> Base
) {
922 PrivateData
->Mem32Base
= Base
;
924 if (PrivateData
->Mem32Limit
< Limit
) {
925 PrivateData
->Mem32Limit
= Limit
;
929 case 0x04: //memory space; anywhere in 64 bit address space
931 if (PrivateData
->Pmem64Base
> Base
) {
932 PrivateData
->Pmem64Base
= Base
;
934 if (PrivateData
->Pmem64Limit
< Limit
) {
935 PrivateData
->Pmem64Limit
= Limit
;
938 if (PrivateData
->Mem64Base
> Base
) {
939 PrivateData
->Mem64Base
= Base
;
941 if (PrivateData
->Mem64Limit
< Limit
) {
942 PrivateData
->Mem64Limit
= Limit
;
956 GetPciExpressBaseAddressForRootBridge (
957 IN UINTN HostBridgeNumber
,
958 IN UINTN RootBridgeNumber
963 This routine is to get PciExpress Base Address for this RootBridge
966 HostBridgeNumber - The number of HostBridge
967 RootBridgeNumber - The number of RootBridge
970 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
974 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
*PciExpressBaseAddressInfo
;
978 EFI_PEI_HOB_POINTERS GuidHob
;
981 // Get PciExpressAddressInfo Hob
983 PciExpressBaseAddressInfo
= NULL
;
985 GuidHob
.Raw
= GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid
);
986 if (GuidHob
.Raw
!= NULL
) {
987 PciExpressBaseAddressInfo
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
988 BufferSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
.Guid
);
994 // Search the PciExpress Base Address in the Hob for current RootBridge
996 Number
= (UINT32
)(BufferSize
/ sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
));
997 for (Index
= 0; Index
< Number
; Index
++) {
998 if ((PciExpressBaseAddressInfo
[Index
].HostBridgeNumber
== HostBridgeNumber
) &&
999 (PciExpressBaseAddressInfo
[Index
].RootBridgeNumber
== RootBridgeNumber
)) {
1000 return PciExpressBaseAddressInfo
[Index
].PciExpressBaseAddress
;
1005 // Do not find the PciExpress Base Address in the Hob