1 /** @file 2 * Implementation of the PCI Root Bridge Protocol for 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 #include <Library/DevicePathLib.h> 19 #include <Library/DmaLib.h> 20 21 #define CPUIO_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->CpuIo) 22 #define METRONOME_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->Metronome) 23 24 /** 25 * PCI Root Bridge Instance Templates 26 */ 27 STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH gDevicePathTemplate = { 28 { 29 { ACPI_DEVICE_PATH, 30 ACPI_DP, 31 { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), 32 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) } 33 }, 34 EISA_PNP_ID (0x0A03), 35 0 36 }, 37 { 38 END_DEVICE_PATH_TYPE, 39 END_ENTIRE_DEVICE_PATH_SUBTYPE, 40 { END_DEVICE_PATH_LENGTH, 0 } 41 } 42 }; 43 44 STATIC CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL gIoTemplate = { 45 0, 46 PciRbPollMem, 47 PciRbPollIo, 48 { 49 PciRbMemRead, 50 PciRbMemWrite 51 }, 52 { 53 PciRbIoRead, 54 PciRbIoWrite 55 }, 56 { 57 PciRbPciRead, 58 PciRbPciWrite 59 }, 60 PciRbCopyMem, 61 PciRbMap, 62 PciRbUnMap, 63 PciRbAllocateBuffer, 64 PciRbFreeBuffer, 65 PciRbFlush, 66 PciRbGetAttributes, 67 PciRbSetAttributes, 68 PciRbConfiguration, 69 0 70 }; 71 72 typedef struct { 73 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[ResTypeMax+1]; 74 EFI_ACPI_END_TAG_DESCRIPTOR EndDesp; 75 } RESOURCE_CONFIGURATION; 76 77 78 RESOURCE_CONFIGURATION Configuration = { 79 {{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0}, 80 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0}, 81 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0}, 82 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0}, 83 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0}, 84 {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}}, 85 {ACPI_END_TAG_DESCRIPTOR, 0} 86 }; 87 88 89 EFI_STATUS 90 PciRbPollMem ( 91 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 92 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 93 IN UINT64 Address, 94 IN UINT64 Mask, 95 IN UINT64 Value, 96 IN UINT64 Delay, 97 OUT UINT64 *Result 98 ) 99 { 100 EFI_STATUS Status; 101 UINT64 NumberOfTicks; 102 UINT32 Remainder; 103 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 104 EFI_METRONOME_ARCH_PROTOCOL *Metronome; 105 106 PCI_TRACE ("PciRbPollMem()"); 107 108 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 109 Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance); 110 111 if (Result == NULL) { 112 return EFI_INVALID_PARAMETER; 113 } 114 115 if (Width > EfiPciWidthUint64) { 116 return EFI_INVALID_PARAMETER; 117 } 118 119 // No matter what, always do a single poll. 120 Status = This->Mem.Read (This, Width, Address, 1, Result); 121 if (EFI_ERROR (Status)) { 122 return Status; 123 } 124 if ((*Result & Mask) == Value) { 125 return EFI_SUCCESS; 126 } 127 128 if (Delay == 0) { 129 return EFI_SUCCESS; 130 } 131 132 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder); 133 if (Remainder != 0) { 134 NumberOfTicks += 1; 135 } 136 NumberOfTicks += 1; 137 138 while (NumberOfTicks) { 139 Metronome->WaitForTick (Metronome, 1); 140 141 Status = This->Mem.Read (This, Width, Address, 1, Result); 142 if (EFI_ERROR (Status)) { 143 return Status; 144 } 145 146 if ((*Result & Mask) == Value) { 147 return EFI_SUCCESS; 148 } 149 150 NumberOfTicks -= 1; 151 } 152 153 return EFI_TIMEOUT; 154 } 155 156 EFI_STATUS 157 PciRbPollIo ( 158 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 159 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 160 IN UINT64 Address, 161 IN UINT64 Mask, 162 IN UINT64 Value, 163 IN UINT64 Delay, 164 OUT UINT64 *Result 165 ) 166 { 167 EFI_STATUS Status; 168 UINT64 NumberOfTicks; 169 UINT32 Remainder; 170 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 171 EFI_METRONOME_ARCH_PROTOCOL *Metronome; 172 173 PCI_TRACE ("PciRbPollIo()"); 174 175 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 176 Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance); 177 178 if (Result == NULL) { 179 return EFI_INVALID_PARAMETER; 180 } 181 182 if (Width > EfiPciWidthUint64) { 183 return EFI_INVALID_PARAMETER; 184 } 185 186 // No matter what, always do a single poll. 187 Status = This->Io.Read (This, Width, Address, 1, Result); 188 if (EFI_ERROR (Status)) { 189 return Status; 190 } 191 if ((*Result & Mask) == Value) { 192 return EFI_SUCCESS; 193 } 194 195 if (Delay == 0) { 196 return EFI_SUCCESS; 197 } 198 199 NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder); 200 if (Remainder != 0) { 201 NumberOfTicks += 1; 202 } 203 NumberOfTicks += 1; 204 205 while (NumberOfTicks) { 206 Metronome->WaitForTick (Metronome, 1); 207 208 Status = This->Io.Read (This, Width, Address, 1, Result); 209 if (EFI_ERROR (Status)) { 210 return Status; 211 } 212 213 if ((*Result & Mask) == Value) { 214 return EFI_SUCCESS; 215 } 216 217 NumberOfTicks -= 1; 218 } 219 220 return EFI_TIMEOUT; 221 } 222 223 EFI_STATUS 224 PciRbMemRead ( 225 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 226 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 227 IN UINT64 Address, 228 IN UINTN Count, 229 IN OUT VOID *Buffer 230 ) 231 { 232 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 233 EFI_CPU_IO2_PROTOCOL *CpuIo; 234 235 PCI_TRACE ("PciRbMemRead()"); 236 237 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 238 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance); 239 240 if (Buffer == NULL) { 241 return EFI_INVALID_PARAMETER; 242 } 243 244 if (Width >= EfiPciWidthMaximum) { 245 return EFI_INVALID_PARAMETER; 246 } 247 248 if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) && 249 ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) { 250 return EFI_INVALID_PARAMETER; 251 } 252 253 return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer); 254 } 255 256 EFI_STATUS 257 PciRbMemWrite ( 258 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 259 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 260 IN UINT64 Address, 261 IN UINTN Count, 262 IN OUT VOID *Buffer 263 ) 264 { 265 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 266 EFI_CPU_IO2_PROTOCOL *CpuIo; 267 268 PCI_TRACE ("PciRbMemWrite()"); 269 270 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 271 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance); 272 273 if (Buffer == NULL) { 274 return EFI_INVALID_PARAMETER; 275 } 276 277 if (Width >= EfiPciWidthMaximum) { 278 return EFI_INVALID_PARAMETER; 279 } 280 281 if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) && 282 ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) { 283 return EFI_INVALID_PARAMETER; 284 } 285 286 return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer); 287 } 288 289 EFI_STATUS 290 PciRbIoRead ( 291 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 292 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 293 IN UINT64 Address, 294 IN UINTN Count, 295 IN OUT VOID *Buffer 296 ) 297 { 298 PCI_TRACE ("PciRbIoRead()"); 299 300 if (Buffer == NULL) { 301 return EFI_INVALID_PARAMETER; 302 } 303 304 if (Width >= EfiPciWidthMaximum) { 305 return EFI_INVALID_PARAMETER; 306 } 307 308 // IO currently unsupported 309 return EFI_INVALID_PARAMETER; 310 } 311 312 EFI_STATUS 313 PciRbIoWrite ( 314 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 315 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 316 IN UINT64 Address, 317 IN UINTN Count, 318 IN OUT VOID *Buffer 319 ) 320 { 321 PCI_TRACE ("PciRbIoWrite()"); 322 323 if (Buffer == NULL) { 324 return EFI_INVALID_PARAMETER; 325 } 326 327 if (Width >= EfiPciWidthMaximum) { 328 return EFI_INVALID_PARAMETER; 329 } 330 331 // IO currently unsupported 332 return EFI_INVALID_PARAMETER; 333 } 334 335 EFI_STATUS 336 PciRbPciRead ( 337 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 338 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 339 IN UINT64 EfiAddress, 340 IN UINTN Count, 341 IN OUT VOID *Buffer 342 ) 343 { 344 UINT32 Offset; 345 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 346 EFI_CPU_IO2_PROTOCOL *CpuIo; 347 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress; 348 UINT64 Address; 349 350 EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress; 351 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 352 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance); 353 354 if (Buffer == NULL) { 355 return EFI_INVALID_PARAMETER; 356 } 357 358 if (Width >= EfiPciWidthMaximum) { 359 return EFI_INVALID_PARAMETER; 360 } 361 362 if (EfiPciAddress->ExtendedRegister) { 363 Offset = EfiPciAddress->ExtendedRegister; 364 } else { 365 Offset = EfiPciAddress->Register; 366 } 367 368 // The UEFI PCI enumerator scans for devices at all possible addresses, 369 // and ignores some PCI rules - this results in some hardware being 370 // detected multiple times. We work around this by faking absent 371 // devices 372 if ((EfiPciAddress->Bus == 0) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) { 373 *((UINT32 *)Buffer) = 0xffffffff; 374 return EFI_SUCCESS; 375 } 376 if ((EfiPciAddress->Bus == 1) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) { 377 *((UINT32 *)Buffer) = 0xffffffff; 378 return EFI_SUCCESS; 379 } 380 381 // Work around incorrect class ID in the root bridge 382 if ((EfiPciAddress->Bus == 0) && (EfiPciAddress->Device == 0) && (EfiPciAddress->Function == 0) && (Offset == 8)) { 383 *((UINT32 *)Buffer) = 0x06040001; 384 return EFI_SUCCESS; 385 } 386 387 Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) | 388 (EfiPciAddress->Device << 15) | 389 (EfiPciAddress->Function << 12) | Offset); 390 391 if ((Address < PCI_ECAM_BASE) || (Address > PCI_ECAM_BASE + PCI_ECAM_SIZE)) { 392 return EFI_INVALID_PARAMETER; 393 } 394 395 return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer); 396 } 397 398 EFI_STATUS 399 PciRbPciWrite ( 400 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 401 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 402 IN UINT64 EfiAddress, 403 IN UINTN Count, 404 IN OUT VOID *Buffer 405 ) 406 { 407 UINT32 Offset; 408 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 409 EFI_CPU_IO2_PROTOCOL *CpuIo; 410 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress; 411 UINT64 Address; 412 413 EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress; 414 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 415 CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance); 416 417 if (Buffer == NULL) { 418 return EFI_INVALID_PARAMETER; 419 } 420 421 if (Width >= EfiPciWidthMaximum) { 422 return EFI_INVALID_PARAMETER; 423 } 424 425 if (EfiPciAddress->ExtendedRegister) 426 Offset = EfiPciAddress->ExtendedRegister; 427 else 428 Offset = EfiPciAddress->Register; 429 430 Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) | 431 (EfiPciAddress->Device << 15) | 432 (EfiPciAddress->Function << 12) | Offset); 433 434 if (Address < PCI_ECAM_BASE || Address > PCI_ECAM_BASE + PCI_ECAM_SIZE) { 435 return EFI_INVALID_PARAMETER; 436 } 437 438 return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer); 439 } 440 441 EFI_STATUS 442 PciRbCopyMem ( 443 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 444 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 445 IN UINT64 DestAddress, 446 IN UINT64 SrcAddress, 447 IN UINTN Count 448 ) 449 { 450 EFI_STATUS Status; 451 BOOLEAN Direction; 452 UINTN Stride; 453 UINTN Index; 454 UINT64 Result; 455 456 PCI_TRACE ("PciRbCopyMem()"); 457 458 if (Width > EfiPciWidthUint64) { 459 return EFI_INVALID_PARAMETER; 460 } 461 462 if (DestAddress == SrcAddress) { 463 return EFI_SUCCESS; 464 } 465 466 Stride = (UINTN)(1 << Width); 467 468 Direction = TRUE; 469 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) { 470 Direction = FALSE; 471 SrcAddress = SrcAddress + (Count-1) * Stride; 472 DestAddress = DestAddress + (Count-1) * Stride; 473 } 474 475 for (Index = 0; Index < Count; Index++) { 476 Status = PciRbMemRead ( 477 This, 478 Width, 479 SrcAddress, 480 1, 481 &Result 482 ); 483 if (EFI_ERROR (Status)) { 484 return Status; 485 } 486 Status = PciRbMemWrite ( 487 This, 488 Width, 489 DestAddress, 490 1, 491 &Result 492 ); 493 if (EFI_ERROR (Status)) { 494 return Status; 495 } 496 if (Direction) { 497 SrcAddress += Stride; 498 DestAddress += Stride; 499 } else { 500 SrcAddress -= Stride; 501 DestAddress -= Stride; 502 } 503 } 504 return EFI_SUCCESS; 505 } 506 507 EFI_STATUS 508 PciRbMap ( 509 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 510 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, 511 IN VOID *HostAddress, 512 IN OUT UINTN *NumberOfBytes, 513 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 514 OUT VOID **Mapping 515 ) 516 { 517 DMA_MAP_OPERATION DmaOperation; 518 519 PCI_TRACE ("PciRbMap()"); 520 521 if (Operation == EfiPciOperationBusMasterRead || 522 Operation == EfiPciOperationBusMasterRead64) { 523 DmaOperation = MapOperationBusMasterRead; 524 } else if (Operation == EfiPciOperationBusMasterWrite || 525 Operation == EfiPciOperationBusMasterWrite64) { 526 DmaOperation = MapOperationBusMasterWrite; 527 } else if (Operation == EfiPciOperationBusMasterCommonBuffer || 528 Operation == EfiPciOperationBusMasterCommonBuffer64) { 529 DmaOperation = MapOperationBusMasterCommonBuffer; 530 } else { 531 return EFI_INVALID_PARAMETER; 532 } 533 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping); 534 } 535 536 EFI_STATUS 537 PciRbUnMap ( 538 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 539 IN VOID *Mapping 540 ) 541 { 542 PCI_TRACE ("PciRbUnMap()"); 543 return DmaUnmap (Mapping); 544 } 545 546 EFI_STATUS 547 PciRbAllocateBuffer ( 548 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 549 IN EFI_ALLOCATE_TYPE Type, 550 IN EFI_MEMORY_TYPE MemoryType, 551 IN UINTN Pages, 552 IN OUT VOID **HostAddress, 553 IN UINT64 Attributes 554 ) 555 { 556 PCI_TRACE ("PciRbAllocateBuffer()"); 557 558 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { 559 return EFI_UNSUPPORTED; 560 } 561 562 return DmaAllocateBuffer (MemoryType, Pages, HostAddress); 563 } 564 565 EFI_STATUS 566 PciRbFreeBuffer ( 567 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 568 IN UINTN Pages, 569 IN VOID *HostAddress 570 ) 571 { 572 PCI_TRACE ("PciRbFreeBuffer()"); 573 return DmaFreeBuffer (Pages, HostAddress); 574 } 575 576 EFI_STATUS 577 PciRbFlush ( 578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This 579 ) 580 { 581 PCI_TRACE ("PciRbFlush()"); 582 583 //TODO: Not supported yet 584 585 return EFI_SUCCESS; 586 } 587 588 EFI_STATUS 589 PciRbSetAttributes ( 590 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 591 IN UINT64 Attributes, 592 IN OUT UINT64 *ResourceBase, 593 IN OUT UINT64 *ResourceLength 594 ) 595 { 596 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 597 598 PCI_TRACE ("PciRbSetAttributes()"); 599 600 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 601 602 if (Attributes) { 603 if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) { 604 return EFI_UNSUPPORTED; 605 } 606 } 607 608 //TODO: Cannot allowed to change attributes 609 if (Attributes & ~RootBridgeInstance->Attributes) { 610 return EFI_UNSUPPORTED; 611 } 612 613 return EFI_SUCCESS; 614 } 615 616 EFI_STATUS 617 PciRbGetAttributes ( 618 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 619 OUT UINT64 *Supported, 620 OUT UINT64 *Attributes 621 ) 622 { 623 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; 624 625 PCI_TRACE ("PciRbGetAttributes()"); 626 627 RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 628 629 if (Attributes == NULL && Supported == NULL) { 630 return EFI_INVALID_PARAMETER; 631 } 632 633 // Set the return value for Supported and Attributes 634 if (Supported) { 635 *Supported = RootBridgeInstance->Supports; 636 } 637 638 if (Attributes) { 639 *Attributes = RootBridgeInstance->Attributes; 640 } 641 642 return EFI_SUCCESS; 643 } 644 645 EFI_STATUS 646 PciRbConfiguration ( 647 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 648 OUT VOID **Resources 649 ) 650 { 651 PCI_ROOT_BRIDGE_INSTANCE *RootBridge; 652 UINTN Index; 653 654 PCI_TRACE ("PciRbConfiguration()"); 655 656 RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This); 657 658 for (Index = 0; Index < ResTypeMax; Index++) { 659 //if (ResAlloc[Index].Length != 0) => Resource allocated 660 if (RootBridge->ResAlloc[Index].Length != 0) { 661 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base; 662 Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1; 663 Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length; 664 } 665 } 666 667 // Set up Configuration for the bus 668 Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart; 669 Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength; 670 671 *Resources = &Configuration; 672 return EFI_SUCCESS; 673 } 674 675 EFI_STATUS 676 PciRbConstructor ( 677 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge, 678 IN UINT32 PciAcpiUid, 679 IN UINT64 MemAllocAttributes 680 ) 681 { 682 PCI_ROOT_BRIDGE_INSTANCE* RootBridge; 683 EFI_STATUS Status; 684 685 PCI_TRACE ("PciRbConstructor()"); 686 687 // Allocate Memory for the Instance from a Template 688 RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE)); 689 if (RootBridge == NULL) { 690 PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources"); 691 return EFI_OUT_OF_RESOURCES; 692 } 693 RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE; 694 CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH)); 695 CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL)); 696 697 // Set Parent Handle 698 RootBridge->Io.ParentHandle = HostBridge->Handle; 699 700 // Attach the Root Bridge to the PCI Host Bridge Instance 701 RootBridge->HostBridge = HostBridge; 702 703 // Set Device Path for this Root Bridge 704 RootBridge->DevicePath.Acpi.UID = PciAcpiUid; 705 706 RootBridge->BusStart = FixedPcdGet32 (PcdPciBusMin); 707 RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1; 708 709 // PCI Attributes 710 RootBridge->Supports = 0; 711 RootBridge->Attributes = 0; 712 713 // Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge 714 Status = gBS->InstallMultipleProtocolInterfaces ( 715 &RootBridge->Handle, 716 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath, 717 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io, 718 NULL 719 ); 720 ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE); 721 if (EFI_ERROR (Status)) { 722 PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces"); 723 FreePool (RootBridge); 724 return EFI_DEVICE_ERROR; 725 } 726 727 HostBridge->RootBridge = RootBridge; 728 return EFI_SUCCESS; 729 } 730 731 EFI_STATUS 732 PciRbDestructor ( 733 IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge 734 ) 735 { 736 EFI_STATUS Status; 737 738 Status = gBS->UninstallMultipleProtocolInterfaces ( 739 RootBridge->Handle, 740 &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath, 741 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io, 742 NULL 743 ); 744 745 FreePool (RootBridge); 746 747 return Status; 748 } 749