]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
a21df4cec23786951d78d4c191641426f746a72d
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciEnumeratorSupport.c
1 /*++
2
3 Copyright (c) 2005 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 PciEnumeratorSupport.c
15
16 Abstract:
17
18 PCI Bus Driver
19
20 Revision History
21
22 --*/
23
24 #include "PciBus.h"
25
26 EFI_STATUS
27 InitializePPB (
28 IN PCI_IO_DEVICE *PciIoDevice
29 );
30
31 EFI_STATUS
32 InitializeP2C (
33 IN PCI_IO_DEVICE *PciIoDevice
34 );
35
36 PCI_IO_DEVICE*
37 CreatePciIoDevice (
38 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
39 IN PCI_TYPE00 *Pci,
40 UINT8 Bus,
41 UINT8 Device,
42 UINT8 Func
43 );
44
45
46 PCI_IO_DEVICE*
47 GatherP2CInfo (
48 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
49 IN PCI_TYPE00 *Pci,
50 UINT8 Bus,
51 UINT8 Device,
52 UINT8 Func
53 );
54
55 UINTN
56 PciParseBar (
57 IN PCI_IO_DEVICE *PciIoDevice,
58 IN UINTN Offset,
59 IN UINTN BarIndex
60 );
61
62
63 EFI_STATUS
64 PciSearchDevice (
65 IN PCI_IO_DEVICE *Bridge,
66 PCI_TYPE00 *Pci,
67 UINT8 Bus,
68 UINT8 Device,
69 UINT8 Func,
70 PCI_IO_DEVICE **PciDevice
71 );
72
73
74 EFI_STATUS
75 DetermineDeviceAttribute (
76 IN PCI_IO_DEVICE *PciIoDevice
77 );
78
79 EFI_STATUS
80 BarExisted (
81 IN PCI_IO_DEVICE *PciIoDevice,
82 IN UINTN Offset,
83 OUT UINT32 *BarLengthValue,
84 OUT UINT32 *OriginalBarValue
85 );
86
87
88
89 EFI_DEVICE_PATH_PROTOCOL*
90 CreatePciDevicePath(
91 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
92 IN PCI_IO_DEVICE *PciIoDevice
93 );
94
95 PCI_IO_DEVICE*
96 GatherDeviceInfo (
97 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
98 IN PCI_TYPE00 *Pci,
99 UINT8 Bus,
100 UINT8 Device,
101 UINT8 Func
102 );
103
104 PCI_IO_DEVICE*
105 GatherPPBInfo (
106 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
107 IN PCI_TYPE00 *Pci,
108 UINT8 Bus,
109 UINT8 Device,
110 UINT8 Func
111 );
112
113 EFI_STATUS
114 PciDevicePresent (
115 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
116 PCI_TYPE00 *Pci,
117 UINT8 Bus,
118 UINT8 Device,
119 UINT8 Func
120 )
121 /*++
122
123 Routine Description:
124
125 This routine is used to check whether the pci device is present
126
127 Arguments:
128
129 Returns:
130
131 None
132
133 --*/
134 {
135 UINT64 Address;
136 EFI_STATUS Status;
137
138 //
139 // Create PCI address map in terms of Bus, Device and Func
140 //
141 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
142
143 //
144 // Read the Vendor Id register
145 //
146 Status = PciRootBridgeIo->Pci.Read (
147 PciRootBridgeIo,
148 EfiPciWidthUint32,
149 Address,
150 1,
151 Pci
152 );
153
154 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
155
156 //
157 // Read the entire config header for the device
158 //
159
160 Status = PciRootBridgeIo->Pci.Read (
161 PciRootBridgeIo,
162 EfiPciWidthUint32,
163 Address,
164 sizeof (PCI_TYPE00) / sizeof (UINT32),
165 Pci
166 );
167
168 return EFI_SUCCESS;
169 }
170
171 return EFI_NOT_FOUND;
172 }
173
174 EFI_STATUS
175 PciPciDeviceInfoCollector (
176 IN PCI_IO_DEVICE *Bridge,
177 UINT8 StartBusNumber
178 )
179 /*++
180
181 Routine Description:
182
183 Arguments:
184
185 Returns:
186
187 None
188
189 --*/
190 {
191 EFI_STATUS Status;
192 PCI_TYPE00 Pci;
193 UINT8 Device;
194 UINT8 Func;
195 UINT8 SecBus;
196 PCI_IO_DEVICE *PciIoDevice;
197 EFI_PCI_IO_PROTOCOL *PciIo;
198
199 Status = EFI_SUCCESS;
200 SecBus = 0;
201
202 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
203
204 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
205
206 //
207 // Check to see whether PCI device is present
208 //
209
210 Status = PciDevicePresent (
211 Bridge->PciRootBridgeIo,
212 &Pci,
213 (UINT8) StartBusNumber,
214 (UINT8) Device,
215 (UINT8) Func
216 );
217
218 if (!EFI_ERROR (Status)) {
219
220 //
221 // Collect all the information about the PCI device discovered
222 //
223 Status = PciSearchDevice (
224 Bridge,
225 &Pci,
226 (UINT8) StartBusNumber,
227 Device,
228 Func,
229 &PciIoDevice
230 );
231
232 //
233 // Recursively scan PCI busses on the other side of PCI-PCI bridges
234 //
235 //
236
237 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
238
239 //
240 // If it is PPB, we need to get the secondary bus to continue the enumeration
241 //
242 PciIo = &(PciIoDevice->PciIo);
243
244 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
245
246 if (EFI_ERROR (Status)) {
247 return Status;
248 }
249
250 //
251 // Deep enumerate the next level bus
252 //
253 Status = PciPciDeviceInfoCollector (
254 PciIoDevice,
255 (UINT8) (SecBus)
256 );
257
258 }
259
260 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
261
262 //
263 // Skip sub functions, this is not a multi function device
264 //
265 Func = PCI_MAX_FUNC;
266 }
267 }
268
269 }
270 }
271
272 return EFI_SUCCESS;
273 }
274
275 EFI_STATUS
276 PciSearchDevice (
277 IN PCI_IO_DEVICE *Bridge,
278 IN PCI_TYPE00 *Pci,
279 IN UINT8 Bus,
280 IN UINT8 Device,
281 IN UINT8 Func,
282 OUT PCI_IO_DEVICE **PciDevice
283 )
284 /*++
285
286 Routine Description:
287
288 Search required device.
289
290 Arguments:
291
292 Bridge - A pointer to the PCI_IO_DEVICE.
293 Pci - A pointer to the PCI_TYPE00.
294 Bus - Bus number.
295 Device - Device number.
296 Func - Function number.
297 PciDevice - The Required pci device.
298
299 Returns:
300
301 Status code.
302
303 --*/
304 {
305 PCI_IO_DEVICE *PciIoDevice;
306
307 PciIoDevice = NULL;
308
309 if (!IS_PCI_BRIDGE (Pci)) {
310
311 if (IS_CARDBUS_BRIDGE (Pci)) {
312 PciIoDevice = GatherP2CInfo (
313 Bridge->PciRootBridgeIo,
314 Pci,
315 Bus,
316 Device,
317 Func
318 );
319 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
320 InitializeP2C (PciIoDevice);
321 }
322 } else {
323
324 //
325 // Create private data for Pci Device
326 //
327 PciIoDevice = GatherDeviceInfo (
328 Bridge->PciRootBridgeIo,
329 Pci,
330 Bus,
331 Device,
332 Func
333 );
334
335 }
336
337 } else {
338
339 //
340 // Create private data for PPB
341 //
342 PciIoDevice = GatherPPBInfo (
343 Bridge->PciRootBridgeIo,
344 Pci,
345 Bus,
346 Device,
347 Func
348 );
349
350 //
351 // Special initialization for PPB including making the PPB quiet
352 //
353 if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
354 InitializePPB (PciIoDevice);
355 }
356 }
357
358 if (!PciIoDevice) {
359 return EFI_OUT_OF_RESOURCES;
360 }
361
362 //
363 // Create a device path for this PCI device and store it into its private data
364 //
365 CreatePciDevicePath(
366 Bridge->DevicePath,
367 PciIoDevice
368 );
369
370 //
371 // Detect this function has option rom
372 //
373 if (gFullEnumeration) {
374
375 if (!IS_CARDBUS_BRIDGE (Pci)) {
376
377 GetOpRomInfo (PciIoDevice);
378
379 }
380
381 ResetPowerManagementFeature (PciIoDevice);
382
383 }
384 else {
385 PciRomGetRomResourceFromPciOptionRomTable (
386 &gPciBusDriverBinding,
387 PciIoDevice->PciRootBridgeIo,
388 PciIoDevice
389 );
390 }
391
392
393 //
394 // Insert it into a global tree for future reference
395 //
396 InsertPciDevice (Bridge, PciIoDevice);
397
398 //
399 // Determine PCI device attributes
400 //
401 DetermineDeviceAttribute (PciIoDevice);
402
403 if (PciDevice != NULL) {
404 *PciDevice = PciIoDevice;
405 }
406
407 return EFI_SUCCESS;
408 }
409
410 PCI_IO_DEVICE *
411 GatherDeviceInfo (
412 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
413 IN PCI_TYPE00 *Pci,
414 UINT8 Bus,
415 UINT8 Device,
416 UINT8 Func
417 )
418 /*++
419
420 Routine Description:
421
422 Arguments:
423
424 Returns:
425
426 None
427
428 --*/
429 {
430 UINTN Offset;
431 UINTN BarIndex;
432 PCI_IO_DEVICE *PciIoDevice;
433
434 PciIoDevice = CreatePciIoDevice (
435 PciRootBridgeIo,
436 Pci,
437 Bus,
438 Device,
439 Func
440 );
441
442 if (!PciIoDevice) {
443 return NULL;
444 }
445
446 //
447 // If it is a full enumeration, disconnect the device in advance
448 //
449 if (gFullEnumeration) {
450
451 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
452
453 }
454
455 //
456 // Start to parse the bars
457 //
458 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
459 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
460 }
461
462 return PciIoDevice;
463 }
464
465 PCI_IO_DEVICE *
466 GatherPPBInfo (
467 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
468 IN PCI_TYPE00 *Pci,
469 UINT8 Bus,
470 UINT8 Device,
471 UINT8 Func
472 )
473 /*++
474
475 Routine Description:
476
477 Arguments:
478
479 Returns:
480
481 None
482
483 --*/
484 {
485 PCI_IO_DEVICE *PciIoDevice;
486 EFI_STATUS Status;
487 UINT8 Value;
488 EFI_PCI_IO_PROTOCOL *PciIo;
489 UINT8 Temp;
490
491 PciIoDevice = CreatePciIoDevice (
492 PciRootBridgeIo,
493 Pci,
494 Bus,
495 Device,
496 Func
497 );
498
499 if (!PciIoDevice) {
500 return NULL;
501 }
502
503 if (gFullEnumeration) {
504 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
505
506 //
507 // Initalize the bridge control register
508 //
509 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
510 }
511
512 PciIo = &PciIoDevice->PciIo;
513
514 //
515 // Test whether it support 32 decode or not
516 //
517 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
518 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
519 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
520 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
521
522 if (Value) {
523 if (Value & 0x01) {
524 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
525 } else {
526 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
527 }
528 }
529
530 Status = BarExisted (
531 PciIoDevice,
532 0x24,
533 NULL,
534 NULL
535 );
536
537 //
538 // test if it supports 64 memory or not
539 //
540 if (!EFI_ERROR (Status)) {
541
542 Status = BarExisted (
543 PciIoDevice,
544 0x28,
545 NULL,
546 NULL
547 );
548
549 if (!EFI_ERROR (Status)) {
550 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
551 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
552 } else {
553 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
554 }
555 }
556
557 //
558 // Memory 32 code is required for ppb
559 //
560 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
561
562 return PciIoDevice;
563 }
564
565 PCI_IO_DEVICE *
566 GatherP2CInfo (
567 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
568 IN PCI_TYPE00 *Pci,
569 UINT8 Bus,
570 UINT8 Device,
571 UINT8 Func
572 )
573 /*++
574
575 Routine Description:
576
577 Arguments:
578
579 Returns:
580
581 None
582
583 --*/
584 {
585 PCI_IO_DEVICE *PciIoDevice;
586
587 PciIoDevice = CreatePciIoDevice (
588 PciRootBridgeIo,
589 Pci,
590 Bus,
591 Device,
592 Func
593 );
594
595 if (!PciIoDevice) {
596 return NULL;
597 }
598
599 if (gFullEnumeration) {
600 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
601
602 //
603 // Initalize the bridge control register
604 //
605 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
606
607 }
608 //
609 // P2C only has one bar that is in 0x10
610 //
611 PciParseBar(PciIoDevice, 0x10, 0);
612
613 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
614 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
615 EFI_BRIDGE_IO32_DECODE_SUPPORTED;
616
617 return PciIoDevice;
618 }
619
620 EFI_DEVICE_PATH_PROTOCOL *
621 CreatePciDevicePath (
622 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
623 IN PCI_IO_DEVICE *PciIoDevice
624 )
625 /*++
626
627 Routine Description:
628
629 Arguments:
630
631 Returns:
632
633 None
634
635 --*/
636 {
637
638 PCI_DEVICE_PATH PciNode;
639
640 //
641 // Create PCI device path
642 //
643 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
644 PciNode.Header.SubType = HW_PCI_DP;
645 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
646
647 PciNode.Device = PciIoDevice->DeviceNumber;
648 PciNode.Function = PciIoDevice->FunctionNumber;
649 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
650
651 return PciIoDevice->DevicePath;
652 }
653
654 EFI_STATUS
655 BarExisted (
656 IN PCI_IO_DEVICE *PciIoDevice,
657 IN UINTN Offset,
658 OUT UINT32 *BarLengthValue,
659 OUT UINT32 *OriginalBarValue
660 )
661 /*++
662
663 Routine Description:
664
665 Check the bar is existed or not.
666
667 Arguments:
668
669 PciIoDevice - A pointer to the PCI_IO_DEVICE.
670 Offset - The offset.
671 BarLengthValue - The bar length value.
672 OriginalBarValue - The original bar value.
673
674 Returns:
675
676 EFI_NOT_FOUND - The bar don't exist.
677 EFI_SUCCESS - The bar exist.
678
679 --*/
680 {
681 EFI_PCI_IO_PROTOCOL *PciIo;
682 UINT32 OriginalValue;
683 UINT32 Value;
684 EFI_TPL OldTpl;
685
686 PciIo = &PciIoDevice->PciIo;
687
688 //
689 // Preserve the original value
690 //
691
692 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
693
694 //
695 // Raise TPL to high level to disable timer interrupt while the BAR is probed
696 //
697 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
698
699 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
700 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
701
702 //
703 // Write back the original value
704 //
705 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
706
707 //
708 // Restore TPL to its original level
709 //
710 gBS->RestoreTPL (OldTpl);
711
712 if (BarLengthValue != NULL) {
713 *BarLengthValue = Value;
714 }
715
716 if (OriginalBarValue != NULL) {
717 *OriginalBarValue = OriginalValue;
718 }
719
720 if (Value == 0) {
721 return EFI_NOT_FOUND;
722 } else {
723 return EFI_SUCCESS;
724 }
725 }
726
727
728 EFI_STATUS
729 DetermineDeviceAttribute (
730 IN PCI_IO_DEVICE *PciIoDevice
731 )
732 /*++
733
734 Routine Description:
735
736 Determine the related attributes of all devices under a Root Bridge
737
738 Arguments:
739
740 Returns:
741
742 None
743
744 --*/
745 {
746 UINT16 Command;
747 UINT16 BridgeControl;
748
749 Command = 0;
750
751 PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;
752 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
753
754 if (IS_PCI_VGA (&(PciIoDevice->Pci))){
755
756 //
757 // If the device is VGA, VGA related Attributes are supported
758 //
759 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
760 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ;
761 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ;
762 }
763
764 if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {
765 //
766 // If the devie is a ISA Bridge, set the two attributes
767 //
768 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
769 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
770 }
771
772 if (IS_PCI_GFX (&(PciIoDevice->Pci))) {
773
774 //
775 // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
776 // attribute
777 //
778 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
779 }
780
781
782 //
783 // If the device is IDE, IDE related attributes are supported
784 //
785 if (IS_PCI_IDE (&(PciIoDevice->Pci))) {
786 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ;
787 PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ;
788 }
789
790 PciReadCommandRegister(PciIoDevice, &Command);
791
792
793 if (Command & EFI_PCI_COMMAND_IO_SPACE) {
794 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
795 }
796
797 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
798 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
799 }
800
801 if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
802 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
803 }
804
805 if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) ||
806 IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){
807
808 //
809 // If it is a PPB, read the Bridge Control Register to determine
810 // the relevant attributes
811 //
812 BridgeControl = 0;
813 PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);
814
815 //
816 // Determine whether the ISA bit is set
817 // If ISA Enable on Bridge is set, the PPB
818 // will block forwarding 0x100-0x3ff for each 1KB in the
819 // first 64KB I/O range.
820 //
821 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
822 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
823 }
824
825 //
826 // Determine whether the VGA bit is set
827 // If it is set, the bridge is set to decode VGA memory range
828 // and palette register range
829 //
830 if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
831 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
832 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
833 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
834 }
835
836 //
837 // if the palette snoop bit is set, then the brige is set to
838 // decode palette IO write
839 //
840 if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
841 PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
842 }
843 }
844
845 return EFI_SUCCESS;
846 }
847
848 UINTN
849 PciParseBar (
850 IN PCI_IO_DEVICE *PciIoDevice,
851 IN UINTN Offset,
852 IN UINTN BarIndex
853 )
854 /*++
855
856 Routine Description:
857
858 Arguments:
859
860 Returns:
861
862 None
863
864 --*/
865 {
866 UINT32 Value;
867 //UINT64 BarValue64;
868 UINT32 OriginalValue;
869 UINT32 Mask;
870 UINT32 Data;
871 UINT8 Index;
872 EFI_STATUS Status;
873
874 OriginalValue = 0;
875 Value = 0;
876 //BarValue64 = 0;
877
878 Status = BarExisted (
879 PciIoDevice,
880 Offset,
881 &Value,
882 &OriginalValue
883 );
884
885 if (EFI_ERROR (Status)) {
886 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
887 PciIoDevice->PciBar[BarIndex].Length = 0;
888 PciIoDevice->PciBar[BarIndex].Alignment = 0;
889
890 //
891 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
892 //
893 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
894 return Offset + 4;
895 }
896
897 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
898 if (Value & 0x01) {
899 //
900 // Device I/Os
901 //
902 Mask = 0xfffffffc;
903
904 if (Value & 0xFFFF0000) {
905 //
906 // It is a IO32 bar
907 //
908 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
909 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
910 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
911
912 } else {
913 //
914 // It is a IO16 bar
915 //
916 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
917 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
918 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
919
920 }
921 //
922 // Workaround. Some platforms inplement IO bar with 0 length
923 // Need to treat it as no-bar
924 //
925 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
926 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
927 }
928
929 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
930 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
931
932 } else {
933
934 Mask = 0xfffffff0;
935
936 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
937
938 switch (Value & 0x07) {
939
940 //
941 //memory space; anywhere in 32 bit address space
942 //
943 case 0x00:
944 if (Value & 0x08) {
945 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
946 } else {
947 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
948 }
949
950 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
951 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
952
953 break;
954
955 //
956 // memory space; anywhere in 64 bit address space
957 //
958 case 0x04:
959 if (Value & 0x08) {
960 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
961 } else {
962 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
963 }
964
965 //
966 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
967 // is regarded as an extension for the first bar. As a result
968 // the sizing will be conducted on combined 64 bit value
969 // Here just store the masked first 32bit value for future size
970 // calculation
971 //
972 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
973 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
974
975 //
976 // Increment the offset to point to next DWORD
977 //
978 Offset += 4;
979
980 Status = BarExisted (
981 PciIoDevice,
982 Offset,
983 &Value,
984 &OriginalValue
985 );
986
987 if (EFI_ERROR (Status)) {
988 return Offset + 4;
989 }
990
991 //
992 // Fix the length to support some spefic 64 bit BAR
993 //
994 Data = Value;
995 Index = 0;
996 for (Data = Value; Data != 0; Data >>= 1) {
997 Index ++;
998 }
999 Value |= ((UINT32)(-1) << Index);
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