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