1/*++
2
3Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
4(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13Module Name:
14
15  PciEnumeratorSupport.c
16
17Abstract:
18
19  PCI Bus Driver
20
21Revision History
22
23--*/
24
25#include "PciBus.h"
26
27EFI_STATUS
28InitializePPB (
29  IN PCI_IO_DEVICE *PciIoDevice
30);
31
32EFI_STATUS
33InitializeP2C (
34  IN PCI_IO_DEVICE *PciIoDevice
35);
36
37PCI_IO_DEVICE*
38CreatePciIoDevice (
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
47PCI_IO_DEVICE*
48GatherP2CInfo (
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
56UINTN
57PciParseBar (
58  IN PCI_IO_DEVICE  *PciIoDevice,
59  IN UINTN          Offset,
60  IN UINTN          BarIndex
61);
62
63
64EFI_STATUS
65PciSearchDevice (
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
75EFI_STATUS
76DetermineDeviceAttribute (
77  IN PCI_IO_DEVICE                      *PciIoDevice
78);
79
80EFI_STATUS
81BarExisted (
82  IN PCI_IO_DEVICE *PciIoDevice,
83  IN UINTN         Offset,
84  OUT UINT32       *BarLengthValue,
85  OUT UINT32       *OriginalBarValue
86  );
87
88
89
90EFI_DEVICE_PATH_PROTOCOL*
91CreatePciDevicePath(
92  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
93  IN  PCI_IO_DEVICE            *PciIoDevice
94);
95
96PCI_IO_DEVICE*
97GatherDeviceInfo (
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
105PCI_IO_DEVICE*
106GatherPPBInfo (
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
114EFI_STATUS
115PciDevicePresent (
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
124Routine Description:
125
126  This routine is used to check whether the pci device is present
127
128Arguments:
129
130Returns:
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
175EFI_STATUS
176PciPciDeviceInfoCollector (
177  IN PCI_IO_DEVICE                      *Bridge,
178  UINT8                                 StartBusNumber
179  )
180/*++
181
182Routine Description:
183
184Arguments:
185
186Returns:
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
285EFI_STATUS
286PciSearchDevice (
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
296Routine Description:
297
298  Search required device.
299
300Arguments:
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
309Returns:
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
420PCI_IO_DEVICE *
421GatherDeviceInfo (
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
430Routine Description:
431
432Arguments:
433
434Returns:
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
475PCI_IO_DEVICE *
476GatherPPBInfo (
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
485Routine Description:
486
487Arguments:
488
489Returns:
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
575PCI_IO_DEVICE *
576GatherP2CInfo (
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
585Routine Description:
586
587Arguments:
588
589Returns:
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
630EFI_DEVICE_PATH_PROTOCOL *
631CreatePciDevicePath (
632  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
633  IN  PCI_IO_DEVICE            *PciIoDevice
634  )
635/*++
636
637Routine Description:
638
639Arguments:
640
641Returns:
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
664EFI_STATUS
665BarExisted (
666  IN PCI_IO_DEVICE *PciIoDevice,
667  IN UINTN         Offset,
668  OUT UINT32       *BarLengthValue,
669  OUT UINT32       *OriginalBarValue
670  )
671/*++
672
673Routine Description:
674
675  Check the bar is existed or not.
676
677Arguments:
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
684Returns:
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
738EFI_STATUS
739DetermineDeviceAttribute (
740  IN PCI_IO_DEVICE                      *PciIoDevice
741  )
742/*++
743
744Routine Description:
745
746  Determine the related attributes of all devices under a Root Bridge
747
748Arguments:
749
750Returns:
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
858UINTN
859PciParseBar (
860  IN PCI_IO_DEVICE  *PciIoDevice,
861  IN UINTN          Offset,
862  IN UINTN          BarIndex
863  )
864/*++
865
866Routine Description:
867
868Arguments:
869
870Returns:
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
1040EFI_STATUS
1041InitializePPB (
1042  IN PCI_IO_DEVICE *PciIoDevice
1043  )
1044/*++
1045
1046Routine Description:
1047
1048Arguments:
1049
1050Returns:
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
1086EFI_STATUS
1087InitializeP2C (
1088  IN PCI_IO_DEVICE *PciIoDevice
1089  )
1090/*++
1091
1092Routine Description:
1093
1094Arguments:
1095
1096Returns:
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
1126PCI_IO_DEVICE *
1127CreatePciIoDevice (
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
1136Routine Description:
1137
1138Arguments:
1139
1140Returns:
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
1215EFI_STATUS
1216PciEnumeratorLight (
1217  IN EFI_HANDLE                    Controller
1218  )
1219/*++
1220
1221Routine Description:
1222
1223  This routine is used to enumerate entire pci bus system
1224  in a given platform
1225
1226Arguments:
1227
1228Returns:
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
1337EFI_STATUS
1338PciGetBusRange (
1339  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
1340  OUT    UINT16                             *MinBus,
1341  OUT    UINT16                             *MaxBus,
1342  OUT    UINT16                             *BusRange
1343  )
1344/*++
1345
1346Routine Description:
1347
1348  Get the bus range.
1349
1350Arguments:
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
1357Returns:
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