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