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