]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
CorebootModulePkg: Remove DuetPkg references
[mirror_edk2.git] / CorebootModulePkg / PciBusNoEnumerationDxe / PciEnumeratorSupport.c
1 /*++
2
3 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
4 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 Module Name:
14
15 PciEnumeratorSupport.c
16
17 Abstract:
18
19 PCI Bus Driver
20
21 Revision History
22
23 --*/
24
25 #include "PciBus.h"
26
27 EFI_STATUS
28 InitializePPB (
29 IN PCI_IO_DEVICE *PciIoDevice
30 );
31
32 EFI_STATUS
33 InitializeP2C (
34 IN PCI_IO_DEVICE *PciIoDevice
35 );
36
37 PCI_IO_DEVICE*
38 CreatePciIoDevice (
39 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
40 IN PCI_TYPE00 *Pci,
41 UINT8 Bus,
42 UINT8 Device,
43 UINT8 Func
44 );
45
46
47 PCI_IO_DEVICE*
48 GatherP2CInfo (
49 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
50 IN PCI_TYPE00 *Pci,
51 UINT8 Bus,
52 UINT8 Device,
53 UINT8 Func
54 );
55
56 UINTN
57 PciParseBar (
58 IN PCI_IO_DEVICE *PciIoDevice,
59 IN UINTN Offset,
60 IN UINTN BarIndex
61 );
62
63
64 EFI_STATUS
65 PciSearchDevice (
66 IN PCI_IO_DEVICE *Bridge,
67 PCI_TYPE00 *Pci,
68 UINT8 Bus,
69 UINT8 Device,
70 UINT8 Func,
71 PCI_IO_DEVICE **PciDevice
72 );
73
74
75 EFI_STATUS
76 DetermineDeviceAttribute (
77 IN PCI_IO_DEVICE *PciIoDevice
78 );
79
80 EFI_STATUS
81 BarExisted (
82 IN PCI_IO_DEVICE *PciIoDevice,
83 IN UINTN Offset,
84 OUT UINT32 *BarLengthValue,
85 OUT UINT32 *OriginalBarValue
86 );
87
88
89
90 EFI_DEVICE_PATH_PROTOCOL*
91 CreatePciDevicePath(
92 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
93 IN PCI_IO_DEVICE *PciIoDevice
94 );
95
96 PCI_IO_DEVICE*
97 GatherDeviceInfo (
98 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
99 IN PCI_TYPE00 *Pci,
100 UINT8 Bus,
101 UINT8 Device,
102 UINT8 Func
103 );
104
105 PCI_IO_DEVICE*
106 GatherPPBInfo (
107 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
108 IN PCI_TYPE00 *Pci,
109 UINT8 Bus,
110 UINT8 Device,
111 UINT8 Func
112 );
113
114 EFI_STATUS
115 PciDevicePresent (
116 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
117 PCI_TYPE00 *Pci,
118 UINT8 Bus,
119 UINT8 Device,
120 UINT8 Func
121 )
122 /*++
123
124 Routine Description:
125
126 This routine is used to check whether the pci device is present
127
128 Arguments:
129
130 Returns:
131
132 None
133
134 --*/
135 {
136 UINT64 Address;
137 EFI_STATUS Status;
138
139 //
140 // Create PCI address map in terms of Bus, Device and Func
141 //
142 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
143
144 //
145 // Read the Vendor Id register
146 //
147 Status = PciRootBridgeIo->Pci.Read (
148 PciRootBridgeIo,
149 EfiPciWidthUint32,
150 Address,
151 1,
152 Pci
153 );
154
155 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
156
157 //
158 // Read the entire config header for the device
159 //
160
161 Status = PciRootBridgeIo->Pci.Read (
162 PciRootBridgeIo,
163 EfiPciWidthUint32,
164 Address,
165 sizeof (PCI_TYPE00) / sizeof (UINT32),
166 Pci
167 );
168
169 return EFI_SUCCESS;
170 }
171
172 return EFI_NOT_FOUND;
173 }
174
175 EFI_STATUS
176 PciPciDeviceInfoCollector (
177 IN PCI_IO_DEVICE *Bridge,
178 UINT8 StartBusNumber
179 )
180 /*++
181
182 Routine Description:
183
184 Arguments:
185
186 Returns:
187
188 None
189
190 --*/
191 {
192 EFI_STATUS Status;
193 PCI_TYPE00 Pci;
194 UINT8 Device;
195 UINT8 Func;
196 UINT8 SecBus;
197 PCI_IO_DEVICE *PciIoDevice;
198 EFI_PCI_IO_PROTOCOL *PciIo;
199
200 Status = EFI_SUCCESS;
201 SecBus = 0;
202 PciIoDevice = NULL;
203
204 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
205
206 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
207
208 //
209 // Check to see whether PCI device is present
210 //
211
212 Status = PciDevicePresent (
213 Bridge->PciRootBridgeIo,
214 &Pci,
215 (UINT8) StartBusNumber,
216 (UINT8) Device,
217 (UINT8) Func
218 );
219
220 if (EFI_ERROR (Status) && Func == 0) {
221 //
222 // go to next device if there is no Function 0
223 //
224 break;
225 }
226
227 if (!EFI_ERROR (Status)) {
228
229 //
230 // Collect all the information about the PCI device discovered
231 //
232 Status = PciSearchDevice (
233 Bridge,
234 &Pci,
235 (UINT8) StartBusNumber,
236 Device,
237 Func,
238 &PciIoDevice
239 );
240
241 //
242 // Recursively scan PCI busses on the other side of PCI-PCI bridges
243 //
244 //
245
246 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
247
248 //
249 // If it is PPB, we need to get the secondary bus to continue the enumeration
250 //
251 PciIo = &(PciIoDevice->PciIo);
252
253 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
254
255 if (EFI_ERROR (Status)) {
256 return Status;
257 }
258
259 //
260 // If the PCI bridge is initialized then enumerate the next level bus
261 //
262 if (SecBus != 0) {
263 Status = PciPciDeviceInfoCollector (
264 PciIoDevice,
265 (UINT8) (SecBus)
266 );
267 }
268 }
269
270 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
271
272 //
273 // Skip sub functions, this is not a multi function device
274 //
275 Func = PCI_MAX_FUNC;
276 }
277 }
278
279 }
280 }
281
282 return EFI_SUCCESS;
283 }
284
285 EFI_STATUS
286 PciSearchDevice (
287 IN PCI_IO_DEVICE *Bridge,
288 IN PCI_TYPE00 *Pci,
289 IN UINT8 Bus,
290 IN UINT8 Device,
291 IN UINT8 Func,
292 OUT PCI_IO_DEVICE **PciDevice
293 )
294 /*++
295
296 Routine Description:
297
298 Search required device.
299
300 Arguments:
301
302 Bridge - A pointer to the PCI_IO_DEVICE.
303 Pci - A pointer to the PCI_TYPE00.
304 Bus - Bus number.
305 Device - Device number.
306 Func - Function number.
307 PciDevice - The Required pci device.
308
309 Returns:
310
311 Status code.
312
313 --*/
314 {
315 PCI_IO_DEVICE *PciIoDevice;
316
317 PciIoDevice = NULL;
318
319 if (!IS_PCI_BRIDGE (Pci)) {
320
321 if (IS_CARDBUS_BRIDGE (Pci)) {
322 PciIoDevice = GatherP2CInfo (
323 Bridge->PciRootBridgeIo,
324 Pci,
325 Bus,
326 Device,
327 Func
328 );
329 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
330 InitializeP2C (PciIoDevice);
331 }
332 } else {
333
334 //
335 // Create private data for Pci Device
336 //
337 PciIoDevice = GatherDeviceInfo (
338 Bridge->PciRootBridgeIo,
339 Pci,
340 Bus,
341 Device,
342 Func
343 );
344
345 }
346
347 } else {
348
349 //
350 // Create private data for PPB
351 //
352 PciIoDevice = GatherPPBInfo (
353 Bridge->PciRootBridgeIo,
354 Pci,
355 Bus,
356 Device,
357 Func
358 );
359
360 //
361 // Special initialization for PPB including making the PPB quiet
362 //
363 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
364 InitializePPB (PciIoDevice);
365 }
366 }
367
368 if (!PciIoDevice) {
369 return EFI_OUT_OF_RESOURCES;
370 }
371
372 //
373 // Create a device path for this PCI device and store it into its private data
374 //
375 CreatePciDevicePath(
376 Bridge->DevicePath,
377 PciIoDevice
378 );
379
380 //
381 // Detect this function has option rom
382 //
383 if (gFullEnumeration) {
384
385 if (!IS_CARDBUS_BRIDGE (Pci)) {
386
387 GetOpRomInfo (PciIoDevice);
388
389 }
390
391 ResetPowerManagementFeature (PciIoDevice);
392
393 }
394 else {
395 PciRomGetRomResourceFromPciOptionRomTable (
396 &gPciBusDriverBinding,
397 PciIoDevice->PciRootBridgeIo,
398 PciIoDevice
399 );
400 }
401
402
403 //
404 // Insert it into a global tree for future reference
405 //
406 InsertPciDevice (Bridge, PciIoDevice);
407
408 //
409 // Determine PCI device attributes
410 //
411 DetermineDeviceAttribute (PciIoDevice);
412
413 if (PciDevice != NULL) {
414 *PciDevice = PciIoDevice;
415 }
416
417 return EFI_SUCCESS;
418 }
419
420 PCI_IO_DEVICE *
421 GatherDeviceInfo (
422 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
423 IN PCI_TYPE00 *Pci,
424 UINT8 Bus,
425 UINT8 Device,
426 UINT8 Func
427 )
428 /*++
429
430 Routine Description:
431
432 Arguments:
433
434 Returns:
435
436 None
437
438 --*/
439 {
440 UINTN Offset;
441 UINTN BarIndex;
442 PCI_IO_DEVICE *PciIoDevice;
443
444 PciIoDevice = CreatePciIoDevice (
445 PciRootBridgeIo,
446 Pci,
447 Bus,
448 Device,
449 Func
450 );
451
452 if (!PciIoDevice) {
453 return NULL;
454 }
455
456 //
457 // If it is a full enumeration, disconnect the device in advance
458 //
459 if (gFullEnumeration) {
460
461 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
462
463 }
464
465 //
466 // Start to parse the bars
467 //
468 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
469 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
470 }
471
472 return PciIoDevice;
473 }
474
475 PCI_IO_DEVICE *
476 GatherPPBInfo (
477 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
478 IN PCI_TYPE00 *Pci,
479 UINT8 Bus,
480 UINT8 Device,
481 UINT8 Func
482 )
483 /*++
484
485 Routine Description:
486
487 Arguments:
488
489 Returns:
490
491 None
492
493 --*/
494 {
495 PCI_IO_DEVICE *PciIoDevice;
496 EFI_STATUS Status;
497 UINT8 Value;
498 EFI_PCI_IO_PROTOCOL *PciIo;
499 UINT8 Temp;
500
501 PciIoDevice = CreatePciIoDevice (
502 PciRootBridgeIo,
503 Pci,
504 Bus,
505 Device,
506 Func
507 );
508
509 if (!PciIoDevice) {
510 return NULL;
511 }
512
513 if (gFullEnumeration) {
514 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
515
516 //
517 // Initalize the bridge control register
518 //
519 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
520 }
521
522 PciIo = &PciIoDevice->PciIo;
523
524 //
525 // Test whether it support 32 decode or not
526 //
527 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
528 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
529 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
530 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
531
532 if (Value) {
533 if (Value & 0x01) {
534 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
535 } else {
536 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
537 }
538 }
539
540 Status = BarExisted (
541 PciIoDevice,
542 0x24,
543 NULL,
544 NULL
545 );
546
547 //
548 // test if it supports 64 memory or not
549 //
550 if (!EFI_ERROR (Status)) {
551
552 Status = BarExisted (
553 PciIoDevice,
554 0x28,
555 NULL,
556 NULL
557 );
558
559 if (!EFI_ERROR (Status)) {
560 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
561 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
562 } else {
563 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
564 }
565 }
566
567 //
568 // Memory 32 code is required for ppb
569 //
570 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
571
572 return PciIoDevice;
573 }
574
575 PCI_IO_DEVICE *
576 GatherP2CInfo (
577 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
578 IN PCI_TYPE00 *Pci,
579 UINT8 Bus,
580 UINT8 Device,
581 UINT8 Func
582 )
583 /*++
584
585 Routine Description:
586
587 Arguments:
588
589 Returns:
590
591 None
592
593 --*/
594 {
595 PCI_IO_DEVICE *PciIoDevice;
596
597 PciIoDevice = CreatePciIoDevice (
598 PciRootBridgeIo,
599 Pci,
600 Bus,
601 Device,
602 Func
603 );
604
605 if (!PciIoDevice) {
606 return NULL;
607 }
608
609 if (gFullEnumeration) {
610 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
611
612 //
613 // Initalize the bridge control register
614 //
615 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
616
617 }
618 //
619 // P2C only has one bar that is in 0x10
620 //
621 PciParseBar(PciIoDevice, 0x10, 0);
622
623 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
624 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
625 EFI_BRIDGE_IO32_DECODE_SUPPORTED;
626
627 return PciIoDevice;
628 }
629
630 EFI_DEVICE_PATH_PROTOCOL *
631 CreatePciDevicePath (
632 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
633 IN PCI_IO_DEVICE *PciIoDevice
634 )
635 /*++
636
637 Routine Description:
638
639 Arguments:
640
641 Returns:
642
643 None
644
645 --*/
646 {
647
648 PCI_DEVICE_PATH PciNode;
649
650 //
651 // Create PCI device path
652 //
653 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
654 PciNode.Header.SubType = HW_PCI_DP;
655 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
656
657 PciNode.Device = PciIoDevice->DeviceNumber;
658 PciNode.Function = PciIoDevice->FunctionNumber;
659 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
660
661 return PciIoDevice->DevicePath;
662 }
663
664 EFI_STATUS
665 BarExisted (
666 IN PCI_IO_DEVICE *PciIoDevice,
667 IN UINTN Offset,
668 OUT UINT32 *BarLengthValue,
669 OUT UINT32 *OriginalBarValue
670 )
671 /*++
672
673 Routine Description:
674
675 Check the bar is existed or not.
676
677 Arguments:
678
679 PciIoDevice - A pointer to the PCI_IO_DEVICE.
680 Offset - The offset.
681 BarLengthValue - The bar length value.
682 OriginalBarValue - The original bar value.
683
684 Returns:
685
686 EFI_NOT_FOUND - The bar don't exist.
687 EFI_SUCCESS - The bar exist.
688
689 --*/
690 {
691 EFI_PCI_IO_PROTOCOL *PciIo;
692 UINT32 OriginalValue;
693 UINT32 Value;
694 EFI_TPL OldTpl;
695
696 PciIo = &PciIoDevice->PciIo;
697
698 //
699 // Preserve the original value
700 //
701
702 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
703
704 //
705 // Raise TPL to high level to disable timer interrupt while the BAR is probed
706 //
707 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
708
709 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
710 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
711
712 //
713 // Write back the original value
714 //
715 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
716
717 //
718 // Restore TPL to its original level
719 //
720 gBS->RestoreTPL (OldTpl);
721
722 if (BarLengthValue != NULL) {
723 *BarLengthValue = Value;
724 }
725
726 if (OriginalBarValue != NULL) {
727 *OriginalBarValue = OriginalValue;
728 }
729
730 if (Value == 0) {
731 return EFI_NOT_FOUND;
732 } else {
733 return EFI_SUCCESS;
734 }
735 }
736
737
738 EFI_STATUS
739 DetermineDeviceAttribute (
740 IN PCI_IO_DEVICE *PciIoDevice
741 )
742 /*++
743
744 Routine Description:
745
746 Determine the related attributes of all devices under a Root Bridge
747
748 Arguments:
749
750 Returns:
751
752 None
753
754 --*/
755 {
756 UINT16 Command;
757 UINT16 BridgeControl;
758
759 Command = 0;
760
761 PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;
762 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
763
764 if (IS_PCI_VGA (&(PciIoDevice->Pci))){
765
766 //
767 // If the device is VGA, VGA related Attributes are supported
768 //
769 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
770 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ;
771 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ;
772 }
773
774 if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {
775 //
776 // If the devie is a ISA Bridge, set the two attributes
777 //
778 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
779 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
780 }
781
782 if (IS_PCI_GFX (&(PciIoDevice->Pci))) {
783
784 //
785 // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
786 // attribute
787 //
788 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
789 }
790
791
792 //
793 // If the device is IDE, IDE related attributes are supported
794 //
795 if (IS_PCI_IDE (&(PciIoDevice->Pci))) {
796 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ;
797 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ;
798 }
799
800 PciReadCommandRegister(PciIoDevice, &Command);
801
802
803 if (Command & EFI_PCI_COMMAND_IO_SPACE) {
804 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
805 }
806
807 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
808 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
809 }
810
811 if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
812 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
813 }
814
815 if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) ||
816 IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){
817
818 //
819 // If it is a PPB, read the Bridge Control Register to determine
820 // the relevant attributes
821 //
822 BridgeControl = 0;
823 PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);
824
825 //
826 // Determine whether the ISA bit is set
827 // If ISA Enable on Bridge is set, the PPB
828 // will block forwarding 0x100-0x3ff for each 1KB in the
829 // first 64KB I/O range.
830 //
831 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
832 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
833 }
834
835 //
836 // Determine whether the VGA bit is set
837 // If it is set, the bridge is set to decode VGA memory range
838 // and palette register range
839 //
840 if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
841 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
842 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
843 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
844 }
845
846 //
847 // if the palette snoop bit is set, then the brige is set to
848 // decode palette IO write
849 //
850 if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
851 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
852 }
853 }
854
855 return EFI_SUCCESS;
856 }
857
858 UINTN
859 PciParseBar (
860 IN PCI_IO_DEVICE *PciIoDevice,
861 IN UINTN Offset,
862 IN UINTN BarIndex
863 )
864 /*++
865
866 Routine Description:
867
868 Arguments:
869
870 Returns:
871
872 None
873
874 --*/
875 {
876 UINT32 Value;
877 UINT32 OriginalValue;
878 UINT32 Mask;
879 EFI_STATUS Status;
880
881 OriginalValue = 0;
882 Value = 0;
883
884 Status = BarExisted (
885 PciIoDevice,
886 Offset,
887 &Value,
888 &OriginalValue
889 );
890
891 if (EFI_ERROR (Status)) {
892 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
893 PciIoDevice->PciBar[BarIndex].Length = 0;
894 PciIoDevice->PciBar[BarIndex].Alignment = 0;
895
896 //
897 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
898 //
899 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
900 return Offset + 4;
901 }
902
903 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
904 if (Value & 0x01) {
905 //
906 // Device I/Os
907 //
908 Mask = 0xfffffffc;
909
910 if (Value & 0xFFFF0000) {
911 //
912 // It is a IO32 bar
913 //
914 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
915 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
916 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
917
918 } else {
919 //
920 // It is a IO16 bar
921 //
922 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
923 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
924 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
925
926 }
927 //
928 // Workaround. Some platforms inplement IO bar with 0 length
929 // Need to treat it as no-bar
930 //
931 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
932 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
933 }
934
935 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
936 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
937
938 } else {
939
940 Mask = 0xfffffff0;
941
942 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
943
944 switch (Value & 0x07) {
945
946 //
947 //memory space; anywhere in 32 bit address space
948 //
949 case 0x00:
950 if (Value & 0x08) {
951 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
952 } else {
953 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
954 }
955
956 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
957 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
958
959 break;
960
961 //
962 // memory space; anywhere in 64 bit address space
963 //
964 case 0x04:
965 if (Value & 0x08) {
966 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
967 } else {
968 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
969 }
970
971 //
972 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
973 // is regarded as an extension for the first bar. As a result
974 // the sizing will be conducted on combined 64 bit value
975 // Here just store the masked first 32bit value for future size
976 // calculation
977 //
978 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
979 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
980
981 //
982 // Increment the offset to point to next DWORD
983 //
984 Offset += 4;
985
986 Status = BarExisted (
987 PciIoDevice,
988 Offset,
989 &Value,
990 &OriginalValue
991 );
992
993 if (EFI_ERROR (Status)) {
994 return Offset + 4;
995 }
996
997 //
998 // Fix the length to support some spefic 64 bit BAR
999 //
1000 Value |= ((UINT32)(-1) << HighBitSet32 (Value));
1001
1002 //
1003 // Calculate the size of 64bit bar
1004 //
1005 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
1006
1007 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
1008 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
1009 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1010
1011 break;
1012
1013 //
1014 // reserved
1015 //
1016 default:
1017 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1018 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1019 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1020
1021 break;
1022 }
1023 }
1024
1025 //
1026 // Check the length again so as to keep compatible with some special bars
1027 //
1028 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1029 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1030 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1031 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1032 }
1033
1034 //
1035 // Increment number of bar
1036 //
1037 return Offset + 4;
1038 }
1039
1040 EFI_STATUS
1041 InitializePPB (
1042 IN PCI_IO_DEVICE *PciIoDevice
1043 )
1044 /*++
1045
1046 Routine Description:
1047
1048 Arguments:
1049
1050 Returns:
1051
1052 None
1053
1054 --*/
1055 {
1056 EFI_PCI_IO_PROTOCOL *PciIo;
1057
1058 PciIo = &(PciIoDevice->PciIo);
1059
1060 //
1061 // Put all the resource apertures including IO16
1062 // Io32, pMem32, pMem64 to quiescent state
1063 // Resource base all ones, Resource limit all zeros
1064 //
1065 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
1066 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
1067
1068 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
1069 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
1070
1071 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
1072 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
1073
1074 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
1075 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
1076
1077 //
1078 // don't support use io32 as for now
1079 //
1080 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
1081 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
1082
1083 return EFI_SUCCESS;
1084 }
1085
1086 EFI_STATUS
1087 InitializeP2C (
1088 IN PCI_IO_DEVICE *PciIoDevice
1089 )
1090 /*++
1091
1092 Routine Description:
1093
1094 Arguments:
1095
1096 Returns:
1097
1098 None
1099
1100 --*/
1101 {
1102 EFI_PCI_IO_PROTOCOL *PciIo;
1103
1104 PciIo = &(PciIoDevice->PciIo);
1105
1106 //
1107 // Put all the resource apertures including IO16
1108 // Io32, pMem32, pMem64 to quiescent state(
1109 // Resource base all ones, Resource limit all zeros
1110 //
1111 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
1112 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
1113
1114 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
1115 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
1116
1117 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
1118 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
1119
1120 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
1121 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
1122
1123 return EFI_SUCCESS;
1124 }
1125
1126 PCI_IO_DEVICE *
1127 CreatePciIoDevice (
1128 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
1129 IN PCI_TYPE00 *Pci,
1130 UINT8 Bus,
1131 UINT8 Device,
1132 UINT8 Func
1133 )
1134 /*++
1135
1136 Routine Description:
1137
1138 Arguments:
1139
1140 Returns:
1141
1142 None
1143
1144 --*/
1145 {
1146
1147 EFI_STATUS Status;
1148 PCI_IO_DEVICE *PciIoDevice;
1149
1150 PciIoDevice = NULL;
1151
1152 Status = gBS->AllocatePool (
1153 EfiBootServicesData,
1154 sizeof (PCI_IO_DEVICE),
1155 (VOID **) &PciIoDevice
1156 );
1157
1158 if (EFI_ERROR (Status)) {
1159 return NULL;
1160 }
1161
1162 ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
1163
1164 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
1165 PciIoDevice->Handle = NULL;
1166 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
1167 PciIoDevice->DevicePath = NULL;
1168 PciIoDevice->BusNumber = Bus;
1169 PciIoDevice->DeviceNumber = Device;
1170 PciIoDevice->FunctionNumber = Func;
1171 PciIoDevice->Decodes = 0;
1172 if (gFullEnumeration) {
1173 PciIoDevice->Allocated = FALSE;
1174 } else {
1175 PciIoDevice->Allocated = TRUE;
1176 }
1177
1178 PciIoDevice->Attributes = 0;
1179 PciIoDevice->Supports = 0;
1180 PciIoDevice->BusOverride = FALSE;
1181 PciIoDevice->IsPciExp = FALSE;
1182
1183 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
1184
1185 //
1186 // Initialize the PCI I/O instance structure
1187 //
1188
1189 Status = InitializePciIoInstance (PciIoDevice);
1190 Status = InitializePciDriverOverrideInstance (PciIoDevice);
1191
1192 if (EFI_ERROR (Status)) {
1193 gBS->FreePool (PciIoDevice);
1194 return NULL;
1195 }
1196
1197 //
1198 // Initialize the reserved resource list
1199 //
1200 InitializeListHead (&PciIoDevice->ReservedResourceList);
1201
1202 //
1203 // Initialize the driver list
1204 //
1205 InitializeListHead (&PciIoDevice->OptionRomDriverList);
1206
1207 //
1208 // Initialize the child list
1209 //
1210 InitializeListHead (&PciIoDevice->ChildList);
1211
1212 return PciIoDevice;
1213 }
1214
1215 EFI_STATUS
1216 PciEnumeratorLight (
1217 IN EFI_HANDLE Controller
1218 )
1219 /*++
1220
1221 Routine Description:
1222
1223 This routine is used to enumerate entire pci bus system
1224 in a given platform
1225
1226 Arguments:
1227
1228 Returns:
1229
1230 None
1231
1232 --*/
1233 {
1234
1235 EFI_STATUS Status;
1236 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1237 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1238 PCI_IO_DEVICE *RootBridgeDev;
1239 UINT16 MinBus;
1240 UINT16 MaxBus;
1241 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1242
1243 MinBus = 0;
1244 MaxBus = PCI_MAX_BUS;
1245 Descriptors = NULL;
1246
1247 //
1248 // If this host bridge has been already enumerated, then return successfully
1249 //
1250 if (RootBridgeExisted (Controller)) {
1251 return EFI_SUCCESS;
1252 }
1253
1254 //
1255 // Open the IO Abstraction(s) needed to perform the supported test
1256 //
1257 Status = gBS->OpenProtocol (
1258 Controller ,
1259 &gEfiDevicePathProtocolGuid,
1260 (VOID **)&ParentDevicePath,
1261 gPciBusDriverBinding.DriverBindingHandle,
1262 Controller,
1263 EFI_OPEN_PROTOCOL_BY_DRIVER
1264 );
1265 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1266 return Status;
1267 }
1268
1269 //
1270 // Open pci root bridge io protocol
1271 //
1272 Status = gBS->OpenProtocol (
1273 Controller,
1274 &gEfiPciRootBridgeIoProtocolGuid,
1275 (VOID **) &PciRootBridgeIo,
1276 gPciBusDriverBinding.DriverBindingHandle,
1277 Controller,
1278 EFI_OPEN_PROTOCOL_BY_DRIVER
1279 );
1280 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1281 return Status;
1282 }
1283
1284 //
1285 // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge
1286 //
1287 Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);
1288
1289 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1290
1291 if (EFI_ERROR (Status)) {
1292 return Status;
1293 }
1294
1295 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
1296
1297 //
1298 // Create a device node for root bridge device with a NULL host bridge controller handle
1299 //
1300 RootBridgeDev = CreateRootBridge (Controller);
1301
1302 //
1303 // Record the root bridge device path
1304 //
1305 RootBridgeDev->DevicePath = ParentDevicePath;
1306
1307 //
1308 // Record the root bridge io protocol
1309 //
1310 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
1311
1312 Status = PciPciDeviceInfoCollector (
1313 RootBridgeDev,
1314 (UINT8) MinBus
1315 );
1316
1317 if (!EFI_ERROR (Status)) {
1318
1319 //
1320 // If successfully, insert the node into device pool
1321 //
1322 InsertRootBridge (RootBridgeDev);
1323 } else {
1324
1325 //
1326 // If unsuccessly, destroy the entire node
1327 //
1328 DestroyRootBridge (RootBridgeDev);
1329 }
1330
1331 Descriptors++;
1332 }
1333
1334 return EFI_SUCCESS;
1335 }
1336
1337 EFI_STATUS
1338 PciGetBusRange (
1339 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
1340 OUT UINT16 *MinBus,
1341 OUT UINT16 *MaxBus,
1342 OUT UINT16 *BusRange
1343 )
1344 /*++
1345
1346 Routine Description:
1347
1348 Get the bus range.
1349
1350 Arguments:
1351
1352 Descriptors - A pointer to the address space descriptor.
1353 MinBus - The min bus.
1354 MaxBus - The max bus.
1355 BusRange - The bus range.
1356
1357 Returns:
1358
1359 Status Code.
1360
1361 --*/
1362 {
1363
1364 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
1365 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
1366 if (MinBus != NULL) {
1367 *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
1368 }
1369
1370 if (MaxBus != NULL) {
1371 *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
1372 }
1373
1374 if (BusRange != NULL) {
1375 *BusRange = (UINT16)(*Descriptors)->AddrLen;
1376 }
1377 return EFI_SUCCESS;
1378 }
1379
1380 (*Descriptors)++;
1381 }
1382
1383 return EFI_NOT_FOUND;
1384 }
1385