]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootModulePkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
58b9385a375d0b4336ea18fed7d3261797e5b5a3
[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 // 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
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 }
267
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
294 EFI_STATUS
295 PciSearchDevice (
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
305 Routine Description:
306
307 Search required device.
308
309 Arguments:
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
318 Returns:
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 }
380
381 //
382 // Create a device path for this PCI device and store it into its private data
383 //
384 CreatePciDevicePath(
385 Bridge->DevicePath,
386 PciIoDevice
387 );
388
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);
401
402 }
403 else {
404 PciRomGetRomResourceFromPciOptionRomTable (
405 &gPciBusDriverBinding,
406 PciIoDevice->PciRootBridgeIo,
407 PciIoDevice
408 );
409 }
410
411
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
429 PCI_IO_DEVICE *
430 GatherDeviceInfo (
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
439 Routine Description:
440
441 Arguments:
442
443 Returns:
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
484 PCI_IO_DEVICE *
485 GatherPPBInfo (
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
494 Routine Description:
495
496 Arguments:
497
498 Returns:
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 }
521
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
584 PCI_IO_DEVICE *
585 GatherP2CInfo (
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
594 Routine Description:
595
596 Arguments:
597
598 Returns:
599
600 None
601
602 --*/
603 {
604 PCI_IO_DEVICE *PciIoDevice;
605
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);
631
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
639 EFI_DEVICE_PATH_PROTOCOL *
640 CreatePciDevicePath (
641 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
642 IN PCI_IO_DEVICE *PciIoDevice
643 )
644 /*++
645
646 Routine Description:
647
648 Arguments:
649
650 Returns:
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
673 EFI_STATUS
674 BarExisted (
675 IN PCI_IO_DEVICE *PciIoDevice,
676 IN UINTN Offset,
677 OUT UINT32 *BarLengthValue,
678 OUT UINT32 *OriginalBarValue
679 )
680 /*++
681
682 Routine Description:
683
684 Check the bar is existed or not.
685
686 Arguments:
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
693 Returns:
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
747 EFI_STATUS
748 DetermineDeviceAttribute (
749 IN PCI_IO_DEVICE *PciIoDevice
750 )
751 /*++
752
753 Routine Description:
754
755 Determine the related attributes of all devices under a Root Bridge
756
757 Arguments:
758
759 Returns:
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
811
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
824 if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) ||
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
837 // will block forwarding 0x100-0x3ff for each 1KB in the
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;
842 }
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 //
856 // if the palette snoop bit is set, then the brige is set to
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 }
862 }
863
864 return EFI_SUCCESS;
865 }
866
867 UINTN
868 PciParseBar (
869 IN PCI_IO_DEVICE *PciIoDevice,
870 IN UINTN Offset,
871 IN UINTN BarIndex
872 )
873 /*++
874
875 Routine Description:
876
877 Arguments:
878
879 Returns:
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 //
1009 Value |= ((UINT32)(-1) << HighBitSet32 (Value));
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 }
1033
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 }
1042
1043 //
1044 // Increment number of bar
1045 //
1046 return Offset + 4;
1047 }
1048
1049 EFI_STATUS
1050 InitializePPB (
1051 IN PCI_IO_DEVICE *PciIoDevice
1052 )
1053 /*++
1054
1055 Routine Description:
1056
1057 Arguments:
1058
1059 Returns:
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
1095 EFI_STATUS
1096 InitializeP2C (
1097 IN PCI_IO_DEVICE *PciIoDevice
1098 )
1099 /*++
1100
1101 Routine Description:
1102
1103 Arguments:
1104
1105 Returns:
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
1135 PCI_IO_DEVICE *
1136 CreatePciIoDevice (
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
1145 Routine Description:
1146
1147 Arguments:
1148
1149 Returns:
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
1224 EFI_STATUS
1225 PciEnumeratorLight (
1226 IN EFI_HANDLE Controller
1227 )
1228 /*++
1229
1230 Routine Description:
1231
1232 This routine is used to enumerate entire pci bus system
1233 in a given platform
1234
1235 Arguments:
1236
1237 Returns:
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 (
1267 Controller ,
1268 &gEfiDevicePathProtocolGuid,
1269 (VOID **)&ParentDevicePath,
1270 gPciBusDriverBinding.DriverBindingHandle,
1271 Controller,
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 //
1294 // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge
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
1346 EFI_STATUS
1347 PciGetBusRange (
1348 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
1349 OUT UINT16 *MinBus,
1350 OUT UINT16 *MaxBus,
1351 OUT UINT16 *BusRange
1352 )
1353 /*++
1354
1355 Routine Description:
1356
1357 Get the bus range.
1358
1359 Arguments:
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.
1365
1366 Returns:
1367
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