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