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