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