]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
MdeModulePkg: Clean up source files
[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 - 2018, 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 PCI supported attributes but not defined in PCI_IO_PROTOCOL
1258 // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.
1259 if (!PciIoDevice->IsPciExp) {
1260 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
1261 }
1262 }
1263
1264 FastB2BSupport = TRUE;
1265
1266 //
1267 // P2C can not support FB2B on the secondary side
1268 //
1269 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1270 FastB2BSupport = FALSE;
1271 }
1272
1273 //
1274 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1275 //
1276 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1277 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
1278
1279 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1280 Status = DetermineDeviceAttribute (Temp);
1281 if (EFI_ERROR (Status)) {
1282 return Status;
1283 }
1284 //
1285 // Detect Fast Bact to Bact support for the device under the bridge
1286 //
1287 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
1288 if (FastB2BSupport && EFI_ERROR (Status)) {
1289 FastB2BSupport = FALSE;
1290 }
1291
1292 CurrentLink = CurrentLink->ForwardLink;
1293 }
1294 //
1295 // Set or clear Fast Back to Back bit for the whole bridge
1296 //
1297 if (!IsListEmpty (&PciIoDevice->ChildList)) {
1298
1299 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
1300
1301 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
1302
1303 if (EFI_ERROR (Status) || (!FastB2BSupport)) {
1304 FastB2BSupport = FALSE;
1305 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1306 } else {
1307 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1308 }
1309 }
1310
1311 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1312 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
1313 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1314 if (FastB2BSupport) {
1315 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1316 } else {
1317 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1318 }
1319
1320 CurrentLink = CurrentLink->ForwardLink;
1321 }
1322 }
1323 //
1324 // End for IsListEmpty
1325 //
1326 return EFI_SUCCESS;
1327 }
1328
1329 /**
1330 This routine is used to update the bar information for those incompatible PCI device.
1331
1332 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1333 Bar information.
1334
1335 @retval EFI_SUCCESS Successfully updated bar information.
1336 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1337
1338 **/
1339 EFI_STATUS
1340 UpdatePciInfo (
1341 IN OUT PCI_IO_DEVICE *PciIoDevice
1342 )
1343 {
1344 EFI_STATUS Status;
1345 UINTN BarIndex;
1346 BOOLEAN SetFlag;
1347 VOID *Configuration;
1348 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1349
1350 Configuration = NULL;
1351 Status = EFI_SUCCESS;
1352
1353 if (gIncompatiblePciDeviceSupport == NULL) {
1354 //
1355 // It can only be supported after the Incompatible PCI Device
1356 // Support Protocol has been installed
1357 //
1358 Status = gBS->LocateProtocol (
1359 &gEfiIncompatiblePciDeviceSupportProtocolGuid,
1360 NULL,
1361 (VOID **) &gIncompatiblePciDeviceSupport
1362 );
1363 }
1364 if (Status == EFI_SUCCESS) {
1365 //
1366 // Check whether the device belongs to incompatible devices from protocol or not
1367 // If it is , then get its special requirement in the ACPI table
1368 //
1369 Status = gIncompatiblePciDeviceSupport->CheckDevice (
1370 gIncompatiblePciDeviceSupport,
1371 PciIoDevice->Pci.Hdr.VendorId,
1372 PciIoDevice->Pci.Hdr.DeviceId,
1373 PciIoDevice->Pci.Hdr.RevisionID,
1374 PciIoDevice->Pci.Device.SubsystemVendorID,
1375 PciIoDevice->Pci.Device.SubsystemID,
1376 &Configuration
1377 );
1378
1379 }
1380
1381 if (EFI_ERROR (Status) || Configuration == NULL ) {
1382 return EFI_UNSUPPORTED;
1383 }
1384
1385 //
1386 // Update PCI device information from the ACPI table
1387 //
1388 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1389
1390 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
1391
1392 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1393 //
1394 // The format is not support
1395 //
1396 break;
1397 }
1398
1399 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
1400 if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&
1401 (Ptr->AddrTranslationOffset != MAX_UINT8) &&
1402 (Ptr->AddrTranslationOffset != BarIndex)
1403 ) {
1404 //
1405 // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
1406 // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
1407 // Comparing against MAX_UINT8 is to keep backward compatibility.
1408 //
1409 continue;
1410 }
1411
1412 SetFlag = FALSE;
1413 switch (Ptr->ResType) {
1414 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1415
1416 //
1417 // Make sure the bar is memory type
1418 //
1419 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
1420 SetFlag = TRUE;
1421
1422 //
1423 // Ignored if granularity is 0.
1424 // Ignored if PCI BAR is I/O or 32-bit memory.
1425 // If PCI BAR is 64-bit memory and granularity is 32, then
1426 // the PCI BAR resource is allocated below 4GB.
1427 // If PCI BAR is 64-bit memory and granularity is 64, then
1428 // the PCI BAR resource is allocated above 4GB.
1429 //
1430 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {
1431 switch (Ptr->AddrSpaceGranularity) {
1432 case 32:
1433 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
1434 case 64:
1435 PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
1436 break;
1437 default:
1438 break;
1439 }
1440 }
1441
1442 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {
1443 switch (Ptr->AddrSpaceGranularity) {
1444 case 32:
1445 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
1446 case 64:
1447 PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
1448 break;
1449 default:
1450 break;
1451 }
1452 }
1453 }
1454 break;
1455
1456 case ACPI_ADDRESS_SPACE_TYPE_IO:
1457
1458 //
1459 // Make sure the bar is IO type
1460 //
1461 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
1462 SetFlag = TRUE;
1463 }
1464 break;
1465 }
1466
1467 if (SetFlag) {
1468
1469 //
1470 // Update the new alignment for the device
1471 //
1472 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
1473
1474 //
1475 // Update the new length for the device
1476 //
1477 if (Ptr->AddrLen != 0) {
1478 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
1479 }
1480 }
1481 }
1482
1483 Ptr++;
1484 }
1485
1486 FreePool (Configuration);
1487
1488 return EFI_SUCCESS;
1489 }
1490
1491 /**
1492 This routine will update the alignment with the new alignment.
1493 Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
1494 backward compatibility.
1495
1496 @param Alignment Input Old alignment. Output updated alignment.
1497 @param NewAlignment New alignment.
1498
1499 **/
1500 VOID
1501 SetNewAlign (
1502 IN OUT UINT64 *Alignment,
1503 IN UINT64 NewAlignment
1504 )
1505 {
1506 UINT64 OldAlignment;
1507 UINTN ShiftBit;
1508
1509 //
1510 // The new alignment is the same as the original,
1511 // so skip it
1512 //
1513 if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {
1514 return ;
1515 }
1516 //
1517 // Check the validity of the parameter
1518 //
1519 if (NewAlignment != EVEN_ALIGN &&
1520 NewAlignment != SQUAD_ALIGN &&
1521 NewAlignment != DQUAD_ALIGN ) {
1522 *Alignment = NewAlignment;
1523 return ;
1524 }
1525
1526 OldAlignment = (*Alignment) + 1;
1527 ShiftBit = 0;
1528
1529 //
1530 // Get the first non-zero hex value of the length
1531 //
1532 while ((OldAlignment & 0x0F) == 0x00) {
1533 OldAlignment = RShiftU64 (OldAlignment, 4);
1534 ShiftBit += 4;
1535 }
1536
1537 //
1538 // Adjust the alignment to even, quad or double quad boundary
1539 //
1540 if (NewAlignment == EVEN_ALIGN) {
1541 if ((OldAlignment & 0x01) != 0) {
1542 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
1543 }
1544 } else if (NewAlignment == SQUAD_ALIGN) {
1545 if ((OldAlignment & 0x03) != 0) {
1546 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
1547 }
1548 } else if (NewAlignment == DQUAD_ALIGN) {
1549 if ((OldAlignment & 0x07) != 0) {
1550 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
1551 }
1552 }
1553
1554 //
1555 // Update the old value
1556 //
1557 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
1558 *Alignment = NewAlignment;
1559
1560 return ;
1561 }
1562
1563 /**
1564 Parse PCI IOV VF bar information and fill them into PCI device instance.
1565
1566 @param PciIoDevice Pci device instance.
1567 @param Offset Bar offset.
1568 @param BarIndex Bar index.
1569
1570 @return Next bar offset.
1571
1572 **/
1573 UINTN
1574 PciIovParseVfBar (
1575 IN PCI_IO_DEVICE *PciIoDevice,
1576 IN UINTN Offset,
1577 IN UINTN BarIndex
1578 )
1579 {
1580 UINT32 Value;
1581 UINT32 OriginalValue;
1582 UINT32 Mask;
1583 EFI_STATUS Status;
1584
1585 //
1586 // Ensure it is called properly
1587 //
1588 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
1589 if (PciIoDevice->SrIovCapabilityOffset == 0) {
1590 return 0;
1591 }
1592
1593 OriginalValue = 0;
1594 Value = 0;
1595
1596 Status = VfBarExisted (
1597 PciIoDevice,
1598 Offset,
1599 &Value,
1600 &OriginalValue
1601 );
1602
1603 if (EFI_ERROR (Status)) {
1604 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
1605 PciIoDevice->VfPciBar[BarIndex].Length = 0;
1606 PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
1607
1608 //
1609 // Scan all the BARs anyway
1610 //
1611 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
1612 return Offset + 4;
1613 }
1614
1615 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
1616 if ((Value & 0x01) != 0) {
1617 //
1618 // Device I/Os. Impossible
1619 //
1620 ASSERT (FALSE);
1621 return Offset + 4;
1622
1623 } else {
1624
1625 Mask = 0xfffffff0;
1626
1627 PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1628
1629 switch (Value & 0x07) {
1630
1631 //
1632 //memory space; anywhere in 32 bit address space
1633 //
1634 case 0x00:
1635 if ((Value & 0x08) != 0) {
1636 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
1637 } else {
1638 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;
1639 }
1640
1641 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1642 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1643
1644 //
1645 // Adjust Length
1646 //
1647 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
1648 //
1649 // Adjust Alignment
1650 //
1651 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1652 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1653 }
1654
1655 break;
1656
1657 //
1658 // memory space; anywhere in 64 bit address space
1659 //
1660 case 0x04:
1661 if ((Value & 0x08) != 0) {
1662 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
1663 } else {
1664 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
1665 }
1666
1667 //
1668 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1669 // is regarded as an extension for the first bar. As a result
1670 // the sizing will be conducted on combined 64 bit value
1671 // Here just store the masked first 32bit value for future size
1672 // calculation
1673 //
1674 PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask;
1675 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1676
1677 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1678 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1679 }
1680
1681 //
1682 // Increment the offset to point to next DWORD
1683 //
1684 Offset += 4;
1685
1686 Status = VfBarExisted (
1687 PciIoDevice,
1688 Offset,
1689 &Value,
1690 &OriginalValue
1691 );
1692
1693 if (EFI_ERROR (Status)) {
1694 return Offset + 4;
1695 }
1696
1697 //
1698 // Fix the length to support some spefic 64 bit BAR
1699 //
1700 Value |= ((UINT32) -1 << HighBitSet32 (Value));
1701
1702 //
1703 // Calculate the size of 64bit bar
1704 //
1705 PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
1706
1707 PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
1708 PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;
1709 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1710
1711 //
1712 // Adjust Length
1713 //
1714 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
1715 //
1716 // Adjust Alignment
1717 //
1718 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1719 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1720 }
1721
1722 break;
1723
1724 //
1725 // reserved
1726 //
1727 default:
1728 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
1729 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1730 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1731
1732 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1733 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1734 }
1735
1736 break;
1737 }
1738 }
1739
1740 //
1741 // Check the length again so as to keep compatible with some special bars
1742 //
1743 if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {
1744 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
1745 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
1746 PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
1747 }
1748
1749 //
1750 // Increment number of bar
1751 //
1752 return Offset + 4;
1753 }
1754
1755 /**
1756 Parse PCI bar information and fill them into PCI device instance.
1757
1758 @param PciIoDevice Pci device instance.
1759 @param Offset Bar offset.
1760 @param BarIndex Bar index.
1761
1762 @return Next bar offset.
1763
1764 **/
1765 UINTN
1766 PciParseBar (
1767 IN PCI_IO_DEVICE *PciIoDevice,
1768 IN UINTN Offset,
1769 IN UINTN BarIndex
1770 )
1771 {
1772 UINT32 Value;
1773 UINT32 OriginalValue;
1774 UINT32 Mask;
1775 EFI_STATUS Status;
1776
1777 OriginalValue = 0;
1778 Value = 0;
1779
1780 Status = BarExisted (
1781 PciIoDevice,
1782 Offset,
1783 &Value,
1784 &OriginalValue
1785 );
1786
1787 if (EFI_ERROR (Status)) {
1788 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1789 PciIoDevice->PciBar[BarIndex].Length = 0;
1790 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1791
1792 //
1793 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1794 //
1795 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
1796 return Offset + 4;
1797 }
1798
1799 PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;
1800 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
1801 if ((Value & 0x01) != 0) {
1802 //
1803 // Device I/Os
1804 //
1805 Mask = 0xfffffffc;
1806
1807 if ((Value & 0xFFFF0000) != 0) {
1808 //
1809 // It is a IO32 bar
1810 //
1811 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
1812 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
1813 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1814
1815 } else {
1816 //
1817 // It is a IO16 bar
1818 //
1819 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
1820 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
1821 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1822
1823 }
1824 //
1825 // Workaround. Some platforms inplement IO bar with 0 length
1826 // Need to treat it as no-bar
1827 //
1828 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1829 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;
1830 }
1831
1832 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1833
1834 } else {
1835
1836 Mask = 0xfffffff0;
1837
1838 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1839
1840 switch (Value & 0x07) {
1841
1842 //
1843 //memory space; anywhere in 32 bit address space
1844 //
1845 case 0x00:
1846 if ((Value & 0x08) != 0) {
1847 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
1848 } else {
1849 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
1850 }
1851
1852 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1853 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
1854 //
1855 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1856 //
1857 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
1858 } else {
1859 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1860 }
1861 break;
1862
1863 //
1864 // memory space; anywhere in 64 bit address space
1865 //
1866 case 0x04:
1867 if ((Value & 0x08) != 0) {
1868 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
1869 } else {
1870 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
1871 }
1872
1873 //
1874 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1875 // is regarded as an extension for the first bar. As a result
1876 // the sizing will be conducted on combined 64 bit value
1877 // Here just store the masked first 32bit value for future size
1878 // calculation
1879 //
1880 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
1881 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1882
1883 //
1884 // Increment the offset to point to next DWORD
1885 //
1886 Offset += 4;
1887
1888 Status = BarExisted (
1889 PciIoDevice,
1890 Offset,
1891 &Value,
1892 &OriginalValue
1893 );
1894
1895 if (EFI_ERROR (Status)) {
1896 //
1897 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1898 //
1899 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1900 //
1901 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1902 //
1903 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1904 return Offset + 4;
1905 }
1906 }
1907
1908 //
1909 // Fix the length to support some spefic 64 bit BAR
1910 //
1911 if (Value == 0) {
1912 DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
1913 Value = (UINT32) -1;
1914 } else {
1915 Value |= ((UINT32)(-1) << HighBitSet32 (Value));
1916 }
1917
1918 //
1919 // Calculate the size of 64bit bar
1920 //
1921 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
1922
1923 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
1924 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
1925 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
1926 //
1927 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1928 //
1929 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
1930 } else {
1931 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1932 }
1933
1934 break;
1935
1936 //
1937 // reserved
1938 //
1939 default:
1940 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1941 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1942 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
1943 //
1944 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1945 //
1946 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
1947 } else {
1948 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1949 }
1950 break;
1951 }
1952 }
1953
1954 //
1955 // Check the length again so as to keep compatible with some special bars
1956 //
1957 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1958 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1959 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1960 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1961 }
1962
1963 //
1964 // Increment number of bar
1965 //
1966 return Offset + 4;
1967 }
1968
1969 /**
1970 This routine is used to initialize the bar of a PCI device.
1971
1972 @param PciIoDevice Pci device instance.
1973
1974 @note It can be called typically when a device is going to be rejected.
1975
1976 **/
1977 VOID
1978 InitializePciDevice (
1979 IN PCI_IO_DEVICE *PciIoDevice
1980 )
1981 {
1982 EFI_PCI_IO_PROTOCOL *PciIo;
1983 UINT8 Offset;
1984
1985 PciIo = &(PciIoDevice->PciIo);
1986
1987 //
1988 // Put all the resource apertures
1989 // Resource base is set to all ones so as to indicate its resource
1990 // has not been alloacted
1991 //
1992 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
1993 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
1994 }
1995 }
1996
1997 /**
1998 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1999
2000 @param PciIoDevice PCI-PCI bridge device instance.
2001
2002 **/
2003 VOID
2004 InitializePpb (
2005 IN PCI_IO_DEVICE *PciIoDevice
2006 )
2007 {
2008 EFI_PCI_IO_PROTOCOL *PciIo;
2009
2010 PciIo = &(PciIoDevice->PciIo);
2011
2012 //
2013 // Put all the resource apertures including IO16
2014 // Io32, pMem32, pMem64 to quiescent state
2015 // Resource base all ones, Resource limit all zeros
2016 //
2017 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
2018 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
2019
2020 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
2021 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
2022
2023 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
2024 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
2025
2026 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
2027 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
2028
2029 //
2030 // Don't support use io32 as for now
2031 //
2032 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
2033 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
2034
2035 //
2036 // Force Interrupt line to zero for cards that come up randomly
2037 //
2038 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
2039 }
2040
2041 /**
2042 This routine is used to initialize the bar of a PCI Card Bridge device.
2043
2044 @param PciIoDevice PCI Card bridge device.
2045
2046 **/
2047 VOID
2048 InitializeP2C (
2049 IN PCI_IO_DEVICE *PciIoDevice
2050 )
2051 {
2052 EFI_PCI_IO_PROTOCOL *PciIo;
2053
2054 PciIo = &(PciIoDevice->PciIo);
2055
2056 //
2057 // Put all the resource apertures including IO16
2058 // Io32, pMem32, pMem64 to quiescent state(
2059 // Resource base all ones, Resource limit all zeros
2060 //
2061 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
2062 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
2063
2064 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
2065 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
2066
2067 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
2068 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
2069
2070 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
2071 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
2072
2073 //
2074 // Force Interrupt line to zero for cards that come up randomly
2075 //
2076 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
2077 }
2078
2079 /**
2080 Create and initiliaze general PCI I/O device instance for
2081 PCI device/bridge device/hotplug bridge device.
2082
2083 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2084 @param Pci Input Pci information block.
2085 @param Bus Device Bus NO.
2086 @param Device Device device NO.
2087 @param Func Device func NO.
2088
2089 @return Instance of PCI device. NULL means no instance created.
2090
2091 **/
2092 PCI_IO_DEVICE *
2093 CreatePciIoDevice (
2094 IN PCI_IO_DEVICE *Bridge,
2095 IN PCI_TYPE00 *Pci,
2096 IN UINT8 Bus,
2097 IN UINT8 Device,
2098 IN UINT8 Func
2099 )
2100 {
2101 PCI_IO_DEVICE *PciIoDevice;
2102 EFI_PCI_IO_PROTOCOL *PciIo;
2103 EFI_STATUS Status;
2104
2105 PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
2106 if (PciIoDevice == NULL) {
2107 return NULL;
2108 }
2109
2110 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
2111 PciIoDevice->Handle = NULL;
2112 PciIoDevice->PciRootBridgeIo = Bridge->PciRootBridgeIo;
2113 PciIoDevice->DevicePath = NULL;
2114 PciIoDevice->BusNumber = Bus;
2115 PciIoDevice->DeviceNumber = Device;
2116 PciIoDevice->FunctionNumber = Func;
2117 PciIoDevice->Decodes = 0;
2118
2119 if (gFullEnumeration) {
2120 PciIoDevice->Allocated = FALSE;
2121 } else {
2122 PciIoDevice->Allocated = TRUE;
2123 }
2124
2125 PciIoDevice->Registered = FALSE;
2126 PciIoDevice->Attributes = 0;
2127 PciIoDevice->Supports = 0;
2128 PciIoDevice->BusOverride = FALSE;
2129 PciIoDevice->AllOpRomProcessed = FALSE;
2130
2131 PciIoDevice->IsPciExp = FALSE;
2132
2133 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
2134
2135 //
2136 // Initialize the PCI I/O instance structure
2137 //
2138 InitializePciIoInstance (PciIoDevice);
2139 InitializePciDriverOverrideInstance (PciIoDevice);
2140 InitializePciLoadFile2 (PciIoDevice);
2141 PciIo = &PciIoDevice->PciIo;
2142
2143 //
2144 // Create a device path for this PCI device and store it into its private data
2145 //
2146 CreatePciDevicePath (
2147 Bridge->DevicePath,
2148 PciIoDevice
2149 );
2150
2151 //
2152 // Detect if PCI Express Device
2153 //
2154 PciIoDevice->PciExpressCapabilityOffset = 0;
2155 Status = LocateCapabilityRegBlock (
2156 PciIoDevice,
2157 EFI_PCI_CAPABILITY_ID_PCIEXP,
2158 &PciIoDevice->PciExpressCapabilityOffset,
2159 NULL
2160 );
2161 if (!EFI_ERROR (Status)) {
2162 PciIoDevice->IsPciExp = TRUE;
2163 }
2164
2165 if (PcdGetBool (PcdAriSupport)) {
2166 //
2167 // Check if the device is an ARI device.
2168 //
2169 Status = LocatePciExpressCapabilityRegBlock (
2170 PciIoDevice,
2171 EFI_PCIE_CAPABILITY_ID_ARI,
2172 &PciIoDevice->AriCapabilityOffset,
2173 NULL
2174 );
2175 if (!EFI_ERROR (Status)) {
2176 //
2177 // We need to enable ARI feature before calculate BusReservation,
2178 // because FirstVFOffset and VFStride may change after that.
2179 //
2180 EFI_PCI_IO_PROTOCOL *ParentPciIo;
2181 UINT32 Data32;
2182
2183 //
2184 // Check if its parent supports ARI forwarding.
2185 //
2186 ParentPciIo = &Bridge->PciIo;
2187 ParentPciIo->Pci.Read (
2188 ParentPciIo,
2189 EfiPciIoWidthUint32,
2190 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
2191 1,
2192 &Data32
2193 );
2194 if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
2195 //
2196 // ARI forward support in bridge, so enable it.
2197 //
2198 ParentPciIo->Pci.Read (
2199 ParentPciIo,
2200 EfiPciIoWidthUint32,
2201 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
2202 1,
2203 &Data32
2204 );
2205 if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
2206 Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
2207 ParentPciIo->Pci.Write (
2208 ParentPciIo,
2209 EfiPciIoWidthUint32,
2210 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
2211 1,
2212 &Data32
2213 );
2214 DEBUG ((
2215 EFI_D_INFO,
2216 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
2217 Bridge->BusNumber,
2218 Bridge->DeviceNumber,
2219 Bridge->FunctionNumber
2220 ));
2221 }
2222 }
2223
2224 DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
2225 }
2226 }
2227
2228 //
2229 // Initialization for SR-IOV
2230 //
2231
2232 if (PcdGetBool (PcdSrIovSupport)) {
2233 Status = LocatePciExpressCapabilityRegBlock (
2234 PciIoDevice,
2235 EFI_PCIE_CAPABILITY_ID_SRIOV,
2236 &PciIoDevice->SrIovCapabilityOffset,
2237 NULL
2238 );
2239 if (!EFI_ERROR (Status)) {
2240 UINT32 SupportedPageSize;
2241 UINT16 VFStride;
2242 UINT16 FirstVFOffset;
2243 UINT16 Data16;
2244 UINT32 PFRid;
2245 UINT32 LastVF;
2246
2247 //
2248 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2249 //
2250 if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) {
2251 PciIo->Pci.Read (
2252 PciIo,
2253 EfiPciIoWidthUint16,
2254 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
2255 1,
2256 &Data16
2257 );
2258 Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
2259 PciIo->Pci.Write (
2260 PciIo,
2261 EfiPciIoWidthUint16,
2262 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
2263 1,
2264 &Data16
2265 );
2266 }
2267
2268 //
2269 // Calculate SystemPageSize
2270 //
2271
2272 PciIo->Pci.Read (
2273 PciIo,
2274 EfiPciIoWidthUint32,
2275 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
2276 1,
2277 &SupportedPageSize
2278 );
2279 PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);
2280 ASSERT (PciIoDevice->SystemPageSize != 0);
2281
2282 PciIo->Pci.Write (
2283 PciIo,
2284 EfiPciIoWidthUint32,
2285 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
2286 1,
2287 &PciIoDevice->SystemPageSize
2288 );
2289 //
2290 // Adjust SystemPageSize for Alignment usage later
2291 //
2292 PciIoDevice->SystemPageSize <<= 12;
2293
2294 //
2295 // Calculate BusReservation for PCI IOV
2296 //
2297
2298 //
2299 // Read First FirstVFOffset, InitialVFs, and VFStride
2300 //
2301 PciIo->Pci.Read (
2302 PciIo,
2303 EfiPciIoWidthUint16,
2304 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
2305 1,
2306 &FirstVFOffset
2307 );
2308 PciIo->Pci.Read (
2309 PciIo,
2310 EfiPciIoWidthUint16,
2311 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
2312 1,
2313 &PciIoDevice->InitialVFs
2314 );
2315 PciIo->Pci.Read (
2316 PciIo,
2317 EfiPciIoWidthUint16,
2318 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
2319 1,
2320 &VFStride
2321 );
2322 //
2323 // Calculate LastVF
2324 //
2325 PFRid = EFI_PCI_RID(Bus, Device, Func);
2326 LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
2327
2328 //
2329 // Calculate ReservedBusNum for this PF
2330 //
2331 PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
2332
2333 DEBUG ((
2334 EFI_D_INFO,
2335 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
2336 SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
2337 ));
2338 DEBUG ((
2339 EFI_D_INFO,
2340 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
2341 PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset
2342 ));
2343 }
2344 }
2345
2346 if (PcdGetBool (PcdMrIovSupport)) {
2347 Status = LocatePciExpressCapabilityRegBlock (
2348 PciIoDevice,
2349 EFI_PCIE_CAPABILITY_ID_MRIOV,
2350 &PciIoDevice->MrIovCapabilityOffset,
2351 NULL
2352 );
2353 if (!EFI_ERROR (Status)) {
2354 DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
2355 }
2356 }
2357
2358 //
2359 // Initialize the reserved resource list
2360 //
2361 InitializeListHead (&PciIoDevice->ReservedResourceList);
2362
2363 //
2364 // Initialize the driver list
2365 //
2366 InitializeListHead (&PciIoDevice->OptionRomDriverList);
2367
2368 //
2369 // Initialize the child list
2370 //
2371 InitializeListHead (&PciIoDevice->ChildList);
2372
2373 return PciIoDevice;
2374 }
2375
2376 /**
2377 This routine is used to enumerate entire pci bus system
2378 in a given platform.
2379
2380 It is only called on the second start on the same Root Bridge.
2381
2382 @param Controller Parent bridge handler.
2383
2384 @retval EFI_SUCCESS PCI enumeration finished successfully.
2385 @retval other Some error occurred when enumerating the pci bus system.
2386
2387 **/
2388 EFI_STATUS
2389 PciEnumeratorLight (
2390 IN EFI_HANDLE Controller
2391 )
2392 {
2393
2394 EFI_STATUS Status;
2395 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2396 PCI_IO_DEVICE *RootBridgeDev;
2397 UINT16 MinBus;
2398 UINT16 MaxBus;
2399 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
2400
2401 MinBus = 0;
2402 MaxBus = PCI_MAX_BUS;
2403 Descriptors = NULL;
2404
2405 //
2406 // If this root bridge has been already enumerated, then return successfully
2407 //
2408 if (GetRootBridgeByHandle (Controller) != NULL) {
2409 return EFI_SUCCESS;
2410 }
2411
2412 //
2413 // Open pci root bridge io protocol
2414 //
2415 Status = gBS->OpenProtocol (
2416 Controller,
2417 &gEfiPciRootBridgeIoProtocolGuid,
2418 (VOID **) &PciRootBridgeIo,
2419 gPciBusDriverBinding.DriverBindingHandle,
2420 Controller,
2421 EFI_OPEN_PROTOCOL_BY_DRIVER
2422 );
2423 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
2424 return Status;
2425 }
2426
2427 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
2428
2429 if (EFI_ERROR (Status)) {
2430 return Status;
2431 }
2432
2433 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
2434
2435 //
2436 // Create a device node for root bridge device with a NULL host bridge controller handle
2437 //
2438 RootBridgeDev = CreateRootBridge (Controller);
2439
2440 if (RootBridgeDev == NULL) {
2441 Descriptors++;
2442 continue;
2443 }
2444
2445 //
2446 // Record the root bridgeio protocol
2447 //
2448 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
2449
2450 Status = PciPciDeviceInfoCollector (
2451 RootBridgeDev,
2452 (UINT8) MinBus
2453 );
2454
2455 if (!EFI_ERROR (Status)) {
2456
2457 //
2458 // Remove those PCI devices which are rejected when full enumeration
2459 //
2460 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
2461
2462 //
2463 // Process option rom light
2464 //
2465 ProcessOptionRomLight (RootBridgeDev);
2466
2467 //
2468 // Determine attributes for all devices under this root bridge
2469 //
2470 DetermineDeviceAttribute (RootBridgeDev);
2471
2472 //
2473 // If successfully, insert the node into device pool
2474 //
2475 InsertRootBridge (RootBridgeDev);
2476 } else {
2477
2478 //
2479 // If unsuccessly, destroy the entire node
2480 //
2481 DestroyRootBridge (RootBridgeDev);
2482 }
2483
2484 Descriptors++;
2485 }
2486
2487 return EFI_SUCCESS;
2488 }
2489
2490 /**
2491 Get bus range from PCI resource descriptor list.
2492
2493 @param Descriptors A pointer to the address space descriptor.
2494 @param MinBus The min bus returned.
2495 @param MaxBus The max bus returned.
2496 @param BusRange The bus range returned.
2497
2498 @retval EFI_SUCCESS Successfully got bus range.
2499 @retval EFI_NOT_FOUND Can not find the specific bus.
2500
2501 **/
2502 EFI_STATUS
2503 PciGetBusRange (
2504 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
2505 OUT UINT16 *MinBus,
2506 OUT UINT16 *MaxBus,
2507 OUT UINT16 *BusRange
2508 )
2509 {
2510 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2511 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
2512 if (MinBus != NULL) {
2513 *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
2514 }
2515
2516 if (MaxBus != NULL) {
2517 *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
2518 }
2519
2520 if (BusRange != NULL) {
2521 *BusRange = (UINT16) (*Descriptors)->AddrLen;
2522 }
2523
2524 return EFI_SUCCESS;
2525 }
2526
2527 (*Descriptors)++;
2528 }
2529
2530 return EFI_NOT_FOUND;
2531 }
2532
2533 /**
2534 This routine can be used to start the root bridge.
2535
2536 @param RootBridgeDev Pci device instance.
2537
2538 @retval EFI_SUCCESS This device started.
2539 @retval other Failed to get PCI Root Bridge I/O protocol.
2540
2541 **/
2542 EFI_STATUS
2543 StartManagingRootBridge (
2544 IN PCI_IO_DEVICE *RootBridgeDev
2545 )
2546 {
2547 EFI_HANDLE RootBridgeHandle;
2548 EFI_STATUS Status;
2549 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2550
2551 //
2552 // Get the root bridge handle
2553 //
2554 RootBridgeHandle = RootBridgeDev->Handle;
2555 PciRootBridgeIo = NULL;
2556
2557 //
2558 // Get the pci root bridge io protocol
2559 //
2560 Status = gBS->OpenProtocol (
2561 RootBridgeHandle,
2562 &gEfiPciRootBridgeIoProtocolGuid,
2563 (VOID **) &PciRootBridgeIo,
2564 gPciBusDriverBinding.DriverBindingHandle,
2565 RootBridgeHandle,
2566 EFI_OPEN_PROTOCOL_BY_DRIVER
2567 );
2568
2569 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
2570 return Status;
2571 }
2572
2573 //
2574 // Store the PciRootBridgeIo protocol into root bridge private data
2575 //
2576 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
2577
2578 return EFI_SUCCESS;
2579
2580 }
2581
2582 /**
2583 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2584
2585 @param PciIoDevice Pci device instance.
2586
2587 @retval TRUE This device should be rejected.
2588 @retval FALSE This device shouldn't be rejected.
2589
2590 **/
2591 BOOLEAN
2592 IsPciDeviceRejected (
2593 IN PCI_IO_DEVICE *PciIoDevice
2594 )
2595 {
2596 EFI_STATUS Status;
2597 UINT32 TestValue;
2598 UINT32 OldValue;
2599 UINT32 Mask;
2600 UINT8 BarOffset;
2601
2602 //
2603 // PPB should be skip!
2604 //
2605 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
2606 return FALSE;
2607 }
2608
2609 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
2610 //
2611 // Only test base registers for P2C
2612 //
2613 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
2614
2615 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2616 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2617 if (EFI_ERROR (Status)) {
2618 continue;
2619 }
2620
2621 TestValue = TestValue & Mask;
2622 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2623 //
2624 // The bar isn't programed, so it should be rejected
2625 //
2626 return TRUE;
2627 }
2628 }
2629
2630 return FALSE;
2631 }
2632
2633 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
2634 //
2635 // Test PCI devices
2636 //
2637 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2638 if (EFI_ERROR (Status)) {
2639 continue;
2640 }
2641
2642 if ((TestValue & 0x01) != 0) {
2643
2644 //
2645 // IO Bar
2646 //
2647 Mask = 0xFFFFFFFC;
2648 TestValue = TestValue & Mask;
2649 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2650 return TRUE;
2651 }
2652
2653 } else {
2654
2655 //
2656 // Mem Bar
2657 //
2658 Mask = 0xFFFFFFF0;
2659 TestValue = TestValue & Mask;
2660
2661 if ((TestValue & 0x07) == 0x04) {
2662
2663 //
2664 // Mem64 or PMem64
2665 //
2666 BarOffset += sizeof (UINT32);
2667 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2668
2669 //
2670 // Test its high 32-Bit BAR
2671 //
2672 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2673 if (TestValue == OldValue) {
2674 return TRUE;
2675 }
2676 }
2677
2678 } else {
2679
2680 //
2681 // Mem32 or PMem32
2682 //
2683 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2684 return TRUE;
2685 }
2686 }
2687 }
2688 }
2689
2690 return FALSE;
2691 }
2692
2693 /**
2694 Reset all bus number from specific bridge.
2695
2696 @param Bridge Parent specific bridge.
2697 @param StartBusNumber Start bus number.
2698
2699 **/
2700 VOID
2701 ResetAllPpbBusNumber (
2702 IN PCI_IO_DEVICE *Bridge,
2703 IN UINT8 StartBusNumber
2704 )
2705 {
2706 EFI_STATUS Status;
2707 PCI_TYPE00 Pci;
2708 UINT8 Device;
2709 UINT32 Register;
2710 UINT8 Func;
2711 UINT64 Address;
2712 UINT8 SecondaryBus;
2713 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2714
2715 PciRootBridgeIo = Bridge->PciRootBridgeIo;
2716
2717 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
2718 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
2719
2720 //
2721 // Check to see whether a pci device is present
2722 //
2723 Status = PciDevicePresent (
2724 PciRootBridgeIo,
2725 &Pci,
2726 StartBusNumber,
2727 Device,
2728 Func
2729 );
2730
2731 if (EFI_ERROR (Status) && Func == 0) {
2732 //
2733 // go to next device if there is no Function 0
2734 //
2735 break;
2736 }
2737
2738 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
2739
2740 Register = 0;
2741 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
2742 Status = PciRootBridgeIo->Pci.Read (
2743 PciRootBridgeIo,
2744 EfiPciWidthUint32,
2745 Address,
2746 1,
2747 &Register
2748 );
2749 SecondaryBus = (UINT8)(Register >> 8);
2750
2751 if (SecondaryBus != 0) {
2752 ResetAllPpbBusNumber (Bridge, SecondaryBus);
2753 }
2754
2755 //
2756 // Reset register 18h, 19h, 1Ah on PCI Bridge
2757 //
2758 Register &= 0xFF000000;
2759 Status = PciRootBridgeIo->Pci.Write (
2760 PciRootBridgeIo,
2761 EfiPciWidthUint32,
2762 Address,
2763 1,
2764 &Register
2765 );
2766 }
2767
2768 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
2769 //
2770 // Skip sub functions, this is not a multi function device
2771 //
2772 Func = PCI_MAX_FUNC;
2773 }
2774 }
2775 }
2776 }
2777