]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
Porting Duet module from EDKI to EDKII
[mirror_edk2.git] / DuetPkg / PciRootBridgeNoEnumerationDxe / PcatPciRootBridge.c
1 /*++
2
3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. 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_IO_PROTOCOL *gCpuIo;
25
26 EFI_STATUS
27 EFIAPI
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 (&gEfiCpuIoProtocolGuid, NULL, &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 &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 = 0xffffffffffffffff;
108 PrivateData->Pmem32Base = 0xffffffffffffffff;
109 PrivateData->Mem64Base = 0xffffffffffffffff;
110 PrivateData->Pmem64Base = 0xffffffffffffffff;
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, (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),
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 EfiPciWidthUint32,
209 Address,
210 sizeof (PciConfigurationHeader) / sizeof (UINT32),
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 // Increment the number of PCI device found on the primary bus of the PCI root bridge
222 //
223 NumberOfPciDevices++;
224
225 //
226 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
227 //
228 if (PciConfigurationHeader.Hdr.Command & 0x20) {
229 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
230 }
231
232 //
233 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
234 //
235 if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
236 //
237 // Get the Bus range that the PPB is decoding
238 //
239 if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {
240 //
241 // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
242 // current subordinate bus number, then update the PCI root bridge's subordinate bus number
243 //
244 PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;
245 }
246
247 //
248 // Get the I/O range that the PPB is decoding
249 //
250 Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;
251 Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;
252 Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
253 if (Value == 0x01) {
254 Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);
255 Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);
256 }
257 if (Base < Limit) {
258 if (PrivateData->IoBase > Base) {
259 PrivateData->IoBase = Base;
260 }
261 if (PrivateData->IoLimit < Limit) {
262 PrivateData->IoLimit = Limit;
263 }
264 }
265
266 //
267 // Get the Memory range that the PPB is decoding
268 //
269 Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;
270 Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
271 if (Base < Limit) {
272 if (PrivateData->MemBase > Base) {
273 PrivateData->MemBase = Base;
274 }
275 if (PrivateData->MemLimit < Limit) {
276 PrivateData->MemLimit = Limit;
277 }
278 if (PrivateData->Mem32Base > Base) {
279 PrivateData->Mem32Base = Base;
280 }
281 if (PrivateData->Mem32Limit < Limit) {
282 PrivateData->Mem32Limit = Limit;
283 }
284 }
285
286 //
287 // Get the Prefetchable Memory range that the PPB is decoding
288 //
289 Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;
290 Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
291 Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
292 if (Value == 0x01) {
293 Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);
294 Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);
295 }
296 if (Base < Limit) {
297 if (PrivateData->MemBase > Base) {
298 PrivateData->MemBase = Base;
299 }
300 if (PrivateData->MemLimit < Limit) {
301 PrivateData->MemLimit = Limit;
302 }
303 if (Value == 0x00) {
304 if (PrivateData->Pmem32Base > Base) {
305 PrivateData->Pmem32Base = Base;
306 }
307 if (PrivateData->Pmem32Limit < Limit) {
308 PrivateData->Pmem32Limit = Limit;
309 }
310 }
311 if (Value == 0x01) {
312 if (PrivateData->Pmem64Base > Base) {
313 PrivateData->Pmem64Base = Base;
314 }
315 if (PrivateData->Pmem64Limit < Limit) {
316 PrivateData->Pmem64Limit = Limit;
317 }
318 }
319 }
320
321 //
322 // Look at the PPB Configuration for legacy decoding attributes
323 //
324 if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
325 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
326 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
327 }
328 if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
329 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
330 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
331 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
332 }
333
334 } else {
335 //
336 // Parse the BARs of the PCI device to determine what I/O Ranges,
337 // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
338 //
339 if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
340 Status = PcatPciRootBridgeParseBars (
341 PrivateData,
342 PciConfigurationHeader.Hdr.Command,
343 PrimaryBusIndex,
344 Device,
345 Function
346 );
347 }
348
349 //
350 // See if the PCI device is an IDE controller
351 //
352 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
353 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
354 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
355 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
356 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
357 }
358 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
359 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
360 }
361 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
362 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
363 }
364 }
365
366 //
367 // See if the PCI device is a legacy VGA controller
368 //
369 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
370 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
371 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
372 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
373 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
374 }
375
376 //
377 // See if the PCI device is a standard VGA controller
378 //
379 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
380 PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {
381 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
382 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
383 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
384 }
385
386 //
387 // See if the PCI Device is a PCI - ISA or PCI - EISA
388 // or ISA_POSITIVIE_DECODE Bridge device
389 //
390 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
391 if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
392 PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 ||
393 PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
394 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
395 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
396
397 if (PrivateData->MemBase > 0xa0000) {
398 PrivateData->MemBase = 0xa0000;
399 }
400 if (PrivateData->MemLimit < 0xbffff) {
401 PrivateData->MemLimit = 0xbffff;
402 }
403 }
404 }
405 }
406
407 //
408 // If this device is not a multi function device, then skip the rest of this PCI device
409 //
410 if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
411 break;
412 }
413 }
414 }
415
416 //
417 // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
418 // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
419 // bus number + 1.
420 //
421 PrimaryBusIndex = PrivateData->SubordinateBus + 1;
422
423 //
424 // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
425 // exists.
426 //
427 if (NumberOfPciDevices > 0) {
428
429 //
430 // Adjust the I/O range used for bounds checking for the legacy decoding attributed
431 //
432 if (PrivateData->Attributes & 0x7f) {
433 PrivateData->IoBase = 0;
434 if (PrivateData->IoLimit < 0xffff) {
435 PrivateData->IoLimit = 0xffff;
436 }
437 }
438
439 //
440 // Adjust the Memory range used for bounds checking for the legacy decoding attributed
441 //
442 if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
443 if (PrivateData->MemBase > 0xa0000) {
444 PrivateData->MemBase = 0xa0000;
445 }
446 if (PrivateData->MemLimit < 0xbffff) {
447 PrivateData->MemLimit = 0xbffff;
448 }
449 }
450
451 //
452 // Build ACPI descriptors for the resources on the PCI Root Bridge
453 //
454 Status = ConstructConfiguration(PrivateData);
455 ASSERT_EFI_ERROR (Status);
456
457 //
458 // Create the handle for this PCI Root Bridge
459 //
460 Status = gBS->InstallMultipleProtocolInterfaces (
461 &PrivateData->Handle,
462 &gEfiDevicePathProtocolGuid,
463 PrivateData->DevicePath,
464 &gEfiPciRootBridgeIoProtocolGuid,
465 &PrivateData->Io,
466 NULL
467 );
468 ASSERT_EFI_ERROR (Status);
469
470 //
471 // Contruct DeviceIoProtocol
472 //
473 Status = DeviceIoConstructor (
474 PrivateData->Handle,
475 &PrivateData->Io,
476 PrivateData->DevicePath,
477 (UINT16)PrivateData->PrimaryBus,
478 (UINT16)PrivateData->SubordinateBus
479 );
480 ASSERT_EFI_ERROR (Status);
481
482 //
483 // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
484 //
485 Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
486
487 //
488 // Increment the index for the next PCI Root Bridge
489 //
490 PciRootBridgeIndex++;
491
492 } else {
493
494 //
495 // If no PCI Root Bridges were found on the current PCI segment, then exit
496 //
497 if (NumberOfPciRootBridges == 0) {
498 Status = EFI_SUCCESS;
499 goto Done;
500 }
501
502 }
503
504 //
505 // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
506 // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
507 // Otherwise, the search is continued on the next PCI Root Bridge
508 //
509 if (PrimaryBusIndex > PCI_MAX_BUS) {
510 PciSegmentIndex++;
511 NumberOfPciRootBridges = 0;
512 PrimaryBusIndex = 0;
513 } else {
514 NumberOfPciRootBridges++;
515 }
516
517 }
518
519 return EFI_SUCCESS;
520
521 Done:
522 //
523 // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
524 //
525 if (PrivateData) {
526 if (PrivateData->DevicePath) {
527 gBS->FreePool(PrivateData->DevicePath);
528 }
529 gBS->FreePool (PrivateData);
530 }
531
532 //
533 // If no PCI Root Bridges were discovered, then return the error condition from scanning the
534 // first PCI Root Bridge
535 //
536 if (PciRootBridgeIndex == 0) {
537 return Status;
538 }
539
540 return EFI_SUCCESS;
541 }
542
543 EFI_STATUS
544 ConstructConfiguration(
545 IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
546 )
547 /*++
548
549 Routine Description:
550
551 Arguments:
552
553 Returns:
554
555 None
556
557 --*/
558
559 {
560 EFI_STATUS Status;
561 UINT8 NumConfig;
562 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
563 EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;
564
565 NumConfig = 0;
566 PrivateData->Configuration = NULL;
567
568 if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
569 NumConfig++;
570 }
571 if (PrivateData->IoLimit >= PrivateData->IoBase) {
572 NumConfig++;
573 }
574 if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
575 NumConfig++;
576 }
577 if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
578 NumConfig++;
579 }
580 if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
581 NumConfig++;
582 }
583 if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
584 NumConfig++;
585 }
586
587 if ( NumConfig == 0 ) {
588
589 //
590 // If there is no resource request
591 //
592 Status = gBS->AllocatePool (
593 EfiBootServicesData,
594 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
595 &PrivateData->Configuration
596 );
597 if (EFI_ERROR (Status )) {
598 return Status;
599 }
600
601 Configuration = PrivateData->Configuration;
602
603 ZeroMem (
604 Configuration,
605 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
606 );
607
608 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
609 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
610 Configuration++;
611
612 ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
613 ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
614 ConfigurationEnd->Checksum = 0;
615 }
616
617 //
618 // If there is at least one type of resource request,
619 // allocate a acpi resource node
620 //
621 Status = gBS->AllocatePool (
622 EfiBootServicesData,
623 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
624 &PrivateData->Configuration
625 );
626 if (EFI_ERROR (Status )) {
627 return Status;
628 }
629
630 Configuration = PrivateData->Configuration;
631
632 ZeroMem (
633 Configuration,
634 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
635 );
636
637 if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
638 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
639 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
640 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
641 Configuration->SpecificFlag = 0;
642 Configuration->AddrRangeMin = PrivateData->PrimaryBus;
643 Configuration->AddrRangeMax = PrivateData->SubordinateBus;
644 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
645 Configuration++;
646 }
647 //
648 // Deal with io aperture
649 //
650 if (PrivateData->IoLimit >= PrivateData->IoBase) {
651 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
652 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
653 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
654 Configuration->SpecificFlag = 1; //non ISA range
655 Configuration->AddrRangeMin = PrivateData->IoBase;
656 Configuration->AddrRangeMax = PrivateData->IoLimit;
657 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
658 Configuration++;
659 }
660
661 //
662 // Deal with mem32 aperture
663 //
664 if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
665 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
666 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
667 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
668 Configuration->SpecificFlag = 0; //Nonprefechable
669 Configuration->AddrSpaceGranularity = 32; //32 bit
670 Configuration->AddrRangeMin = PrivateData->Mem32Base;
671 Configuration->AddrRangeMax = PrivateData->Mem32Limit;
672 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
673 Configuration++;
674 }
675
676 //
677 // Deal with Pmem32 aperture
678 //
679 if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
680 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
681 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
682 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
683 Configuration->SpecificFlag = 0x6; //prefechable
684 Configuration->AddrSpaceGranularity = 32; //32 bit
685 Configuration->AddrRangeMin = PrivateData->Pmem32Base;
686 Configuration->AddrRangeMax = PrivateData->Pmem32Limit;
687 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
688 Configuration++;
689 }
690
691 //
692 // Deal with mem64 aperture
693 //
694 if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
695 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
696 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
697 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
698 Configuration->SpecificFlag = 0; //nonprefechable
699 Configuration->AddrSpaceGranularity = 64; //32 bit
700 Configuration->AddrRangeMin = PrivateData->Mem64Base;
701 Configuration->AddrRangeMax = PrivateData->Mem64Limit;
702 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
703 Configuration++;
704 }
705
706 //
707 // Deal with Pmem64 aperture
708 //
709 if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
710 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
711 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
712 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
713 Configuration->SpecificFlag = 0x06; //prefechable
714 Configuration->AddrSpaceGranularity = 64; //32 bit
715 Configuration->AddrRangeMin = PrivateData->Pmem64Base;
716 Configuration->AddrRangeMax = PrivateData->Pmem64Limit;
717 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
718 Configuration++;
719 }
720
721 //
722 // put the checksum
723 //
724 ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
725 ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
726 ConfigurationEnd->Checksum = 0;
727
728 return EFI_SUCCESS;
729 }
730
731 EFI_STATUS
732 PcatPciRootBridgeBarExisted (
733 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
734 IN UINT64 Address,
735 OUT UINT32 *OriginalValue,
736 OUT UINT32 *Value
737 )
738 /*++
739
740 Routine Description:
741
742 Arguments:
743
744 Returns:
745
746 None
747
748 --*/
749 {
750 EFI_STATUS Status;
751 UINT32 AllOnes;
752 EFI_TPL OldTpl;
753
754 //
755 // Preserve the original value
756 //
757 Status = PrivateData->Io.Pci.Read (
758 &PrivateData->Io,
759 EfiPciWidthUint32,
760 Address,
761 1,
762 OriginalValue
763 );
764
765 //
766 // Raise TPL to high level to disable timer interrupt while the BAR is probed
767 //
768 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
769
770 AllOnes = 0xffffffff;
771
772 Status = PrivateData->Io.Pci.Write (
773 &PrivateData->Io,
774 EfiPciWidthUint32,
775 Address,
776 1,
777 &AllOnes
778 );
779 Status = PrivateData->Io.Pci.Read (
780 &PrivateData->Io,
781 EfiPciWidthUint32,
782 Address,
783 1,
784 Value
785 );
786
787 //
788 //Write back the original value
789 //
790 Status = PrivateData->Io.Pci.Write (
791 &PrivateData->Io,
792 EfiPciWidthUint32,
793 Address,
794 1,
795 OriginalValue
796 );
797
798 //
799 // Restore TPL to its original level
800 //
801 gBS->RestoreTPL (OldTpl);
802
803 if ( *Value == 0 ) {
804 return EFI_DEVICE_ERROR;
805 }
806 return EFI_SUCCESS;
807 }
808
809 EFI_STATUS
810 PcatPciRootBridgeParseBars (
811 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
812 IN UINT16 Command,
813 IN UINTN Bus,
814 IN UINTN Device,
815 IN UINTN Function
816 )
817 /*++
818
819 Routine Description:
820
821 Arguments:
822
823 Returns:
824
825 None
826
827 --*/
828 {
829 EFI_STATUS Status;
830 UINT64 Address;
831 UINT32 OriginalValue;
832 UINT32 Value;
833 UINT32 OriginalUpperValue;
834 UINT32 UpperValue;
835 UINT64 Mask;
836 UINTN Offset;
837 UINT64 Base;
838 UINT64 Length;
839 UINT64 Limit;
840
841 for (Offset = 0x10; Offset < 0x28; Offset += 4) {
842 Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
843 Status = PcatPciRootBridgeBarExisted (
844 PrivateData,
845 Address,
846 &OriginalValue,
847 &Value
848 );
849
850 if (!EFI_ERROR (Status )) {
851 if ( Value & 0x01 ) {
852 if (Command & 0x0001) {
853 //
854 //Device I/Os
855 //
856 Mask = 0xfffffffc;
857 Base = OriginalValue & Mask;
858 Length = ((~(Value & Mask)) & Mask) + 0x04;
859 if (!(Value & 0xFFFF0000)){
860 Length &= 0x0000FFFF;
861 }
862 Limit = Base + Length - 1;
863
864 if (Base < Limit) {
865 if (PrivateData->IoBase > Base) {
866 PrivateData->IoBase = (UINT32)Base;
867 }
868 if (PrivateData->IoLimit < Limit) {
869 PrivateData->IoLimit = (UINT32)Limit;
870 }
871 }
872 }
873
874 } else {
875
876 if (Command & 0x0002) {
877
878 Mask = 0xfffffff0;
879 Base = OriginalValue & Mask;
880 Length = Value & Mask;
881
882 if ((Value & 0x07) != 0x04) {
883 Length = ((~Length) + 1) & 0xffffffff;
884 } else {
885 Offset += 4;
886 Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
887
888 Status = PcatPciRootBridgeBarExisted (
889 PrivateData,
890 Address,
891 &OriginalUpperValue,
892 &UpperValue
893 );
894
895 Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);
896 Length = Length | LShiftU64((UINT64)UpperValue,32);
897 Length = (~Length) + 1;
898 }
899
900 Limit = Base + Length - 1;
901
902 if (Base < Limit) {
903 if (PrivateData->MemBase > Base) {
904 PrivateData->MemBase = Base;
905 }
906 if (PrivateData->MemLimit < Limit) {
907 PrivateData->MemLimit = Limit;
908 }
909
910 switch (Value &0x07) {
911 case 0x00: ////memory space; anywhere in 32 bit address space
912 if (Value & 0x08) {
913 if (PrivateData->Pmem32Base > Base) {
914 PrivateData->Pmem32Base = Base;
915 }
916 if (PrivateData->Pmem32Limit < Limit) {
917 PrivateData->Pmem32Limit = Limit;
918 }
919 } else {
920 if (PrivateData->Mem32Base > Base) {
921 PrivateData->Mem32Base = Base;
922 }
923 if (PrivateData->Mem32Limit < Limit) {
924 PrivateData->Mem32Limit = Limit;
925 }
926 }
927 break;
928 case 0x04: //memory space; anywhere in 64 bit address space
929 if (Value & 0x08) {
930 if (PrivateData->Pmem64Base > Base) {
931 PrivateData->Pmem64Base = Base;
932 }
933 if (PrivateData->Pmem64Limit < Limit) {
934 PrivateData->Pmem64Limit = Limit;
935 }
936 } else {
937 if (PrivateData->Mem64Base > Base) {
938 PrivateData->Mem64Base = Base;
939 }
940 if (PrivateData->Mem64Limit < Limit) {
941 PrivateData->Mem64Limit = Limit;
942 }
943 }
944 break;
945 }
946 }
947 }
948 }
949 }
950 }
951 return EFI_SUCCESS;
952 }
953
954 UINT64
955 GetPciExpressBaseAddressForRootBridge (
956 IN UINTN HostBridgeNumber,
957 IN UINTN RootBridgeNumber
958 )
959 /*++
960
961 Routine Description:
962 This routine is to get PciExpress Base Address for this RootBridge
963
964 Arguments:
965 HostBridgeNumber - The number of HostBridge
966 RootBridgeNumber - The number of RootBridge
967
968 Returns:
969 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
970
971 --*/
972 {
973 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
974 UINTN BufferSize;
975 UINT32 Index;
976 UINT32 Number;
977 VOID *HobList;
978 EFI_STATUS Status;
979 EFI_PEI_HOB_POINTERS GuidHob;
980
981 //
982 // Get Hob List from configuration table
983 //
984 Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
985 if (EFI_ERROR (Status)) {
986 return 0;
987 }
988
989 //
990 // Get PciExpressAddressInfo Hob
991 //
992 PciExpressBaseAddressInfo = NULL;
993 BufferSize = 0;
994 GuidHob.Raw = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);
995 if (GuidHob.Raw != NULL) {
996 PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
997 BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
998 } else {
999 return 0;
1000 }
1001
1002 //
1003 // Search the PciExpress Base Address in the Hob for current RootBridge
1004 //
1005 Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
1006 for (Index = 0; Index < Number; Index++) {
1007 if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
1008 (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
1009 return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
1010 }
1011 }
1012
1013 //
1014 // Do not find the PciExpress Base Address in the Hob
1015 //
1016 return 0;
1017 }
1018