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