1 /** @file 2 * Implementation of the Pci Host Bridge Resource Allocation for the Xpress-RICH3 PCIe Root Complex 3 * 4 * Copyright (c) 2011-2015, ARM Ltd. All rights reserved. 5 * 6 * This program and the accompanying materials 7 * are licensed and made available under the terms and conditions of the BSD License 8 * which accompanies this distribution. The full text of the license may be found at 9 * http://opensource.org/licenses/bsd-license.php 10 * 11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 * 14 **/ 15 16 #include "PciHostBridge.h" 17 18 EFI_STATUS 19 PciHbRaNotifyPhase ( 20 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 21 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase 22 ) 23 { 24 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 25 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 26 EFI_STATUS Status; 27 EFI_PHYSICAL_ADDRESS BaseAddress; 28 UINT64 AddrLen; 29 UINTN BitsOfAlignment; 30 31 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 32 33 PCI_TRACE ("PciHbRaNotifyPhase()"); 34 35 // Check RootBridge Signature 36 ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE); 37 38 // The enumeration cannot be restarted after the process has been further than the first phase 39 if (Phase == EfiPciHostBridgeBeginEnumeration) { 40 if (!HostBridgeInstance->CanRestarted) { 41 return EFI_NOT_READY; 42 } 43 } else { 44 HostBridgeInstance->CanRestarted = FALSE; 45 } 46 47 switch (Phase) { 48 case EfiPciHostBridgeBeginEnumeration: 49 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginEnumeration)"); 50 // Resets the host bridge PCI apertures and internal data structures 51 Status = HWPciRbInit (HostBridgeInstance->CpuIo); 52 if (EFI_ERROR (Status)) { 53 return Status; 54 } 55 break; 56 57 case EfiPciHostBridgeBeginBusAllocation: 58 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginBusAllocation)"); 59 // The bus allocation phase is about to begin 60 break; 61 62 case EfiPciHostBridgeEndBusAllocation: 63 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndBusAllocation)"); 64 // The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back 65 // a bus number range into their configuration 66 break; 67 68 case EfiPciHostBridgeBeginResourceAllocation: 69 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginResourceAllocation)"); 70 // The resource allocation phase is about to begin. 71 break; 72 73 case EfiPciHostBridgeAllocateResources: 74 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeAllocateResources)"); 75 // Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to 76 // PciHbRaSubmitResources() before. 77 78 RootBridgeInstance = HostBridgeInstance->RootBridge; 79 if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) { 80 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1; // Get the number of '1' in Alignment 81 AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length; 82 83 Status = gDS->AllocateIoSpace ( 84 EfiGcdAllocateAnySearchBottomUp, 85 EfiGcdIoTypeIo, 86 BitsOfAlignment, 87 AddrLen, 88 &BaseAddress, 89 HostBridgeInstance->ImageHandle, 90 NULL 91 ); 92 // If error then ResAlloc[n].Base ==0 93 if (!EFI_ERROR (Status)) { 94 RootBridgeInstance->ResAlloc[ResTypeIo].Base = (UINTN)BaseAddress; 95 } 96 } 97 98 if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) { 99 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1; // Get the number of '1' in Alignment 100 AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length; 101 102 // Top of the 32bit PCI Memory space 103 BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size); 104 105 Status = gDS->AllocateMemorySpace ( 106 EfiGcdAllocateMaxAddressSearchTopDown, 107 EfiGcdMemoryTypeMemoryMappedIo, 108 BitsOfAlignment, 109 AddrLen, 110 &BaseAddress, 111 HostBridgeInstance->ImageHandle, 112 NULL 113 ); 114 115 // Ensure the allocation is in the 32bit PCI memory space 116 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) { 117 RootBridgeInstance->ResAlloc[ResTypeMem32].Base = (UINTN)BaseAddress; 118 } 119 } 120 if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) { 121 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1; // Get the number of '1' in Alignment 122 AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length; 123 124 // Top of the 32bit PCI Memory space 125 BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size); 126 127 Status = gDS->AllocateMemorySpace ( 128 EfiGcdAllocateMaxAddressSearchTopDown, 129 EfiGcdMemoryTypeMemoryMappedIo, 130 BitsOfAlignment, 131 AddrLen, 132 &BaseAddress, 133 HostBridgeInstance->ImageHandle, 134 NULL 135 ); 136 137 // Ensure the allocation is in the 32bit PCI memory space 138 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) { 139 RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)BaseAddress; 140 } 141 } 142 if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) { 143 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1; // Get the number of '1' in Alignment 144 AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length; 145 146 // Top of the 64bit PCI Memory space 147 BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size); 148 149 Status = gDS->AllocateMemorySpace ( 150 EfiGcdAllocateMaxAddressSearchTopDown, 151 EfiGcdMemoryTypeMemoryMappedIo, 152 BitsOfAlignment, 153 AddrLen, 154 &BaseAddress, 155 HostBridgeInstance->ImageHandle, 156 NULL 157 ); 158 159 // Ensure the allocation is in the 64bit PCI memory space 160 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) { 161 RootBridgeInstance->ResAlloc[ResTypeMem64].Base = (UINTN)BaseAddress; 162 } 163 } 164 if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) { 165 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1; //Get the number of '1' in Alignment 166 AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length; 167 168 // Top of the 64bit PCI Memory space 169 BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size); 170 171 Status = gDS->AllocateMemorySpace ( 172 EfiGcdAllocateMaxAddressSearchTopDown, 173 EfiGcdMemoryTypeMemoryMappedIo, 174 BitsOfAlignment, 175 AddrLen, 176 &BaseAddress, 177 HostBridgeInstance->ImageHandle, 178 NULL 179 ); 180 181 // Ensure the allocation is in the 64bit PCI memory space 182 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) { 183 RootBridgeInstance->ResAlloc[ResTypePMem64].Base = (UINTN)BaseAddress; 184 } 185 } 186 187 break; 188 189 case EfiPciHostBridgeSetResources: 190 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeSetResources)"); 191 // Programs the host bridge hardware to decode previously allocated resources (proposed resources) 192 // for all the PCI root bridges. The PCI bus driver will now program the resources 193 break; 194 195 case EfiPciHostBridgeFreeResources: 196 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeFreeResources)"); 197 // Deallocates resources that were previously allocated for all the PCI root bridges and resets the 198 // I/O and memory apertures to their initial state.*/ 199 break; 200 201 case EfiPciHostBridgeEndResourceAllocation: 202 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndResourceAllocation)"); 203 break; 204 205 case EfiPciHostBridgeEndEnumeration: 206 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndEnumeration)"); 207 break; 208 209 default: 210 DEBUG ((EFI_D_INFO, "PciHbRaNotifyPhase(Phase:%d)\n", Phase)); 211 ASSERT (0); 212 } 213 214 return EFI_SUCCESS; 215 } 216 217 /** 218 * PciHbRaGetNextRootBridge() returns the next root bridge attached to the 'This' PCI Host Bridge. 219 * As we have only got one PCI Root Bridge in this PCI interface, we return either this root bridge 220 * if it the first time we call this function (*RootBridgeHandle == NULL) or we return EFI_NOT_FOUND 221 **/ 222 EFI_STATUS 223 PciHbRaGetNextRootBridge ( 224 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 225 IN OUT EFI_HANDLE *RootBridgeHandle 226 ) 227 { 228 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 229 230 PCI_TRACE ("PciHbRaGetNextRootBridge()"); 231 232 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 233 ASSERT (HostBridgeInstance->RootBridge != NULL); 234 235 //Check RootBridge Signature 236 ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE); 237 238 if (*RootBridgeHandle == NULL) { 239 *RootBridgeHandle = HostBridgeInstance->RootBridge->Handle; 240 return EFI_SUCCESS; 241 } else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) { 242 return EFI_NOT_FOUND; 243 } else { 244 return EFI_INVALID_PARAMETER; 245 } 246 } 247 248 /** PciHbRaGetAllocAttributes() returns the resource allocation attributes supported by this PCI Root Bridge. 249 * A PCI Root bridge could support these types : 250 * - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate windows for nonprefetchable and prefetchable memory. 251 * - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows 252 **/ 253 EFI_STATUS 254 PciHbRaGetAllocAttributes ( 255 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 256 IN EFI_HANDLE RootBridgeHandle, 257 OUT UINT64 *Attributes 258 ) 259 { 260 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 261 262 PCI_TRACE ("PciHbRaGetAllocAttributes()"); 263 264 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 265 266 // Check if the RootBridgeHandle is the one managed by this PCI Host Bridge 267 ASSERT (HostBridgeInstance->RootBridge != NULL); 268 if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) { 269 return EFI_INVALID_PARAMETER; 270 } 271 272 *Attributes = HostBridgeInstance->RootBridge->MemAllocAttributes; 273 return EFI_SUCCESS; 274 } 275 276 EFI_STATUS 277 PciHbRaStartBusEnumeration ( 278 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 279 IN EFI_HANDLE RootBridgeHandle, 280 OUT VOID **Configuration 281 ) 282 { 283 VOID *Buffer; 284 UINT8 *Ptr; 285 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 286 287 // Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver 288 // to set bus numbers to PCI-to-PCI bridge. 289 PCI_TRACE ("PciHbRaStartBusEnumeration()"); 290 291 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 292 293 Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); 294 if (Buffer == NULL) { 295 return EFI_OUT_OF_RESOURCES; 296 } 297 298 Ptr = (UINT8 *)Buffer; 299 300 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; // QWORD Address space Descriptor 301 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len = 0x2B; // Length of this descriptor in bytes not including the first two fields 302 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; // Resource Type Bus Number Range 303 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0; 304 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0; 305 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0; 306 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart; // Bus Start 307 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0; // Bus Max 308 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0; 309 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1; 310 311 Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 312 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR; 313 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0; 314 315 *Configuration = Buffer; 316 return EFI_SUCCESS; 317 } 318 319 EFI_STATUS 320 PciHbRaSetBusNumbers ( 321 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 322 IN EFI_HANDLE RootBridgeHandle, 323 IN VOID *Configuration 324 ) 325 { 326 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 327 UINT8 *Ptr; 328 UINTN BusStart; 329 UINTN BusEnd; 330 UINTN BusLen; 331 332 PCI_TRACE ("PciHbRaSetBusNumbers()"); 333 334 Ptr = Configuration; 335 if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) { 336 return EFI_INVALID_PARAMETER; 337 } 338 339 // Check if the passed ACPI descriptor table define a Bus Number Range 340 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) { 341 return EFI_INVALID_PARAMETER; 342 } 343 344 // Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor) 345 if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) { 346 return EFI_INVALID_PARAMETER; 347 } 348 349 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 350 ASSERT (HostBridgeInstance->RootBridge != NULL); 351 if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) { 352 return EFI_INVALID_PARAMETER; 353 } 354 355 BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin; 356 BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen; 357 BusEnd = BusStart + BusLen - 1; 358 359 ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS 360 ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength)); 361 362 HostBridgeInstance->RootBridge->BusStart = BusStart; 363 HostBridgeInstance->RootBridge->BusLength = BusLen; 364 365 return EFI_SUCCESS; 366 } 367 368 /** 369 * This function is used to submit all the I/O and memory resources that are required by the specified 370 * PCI root bridge. 371 **/ 372 EFI_STATUS 373 PciHbRaSubmitResources ( 374 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 375 IN EFI_HANDLE RootBridgeHandle, 376 IN VOID *Configuration 377 ) 378 { 379 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 380 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 381 UINT8 *Ptr; 382 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; 383 PCI_RESOURCE_TYPE ResType; 384 385 PCI_TRACE ("PciHbRaSubmitResources()"); 386 387 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 388 389 if (Configuration == NULL) { 390 return EFI_INVALID_PARAMETER; 391 } 392 393 // Check if the ACPI Descriptor tables is conformed 394 Ptr = (UINT8 *)Configuration; 395 while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor 396 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; 397 } 398 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag 399 return EFI_INVALID_PARAMETER; 400 } 401 402 // Check the RootBridgeHandle 403 RootBridgeInstance = HostBridgeInstance->RootBridge; 404 ASSERT (RootBridgeInstance != NULL); 405 if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) { 406 return EFI_INVALID_PARAMETER; 407 } 408 409 Ptr = (UINT8 *)Configuration; 410 while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table 411 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr; 412 413 // Check if the description is valid 414 if (Desc->AddrLen > 0xffffffff) { 415 return EFI_INVALID_PARAMETER; 416 } 417 418 if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) { 419 return EFI_INVALID_PARAMETER; 420 } 421 422 switch (Desc->ResType) { 423 case ACPI_ADDRESS_SPACE_TYPE_MEM: 424 // Check invalid Address Space Granularity 425 if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) { 426 return EFI_INVALID_PARAMETER; 427 } 428 429 // check the memory resource request is supported by PCI root bridge 430 if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) { 431 return EFI_INVALID_PARAMETER; 432 } 433 434 if (Desc->AddrSpaceGranularity == 32) { 435 if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) { 436 ResType = ResTypePMem32; 437 } else { 438 ResType = ResTypeMem32; 439 } 440 } else { 441 if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) { 442 ResType = ResTypePMem64; 443 } else { 444 ResType = ResTypeMem64; 445 } 446 } 447 RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen; 448 RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax; 449 RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin; 450 break; 451 case ACPI_ADDRESS_SPACE_TYPE_IO: 452 RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen; 453 RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax; 454 RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0; 455 break; 456 default: 457 ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS 458 break; 459 } 460 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 461 } 462 463 return EFI_SUCCESS; 464 } 465 466 /** Returns the proposed resource settings for the specified PCI root bridge. The resources have been submitted by 467 * PciHbRaSubmitResources() before 468 **/ 469 EFI_STATUS 470 PciHbRaGetProposedResources ( 471 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 472 IN EFI_HANDLE RootBridgeHandle, 473 OUT VOID **Configuration 474 ) 475 { 476 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; 477 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 478 UINT32 i; 479 UINT32 ResAllocCount; 480 VOID *Buffer; 481 UINT8 *Ptr; 482 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; 483 484 PCI_TRACE ("PciHbRaGetProposedResources()"); 485 486 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 487 488 // Check the RootBridgeHandle 489 RootBridgeInstance = HostBridgeInstance->RootBridge; 490 ASSERT (RootBridgeInstance != NULL); 491 if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) { 492 return EFI_INVALID_PARAMETER; 493 } 494 495 // Count the number of Resource Allocated for this Root Bridge 496 ResAllocCount = 0; 497 for (i = 0; i < ResTypeMax; i++) { 498 if (RootBridgeInstance->ResAlloc[i].Length != 0) ResAllocCount++; 499 } 500 501 if (ResAllocCount == 0) { 502 return EFI_INVALID_PARAMETER; 503 } 504 505 Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); 506 if (Buffer == NULL) { 507 return EFI_OUT_OF_RESOURCES; 508 } 509 510 Ptr = Buffer; 511 for (i = 0; i < ResTypeMax; i++) { 512 if (RootBridgeInstance->ResAlloc[i].Length != 0) { // Base != 0 if the resource has been allocated 513 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr; 514 515 Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; 516 Desc->Len = 0x2B; 517 Desc->GenFlag = 0; 518 Desc->AddrRangeMax = 0; 519 520 switch (i) { 521 case ResTypeIo: 522 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; 523 Desc->SpecificFlag = 0; 524 Desc->AddrSpaceGranularity = 0; 525 break; 526 case ResTypeMem32: 527 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 528 Desc->SpecificFlag = 0; 529 Desc->AddrSpaceGranularity = 32; 530 break; 531 case ResTypePMem32: 532 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 533 Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE; 534 Desc->AddrSpaceGranularity = 32; 535 break; 536 case ResTypeMem64: 537 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 538 Desc->SpecificFlag = 0; 539 Desc->AddrSpaceGranularity = 64; 540 break; 541 case ResTypePMem64: 542 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; 543 Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE; 544 Desc->AddrSpaceGranularity = 64; 545 break; 546 } 547 Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base; 548 Desc->AddrTranslationOffset = (RootBridgeInstance->ResAlloc[i].Base != 0) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS; 549 Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length; 550 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); 551 } 552 } 553 554 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR; 555 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0; 556 557 *Configuration = Buffer; 558 return EFI_SUCCESS; 559 } 560 561 EFI_STATUS 562 PciHbRaPreprocessController ( 563 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, 564 IN EFI_HANDLE RootBridgeHandle, 565 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, 566 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase 567 ) 568 { 569 PCI_HOST_BRIDGE_INSTANCE* HostBridge; 570 PCI_ROOT_BRIDGE_INSTANCE* RootBridge; 571 UINT32 CapabilityPtr; 572 UINT32 CapabilityEntry; 573 UINT16 CapabilityID; 574 UINT32 DeviceCapability; 575 576 PCI_TRACE ("PciHbRaPreprocessController()"); 577 578 if (FeaturePcdGet (PcdPciMaxPayloadFixup)) { 579 // Do Max payload fixup for every devices 580 if (Phase == EfiPciBeforeResourceCollection) { 581 // Get RootBridge Instance from Host Bridge Instance 582 HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); 583 RootBridge = HostBridge->RootBridge; 584 585 // Get the first PCI Capability 586 CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET; 587 RootBridge->Io.Pci.Read ( 588 &RootBridge->Io, 589 EfiPciWidthUint8, 590 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr), 591 1, 592 &CapabilityPtr 593 ); 594 CapabilityPtr &= 0x1FF; 595 596 // Get Pci Express Capability 597 while (CapabilityPtr != 0) { 598 RootBridge->Io.Pci.Read ( 599 &RootBridge->Io, 600 EfiPciWidthUint16, 601 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr), 602 1, 603 &CapabilityEntry 604 ); 605 606 CapabilityID = (UINT8)CapabilityEntry; 607 608 // Is PCIe capability ? 609 if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) { 610 // Get PCIe Device Capabilities 611 RootBridge->Io.Pci.Read ( 612 &RootBridge->Io, 613 EfiPciWidthUint32, 614 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8), 615 1, 616 &DeviceCapability 617 ); 618 619 // Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0) 620 DeviceCapability &= ~ ((UINT32)(0x7 << 5 )); 621 // Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0) 622 DeviceCapability &= ~ ((UINT32)(0x7 << 12)); 623 // Enable all error reporting 624 DeviceCapability |= 0xF; 625 626 RootBridge->Io.Pci.Write ( 627 &RootBridge->Io, 628 EfiPciWidthUint32, 629 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8), 630 1, 631 &DeviceCapability 632 ); 633 634 return EFI_SUCCESS; 635 } 636 CapabilityPtr = (CapabilityEntry >> 8) & 0xFF; 637 } 638 } 639 } 640 641 return EFI_SUCCESS; 642 } 643