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