1 /*++ 2 3 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 PcatPciRootBridgeIo.c 14 15 Abstract: 16 17 EFI PC AT PCI Root Bridge Io Protocol 18 19 Revision History 20 21 --*/ 22 23 #include "PcatPciRootBridge.h" 24 25 // 26 // Protocol Member Function Prototypes 27 // 28 EFI_STATUS 29 EFIAPI 30 PcatRootBridgeIoPollMem ( 31 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 32 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 33 IN UINT64 Address, 34 IN UINT64 Mask, 35 IN UINT64 Value, 36 IN UINT64 Delay, 37 OUT UINT64 *Result 38 ); 39 40 EFI_STATUS 41 EFIAPI 42 PcatRootBridgeIoPollIo ( 43 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 44 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 45 IN UINT64 Address, 46 IN UINT64 Mask, 47 IN UINT64 Value, 48 IN UINT64 Delay, 49 OUT UINT64 *Result 50 ); 51 52 EFI_STATUS 53 EFIAPI 54 PcatRootBridgeIoMemRead ( 55 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 56 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 57 IN UINT64 Address, 58 IN UINTN Count, 59 IN OUT VOID *Buffer 60 ); 61 62 EFI_STATUS 63 EFIAPI 64 PcatRootBridgeIoMemWrite ( 65 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 66 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 67 IN UINT64 Address, 68 IN UINTN Count, 69 IN OUT VOID *Buffer 70 ); 71 72 EFI_STATUS 73 EFIAPI 74 PcatRootBridgeIoCopyMem ( 75 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 76 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 77 IN UINT64 DestAddress, 78 IN UINT64 SrcAddress, 79 IN UINTN Count 80 ); 81 82 EFI_STATUS 83 EFIAPI 84 PcatRootBridgeIoPciRead ( 85 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 86 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 87 IN UINT64 Address, 88 IN UINTN Count, 89 IN OUT VOID *Buffer 90 ); 91 92 EFI_STATUS 93 EFIAPI 94 PcatRootBridgeIoPciWrite ( 95 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 96 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 97 IN UINT64 Address, 98 IN UINTN Count, 99 IN OUT VOID *Buffer 100 ); 101 102 EFI_STATUS 103 EFIAPI 104 PcatRootBridgeIoMap ( 105 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 106 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, 107 IN VOID *HostAddress, 108 IN OUT UINTN *NumberOfBytes, 109 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 110 OUT VOID **Mapping 111 ); 112 113 EFI_STATUS 114 EFIAPI 115 PcatRootBridgeIoUnmap ( 116 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 117 IN VOID *Mapping 118 ); 119 120 EFI_STATUS 121 EFIAPI 122 PcatRootBridgeIoAllocateBuffer ( 123 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 124 IN EFI_ALLOCATE_TYPE Type, 125 IN EFI_MEMORY_TYPE MemoryType, 126 IN UINTN Pages, 127 OUT VOID **HostAddress, 128 IN UINT64 Attributes 129 ); 130 131 EFI_STATUS 132 EFIAPI 133 PcatRootBridgeIoFreeBuffer ( 134 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 135 IN UINTN Pages, 136 OUT VOID *HostAddress 137 ); 138 139 EFI_STATUS 140 EFIAPI 141 PcatRootBridgeIoFlush ( 142 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This 143 ); 144 145 EFI_STATUS 146 EFIAPI 147 PcatRootBridgeIoGetAttributes ( 148 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 149 OUT UINT64 *Supported, 150 OUT UINT64 *Attributes 151 ); 152 153 EFI_STATUS 154 EFIAPI 155 PcatRootBridgeIoSetAttributes ( 156 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 157 IN UINT64 Attributes, 158 IN OUT UINT64 *ResourceBase, 159 IN OUT UINT64 *ResourceLength 160 ); 161 162 EFI_STATUS 163 EFIAPI 164 PcatRootBridgeIoConfiguration ( 165 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 166 OUT VOID **Resources 167 ); 168 169 // 170 // Private Function Prototypes 171 // 172 EFI_STATUS 173 EFIAPI 174 PcatRootBridgeIoMemRW ( 175 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 176 IN UINTN Count, 177 IN BOOLEAN InStrideFlag, 178 IN PTR In, 179 IN BOOLEAN OutStrideFlag, 180 OUT PTR Out 181 ); 182 183 EFI_STATUS 184 PcatRootBridgeIoConstructor ( 185 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, 186 IN UINTN SegmentNumber 187 ) 188 /*++ 189 190 Routine Description: 191 192 Contruct the Pci Root Bridge Io protocol 193 194 Arguments: 195 196 Protocol - protocol to initialize 197 198 Returns: 199 200 None 201 202 --*/ 203 { 204 Protocol->ParentHandle = NULL; 205 206 Protocol->PollMem = PcatRootBridgeIoPollMem; 207 Protocol->PollIo = PcatRootBridgeIoPollIo; 208 209 Protocol->Mem.Read = PcatRootBridgeIoMemRead; 210 Protocol->Mem.Write = PcatRootBridgeIoMemWrite; 211 212 Protocol->Io.Read = PcatRootBridgeIoIoRead; 213 Protocol->Io.Write = PcatRootBridgeIoIoWrite; 214 215 Protocol->CopyMem = PcatRootBridgeIoCopyMem; 216 217 Protocol->Pci.Read = PcatRootBridgeIoPciRead; 218 Protocol->Pci.Write = PcatRootBridgeIoPciWrite; 219 220 Protocol->Map = PcatRootBridgeIoMap; 221 Protocol->Unmap = PcatRootBridgeIoUnmap; 222 223 Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer; 224 Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer; 225 226 Protocol->Flush = PcatRootBridgeIoFlush; 227 228 Protocol->GetAttributes = PcatRootBridgeIoGetAttributes; 229 Protocol->SetAttributes = PcatRootBridgeIoSetAttributes; 230 231 Protocol->Configuration = PcatRootBridgeIoConfiguration; 232 233 Protocol->SegmentNumber = (UINT32)SegmentNumber; 234 235 return EFI_SUCCESS; 236 } 237 238 EFI_STATUS 239 EFIAPI 240 PcatRootBridgeIoPollMem ( 241 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 242 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 243 IN UINT64 Address, 244 IN UINT64 Mask, 245 IN UINT64 Value, 246 IN UINT64 Delay, 247 OUT UINT64 *Result 248 ) 249 { 250 EFI_STATUS Status; 251 UINT64 NumberOfTicks; 252 UINT32 Remainder; 253 254 if (Result == NULL) { 255 return EFI_INVALID_PARAMETER; 256 } 257 258 259 if ((UINT32)Width > EfiPciWidthUint64) { 260 return EFI_INVALID_PARAMETER; 261 } 262 // 263 // No matter what, always do a single poll. 264 // 265 Status = This->Mem.Read (This, Width, Address, 1, Result); 266 if ( EFI_ERROR(Status) ) { 267 return Status; 268 } 269 if ( (*Result & Mask) == Value ) { 270 return EFI_SUCCESS; 271 } 272 273 if (Delay == 0) { 274 return EFI_SUCCESS; 275 } else { 276 277 NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder); 278 if ( Remainder !=0 ) { 279 NumberOfTicks += 1; 280 } 281 NumberOfTicks += 1; 282 283 while ( NumberOfTicks ) { 284 285 gBS->Stall (10); 286 287 Status = This->Mem.Read (This, Width, Address, 1, Result); 288 if ( EFI_ERROR(Status) ) { 289 return Status; 290 } 291 292 if ( (*Result & Mask) == Value ) { 293 return EFI_SUCCESS; 294 } 295 296 NumberOfTicks -= 1; 297 } 298 } 299 return EFI_TIMEOUT; 300 } 301 302 EFI_STATUS 303 EFIAPI 304 PcatRootBridgeIoPollIo ( 305 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 306 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 307 IN UINT64 Address, 308 IN UINT64 Mask, 309 IN UINT64 Value, 310 IN UINT64 Delay, 311 OUT UINT64 *Result 312 ) 313 { 314 EFI_STATUS Status; 315 UINT64 NumberOfTicks; 316 UINT32 Remainder; 317 318 if (Result == NULL) { 319 return EFI_INVALID_PARAMETER; 320 } 321 322 if ((UINT32)Width > EfiPciWidthUint64) { 323 return EFI_INVALID_PARAMETER; 324 } 325 // 326 // No matter what, always do a single poll. 327 // 328 Status = This->Io.Read (This, Width, Address, 1, Result); 329 if ( EFI_ERROR(Status) ) { 330 return Status; 331 } 332 if ( (*Result & Mask) == Value ) { 333 return EFI_SUCCESS; 334 } 335 336 if (Delay == 0) { 337 return EFI_SUCCESS; 338 } else { 339 340 NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder); 341 if ( Remainder !=0 ) { 342 NumberOfTicks += 1; 343 } 344 NumberOfTicks += 1; 345 346 while ( NumberOfTicks ) { 347 348 gBS->Stall(10); 349 350 Status = This->Io.Read (This, Width, Address, 1, Result); 351 if ( EFI_ERROR(Status) ) { 352 return Status; 353 } 354 355 if ( (*Result & Mask) == Value ) { 356 return EFI_SUCCESS; 357 } 358 359 NumberOfTicks -= 1; 360 } 361 } 362 return EFI_TIMEOUT; 363 } 364 365 BOOLEAN 366 PcatRootBridgeMemAddressValid ( 367 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData, 368 IN UINT64 Address 369 ) 370 { 371 if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) { 372 return TRUE; 373 } 374 if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) { 375 return TRUE; 376 } 377 378 return FALSE; 379 } 380 381 EFI_STATUS 382 EFIAPI 383 PcatRootBridgeIoMemRead ( 384 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 385 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 386 IN UINT64 Address, 387 IN UINTN Count, 388 IN OUT VOID *Buffer 389 ) 390 { 391 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 392 UINTN AlignMask; 393 PTR In; 394 PTR Out; 395 396 if ( Buffer == NULL ) { 397 return EFI_INVALID_PARAMETER; 398 } 399 400 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 401 402 if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) { 403 return EFI_INVALID_PARAMETER; 404 } 405 406 AlignMask = (1 << (Width & 0x03)) - 1; 407 if (Address & AlignMask) { 408 return EFI_INVALID_PARAMETER; 409 } 410 411 Address += PrivateData->PhysicalMemoryBase; 412 413 In.buf = Buffer; 414 Out.buf = (VOID *)(UINTN) Address; 415 if ((UINT32)Width <= EfiPciWidthUint64) { 416 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); 417 } 418 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { 419 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); 420 } 421 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { 422 return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); 423 } 424 425 return EFI_INVALID_PARAMETER; 426 } 427 428 EFI_STATUS 429 EFIAPI 430 PcatRootBridgeIoMemWrite ( 431 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 432 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 433 IN UINT64 Address, 434 IN UINTN Count, 435 IN OUT VOID *Buffer 436 ) 437 { 438 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 439 UINTN AlignMask; 440 PTR In; 441 PTR Out; 442 443 if ( Buffer == NULL ) { 444 return EFI_INVALID_PARAMETER; 445 } 446 447 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 448 449 if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) { 450 return EFI_INVALID_PARAMETER; 451 } 452 453 AlignMask = (1 << (Width & 0x03)) - 1; 454 if (Address & AlignMask) { 455 return EFI_INVALID_PARAMETER; 456 } 457 458 Address += PrivateData->PhysicalMemoryBase; 459 460 In.buf = (VOID *)(UINTN) Address; 461 Out.buf = Buffer; 462 if ((UINT32)Width <= EfiPciWidthUint64) { 463 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); 464 } 465 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { 466 return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); 467 } 468 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { 469 return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); 470 } 471 472 return EFI_INVALID_PARAMETER; 473 } 474 475 EFI_STATUS 476 EFIAPI 477 PcatRootBridgeIoCopyMem ( 478 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 479 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 480 IN UINT64 DestAddress, 481 IN UINT64 SrcAddress, 482 IN UINTN Count 483 ) 484 485 { 486 EFI_STATUS Status; 487 BOOLEAN Direction; 488 UINTN Stride; 489 UINTN Index; 490 UINT64 Result; 491 492 if ((UINT32)Width > EfiPciWidthUint64) { 493 return EFI_INVALID_PARAMETER; 494 } 495 496 if (DestAddress == SrcAddress) { 497 return EFI_SUCCESS; 498 } 499 500 Stride = (UINTN)1 << Width; 501 502 Direction = TRUE; 503 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) { 504 Direction = FALSE; 505 SrcAddress = SrcAddress + (Count-1) * Stride; 506 DestAddress = DestAddress + (Count-1) * Stride; 507 } 508 509 for (Index = 0;Index < Count;Index++) { 510 Status = PcatRootBridgeIoMemRead ( 511 This, 512 Width, 513 SrcAddress, 514 1, 515 &Result 516 ); 517 if (EFI_ERROR (Status)) { 518 return Status; 519 } 520 Status = PcatRootBridgeIoMemWrite ( 521 This, 522 Width, 523 DestAddress, 524 1, 525 &Result 526 ); 527 if (EFI_ERROR (Status)) { 528 return Status; 529 } 530 if (Direction) { 531 SrcAddress += Stride; 532 DestAddress += Stride; 533 } else { 534 SrcAddress -= Stride; 535 DestAddress -= Stride; 536 } 537 } 538 return EFI_SUCCESS; 539 } 540 541 EFI_STATUS 542 EFIAPI 543 PcatRootBridgeIoPciRead ( 544 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 545 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 546 IN UINT64 Address, 547 IN UINTN Count, 548 IN OUT VOID *Buffer 549 ) 550 { 551 if (Buffer == NULL) { 552 return EFI_INVALID_PARAMETER; 553 } 554 555 return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer); 556 } 557 558 EFI_STATUS 559 EFIAPI 560 PcatRootBridgeIoPciWrite ( 561 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 562 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 563 IN UINT64 Address, 564 IN UINTN Count, 565 IN OUT VOID *Buffer 566 ) 567 { 568 if (Buffer == NULL) { 569 return EFI_INVALID_PARAMETER; 570 } 571 572 return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer); 573 } 574 575 EFI_STATUS 576 EFIAPI 577 PcatRootBridgeIoMap ( 578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 579 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, 580 IN VOID *HostAddress, 581 IN OUT UINTN *NumberOfBytes, 582 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 583 OUT VOID **Mapping 584 ) 585 586 { 587 EFI_STATUS Status; 588 EFI_PHYSICAL_ADDRESS PhysicalAddress; 589 MAP_INFO *MapInfo; 590 MAP_INFO_INSTANCE *MapInstance; 591 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 592 593 if ( HostAddress == NULL || NumberOfBytes == NULL || 594 DeviceAddress == NULL || Mapping == NULL ) { 595 596 return EFI_INVALID_PARAMETER; 597 } 598 599 // 600 // Perform a fence operation to make sure all memory operations are flushed 601 // 602 MemoryFence(); 603 604 // 605 // Initialize the return values to their defaults 606 // 607 *Mapping = NULL; 608 609 // 610 // Make sure that Operation is valid 611 // 612 if ((UINT32)Operation >= EfiPciOperationMaximum) { 613 return EFI_INVALID_PARAMETER; 614 } 615 616 // 617 // Most PCAT like chipsets can not handle performing DMA above 4GB. 618 // If any part of the DMA transfer being mapped is above 4GB, then 619 // map the DMA transfer to a buffer below 4GB. 620 // 621 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; 622 if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) { 623 624 // 625 // Common Buffer operations can not be remapped. If the common buffer 626 // if above 4GB, then it is not possible to generate a mapping, so return 627 // an error. 628 // 629 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) { 630 return EFI_UNSUPPORTED; 631 } 632 633 // 634 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is 635 // called later. 636 // 637 Status = gBS->AllocatePool ( 638 EfiBootServicesData, 639 sizeof(MAP_INFO), 640 (VOID **)&MapInfo 641 ); 642 if (EFI_ERROR (Status)) { 643 *NumberOfBytes = 0; 644 return Status; 645 } 646 647 // 648 // Return a pointer to the MAP_INFO structure in Mapping 649 // 650 *Mapping = MapInfo; 651 652 // 653 // Initialize the MAP_INFO structure 654 // 655 MapInfo->Operation = Operation; 656 MapInfo->NumberOfBytes = *NumberOfBytes; 657 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes); 658 MapInfo->HostAddress = PhysicalAddress; 659 MapInfo->MappedHostAddress = 0x00000000ffffffff; 660 661 // 662 // Allocate a buffer below 4GB to map the transfer to. 663 // 664 Status = gBS->AllocatePages ( 665 AllocateMaxAddress, 666 EfiBootServicesData, 667 MapInfo->NumberOfPages, 668 &MapInfo->MappedHostAddress 669 ); 670 if (EFI_ERROR(Status)) { 671 gBS->FreePool (MapInfo); 672 *NumberOfBytes = 0; 673 return Status; 674 } 675 676 // 677 // If this is a read operation from the Bus Master's point of view, 678 // then copy the contents of the real buffer into the mapped buffer 679 // so the Bus Master can read the contents of the real buffer. 680 // 681 if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) { 682 CopyMem ( 683 (VOID *)(UINTN)MapInfo->MappedHostAddress, 684 (VOID *)(UINTN)MapInfo->HostAddress, 685 MapInfo->NumberOfBytes 686 ); 687 } 688 689 690 Status =gBS->AllocatePool ( 691 EfiBootServicesData, 692 sizeof(MAP_INFO_INSTANCE), 693 (VOID **)&MapInstance 694 ); 695 if (EFI_ERROR(Status)) { 696 gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages); 697 gBS->FreePool (MapInfo); 698 *NumberOfBytes = 0; 699 return Status; 700 } 701 702 MapInstance->Map=MapInfo; 703 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 704 InsertTailList(&PrivateData->MapInfo,&MapInstance->Link); 705 706 // 707 // The DeviceAddress is the address of the maped buffer below 4GB 708 // 709 *DeviceAddress = MapInfo->MappedHostAddress; 710 } else { 711 // 712 // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress 713 // 714 *DeviceAddress = PhysicalAddress; 715 } 716 717 // 718 // Perform a fence operation to make sure all memory operations are flushed 719 // 720 MemoryFence(); 721 722 return EFI_SUCCESS; 723 } 724 725 EFI_STATUS 726 EFIAPI 727 PcatRootBridgeIoUnmap ( 728 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 729 IN VOID *Mapping 730 ) 731 732 { 733 MAP_INFO *MapInfo; 734 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 735 LIST_ENTRY *Link; 736 737 // 738 // Perform a fence operation to make sure all memory operations are flushed 739 // 740 MemoryFence(); 741 742 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 743 // 744 // See if the Map() operation associated with this Unmap() required a mapping buffer. 745 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS. 746 // 747 if (Mapping != NULL) { 748 // 749 // Get the MAP_INFO structure from Mapping 750 // 751 MapInfo = (MAP_INFO *)Mapping; 752 753 for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) { 754 if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo) 755 break; 756 } 757 758 if (Link == &PrivateData->MapInfo) { 759 return EFI_INVALID_PARAMETER; 760 } 761 762 RemoveEntryList(Link); 763 ((MAP_INFO_INSTANCE*)Link)->Map = NULL; 764 gBS->FreePool((MAP_INFO_INSTANCE*)Link); 765 766 // 767 // If this is a write operation from the Bus Master's point of view, 768 // then copy the contents of the mapped buffer into the real buffer 769 // so the processor can read the contents of the real buffer. 770 // 771 if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) { 772 CopyMem ( 773 (VOID *)(UINTN)MapInfo->HostAddress, 774 (VOID *)(UINTN)MapInfo->MappedHostAddress, 775 MapInfo->NumberOfBytes 776 ); 777 } 778 779 // 780 // Free the mapped buffer and the MAP_INFO structure. 781 // 782 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages); 783 gBS->FreePool (Mapping); 784 } 785 786 // 787 // Perform a fence operation to make sure all memory operations are flushed 788 // 789 MemoryFence(); 790 791 return EFI_SUCCESS; 792 } 793 794 EFI_STATUS 795 EFIAPI 796 PcatRootBridgeIoAllocateBuffer ( 797 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 798 IN EFI_ALLOCATE_TYPE Type, 799 IN EFI_MEMORY_TYPE MemoryType, 800 IN UINTN Pages, 801 OUT VOID **HostAddress, 802 IN UINT64 Attributes 803 ) 804 { 805 EFI_STATUS Status; 806 EFI_PHYSICAL_ADDRESS PhysicalAddress; 807 808 // 809 // Validate Attributes 810 // 811 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { 812 return EFI_UNSUPPORTED; 813 } 814 815 // 816 // Check for invalid inputs 817 // 818 if (HostAddress == NULL) { 819 return EFI_INVALID_PARAMETER; 820 } 821 822 // 823 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData 824 // 825 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { 826 return EFI_INVALID_PARAMETER; 827 } 828 829 // 830 // Limit allocations to memory below 4GB 831 // 832 PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff); 833 834 Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress); 835 if (EFI_ERROR (Status)) { 836 return Status; 837 } 838 839 *HostAddress = (VOID *)(UINTN)PhysicalAddress; 840 841 return EFI_SUCCESS; 842 } 843 844 EFI_STATUS 845 EFIAPI 846 PcatRootBridgeIoFreeBuffer ( 847 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 848 IN UINTN Pages, 849 OUT VOID *HostAddress 850 ) 851 852 { 853 854 if( HostAddress == NULL ){ 855 return EFI_INVALID_PARAMETER; 856 } 857 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages); 858 } 859 860 EFI_STATUS 861 EFIAPI 862 PcatRootBridgeIoFlush ( 863 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This 864 ) 865 866 { 867 // 868 // Perform a fence operation to make sure all memory operations are flushed 869 // 870 MemoryFence(); 871 872 return EFI_SUCCESS; 873 } 874 875 EFI_STATUS 876 EFIAPI 877 PcatRootBridgeIoGetAttributes ( 878 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 879 OUT UINT64 *Supported, OPTIONAL 880 OUT UINT64 *Attributes 881 ) 882 883 { 884 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 885 886 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 887 888 if (Attributes == NULL && Supported == NULL) { 889 return EFI_INVALID_PARAMETER; 890 } 891 892 // 893 // Supported is an OPTIONAL parameter. See if it is NULL 894 // 895 if (Supported) { 896 // 897 // This is a generic driver for a PC-AT class system. It does not have any 898 // chipset specific knowlegde, so none of the attributes can be set or 899 // cleared. Any attempt to set attribute that are already set will succeed, 900 // and any attempt to set an attribute that is not supported will fail. 901 // 902 *Supported = PrivateData->Attributes; 903 } 904 905 // 906 // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized 907 // 908 909 if (Attributes) { 910 *Attributes = PrivateData->Attributes; 911 } 912 913 914 return EFI_SUCCESS; 915 } 916 917 EFI_STATUS 918 EFIAPI 919 PcatRootBridgeIoSetAttributes ( 920 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 921 IN UINT64 Attributes, 922 IN OUT UINT64 *ResourceBase, 923 IN OUT UINT64 *ResourceLength 924 ) 925 926 { 927 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 928 929 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 930 931 // 932 // This is a generic driver for a PC-AT class system. It does not have any 933 // chipset specific knowlegde, so none of the attributes can be set or 934 // cleared. Any attempt to set attribute that are already set will succeed, 935 // and any attempt to set an attribute that is not supported will fail. 936 // 937 if (Attributes & (~PrivateData->Attributes)) { 938 return EFI_UNSUPPORTED; 939 } 940 941 return EFI_SUCCESS; 942 } 943 944 EFI_STATUS 945 EFIAPI 946 PcatRootBridgeIoConfiguration ( 947 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, 948 OUT VOID **Resources 949 ) 950 951 { 952 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; 953 954 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); 955 956 *Resources = PrivateData->Configuration; 957 958 return EFI_SUCCESS; 959 } 960 961 // 962 // Internal function 963 // 964 965 EFI_STATUS 966 EFIAPI 967 PcatRootBridgeIoMemRW ( 968 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, 969 IN UINTN Count, 970 IN BOOLEAN InStrideFlag, 971 IN PTR In, 972 IN BOOLEAN OutStrideFlag, 973 OUT PTR Out 974 ) 975 /*++ 976 977 Routine Description: 978 979 Private service to provide the memory read/write 980 981 Arguments: 982 983 Width of the Memory Access 984 Count of the number of accesses to perform 985 986 Returns: 987 988 Status 989 990 EFI_SUCCESS - Successful transaction 991 EFI_INVALID_PARAMETER - Unsupported width and address combination 992 993 --*/ 994 { 995 UINTN Stride; 996 UINTN InStride; 997 UINTN OutStride; 998 999 1000 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); 1001 Stride = (UINTN)1 << Width; 1002 InStride = InStrideFlag ? Stride : 0; 1003 OutStride = OutStrideFlag ? Stride : 0; 1004 1005 // 1006 // Loop for each iteration and move the data 1007 // 1008 switch (Width) { 1009 case EfiPciWidthUint8: 1010 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { 1011 MemoryFence(); 1012 *In.ui8 = *Out.ui8; 1013 MemoryFence(); 1014 } 1015 break; 1016 case EfiPciWidthUint16: 1017 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { 1018 MemoryFence(); 1019 *In.ui16 = *Out.ui16; 1020 MemoryFence(); 1021 } 1022 break; 1023 case EfiPciWidthUint32: 1024 for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { 1025 MemoryFence(); 1026 *In.ui32 = *Out.ui32; 1027 MemoryFence(); 1028 } 1029 break; 1030 default: 1031 return EFI_INVALID_PARAMETER; 1032 } 1033 1034 return EFI_SUCCESS; 1035 } 1036 1037