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