1 /*++
2 
3 Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13   PcatPciRootBridge.c
14 
15 Abstract:
16 
17     EFI PC-AT PCI Root Bridge Controller
18 
19 --*/
20 
21 #include "PcatPciRootBridge.h"
22 #include "DeviceIo.h"
23 
24 EFI_CPU_IO2_PROTOCOL *gCpuIo;
25 
26 EFI_STATUS
27 EFIAPI
InitializePcatPciRootBridge(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)28 InitializePcatPciRootBridge (
29   IN EFI_HANDLE       ImageHandle,
30   IN EFI_SYSTEM_TABLE *SystemTable
31   )
32 /*++
33 
34 Routine Description:
35   Initializes the PCI Root Bridge Controller
36 
37 Arguments:
38   ImageHandle -
39   SystemTable -
40 
41 Returns:
42     None
43 
44 --*/
45 {
46   EFI_STATUS                     Status;
47   PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
48   UINTN                          PciSegmentIndex;
49   UINTN                          PciRootBridgeIndex;
50   UINTN                          PrimaryBusIndex;
51   UINTN                          NumberOfPciRootBridges;
52   UINTN                          NumberOfPciDevices;
53   UINTN                          Device;
54   UINTN                          Function;
55   UINT16                         VendorId;
56   PCI_TYPE01                     PciConfigurationHeader;
57   UINT64                         Address;
58   UINT64                         Value;
59   UINT64                         Base;
60   UINT64                         Limit;
61 
62   //
63   // Initialize gCpuIo now since the chipset init code requires it.
64   //
65   Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&gCpuIo);
66   ASSERT_EFI_ERROR (Status);
67 
68   //
69   // Initialize variables required to search all PCI segments for PCI devices
70   //
71   PciSegmentIndex        = 0;
72   PciRootBridgeIndex     = 0;
73   NumberOfPciRootBridges = 0;
74   PrimaryBusIndex        = 0;
75 
76   while (PciSegmentIndex <= PCI_MAX_SEGMENT) {
77 
78     PrivateData = NULL;
79     Status = gBS->AllocatePool(
80                     EfiBootServicesData,
81                     sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),
82                     (VOID **)&PrivateData
83                     );
84     if (EFI_ERROR (Status)) {
85       goto Done;
86     }
87 
88     ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));
89 
90     //
91     // Initialize the signature of the private data structure
92     //
93     PrivateData->Signature  = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;
94     PrivateData->Handle     = NULL;
95     PrivateData->DevicePath = NULL;
96     InitializeListHead (&PrivateData->MapInfo);
97 
98     //
99     // Initialize the PCI root bridge number and the bus range for that root bridge
100     //
101     PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;
102     PrivateData->PrimaryBus       = (UINT32)PrimaryBusIndex;
103     PrivateData->SubordinateBus   = (UINT32)PrimaryBusIndex;
104 
105     PrivateData->IoBase      = 0xffffffff;
106     PrivateData->MemBase     = 0xffffffff;
107     PrivateData->Mem32Base   = 0xffffffffffffffffULL;
108     PrivateData->Pmem32Base  = 0xffffffffffffffffULL;
109     PrivateData->Mem64Base   = 0xffffffffffffffffULL;
110     PrivateData->Pmem64Base  = 0xffffffffffffffffULL;
111 
112     //
113     // The default mechanism for performing PCI Configuration cycles is to
114     // use the I/O ports at 0xCF8 and 0xCFC.  This is only used for IA-32.
115     // IPF uses SAL calls to perform PCI COnfiguration cycles
116     //
117     PrivateData->PciAddress  = 0xCF8;
118     PrivateData->PciData     = 0xCFC;
119 
120     //
121     // Get the physical I/O base for performing PCI I/O cycles
122     // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
123     // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
124     //
125     Status = PcatRootBridgeIoGetIoPortMapping (
126                &PrivateData->PhysicalIoBase,
127                &PrivateData->PhysicalMemoryBase
128                );
129     if (EFI_ERROR (Status)) {
130       goto Done;
131     }
132 
133     //
134     // Get PCI Express Base Address
135     //
136     PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);
137     if (PrivateData->PciExpressBaseAddress != 0) {
138       DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));
139     }
140 
141     //
142     // Create a lock for performing PCI Configuration cycles
143     //
144     EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
145 
146     //
147     // Initialize the attributes for this PCI root bridge
148     //
149     PrivateData->Attributes  = 0;
150 
151     //
152     // Build the EFI Device Path Protocol instance for this PCI Root Bridge
153     //
154     Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE));
155     if (EFI_ERROR (Status)) {
156       goto Done;
157     }
158 
159     //
160     // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
161     //
162     Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);
163     if (EFI_ERROR (Status)) {
164       goto Done;
165     }
166 
167     //
168     // Scan all the PCI devices on the primary bus of the PCI root bridge
169     //
170     for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
171 
172       for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
173 
174         //
175         // Compute the PCI configuration address of the PCI device to probe
176         //
177         Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);
178 
179         //
180         // Read the Vendor ID from the PCI Configuration Header
181         //
182         Status = PrivateData->Io.Pci.Read (
183                                        &PrivateData->Io,
184                                        EfiPciWidthUint16,
185                                        Address,
186                                        sizeof (VendorId) / sizeof (UINT16),
187                                        &VendorId
188                                        );
189         if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {
190           //
191           // If the PCI Configuration Read fails, or a PCI device does not exist, then
192           // skip this entire PCI device
193           //
194           break;
195         }
196         if (VendorId == 0xffff) {
197           //
198           // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
199           //
200           continue;
201         }
202 
203         //
204         // Read the entire PCI Configuration Header
205         //
206         Status = PrivateData->Io.Pci.Read (
207                                        &PrivateData->Io,
208                                        EfiPciWidthUint16,
209                                        Address,
210                                        sizeof (PciConfigurationHeader) / sizeof (UINT16),
211                                        &PciConfigurationHeader
212                                        );
213         if (EFI_ERROR (Status)) {
214           //
215           // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
216           //
217           break;
218         }
219 
220 
221         //
222         // Increment the number of PCI device found on the primary bus of the PCI root bridge
223         //
224         NumberOfPciDevices++;
225 
226         //
227         // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
228         //
229         if (PciConfigurationHeader.Hdr.Command & 0x20) {
230           PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
231         }
232 
233         //
234         // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
235         //
236         if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
237           //
238           // Get the Bus range that the PPB is decoding
239           //
240           if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {
241             //
242             // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
243             // current subordinate bus number, then update the PCI root bridge's subordinate bus number
244             //
245             PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;
246           }
247 
248           //
249           // Get the I/O range that the PPB is decoding
250           //
251           Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;
252           Base  = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;
253           Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
254           if (Value == 0x01) {
255             Base  |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);
256             Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);
257           }
258           if (Base < Limit) {
259             if (PrivateData->IoBase > Base) {
260               PrivateData->IoBase = Base;
261             }
262             if (PrivateData->IoLimit < Limit) {
263               PrivateData->IoLimit = Limit;
264             }
265           }
266 
267           //
268           // Get the Memory range that the PPB is decoding
269           //
270           Base  = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;
271           Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
272           if (Base < Limit) {
273             if (PrivateData->MemBase > Base) {
274               PrivateData->MemBase = Base;
275             }
276             if (PrivateData->MemLimit < Limit) {
277               PrivateData->MemLimit = Limit;
278             }
279             if (PrivateData->Mem32Base > Base) {
280               PrivateData->Mem32Base = Base;
281             }
282             if (PrivateData->Mem32Limit < Limit) {
283               PrivateData->Mem32Limit = Limit;
284             }
285           }
286 
287           //
288           // Get the Prefetchable Memory range that the PPB is decoding
289           //
290           Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;
291           Base  = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
292           Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
293           if (Value == 0x01) {
294             Base  |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);
295             Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);
296           }
297           if (Base < Limit) {
298             if (PrivateData->MemBase > Base) {
299               PrivateData->MemBase = Base;
300             }
301             if (PrivateData->MemLimit < Limit) {
302               PrivateData->MemLimit = Limit;
303             }
304             if (Value == 0x00) {
305               if (PrivateData->Pmem32Base > Base) {
306                 PrivateData->Pmem32Base = Base;
307               }
308               if (PrivateData->Pmem32Limit < Limit) {
309                 PrivateData->Pmem32Limit = Limit;
310               }
311             }
312             if (Value == 0x01) {
313               if (PrivateData->Pmem64Base > Base) {
314                 PrivateData->Pmem64Base = Base;
315               }
316               if (PrivateData->Pmem64Limit < Limit) {
317                 PrivateData->Pmem64Limit = Limit;
318               }
319             }
320           }
321 
322           //
323           // Look at the PPB Configuration for legacy decoding attributes
324           //
325           if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
326             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
327             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
328           }
329           if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
330             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
331             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
332             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
333           }
334 
335         } else {
336           //
337           // Parse the BARs of the PCI device to determine what I/O Ranges,
338           // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
339           //
340           if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
341             Status = PcatPciRootBridgeParseBars (
342                        PrivateData,
343                        PciConfigurationHeader.Hdr.Command,
344                        PrimaryBusIndex,
345                        Device,
346                        Function
347                        );
348           }
349 
350           //
351           // See if the PCI device is an IDE controller
352           //
353           if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
354               PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {
355             if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
356               PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
357               PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
358             }
359             if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
360               PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
361             }
362             if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
363               PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
364             }
365           }
366 
367           //
368           // See if the PCI device is a legacy VGA controller
369           //
370           if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
371               PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {
372             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
373             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
374             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
375           }
376 
377           //
378           // See if the PCI device is a standard VGA controller
379           //
380           if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
381               PciConfigurationHeader.Hdr.ClassCode[1] == 0x00    ) {
382             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
383             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
384             PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
385           }
386 
387           //
388           // See if the PCI Device is a PCI - ISA or PCI - EISA
389           // or ISA_POSITIVIE_DECODE Bridge device
390           //
391           if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
392             if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
393                 PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 ||
394                 PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
395               PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
396               PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
397 
398               if (PrivateData->MemBase > 0xa0000) {
399                 PrivateData->MemBase = 0xa0000;
400               }
401               if (PrivateData->MemLimit < 0xbffff) {
402                PrivateData->MemLimit = 0xbffff;
403              }
404             }
405           }
406         }
407 
408         //
409         // If this device is not a multi function device, then skip the rest of this PCI device
410         //
411         if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
412           break;
413         }
414       }
415     }
416 
417     //
418     // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
419     // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
420     // bus number + 1.
421     //
422     PrimaryBusIndex = PrivateData->SubordinateBus + 1;
423 
424     //
425     // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
426     // exists.
427     //
428     if (NumberOfPciDevices > 0) {
429 
430       //
431       // Adjust the I/O range used for bounds checking for the legacy decoding attributed
432       //
433       if (PrivateData->Attributes & 0x7f) {
434         PrivateData->IoBase = 0;
435         if (PrivateData->IoLimit < 0xffff) {
436           PrivateData->IoLimit = 0xffff;
437         }
438       }
439 
440       //
441       // Adjust the Memory range used for bounds checking for the legacy decoding attributed
442       //
443       if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
444         if (PrivateData->MemBase > 0xa0000) {
445           PrivateData->MemBase = 0xa0000;
446         }
447         if (PrivateData->MemLimit < 0xbffff) {
448           PrivateData->MemLimit = 0xbffff;
449         }
450       }
451 
452       //
453       // Build ACPI descriptors for the resources on the PCI Root Bridge
454       //
455       Status = ConstructConfiguration(PrivateData);
456       ASSERT_EFI_ERROR (Status);
457 
458       //
459       // Create the handle for this PCI Root Bridge
460       //
461       Status = gBS->InstallMultipleProtocolInterfaces (
462                      &PrivateData->Handle,
463                      &gEfiDevicePathProtocolGuid,
464                      PrivateData->DevicePath,
465                      &gEfiPciRootBridgeIoProtocolGuid,
466                      &PrivateData->Io,
467                      NULL
468                      );
469       ASSERT_EFI_ERROR (Status);
470 
471       //
472       // Contruct DeviceIoProtocol
473       //
474       Status = DeviceIoConstructor (
475                  PrivateData->Handle,
476                  &PrivateData->Io,
477                  PrivateData->DevicePath,
478                  (UINT16)PrivateData->PrimaryBus,
479                  (UINT16)PrivateData->SubordinateBus
480                  );
481       ASSERT_EFI_ERROR (Status);
482 
483       //
484       // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
485       //
486       Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
487 
488       //
489       // Increment the index for the next PCI Root Bridge
490       //
491       PciRootBridgeIndex++;
492 
493     } else {
494 
495       //
496       // If no PCI Root Bridges were found on the current PCI segment, then exit
497       //
498       if (NumberOfPciRootBridges == 0) {
499         Status = EFI_SUCCESS;
500         goto Done;
501       }
502 
503     }
504 
505     //
506     // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
507     // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
508     // Otherwise, the search is continued on the next PCI Root Bridge
509     //
510     if (PrimaryBusIndex > PCI_MAX_BUS) {
511       PciSegmentIndex++;
512       NumberOfPciRootBridges = 0;
513       PrimaryBusIndex = 0;
514     } else {
515       NumberOfPciRootBridges++;
516     }
517 
518   }
519 
520   return EFI_SUCCESS;
521 
522 Done:
523   //
524   // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
525   //
526   if (PrivateData) {
527     if (PrivateData->DevicePath) {
528       gBS->FreePool(PrivateData->DevicePath);
529     }
530     gBS->FreePool (PrivateData);
531   }
532 
533   //
534   // If no PCI Root Bridges were discovered, then return the error condition from scanning the
535   // first PCI Root Bridge
536   //
537   if (PciRootBridgeIndex == 0) {
538     return Status;
539   }
540 
541   return EFI_SUCCESS;
542 }
543 
544 EFI_STATUS
ConstructConfiguration(IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE * PrivateData)545 ConstructConfiguration(
546   IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData
547   )
548 /*++
549 
550 Routine Description:
551 
552 Arguments:
553 
554 Returns:
555 
556   None
557 
558 --*/
559 
560 {
561   EFI_STATUS                         Status;
562   UINT8                              NumConfig;
563   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Configuration;
564   EFI_ACPI_END_TAG_DESCRIPTOR        *ConfigurationEnd;
565 
566   NumConfig = 0;
567   PrivateData->Configuration = NULL;
568 
569   if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
570     NumConfig++;
571   }
572   if (PrivateData->IoLimit >= PrivateData->IoBase) {
573     NumConfig++;
574   }
575   if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
576     NumConfig++;
577   }
578   if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
579     NumConfig++;
580   }
581   if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
582     NumConfig++;
583   }
584   if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
585     NumConfig++;
586   }
587 
588   if ( NumConfig == 0 ) {
589 
590     //
591     // If there is no resource request
592     //
593     Status = gBS->AllocatePool (
594                     EfiBootServicesData,
595                     sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
596                     (VOID **)&PrivateData->Configuration
597                     );
598     if (EFI_ERROR (Status )) {
599       return Status;
600     }
601 
602     Configuration = PrivateData->Configuration;
603 
604     ZeroMem (
605       Configuration,
606       sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
607       );
608 
609     Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
610     Configuration->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
611     Configuration++;
612 
613     ConfigurationEnd       = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
614     ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
615     ConfigurationEnd->Checksum = 0;
616   }
617 
618   //
619   // If there is at least one type of resource request,
620   // allocate a acpi resource node
621   //
622   Status = gBS->AllocatePool (
623                   EfiBootServicesData,
624                   sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
625                   (VOID **)&PrivateData->Configuration
626                   );
627   if (EFI_ERROR (Status )) {
628     return Status;
629   }
630 
631   Configuration = PrivateData->Configuration;
632 
633   ZeroMem (
634     Configuration,
635     sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
636     );
637 
638   if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
639     Configuration->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
640     Configuration->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
641     Configuration->ResType      = ACPI_ADDRESS_SPACE_TYPE_BUS;
642     Configuration->SpecificFlag = 0;
643     Configuration->AddrRangeMin = PrivateData->PrimaryBus;
644     Configuration->AddrRangeMax = PrivateData->SubordinateBus;
645     Configuration->AddrLen      = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
646     Configuration++;
647   }
648   //
649   // Deal with io aperture
650   //
651   if (PrivateData->IoLimit >= PrivateData->IoBase) {
652     Configuration->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
653     Configuration->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
654     Configuration->ResType      = ACPI_ADDRESS_SPACE_TYPE_IO;
655     Configuration->SpecificFlag = 1; //non ISA range
656     Configuration->AddrRangeMin = PrivateData->IoBase;
657     Configuration->AddrRangeMax = PrivateData->IoLimit;
658     Configuration->AddrLen      = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
659     Configuration++;
660   }
661 
662   //
663   // Deal with mem32 aperture
664   //
665   if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
666     Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
667     Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
668     Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
669     Configuration->SpecificFlag         = 0; //Nonprefechable
670     Configuration->AddrSpaceGranularity = 32; //32 bit
671     Configuration->AddrRangeMin         = PrivateData->Mem32Base;
672     Configuration->AddrRangeMax         = PrivateData->Mem32Limit;
673     Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
674     Configuration++;
675   }
676 
677   //
678   // Deal with Pmem32 aperture
679   //
680   if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
681     Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
682     Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
683     Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
684     Configuration->SpecificFlag         = 0x6; //prefechable
685     Configuration->AddrSpaceGranularity = 32; //32 bit
686     Configuration->AddrRangeMin         = PrivateData->Pmem32Base;
687     Configuration->AddrRangeMax         = PrivateData->Pmem32Limit;
688     Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
689     Configuration++;
690   }
691 
692   //
693   // Deal with mem64 aperture
694   //
695   if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
696     Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
697     Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
698     Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
699     Configuration->SpecificFlag         = 0; //nonprefechable
700     Configuration->AddrSpaceGranularity = 64; //32 bit
701     Configuration->AddrRangeMin         = PrivateData->Mem64Base;
702     Configuration->AddrRangeMax         = PrivateData->Mem64Limit;
703     Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
704     Configuration++;
705   }
706 
707   //
708   // Deal with Pmem64 aperture
709   //
710   if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
711     Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;
712     Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
713     Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;
714     Configuration->SpecificFlag         = 0x06; //prefechable
715     Configuration->AddrSpaceGranularity = 64; //32 bit
716     Configuration->AddrRangeMin         = PrivateData->Pmem64Base;
717     Configuration->AddrRangeMax         = PrivateData->Pmem64Limit;
718     Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
719     Configuration++;
720   }
721 
722   //
723   // put the checksum
724   //
725   ConfigurationEnd           = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
726   ConfigurationEnd->Desc     = ACPI_END_TAG_DESCRIPTOR;
727   ConfigurationEnd->Checksum = 0;
728 
729   return EFI_SUCCESS;
730 }
731 
732 EFI_STATUS
PcatPciRootBridgeBarExisted(IN PCAT_PCI_ROOT_BRIDGE_INSTANCE * PrivateData,IN UINT64 Address,OUT UINT32 * OriginalValue,OUT UINT32 * Value)733 PcatPciRootBridgeBarExisted (
734   IN  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
735   IN  UINT64                         Address,
736   OUT UINT32                         *OriginalValue,
737   OUT UINT32                         *Value
738   )
739 /*++
740 
741 Routine Description:
742 
743 Arguments:
744 
745 Returns:
746 
747   None
748 
749 --*/
750 {
751   EFI_STATUS  Status;
752   UINT32      AllOnes;
753   EFI_TPL     OldTpl;
754 
755   //
756   // Preserve the original value
757   //
758   Status = PrivateData->Io.Pci.Read (
759                                  &PrivateData->Io,
760                                  EfiPciWidthUint32,
761                                  Address,
762                                  1,
763                                  OriginalValue
764                                  );
765 
766   //
767   // Raise TPL to high level to disable timer interrupt while the BAR is probed
768   //
769   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
770 
771   AllOnes = 0xffffffff;
772 
773   Status = PrivateData->Io.Pci.Write (
774                                  &PrivateData->Io,
775                                  EfiPciWidthUint32,
776                                  Address,
777                                  1,
778                                  &AllOnes
779                                  );
780   Status = PrivateData->Io.Pci.Read (
781                                  &PrivateData->Io,
782                                  EfiPciWidthUint32,
783                                  Address,
784                                  1,
785                                  Value
786                                  );
787 
788   //
789   //Write back the original value
790   //
791   Status = PrivateData->Io.Pci.Write (
792                                  &PrivateData->Io,
793                                  EfiPciWidthUint32,
794                                  Address,
795                                  1,
796                                  OriginalValue
797                                  );
798 
799   //
800   // Restore TPL to its original level
801   //
802   gBS->RestoreTPL (OldTpl);
803 
804   if ( *Value == 0 ) {
805     return EFI_DEVICE_ERROR;
806   }
807   return Status;
808 }
809 
810 EFI_STATUS
PcatPciRootBridgeParseBars(IN PCAT_PCI_ROOT_BRIDGE_INSTANCE * PrivateData,IN UINT16 Command,IN UINTN Bus,IN UINTN Device,IN UINTN Function)811 PcatPciRootBridgeParseBars (
812   IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
813   IN UINT16                         Command,
814   IN UINTN                          Bus,
815   IN UINTN                          Device,
816   IN UINTN                          Function
817   )
818 /*++
819 
820 Routine Description:
821 
822 Arguments:
823 
824 Returns:
825 
826   None
827 
828 --*/
829 {
830   EFI_STATUS  Status;
831   UINT64      Address;
832   UINT32      OriginalValue;
833   UINT32      Value;
834   UINT32      OriginalUpperValue;
835   UINT32      UpperValue;
836   UINT64      Mask;
837   UINTN       Offset;
838   UINT64      Base;
839   UINT64      Length;
840   UINT64      Limit;
841 
842   for (Offset = 0x10; Offset < 0x28; Offset += 4) {
843     Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
844     Status = PcatPciRootBridgeBarExisted (
845                PrivateData,
846                Address,
847                &OriginalValue,
848                &Value
849                );
850 
851     if (!EFI_ERROR (Status )) {
852       if ( Value & 0x01 ) {
853         if (Command & 0x0001) {
854           //
855           //Device I/Os
856           //
857           Mask = 0xfffffffc;
858           Base = OriginalValue & Mask;
859           Length = ((~(Value & Mask)) & Mask) + 0x04;
860           if (!(Value & 0xFFFF0000)){
861             Length &= 0x0000FFFF;
862           }
863           Limit = Base + Length - 1;
864 
865           if (Base < Limit) {
866             if (PrivateData->IoBase > Base) {
867               PrivateData->IoBase = (UINT32)Base;
868             }
869             if (PrivateData->IoLimit < Limit) {
870               PrivateData->IoLimit = (UINT32)Limit;
871             }
872           }
873         }
874 
875       } else {
876 
877         if (Command & 0x0002) {
878 
879           Mask = 0xfffffff0;
880           Base = OriginalValue & Mask;
881           Length = Value & Mask;
882 
883           if ((Value & 0x07) != 0x04) {
884             Length = ((~Length) + 1) & 0xffffffff;
885           } else {
886             Offset += 4;
887             Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
888 
889             Status = PcatPciRootBridgeBarExisted (
890                        PrivateData,
891                        Address,
892                        &OriginalUpperValue,
893                        &UpperValue
894                        );
895 
896             Base   = Base | LShiftU64((UINT64)OriginalUpperValue,32);
897             Length = Length | LShiftU64((UINT64)UpperValue,32);
898             Length = (~Length) + 1;
899           }
900 
901           Limit = Base + Length - 1;
902 
903           if (Base < Limit) {
904             if (PrivateData->MemBase > Base) {
905               PrivateData->MemBase = Base;
906             }
907             if (PrivateData->MemLimit < Limit) {
908               PrivateData->MemLimit = Limit;
909             }
910 
911             switch (Value &0x07) {
912             case 0x00: ////memory space; anywhere in 32 bit address space
913               if (Value & 0x08) {
914                 if (PrivateData->Pmem32Base > Base) {
915                   PrivateData->Pmem32Base = Base;
916                 }
917                 if (PrivateData->Pmem32Limit < Limit) {
918                   PrivateData->Pmem32Limit = Limit;
919                 }
920               } else {
921                 if (PrivateData->Mem32Base > Base) {
922                   PrivateData->Mem32Base = Base;
923                 }
924                 if (PrivateData->Mem32Limit < Limit) {
925                   PrivateData->Mem32Limit = Limit;
926                 }
927               }
928               break;
929             case 0x04: //memory space; anywhere in 64 bit address space
930               if (Value & 0x08) {
931                 if (PrivateData->Pmem64Base > Base) {
932                   PrivateData->Pmem64Base = Base;
933                 }
934                 if (PrivateData->Pmem64Limit < Limit) {
935                   PrivateData->Pmem64Limit = Limit;
936                 }
937               } else {
938                 if (PrivateData->Mem64Base > Base) {
939                   PrivateData->Mem64Base = Base;
940                 }
941                 if (PrivateData->Mem64Limit < Limit) {
942                   PrivateData->Mem64Limit = Limit;
943                 }
944               }
945               break;
946             }
947           }
948         }
949       }
950     }
951   }
952   return EFI_SUCCESS;
953 }
954 
955 UINT64
GetPciExpressBaseAddressForRootBridge(IN UINTN HostBridgeNumber,IN UINTN RootBridgeNumber)956 GetPciExpressBaseAddressForRootBridge (
957   IN UINTN    HostBridgeNumber,
958   IN UINTN    RootBridgeNumber
959   )
960 /*++
961 
962 Routine Description:
963   This routine is to get PciExpress Base Address for this RootBridge
964 
965 Arguments:
966   HostBridgeNumber - The number of HostBridge
967   RootBridgeNumber - The number of RootBridge
968 
969 Returns:
970   UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
971 
972 --*/
973 {
974   EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
975   UINTN                                    BufferSize;
976   UINT32                                   Index;
977   UINT32                                   Number;
978   EFI_PEI_HOB_POINTERS                     GuidHob;
979 
980   //
981   // Get PciExpressAddressInfo Hob
982   //
983   PciExpressBaseAddressInfo = NULL;
984   BufferSize                = 0;
985   GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);
986   if (GuidHob.Raw != NULL) {
987     PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
988     BufferSize                = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
989   } else {
990     return 0;
991   }
992 
993   //
994   // Search the PciExpress Base Address in the Hob for current RootBridge
995   //
996   Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
997   for (Index = 0; Index < Number; Index++) {
998     if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
999         (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
1000       return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
1001     }
1002   }
1003 
1004   //
1005   // Do not find the PciExpress Base Address in the Hob
1006   //
1007   return 0;
1008 }
1009 
1010