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