]>
Commit | Line | Data |
---|---|---|
04af8bf2 DG |
1 | /** @file\r |
2 | Scan the entire PCI bus for root bridges to support coreboot UEFI payload.\r | |
3 | \r | |
99de2e7e | 4 | Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>\r |
04af8bf2 DG |
5 | \r |
6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
7 | \r | |
8 | **/\r | |
9 | \r | |
10 | #include <PiDxe.h>\r | |
11 | #include <IndustryStandard/Pci.h>\r | |
12 | #include <Protocol/PciHostBridgeResourceAllocation.h>\r | |
13 | #include <Protocol/PciRootBridgeIo.h>\r | |
14 | #include <Library/BaseMemoryLib.h>\r | |
15 | #include <Library/DebugLib.h>\r | |
16 | #include <Library/MemoryAllocationLib.h>\r | |
17 | #include <Library/PciHostBridgeLib.h>\r | |
18 | #include <Library/PciLib.h>\r | |
19 | #include "PciHostBridge.h"\r | |
20 | \r | |
04af8bf2 DG |
21 | /**\r |
22 | Probe a bar is existed or not.\r | |
23 | \r | |
24 | @param[in] Address PCI address for the BAR.\r | |
25 | @param[out] OriginalValue The original bar value returned.\r | |
26 | @param[out] Value The probed bar value returned.\r | |
27 | **/\r | |
28 | STATIC\r | |
29 | VOID\r | |
30 | PcatPciRootBridgeBarExisted (\r | |
c248802e | 31 | IN UINTN Address,\r |
e5efcf8b MK |
32 | OUT UINT32 *OriginalValue,\r |
33 | OUT UINT32 *Value\r | |
34 | )\r | |
04af8bf2 | 35 | {\r |
04af8bf2 DG |
36 | //\r |
37 | // Preserve the original value\r | |
38 | //\r | |
c248802e | 39 | *OriginalValue = PciRead32 (Address);\r |
04af8bf2 DG |
40 | \r |
41 | //\r | |
42 | // Disable timer interrupt while the BAR is probed\r | |
43 | //\r | |
44 | DisableInterrupts ();\r | |
45 | \r | |
c248802e PR |
46 | PciWrite32 (Address, 0xFFFFFFFF);\r |
47 | *Value = PciRead32 (Address);\r | |
48 | PciWrite32 (Address, *OriginalValue);\r | |
04af8bf2 DG |
49 | \r |
50 | //\r | |
51 | // Enable interrupt\r | |
52 | //\r | |
53 | EnableInterrupts ();\r | |
54 | }\r | |
55 | \r | |
56 | /**\r | |
57 | Parse PCI bar and collect the assigned PCI resource information.\r | |
58 | \r | |
59 | @param[in] Command Supported attributes.\r | |
60 | \r | |
61 | @param[in] Bus PCI bus number.\r | |
62 | \r | |
63 | @param[in] Device PCI device number.\r | |
64 | \r | |
65 | @param[in] Function PCI function number.\r | |
66 | \r | |
67 | @param[in] BarOffsetBase PCI bar start offset.\r | |
68 | \r | |
69 | @param[in] BarOffsetEnd PCI bar end offset.\r | |
70 | \r | |
71 | @param[in] Io IO aperture.\r | |
72 | \r | |
73 | @param[in] Mem MMIO aperture.\r | |
74 | \r | |
75 | @param[in] MemAbove4G MMIO aperture above 4G.\r | |
76 | \r | |
77 | @param[in] PMem Prefetchable MMIO aperture.\r | |
78 | \r | |
79 | @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r | |
80 | **/\r | |
81 | STATIC\r | |
82 | VOID\r | |
83 | PcatPciRootBridgeParseBars (\r | |
e5efcf8b MK |
84 | IN UINT16 Command,\r |
85 | IN UINTN Bus,\r | |
86 | IN UINTN Device,\r | |
87 | IN UINTN Function,\r | |
88 | IN UINTN BarOffsetBase,\r | |
89 | IN UINTN BarOffsetEnd,\r | |
90 | IN PCI_ROOT_BRIDGE_APERTURE *Io,\r | |
91 | IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r | |
c248802e | 92 | IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G\r |
e5efcf8b MK |
93 | \r |
94 | )\r | |
04af8bf2 | 95 | {\r |
e5efcf8b MK |
96 | UINT32 OriginalValue;\r |
97 | UINT32 Value;\r | |
98 | UINT32 OriginalUpperValue;\r | |
99 | UINT32 UpperValue;\r | |
100 | UINT64 Mask;\r | |
101 | UINTN Offset;\r | |
102 | UINTN LowBit;\r | |
103 | UINT64 Base;\r | |
104 | UINT64 Length;\r | |
105 | UINT64 Limit;\r | |
106 | PCI_ROOT_BRIDGE_APERTURE *MemAperture;\r | |
04af8bf2 DG |
107 | \r |
108 | for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {\r | |
109 | PcatPciRootBridgeBarExisted (\r | |
110 | PCI_LIB_ADDRESS (Bus, Device, Function, Offset),\r | |
e5efcf8b MK |
111 | &OriginalValue,\r |
112 | &Value\r | |
113 | );\r | |
04af8bf2 DG |
114 | if (Value == 0) {\r |
115 | continue;\r | |
116 | }\r | |
e5efcf8b | 117 | \r |
04af8bf2 DG |
118 | if ((Value & BIT0) == BIT0) {\r |
119 | //\r | |
120 | // IO Bar\r | |
121 | //\r | |
6ef57974 | 122 | if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {\r |
e5efcf8b MK |
123 | Mask = 0xfffffffc;\r |
124 | Base = OriginalValue & Mask;\r | |
04af8bf2 DG |
125 | Length = ((~(Value & Mask)) & Mask) + 0x04;\r |
126 | if (!(Value & 0xFFFF0000)) {\r | |
127 | Length &= 0x0000FFFF;\r | |
128 | }\r | |
e5efcf8b | 129 | \r |
04af8bf2 DG |
130 | Limit = Base + Length - 1;\r |
131 | \r | |
132 | if ((Base > 0) && (Base < Limit)) {\r | |
133 | if (Io->Base > Base) {\r | |
134 | Io->Base = Base;\r | |
135 | }\r | |
e5efcf8b | 136 | \r |
04af8bf2 DG |
137 | if (Io->Limit < Limit) {\r |
138 | Io->Limit = Limit;\r | |
139 | }\r | |
140 | }\r | |
141 | }\r | |
142 | } else {\r | |
143 | //\r | |
144 | // Mem Bar\r | |
145 | //\r | |
6ef57974 | 146 | if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {\r |
e5efcf8b MK |
147 | Mask = 0xfffffff0;\r |
148 | Base = OriginalValue & Mask;\r | |
04af8bf2 DG |
149 | Length = Value & Mask;\r |
150 | \r | |
151 | if ((Value & (BIT1 | BIT2)) == 0) {\r | |
152 | //\r | |
153 | // 32bit\r | |
154 | //\r | |
155 | Length = ((~Length) + 1) & 0xffffffff;\r | |
156 | \r | |
c248802e | 157 | MemAperture = Mem;\r |
04af8bf2 DG |
158 | } else {\r |
159 | //\r | |
160 | // 64bit\r | |
161 | //\r | |
162 | Offset += 4;\r | |
163 | PcatPciRootBridgeBarExisted (\r | |
164 | PCI_LIB_ADDRESS (Bus, Device, Function, Offset),\r | |
165 | &OriginalUpperValue,\r | |
166 | &UpperValue\r | |
e5efcf8b | 167 | );\r |
04af8bf2 | 168 | \r |
e5efcf8b MK |
169 | Base = Base | LShiftU64 ((UINT64)OriginalUpperValue, 32);\r |
170 | Length = Length | LShiftU64 ((UINT64)UpperValue, 32);\r | |
04af8bf2 DG |
171 | if (Length != 0) {\r |
172 | LowBit = LowBitSet64 (Length);\r | |
173 | Length = LShiftU64 (1ULL, LowBit);\r | |
174 | }\r | |
175 | \r | |
c248802e PR |
176 | if (Base < BASE_4GB) {\r |
177 | MemAperture = Mem;\r | |
04af8bf2 DG |
178 | } else {\r |
179 | MemAperture = MemAbove4G;\r | |
180 | }\r | |
181 | }\r | |
182 | \r | |
183 | Limit = Base + Length - 1;\r | |
184 | if ((Base > 0) && (Base < Limit)) {\r | |
185 | if (MemAperture->Base > Base) {\r | |
186 | MemAperture->Base = Base;\r | |
187 | }\r | |
e5efcf8b | 188 | \r |
04af8bf2 DG |
189 | if (MemAperture->Limit < Limit) {\r |
190 | MemAperture->Limit = Limit;\r | |
191 | }\r | |
192 | }\r | |
193 | }\r | |
194 | }\r | |
195 | }\r | |
196 | }\r | |
197 | \r | |
c248802e PR |
198 | STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };\r |
199 | \r | |
04af8bf2 DG |
200 | /**\r |
201 | Scan for all root bridges in platform.\r | |
202 | \r | |
203 | @param[out] NumberOfRootBridges Number of root bridges detected\r | |
204 | \r | |
205 | @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.\r | |
206 | **/\r | |
207 | PCI_ROOT_BRIDGE *\r | |
208 | ScanForRootBridges (\r | |
e5efcf8b MK |
209 | OUT UINTN *NumberOfRootBridges\r |
210 | )\r | |
04af8bf2 | 211 | {\r |
e5efcf8b MK |
212 | UINTN PrimaryBus;\r |
213 | UINTN SubBus;\r | |
214 | UINT8 Device;\r | |
215 | UINT8 Function;\r | |
216 | UINTN NumberOfDevices;\r | |
217 | UINTN Address;\r | |
218 | PCI_TYPE01 Pci;\r | |
219 | UINT64 Attributes;\r | |
220 | UINT64 Base;\r | |
221 | UINT64 Limit;\r | |
222 | UINT64 Value;\r | |
223 | PCI_ROOT_BRIDGE_APERTURE Io;\r | |
224 | PCI_ROOT_BRIDGE_APERTURE Mem;\r | |
225 | PCI_ROOT_BRIDGE_APERTURE MemAbove4G;\r | |
e5efcf8b MK |
226 | PCI_ROOT_BRIDGE_APERTURE *MemAperture;\r |
227 | PCI_ROOT_BRIDGE *RootBridges;\r | |
228 | UINTN BarOffsetEnd;\r | |
04af8bf2 DG |
229 | \r |
230 | *NumberOfRootBridges = 0;\r | |
e5efcf8b | 231 | RootBridges = NULL;\r |
04af8bf2 DG |
232 | \r |
233 | //\r | |
234 | // After scanning all the PCI devices on the PCI root bridge's primary bus,\r | |
235 | // update the Primary Bus Number for the next PCI root bridge to be this PCI\r | |
236 | // root bridge's subordinate bus number + 1.\r | |
237 | //\r | |
238 | for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {\r | |
e5efcf8b | 239 | SubBus = PrimaryBus;\r |
04af8bf2 DG |
240 | Attributes = 0;\r |
241 | \r | |
242 | ZeroMem (&Io, sizeof (Io));\r | |
243 | ZeroMem (&Mem, sizeof (Mem));\r | |
244 | ZeroMem (&MemAbove4G, sizeof (MemAbove4G));\r | |
c248802e | 245 | Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;\r |
04af8bf2 DG |
246 | //\r |
247 | // Scan all the PCI devices on the primary bus of the PCI root bridge\r | |
248 | //\r | |
249 | for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {\r | |
04af8bf2 | 250 | for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {\r |
04af8bf2 DG |
251 | //\r |
252 | // Compute the PCI configuration address of the PCI device to probe\r | |
253 | //\r | |
254 | Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);\r | |
255 | \r | |
256 | //\r | |
257 | // Read the Vendor ID from the PCI Configuration Header\r | |
258 | //\r | |
259 | if (PciRead16 (Address) == MAX_UINT16) {\r | |
260 | if (Function == 0) {\r | |
261 | //\r | |
262 | // If the PCI Configuration Read fails, or a PCI device does not\r | |
263 | // exist, then skip this entire PCI device\r | |
264 | //\r | |
265 | break;\r | |
266 | } else {\r | |
267 | //\r | |
268 | // If PCI function != 0, VendorId == 0xFFFF, we continue to search\r | |
269 | // PCI function.\r | |
270 | //\r | |
271 | continue;\r | |
272 | }\r | |
273 | }\r | |
274 | \r | |
275 | //\r | |
276 | // Read the entire PCI Configuration Header\r | |
277 | //\r | |
278 | PciReadBuffer (Address, sizeof (Pci), &Pci);\r | |
279 | \r | |
280 | //\r | |
281 | // Increment the number of PCI device found on the primary bus of the\r | |
282 | // PCI root bridge\r | |
283 | //\r | |
284 | NumberOfDevices++;\r | |
285 | \r | |
286 | //\r | |
287 | // Look for devices with the VGA Palette Snoop enabled in the COMMAND\r | |
288 | // register of the PCI Config Header\r | |
289 | //\r | |
290 | if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r | |
291 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r | |
292 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r | |
293 | }\r | |
294 | \r | |
295 | BarOffsetEnd = 0;\r | |
296 | \r | |
297 | //\r | |
298 | // PCI-PCI Bridge\r | |
299 | //\r | |
300 | if (IS_PCI_BRIDGE (&Pci)) {\r | |
301 | //\r | |
302 | // Get the Bus range that the PPB is decoding\r | |
303 | //\r | |
304 | if (Pci.Bridge.SubordinateBus > SubBus) {\r | |
305 | //\r | |
306 | // If the subordinate bus number of the PCI-PCI bridge is greater\r | |
307 | // than the PCI root bridge's current subordinate bus number,\r | |
308 | // then update the PCI root bridge's subordinate bus number\r | |
309 | //\r | |
310 | SubBus = Pci.Bridge.SubordinateBus;\r | |
311 | }\r | |
312 | \r | |
313 | //\r | |
314 | // Get the I/O range that the PPB is decoding\r | |
315 | //\r | |
316 | Value = Pci.Bridge.IoBase & 0x0f;\r | |
e5efcf8b MK |
317 | Base = ((UINT32)Pci.Bridge.IoBase & 0xf0) << 8;\r |
318 | Limit = (((UINT32)Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;\r | |
04af8bf2 | 319 | if (Value == BIT0) {\r |
e5efcf8b MK |
320 | Base |= ((UINT32)Pci.Bridge.IoBaseUpper16 << 16);\r |
321 | Limit |= ((UINT32)Pci.Bridge.IoLimitUpper16 << 16);\r | |
04af8bf2 | 322 | }\r |
e5efcf8b | 323 | \r |
04af8bf2 DG |
324 | if ((Base > 0) && (Base < Limit)) {\r |
325 | if (Io.Base > Base) {\r | |
326 | Io.Base = Base;\r | |
327 | }\r | |
e5efcf8b | 328 | \r |
04af8bf2 DG |
329 | if (Io.Limit < Limit) {\r |
330 | Io.Limit = Limit;\r | |
331 | }\r | |
332 | }\r | |
333 | \r | |
334 | //\r | |
335 | // Get the Memory range that the PPB is decoding\r | |
336 | //\r | |
e5efcf8b MK |
337 | Base = ((UINT32)Pci.Bridge.MemoryBase & 0xfff0) << 16;\r |
338 | Limit = (((UINT32)Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;\r | |
04af8bf2 DG |
339 | if ((Base > 0) && (Base < Limit)) {\r |
340 | if (Mem.Base > Base) {\r | |
341 | Mem.Base = Base;\r | |
342 | }\r | |
e5efcf8b | 343 | \r |
04af8bf2 DG |
344 | if (Mem.Limit < Limit) {\r |
345 | Mem.Limit = Limit;\r | |
346 | }\r | |
347 | }\r | |
348 | \r | |
349 | //\r | |
350 | // Get the Prefetchable Memory range that the PPB is decoding\r | |
c248802e | 351 | // and merge it into Memory range\r |
04af8bf2 DG |
352 | //\r |
353 | Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;\r | |
e5efcf8b MK |
354 | Base = ((UINT32)Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;\r |
355 | Limit = (((UINT32)Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)\r | |
04af8bf2 | 356 | << 16) | 0xfffff;\r |
c248802e | 357 | MemAperture = &Mem;\r |
04af8bf2 | 358 | if (Value == BIT0) {\r |
e5efcf8b MK |
359 | Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);\r |
360 | Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);\r | |
c248802e | 361 | MemAperture = &MemAbove4G;\r |
04af8bf2 | 362 | }\r |
e5efcf8b | 363 | \r |
04af8bf2 DG |
364 | if ((Base > 0) && (Base < Limit)) {\r |
365 | if (MemAperture->Base > Base) {\r | |
366 | MemAperture->Base = Base;\r | |
367 | }\r | |
e5efcf8b | 368 | \r |
04af8bf2 DG |
369 | if (MemAperture->Limit < Limit) {\r |
370 | MemAperture->Limit = Limit;\r | |
371 | }\r | |
372 | }\r | |
373 | \r | |
374 | //\r | |
375 | // Look at the PPB Configuration for legacy decoding attributes\r | |
376 | //\r | |
377 | if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)\r | |
e5efcf8b MK |
378 | == EFI_PCI_BRIDGE_CONTROL_ISA)\r |
379 | {\r | |
04af8bf2 DG |
380 | Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r |
381 | Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;\r | |
382 | Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r | |
383 | }\r | |
e5efcf8b | 384 | \r |
04af8bf2 | 385 | if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)\r |
e5efcf8b MK |
386 | == EFI_PCI_BRIDGE_CONTROL_VGA)\r |
387 | {\r | |
04af8bf2 DG |
388 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r |
389 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r | |
390 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r | |
391 | if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)\r | |
e5efcf8b MK |
392 | != 0)\r |
393 | {\r | |
04af8bf2 DG |
394 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r |
395 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;\r | |
396 | }\r | |
397 | }\r | |
398 | \r | |
399 | BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);\r | |
400 | } else {\r | |
401 | //\r | |
402 | // Parse the BARs of the PCI device to get what I/O Ranges, Memory\r | |
403 | // Ranges, and Prefetchable Memory Ranges the device is decoding\r | |
404 | //\r | |
405 | if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {\r | |
406 | BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);\r | |
407 | }\r | |
408 | }\r | |
409 | \r | |
410 | PcatPciRootBridgeParseBars (\r | |
411 | Pci.Hdr.Command,\r | |
412 | PrimaryBus,\r | |
413 | Device,\r | |
414 | Function,\r | |
415 | OFFSET_OF (PCI_TYPE00, Device.Bar),\r | |
416 | BarOffsetEnd,\r | |
417 | &Io,\r | |
e5efcf8b | 418 | &Mem,\r |
c248802e | 419 | &MemAbove4G\r |
e5efcf8b | 420 | );\r |
04af8bf2 DG |
421 | \r |
422 | //\r | |
423 | // See if the PCI device is an IDE controller\r | |
424 | //\r | |
e5efcf8b MK |
425 | if (IS_CLASS2 (\r |
426 | &Pci,\r | |
427 | PCI_CLASS_MASS_STORAGE,\r | |
428 | PCI_CLASS_MASS_STORAGE_IDE\r | |
429 | ))\r | |
430 | {\r | |
04af8bf2 DG |
431 | if (Pci.Hdr.ClassCode[0] & 0x80) {\r |
432 | Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r | |
433 | Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r | |
434 | }\r | |
e5efcf8b | 435 | \r |
04af8bf2 DG |
436 | if (Pci.Hdr.ClassCode[0] & 0x01) {\r |
437 | Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r | |
438 | }\r | |
e5efcf8b | 439 | \r |
04af8bf2 DG |
440 | if (Pci.Hdr.ClassCode[0] & 0x04) {\r |
441 | Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r | |
442 | }\r | |
443 | }\r | |
444 | \r | |
445 | //\r | |
446 | // See if the PCI device is a legacy VGA controller or\r | |
447 | // a standard VGA controller\r | |
448 | //\r | |
449 | if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||\r | |
450 | IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)\r | |
e5efcf8b MK |
451 | )\r |
452 | {\r | |
04af8bf2 DG |
453 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r |
454 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r | |
455 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r | |
456 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r | |
457 | Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;\r | |
458 | }\r | |
459 | \r | |
460 | //\r | |
461 | // See if the PCI Device is a PCI - ISA or PCI - EISA\r | |
462 | // or ISA_POSITIVE_DECODE Bridge device\r | |
463 | //\r | |
464 | if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {\r | |
e5efcf8b MK |
465 | if ((Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) ||\r |
466 | (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA) ||\r | |
467 | (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE))\r | |
468 | {\r | |
04af8bf2 DG |
469 | Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r |
470 | Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;\r | |
471 | Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r | |
472 | }\r | |
473 | }\r | |
474 | \r | |
475 | //\r | |
476 | // If this device is not a multi function device, then skip the rest\r | |
477 | // of this PCI device\r | |
478 | //\r | |
e5efcf8b | 479 | if ((Function == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {\r |
04af8bf2 DG |
480 | break;\r |
481 | }\r | |
482 | }\r | |
483 | }\r | |
484 | \r | |
485 | //\r | |
486 | // If at least one PCI device was found on the primary bus of this PCI\r | |
487 | // root bridge, then the PCI root bridge exists.\r | |
488 | //\r | |
489 | if (NumberOfDevices > 0) {\r | |
490 | RootBridges = ReallocatePool (\r | |
491 | (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),\r | |
492 | (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),\r | |
493 | RootBridges\r | |
e5efcf8b | 494 | );\r |
04af8bf2 DG |
495 | ASSERT (RootBridges != NULL);\r |
496 | \r | |
04af8bf2 | 497 | InitRootBridge (\r |
e5efcf8b MK |
498 | Attributes,\r |
499 | Attributes,\r | |
500 | 0,\r | |
501 | (UINT8)PrimaryBus,\r | |
502 | (UINT8)SubBus,\r | |
503 | &Io,\r | |
504 | &Mem,\r | |
505 | &MemAbove4G,\r | |
c248802e PR |
506 | &mNonExistAperture,\r |
507 | &mNonExistAperture,\r | |
04af8bf2 | 508 | &RootBridges[*NumberOfRootBridges]\r |
e5efcf8b | 509 | );\r |
04af8bf2 DG |
510 | RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;\r |
511 | //\r | |
512 | // Increment the index for the next PCI Root Bridge\r | |
513 | //\r | |
514 | (*NumberOfRootBridges)++;\r | |
515 | }\r | |
516 | }\r | |
517 | \r | |
518 | return RootBridges;\r | |
519 | }\r | |
99de2e7e ZL |
520 | \r |
521 | /**\r | |
522 | Scan for all root bridges from Universal Payload PciRootBridgeInfoHob\r | |
523 | \r | |
524 | @param[in] PciRootBridgeInfo Pointer of Universal Payload PCI Root Bridge Info Hob\r | |
525 | @param[out] NumberOfRootBridges Number of root bridges detected\r | |
526 | \r | |
527 | @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array.\r | |
528 | \r | |
529 | **/\r | |
530 | PCI_ROOT_BRIDGE *\r | |
531 | RetrieveRootBridgeInfoFromHob (\r | |
532 | IN UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo,\r | |
533 | OUT UINTN *NumberOfRootBridges\r | |
e5efcf8b | 534 | )\r |
99de2e7e | 535 | {\r |
e5efcf8b MK |
536 | PCI_ROOT_BRIDGE *PciRootBridges;\r |
537 | UINTN Size;\r | |
538 | UINT8 Index;\r | |
99de2e7e ZL |
539 | \r |
540 | ASSERT (PciRootBridgeInfo != NULL);\r | |
541 | ASSERT (NumberOfRootBridges != NULL);\r | |
542 | if (PciRootBridgeInfo == NULL) {\r | |
543 | return NULL;\r | |
544 | }\r | |
e5efcf8b | 545 | \r |
99de2e7e ZL |
546 | if (PciRootBridgeInfo->Count == 0) {\r |
547 | return NULL;\r | |
548 | }\r | |
e5efcf8b MK |
549 | \r |
550 | Size = PciRootBridgeInfo->Count * sizeof (PCI_ROOT_BRIDGE);\r | |
551 | PciRootBridges = (PCI_ROOT_BRIDGE *)AllocatePool (Size);\r | |
99de2e7e ZL |
552 | ASSERT (PciRootBridges != NULL);\r |
553 | if (PciRootBridges == NULL) {\r | |
554 | return NULL;\r | |
555 | }\r | |
e5efcf8b | 556 | \r |
99de2e7e ZL |
557 | ZeroMem (PciRootBridges, PciRootBridgeInfo->Count * sizeof (PCI_ROOT_BRIDGE));\r |
558 | \r | |
559 | //\r | |
560 | // Create all root bridges with PciRootBridgeInfoHob\r | |
561 | //\r | |
562 | for (Index = 0; Index < PciRootBridgeInfo->Count; Index++) {\r | |
563 | PciRootBridges[Index].Segment = PciRootBridgeInfo->RootBridge[Index].Segment;\r | |
564 | PciRootBridges[Index].Supports = PciRootBridgeInfo->RootBridge[Index].Supports;\r | |
565 | PciRootBridges[Index].Attributes = PciRootBridgeInfo->RootBridge[Index].Attributes;\r | |
566 | PciRootBridges[Index].DmaAbove4G = PciRootBridgeInfo->RootBridge[Index].DmaAbove4G;\r | |
567 | PciRootBridges[Index].NoExtendedConfigSpace = PciRootBridgeInfo->RootBridge[Index].NoExtendedConfigSpace;\r | |
568 | PciRootBridges[Index].ResourceAssigned = PciRootBridgeInfo->ResourceAssigned;\r | |
569 | PciRootBridges[Index].AllocationAttributes = PciRootBridgeInfo->RootBridge[Index].AllocationAttributes;\r | |
e5efcf8b MK |
570 | PciRootBridges[Index].DevicePath = CreateRootBridgeDevicePath (PciRootBridgeInfo->RootBridge[Index].HID, PciRootBridgeInfo->RootBridge[Index].UID);\r |
571 | CopyMem (&PciRootBridges[Index].Bus, &PciRootBridgeInfo->RootBridge[Index].Bus, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r | |
572 | CopyMem (&PciRootBridges[Index].Io, &PciRootBridgeInfo->RootBridge[Index].Io, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r | |
573 | CopyMem (&PciRootBridges[Index].Mem, &PciRootBridgeInfo->RootBridge[Index].Mem, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r | |
574 | CopyMem (&PciRootBridges[Index].MemAbove4G, &PciRootBridgeInfo->RootBridge[Index].MemAbove4G, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r | |
575 | CopyMem (&PciRootBridges[Index].PMem, &PciRootBridgeInfo->RootBridge[Index].PMem, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r | |
576 | CopyMem (&PciRootBridges[Index].PMemAbove4G, &PciRootBridgeInfo->RootBridge[Index].PMemAbove4G, sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE_APERTURE));\r | |
99de2e7e ZL |
577 | }\r |
578 | \r | |
579 | *NumberOfRootBridges = PciRootBridgeInfo->Count;\r | |
580 | \r | |
581 | //\r | |
582 | // Now, this library only supports RootBridge that ResourceAssigned is True\r | |
583 | //\r | |
584 | if (PciRootBridgeInfo->ResourceAssigned) {\r | |
585 | PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);\r | |
586 | } else {\r | |
587 | DEBUG ((DEBUG_ERROR, "There is root bridge whose ResourceAssigned is FALSE\n"));\r | |
588 | PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);\r | |
589 | return NULL;\r | |
590 | }\r | |
591 | \r | |
592 | return PciRootBridges;\r | |
593 | }\r |