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