]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
OvmfPkg/Xen: Fix various typos
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeLib / XenSupport.c
CommitLineData
49effaf2
RN
1/** @file\r
2 Scan the entire PCI bus for root bridges to support OVMF above Xen.\r
3\r
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5\r
b26f0cf9 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
49effaf2
RN
7\r
8**/\r
9#include <PiDxe.h>\r
10\r
11#include <IndustryStandard/Pci.h>\r
12#include <IndustryStandard/Q35MchIch9.h>\r
13\r
14#include <Protocol/PciHostBridgeResourceAllocation.h>\r
15#include <Protocol/PciRootBridgeIo.h>\r
16\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/PciHostBridgeLib.h>\r
21#include <Library/PciLib.h>\r
22#include "PciHostBridge.h"\r
23\r
24STATIC\r
25VOID\r
26PcatPciRootBridgeBarExisted (\r
f982bb8d 27 IN UINTN Address,\r
49effaf2
RN
28 OUT UINT32 *OriginalValue,\r
29 OUT UINT32 *Value\r
30 )\r
31{\r
32 //\r
33 // Preserve the original value\r
34 //\r
35 *OriginalValue = PciRead32 (Address);\r
36\r
37 //\r
38 // Disable timer interrupt while the BAR is probed\r
39 //\r
40 DisableInterrupts ();\r
41\r
42 PciWrite32 (Address, 0xFFFFFFFF);\r
43 *Value = PciRead32 (Address);\r
44 PciWrite32 (Address, *OriginalValue);\r
45\r
46 //\r
47 // Enable interrupt\r
48 //\r
49 EnableInterrupts ();\r
50}\r
51\r
0c40c9c9
ID
52#define PCI_COMMAND_DECODE ((UINT16)(EFI_PCI_COMMAND_IO_SPACE | \\r
53 EFI_PCI_COMMAND_MEMORY_SPACE))\r
54STATIC\r
55VOID\r
56PcatPciRootBridgeDecodingDisable (\r
57 IN UINTN Address\r
58 )\r
59{\r
60 UINT16 Value;\r
61\r
62 Value = PciRead16 (Address);\r
63 if (Value & PCI_COMMAND_DECODE) {\r
64 PciWrite16 (Address, Value & ~(UINT32)PCI_COMMAND_DECODE);\r
65 }\r
66}\r
67\r
49effaf2
RN
68STATIC\r
69VOID\r
70PcatPciRootBridgeParseBars (\r
71 IN UINT16 Command,\r
72 IN UINTN Bus,\r
73 IN UINTN Device,\r
74 IN UINTN Function,\r
75 IN UINTN BarOffsetBase,\r
76 IN UINTN BarOffsetEnd,\r
77 IN PCI_ROOT_BRIDGE_APERTURE *Io,\r
78 IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r
27e4d6ae 79 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G\r
49effaf2
RN
80\r
81)\r
82{\r
83 UINT32 OriginalValue;\r
84 UINT32 Value;\r
85 UINT32 OriginalUpperValue;\r
86 UINT32 UpperValue;\r
87 UINT64 Mask;\r
88 UINTN Offset;\r
89 UINT64 Base;\r
90 UINT64 Length;\r
91 UINT64 Limit;\r
92 PCI_ROOT_BRIDGE_APERTURE *MemAperture;\r
93\r
0c40c9c9
ID
94 // Disable address decoding for every device before OVMF starts sizing it\r
95 PcatPciRootBridgeDecodingDisable (\r
96 PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET)\r
97 );\r
98\r
49effaf2
RN
99 for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {\r
100 PcatPciRootBridgeBarExisted (\r
101 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),\r
102 &OriginalValue, &Value\r
103 );\r
104 if (Value == 0) {\r
105 continue;\r
106 }\r
107 if ((Value & BIT0) == BIT0) {\r
108 //\r
109 // IO Bar\r
110 //\r
111 if (Command & EFI_PCI_COMMAND_IO_SPACE) {\r
112 Mask = 0xfffffffc;\r
113 Base = OriginalValue & Mask;\r
114 Length = ((~(Value & Mask)) & Mask) + 0x04;\r
115 if (!(Value & 0xFFFF0000)) {\r
116 Length &= 0x0000FFFF;\r
117 }\r
118 Limit = Base + Length - 1;\r
119\r
120 if (Base < Limit) {\r
121 if (Io->Base > Base) {\r
122 Io->Base = Base;\r
123 }\r
124 if (Io->Limit < Limit) {\r
125 Io->Limit = Limit;\r
126 }\r
127 }\r
128 }\r
129 } else {\r
130 //\r
131 // Mem Bar\r
132 //\r
133 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {\r
134\r
135 Mask = 0xfffffff0;\r
136 Base = OriginalValue & Mask;\r
137 Length = Value & Mask;\r
138\r
139 if ((Value & (BIT1 | BIT2)) == 0) {\r
140 //\r
141 // 32bit\r
142 //\r
143 Length = ((~Length) + 1) & 0xffffffff;\r
144\r
27e4d6ae 145 MemAperture = Mem;\r
49effaf2
RN
146 } else {\r
147 //\r
148 // 64bit\r
149 //\r
150 Offset += 4;\r
151 PcatPciRootBridgeBarExisted (\r
152 PCI_LIB_ADDRESS (Bus, Device, Function, Offset),\r
153 &OriginalUpperValue,\r
154 &UpperValue\r
155 );\r
156\r
157 Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32);\r
158 Length = Length | LShiftU64 ((UINT64) UpperValue, 32);\r
159 Length = (~Length) + 1;\r
160\r
d63610df
ID
161 if (Base < BASE_4GB) {\r
162 MemAperture = Mem;\r
163 } else {\r
164 MemAperture = MemAbove4G;\r
165 }\r
49effaf2
RN
166 }\r
167\r
168 Limit = Base + Length - 1;\r
169 if (Base < Limit) {\r
170 if (MemAperture->Base > Base) {\r
171 MemAperture->Base = Base;\r
172 }\r
173 if (MemAperture->Limit < Limit) {\r
174 MemAperture->Limit = Limit;\r
175 }\r
176 }\r
177 }\r
178 }\r
179 }\r
180}\r
181\r
27e4d6ae
ID
182STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };\r
183\r
49effaf2
RN
184PCI_ROOT_BRIDGE *\r
185ScanForRootBridges (\r
186 UINTN *NumberOfRootBridges\r
187 )\r
188{\r
189 UINTN PrimaryBus;\r
190 UINTN SubBus;\r
191 UINT8 Device;\r
192 UINT8 Function;\r
193 UINTN NumberOfDevices;\r
f982bb8d 194 UINTN Address;\r
49effaf2
RN
195 PCI_TYPE01 Pci;\r
196 UINT64 Attributes;\r
197 UINT64 Base;\r
198 UINT64 Limit;\r
199 UINT64 Value;\r
27e4d6ae 200 PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, *MemAperture;\r
49effaf2
RN
201 PCI_ROOT_BRIDGE *RootBridges;\r
202 UINTN BarOffsetEnd;\r
203\r
204\r
205 *NumberOfRootBridges = 0;\r
206 RootBridges = NULL;\r
207\r
208 //\r
209 // After scanning all the PCI devices on the PCI root bridge's primary bus,\r
210 // update the Primary Bus Number for the next PCI root bridge to be this PCI\r
211 // root bridge's subordinate bus number + 1.\r
212 //\r
213 for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {\r
214 SubBus = PrimaryBus;\r
215 Attributes = 0;\r
e33305ea
HG
216\r
217 ZeroMem (&Io, sizeof (Io));\r
218 ZeroMem (&Mem, sizeof (Mem));\r
219 ZeroMem (&MemAbove4G, sizeof (MemAbove4G));\r
27e4d6ae 220 Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64;\r
49effaf2
RN
221 //\r
222 // Scan all the PCI devices on the primary bus of the PCI root bridge\r
223 //\r
224 for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
225\r
226 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {\r
227\r
228 //\r
229 // Compute the PCI configuration address of the PCI device to probe\r
230 //\r
231 Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);\r
232\r
233 //\r
234 // Read the Vendor ID from the PCI Configuration Header\r
235 //\r
236 if (PciRead16 (Address) == MAX_UINT16) {\r
237 if (Function == 0) {\r
238 //\r
239 // If the PCI Configuration Read fails, or a PCI device does not\r
240 // exist, then skip this entire PCI device\r
241 //\r
242 break;\r
243 } else {\r
244 //\r
245 // If PCI function != 0, VendorId == 0xFFFF, we continue to search\r
246 // PCI function.\r
247 //\r
248 continue;\r
249 }\r
250 }\r
251\r
252 //\r
253 // Read the entire PCI Configuration Header\r
254 //\r
255 PciReadBuffer (Address, sizeof (Pci), &Pci);\r
256\r
257 //\r
258 // Increment the number of PCI device found on the primary bus of the\r
259 // PCI root bridge\r
260 //\r
261 NumberOfDevices++;\r
262\r
263 //\r
264 // Look for devices with the VGA Palette Snoop enabled in the COMMAND\r
265 // register of the PCI Config Header\r
266 //\r
267 if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
268 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
269 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
270 }\r
271\r
272 BarOffsetEnd = 0;\r
273\r
274 //\r
275 // PCI-PCI Bridge\r
276 //\r
277 if (IS_PCI_BRIDGE (&Pci)) {\r
278 //\r
279 // Get the Bus range that the PPB is decoding\r
280 //\r
281 if (Pci.Bridge.SubordinateBus > SubBus) {\r
282 //\r
493dde94 283 // If the subordinate bus number of the PCI-PCI bridge is greater\r
49effaf2
RN
284 // than the PCI root bridge's current subordinate bus number,\r
285 // then update the PCI root bridge's subordinate bus number\r
286 //\r
287 SubBus = Pci.Bridge.SubordinateBus;\r
288 }\r
289\r
290 //\r
291 // Get the I/O range that the PPB is decoding\r
292 //\r
293 Value = Pci.Bridge.IoBase & 0x0f;\r
294 Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8;\r
295 Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;\r
296 if (Value == BIT0) {\r
297 Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16);\r
298 Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16);\r
299 }\r
300 if (Base < Limit) {\r
301 if (Io.Base > Base) {\r
302 Io.Base = Base;\r
303 }\r
304 if (Io.Limit < Limit) {\r
305 Io.Limit = Limit;\r
306 }\r
307 }\r
308\r
309 //\r
310 // Get the Memory range that the PPB is decoding\r
311 //\r
312 Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16;\r
313 Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;\r
314 if (Base < Limit) {\r
315 if (Mem.Base > Base) {\r
316 Mem.Base = Base;\r
317 }\r
318 if (Mem.Limit < Limit) {\r
319 Mem.Limit = Limit;\r
320 }\r
321 }\r
322\r
323 //\r
324 // Get the Prefetchable Memory range that the PPB is decoding\r
27e4d6ae 325 // and merge it into Memory range\r
49effaf2
RN
326 //\r
327 Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;\r
328 Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;\r
329 Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)\r
330 << 16) | 0xfffff;\r
27e4d6ae 331 MemAperture = &Mem;\r
49effaf2
RN
332 if (Value == BIT0) {\r
333 Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);\r
334 Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);\r
27e4d6ae 335 MemAperture = &MemAbove4G;\r
49effaf2
RN
336 }\r
337 if (Base < Limit) {\r
338 if (MemAperture->Base > Base) {\r
339 MemAperture->Base = Base;\r
340 }\r
341 if (MemAperture->Limit < Limit) {\r
342 MemAperture->Limit = Limit;\r
343 }\r
344 }\r
345\r
346 //\r
347 // Look at the PPB Configuration for legacy decoding attributes\r
348 //\r
349 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)\r
350 == EFI_PCI_BRIDGE_CONTROL_ISA) {\r
351 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
352 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;\r
353 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
354 }\r
355 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)\r
356 == EFI_PCI_BRIDGE_CONTROL_VGA) {\r
357 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
358 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
359 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
360 if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)\r
361 != 0) {\r
362 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
363 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;\r
364 }\r
365 }\r
366\r
367 BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);\r
368 } else {\r
369 //\r
370 // Parse the BARs of the PCI device to get what I/O Ranges, Memory\r
371 // Ranges, and Prefetchable Memory Ranges the device is decoding\r
372 //\r
373 if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {\r
374 BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);\r
375 }\r
376 }\r
377\r
378 PcatPciRootBridgeParseBars (\r
379 Pci.Hdr.Command,\r
380 PrimaryBus,\r
381 Device,\r
382 Function,\r
383 OFFSET_OF (PCI_TYPE00, Device.Bar),\r
384 BarOffsetEnd,\r
385 &Io,\r
27e4d6ae 386 &Mem, &MemAbove4G\r
49effaf2
RN
387 );\r
388\r
389 //\r
390 // See if the PCI device is an IDE controller\r
391 //\r
392 if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE,\r
393 PCI_CLASS_MASS_STORAGE_IDE)) {\r
394 if (Pci.Hdr.ClassCode[0] & 0x80) {\r
395 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
396 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
397 }\r
398 if (Pci.Hdr.ClassCode[0] & 0x01) {\r
399 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
400 }\r
401 if (Pci.Hdr.ClassCode[0] & 0x04) {\r
402 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
403 }\r
404 }\r
405\r
406 //\r
407 // See if the PCI device is a legacy VGA controller or\r
408 // a standard VGA controller\r
409 //\r
410 if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||\r
411 IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)\r
412 ) {\r
413 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
414 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
415 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
416 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
417 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;\r
418 }\r
419\r
420 //\r
421 // See if the PCI Device is a PCI - ISA or PCI - EISA\r
493dde94 422 // or ISA_POSITIVE_DECODE Bridge device\r
49effaf2
RN
423 //\r
424 if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {\r
425 if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA ||\r
426 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA ||\r
427 Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) {\r
428 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
429 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;\r
430 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
431 }\r
432 }\r
433\r
434 //\r
435 // If this device is not a multi function device, then skip the rest\r
436 // of this PCI device\r
437 //\r
438 if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
439 break;\r
440 }\r
441 }\r
442 }\r
443\r
444 //\r
445 // If at least one PCI device was found on the primary bus of this PCI\r
446 // root bridge, then the PCI root bridge exists.\r
447 //\r
448 if (NumberOfDevices > 0) {\r
449 RootBridges = ReallocatePool (\r
450 (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),\r
451 (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),\r
452 RootBridges\r
453 );\r
454 ASSERT (RootBridges != NULL);\r
455 InitRootBridge (\r
456 Attributes, Attributes, 0,\r
457 (UINT8) PrimaryBus, (UINT8) SubBus,\r
27e4d6ae 458 &Io, &Mem, &MemAbove4G, &mNonExistAperture, &mNonExistAperture,\r
49effaf2
RN
459 &RootBridges[*NumberOfRootBridges]\r
460 );\r
461 RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;\r
462 //\r
463 // Increment the index for the next PCI Root Bridge\r
464 //\r
465 (*NumberOfRootBridges)++;\r
466 }\r
467 }\r
468\r
469 return RootBridges;\r
470}\r