2 Scan the entire PCI bus for root bridges to support OVMF above Xen.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
12 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <IndustryStandard/Pci.h>
18 #include <IndustryStandard/Q35MchIch9.h>
20 #include <Protocol/PciHostBridgeResourceAllocation.h>
21 #include <Protocol/PciRootBridgeIo.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/DebugLib.h>
25 #include <Library/MemoryAllocationLib.h>
26 #include <Library/PciHostBridgeLib.h>
27 #include <Library/PciLib.h>
28 #include "PciHostBridge.h"
32 PcatPciRootBridgeBarExisted (
34 OUT UINT32
*OriginalValue
,
39 // Preserve the original value
41 *OriginalValue
= PciRead32 (Address
);
44 // Disable timer interrupt while the BAR is probed
48 PciWrite32 (Address
, 0xFFFFFFFF);
49 *Value
= PciRead32 (Address
);
50 PciWrite32 (Address
, *OriginalValue
);
60 PcatPciRootBridgeParseBars (
65 IN UINTN BarOffsetBase
,
66 IN UINTN BarOffsetEnd
,
67 IN PCI_ROOT_BRIDGE_APERTURE
*Io
,
68 IN PCI_ROOT_BRIDGE_APERTURE
*Mem
,
69 IN PCI_ROOT_BRIDGE_APERTURE
*MemAbove4G
,
70 IN PCI_ROOT_BRIDGE_APERTURE
*PMem
,
71 IN PCI_ROOT_BRIDGE_APERTURE
*PMemAbove4G
77 UINT32 OriginalUpperValue
;
84 PCI_ROOT_BRIDGE_APERTURE
*MemAperture
;
86 for (Offset
= BarOffsetBase
; Offset
< BarOffsetEnd
; Offset
+= sizeof (UINT32
)) {
87 PcatPciRootBridgeBarExisted (
88 PCI_LIB_ADDRESS (Bus
, Device
, Function
, Offset
),
89 &OriginalValue
, &Value
94 if ((Value
& BIT0
) == BIT0
) {
98 if (Command
& EFI_PCI_COMMAND_IO_SPACE
) {
100 Base
= OriginalValue
& Mask
;
101 Length
= ((~(Value
& Mask
)) & Mask
) + 0x04;
102 if (!(Value
& 0xFFFF0000)) {
103 Length
&= 0x0000FFFF;
105 Limit
= Base
+ Length
- 1;
108 if (Io
->Base
> Base
) {
111 if (Io
->Limit
< Limit
) {
120 if (Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) {
123 Base
= OriginalValue
& Mask
;
124 Length
= Value
& Mask
;
126 if ((Value
& (BIT1
| BIT2
)) == 0) {
130 Length
= ((~Length
) + 1) & 0xffffffff;
132 if ((Value
& BIT3
) == BIT3
) {
142 PcatPciRootBridgeBarExisted (
143 PCI_LIB_ADDRESS (Bus
, Device
, Function
, Offset
),
148 Base
= Base
| LShiftU64 ((UINT64
) OriginalUpperValue
, 32);
149 Length
= Length
| LShiftU64 ((UINT64
) UpperValue
, 32);
150 Length
= (~Length
) + 1;
152 if ((Value
& BIT3
) == BIT3
) {
153 MemAperture
= PMemAbove4G
;
155 MemAperture
= MemAbove4G
;
159 Limit
= Base
+ Length
- 1;
161 if (MemAperture
->Base
> Base
) {
162 MemAperture
->Base
= Base
;
164 if (MemAperture
->Limit
< Limit
) {
165 MemAperture
->Limit
= Limit
;
175 UINTN
*NumberOfRootBridges
182 UINTN NumberOfDevices
;
189 PCI_ROOT_BRIDGE_APERTURE Io
, Mem
, MemAbove4G
, PMem
, PMemAbove4G
, *MemAperture
;
190 PCI_ROOT_BRIDGE
*RootBridges
;
194 *NumberOfRootBridges
= 0;
198 // After scanning all the PCI devices on the PCI root bridge's primary bus,
199 // update the Primary Bus Number for the next PCI root bridge to be this PCI
200 // root bridge's subordinate bus number + 1.
202 for (PrimaryBus
= 0; PrimaryBus
<= PCI_MAX_BUS
; PrimaryBus
= SubBus
+ 1) {
206 ZeroMem (&Io
, sizeof (Io
));
207 ZeroMem (&Mem
, sizeof (Mem
));
208 ZeroMem (&MemAbove4G
, sizeof (MemAbove4G
));
209 ZeroMem (&PMem
, sizeof (PMem
));
210 ZeroMem (&PMemAbove4G
, sizeof (PMemAbove4G
));
211 Io
.Base
= Mem
.Base
= MemAbove4G
.Base
= PMem
.Base
= PMemAbove4G
.Base
= MAX_UINT64
;
213 // Scan all the PCI devices on the primary bus of the PCI root bridge
215 for (Device
= 0, NumberOfDevices
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
217 for (Function
= 0; Function
<= PCI_MAX_FUNC
; Function
++) {
220 // Compute the PCI configuration address of the PCI device to probe
222 Address
= PCI_LIB_ADDRESS (PrimaryBus
, Device
, Function
, 0);
225 // Read the Vendor ID from the PCI Configuration Header
227 if (PciRead16 (Address
) == MAX_UINT16
) {
230 // If the PCI Configuration Read fails, or a PCI device does not
231 // exist, then skip this entire PCI device
236 // If PCI function != 0, VendorId == 0xFFFF, we continue to search
244 // Read the entire PCI Configuration Header
246 PciReadBuffer (Address
, sizeof (Pci
), &Pci
);
249 // Increment the number of PCI device found on the primary bus of the
255 // Look for devices with the VGA Palette Snoop enabled in the COMMAND
256 // register of the PCI Config Header
258 if ((Pci
.Hdr
.Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
259 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
260 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
268 if (IS_PCI_BRIDGE (&Pci
)) {
270 // Get the Bus range that the PPB is decoding
272 if (Pci
.Bridge
.SubordinateBus
> SubBus
) {
274 // If the suborinate bus number of the PCI-PCI bridge is greater
275 // than the PCI root bridge's current subordinate bus number,
276 // then update the PCI root bridge's subordinate bus number
278 SubBus
= Pci
.Bridge
.SubordinateBus
;
282 // Get the I/O range that the PPB is decoding
284 Value
= Pci
.Bridge
.IoBase
& 0x0f;
285 Base
= ((UINT32
) Pci
.Bridge
.IoBase
& 0xf0) << 8;
286 Limit
= (((UINT32
) Pci
.Bridge
.IoLimit
& 0xf0) << 8) | 0x0fff;
288 Base
|= ((UINT32
) Pci
.Bridge
.IoBaseUpper16
<< 16);
289 Limit
|= ((UINT32
) Pci
.Bridge
.IoLimitUpper16
<< 16);
292 if (Io
.Base
> Base
) {
295 if (Io
.Limit
< Limit
) {
301 // Get the Memory range that the PPB is decoding
303 Base
= ((UINT32
) Pci
.Bridge
.MemoryBase
& 0xfff0) << 16;
304 Limit
= (((UINT32
) Pci
.Bridge
.MemoryLimit
& 0xfff0) << 16) | 0xfffff;
306 if (Mem
.Base
> Base
) {
309 if (Mem
.Limit
< Limit
) {
315 // Get the Prefetchable Memory range that the PPB is decoding
317 Value
= Pci
.Bridge
.PrefetchableMemoryBase
& 0x0f;
318 Base
= ((UINT32
) Pci
.Bridge
.PrefetchableMemoryBase
& 0xfff0) << 16;
319 Limit
= (((UINT32
) Pci
.Bridge
.PrefetchableMemoryLimit
& 0xfff0)
323 Base
|= LShiftU64 (Pci
.Bridge
.PrefetchableBaseUpper32
, 32);
324 Limit
|= LShiftU64 (Pci
.Bridge
.PrefetchableLimitUpper32
, 32);
325 MemAperture
= &PMemAbove4G
;
328 if (MemAperture
->Base
> Base
) {
329 MemAperture
->Base
= Base
;
331 if (MemAperture
->Limit
< Limit
) {
332 MemAperture
->Limit
= Limit
;
337 // Look at the PPB Configuration for legacy decoding attributes
339 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
)
340 == EFI_PCI_BRIDGE_CONTROL_ISA
) {
341 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
342 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO_16
;
343 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
345 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
)
346 == EFI_PCI_BRIDGE_CONTROL_VGA
) {
347 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
348 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
349 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
350 if ((Pci
.Bridge
.BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
)
352 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
353 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO_16
;
357 BarOffsetEnd
= OFFSET_OF (PCI_TYPE01
, Bridge
.Bar
[2]);
360 // Parse the BARs of the PCI device to get what I/O Ranges, Memory
361 // Ranges, and Prefetchable Memory Ranges the device is decoding
363 if ((Pci
.Hdr
.HeaderType
& HEADER_LAYOUT_CODE
) == HEADER_TYPE_DEVICE
) {
364 BarOffsetEnd
= OFFSET_OF (PCI_TYPE00
, Device
.Bar
[6]);
368 PcatPciRootBridgeParseBars (
373 OFFSET_OF (PCI_TYPE00
, Device
.Bar
),
381 // See if the PCI device is an IDE controller
383 if (IS_CLASS2 (&Pci
, PCI_CLASS_MASS_STORAGE
,
384 PCI_CLASS_MASS_STORAGE_IDE
)) {
385 if (Pci
.Hdr
.ClassCode
[0] & 0x80) {
386 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
387 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
389 if (Pci
.Hdr
.ClassCode
[0] & 0x01) {
390 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
;
392 if (Pci
.Hdr
.ClassCode
[0] & 0x04) {
393 Attributes
|= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
;
398 // See if the PCI device is a legacy VGA controller or
399 // a standard VGA controller
401 if (IS_CLASS2 (&Pci
, PCI_CLASS_OLD
, PCI_CLASS_OLD_VGA
) ||
402 IS_CLASS2 (&Pci
, PCI_CLASS_DISPLAY
, PCI_CLASS_DISPLAY_VGA
)
404 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
;
405 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
;
406 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_MEMORY
;
407 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO
;
408 Attributes
|= EFI_PCI_ATTRIBUTE_VGA_IO_16
;
412 // See if the PCI Device is a PCI - ISA or PCI - EISA
413 // or ISA_POSITIVIE_DECODE Bridge device
415 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_BRIDGE
) {
416 if (Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA
||
417 Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_EISA
||
418 Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_BRIDGE_ISA_PDECODE
) {
419 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO
;
420 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_IO_16
;
421 Attributes
|= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
426 // If this device is not a multi function device, then skip the rest
427 // of this PCI device
429 if (Function
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
436 // If at least one PCI device was found on the primary bus of this PCI
437 // root bridge, then the PCI root bridge exists.
439 if (NumberOfDevices
> 0) {
440 RootBridges
= ReallocatePool (
441 (*NumberOfRootBridges
) * sizeof (PCI_ROOT_BRIDGE
),
442 (*NumberOfRootBridges
+ 1) * sizeof (PCI_ROOT_BRIDGE
),
445 ASSERT (RootBridges
!= NULL
);
447 Attributes
, Attributes
, 0,
448 (UINT8
) PrimaryBus
, (UINT8
) SubBus
,
449 &Io
, &Mem
, &MemAbove4G
, &PMem
, &PMemAbove4G
,
450 &RootBridges
[*NumberOfRootBridges
]
452 RootBridges
[*NumberOfRootBridges
].ResourceAssigned
= TRUE
;
454 // Increment the index for the next PCI Root Bridge
456 (*NumberOfRootBridges
)++;