]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
Code scrub for PCI Bus module and PciIncompatibleDeviceSupportLib module.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
1 /** @file
2 PCI emumeration support functions implementation for PCI Bus module.
3
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PciBus.h"
16
17 /**
18 This routine is used to check whether the pci device is present.
19
20 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
21 @param Pci Output buffer for PCI device configuration space.
22 @param Bus PCI bus NO.
23 @param Device PCI device NO.
24 @param Func PCI Func NO.
25
26 @retval EFI_NOT_FOUND PCI device not present.
27 @retval EFI_SUCCESS PCI device is found.
28
29 **/
30 EFI_STATUS
31 PciDevicePresent (
32 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
33 OUT PCI_TYPE00 *Pci,
34 IN UINT8 Bus,
35 IN UINT8 Device,
36 IN UINT8 Func
37 )
38 {
39 UINT64 Address;
40 EFI_STATUS Status;
41
42 //
43 // Create PCI address map in terms of Bus, Device and Func
44 //
45 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
46
47 //
48 // Read the Vendor ID register
49 //
50 Status = PciRootBridgeIoRead (
51 PciRootBridgeIo,
52 NULL,
53 EfiPciWidthUint32,
54 Address,
55 1,
56 Pci
57 );
58
59 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
60 //
61 // Read the entire config header for the device
62 //
63 Status = PciRootBridgeIoRead (
64 PciRootBridgeIo,
65 NULL,
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 = PciIoRead (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 if (!IS_PCI_BRIDGE (Pci)) {
217
218 if (IS_CARDBUS_BRIDGE (Pci)) {
219 PciIoDevice = GatherP2CInfo (
220 Bridge,
221 Pci,
222 Bus,
223 Device,
224 Func
225 );
226 if ((PciIoDevice != NULL) && gFullEnumeration) {
227 InitializeP2C (PciIoDevice);
228 }
229 } else {
230
231 //
232 // Create private data for Pci Device
233 //
234 PciIoDevice = GatherDeviceInfo (
235 Bridge,
236 Pci,
237 Bus,
238 Device,
239 Func
240 );
241
242 }
243
244 } else {
245
246 //
247 // Create private data for PPB
248 //
249 PciIoDevice = GatherPpbInfo (
250 Bridge,
251 Pci,
252 Bus,
253 Device,
254 Func
255 );
256
257 //
258 // Special initialization for PPB including making the PPB quiet
259 //
260 if ((PciIoDevice != NULL) && gFullEnumeration) {
261 InitializePpb (PciIoDevice);
262 }
263 }
264
265 if (PciIoDevice == NULL) {
266 return EFI_OUT_OF_RESOURCES;
267 }
268
269 //
270 // Update the bar information for this PCI device so as to support some specific device
271 //
272 UpdatePciInfo (PciIoDevice);
273
274 if (PciIoDevice->DevicePath == NULL) {
275 return EFI_OUT_OF_RESOURCES;
276 }
277
278 //
279 // Detect this function has option rom
280 //
281 if (gFullEnumeration) {
282
283 if (!IS_CARDBUS_BRIDGE (Pci)) {
284
285 GetOpRomInfo (PciIoDevice);
286
287 }
288
289 ResetPowerManagementFeature (PciIoDevice);
290
291 }
292
293 //
294 // Insert it into a global tree for future reference
295 //
296 InsertPciDevice (Bridge, PciIoDevice);
297
298 //
299 // Determine PCI device attributes
300 //
301
302 if (PciDevice != NULL) {
303 *PciDevice = PciIoDevice;
304 }
305
306 return EFI_SUCCESS;
307 }
308
309 /**
310 Create PCI device instance for PCI device.
311
312 @param Bridge Parent bridge instance.
313 @param Pci Input PCI device information block.
314 @param Bus PCI device Bus NO.
315 @param Device PCI device Device NO.
316 @param Func PCI device's func NO.
317
318 @return Created PCI device instance.
319
320 **/
321 PCI_IO_DEVICE *
322 GatherDeviceInfo (
323 IN PCI_IO_DEVICE *Bridge,
324 IN PCI_TYPE00 *Pci,
325 IN UINT8 Bus,
326 IN UINT8 Device,
327 IN UINT8 Func
328 )
329 {
330 UINTN Offset;
331 UINTN BarIndex;
332 PCI_IO_DEVICE *PciIoDevice;
333 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
334
335 PciRootBridgeIo = Bridge->PciRootBridgeIo;
336 PciIoDevice = CreatePciIoDevice (
337 PciRootBridgeIo,
338 Pci,
339 Bus,
340 Device,
341 Func
342 );
343
344 if (PciIoDevice == NULL) {
345 return NULL;
346 }
347
348 //
349 // Create a device path for this PCI device and store it into its private data
350 //
351 CreatePciDevicePath (
352 Bridge->DevicePath,
353 PciIoDevice
354 );
355
356 //
357 // If it is a full enumeration, disconnect the device in advance
358 //
359 if (gFullEnumeration) {
360
361 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
362
363 }
364
365 //
366 // Start to parse the bars
367 //
368 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
369 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
370 }
371
372 return PciIoDevice;
373 }
374
375 /**
376 Create PCI device instance for PCI-PCI bridge.
377
378 @param Bridge Parent bridge instance.
379 @param Pci Input PCI device information block.
380 @param Bus PCI device Bus NO.
381 @param Device PCI device Device NO.
382 @param Func PCI device's func NO.
383
384 @return Created PCI device instance.
385
386 **/
387 PCI_IO_DEVICE *
388 GatherPpbInfo (
389 IN PCI_IO_DEVICE *Bridge,
390 IN PCI_TYPE00 *Pci,
391 IN UINT8 Bus,
392 IN UINT8 Device,
393 IN UINT8 Func
394 )
395 {
396 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
397 PCI_IO_DEVICE *PciIoDevice;
398 EFI_STATUS Status;
399 UINT8 Value;
400 EFI_PCI_IO_PROTOCOL *PciIo;
401 UINT8 Temp;
402
403 PciRootBridgeIo = Bridge->PciRootBridgeIo;
404 PciIoDevice = CreatePciIoDevice (
405 PciRootBridgeIo,
406 Pci,
407 Bus,
408 Device,
409 Func
410 );
411
412 if (PciIoDevice == NULL) {
413 return NULL;
414 }
415
416 //
417 // Create a device path for this PCI device and store it into its private data
418 //
419 CreatePciDevicePath (
420 Bridge->DevicePath,
421 PciIoDevice
422 );
423
424 if (gFullEnumeration) {
425 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
426
427 //
428 // Initalize the bridge control register
429 //
430 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
431
432 }
433
434 //
435 // PPB can have two BARs
436 //
437 if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
438 //
439 // Not 64-bit bar
440 //
441 PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
442 }
443
444 PciIo = &PciIoDevice->PciIo;
445
446 //
447 // Test whether it support 32 decode or not
448 //
449 PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
450 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
451 PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
452 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
453
454 if (Value != 0) {
455 if ((Value & 0x01) != 0) {
456 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
457 } else {
458 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
459 }
460 }
461
462 Status = BarExisted (
463 PciIoDevice,
464 0x24,
465 NULL,
466 NULL
467 );
468
469 //
470 // Test if it supports 64 memory or not
471 //
472 if (!EFI_ERROR (Status)) {
473
474 Status = BarExisted (
475 PciIoDevice,
476 0x28,
477 NULL,
478 NULL
479 );
480
481 if (!EFI_ERROR (Status)) {
482 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
483 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
484 } else {
485 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
486 }
487 }
488
489 //
490 // Memory 32 code is required for ppb
491 //
492 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
493
494 GetResourcePaddingPpb (PciIoDevice);
495
496 return PciIoDevice;
497 }
498
499
500 /**
501 Create PCI device instance for PCI Card bridge device.
502
503 @param Bridge Parent bridge instance.
504 @param Pci Input PCI device information block.
505 @param Bus PCI device Bus NO.
506 @param Device PCI device Device NO.
507 @param Func PCI device's func NO.
508
509 @return Created PCI device instance.
510
511 **/
512 PCI_IO_DEVICE *
513 GatherP2CInfo (
514 IN PCI_IO_DEVICE *Bridge,
515 IN PCI_TYPE00 *Pci,
516 IN UINT8 Bus,
517 IN UINT8 Device,
518 IN UINT8 Func
519 )
520 {
521 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
522 PCI_IO_DEVICE *PciIoDevice;
523
524 PciRootBridgeIo = Bridge->PciRootBridgeIo;
525 PciIoDevice = CreatePciIoDevice (
526 PciRootBridgeIo,
527 Pci,
528 Bus,
529 Device,
530 Func
531 );
532
533 if (PciIoDevice == NULL) {
534 return NULL;
535 }
536
537 //
538 // Create a device path for this PCI device and store it into its private data
539 //
540 CreatePciDevicePath (
541 Bridge->DevicePath,
542 PciIoDevice
543 );
544
545 if (gFullEnumeration) {
546 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
547
548 //
549 // Initalize the bridge control register
550 //
551 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
552 }
553
554 //
555 // P2C only has one bar that is in 0x10
556 //
557 PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
558
559 //
560 // Read PciBar information from the bar register
561 //
562 GetBackPcCardBar (PciIoDevice);
563 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
564 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
565 EFI_BRIDGE_IO32_DECODE_SUPPORTED;
566
567 return PciIoDevice;
568 }
569
570 /**
571 Create device path for pci deivce.
572
573 @param ParentDevicePath Parent bridge's path.
574 @param PciIoDevice Pci device instance.
575
576 @return Device path protocol instance for specific pci device.
577
578 **/
579 EFI_DEVICE_PATH_PROTOCOL *
580 CreatePciDevicePath (
581 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
582 IN PCI_IO_DEVICE *PciIoDevice
583 )
584 {
585
586 PCI_DEVICE_PATH PciNode;
587
588 //
589 // Create PCI device path
590 //
591 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
592 PciNode.Header.SubType = HW_PCI_DP;
593 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
594
595 PciNode.Device = PciIoDevice->DeviceNumber;
596 PciNode.Function = PciIoDevice->FunctionNumber;
597 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
598
599 return PciIoDevice->DevicePath;
600 }
601
602 /**
603 Check whether the bar is existed or not.
604
605 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
606 @param Offset The offset.
607 @param BarLengthValue The bar length value returned.
608 @param OriginalBarValue The original bar value returned.
609
610 @retval EFI_NOT_FOUND The bar doesn't exist.
611 @retval EFI_SUCCESS The bar exist.
612
613 **/
614 EFI_STATUS
615 BarExisted (
616 IN PCI_IO_DEVICE *PciIoDevice,
617 IN UINTN Offset,
618 OUT UINT32 *BarLengthValue,
619 OUT UINT32 *OriginalBarValue
620 )
621 {
622 EFI_PCI_IO_PROTOCOL *PciIo;
623 UINT32 OriginalValue;
624 UINT32 Value;
625 EFI_TPL OldTpl;
626
627 PciIo = &PciIoDevice->PciIo;
628
629 //
630 // Preserve the original value
631 //
632 PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
633
634 //
635 // Raise TPL to high level to disable timer interrupt while the BAR is probed
636 //
637 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
638
639 PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
640 PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
641
642 //
643 // Write back the original value
644 //
645 PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
646
647 //
648 // Restore TPL to its original level
649 //
650 gBS->RestoreTPL (OldTpl);
651
652 if (BarLengthValue != NULL) {
653 *BarLengthValue = Value;
654 }
655
656 if (OriginalBarValue != NULL) {
657 *OriginalBarValue = OriginalValue;
658 }
659
660 if (Value == 0) {
661 return EFI_NOT_FOUND;
662 } else {
663 return EFI_SUCCESS;
664 }
665 }
666
667 /**
668 Test whether the device can support given attributes.
669
670 @param PciIoDevice Pci device instance.
671 @param Command Input command register value, and
672 returned supported register value.
673 @param BridgeControl Inout bridge control value for PPB or P2C, and
674 returned supported bridge control value.
675 @param OldCommand Returned and stored old command register offset.
676 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
677
678 **/
679 VOID
680 PciTestSupportedAttribute (
681 IN PCI_IO_DEVICE *PciIoDevice,
682 IN OUT UINT16 *Command,
683 IN OUT UINT16 *BridgeControl,
684 OUT UINT16 *OldCommand,
685 OUT UINT16 *OldBridgeControl
686 )
687 {
688 EFI_TPL OldTpl;
689
690 //
691 // Preserve the original value
692 //
693 PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);
694
695 //
696 // Raise TPL to high level to disable timer interrupt while the BAR is probed
697 //
698 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
699
700 PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command);
701 PCI_READ_COMMAND_REGISTER (PciIoDevice, Command);
702
703 //
704 // Write back the original value
705 //
706 PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);
707
708 //
709 // Restore TPL to its original level
710 //
711 gBS->RestoreTPL (OldTpl);
712
713 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
714
715 //
716 // Preserve the original value
717 //
718 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);
719
720 //
721 // Raise TPL to high level to disable timer interrupt while the BAR is probed
722 //
723 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
724
725 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);
726 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
727
728 //
729 // Write back the original value
730 //
731 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);
732
733 //
734 // Restore TPL to its original level
735 //
736 gBS->RestoreTPL (OldTpl);
737
738 } else {
739 *OldBridgeControl = 0;
740 *BridgeControl = 0;
741 }
742 }
743
744 /**
745 Set the supported or current attributes of a PCI device.
746
747 @param PciIoDevice Structure pointer for PCI device.
748 @param Command Command register value.
749 @param BridgeControl Bridge control value for PPB or P2C.
750 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
751
752 **/
753 VOID
754 PciSetDeviceAttribute (
755 IN PCI_IO_DEVICE *PciIoDevice,
756 IN UINT16 Command,
757 IN UINT16 BridgeControl,
758 IN UINTN Option
759 )
760 {
761 UINT64 Attributes;
762
763 Attributes = 0;
764
765 if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
766 Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
767 }
768
769 if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
770 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
771 }
772
773 if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
774 Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
775 }
776
777 if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
778 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
779 }
780
781 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
782 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
783 }
784
785 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {
786 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
787 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
788 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
789 }
790
791 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {
792 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
793 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
794 }
795
796 if (Option == EFI_SET_SUPPORTS) {
797
798 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
799 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
800 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
801 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
802 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
803 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
804
805 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {
806 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
807 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
808 }
809
810 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
811 //
812 // For bridge, it should support IDE attributes
813 //
814 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
815 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
816 } else {
817
818 if (IS_PCI_IDE (&PciIoDevice->Pci)) {
819 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
820 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
821 }
822
823 if (IS_PCI_VGA (&PciIoDevice->Pci)) {
824 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
825 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
826 }
827 }
828
829 PciIoDevice->Supports = Attributes;
830 PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \
831 EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
832 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );
833
834 } else {
835 PciIoDevice->Attributes = Attributes;
836 }
837 }
838
839 /**
840 Determine if the device can support Fast Back to Back attribute.
841
842 @param PciIoDevice Pci device instance.
843 @param StatusIndex Status register value.
844
845 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
846 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
847
848 **/
849 EFI_STATUS
850 GetFastBackToBackSupport (
851 IN PCI_IO_DEVICE *PciIoDevice,
852 IN UINT8 StatusIndex
853 )
854 {
855 EFI_PCI_IO_PROTOCOL *PciIo;
856 EFI_STATUS Status;
857 UINT32 StatusRegister;
858
859 //
860 // Read the status register
861 //
862 PciIo = &PciIoDevice->PciIo;
863 Status = PciIoRead (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
864 if (EFI_ERROR (Status)) {
865 return EFI_UNSUPPORTED;
866 }
867
868 //
869 // Check the Fast B2B bit
870 //
871 if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {
872 return EFI_SUCCESS;
873 } else {
874 return EFI_UNSUPPORTED;
875 }
876 }
877
878 /**
879 Process the option ROM for all the children of the specified parent PCI device.
880 It can only be used after the first full Option ROM process.
881
882 @param PciIoDevice Pci device instance.
883
884 **/
885 VOID
886 ProcessOptionRomLight (
887 IN PCI_IO_DEVICE *PciIoDevice
888 )
889 {
890 PCI_IO_DEVICE *Temp;
891 LIST_ENTRY *CurrentLink;
892
893 //
894 // For RootBridge, PPB , P2C, go recursively to traverse all its children
895 //
896 CurrentLink = PciIoDevice->ChildList.ForwardLink;
897 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
898
899 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
900
901 if (!IsListEmpty (&Temp->ChildList)) {
902 ProcessOptionRomLight (Temp);
903 }
904
905 PciRomGetImageMapping (Temp);
906
907 //
908 // The OpRom has already been processed in the first round
909 //
910 Temp->AllOpRomProcessed = TRUE;
911
912 CurrentLink = CurrentLink->ForwardLink;
913 }
914 }
915
916 /**
917 Determine the related attributes of all devices under a Root Bridge.
918
919 @param PciIoDevice PCI device instance.
920
921 **/
922 EFI_STATUS
923 DetermineDeviceAttribute (
924 IN PCI_IO_DEVICE *PciIoDevice
925 )
926 {
927 UINT16 Command;
928 UINT16 BridgeControl;
929 UINT16 OldCommand;
930 UINT16 OldBridgeControl;
931 BOOLEAN FastB2BSupport;
932 PCI_IO_DEVICE *Temp;
933 LIST_ENTRY *CurrentLink;
934 EFI_STATUS Status;
935
936 //
937 // For Root Bridge, just copy it by RootBridgeIo proctocol
938 // so as to keep consistent with the actual attribute
939 //
940 if (PciIoDevice->Parent == NULL) {
941 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
942 PciIoDevice->PciRootBridgeIo,
943 &PciIoDevice->Supports,
944 &PciIoDevice->Attributes
945 );
946 if (EFI_ERROR (Status)) {
947 return Status;
948 }
949 } else {
950
951 //
952 // Set the attributes to be checked for common PCI devices and PPB or P2C
953 // Since some devices only support part of them, it is better to set the
954 // attribute according to its command or bridge control register
955 //
956 Command = EFI_PCI_COMMAND_IO_SPACE |
957 EFI_PCI_COMMAND_MEMORY_SPACE |
958 EFI_PCI_COMMAND_BUS_MASTER |
959 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
960
961 BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
962
963 //
964 // Test whether the device can support attributes above
965 //
966 PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
967
968 //
969 // Set the supported attributes for specified PCI device
970 //
971 PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
972
973 //
974 // Set the current attributes for specified PCI device
975 //
976 PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
977
978 //
979 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
980 //
981 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
982 }
983
984 FastB2BSupport = TRUE;
985
986 //
987 // P2C can not support FB2B on the secondary side
988 //
989 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
990 FastB2BSupport = FALSE;
991 }
992
993 //
994 // For RootBridge, PPB , P2C, go recursively to traverse all its children
995 //
996 CurrentLink = PciIoDevice->ChildList.ForwardLink;
997 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
998
999 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1000 Status = DetermineDeviceAttribute (Temp);
1001 if (EFI_ERROR (Status)) {
1002 return Status;
1003 }
1004 //
1005 // Detect Fast Bact to Bact support for the device under the bridge
1006 //
1007 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
1008 if (FastB2BSupport && EFI_ERROR (Status)) {
1009 FastB2BSupport = FALSE;
1010 }
1011
1012 CurrentLink = CurrentLink->ForwardLink;
1013 }
1014 //
1015 // Set or clear Fast Back to Back bit for the whole bridge
1016 //
1017 if (!IsListEmpty (&PciIoDevice->ChildList)) {
1018
1019 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
1020
1021 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
1022
1023 if (EFI_ERROR (Status) || (!FastB2BSupport)) {
1024 FastB2BSupport = FALSE;
1025 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1026 } else {
1027 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1028 }
1029 }
1030
1031 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1032 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
1033 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1034 if (FastB2BSupport) {
1035 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1036 } else {
1037 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1038 }
1039
1040 CurrentLink = CurrentLink->ForwardLink;
1041 }
1042 }
1043 //
1044 // End for IsListEmpty
1045 //
1046 return EFI_SUCCESS;
1047 }
1048
1049 /**
1050 This routine is used to update the bar information for those incompatible PCI device.
1051
1052 @param PciIoDevice Pci device instance.
1053
1054 @retval EFI_SUCCESS Successfully updated bar information.
1055 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1056 @retval other Failed to check incompatibility device.
1057
1058 **/
1059 EFI_STATUS
1060 UpdatePciInfo (
1061 IN PCI_IO_DEVICE *PciIoDevice
1062 )
1063 {
1064 EFI_STATUS Status;
1065 UINTN BarIndex;
1066 UINTN BarEndIndex;
1067 BOOLEAN SetFlag;
1068 EFI_PCI_DEVICE_INFO PciDeviceInfo;
1069 VOID *Configuration;
1070 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1071
1072 Configuration = NULL;
1073 Status = EFI_SUCCESS;
1074
1075 if (gEfiIncompatiblePciDeviceSupport == NULL) {
1076 //
1077 // It can only be supported after the Incompatible PCI Device
1078 // Support Protocol has been installed
1079 //
1080 Status = gBS->LocateProtocol (
1081 &gEfiIncompatiblePciDeviceSupportProtocolGuid,
1082 NULL,
1083 (VOID **) &gEfiIncompatiblePciDeviceSupport
1084 );
1085 }
1086 if (Status == EFI_SUCCESS) {
1087 //
1088 // Check whether the device belongs to incompatible devices from protocol or not
1089 // If it is , then get its special requirement in the ACPI table
1090 //
1091 Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (
1092 gEfiIncompatiblePciDeviceSupport,
1093 PciIoDevice->Pci.Hdr.VendorId,
1094 PciIoDevice->Pci.Hdr.DeviceId,
1095 PciIoDevice->Pci.Hdr.RevisionID,
1096 PciIoDevice->Pci.Device.SubsystemVendorID,
1097 PciIoDevice->Pci.Device.SubsystemID,
1098 &Configuration
1099 );
1100
1101 }
1102
1103 if (EFI_ERROR (Status)) {
1104 //
1105 // Check whether the device belongs to incompatible devices from library or not
1106 // If it is , then get its special requirement in the ACPI table
1107 //
1108 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {
1109 PciDeviceInfo.VendorID = PciIoDevice->Pci.Hdr.VendorId;
1110 PciDeviceInfo.DeviceID = PciIoDevice->Pci.Hdr.DeviceId;
1111 PciDeviceInfo.RevisionID = PciIoDevice->Pci.Hdr.RevisionID;
1112 PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;
1113 PciDeviceInfo.SubsystemID = PciIoDevice->Pci.Device.SubsystemID;
1114
1115 Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);
1116 }
1117 }
1118
1119 if (EFI_ERROR (Status) || Configuration == NULL ) {
1120 return EFI_UNSUPPORTED;
1121 }
1122
1123 //
1124 // Update PCI device information from the ACPI table
1125 //
1126 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1127
1128 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
1129
1130 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1131 //
1132 // The format is not support
1133 //
1134 break;
1135 }
1136
1137 BarIndex = (UINTN) Ptr->AddrTranslationOffset;
1138 BarEndIndex = BarIndex;
1139
1140 //
1141 // Update all the bars in the device
1142 //
1143 if (BarIndex == PCI_BAR_ALL) {
1144 BarIndex = 0;
1145 BarEndIndex = PCI_MAX_BAR - 1;
1146 }
1147
1148 if (BarIndex >= PCI_MAX_BAR) {
1149 Ptr++;
1150 continue;
1151 }
1152
1153 for (; BarIndex <= BarEndIndex; BarIndex++) {
1154 SetFlag = FALSE;
1155 switch (Ptr->ResType) {
1156 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1157
1158 //
1159 // Make sure the bar is memory type
1160 //
1161 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
1162 SetFlag = TRUE;
1163 }
1164 break;
1165
1166 case ACPI_ADDRESS_SPACE_TYPE_IO:
1167
1168 //
1169 // Make sure the bar is IO type
1170 //
1171 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
1172 SetFlag = TRUE;
1173 }
1174 break;
1175 }
1176
1177 if (SetFlag) {
1178
1179 //
1180 // Update the new alignment for the device
1181 //
1182 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
1183
1184 //
1185 // Update the new length for the device
1186 //
1187 if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {
1188 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
1189 }
1190 }
1191 }
1192
1193 Ptr++;
1194 }
1195
1196 if (Configuration != NULL) {
1197 FreePool (Configuration);
1198 }
1199
1200 return EFI_SUCCESS;
1201 }
1202
1203 /**
1204 This routine will update the alignment with the new alignment.
1205
1206 @param Alignment Old alignment.
1207 @param NewAlignment New alignment.
1208
1209 **/
1210 VOID
1211 SetNewAlign (
1212 IN UINT64 *Alignment,
1213 IN UINT64 NewAlignment
1214 )
1215 {
1216 UINT64 OldAlignment;
1217 UINTN ShiftBit;
1218
1219 //
1220 // The new alignment is the same as the original,
1221 // so skip it
1222 //
1223 if (NewAlignment == PCI_BAR_OLD_ALIGN) {
1224 return ;
1225 }
1226 //
1227 // Check the validity of the parameter
1228 //
1229 if (NewAlignment != PCI_BAR_EVEN_ALIGN &&
1230 NewAlignment != PCI_BAR_SQUAD_ALIGN &&
1231 NewAlignment != PCI_BAR_DQUAD_ALIGN ) {
1232 *Alignment = NewAlignment;
1233 return ;
1234 }
1235
1236 OldAlignment = (*Alignment) + 1;
1237 ShiftBit = 0;
1238
1239 //
1240 // Get the first non-zero hex value of the length
1241 //
1242 while ((OldAlignment & 0x0F) == 0x00) {
1243 OldAlignment = RShiftU64 (OldAlignment, 4);
1244 ShiftBit += 4;
1245 }
1246
1247 //
1248 // Adjust the alignment to even, quad or double quad boundary
1249 //
1250 if (NewAlignment == PCI_BAR_EVEN_ALIGN) {
1251 if ((OldAlignment & 0x01) != 0) {
1252 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
1253 }
1254 } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {
1255 if ((OldAlignment & 0x03) != 0) {
1256 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
1257 }
1258 } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {
1259 if ((OldAlignment & 0x07) != 0) {
1260 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
1261 }
1262 }
1263
1264 //
1265 // Update the old value
1266 //
1267 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
1268 *Alignment = NewAlignment;
1269
1270 return ;
1271 }
1272
1273 /**
1274 Parse PCI bar information and fill them into PCI device instance.
1275
1276 @param PciIoDevice Pci device instance.
1277 @param Offset Bar offset.
1278 @param BarIndex Bar index.
1279
1280 @return Next bar offset.
1281
1282 **/
1283 UINTN
1284 PciParseBar (
1285 IN PCI_IO_DEVICE *PciIoDevice,
1286 IN UINTN Offset,
1287 IN UINTN BarIndex
1288 )
1289 {
1290 UINT32 Value;
1291 UINT32 OriginalValue;
1292 UINT32 Mask;
1293 UINT32 Data;
1294 UINT8 Index;
1295 EFI_STATUS Status;
1296
1297 OriginalValue = 0;
1298 Value = 0;
1299
1300 Status = BarExisted (
1301 PciIoDevice,
1302 Offset,
1303 &Value,
1304 &OriginalValue
1305 );
1306
1307 if (EFI_ERROR (Status)) {
1308 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1309 PciIoDevice->PciBar[BarIndex].Length = 0;
1310 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1311
1312 //
1313 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1314 //
1315 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
1316 return Offset + 4;
1317 }
1318
1319 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
1320 if ((Value & 0x01) != 0) {
1321 //
1322 // Device I/Os
1323 //
1324 Mask = 0xfffffffc;
1325
1326 if ((Value & 0xFFFF0000) != 0) {
1327 //
1328 // It is a IO32 bar
1329 //
1330 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
1331 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
1332 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1333
1334 } else {
1335 //
1336 // It is a IO16 bar
1337 //
1338 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
1339 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
1340 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1341
1342 }
1343 //
1344 // Workaround. Some platforms inplement IO bar with 0 length
1345 // Need to treat it as no-bar
1346 //
1347 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1348 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;
1349 }
1350
1351 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
1352 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1353
1354 } else {
1355
1356 Mask = 0xfffffff0;
1357
1358 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1359
1360 switch (Value & 0x07) {
1361
1362 //
1363 //memory space; anywhere in 32 bit address space
1364 //
1365 case 0x00:
1366 if ((Value & 0x08) != 0) {
1367 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
1368 } else {
1369 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
1370 }
1371
1372 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1373 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1374
1375 break;
1376
1377 //
1378 // memory space; anywhere in 64 bit address space
1379 //
1380 case 0x04:
1381 if ((Value & 0x08) != 0) {
1382 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
1383 } else {
1384 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
1385 }
1386
1387 //
1388 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1389 // is regarded as an extension for the first bar. As a result
1390 // the sizing will be conducted on combined 64 bit value
1391 // Here just store the masked first 32bit value for future size
1392 // calculation
1393 //
1394 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
1395 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1396
1397 //
1398 // Increment the offset to point to next DWORD
1399 //
1400 Offset += 4;
1401
1402 Status = BarExisted (
1403 PciIoDevice,
1404 Offset,
1405 &Value,
1406 &OriginalValue
1407 );
1408
1409 if (EFI_ERROR (Status)) {
1410 return Offset + 4;
1411 }
1412
1413 //
1414 // Fix the length to support some spefic 64 bit BAR
1415 //
1416 Data = Value;
1417 Index = 0;
1418 for (Data = Value; Data != 0; Data >>= 1) {
1419 Index ++;
1420 }
1421 Value |= ((UINT32)(-1) << Index);
1422
1423 //
1424 // Calculate the size of 64bit bar
1425 //
1426 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
1427
1428 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
1429 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
1430 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1431
1432 break;
1433
1434 //
1435 // reserved
1436 //
1437 default:
1438 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1439 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1440 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1441
1442 break;
1443 }
1444 }
1445
1446 //
1447 // Check the length again so as to keep compatible with some special bars
1448 //
1449 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1450 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1451 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1452 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1453 }
1454
1455 //
1456 // Increment number of bar
1457 //
1458 return Offset + 4;
1459 }
1460
1461 /**
1462 This routine is used to initialize the bar of a PCI device.
1463
1464 @param PciIoDevice Pci device instance.
1465
1466 @note It can be called typically when a device is going to be rejected.
1467
1468 **/
1469 VOID
1470 InitializePciDevice (
1471 IN PCI_IO_DEVICE *PciIoDevice
1472 )
1473 {
1474 EFI_PCI_IO_PROTOCOL *PciIo;
1475 UINT8 Offset;
1476
1477 PciIo = &(PciIoDevice->PciIo);
1478
1479 //
1480 // Put all the resource apertures
1481 // Resource base is set to all ones so as to indicate its resource
1482 // has not been alloacted
1483 //
1484 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
1485 PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
1486 }
1487 }
1488
1489 /**
1490 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1491
1492 @param PciIoDevice PCI-PCI bridge device instance.
1493
1494 **/
1495 VOID
1496 InitializePpb (
1497 IN PCI_IO_DEVICE *PciIoDevice
1498 )
1499 {
1500 EFI_PCI_IO_PROTOCOL *PciIo;
1501
1502 PciIo = &(PciIoDevice->PciIo);
1503
1504 //
1505 // Put all the resource apertures including IO16
1506 // Io32, pMem32, pMem64 to quiescent state
1507 // Resource base all ones, Resource limit all zeros
1508 //
1509 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
1510 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
1511
1512 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
1513 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
1514
1515 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
1516 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
1517
1518 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
1519 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
1520
1521 //
1522 // don't support use io32 as for now
1523 //
1524 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
1525 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
1526
1527 //
1528 // Force Interrupt line to zero for cards that come up randomly
1529 //
1530 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
1531 }
1532
1533 /**
1534 This routine is used to initialize the bar of a PCI Card Bridge device.
1535
1536 @param PciIoDevice PCI Card bridge device.
1537
1538 **/
1539 VOID
1540 InitializeP2C (
1541 IN PCI_IO_DEVICE *PciIoDevice
1542 )
1543 {
1544 EFI_PCI_IO_PROTOCOL *PciIo;
1545
1546 PciIo = &(PciIoDevice->PciIo);
1547
1548 //
1549 // Put all the resource apertures including IO16
1550 // Io32, pMem32, pMem64 to quiescent state(
1551 // Resource base all ones, Resource limit all zeros
1552 //
1553 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
1554 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
1555
1556 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
1557 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
1558
1559 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
1560 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
1561
1562 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
1563 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
1564
1565 //
1566 // Force Interrupt line to zero for cards that come up randomly
1567 //
1568 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
1569 }
1570
1571 /**
1572 Create and initiliaze general PCI I/O device instance for
1573 PCI device/bridge device/hotplug bridge device.
1574
1575 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1576 @param Pci Input Pci information block.
1577 @param Bus Device Bus NO.
1578 @param Device Device device NO.
1579 @param Func Device func NO.
1580
1581 @return Instance of PCI device. NULL means no instance created.
1582
1583 **/
1584 PCI_IO_DEVICE *
1585 CreatePciIoDevice (
1586 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
1587 IN PCI_TYPE00 *Pci,
1588 IN UINT8 Bus,
1589 IN UINT8 Device,
1590 IN UINT8 Func
1591 )
1592 {
1593 PCI_IO_DEVICE *PciIoDevice;
1594
1595 PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
1596 if (PciIoDevice == NULL) {
1597 return NULL;
1598 }
1599
1600 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
1601 PciIoDevice->Handle = NULL;
1602 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
1603 PciIoDevice->DevicePath = NULL;
1604 PciIoDevice->BusNumber = Bus;
1605 PciIoDevice->DeviceNumber = Device;
1606 PciIoDevice->FunctionNumber = Func;
1607 PciIoDevice->Decodes = 0;
1608
1609 if (gFullEnumeration) {
1610 PciIoDevice->Allocated = FALSE;
1611 } else {
1612 PciIoDevice->Allocated = TRUE;
1613 }
1614
1615 PciIoDevice->Registered = FALSE;
1616 PciIoDevice->Attributes = 0;
1617 PciIoDevice->Supports = 0;
1618 PciIoDevice->BusOverride = FALSE;
1619 PciIoDevice->AllOpRomProcessed = FALSE;
1620
1621 PciIoDevice->IsPciExp = FALSE;
1622
1623 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
1624
1625 //
1626 // Initialize the PCI I/O instance structure
1627 //
1628 InitializePciIoInstance (PciIoDevice);
1629 InitializePciDriverOverrideInstance (PciIoDevice);
1630 InitializePciLoadFile2 (PciIoDevice);
1631
1632 //
1633 // Initialize the reserved resource list
1634 //
1635 InitializeListHead (&PciIoDevice->ReservedResourceList);
1636
1637 //
1638 // Initialize the driver list
1639 //
1640 InitializeListHead (&PciIoDevice->OptionRomDriverList);
1641
1642 //
1643 // Initialize the child list
1644 //
1645 InitializeListHead (&PciIoDevice->ChildList);
1646
1647 return PciIoDevice;
1648 }
1649
1650 /**
1651 This routine is used to enumerate entire pci bus system
1652 in a given platform.
1653
1654 It is only called on the second start on the same Root Bridge.
1655
1656 @param Controller Parent bridge handler.
1657
1658 @retval EFI_SUCCESS PCI enumeration finished successfully.
1659 @retval other Some error occurred when enumerating the pci bus system.
1660
1661 **/
1662 EFI_STATUS
1663 PciEnumeratorLight (
1664 IN EFI_HANDLE Controller
1665 )
1666 {
1667
1668 EFI_STATUS Status;
1669 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1670 PCI_IO_DEVICE *RootBridgeDev;
1671 UINT16 MinBus;
1672 UINT16 MaxBus;
1673 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1674
1675 MinBus = 0;
1676 MaxBus = PCI_MAX_BUS;
1677 Descriptors = NULL;
1678
1679 //
1680 // If this root bridge has been already enumerated, then return successfully
1681 //
1682 if (GetRootBridgeByHandle (Controller) != NULL) {
1683 return EFI_SUCCESS;
1684 }
1685
1686 //
1687 // Open pci root bridge io protocol
1688 //
1689 Status = gBS->OpenProtocol (
1690 Controller,
1691 &gEfiPciRootBridgeIoProtocolGuid,
1692 (VOID **) &PciRootBridgeIo,
1693 gPciBusDriverBinding.DriverBindingHandle,
1694 Controller,
1695 EFI_OPEN_PROTOCOL_BY_DRIVER
1696 );
1697 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1698 return Status;
1699 }
1700
1701 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1702
1703 if (EFI_ERROR (Status)) {
1704 return Status;
1705 }
1706
1707 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
1708
1709 //
1710 // Create a device node for root bridge device with a NULL host bridge controller handle
1711 //
1712 RootBridgeDev = CreateRootBridge (Controller);
1713
1714 if (RootBridgeDev == NULL) {
1715 Descriptors++;
1716 continue;
1717 }
1718
1719 //
1720 // Record the root bridgeio protocol
1721 //
1722 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
1723
1724 Status = PciPciDeviceInfoCollector (
1725 RootBridgeDev,
1726 (UINT8) MinBus
1727 );
1728
1729 if (!EFI_ERROR (Status)) {
1730
1731 //
1732 // Remove those PCI devices which are rejected when full enumeration
1733 //
1734 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
1735
1736 //
1737 // Process option rom light
1738 //
1739 ProcessOptionRomLight (RootBridgeDev);
1740
1741 //
1742 // Determine attributes for all devices under this root bridge
1743 //
1744 DetermineDeviceAttribute (RootBridgeDev);
1745
1746 //
1747 // If successfully, insert the node into device pool
1748 //
1749 InsertRootBridge (RootBridgeDev);
1750 } else {
1751
1752 //
1753 // If unsuccessly, destroy the entire node
1754 //
1755 DestroyRootBridge (RootBridgeDev);
1756 }
1757
1758 Descriptors++;
1759 }
1760
1761 return EFI_SUCCESS;
1762 }
1763
1764 /**
1765 Get bus range from PCI resource descriptor list.
1766
1767 @param Descriptors A pointer to the address space descriptor.
1768 @param MinBus The min bus returned.
1769 @param MaxBus The max bus returned.
1770 @param BusRange The bus range returned.
1771
1772 @retval EFI_SUCCESS Successfully got bus range.
1773 @retval EFI_NOT_FOUND Can not find the specific bus.
1774
1775 **/
1776 EFI_STATUS
1777 PciGetBusRange (
1778 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
1779 OUT UINT16 *MinBus,
1780 OUT UINT16 *MaxBus,
1781 OUT UINT16 *BusRange
1782 )
1783 {
1784 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
1785 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
1786 if (MinBus != NULL) {
1787 *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
1788 }
1789
1790 if (MaxBus != NULL) {
1791 *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
1792 }
1793
1794 if (BusRange != NULL) {
1795 *BusRange = (UINT16) (*Descriptors)->AddrLen;
1796 }
1797
1798 return EFI_SUCCESS;
1799 }
1800
1801 (*Descriptors)++;
1802 }
1803
1804 return EFI_NOT_FOUND;
1805 }
1806
1807 /**
1808 This routine can be used to start the root bridge.
1809
1810 @param RootBridgeDev Pci device instance.
1811
1812 @retval EFI_SUCCESS This device started.
1813 @retval other Failed to get PCI Root Bridge I/O protocol.
1814
1815 **/
1816 EFI_STATUS
1817 StartManagingRootBridge (
1818 IN PCI_IO_DEVICE *RootBridgeDev
1819 )
1820 {
1821 EFI_HANDLE RootBridgeHandle;
1822 EFI_STATUS Status;
1823 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1824
1825 //
1826 // Get the root bridge handle
1827 //
1828 RootBridgeHandle = RootBridgeDev->Handle;
1829 PciRootBridgeIo = NULL;
1830
1831 //
1832 // Get the pci root bridge io protocol
1833 //
1834 Status = gBS->OpenProtocol (
1835 RootBridgeHandle,
1836 &gEfiPciRootBridgeIoProtocolGuid,
1837 (VOID **) &PciRootBridgeIo,
1838 gPciBusDriverBinding.DriverBindingHandle,
1839 RootBridgeHandle,
1840 EFI_OPEN_PROTOCOL_BY_DRIVER
1841 );
1842
1843 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1844 return Status;
1845 }
1846
1847 //
1848 // Store the PciRootBridgeIo protocol into root bridge private data
1849 //
1850 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
1851
1852 return EFI_SUCCESS;
1853
1854 }
1855
1856 /**
1857 This routine can be used to check whether a PCI device should be rejected when light enumeration.
1858
1859 @param PciIoDevice Pci device instance.
1860
1861 @retval TRUE This device should be rejected.
1862 @retval FALSE This device shouldn't be rejected.
1863
1864 **/
1865 BOOLEAN
1866 IsPciDeviceRejected (
1867 IN PCI_IO_DEVICE *PciIoDevice
1868 )
1869 {
1870 EFI_STATUS Status;
1871 UINT32 TestValue;
1872 UINT32 OldValue;
1873 UINT32 Mask;
1874 UINT8 BarOffset;
1875
1876 //
1877 // PPB should be skip!
1878 //
1879 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
1880 return FALSE;
1881 }
1882
1883 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1884 //
1885 // Only test base registers for P2C
1886 //
1887 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
1888
1889 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
1890 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
1891 if (EFI_ERROR (Status)) {
1892 continue;
1893 }
1894
1895 TestValue = TestValue & Mask;
1896 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
1897 //
1898 // The bar isn't programed, so it should be rejected
1899 //
1900 return TRUE;
1901 }
1902 }
1903
1904 return FALSE;
1905 }
1906
1907 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
1908 //
1909 // Test PCI devices
1910 //
1911 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
1912 if (EFI_ERROR (Status)) {
1913 continue;
1914 }
1915
1916 if ((TestValue & 0x01) != 0) {
1917
1918 //
1919 // IO Bar
1920 //
1921 Mask = 0xFFFFFFFC;
1922 TestValue = TestValue & Mask;
1923 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
1924 return TRUE;
1925 }
1926
1927 } else {
1928
1929 //
1930 // Mem Bar
1931 //
1932 Mask = 0xFFFFFFF0;
1933 TestValue = TestValue & Mask;
1934
1935 if ((TestValue & 0x07) == 0x04) {
1936
1937 //
1938 // Mem64 or PMem64
1939 //
1940 BarOffset += sizeof (UINT32);
1941 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
1942
1943 //
1944 // Test its high 32-Bit BAR
1945 //
1946 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
1947 if (TestValue == OldValue) {
1948 return TRUE;
1949 }
1950 }
1951
1952 } else {
1953
1954 //
1955 // Mem32 or PMem32
1956 //
1957 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
1958 return TRUE;
1959 }
1960 }
1961 }
1962 }
1963
1964 return FALSE;
1965 }
1966
1967 /**
1968 Reset all bus number from specific bridge.
1969
1970 @param Bridge Parent specific bridge.
1971 @param StartBusNumber Start bus number.
1972
1973 **/
1974 VOID
1975 ResetAllPpbBusNumber (
1976 IN PCI_IO_DEVICE *Bridge,
1977 IN UINT8 StartBusNumber
1978 )
1979 {
1980 EFI_STATUS Status;
1981 PCI_TYPE00 Pci;
1982 UINT8 Device;
1983 UINT32 Register;
1984 UINT8 Func;
1985 UINT64 Address;
1986 UINT8 SecondaryBus;
1987 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1988
1989 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1990
1991 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1992 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1993
1994 //
1995 // Check to see whether a pci device is present
1996 //
1997 Status = PciDevicePresent (
1998 PciRootBridgeIo,
1999 &Pci,
2000 StartBusNumber,
2001 Device,
2002 Func
2003 );
2004
2005 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
2006
2007 Register = 0;
2008 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
2009 Status = PciRootBridgeIoRead (
2010 PciRootBridgeIo,
2011 &Pci,
2012 EfiPciWidthUint32,
2013 Address,
2014 1,
2015 &Register
2016 );
2017 SecondaryBus = (UINT8)(Register >> 8);
2018
2019 if (SecondaryBus != 0) {
2020 ResetAllPpbBusNumber (Bridge, SecondaryBus);
2021 }
2022
2023 //
2024 // Reset register 18h, 19h, 1Ah on PCI Bridge
2025 //
2026 Register &= 0xFF000000;
2027 Status = PciRootBridgeIoWrite (
2028 PciRootBridgeIo,
2029 &Pci,
2030 EfiPciWidthUint32,
2031 Address,
2032 1,
2033 &Register
2034 );
2035 }
2036
2037 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
2038 //
2039 // Skip sub functions, this is not a multi function device
2040 //
2041 Func = PCI_MAX_FUNC;
2042 }
2043 }
2044 }
2045 }
2046