3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. 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_IO_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 (&gEfiCpuIoProtocolGuid
, NULL
, &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
= 0xffffffffffffffff;
108 PrivateData
->Pmem32Base
= 0xffffffffffffffff;
109 PrivateData
->Mem64Base
= 0xffffffffffffffff;
110 PrivateData
->Pmem64Base
= 0xffffffffffffffff;
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
, (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 (
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 (UINT32
),
211 &PciConfigurationHeader
213 if (EFI_ERROR (Status
)) {
215 // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
221 // Increment the number of PCI device found on the primary bus of the PCI root bridge
223 NumberOfPciDevices
++;
226 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
228 if (PciConfigurationHeader
.Hdr
.Command
& 0x20) {
229 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
233 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
235 if (IS_PCI_BRIDGE(&PciConfigurationHeader
)) {
237 // Get the Bus range that the PPB is decoding
239 if (PciConfigurationHeader
.Bridge
.SubordinateBus
> PrivateData
->SubordinateBus
) {
241 // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
242 // current subordinate bus number, then update the PCI root bridge's subordinate bus number
244 PrivateData
->SubordinateBus
= PciConfigurationHeader
.Bridge
.SubordinateBus
;
248 // Get the I/O range that the PPB is decoding
250 Value
= PciConfigurationHeader
.Bridge
.IoBase
& 0x0f;
251 Base
= ((UINT32
)PciConfigurationHeader
.Bridge
.IoBase
& 0xf0) << 8;
252 Limit
= (((UINT32
)PciConfigurationHeader
.Bridge
.IoLimit
& 0xf0) << 8) | 0x0fff;
254 Base
|= ((UINT32
)PciConfigurationHeader
.Bridge
.IoBaseUpper16
<< 16);
255 Limit
|= ((UINT32
)PciConfigurationHeader
.Bridge
.IoLimitUpper16
<< 16);
258 if (PrivateData
->IoBase
> Base
) {
259 PrivateData
->IoBase
= Base
;
261 if (PrivateData
->IoLimit
< Limit
) {
262 PrivateData
->IoLimit
= Limit
;
267 // Get the Memory range that the PPB is decoding
269 Base
= ((UINT32
)PciConfigurationHeader
.Bridge
.MemoryBase
& 0xfff0) << 16;
270 Limit
= (((UINT32
)PciConfigurationHeader
.Bridge
.MemoryLimit
& 0xfff0) << 16) | 0xfffff;
272 if (PrivateData
->MemBase
> Base
) {
273 PrivateData
->MemBase
= Base
;
275 if (PrivateData
->MemLimit
< Limit
) {
276 PrivateData
->MemLimit
= Limit
;
278 if (PrivateData
->Mem32Base
> Base
) {
279 PrivateData
->Mem32Base
= Base
;
281 if (PrivateData
->Mem32Limit
< Limit
) {
282 PrivateData
->Mem32Limit
= Limit
;
287 // Get the Prefetchable Memory range that the PPB is decoding
289 Value
= PciConfigurationHeader
.Bridge
.PrefetchableMemoryBase
& 0x0f;
290 Base
= ((UINT32
)PciConfigurationHeader
.Bridge
.PrefetchableMemoryBase
& 0xfff0) << 16;
291 Limit
= (((UINT32
)PciConfigurationHeader
.Bridge
.PrefetchableMemoryLimit
& 0xfff0) << 16) | 0xffffff;
293 Base
|= LShiftU64((UINT64
)PciConfigurationHeader
.Bridge
.PrefetchableBaseUpper32
,32);
294 Limit
|= LShiftU64((UINT64
)PciConfigurationHeader
.Bridge
.PrefetchableLimitUpper32
,32);
297 if (PrivateData
->MemBase
> Base
) {
298 PrivateData
->MemBase
= Base
;
300 if (PrivateData
->MemLimit
< Limit
) {
301 PrivateData
->MemLimit
= Limit
;
304 if (PrivateData
->Pmem32Base
> Base
) {
305 PrivateData
->Pmem32Base
= Base
;
307 if (PrivateData
->Pmem32Limit
< Limit
) {
308 PrivateData
->Pmem32Limit
= Limit
;
312 if (PrivateData
->Pmem64Base
> Base
) {
313 PrivateData
->Pmem64Base
= Base
;
315 if (PrivateData
->Pmem64Limit
< Limit
) {
316 PrivateData
->Pmem64Limit
= Limit
;
322 // Look at the PPB Configuration for legacy decoding attributes
324 if (PciConfigurationHeader
.Bridge
.BridgeControl
& 0x04) {
325 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
326 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
328 if (PciConfigurationHeader
.Bridge
.BridgeControl
& 0x08) {
329 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
330 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
331 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
336 // Parse the BARs of the PCI device to determine what I/O Ranges,
337 // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
339 if ((PciConfigurationHeader
.Hdr
.HeaderType
& HEADER_LAYOUT_CODE
) == HEADER_TYPE_DEVICE
) {
340 Status
= PcatPciRootBridgeParseBars (
342 PciConfigurationHeader
.Hdr
.Command
,
350 // See if the PCI device is an IDE controller
352 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x01 &&
353 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ) {
354 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x80) {
355 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
356 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
358 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x01) {
359 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
361 if (PciConfigurationHeader
.Hdr
.ClassCode
[0] & 0x04) {
362 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
367 // See if the PCI device is a legacy VGA controller
369 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x00 &&
370 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ) {
371 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
372 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
373 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
377 // See if the PCI device is a standard VGA controller
379 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x03 &&
380 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x00 ) {
381 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
382 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
383 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
387 // See if the PCI Device is a PCI - ISA or PCI - EISA
388 // or ISA_POSITIVIE_DECODE Bridge device
390 if (PciConfigurationHeader
.Hdr
.ClassCode
[2] == 0x06) {
391 if (PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x01 ||
392 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x02 ||
393 PciConfigurationHeader
.Hdr
.ClassCode
[1] == 0x80 ) {
394 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
395 PrivateData
->Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
397 if (PrivateData
->MemBase
> 0xa0000) {
398 PrivateData
->MemBase
= 0xa0000;
400 if (PrivateData
->MemLimit
< 0xbffff) {
401 PrivateData
->MemLimit
= 0xbffff;
408 // If this device is not a multi function device, then skip the rest of this PCI device
410 if (Function
== 0 && !(PciConfigurationHeader
.Hdr
.HeaderType
& HEADER_TYPE_MULTI_FUNCTION
)) {
417 // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
418 // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
421 PrimaryBusIndex
= PrivateData
->SubordinateBus
+ 1;
424 // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
427 if (NumberOfPciDevices
> 0) {
430 // Adjust the I/O range used for bounds checking for the legacy decoding attributed
432 if (PrivateData
->Attributes
& 0x7f) {
433 PrivateData
->IoBase
= 0;
434 if (PrivateData
->IoLimit
< 0xffff) {
435 PrivateData
->IoLimit
= 0xffff;
440 // Adjust the Memory range used for bounds checking for the legacy decoding attributed
442 if (PrivateData
->Attributes
& EFI_PCI_ATTRIBUTE_VGA_MEMORY
) {
443 if (PrivateData
->MemBase
> 0xa0000) {
444 PrivateData
->MemBase
= 0xa0000;
446 if (PrivateData
->MemLimit
< 0xbffff) {
447 PrivateData
->MemLimit
= 0xbffff;
452 // Build ACPI descriptors for the resources on the PCI Root Bridge
454 Status
= ConstructConfiguration(PrivateData
);
455 ASSERT_EFI_ERROR (Status
);
458 // Create the handle for this PCI Root Bridge
460 Status
= gBS
->InstallMultipleProtocolInterfaces (
461 &PrivateData
->Handle
,
462 &gEfiDevicePathProtocolGuid
,
463 PrivateData
->DevicePath
,
464 &gEfiPciRootBridgeIoProtocolGuid
,
468 ASSERT_EFI_ERROR (Status
);
471 // Contruct DeviceIoProtocol
473 Status
= DeviceIoConstructor (
476 PrivateData
->DevicePath
,
477 (UINT16
)PrivateData
->PrimaryBus
,
478 (UINT16
)PrivateData
->SubordinateBus
480 ASSERT_EFI_ERROR (Status
);
483 // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
485 Status
= ScanPciRootBridgeForRoms(&PrivateData
->Io
);
488 // Increment the index for the next PCI Root Bridge
490 PciRootBridgeIndex
++;
495 // If no PCI Root Bridges were found on the current PCI segment, then exit
497 if (NumberOfPciRootBridges
== 0) {
498 Status
= EFI_SUCCESS
;
505 // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
506 // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
507 // Otherwise, the search is continued on the next PCI Root Bridge
509 if (PrimaryBusIndex
> PCI_MAX_BUS
) {
511 NumberOfPciRootBridges
= 0;
514 NumberOfPciRootBridges
++;
523 // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
526 if (PrivateData
->DevicePath
) {
527 gBS
->FreePool(PrivateData
->DevicePath
);
529 gBS
->FreePool (PrivateData
);
533 // If no PCI Root Bridges were discovered, then return the error condition from scanning the
534 // first PCI Root Bridge
536 if (PciRootBridgeIndex
== 0) {
544 ConstructConfiguration(
545 IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
562 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
563 EFI_ACPI_END_TAG_DESCRIPTOR
*ConfigurationEnd
;
566 PrivateData
->Configuration
= NULL
;
568 if (PrivateData
->SubordinateBus
>= PrivateData
->PrimaryBus
) {
571 if (PrivateData
->IoLimit
>= PrivateData
->IoBase
) {
574 if (PrivateData
->Mem32Limit
>= PrivateData
->Mem32Base
) {
577 if (PrivateData
->Pmem32Limit
>= PrivateData
->Pmem32Base
) {
580 if (PrivateData
->Mem64Limit
>= PrivateData
->Mem64Base
) {
583 if (PrivateData
->Pmem64Limit
>= PrivateData
->Pmem64Base
) {
587 if ( NumConfig
== 0 ) {
590 // If there is no resource request
592 Status
= gBS
->AllocatePool (
594 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
),
595 &PrivateData
->Configuration
597 if (EFI_ERROR (Status
)) {
601 Configuration
= PrivateData
->Configuration
;
605 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
608 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
609 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
612 ConfigurationEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Configuration
);
613 ConfigurationEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
614 ConfigurationEnd
->Checksum
= 0;
618 // If there is at least one type of resource request,
619 // allocate a acpi resource node
621 Status
= gBS
->AllocatePool (
623 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
),
624 &PrivateData
->Configuration
626 if (EFI_ERROR (Status
)) {
630 Configuration
= PrivateData
->Configuration
;
634 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
637 if (PrivateData
->SubordinateBus
>= PrivateData
->PrimaryBus
) {
638 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
639 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
640 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
641 Configuration
->SpecificFlag
= 0;
642 Configuration
->AddrRangeMin
= PrivateData
->PrimaryBus
;
643 Configuration
->AddrRangeMax
= PrivateData
->SubordinateBus
;
644 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
648 // Deal with io aperture
650 if (PrivateData
->IoLimit
>= PrivateData
->IoBase
) {
651 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
652 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
653 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
654 Configuration
->SpecificFlag
= 1; //non ISA range
655 Configuration
->AddrRangeMin
= PrivateData
->IoBase
;
656 Configuration
->AddrRangeMax
= PrivateData
->IoLimit
;
657 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
662 // Deal with mem32 aperture
664 if (PrivateData
->Mem32Limit
>= PrivateData
->Mem32Base
) {
665 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
666 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
667 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
668 Configuration
->SpecificFlag
= 0; //Nonprefechable
669 Configuration
->AddrSpaceGranularity
= 32; //32 bit
670 Configuration
->AddrRangeMin
= PrivateData
->Mem32Base
;
671 Configuration
->AddrRangeMax
= PrivateData
->Mem32Limit
;
672 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
677 // Deal with Pmem32 aperture
679 if (PrivateData
->Pmem32Limit
>= PrivateData
->Pmem32Base
) {
680 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
681 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
682 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
683 Configuration
->SpecificFlag
= 0x6; //prefechable
684 Configuration
->AddrSpaceGranularity
= 32; //32 bit
685 Configuration
->AddrRangeMin
= PrivateData
->Pmem32Base
;
686 Configuration
->AddrRangeMax
= PrivateData
->Pmem32Limit
;
687 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
692 // Deal with mem64 aperture
694 if (PrivateData
->Mem64Limit
>= PrivateData
->Mem64Base
) {
695 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
696 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
697 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
698 Configuration
->SpecificFlag
= 0; //nonprefechable
699 Configuration
->AddrSpaceGranularity
= 64; //32 bit
700 Configuration
->AddrRangeMin
= PrivateData
->Mem64Base
;
701 Configuration
->AddrRangeMax
= PrivateData
->Mem64Limit
;
702 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
707 // Deal with Pmem64 aperture
709 if (PrivateData
->Pmem64Limit
>= PrivateData
->Pmem64Base
) {
710 Configuration
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
711 Configuration
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
712 Configuration
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
713 Configuration
->SpecificFlag
= 0x06; //prefechable
714 Configuration
->AddrSpaceGranularity
= 64; //32 bit
715 Configuration
->AddrRangeMin
= PrivateData
->Pmem64Base
;
716 Configuration
->AddrRangeMax
= PrivateData
->Pmem64Limit
;
717 Configuration
->AddrLen
= Configuration
->AddrRangeMax
- Configuration
->AddrRangeMin
+ 1;
724 ConfigurationEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Configuration
);
725 ConfigurationEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
726 ConfigurationEnd
->Checksum
= 0;
732 PcatPciRootBridgeBarExisted (
733 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
,
735 OUT UINT32
*OriginalValue
,
755 // Preserve the original value
757 Status
= PrivateData
->Io
.Pci
.Read (
766 // Raise TPL to high level to disable timer interrupt while the BAR is probed
768 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
770 AllOnes
= 0xffffffff;
772 Status
= PrivateData
->Io
.Pci
.Write (
779 Status
= PrivateData
->Io
.Pci
.Read (
788 //Write back the original value
790 Status
= PrivateData
->Io
.Pci
.Write (
799 // Restore TPL to its original level
801 gBS
->RestoreTPL (OldTpl
);
804 return EFI_DEVICE_ERROR
;
810 PcatPciRootBridgeParseBars (
811 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
,
831 UINT32 OriginalValue
;
833 UINT32 OriginalUpperValue
;
841 for (Offset
= 0x10; Offset
< 0x28; Offset
+= 4) {
842 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, Offset
);
843 Status
= PcatPciRootBridgeBarExisted (
850 if (!EFI_ERROR (Status
)) {
851 if ( Value
& 0x01 ) {
852 if (Command
& 0x0001) {
857 Base
= OriginalValue
& Mask
;
858 Length
= ((~(Value
& Mask
)) & Mask
) + 0x04;
859 if (!(Value
& 0xFFFF0000)){
860 Length
&= 0x0000FFFF;
862 Limit
= Base
+ Length
- 1;
865 if (PrivateData
->IoBase
> Base
) {
866 PrivateData
->IoBase
= (UINT32
)Base
;
868 if (PrivateData
->IoLimit
< Limit
) {
869 PrivateData
->IoLimit
= (UINT32
)Limit
;
876 if (Command
& 0x0002) {
879 Base
= OriginalValue
& Mask
;
880 Length
= Value
& Mask
;
882 if ((Value
& 0x07) != 0x04) {
883 Length
= ((~Length
) + 1) & 0xffffffff;
886 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Function
, Offset
);
888 Status
= PcatPciRootBridgeBarExisted (
895 Base
= Base
| LShiftU64((UINT64
)OriginalUpperValue
,32);
896 Length
= Length
| LShiftU64((UINT64
)UpperValue
,32);
897 Length
= (~Length
) + 1;
900 Limit
= Base
+ Length
- 1;
903 if (PrivateData
->MemBase
> Base
) {
904 PrivateData
->MemBase
= Base
;
906 if (PrivateData
->MemLimit
< Limit
) {
907 PrivateData
->MemLimit
= Limit
;
910 switch (Value
&0x07) {
911 case 0x00: ////memory space; anywhere in 32 bit address space
913 if (PrivateData
->Pmem32Base
> Base
) {
914 PrivateData
->Pmem32Base
= Base
;
916 if (PrivateData
->Pmem32Limit
< Limit
) {
917 PrivateData
->Pmem32Limit
= Limit
;
920 if (PrivateData
->Mem32Base
> Base
) {
921 PrivateData
->Mem32Base
= Base
;
923 if (PrivateData
->Mem32Limit
< Limit
) {
924 PrivateData
->Mem32Limit
= Limit
;
928 case 0x04: //memory space; anywhere in 64 bit address space
930 if (PrivateData
->Pmem64Base
> Base
) {
931 PrivateData
->Pmem64Base
= Base
;
933 if (PrivateData
->Pmem64Limit
< Limit
) {
934 PrivateData
->Pmem64Limit
= Limit
;
937 if (PrivateData
->Mem64Base
> Base
) {
938 PrivateData
->Mem64Base
= Base
;
940 if (PrivateData
->Mem64Limit
< Limit
) {
941 PrivateData
->Mem64Limit
= Limit
;
955 GetPciExpressBaseAddressForRootBridge (
956 IN UINTN HostBridgeNumber
,
957 IN UINTN RootBridgeNumber
962 This routine is to get PciExpress Base Address for this RootBridge
965 HostBridgeNumber - The number of HostBridge
966 RootBridgeNumber - The number of RootBridge
969 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
973 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
*PciExpressBaseAddressInfo
;
979 EFI_PEI_HOB_POINTERS GuidHob
;
982 // Get Hob List from configuration table
984 Status
= EfiGetSystemConfigurationTable (&gEfiHobListGuid
, &HobList
);
985 if (EFI_ERROR (Status
)) {
990 // Get PciExpressAddressInfo Hob
992 PciExpressBaseAddressInfo
= NULL
;
994 GuidHob
.Raw
= GetNextGuidHob (&gEfiPciExpressBaseAddressGuid
, &HobList
);
995 if (GuidHob
.Raw
!= NULL
) {
996 PciExpressBaseAddressInfo
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
997 BufferSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
.Guid
);
1003 // Search the PciExpress Base Address in the Hob for current RootBridge
1005 Number
= (UINT32
)(BufferSize
/ sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
));
1006 for (Index
= 0; Index
< Number
; Index
++) {
1007 if ((PciExpressBaseAddressInfo
[Index
].HostBridgeNumber
== HostBridgeNumber
) &&
1008 (PciExpressBaseAddressInfo
[Index
].RootBridgeNumber
== RootBridgeNumber
)) {
1009 return PciExpressBaseAddressInfo
[Index
].PciExpressBaseAddress
;
1014 // Do not find the PciExpress Base Address in the Hob