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