]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
CommitLineData
9060e3ec 1/** @file\r
2 PCI emumeration support functions implementation for PCI Bus module.\r
3\r
cd5ebaa0
HT
4Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
9060e3ec 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PciBus.h"\r
16\r
17/**\r
18 This routine is used to check whether the pci device is present.\r
19\r
20 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
21 @param Pci Output buffer for PCI device configuration space.\r
22 @param Bus PCI bus NO.\r
23 @param Device PCI device NO.\r
24 @param Func PCI Func NO.\r
25\r
26 @retval EFI_NOT_FOUND PCI device not present.\r
27 @retval EFI_SUCCESS PCI device is found.\r
28\r
29**/\r
30EFI_STATUS\r
31PciDevicePresent (\r
32 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
33 OUT PCI_TYPE00 *Pci,\r
34 IN UINT8 Bus,\r
35 IN UINT8 Device,\r
36 IN UINT8 Func\r
37 )\r
38{\r
39 UINT64 Address;\r
40 EFI_STATUS Status;\r
41\r
42 //\r
43 // Create PCI address map in terms of Bus, Device and Func\r
44 //\r
45 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
46\r
47 //\r
48 // Read the Vendor ID register\r
49 //\r
50 Status = PciRootBridgeIo->Pci.Read (\r
51 PciRootBridgeIo,\r
52 EfiPciWidthUint32,\r
53 Address,\r
54 1,\r
55 Pci\r
56 );\r
57\r
58 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
59 //\r
60 // Read the entire config header for the device\r
61 //\r
62 Status = PciRootBridgeIo->Pci.Read (\r
63 PciRootBridgeIo,\r
64 EfiPciWidthUint32,\r
65 Address,\r
66 sizeof (PCI_TYPE00) / sizeof (UINT32),\r
67 Pci\r
68 );\r
69\r
70 return EFI_SUCCESS;\r
71 }\r
72\r
73 return EFI_NOT_FOUND;\r
74}\r
75\r
76/**\r
77 Collect all the resource information under this root bridge.\r
78\r
79 A database that records all the information about pci device subject to this\r
80 root bridge will then be created.\r
81\r
82 @param Bridge Parent bridge instance.\r
83 @param StartBusNumber Bus number of begining.\r
84\r
85 @retval EFI_SUCCESS PCI device is found.\r
86 @retval other Some error occurred when reading PCI bridge information.\r
87\r
88**/\r
89EFI_STATUS\r
90PciPciDeviceInfoCollector (\r
91 IN PCI_IO_DEVICE *Bridge,\r
92 IN UINT8 StartBusNumber\r
93 )\r
94{\r
95 EFI_STATUS Status;\r
96 PCI_TYPE00 Pci;\r
97 UINT8 Device;\r
98 UINT8 Func;\r
99 UINT8 SecBus;\r
100 PCI_IO_DEVICE *PciIoDevice;\r
101 EFI_PCI_IO_PROTOCOL *PciIo;\r
102\r
103 Status = EFI_SUCCESS;\r
104 SecBus = 0;\r
105\r
106 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
107\r
108 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
109\r
110 //\r
111 // Check to see whether PCI device is present\r
112 //\r
113 Status = PciDevicePresent (\r
114 Bridge->PciRootBridgeIo,\r
115 &Pci,\r
116 (UINT8) StartBusNumber,\r
117 (UINT8) Device,\r
118 (UINT8) Func\r
119 );\r
120 if (!EFI_ERROR (Status)) {\r
121\r
122 //\r
123 // Call back to host bridge function\r
124 //\r
125 PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);\r
126\r
127 //\r
128 // Collect all the information about the PCI device discovered\r
129 //\r
130 Status = PciSearchDevice (\r
131 Bridge,\r
132 &Pci,\r
133 (UINT8) StartBusNumber,\r
134 Device,\r
135 Func,\r
136 &PciIoDevice\r
137 );\r
138\r
139 //\r
140 // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
141 //\r
142 //\r
143 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
144\r
145 //\r
146 // If it is PPB, we need to get the secondary bus to continue the enumeration\r
147 //\r
148 PciIo = &(PciIoDevice->PciIo);\r
149\r
150 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);\r
151\r
152 if (EFI_ERROR (Status)) {\r
153 return Status;\r
154 }\r
155\r
156 //\r
157 // Get resource padding for PPB\r
158 //\r
159 GetResourcePaddingPpb (PciIoDevice);\r
160\r
161 //\r
162 // Deep enumerate the next level bus\r
163 //\r
164 Status = PciPciDeviceInfoCollector (\r
165 PciIoDevice,\r
166 (UINT8) (SecBus)\r
167 );\r
168\r
169 }\r
170\r
171 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
172\r
173 //\r
174 // Skip sub functions, this is not a multi function device\r
175 //\r
176 Func = PCI_MAX_FUNC;\r
177 }\r
178 }\r
179\r
180 }\r
181 }\r
182\r
183 return EFI_SUCCESS;\r
184}\r
185\r
186/**\r
187 Seach required device and create PCI device instance.\r
188\r
189 @param Bridge Parent bridge instance.\r
190 @param Pci Input PCI device information block.\r
191 @param Bus PCI bus NO.\r
192 @param Device PCI device NO.\r
193 @param Func PCI func NO.\r
194 @param PciDevice Output of searched PCI device instance.\r
195\r
196 @retval EFI_SUCCESS Successfully created PCI device instance.\r
197 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.\r
198\r
199**/\r
200EFI_STATUS\r
201PciSearchDevice (\r
202 IN PCI_IO_DEVICE *Bridge,\r
203 IN PCI_TYPE00 *Pci,\r
204 IN UINT8 Bus,\r
205 IN UINT8 Device,\r
206 IN UINT8 Func,\r
207 OUT PCI_IO_DEVICE **PciDevice\r
208 )\r
209{\r
210 PCI_IO_DEVICE *PciIoDevice;\r
211\r
212 PciIoDevice = NULL;\r
213\r
214 if (!IS_PCI_BRIDGE (Pci)) {\r
215\r
216 if (IS_CARDBUS_BRIDGE (Pci)) {\r
217 PciIoDevice = GatherP2CInfo (\r
218 Bridge,\r
219 Pci,\r
220 Bus,\r
221 Device,\r
222 Func\r
223 );\r
224 if ((PciIoDevice != NULL) && gFullEnumeration) {\r
225 InitializeP2C (PciIoDevice);\r
226 }\r
227 } else {\r
228\r
229 //\r
230 // Create private data for Pci Device\r
231 //\r
232 PciIoDevice = GatherDeviceInfo (\r
233 Bridge,\r
234 Pci,\r
235 Bus,\r
236 Device,\r
237 Func\r
238 );\r
239\r
240 }\r
241\r
242 } else {\r
243\r
244 //\r
245 // Create private data for PPB\r
246 //\r
247 PciIoDevice = GatherPpbInfo (\r
248 Bridge,\r
249 Pci,\r
250 Bus,\r
251 Device,\r
252 Func\r
253 );\r
254\r
255 //\r
256 // Special initialization for PPB including making the PPB quiet\r
257 //\r
258 if ((PciIoDevice != NULL) && gFullEnumeration) {\r
259 InitializePpb (PciIoDevice);\r
260 }\r
261 }\r
262\r
263 if (PciIoDevice == NULL) {\r
264 return EFI_OUT_OF_RESOURCES;\r
265 }\r
266\r
267 //\r
268 // Update the bar information for this PCI device so as to support some specific device\r
269 //\r
270 UpdatePciInfo (PciIoDevice);\r
271\r
272 if (PciIoDevice->DevicePath == NULL) {\r
273 return EFI_OUT_OF_RESOURCES;\r
274 }\r
275\r
276 //\r
277 // Detect this function has option rom\r
278 //\r
279 if (gFullEnumeration) {\r
280\r
281 if (!IS_CARDBUS_BRIDGE (Pci)) {\r
282\r
283 GetOpRomInfo (PciIoDevice);\r
284\r
285 }\r
286\r
287 ResetPowerManagementFeature (PciIoDevice);\r
288\r
289 }\r
290\r
291 //\r
292 // Insert it into a global tree for future reference\r
293 //\r
294 InsertPciDevice (Bridge, PciIoDevice);\r
295\r
296 //\r
297 // Determine PCI device attributes\r
298 //\r
299\r
300 if (PciDevice != NULL) {\r
301 *PciDevice = PciIoDevice;\r
302 }\r
303\r
304 return EFI_SUCCESS;\r
305}\r
306\r
307/**\r
308 Create PCI device instance for PCI device.\r
309\r
310 @param Bridge Parent bridge instance.\r
311 @param Pci Input PCI device information block.\r
312 @param Bus PCI device Bus NO.\r
313 @param Device PCI device Device NO.\r
314 @param Func PCI device's func NO.\r
315\r
316 @return Created PCI device instance.\r
317\r
318**/\r
319PCI_IO_DEVICE *\r
320GatherDeviceInfo (\r
321 IN PCI_IO_DEVICE *Bridge,\r
322 IN PCI_TYPE00 *Pci,\r
323 IN UINT8 Bus,\r
324 IN UINT8 Device,\r
325 IN UINT8 Func\r
326 )\r
327{\r
328 UINTN Offset;\r
329 UINTN BarIndex;\r
330 PCI_IO_DEVICE *PciIoDevice;\r
331 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
332\r
333 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
334 PciIoDevice = CreatePciIoDevice (\r
335 PciRootBridgeIo,\r
336 Pci,\r
337 Bus,\r
338 Device,\r
339 Func\r
340 );\r
341\r
342 if (PciIoDevice == NULL) {\r
343 return NULL;\r
344 }\r
345\r
346 //\r
347 // Create a device path for this PCI device and store it into its private data\r
348 //\r
349 CreatePciDevicePath (\r
350 Bridge->DevicePath,\r
351 PciIoDevice\r
352 );\r
353\r
354 //\r
355 // If it is a full enumeration, disconnect the device in advance\r
356 //\r
357 if (gFullEnumeration) {\r
358\r
359 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
360\r
361 }\r
362\r
363 //\r
364 // Start to parse the bars\r
365 //\r
366 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {\r
367 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
368 }\r
369\r
370 //\r
371 // Parse the SR-IOV VF bars\r
372 //\r
373 if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
374 for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;\r
375 Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;\r
376 BarIndex++) {\r
377\r
378 ASSERT (BarIndex < PCI_MAX_BAR);\r
379 Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);\r
380 }\r
381 }\r
382 return PciIoDevice;\r
383}\r
384\r
385/**\r
386 Create PCI device instance for PCI-PCI bridge.\r
387\r
388 @param Bridge Parent bridge instance.\r
389 @param Pci Input PCI device information block.\r
390 @param Bus PCI device Bus NO.\r
391 @param Device PCI device Device NO.\r
392 @param Func PCI device's func NO.\r
393\r
394 @return Created PCI device instance.\r
395\r
396**/\r
397PCI_IO_DEVICE *\r
398GatherPpbInfo (\r
399 IN PCI_IO_DEVICE *Bridge,\r
400 IN PCI_TYPE00 *Pci,\r
401 IN UINT8 Bus,\r
402 IN UINT8 Device,\r
403 IN UINT8 Func\r
404 )\r
405{\r
406 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
407 PCI_IO_DEVICE *PciIoDevice;\r
408 EFI_STATUS Status;\r
409 UINT8 Value;\r
410 EFI_PCI_IO_PROTOCOL *PciIo;\r
411 UINT8 Temp;\r
412\r
413 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
414 PciIoDevice = CreatePciIoDevice (\r
415 PciRootBridgeIo,\r
416 Pci,\r
417 Bus,\r
418 Device,\r
419 Func\r
420 );\r
421\r
422 if (PciIoDevice == NULL) {\r
423 return NULL;\r
424 }\r
425\r
426 //\r
427 // Create a device path for this PCI device and store it into its private data\r
428 //\r
429 CreatePciDevicePath (\r
430 Bridge->DevicePath,\r
431 PciIoDevice\r
432 );\r
433\r
434 if (gFullEnumeration) {\r
435 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
436\r
437 //\r
438 // Initalize the bridge control register\r
439 //\r
440 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
441\r
442 }\r
443\r
444 //\r
445 // PPB can have two BARs\r
446 //\r
447 if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {\r
448 //\r
449 // Not 64-bit bar\r
450 //\r
451 PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);\r
452 }\r
453\r
454 PciIo = &PciIoDevice->PciIo;\r
455\r
456 //\r
457 // Test whether it support 32 decode or not\r
458 //\r
459 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
460 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
461 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
462 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
463\r
464 if (Value != 0) {\r
465 if ((Value & 0x01) != 0) {\r
466 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
467 } else {\r
468 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
469 }\r
470 }\r
471\r
1ef26783 472 //\r
473 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes\r
474 // PCI bridge supporting non-stardard I/O window alignment less than 4K.\r
475 //\r
476\r
477 PciIoDevice->BridgeIoAlignment = 0xFFF;\r
478 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {\r
479 //\r
480 // Check any bits of bit 3-1 of I/O Base Register are writable.\r
481 // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.\r
482 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.\r
483 //\r
f00b5d83 484 Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));\r
1ef26783 485 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
486 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
487 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
f00b5d83 488 Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1));\r
1ef26783 489 switch (Value) {\r
490 case BIT3:\r
491 PciIoDevice->BridgeIoAlignment = 0x7FF;\r
492 break;\r
493 case BIT3 | BIT2:\r
494 PciIoDevice->BridgeIoAlignment = 0x3FF;\r
495 break;\r
496 case BIT3 | BIT2 | BIT1:\r
497 PciIoDevice->BridgeIoAlignment = 0x1FF;\r
498 break;\r
499 }\r
500 }\r
501\r
9060e3ec 502 Status = BarExisted (\r
503 PciIoDevice,\r
504 0x24,\r
505 NULL,\r
506 NULL\r
507 );\r
508\r
509 //\r
510 // Test if it supports 64 memory or not\r
511 //\r
512 if (!EFI_ERROR (Status)) {\r
513\r
514 Status = BarExisted (\r
515 PciIoDevice,\r
516 0x28,\r
517 NULL,\r
518 NULL\r
519 );\r
520\r
521 if (!EFI_ERROR (Status)) {\r
522 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
523 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
524 } else {\r
525 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
526 }\r
527 }\r
528\r
529 //\r
530 // Memory 32 code is required for ppb\r
531 //\r
532 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
533\r
534 GetResourcePaddingPpb (PciIoDevice);\r
535\r
536 return PciIoDevice;\r
537}\r
538\r
539\r
540/**\r
541 Create PCI device instance for PCI Card bridge device.\r
542\r
543 @param Bridge Parent bridge instance.\r
544 @param Pci Input PCI device information block.\r
545 @param Bus PCI device Bus NO.\r
546 @param Device PCI device Device NO.\r
547 @param Func PCI device's func NO.\r
548\r
549 @return Created PCI device instance.\r
550\r
551**/\r
552PCI_IO_DEVICE *\r
553GatherP2CInfo (\r
554 IN PCI_IO_DEVICE *Bridge,\r
555 IN PCI_TYPE00 *Pci,\r
556 IN UINT8 Bus,\r
557 IN UINT8 Device,\r
558 IN UINT8 Func\r
559 )\r
560{\r
561 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
562 PCI_IO_DEVICE *PciIoDevice;\r
563\r
564 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
565 PciIoDevice = CreatePciIoDevice (\r
566 PciRootBridgeIo,\r
567 Pci,\r
568 Bus,\r
569 Device,\r
570 Func\r
571 );\r
572\r
573 if (PciIoDevice == NULL) {\r
574 return NULL;\r
575 }\r
576\r
577 //\r
578 // Create a device path for this PCI device and store it into its private data\r
579 //\r
580 CreatePciDevicePath (\r
581 Bridge->DevicePath,\r
582 PciIoDevice\r
583 );\r
584\r
585 if (gFullEnumeration) {\r
586 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
587\r
588 //\r
589 // Initalize the bridge control register\r
590 //\r
591 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
592 }\r
593\r
594 //\r
595 // P2C only has one bar that is in 0x10\r
596 //\r
597 PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);\r
598\r
599 //\r
600 // Read PciBar information from the bar register\r
601 //\r
602 GetBackPcCardBar (PciIoDevice);\r
603 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |\r
604 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
605 EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
606\r
607 return PciIoDevice;\r
608}\r
609\r
610/**\r
611 Create device path for pci deivce.\r
612\r
613 @param ParentDevicePath Parent bridge's path.\r
614 @param PciIoDevice Pci device instance.\r
615\r
616 @return Device path protocol instance for specific pci device.\r
617\r
618**/\r
619EFI_DEVICE_PATH_PROTOCOL *\r
620CreatePciDevicePath (\r
621 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
622 IN PCI_IO_DEVICE *PciIoDevice\r
623 )\r
624{\r
625\r
626 PCI_DEVICE_PATH PciNode;\r
627\r
628 //\r
629 // Create PCI device path\r
630 //\r
631 PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
632 PciNode.Header.SubType = HW_PCI_DP;\r
633 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
634\r
635 PciNode.Device = PciIoDevice->DeviceNumber;\r
636 PciNode.Function = PciIoDevice->FunctionNumber;\r
637 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
638\r
639 return PciIoDevice->DevicePath;\r
640}\r
641\r
642/**\r
643 Check whether the PCI IOV VF bar is existed or not.\r
644\r
645 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
646 @param Offset The offset.\r
647 @param BarLengthValue The bar length value returned.\r
648 @param OriginalBarValue The original bar value returned.\r
649\r
650 @retval EFI_NOT_FOUND The bar doesn't exist.\r
651 @retval EFI_SUCCESS The bar exist.\r
652\r
653**/\r
654EFI_STATUS\r
655VfBarExisted (\r
656 IN PCI_IO_DEVICE *PciIoDevice,\r
657 IN UINTN Offset,\r
658 OUT UINT32 *BarLengthValue,\r
659 OUT UINT32 *OriginalBarValue\r
660 )\r
661{\r
662 EFI_PCI_IO_PROTOCOL *PciIo;\r
663 UINT32 OriginalValue;\r
664 UINT32 Value;\r
665 EFI_TPL OldTpl;\r
666\r
667 //\r
668 // Ensure it is called properly\r
669 //\r
670 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
671 if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
672 return EFI_NOT_FOUND;\r
673 }\r
674\r
675 PciIo = &PciIoDevice->PciIo;\r
676\r
677 //\r
678 // Preserve the original value\r
679 //\r
680\r
681 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
682\r
683 //\r
684 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
685 //\r
686 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
687\r
688 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);\r
689 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);\r
690\r
691 //\r
692 // Write back the original value\r
693 //\r
694 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
695\r
696 //\r
697 // Restore TPL to its original level\r
698 //\r
699 gBS->RestoreTPL (OldTpl);\r
700\r
701 if (BarLengthValue != NULL) {\r
702 *BarLengthValue = Value;\r
703 }\r
704\r
705 if (OriginalBarValue != NULL) {\r
706 *OriginalBarValue = OriginalValue;\r
707 }\r
708\r
709 if (Value == 0) {\r
710 return EFI_NOT_FOUND;\r
711 } else {\r
712 return EFI_SUCCESS;\r
713 }\r
714}\r
715\r
716/**\r
717 Check whether the bar is existed or not.\r
718\r
719 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
720 @param Offset The offset.\r
721 @param BarLengthValue The bar length value returned.\r
722 @param OriginalBarValue The original bar value returned.\r
723\r
724 @retval EFI_NOT_FOUND The bar doesn't exist.\r
725 @retval EFI_SUCCESS The bar exist.\r
726\r
727**/\r
728EFI_STATUS\r
729BarExisted (\r
730 IN PCI_IO_DEVICE *PciIoDevice,\r
731 IN UINTN Offset,\r
732 OUT UINT32 *BarLengthValue,\r
733 OUT UINT32 *OriginalBarValue\r
734 )\r
735{\r
736 EFI_PCI_IO_PROTOCOL *PciIo;\r
737 UINT32 OriginalValue;\r
738 UINT32 Value;\r
739 EFI_TPL OldTpl;\r
740\r
741 PciIo = &PciIoDevice->PciIo;\r
742\r
743 //\r
744 // Preserve the original value\r
745 //\r
746 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
747\r
748 //\r
749 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
750 //\r
751 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
752\r
753 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
754 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
755\r
756 //\r
757 // Write back the original value\r
758 //\r
759 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
760\r
761 //\r
762 // Restore TPL to its original level\r
763 //\r
764 gBS->RestoreTPL (OldTpl);\r
765\r
766 if (BarLengthValue != NULL) {\r
767 *BarLengthValue = Value;\r
768 }\r
769\r
770 if (OriginalBarValue != NULL) {\r
771 *OriginalBarValue = OriginalValue;\r
772 }\r
773\r
774 if (Value == 0) {\r
775 return EFI_NOT_FOUND;\r
776 } else {\r
777 return EFI_SUCCESS;\r
778 }\r
779}\r
780\r
781/**\r
782 Test whether the device can support given attributes.\r
783\r
784 @param PciIoDevice Pci device instance.\r
785 @param Command Input command register value, and\r
786 returned supported register value.\r
787 @param BridgeControl Inout bridge control value for PPB or P2C, and\r
788 returned supported bridge control value.\r
789 @param OldCommand Returned and stored old command register offset.\r
790 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.\r
791\r
792**/\r
793VOID\r
794PciTestSupportedAttribute (\r
795 IN PCI_IO_DEVICE *PciIoDevice,\r
796 IN OUT UINT16 *Command,\r
797 IN OUT UINT16 *BridgeControl,\r
798 OUT UINT16 *OldCommand,\r
799 OUT UINT16 *OldBridgeControl\r
800 )\r
801{\r
802 EFI_TPL OldTpl;\r
803\r
804 //\r
805 // Preserve the original value\r
806 //\r
807 PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);\r
808\r
809 //\r
810 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
811 //\r
812 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
813\r
814 PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command);\r
815 PCI_READ_COMMAND_REGISTER (PciIoDevice, Command);\r
816\r
817 //\r
818 // Write back the original value\r
819 //\r
820 PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);\r
821\r
822 //\r
823 // Restore TPL to its original level\r
824 //\r
825 gBS->RestoreTPL (OldTpl);\r
826\r
827 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
828\r
829 //\r
830 // Preserve the original value\r
831 //\r
832 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);\r
833\r
834 //\r
835 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
836 //\r
837 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
838\r
839 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);\r
840 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
841\r
842 //\r
843 // Write back the original value\r
844 //\r
845 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);\r
846\r
847 //\r
848 // Restore TPL to its original level\r
849 //\r
850 gBS->RestoreTPL (OldTpl);\r
851\r
852 } else {\r
853 *OldBridgeControl = 0;\r
854 *BridgeControl = 0;\r
855 }\r
856}\r
857\r
858/**\r
859 Set the supported or current attributes of a PCI device.\r
860\r
861 @param PciIoDevice Structure pointer for PCI device.\r
862 @param Command Command register value.\r
863 @param BridgeControl Bridge control value for PPB or P2C.\r
864 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
865\r
866**/\r
867VOID\r
868PciSetDeviceAttribute (\r
869 IN PCI_IO_DEVICE *PciIoDevice,\r
870 IN UINT16 Command,\r
871 IN UINT16 BridgeControl,\r
872 IN UINTN Option\r
873 )\r
874{\r
875 UINT64 Attributes;\r
876\r
877 Attributes = 0;\r
878\r
879 if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {\r
880 Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
881 }\r
882\r
883 if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {\r
884 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
885 }\r
886\r
887 if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {\r
888 Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
889 }\r
890\r
891 if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
892 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
893 }\r
894\r
895 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {\r
896 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
897 }\r
898\r
899 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {\r
900 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
901 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
902 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
903 }\r
904\r
905 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {\r
906 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
907 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;\r
908 }\r
909\r
910 if (Option == EFI_SET_SUPPORTS) {\r
911\r
912 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
913 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |\r
914 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |\r
915 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
916 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |\r
917 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
918\r
919 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
920 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
921 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
922 }\r
923\r
924 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
925 //\r
926 // For bridge, it should support IDE attributes\r
927 //\r
928 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
929 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
930 } else {\r
931\r
932 if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
933 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
934 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
935 }\r
936\r
937 if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
938 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
939 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
940 }\r
941 }\r
942\r
943 PciIoDevice->Supports = Attributes;\r
944 PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \\r
945 EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
946 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
947\r
948 } else {\r
949 PciIoDevice->Attributes = Attributes;\r
950 }\r
951}\r
952\r
953/**\r
954 Determine if the device can support Fast Back to Back attribute.\r
955\r
956 @param PciIoDevice Pci device instance.\r
957 @param StatusIndex Status register value.\r
958\r
959 @retval EFI_SUCCESS This device support Fast Back to Back attribute.\r
960 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.\r
961\r
962**/\r
963EFI_STATUS\r
964GetFastBackToBackSupport (\r
965 IN PCI_IO_DEVICE *PciIoDevice,\r
966 IN UINT8 StatusIndex\r
967 )\r
968{\r
969 EFI_PCI_IO_PROTOCOL *PciIo;\r
970 EFI_STATUS Status;\r
971 UINT32 StatusRegister;\r
972\r
973 //\r
974 // Read the status register\r
975 //\r
976 PciIo = &PciIoDevice->PciIo;\r
977 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);\r
978 if (EFI_ERROR (Status)) {\r
979 return EFI_UNSUPPORTED;\r
980 }\r
981\r
982 //\r
983 // Check the Fast B2B bit\r
984 //\r
985 if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {\r
986 return EFI_SUCCESS;\r
987 } else {\r
988 return EFI_UNSUPPORTED;\r
989 }\r
990}\r
991\r
992/**\r
993 Process the option ROM for all the children of the specified parent PCI device.\r
994 It can only be used after the first full Option ROM process.\r
995\r
996 @param PciIoDevice Pci device instance.\r
997\r
998**/\r
999VOID\r
1000ProcessOptionRomLight (\r
1001 IN PCI_IO_DEVICE *PciIoDevice\r
1002 )\r
1003{\r
1004 PCI_IO_DEVICE *Temp;\r
1005 LIST_ENTRY *CurrentLink;\r
1006\r
1007 //\r
1008 // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
1009 //\r
1010 CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1011 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
1012\r
1013 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1014\r
1015 if (!IsListEmpty (&Temp->ChildList)) {\r
1016 ProcessOptionRomLight (Temp);\r
1017 }\r
1018\r
1019 PciRomGetImageMapping (Temp);\r
1020\r
1021 //\r
1022 // The OpRom has already been processed in the first round\r
1023 //\r
1024 Temp->AllOpRomProcessed = TRUE;\r
1025\r
1026 CurrentLink = CurrentLink->ForwardLink;\r
1027 }\r
1028}\r
1029\r
1030/**\r
1031 Determine the related attributes of all devices under a Root Bridge.\r
1032\r
1033 @param PciIoDevice PCI device instance.\r
1034\r
1035**/\r
1036EFI_STATUS\r
1037DetermineDeviceAttribute (\r
1038 IN PCI_IO_DEVICE *PciIoDevice\r
1039 )\r
1040{\r
1041 UINT16 Command;\r
1042 UINT16 BridgeControl;\r
1043 UINT16 OldCommand;\r
1044 UINT16 OldBridgeControl;\r
1045 BOOLEAN FastB2BSupport;\r
1046 PCI_IO_DEVICE *Temp;\r
1047 LIST_ENTRY *CurrentLink;\r
1048 EFI_STATUS Status;\r
1049\r
1050 //\r
1051 // For Root Bridge, just copy it by RootBridgeIo proctocol\r
1052 // so as to keep consistent with the actual attribute\r
1053 //\r
1054 if (PciIoDevice->Parent == NULL) {\r
1055 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
1056 PciIoDevice->PciRootBridgeIo,\r
1057 &PciIoDevice->Supports,\r
1058 &PciIoDevice->Attributes\r
1059 );\r
1060 if (EFI_ERROR (Status)) {\r
1061 return Status;\r
1062 }\r
1063 } else {\r
1064\r
1065 //\r
1066 // Set the attributes to be checked for common PCI devices and PPB or P2C\r
1067 // Since some devices only support part of them, it is better to set the\r
1068 // attribute according to its command or bridge control register\r
1069 //\r
1070 Command = EFI_PCI_COMMAND_IO_SPACE |\r
1071 EFI_PCI_COMMAND_MEMORY_SPACE |\r
1072 EFI_PCI_COMMAND_BUS_MASTER |\r
1073 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1074\r
1075 BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
1076\r
1077 //\r
1078 // Test whether the device can support attributes above\r
1079 //\r
1080 PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
1081\r
1082 //\r
1083 // Set the supported attributes for specified PCI device\r
1084 //\r
1085 PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
1086\r
1087 //\r
1088 // Set the current attributes for specified PCI device\r
1089 //\r
1090 PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
1091\r
1092 //\r
1093 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
1094 //\r
1095 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
1096 }\r
1097\r
1098 FastB2BSupport = TRUE;\r
1099\r
1100 //\r
1101 // P2C can not support FB2B on the secondary side\r
1102 //\r
1103 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
1104 FastB2BSupport = FALSE;\r
1105 }\r
1106\r
1107 //\r
1108 // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
1109 //\r
1110 CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1111 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
1112\r
1113 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1114 Status = DetermineDeviceAttribute (Temp);\r
1115 if (EFI_ERROR (Status)) {\r
1116 return Status;\r
1117 }\r
1118 //\r
1119 // Detect Fast Bact to Bact support for the device under the bridge\r
1120 //\r
1121 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
1122 if (FastB2BSupport && EFI_ERROR (Status)) {\r
1123 FastB2BSupport = FALSE;\r
1124 }\r
1125\r
1126 CurrentLink = CurrentLink->ForwardLink;\r
1127 }\r
1128 //\r
1129 // Set or clear Fast Back to Back bit for the whole bridge\r
1130 //\r
1131 if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
1132\r
1133 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
1134\r
1135 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
1136\r
1137 if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
1138 FastB2BSupport = FALSE;\r
1139 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1140 } else {\r
1141 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
1142 }\r
1143 }\r
1144\r
1145 CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
1146 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
1147 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1148 if (FastB2BSupport) {\r
1149 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1150 } else {\r
1151 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
1152 }\r
1153\r
1154 CurrentLink = CurrentLink->ForwardLink;\r
1155 }\r
1156 }\r
1157 //\r
1158 // End for IsListEmpty\r
1159 //\r
1160 return EFI_SUCCESS;\r
1161}\r
1162\r
1163/**\r
1164 This routine is used to update the bar information for those incompatible PCI device.\r
1165\r
1166 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated\r
1167 Bar information.\r
1168\r
1169 @retval EFI_SUCCESS Successfully updated bar information.\r
1170 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.\r
1171\r
1172**/\r
1173EFI_STATUS\r
1174UpdatePciInfo (\r
1175 IN OUT PCI_IO_DEVICE *PciIoDevice\r
1176 )\r
1177{\r
1178 EFI_STATUS Status;\r
1179 UINTN BarIndex;\r
1180 UINTN BarEndIndex;\r
1181 BOOLEAN SetFlag;\r
1182 VOID *Configuration;\r
1183 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1184\r
1185 Configuration = NULL;\r
1186 Status = EFI_SUCCESS;\r
1187\r
1188 if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
1189 //\r
1190 // It can only be supported after the Incompatible PCI Device\r
1191 // Support Protocol has been installed\r
1192 //\r
1193 Status = gBS->LocateProtocol (\r
1194 &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
1195 NULL,\r
1196 (VOID **) &gEfiIncompatiblePciDeviceSupport\r
1197 );\r
1198 }\r
1199 if (Status == EFI_SUCCESS) {\r
1200 //\r
1201 // Check whether the device belongs to incompatible devices from protocol or not\r
1202 // If it is , then get its special requirement in the ACPI table\r
1203 //\r
1204 Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
1205 gEfiIncompatiblePciDeviceSupport,\r
1206 PciIoDevice->Pci.Hdr.VendorId,\r
1207 PciIoDevice->Pci.Hdr.DeviceId,\r
1208 PciIoDevice->Pci.Hdr.RevisionID,\r
1209 PciIoDevice->Pci.Device.SubsystemVendorID,\r
1210 PciIoDevice->Pci.Device.SubsystemID,\r
1211 &Configuration\r
1212 );\r
1213\r
1214 }\r
1215\r
1216 if (EFI_ERROR (Status) || Configuration == NULL ) {\r
1217 return EFI_UNSUPPORTED;\r
1218 }\r
1219\r
1220 //\r
1221 // Update PCI device information from the ACPI table\r
1222 //\r
1223 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1224\r
1225 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1226\r
1227 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1228 //\r
1229 // The format is not support\r
1230 //\r
1231 break;\r
1232 }\r
1233\r
1234 BarIndex = (UINTN) Ptr->AddrTranslationOffset;\r
1235 BarEndIndex = BarIndex;\r
1236\r
1237 //\r
1238 // Update all the bars in the device\r
1239 //\r
1240 if (BarIndex == PCI_BAR_ALL) {\r
1241 BarIndex = 0;\r
1242 BarEndIndex = PCI_MAX_BAR - 1;\r
1243 }\r
1244\r
1245 if (BarIndex > PCI_MAX_BAR) {\r
1246 Ptr++;\r
1247 continue;\r
1248 }\r
1249\r
1250 for (; BarIndex <= BarEndIndex; BarIndex++) {\r
1251 SetFlag = FALSE;\r
1252 switch (Ptr->ResType) {\r
1253 case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
1254\r
1255 //\r
1256 // Make sure the bar is memory type\r
1257 //\r
1258 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
1259 SetFlag = TRUE;\r
1260 }\r
1261 break;\r
1262\r
1263 case ACPI_ADDRESS_SPACE_TYPE_IO:\r
1264\r
1265 //\r
1266 // Make sure the bar is IO type\r
1267 //\r
1268 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
1269 SetFlag = TRUE;\r
1270 }\r
1271 break;\r
1272 }\r
1273\r
1274 if (SetFlag) {\r
1275\r
1276 //\r
1277 // Update the new alignment for the device\r
1278 //\r
1279 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
1280\r
1281 //\r
1282 // Update the new length for the device\r
1283 //\r
1284 if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
1285 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
1286 }\r
1287 }\r
1288 }\r
1289\r
1290 Ptr++;\r
1291 }\r
1292\r
1293 FreePool (Configuration);\r
1294\r
1295 return EFI_SUCCESS;\r
1296}\r
1297\r
1298/**\r
1299 This routine will update the alignment with the new alignment.\r
1300\r
1301 @param Alignment Input Old alignment. Output updated alignment.\r
1302 @param NewAlignment New alignment.\r
1303\r
1304**/\r
1305VOID\r
1306SetNewAlign (\r
1307 IN OUT UINT64 *Alignment,\r
1308 IN UINT64 NewAlignment\r
1309 )\r
1310{\r
1311 UINT64 OldAlignment;\r
1312 UINTN ShiftBit;\r
1313\r
1314 //\r
1315 // The new alignment is the same as the original,\r
1316 // so skip it\r
1317 //\r
1318 if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
1319 return ;\r
1320 }\r
1321 //\r
1322 // Check the validity of the parameter\r
1323 //\r
1324 if (NewAlignment != PCI_BAR_EVEN_ALIGN &&\r
1325 NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
1326 NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
1327 *Alignment = NewAlignment;\r
1328 return ;\r
1329 }\r
1330\r
1331 OldAlignment = (*Alignment) + 1;\r
1332 ShiftBit = 0;\r
1333\r
1334 //\r
1335 // Get the first non-zero hex value of the length\r
1336 //\r
1337 while ((OldAlignment & 0x0F) == 0x00) {\r
1338 OldAlignment = RShiftU64 (OldAlignment, 4);\r
1339 ShiftBit += 4;\r
1340 }\r
1341\r
1342 //\r
1343 // Adjust the alignment to even, quad or double quad boundary\r
1344 //\r
1345 if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
1346 if ((OldAlignment & 0x01) != 0) {\r
1347 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
1348 }\r
1349 } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
1350 if ((OldAlignment & 0x03) != 0) {\r
1351 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
1352 }\r
1353 } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
1354 if ((OldAlignment & 0x07) != 0) {\r
1355 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
1356 }\r
1357 }\r
1358\r
1359 //\r
1360 // Update the old value\r
1361 //\r
1362 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
1363 *Alignment = NewAlignment;\r
1364\r
1365 return ;\r
1366}\r
1367\r
1368/**\r
1369 Parse PCI IOV VF bar information and fill them into PCI device instance.\r
1370\r
1371 @param PciIoDevice Pci device instance.\r
1372 @param Offset Bar offset.\r
1373 @param BarIndex Bar index.\r
1374\r
1375 @return Next bar offset.\r
1376\r
1377**/\r
1378UINTN\r
1379PciIovParseVfBar (\r
1380 IN PCI_IO_DEVICE *PciIoDevice,\r
1381 IN UINTN Offset,\r
1382 IN UINTN BarIndex\r
1383 )\r
1384{\r
1385 UINT32 Value;\r
1386 UINT32 OriginalValue;\r
1387 UINT32 Mask;\r
1388 UINT32 Data;\r
1389 UINT8 Index;\r
1390 EFI_STATUS Status;\r
1391\r
1392 //\r
1393 // Ensure it is called properly\r
1394 //\r
1395 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
1396 if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
1397 return 0;\r
1398 }\r
1399\r
1400 OriginalValue = 0;\r
1401 Value = 0;\r
1402\r
1403 Status = VfBarExisted (\r
1404 PciIoDevice,\r
1405 Offset,\r
1406 &Value,\r
1407 &OriginalValue\r
1408 );\r
1409\r
1410 if (EFI_ERROR (Status)) {\r
1411 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
1412 PciIoDevice->VfPciBar[BarIndex].Length = 0;\r
1413 PciIoDevice->VfPciBar[BarIndex].Alignment = 0;\r
1414\r
1415 //\r
1416 // Scan all the BARs anyway\r
1417 //\r
1418 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
1419 return Offset + 4;\r
1420 }\r
1421\r
1422 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
aa75dfec 1423 if ((Value & 0x01) != 0) {\r
9060e3ec 1424 //\r
1425 // Device I/Os. Impossible\r
1426 //\r
1427 ASSERT (FALSE);\r
1428 return Offset + 4;\r
1429\r
1430 } else {\r
1431\r
1432 Mask = 0xfffffff0;\r
1433\r
1434 PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1435\r
1436 switch (Value & 0x07) {\r
1437\r
1438 //\r
1439 //memory space; anywhere in 32 bit address space\r
1440 //\r
1441 case 0x00:\r
aa75dfec 1442 if ((Value & 0x08) != 0) {\r
9060e3ec 1443 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;\r
1444 } else {\r
1445 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;\r
1446 }\r
1447\r
1448 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1449 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
1450\r
1451 //\r
1452 // Adjust Length\r
1453 //\r
1454 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
1455 //\r
1456 // Adjust Alignment\r
1457 //\r
1458 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
1459 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
1460 }\r
1461\r
1462 break;\r
1463\r
1464 //\r
1465 // memory space; anywhere in 64 bit address space\r
1466 //\r
1467 case 0x04:\r
aa75dfec 1468 if ((Value & 0x08) != 0) {\r
9060e3ec 1469 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;\r
1470 } else {\r
1471 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;\r
1472 }\r
1473\r
1474 //\r
1475 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
1476 // is regarded as an extension for the first bar. As a result\r
1477 // the sizing will be conducted on combined 64 bit value\r
1478 // Here just store the masked first 32bit value for future size\r
1479 // calculation\r
1480 //\r
1481 PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask;\r
1482 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
1483\r
1484 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
1485 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
1486 }\r
1487\r
1488 //\r
1489 // Increment the offset to point to next DWORD\r
1490 //\r
1491 Offset += 4;\r
1492\r
1493 Status = VfBarExisted (\r
1494 PciIoDevice,\r
1495 Offset,\r
1496 &Value,\r
1497 &OriginalValue\r
1498 );\r
1499\r
1500 if (EFI_ERROR (Status)) {\r
1501 return Offset + 4;\r
1502 }\r
1503\r
1504 //\r
1505 // Fix the length to support some spefic 64 bit BAR\r
1506 //\r
1507 Data = Value;\r
1508 Index = 0;\r
1509 for (Data = Value; Data != 0; Data >>= 1) {\r
1510 Index ++;\r
1511 }\r
1512 Value |= ((UINT32)(-1) << Index); \r
1513\r
1514 //\r
1515 // Calculate the size of 64bit bar\r
1516 //\r
1517 PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
1518\r
1519 PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
1520 PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;\r
1521 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
1522\r
1523 //\r
1524 // Adjust Length\r
1525 //\r
1526 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
1527 //\r
1528 // Adjust Alignment\r
1529 //\r
1530 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
1531 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
1532 }\r
1533\r
1534 break;\r
1535\r
1536 //\r
1537 // reserved\r
1538 //\r
1539 default:\r
1540 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1541 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1542 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
1543\r
1544 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
1545 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
1546 }\r
1547\r
1548 break;\r
1549 }\r
1550 }\r
1551 \r
1552 //\r
1553 // Check the length again so as to keep compatible with some special bars\r
1554 //\r
1555 if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {\r
1556 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1557 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
1558 PciIoDevice->VfPciBar[BarIndex].Alignment = 0;\r
1559 }\r
1560 \r
1561 //\r
1562 // Increment number of bar\r
1563 //\r
1564 return Offset + 4;\r
1565}\r
1566\r
1567/**\r
1568 Parse PCI bar information and fill them into PCI device instance.\r
1569\r
1570 @param PciIoDevice Pci device instance.\r
1571 @param Offset Bar offset.\r
1572 @param BarIndex Bar index.\r
1573\r
1574 @return Next bar offset.\r
1575\r
1576**/\r
1577UINTN\r
1578PciParseBar (\r
1579 IN PCI_IO_DEVICE *PciIoDevice,\r
1580 IN UINTN Offset,\r
1581 IN UINTN BarIndex\r
1582 )\r
1583{\r
1584 UINT32 Value;\r
1585 UINT32 OriginalValue;\r
1586 UINT32 Mask;\r
1587 UINT32 Data;\r
1588 UINT8 Index;\r
1589 EFI_STATUS Status;\r
1590\r
1591 OriginalValue = 0;\r
1592 Value = 0;\r
1593\r
1594 Status = BarExisted (\r
1595 PciIoDevice,\r
1596 Offset,\r
1597 &Value,\r
1598 &OriginalValue\r
1599 );\r
1600\r
1601 if (EFI_ERROR (Status)) {\r
1602 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1603 PciIoDevice->PciBar[BarIndex].Length = 0;\r
1604 PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
1605\r
1606 //\r
1607 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
1608 //\r
1609 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1610 return Offset + 4;\r
1611 }\r
1612\r
1613 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
1614 if ((Value & 0x01) != 0) {\r
1615 //\r
1616 // Device I/Os\r
1617 //\r
1618 Mask = 0xfffffffc;\r
1619\r
1620 if ((Value & 0xFFFF0000) != 0) {\r
1621 //\r
1622 // It is a IO32 bar\r
1623 //\r
1624 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;\r
1625 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);\r
1626 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1627\r
1628 } else {\r
1629 //\r
1630 // It is a IO16 bar\r
1631 //\r
1632 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;\r
1633 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
1634 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1635\r
1636 }\r
1637 //\r
1638 // Workaround. Some platforms inplement IO bar with 0 length\r
1639 // Need to treat it as no-bar\r
1640 //\r
1641 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1642 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
1643 }\r
1644\r
1645 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;\r
1646 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1647\r
1648 } else {\r
1649\r
1650 Mask = 0xfffffff0;\r
1651\r
1652 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
1653\r
1654 switch (Value & 0x07) {\r
1655\r
1656 //\r
1657 //memory space; anywhere in 32 bit address space\r
1658 //\r
1659 case 0x00:\r
1660 if ((Value & 0x08) != 0) {\r
1661 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
1662 } else {\r
1663 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
1664 }\r
1665\r
1666 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1667 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
1668 //\r
1669 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
1670 //\r
1671 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
1672 } else {\r
1673 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1674 }\r
1675 break;\r
1676\r
1677 //\r
1678 // memory space; anywhere in 64 bit address space\r
1679 //\r
1680 case 0x04:\r
1681 if ((Value & 0x08) != 0) {\r
1682 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
1683 } else {\r
1684 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
1685 }\r
1686\r
1687 //\r
1688 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
1689 // is regarded as an extension for the first bar. As a result\r
1690 // the sizing will be conducted on combined 64 bit value\r
1691 // Here just store the masked first 32bit value for future size\r
1692 // calculation\r
1693 //\r
1694 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;\r
1695 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1696\r
1697 //\r
1698 // Increment the offset to point to next DWORD\r
1699 //\r
1700 Offset += 4;\r
1701\r
1702 Status = BarExisted (\r
1703 PciIoDevice,\r
1704 Offset,\r
1705 &Value,\r
1706 &OriginalValue\r
1707 );\r
1708\r
1709 if (EFI_ERROR (Status)) {\r
1710 //\r
1711 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again\r
1712 //\r
1713 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1714 //\r
1715 // some device implement MMIO bar with 0 length, need to treat it as no-bar\r
1716 //\r
1717 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1718 }\r
1719 return Offset + 4;\r
1720 }\r
1721\r
1722 //\r
1723 // Fix the length to support some spefic 64 bit BAR\r
1724 //\r
1725 Data = Value;\r
1726 Index = 0;\r
1727 for (Data = Value; Data != 0; Data >>= 1) {\r
1728 Index ++;\r
1729 }\r
1730 Value |= ((UINT32)(-1) << Index);\r
1731\r
1732 //\r
1733 // Calculate the size of 64bit bar\r
1734 //\r
1735 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
1736\r
1737 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
1738 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
1739 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
1740 //\r
1741 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
1742 //\r
1743 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
1744 } else {\r
1745 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1746 }\r
1747\r
1748 break;\r
1749\r
1750 //\r
1751 // reserved\r
1752 //\r
1753 default:\r
1754 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1755 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;\r
1756 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
1757 //\r
1758 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
1759 //\r
1760 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
1761 } else {\r
1762 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
1763 }\r
1764 break;\r
1765 }\r
1766 }\r
1767\r
1768 //\r
1769 // Check the length again so as to keep compatible with some special bars\r
1770 //\r
1771 if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
1772 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
1773 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
1774 PciIoDevice->PciBar[BarIndex].Alignment = 0;\r
1775 }\r
1776\r
1777 //\r
1778 // Increment number of bar\r
1779 //\r
1780 return Offset + 4;\r
1781}\r
1782\r
1783/**\r
1784 This routine is used to initialize the bar of a PCI device.\r
1785\r
1786 @param PciIoDevice Pci device instance.\r
1787\r
1788 @note It can be called typically when a device is going to be rejected.\r
1789\r
1790**/\r
1791VOID\r
1792InitializePciDevice (\r
1793 IN PCI_IO_DEVICE *PciIoDevice\r
1794 )\r
1795{\r
1796 EFI_PCI_IO_PROTOCOL *PciIo;\r
1797 UINT8 Offset;\r
1798\r
1799 PciIo = &(PciIoDevice->PciIo);\r
1800\r
1801 //\r
1802 // Put all the resource apertures\r
1803 // Resource base is set to all ones so as to indicate its resource\r
1804 // has not been alloacted\r
1805 //\r
1806 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
1807 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
1808 }\r
1809}\r
1810\r
1811/**\r
1812 This routine is used to initialize the bar of a PCI-PCI Bridge device.\r
1813\r
1814 @param PciIoDevice PCI-PCI bridge device instance.\r
1815\r
1816**/\r
1817VOID\r
1818InitializePpb (\r
1819 IN PCI_IO_DEVICE *PciIoDevice\r
1820 )\r
1821{\r
1822 EFI_PCI_IO_PROTOCOL *PciIo;\r
1823\r
1824 PciIo = &(PciIoDevice->PciIo);\r
1825\r
1826 //\r
1827 // Put all the resource apertures including IO16\r
1828 // Io32, pMem32, pMem64 to quiescent state\r
1829 // Resource base all ones, Resource limit all zeros\r
1830 //\r
1831 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
1832 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
1833\r
1834 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
1835 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
1836\r
1837 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
1838 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
1839\r
1840 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
1841 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
1842\r
1843 //\r
1844 // Don't support use io32 as for now\r
1845 //\r
1846 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
1847 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
1848\r
1849 //\r
1850 // Force Interrupt line to zero for cards that come up randomly\r
1851 //\r
1852 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1853}\r
1854\r
1855/**\r
1856 This routine is used to initialize the bar of a PCI Card Bridge device.\r
1857\r
1858 @param PciIoDevice PCI Card bridge device.\r
1859\r
1860**/\r
1861VOID\r
1862InitializeP2C (\r
1863 IN PCI_IO_DEVICE *PciIoDevice\r
1864 )\r
1865{\r
1866 EFI_PCI_IO_PROTOCOL *PciIo;\r
1867\r
1868 PciIo = &(PciIoDevice->PciIo);\r
1869\r
1870 //\r
1871 // Put all the resource apertures including IO16\r
1872 // Io32, pMem32, pMem64 to quiescent state(\r
1873 // Resource base all ones, Resource limit all zeros\r
1874 //\r
1875 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
1876 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
1877\r
1878 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
1879 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
1880\r
1881 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
1882 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
1883\r
1884 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
1885 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
1886\r
1887 //\r
1888 // Force Interrupt line to zero for cards that come up randomly\r
1889 //\r
1890 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
1891}\r
1892\r
1893/**\r
1894 Create and initiliaze general PCI I/O device instance for\r
1895 PCI device/bridge device/hotplug bridge device.\r
1896\r
1897 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
1898 @param Pci Input Pci information block.\r
1899 @param Bus Device Bus NO.\r
1900 @param Device Device device NO.\r
1901 @param Func Device func NO.\r
1902\r
1903 @return Instance of PCI device. NULL means no instance created.\r
1904\r
1905**/\r
1906PCI_IO_DEVICE *\r
1907CreatePciIoDevice (\r
1908 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
1909 IN PCI_TYPE00 *Pci,\r
1910 IN UINT8 Bus,\r
1911 IN UINT8 Device,\r
1912 IN UINT8 Func\r
1913 )\r
1914{\r
1915 PCI_IO_DEVICE *PciIoDevice;\r
1916 EFI_PCI_IO_PROTOCOL *PciIo;\r
1917 EFI_STATUS Status;\r
1918\r
1919 PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
1920 if (PciIoDevice == NULL) {\r
1921 return NULL;\r
1922 }\r
1923\r
1924 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;\r
1925 PciIoDevice->Handle = NULL;\r
1926 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;\r
1927 PciIoDevice->DevicePath = NULL;\r
1928 PciIoDevice->BusNumber = Bus;\r
1929 PciIoDevice->DeviceNumber = Device;\r
1930 PciIoDevice->FunctionNumber = Func;\r
1931 PciIoDevice->Decodes = 0;\r
1932\r
1933 if (gFullEnumeration) {\r
1934 PciIoDevice->Allocated = FALSE;\r
1935 } else {\r
1936 PciIoDevice->Allocated = TRUE;\r
1937 }\r
1938\r
1939 PciIoDevice->Registered = FALSE;\r
1940 PciIoDevice->Attributes = 0;\r
1941 PciIoDevice->Supports = 0;\r
1942 PciIoDevice->BusOverride = FALSE;\r
1943 PciIoDevice->AllOpRomProcessed = FALSE;\r
1944\r
1945 PciIoDevice->IsPciExp = FALSE;\r
1946\r
1947 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
1948\r
1949 //\r
1950 // Initialize the PCI I/O instance structure\r
1951 //\r
1952 InitializePciIoInstance (PciIoDevice);\r
1953 InitializePciDriverOverrideInstance (PciIoDevice);\r
1954 InitializePciLoadFile2 (PciIoDevice);\r
1955 PciIo = &PciIoDevice->PciIo;\r
1956\r
1957 //\r
1958 // Detect if PCI Express Device\r
1959 //\r
1960 PciIoDevice->PciExpressCapabilityOffset = 0;\r
1961 Status = LocateCapabilityRegBlock (\r
1962 PciIoDevice,\r
1963 EFI_PCI_CAPABILITY_ID_PCIEXP,\r
1964 &PciIoDevice->PciExpressCapabilityOffset,\r
1965 NULL\r
1966 );\r
1967 if (!EFI_ERROR (Status)) {\r
1968 PciIoDevice->IsPciExp = TRUE;\r
1969 }\r
1970\r
1971 //\r
1972 // Initialize for PCI IOV\r
1973 //\r
1974\r
1975 //\r
1976 // Check ARI for function 0 only\r
1977 //\r
1978 Status = LocatePciExpressCapabilityRegBlock (\r
1979 PciIoDevice,\r
1980 EFI_PCIE_CAPABILITY_ID_ARI,\r
1981 &PciIoDevice->AriCapabilityOffset,\r
1982 NULL\r
1983 );\r
1984 if (!EFI_ERROR (Status)) {\r
1985 DEBUG ((\r
1986 EFI_D_INFO,\r
1987 "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",\r
1988 (UINTN)Bus,\r
1989 (UINTN)Device,\r
1990 (UINTN)Func,\r
1991 (UINTN)PciIoDevice->AriCapabilityOffset\r
1992 ));\r
1993 }\r
1994\r
1995 Status = LocatePciExpressCapabilityRegBlock (\r
1996 PciIoDevice,\r
1997 EFI_PCIE_CAPABILITY_ID_SRIOV,\r
1998 &PciIoDevice->SrIovCapabilityOffset,\r
1999 NULL\r
2000 );\r
2001 if (!EFI_ERROR (Status)) {\r
2002 DEBUG ((\r
2003 EFI_D_INFO,\r
2004 "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",\r
2005 (UINTN)Bus,\r
2006 (UINTN)Device,\r
2007 (UINTN)Func,\r
2008 (UINTN)PciIoDevice->SrIovCapabilityOffset\r
2009 ));\r
2010 }\r
2011\r
2012 Status = LocatePciExpressCapabilityRegBlock (\r
2013 PciIoDevice,\r
2014 EFI_PCIE_CAPABILITY_ID_MRIOV,\r
2015 &PciIoDevice->MrIovCapabilityOffset,\r
2016 NULL\r
2017 );\r
2018 if (!EFI_ERROR (Status)) {\r
2019 DEBUG ((\r
2020 EFI_D_INFO,\r
2021 "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",\r
2022 (UINTN)Bus,\r
2023 (UINTN)Device,\r
2024 (UINTN)Func,\r
2025 (UINTN)PciIoDevice->MrIovCapabilityOffset\r
2026 ));\r
2027 }\r
2028\r
2029 //\r
2030 // Calculate SystemPageSize\r
2031 //\r
2032 if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
2033\r
2034 PciIo->Pci.Read (\r
2035 PciIo,\r
2036 EfiPciIoWidthUint32,\r
2037 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
2038 1,\r
2039 &PciIoDevice->SystemPageSize\r
2040 );\r
2041 DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
2042\r
188e4e84 2043 PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);\r
9060e3ec 2044 ASSERT (PciIoDevice->SystemPageSize != 0);\r
2045\r
2046 PciIo->Pci.Write (\r
2047 PciIo,\r
2048 EfiPciIoWidthUint32,\r
2049 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,\r
2050 1,\r
2051 &PciIoDevice->SystemPageSize\r
2052 );\r
2053 DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
2054 //\r
2055 // Adjust SystemPageSize for Alignment usage later\r
2056 //\r
2057 PciIoDevice->SystemPageSize <<= 12;\r
2058 }\r
2059\r
2060 // Calculate BusReservation for PCI IOV\r
2061 //\r
2062 if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
2063 UINT16 VFStride;\r
2064 UINT16 FirstVFOffset;\r
1ccdbf2a 2065 UINT32 PFRid;\r
9060e3ec 2066 UINT32 LastVF;\r
2067\r
2068 //\r
2069 // Read First FirstVFOffset, InitialVFs, and VFStride\r
2070 //\r
2071 PciIo->Pci.Read (\r
2072 PciIo,\r
2073 EfiPciIoWidthUint16,\r
2074 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,\r
2075 1,\r
2076 &FirstVFOffset\r
2077 );\r
2078 DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)FirstVFOffset));\r
2079\r
2080 PciIo->Pci.Read (\r
2081 PciIo,\r
2082 EfiPciIoWidthUint16,\r
2083 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
2084 1,\r
2085 &PciIoDevice->InitialVFs\r
2086 );\r
2087 DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->InitialVFs));\r
2088\r
2089 PciIo->Pci.Read (\r
2090 PciIo,\r
2091 EfiPciIoWidthUint16,\r
2092 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,\r
2093 1,\r
2094 &VFStride\r
2095 );\r
2096 DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)VFStride));\r
2097\r
2098 //\r
2099 // Calculate LastVF\r
2100 //\r
1ccdbf2a 2101 PFRid = EFI_PCI_RID(Bus, Device, Func);\r
2102 LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\r
9060e3ec 2103\r
2104 //\r
2105 // Calculate ReservedBusNum for this PF\r
2106 //\r
2107 PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
2108 DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->ReservedBusNum));\r
2109 }\r
2110\r
2111\r
2112 //\r
2113 // Initialize the reserved resource list\r
2114 //\r
2115 InitializeListHead (&PciIoDevice->ReservedResourceList);\r
2116\r
2117 //\r
2118 // Initialize the driver list\r
2119 //\r
2120 InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
2121\r
2122 //\r
2123 // Initialize the child list\r
2124 //\r
2125 InitializeListHead (&PciIoDevice->ChildList);\r
2126\r
2127 return PciIoDevice;\r
2128}\r
2129\r
2130/**\r
2131 This routine is used to enumerate entire pci bus system\r
2132 in a given platform.\r
2133\r
2134 It is only called on the second start on the same Root Bridge.\r
2135\r
2136 @param Controller Parent bridge handler.\r
2137\r
2138 @retval EFI_SUCCESS PCI enumeration finished successfully.\r
2139 @retval other Some error occurred when enumerating the pci bus system.\r
2140\r
2141**/\r
2142EFI_STATUS\r
2143PciEnumeratorLight (\r
2144 IN EFI_HANDLE Controller\r
2145 )\r
2146{\r
2147\r
2148 EFI_STATUS Status;\r
2149 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2150 PCI_IO_DEVICE *RootBridgeDev;\r
2151 UINT16 MinBus;\r
2152 UINT16 MaxBus;\r
2153 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
2154\r
2155 MinBus = 0;\r
2156 MaxBus = PCI_MAX_BUS;\r
2157 Descriptors = NULL;\r
2158\r
2159 //\r
2160 // If this root bridge has been already enumerated, then return successfully\r
2161 //\r
2162 if (GetRootBridgeByHandle (Controller) != NULL) {\r
2163 return EFI_SUCCESS;\r
2164 }\r
2165\r
2166 //\r
2167 // Open pci root bridge io protocol\r
2168 //\r
2169 Status = gBS->OpenProtocol (\r
2170 Controller,\r
2171 &gEfiPciRootBridgeIoProtocolGuid,\r
2172 (VOID **) &PciRootBridgeIo,\r
2173 gPciBusDriverBinding.DriverBindingHandle,\r
2174 Controller,\r
2175 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2176 );\r
2177 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
2178 return Status;\r
2179 }\r
2180\r
2181 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
2182\r
2183 if (EFI_ERROR (Status)) {\r
2184 return Status;\r
2185 }\r
2186\r
2187 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
2188\r
2189 //\r
2190 // Create a device node for root bridge device with a NULL host bridge controller handle\r
2191 //\r
2192 RootBridgeDev = CreateRootBridge (Controller);\r
2193\r
2194 if (RootBridgeDev == NULL) {\r
2195 Descriptors++;\r
2196 continue;\r
2197 }\r
2198\r
2199 //\r
2200 // Record the root bridgeio protocol\r
2201 //\r
2202 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
2203\r
2204 Status = PciPciDeviceInfoCollector (\r
2205 RootBridgeDev,\r
2206 (UINT8) MinBus\r
2207 );\r
2208\r
2209 if (!EFI_ERROR (Status)) {\r
2210\r
2211 //\r
2212 // Remove those PCI devices which are rejected when full enumeration\r
2213 //\r
2214 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
2215\r
2216 //\r
2217 // Process option rom light\r
2218 //\r
2219 ProcessOptionRomLight (RootBridgeDev);\r
2220\r
2221 //\r
2222 // Determine attributes for all devices under this root bridge\r
2223 //\r
2224 DetermineDeviceAttribute (RootBridgeDev);\r
2225\r
2226 //\r
2227 // If successfully, insert the node into device pool\r
2228 //\r
2229 InsertRootBridge (RootBridgeDev);\r
2230 } else {\r
2231\r
2232 //\r
2233 // If unsuccessly, destroy the entire node\r
2234 //\r
2235 DestroyRootBridge (RootBridgeDev);\r
2236 }\r
2237\r
2238 Descriptors++;\r
2239 }\r
2240\r
2241 return EFI_SUCCESS;\r
2242}\r
2243\r
2244/**\r
2245 Get bus range from PCI resource descriptor list.\r
2246\r
2247 @param Descriptors A pointer to the address space descriptor.\r
2248 @param MinBus The min bus returned.\r
2249 @param MaxBus The max bus returned.\r
2250 @param BusRange The bus range returned.\r
2251\r
2252 @retval EFI_SUCCESS Successfully got bus range.\r
2253 @retval EFI_NOT_FOUND Can not find the specific bus.\r
2254\r
2255**/\r
2256EFI_STATUS\r
2257PciGetBusRange (\r
2258 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,\r
2259 OUT UINT16 *MinBus,\r
2260 OUT UINT16 *MaxBus,\r
2261 OUT UINT16 *BusRange\r
2262 )\r
2263{\r
2264 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
2265 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
2266 if (MinBus != NULL) {\r
2267 *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
2268 }\r
2269\r
2270 if (MaxBus != NULL) {\r
2271 *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
2272 }\r
2273\r
2274 if (BusRange != NULL) {\r
2275 *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
2276 }\r
2277\r
2278 return EFI_SUCCESS;\r
2279 }\r
2280\r
2281 (*Descriptors)++;\r
2282 }\r
2283\r
2284 return EFI_NOT_FOUND;\r
2285}\r
2286\r
2287/**\r
2288 This routine can be used to start the root bridge.\r
2289\r
2290 @param RootBridgeDev Pci device instance.\r
2291\r
2292 @retval EFI_SUCCESS This device started.\r
2293 @retval other Failed to get PCI Root Bridge I/O protocol.\r
2294\r
2295**/\r
2296EFI_STATUS\r
2297StartManagingRootBridge (\r
2298 IN PCI_IO_DEVICE *RootBridgeDev\r
2299 )\r
2300{\r
2301 EFI_HANDLE RootBridgeHandle;\r
2302 EFI_STATUS Status;\r
2303 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2304\r
2305 //\r
2306 // Get the root bridge handle\r
2307 //\r
2308 RootBridgeHandle = RootBridgeDev->Handle;\r
2309 PciRootBridgeIo = NULL;\r
2310\r
2311 //\r
2312 // Get the pci root bridge io protocol\r
2313 //\r
2314 Status = gBS->OpenProtocol (\r
2315 RootBridgeHandle,\r
2316 &gEfiPciRootBridgeIoProtocolGuid,\r
2317 (VOID **) &PciRootBridgeIo,\r
2318 gPciBusDriverBinding.DriverBindingHandle,\r
2319 RootBridgeHandle,\r
2320 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2321 );\r
2322\r
2323 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
2324 return Status;\r
2325 }\r
2326\r
2327 //\r
2328 // Store the PciRootBridgeIo protocol into root bridge private data\r
2329 //\r
2330 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
2331\r
2332 return EFI_SUCCESS;\r
2333\r
2334}\r
2335\r
2336/**\r
2337 This routine can be used to check whether a PCI device should be rejected when light enumeration.\r
2338\r
2339 @param PciIoDevice Pci device instance.\r
2340\r
2341 @retval TRUE This device should be rejected.\r
2342 @retval FALSE This device shouldn't be rejected.\r
2343\r
2344**/\r
2345BOOLEAN\r
2346IsPciDeviceRejected (\r
2347 IN PCI_IO_DEVICE *PciIoDevice\r
2348 )\r
2349{\r
2350 EFI_STATUS Status;\r
2351 UINT32 TestValue;\r
2352 UINT32 OldValue;\r
2353 UINT32 Mask;\r
2354 UINT8 BarOffset;\r
2355\r
2356 //\r
2357 // PPB should be skip!\r
2358 //\r
2359 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
2360 return FALSE;\r
2361 }\r
2362\r
2363 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
2364 //\r
2365 // Only test base registers for P2C\r
2366 //\r
2367 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
2368\r
2369 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
2370 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2371 if (EFI_ERROR (Status)) {\r
2372 continue;\r
2373 }\r
2374\r
2375 TestValue = TestValue & Mask;\r
2376 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2377 //\r
2378 // The bar isn't programed, so it should be rejected\r
2379 //\r
2380 return TRUE;\r
2381 }\r
2382 }\r
2383\r
2384 return FALSE;\r
2385 }\r
2386\r
2387 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
2388 //\r
2389 // Test PCI devices\r
2390 //\r
2391 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2392 if (EFI_ERROR (Status)) {\r
2393 continue;\r
2394 }\r
2395\r
2396 if ((TestValue & 0x01) != 0) {\r
2397\r
2398 //\r
2399 // IO Bar\r
2400 //\r
2401 Mask = 0xFFFFFFFC;\r
2402 TestValue = TestValue & Mask;\r
2403 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2404 return TRUE;\r
2405 }\r
2406\r
2407 } else {\r
2408\r
2409 //\r
2410 // Mem Bar\r
2411 //\r
2412 Mask = 0xFFFFFFF0;\r
2413 TestValue = TestValue & Mask;\r
2414\r
2415 if ((TestValue & 0x07) == 0x04) {\r
2416\r
2417 //\r
2418 // Mem64 or PMem64\r
2419 //\r
2420 BarOffset += sizeof (UINT32);\r
2421 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2422\r
2423 //\r
2424 // Test its high 32-Bit BAR\r
2425 //\r
2426 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
2427 if (TestValue == OldValue) {\r
2428 return TRUE;\r
2429 }\r
2430 }\r
2431\r
2432 } else {\r
2433\r
2434 //\r
2435 // Mem32 or PMem32\r
2436 //\r
2437 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
2438 return TRUE;\r
2439 }\r
2440 }\r
2441 }\r
2442 }\r
2443\r
2444 return FALSE;\r
2445}\r
2446\r
2447/**\r
2448 Reset all bus number from specific bridge.\r
2449\r
2450 @param Bridge Parent specific bridge.\r
2451 @param StartBusNumber Start bus number.\r
2452\r
2453**/\r
2454VOID\r
2455ResetAllPpbBusNumber (\r
2456 IN PCI_IO_DEVICE *Bridge,\r
2457 IN UINT8 StartBusNumber\r
2458 )\r
2459{\r
2460 EFI_STATUS Status;\r
2461 PCI_TYPE00 Pci;\r
2462 UINT8 Device;\r
2463 UINT32 Register;\r
2464 UINT8 Func;\r
2465 UINT64 Address;\r
2466 UINT8 SecondaryBus;\r
2467 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2468\r
2469 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
2470\r
2471 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
2472 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
2473\r
2474 //\r
2475 // Check to see whether a pci device is present\r
2476 //\r
2477 Status = PciDevicePresent (\r
2478 PciRootBridgeIo,\r
2479 &Pci,\r
2480 StartBusNumber,\r
2481 Device,\r
2482 Func\r
2483 );\r
2484\r
2485 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
2486\r
2487 Register = 0;\r
2488 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
2489 Status = PciRootBridgeIo->Pci.Read (\r
2490 PciRootBridgeIo,\r
2491 EfiPciWidthUint32,\r
2492 Address,\r
2493 1,\r
2494 &Register\r
2495 );\r
2496 SecondaryBus = (UINT8)(Register >> 8);\r
2497\r
2498 if (SecondaryBus != 0) {\r
2499 ResetAllPpbBusNumber (Bridge, SecondaryBus);\r
2500 }\r
2501\r
2502 //\r
2503 // Reset register 18h, 19h, 1Ah on PCI Bridge\r
2504 //\r
2505 Register &= 0xFF000000;\r
2506 Status = PciRootBridgeIo->Pci.Write (\r
2507 PciRootBridgeIo,\r
2508 EfiPciWidthUint32,\r
2509 Address,\r
2510 1,\r
2511 &Register\r
2512 );\r
2513 }\r
2514\r
2515 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
2516 //\r
2517 // Skip sub functions, this is not a multi function device\r
2518 //\r
2519 Func = PCI_MAX_FUNC;\r
2520 }\r
2521 }\r
2522 }\r
2523}\r
2524\r