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