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