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