]> git.proxmox.com Git - mirror_edk2.git/blame - CorebootModulePkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
IntelFsp2Pkg/Tools: Add BSF bit field support in GenCfgOpt tool
[mirror_edk2.git] / CorebootModulePkg / PciRootBridgeNoEnumerationDxe / PcatPciRootBridge.c
CommitLineData
81a23a0f
LL
1/*++
2
3Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13 PcatPciRootBridge.c
14
15Abstract:
16
17 EFI PC-AT PCI Root Bridge Controller
18
19--*/
20
21#include "PcatPciRootBridge.h"
22#include "DeviceIo.h"
23
24EFI_CPU_IO2_PROTOCOL *gCpuIo;
25
26EFI_STATUS
27EFIAPI
28InitializePcatPciRootBridge (
29 IN EFI_HANDLE ImageHandle,
30 IN EFI_SYSTEM_TABLE *SystemTable
31 )
32/*++
33
34Routine Description:
35 Initializes the PCI Root Bridge Controller
36
37Arguments:
38 ImageHandle -
39 SystemTable -
40
41Returns:
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
522Done:
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
544EFI_STATUS
545ConstructConfiguration(
546 IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
547 )
548/*++
549
550Routine Description:
551
552Arguments:
553
554Returns:
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
732EFI_STATUS
733PcatPciRootBridgeBarExisted (
734 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
735 IN UINT64 Address,
736 OUT UINT32 *OriginalValue,
737 OUT UINT32 *Value
738 )
739/*++
740
741Routine Description:
742
743Arguments:
744
745Returns:
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
810EFI_STATUS
811PcatPciRootBridgeParseBars (
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
820Routine Description:
821
822Arguments:
823
824Returns:
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
955UINT64
956GetPciExpressBaseAddressForRootBridge (
957 IN UINTN HostBridgeNumber,
958 IN UINTN RootBridgeNumber
959 )
960/*++
961
962Routine Description:
963 This routine is to get PciExpress Base Address for this RootBridge
964
965Arguments:
966 HostBridgeNumber - The number of HostBridge
967 RootBridgeNumber - The number of RootBridge
968
969Returns:
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