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