]> git.proxmox.com Git - mirror_edk2.git/blame - CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
CorebootModulePkg/BaseSerialPortLib: Set DTR and RTS
[mirror_edk2.git] / CorebootModulePkg / PciBusNoEnumerationDxe / PciEnumeratorSupport.c
CommitLineData
81a23a0f
LL
1/*++
2
3Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
4(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13Module Name:
14
15 PciEnumeratorSupport.c
16
17Abstract:
18
19 PCI Bus Driver
20
21Revision History
22
23--*/
24
25#include "PciBus.h"
26
27EFI_STATUS
28InitializePPB (
29 IN PCI_IO_DEVICE *PciIoDevice
30);
31
32EFI_STATUS
33InitializeP2C (
34 IN PCI_IO_DEVICE *PciIoDevice
35);
36
37PCI_IO_DEVICE*
38CreatePciIoDevice (
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
47PCI_IO_DEVICE*
48GatherP2CInfo (
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
56UINTN
57PciParseBar (
58 IN PCI_IO_DEVICE *PciIoDevice,
59 IN UINTN Offset,
60 IN UINTN BarIndex
61);
62
63
64EFI_STATUS
65PciSearchDevice (
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
75EFI_STATUS
76DetermineDeviceAttribute (
77 IN PCI_IO_DEVICE *PciIoDevice
78);
79
80EFI_STATUS
81BarExisted (
82 IN PCI_IO_DEVICE *PciIoDevice,
83 IN UINTN Offset,
84 OUT UINT32 *BarLengthValue,
85 OUT UINT32 *OriginalBarValue
86 );
87
88
89
90EFI_DEVICE_PATH_PROTOCOL*
91CreatePciDevicePath(
92 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
93 IN PCI_IO_DEVICE *PciIoDevice
94);
95
96PCI_IO_DEVICE*
97GatherDeviceInfo (
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
105PCI_IO_DEVICE*
106GatherPPBInfo (
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
114EFI_STATUS
115PciDevicePresent (
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
124Routine Description:
125
126 This routine is used to check whether the pci device is present
127
128Arguments:
129
130Returns:
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
175EFI_STATUS
176PciPciDeviceInfoCollector (
177 IN PCI_IO_DEVICE *Bridge,
178 UINT8 StartBusNumber
179 )
180/*++
181
182Routine Description:
183
184Arguments:
185
186Returns:
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
285EFI_STATUS
286PciSearchDevice (
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
296Routine Description:
297
298 Search required device.
299
300Arguments:
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
309Returns:
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
420PCI_IO_DEVICE *
421GatherDeviceInfo (
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
430Routine Description:
431
432Arguments:
433
434Returns:
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
475PCI_IO_DEVICE *
476GatherPPBInfo (
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
485Routine Description:
486
487Arguments:
488
489Returns:
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
575PCI_IO_DEVICE *
576GatherP2CInfo (
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
585Routine Description:
586
587Arguments:
588
589Returns:
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
630EFI_DEVICE_PATH_PROTOCOL *
631CreatePciDevicePath (
632 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
633 IN PCI_IO_DEVICE *PciIoDevice
634 )
635/*++
636
637Routine Description:
638
639Arguments:
640
641Returns:
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
664EFI_STATUS
665BarExisted (
666 IN PCI_IO_DEVICE *PciIoDevice,
667 IN UINTN Offset,
668 OUT UINT32 *BarLengthValue,
669 OUT UINT32 *OriginalBarValue
670 )
671/*++
672
673Routine Description:
674
675 Check the bar is existed or not.
676
677Arguments:
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
684Returns:
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
738EFI_STATUS
739DetermineDeviceAttribute (
740 IN PCI_IO_DEVICE *PciIoDevice
741 )
742/*++
743
744Routine Description:
745
746 Determine the related attributes of all devices under a Root Bridge
747
748Arguments:
749
750Returns:
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
858UINTN
859PciParseBar (
860 IN PCI_IO_DEVICE *PciIoDevice,
861 IN UINTN Offset,
862 IN UINTN BarIndex
863 )
864/*++
865
866Routine Description:
867
868Arguments:
869
870Returns:
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
1040EFI_STATUS
1041InitializePPB (
1042 IN PCI_IO_DEVICE *PciIoDevice
1043 )
1044/*++
1045
1046Routine Description:
1047
1048Arguments:
1049
1050Returns:
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
1086EFI_STATUS
1087InitializeP2C (
1088 IN PCI_IO_DEVICE *PciIoDevice
1089 )
1090/*++
1091
1092Routine Description:
1093
1094Arguments:
1095
1096Returns:
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
1126PCI_IO_DEVICE *
1127CreatePciIoDevice (
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
1136Routine Description:
1137
1138Arguments:
1139
1140Returns:
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
1215EFI_STATUS
1216PciEnumeratorLight (
1217 IN EFI_HANDLE Controller
1218 )
1219/*++
1220
1221Routine Description:
1222
1223 This routine is used to enumerate entire pci bus system
1224 in a given platform
1225
1226Arguments:
1227
1228Returns:
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
1337EFI_STATUS
1338PciGetBusRange (
1339 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
1340 OUT UINT16 *MinBus,
1341 OUT UINT16 *MaxBus,
1342 OUT UINT16 *BusRange
1343 )
1344/*++
1345
1346Routine Description:
1347
1348 Get the bus range.
1349
1350Arguments:
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
1357Returns:
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