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