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