1 /** @file 2 The implementation for EFI_ISA_IO_PROTOCOL. 3 4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "InternalIsaIo.h" 16 17 // 18 // Module Variables 19 // 20 EFI_ISA_IO_PROTOCOL mIsaIoInterface = { 21 { 22 IsaIoMemRead, 23 IsaIoMemWrite 24 }, 25 { 26 IsaIoIoRead, 27 IsaIoIoWrite 28 }, 29 IsaIoCopyMem, 30 IsaIoMap, 31 IsaIoUnmap, 32 IsaIoAllocateBuffer, 33 IsaIoFreeBuffer, 34 IsaIoFlush, 35 NULL, 36 0, 37 NULL 38 }; 39 40 EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = { 41 { 42 0x00, 43 0x87, 44 0x01 45 }, 46 { 47 0x02, 48 0x83, 49 0x03 50 }, 51 { 52 0x04, 53 0x81, 54 0x05 55 }, 56 { 57 0x06, 58 0x82, 59 0x07 60 }, 61 { 62 0x00, 63 0x00, 64 0x00 65 }, // Channel 4 is invalid 66 { 67 0xC4, 68 0x8B, 69 0xC6 70 }, 71 { 72 0xC8, 73 0x89, 74 0xCA 75 }, 76 { 77 0xCC, 78 0x8A, 79 0xCE 80 }, 81 }; 82 83 /** 84 Initializes an ISA I/O Instance 85 86 @param[in] IsaIoDevice The iso device to be initialized. 87 @param[in] IsaDeviceResourceList The resource list. 88 89 **/ 90 VOID 91 InitializeIsaIoInstance ( 92 IN ISA_IO_DEVICE *IsaIoDevice, 93 IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList 94 ) 95 { 96 // 97 // Use the ISA IO Protocol structure template to initialize the ISA IO instance 98 // 99 CopyMem ( 100 &IsaIoDevice->IsaIo, 101 &mIsaIoInterface, 102 sizeof (EFI_ISA_IO_PROTOCOL) 103 ); 104 105 IsaIoDevice->IsaIo.ResourceList = IsaDeviceResourceList; 106 } 107 108 /** 109 Performs an ISA I/O Read Cycle 110 111 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 112 @param[in] Width Specifies the width of the I/O operation. 113 @param[in] Offset The offset in ISA I/O space to start the I/O operation. 114 @param[in] Count The number of I/O operations to perform. 115 @param[out] Buffer The destination buffer to store the results 116 117 @retval EFI_SUCCESS The data was read from the device sucessfully. 118 @retval EFI_UNSUPPORTED The Offset is not valid for this device. 119 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. 120 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 121 **/ 122 EFI_STATUS 123 EFIAPI 124 IsaIoIoRead ( 125 IN EFI_ISA_IO_PROTOCOL *This, 126 IN EFI_ISA_IO_PROTOCOL_WIDTH Width, 127 IN UINT32 Offset, 128 IN UINTN Count, 129 OUT VOID *Buffer 130 ) 131 { 132 EFI_STATUS Status; 133 ISA_IO_DEVICE *IsaIoDevice; 134 135 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 136 137 // 138 // Verify Isa IO Access 139 // 140 Status = IsaIoVerifyAccess ( 141 IsaIoDevice, 142 IsaAccessTypeIo, 143 Width, 144 Count, 145 Offset 146 ); 147 if (EFI_ERROR (Status)) { 148 return Status; 149 } 150 151 Status = IsaIoDevice->PciIo->Io.Read ( 152 IsaIoDevice->PciIo, 153 (EFI_PCI_IO_PROTOCOL_WIDTH) Width, 154 EFI_PCI_IO_PASS_THROUGH_BAR, 155 Offset, 156 Count, 157 Buffer 158 ); 159 160 if (EFI_ERROR (Status)) { 161 REPORT_STATUS_CODE ( 162 EFI_ERROR_CODE | EFI_ERROR_MINOR, 163 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 164 ); 165 } 166 167 return Status; 168 } 169 170 /** 171 Performs an ISA I/O Write Cycle 172 173 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 174 @param[in] Width Specifies the width of the I/O operation. 175 @param[in] Offset The offset in ISA I/O space to start the I/O operation. 176 @param[in] Count The number of I/O operations to perform. 177 @param[in] Buffer The source buffer to write data from 178 179 @retval EFI_SUCCESS The data was writen to the device sucessfully. 180 @retval EFI_UNSUPPORTED The Offset is not valid for this device. 181 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. 182 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 183 **/ 184 EFI_STATUS 185 EFIAPI 186 IsaIoIoWrite ( 187 IN EFI_ISA_IO_PROTOCOL *This, 188 IN EFI_ISA_IO_PROTOCOL_WIDTH Width, 189 IN UINT32 Offset, 190 IN UINTN Count, 191 IN VOID *Buffer 192 ) 193 { 194 EFI_STATUS Status; 195 ISA_IO_DEVICE *IsaIoDevice; 196 197 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 198 199 // 200 // Verify Isa IO Access 201 // 202 Status = IsaIoVerifyAccess ( 203 IsaIoDevice, 204 IsaAccessTypeIo, 205 Width, 206 Count, 207 Offset 208 ); 209 if (EFI_ERROR (Status)) { 210 return Status; 211 } 212 213 Status = IsaIoDevice->PciIo->Io.Write ( 214 IsaIoDevice->PciIo, 215 (EFI_PCI_IO_PROTOCOL_WIDTH) Width, 216 EFI_PCI_IO_PASS_THROUGH_BAR, 217 Offset, 218 Count, 219 Buffer 220 ); 221 222 if (EFI_ERROR (Status)) { 223 REPORT_STATUS_CODE ( 224 EFI_ERROR_CODE | EFI_ERROR_MINOR, 225 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 226 ); 227 } 228 229 return Status; 230 } 231 232 /** 233 Writes an 8-bit I/O Port 234 235 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 236 @param[in] Offset The offset in ISA IO space to start the IO operation. 237 @param[in] Value The data to write port. 238 239 @retval EFI_SUCCESS Success. 240 @retval EFI_INVALID_PARAMETER Parameter is invalid. 241 @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. 242 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 243 **/ 244 EFI_STATUS 245 WritePort ( 246 IN EFI_ISA_IO_PROTOCOL *This, 247 IN UINT32 Offset, 248 IN UINT8 Value 249 ) 250 { 251 EFI_STATUS Status; 252 ISA_IO_DEVICE *IsaIoDevice; 253 254 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 255 256 Status = IsaIoDevice->PciIo->Io.Write ( 257 IsaIoDevice->PciIo, 258 EfiPciIoWidthUint8, 259 EFI_PCI_IO_PASS_THROUGH_BAR, 260 Offset, 261 1, 262 &Value 263 ); 264 if (EFI_ERROR (Status)) { 265 REPORT_STATUS_CODE ( 266 EFI_ERROR_CODE | EFI_ERROR_MINOR, 267 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 268 ); 269 return Status; 270 } 271 272 gBS->Stall (50); 273 274 return EFI_SUCCESS; 275 } 276 277 /** 278 Writes I/O operation base address and count number to a 8 bit I/O Port. 279 280 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 281 @param[in] AddrOffset The address' offset. 282 @param[in] PageOffset The page's offest. 283 @param[in] CountOffset The count's offset. 284 @param[in] BaseAddress The base address. 285 @param[in] Count The number of I/O operations to perform. 286 287 @retval EFI_SUCCESS Success. 288 @retval EFI_INVALID_PARAMETER Parameter is invalid. 289 @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. 290 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 291 **/ 292 EFI_STATUS 293 WriteDmaPort ( 294 IN EFI_ISA_IO_PROTOCOL *This, 295 IN UINT32 AddrOffset, 296 IN UINT32 PageOffset, 297 IN UINT32 CountOffset, 298 IN UINT32 BaseAddress, 299 IN UINT16 Count 300 ) 301 { 302 EFI_STATUS Status; 303 304 Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); 305 if (EFI_ERROR (Status)) { 306 return Status; 307 } 308 309 Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); 310 if (EFI_ERROR (Status)) { 311 return Status; 312 } 313 314 Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); 315 if (EFI_ERROR (Status)) { 316 return Status; 317 } 318 319 Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); 320 if (EFI_ERROR (Status)) { 321 return Status; 322 } 323 324 Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); 325 return Status; 326 } 327 328 /** 329 Unmaps a memory region for DMA 330 331 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 332 @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). 333 334 @retval EFI_SUCCESS The range was unmapped. 335 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. 336 **/ 337 EFI_STATUS 338 EFIAPI 339 IsaIoUnmap ( 340 IN EFI_ISA_IO_PROTOCOL *This, 341 IN VOID *Mapping 342 ) 343 { 344 ISA_MAP_INFO *IsaMapInfo; 345 346 // 347 // Check if DMA is supported. 348 // 349 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { 350 return EFI_UNSUPPORTED; 351 } 352 353 // 354 // See if the Map() operation associated with this Unmap() required a mapping 355 // buffer.If a mapping buffer was not required, then this function simply 356 // returns EFI_SUCCESS. 357 // 358 if (Mapping != NULL) { 359 // 360 // Get the MAP_INFO structure from Mapping 361 // 362 IsaMapInfo = (ISA_MAP_INFO *) Mapping; 363 364 // 365 // If this is a write operation from the Agent's point of view, 366 // then copy the contents of the mapped buffer into the real buffer 367 // so the processor can read the contents of the real buffer. 368 // 369 if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { 370 CopyMem ( 371 (VOID *) (UINTN) IsaMapInfo->HostAddress, 372 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, 373 IsaMapInfo->NumberOfBytes 374 ); 375 } 376 // 377 // Free the mapped buffer and the MAP_INFO structure. 378 // 379 gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); 380 FreePool (IsaMapInfo); 381 } 382 383 return EFI_SUCCESS; 384 } 385 386 /** 387 Flushes any posted write data to the system memory. 388 389 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 390 391 @retval EFI_SUCCESS The buffers were flushed. 392 @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. 393 **/ 394 EFI_STATUS 395 EFIAPI 396 IsaIoFlush ( 397 IN EFI_ISA_IO_PROTOCOL *This 398 ) 399 { 400 EFI_STATUS Status; 401 ISA_IO_DEVICE *IsaIoDevice; 402 403 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 404 405 Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); 406 407 if (EFI_ERROR (Status)) { 408 REPORT_STATUS_CODE ( 409 EFI_ERROR_CODE | EFI_ERROR_MINOR, 410 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 411 ); 412 } 413 414 return Status; 415 } 416 417 /** 418 Verifies access to an ISA device 419 420 @param[in] IsaIoDevice The ISA device to be verified. 421 @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. 422 @param[in] Width The width of the memory operation. 423 @param[in] Count The number of memory operations to perform. 424 @param[in] Offset The offset in ISA memory space to start the memory operation. 425 426 @retval EFI_SUCCESS Verify success. 427 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. 428 @retval EFI_UNSUPPORTED The device ont support the access type. 429 **/ 430 EFI_STATUS 431 IsaIoVerifyAccess ( 432 IN ISA_IO_DEVICE *IsaIoDevice, 433 IN ISA_ACCESS_TYPE Type, 434 IN EFI_ISA_IO_PROTOCOL_WIDTH Width, 435 IN UINTN Count, 436 IN UINT32 Offset 437 ) 438 { 439 EFI_ISA_ACPI_RESOURCE *Item; 440 EFI_STATUS Status; 441 442 if ((UINT32)Width >= EfiIsaIoWidthMaximum || 443 Width == EfiIsaIoWidthReserved || 444 Width == EfiIsaIoWidthFifoReserved || 445 Width == EfiIsaIoWidthFillReserved 446 ) { 447 return EFI_INVALID_PARAMETER; 448 } 449 450 // 451 // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX 452 // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX 453 // 454 if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) { 455 Count = 1; 456 } 457 458 Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); 459 460 Status = EFI_UNSUPPORTED; 461 Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; 462 while (Item->Type != EfiIsaAcpiResourceEndOfList) { 463 if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || 464 (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) { 465 if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { 466 return EFI_SUCCESS; 467 } 468 469 if (Offset >= Item->StartRange && Offset <= Item->EndRange) { 470 Status = EFI_INVALID_PARAMETER; 471 } 472 } 473 474 Item++; 475 } 476 477 return Status; 478 } 479 480 /** 481 Performs an ISA Memory Read Cycle 482 483 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 484 @param[in] Width Specifies the width of the memory operation. 485 @param[in] Offset The offset in ISA memory space to start the memory operation. 486 @param[in] Count The number of memory operations to perform. 487 @param[out] Buffer The destination buffer to store the results 488 489 @retval EFI_SUCCESS The data was read from the device successfully. 490 @retval EFI_UNSUPPORTED The Offset is not valid for this device. 491 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. 492 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 493 **/ 494 EFI_STATUS 495 EFIAPI 496 IsaIoMemRead ( 497 IN EFI_ISA_IO_PROTOCOL *This, 498 IN EFI_ISA_IO_PROTOCOL_WIDTH Width, 499 IN UINT32 Offset, 500 IN UINTN Count, 501 OUT VOID *Buffer 502 ) 503 { 504 EFI_STATUS Status; 505 ISA_IO_DEVICE *IsaIoDevice; 506 507 // 508 // Check if ISA memory is supported. 509 // 510 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { 511 return EFI_UNSUPPORTED; 512 } 513 514 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 515 516 // 517 // Verify the Isa Io Access 518 // 519 Status = IsaIoVerifyAccess ( 520 IsaIoDevice, 521 IsaAccessTypeMem, 522 Width, 523 Count, 524 Offset 525 ); 526 if (EFI_ERROR (Status)) { 527 return Status; 528 } 529 530 Status = IsaIoDevice->PciIo->Mem.Read ( 531 IsaIoDevice->PciIo, 532 (EFI_PCI_IO_PROTOCOL_WIDTH) Width, 533 EFI_PCI_IO_PASS_THROUGH_BAR, 534 Offset, 535 Count, 536 Buffer 537 ); 538 539 if (EFI_ERROR (Status)) { 540 REPORT_STATUS_CODE ( 541 EFI_ERROR_CODE | EFI_ERROR_MINOR, 542 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 543 ); 544 } 545 546 return Status; 547 } 548 549 /** 550 Performs an ISA Memory Write Cycle 551 552 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 553 @param[in] Width Specifies the width of the memory operation. 554 @param[in] Offset The offset in ISA memory space to start the memory operation. 555 @param[in] Count The number of memory operations to perform. 556 @param[in] Buffer The source buffer to write data from 557 558 @retval EFI_SUCCESS The data was written to the device sucessfully. 559 @retval EFI_UNSUPPORTED The Offset is not valid for this device. 560 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. 561 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 562 **/ 563 EFI_STATUS 564 EFIAPI 565 IsaIoMemWrite ( 566 IN EFI_ISA_IO_PROTOCOL *This, 567 IN EFI_ISA_IO_PROTOCOL_WIDTH Width, 568 IN UINT32 Offset, 569 IN UINTN Count, 570 IN VOID *Buffer 571 ) 572 { 573 EFI_STATUS Status; 574 ISA_IO_DEVICE *IsaIoDevice; 575 576 // 577 // Check if ISA memory is supported. 578 // 579 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { 580 return EFI_UNSUPPORTED; 581 } 582 583 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 584 585 // 586 // Verify Isa IO Access 587 // 588 Status = IsaIoVerifyAccess ( 589 IsaIoDevice, 590 IsaAccessTypeMem, 591 Width, 592 Count, 593 Offset 594 ); 595 if (EFI_ERROR (Status)) { 596 return Status; 597 } 598 599 Status = IsaIoDevice->PciIo->Mem.Write ( 600 IsaIoDevice->PciIo, 601 (EFI_PCI_IO_PROTOCOL_WIDTH) Width, 602 EFI_PCI_IO_PASS_THROUGH_BAR, 603 Offset, 604 Count, 605 Buffer 606 ); 607 608 if (EFI_ERROR (Status)) { 609 REPORT_STATUS_CODE ( 610 EFI_ERROR_CODE | EFI_ERROR_MINOR, 611 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 612 ); 613 } 614 615 return Status; 616 } 617 618 /** 619 Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. 620 621 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 622 @param[in] Width Specifies the width of the memory copy operation. 623 @param[in] DestOffset The offset of the destination 624 @param[in] SrcOffset The offset of the source 625 @param[in] Count The number of memory copy operations to perform 626 627 @retval EFI_SUCCESS The data was copied sucessfully. 628 @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. 629 @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. 630 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 631 **/ 632 EFI_STATUS 633 EFIAPI 634 IsaIoCopyMem ( 635 IN EFI_ISA_IO_PROTOCOL *This, 636 IN EFI_ISA_IO_PROTOCOL_WIDTH Width, 637 IN UINT32 DestOffset, 638 IN UINT32 SrcOffset, 639 IN UINTN Count 640 ) 641 { 642 EFI_STATUS Status; 643 ISA_IO_DEVICE *IsaIoDevice; 644 645 // 646 // Check if ISA memory is supported. 647 // 648 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { 649 return EFI_UNSUPPORTED; 650 } 651 652 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); 653 654 // 655 // Verify Isa IO Access for destination and source 656 // 657 Status = IsaIoVerifyAccess ( 658 IsaIoDevice, 659 IsaAccessTypeMem, 660 Width, 661 Count, 662 DestOffset 663 ); 664 if (EFI_ERROR (Status)) { 665 return Status; 666 } 667 668 Status = IsaIoVerifyAccess ( 669 IsaIoDevice, 670 IsaAccessTypeMem, 671 Width, 672 Count, 673 SrcOffset 674 ); 675 if (EFI_ERROR (Status)) { 676 return Status; 677 } 678 679 Status = IsaIoDevice->PciIo->CopyMem ( 680 IsaIoDevice->PciIo, 681 (EFI_PCI_IO_PROTOCOL_WIDTH) Width, 682 EFI_PCI_IO_PASS_THROUGH_BAR, 683 DestOffset, 684 EFI_PCI_IO_PASS_THROUGH_BAR, 685 SrcOffset, 686 Count 687 ); 688 689 if (EFI_ERROR (Status)) { 690 REPORT_STATUS_CODE ( 691 EFI_ERROR_CODE | EFI_ERROR_MINOR, 692 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 693 ); 694 } 695 696 return Status; 697 } 698 699 /** 700 Maps a memory region for DMA, note this implementation 701 only supports slave read/write operation to save code size. 702 703 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. 704 @param Operation Indicates the type of DMA (slave or bus master), and if 705 the DMA operation is going to read or write to system memory. 706 @param ChannelNumber The slave channel number to use for this DMA operation. 707 If Operation and ChannelAttributes shows that this device 708 performs bus mastering DMA, then this field is ignored. 709 The legal range for this field is 0..7. 710 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation 711 @param HostAddress The system memory address to map to the device. 712 @param NumberOfBytes On input the number of bytes to map. On output the number 713 of bytes that were mapped. 714 @param DeviceAddress The resulting map address for the bus master device to use 715 to access the hosts HostAddress. 716 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). 717 718 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. 719 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. 720 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. 721 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. 722 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. 723 **/ 724 EFI_STATUS 725 IsaIoMapOnlySupportSlaveReadWrite ( 726 IN EFI_ISA_IO_PROTOCOL *This, 727 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, 728 IN UINT8 ChannelNumber OPTIONAL, 729 IN UINT32 ChannelAttributes, 730 IN VOID *HostAddress, 731 IN OUT UINTN *NumberOfBytes, 732 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 733 OUT VOID **Mapping 734 ) 735 { 736 EFI_STATUS Status; 737 EFI_PHYSICAL_ADDRESS PhysicalAddress; 738 ISA_MAP_INFO *IsaMapInfo; 739 UINT8 DmaMode; 740 UINTN MaxNumberOfBytes; 741 UINT32 BaseAddress; 742 UINT16 Count; 743 UINT8 DmaMask; 744 UINT8 DmaClear; 745 UINT8 DmaChannelMode; 746 747 if ((NULL == This) || 748 (NULL == HostAddress) || 749 (NULL == NumberOfBytes) || 750 (NULL == DeviceAddress) || 751 (NULL == Mapping) 752 ) { 753 return EFI_INVALID_PARAMETER; 754 } 755 756 // 757 // Initialize the return values to their defaults 758 // 759 *Mapping = NULL; 760 761 // 762 // Make sure the Operation parameter is valid. 763 // Light IsaIo only supports two operations. 764 // 765 if (!(Operation == EfiIsaIoOperationSlaveRead || 766 Operation == EfiIsaIoOperationSlaveWrite)) { 767 return EFI_INVALID_PARAMETER; 768 } 769 770 if (ChannelNumber >= 4) { 771 // 772 // The Light IsaIo doesn't support channelNumber larger than 4. 773 // 774 return EFI_INVALID_PARAMETER; 775 } 776 777 // 778 // Map the HostAddress to a DeviceAddress. 779 // 780 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; 781 if ((PhysicalAddress + *NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { 782 // 783 // Common Buffer operations can not be remapped. If the common buffer 784 // is above 16MB, then it is not possible to generate a mapping, so return 785 // an error. 786 // 787 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { 788 return EFI_UNSUPPORTED; 789 } 790 // 791 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() 792 // is called later. 793 // 794 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); 795 if (IsaMapInfo == NULL) { 796 *NumberOfBytes = 0; 797 return EFI_OUT_OF_RESOURCES; 798 } 799 // 800 // Return a pointer to the MAP_INFO structure in Mapping 801 // 802 *Mapping = IsaMapInfo; 803 804 // 805 // Initialize the MAP_INFO structure 806 // 807 IsaMapInfo->Operation = Operation; 808 IsaMapInfo->NumberOfBytes = *NumberOfBytes; 809 IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); 810 IsaMapInfo->HostAddress = PhysicalAddress; 811 IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; 812 813 // 814 // Allocate a buffer below 16MB to map the transfer to. 815 // 816 Status = gBS->AllocatePages ( 817 AllocateMaxAddress, 818 EfiBootServicesData, 819 IsaMapInfo->NumberOfPages, 820 &IsaMapInfo->MappedHostAddress 821 ); 822 if (EFI_ERROR (Status)) { 823 FreePool (IsaMapInfo); 824 *NumberOfBytes = 0; 825 *Mapping = NULL; 826 return Status; 827 } 828 // 829 // If this is a read operation from the DMA agents's point of view, 830 // then copy the contents of the real buffer into the mapped buffer 831 // so the DMA agent can read the contents of the real buffer. 832 // 833 if (Operation == EfiIsaIoOperationSlaveRead) { 834 CopyMem ( 835 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, 836 (VOID *) (UINTN) IsaMapInfo->HostAddress, 837 IsaMapInfo->NumberOfBytes 838 ); 839 } 840 // 841 // The DeviceAddress is the address of the maped buffer below 16 MB 842 // 843 *DeviceAddress = IsaMapInfo->MappedHostAddress; 844 } else { 845 // 846 // The transfer is below 16 MB, so the DeviceAddress is simply the 847 // HostAddress 848 // 849 *DeviceAddress = PhysicalAddress; 850 } 851 852 // 853 // Figure out what to program into the DMA Channel Mode Register 854 // 855 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); 856 if (Operation == EfiIsaIoOperationSlaveRead) { 857 DmaMode |= V_8237_DMA_CHMODE_MEM2IO; 858 } else { 859 DmaMode |= V_8237_DMA_CHMODE_IO2MEM; 860 } 861 // 862 // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo 863 // 864 DmaMode |= V_8237_DMA_CHMODE_SINGLE; 865 866 // 867 // A Slave DMA transfer can not cross a 64K boundary. 868 // Compute *NumberOfBytes based on this restriction. 869 // 870 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); 871 if (*NumberOfBytes > MaxNumberOfBytes) { 872 *NumberOfBytes = MaxNumberOfBytes; 873 } 874 // 875 // Compute the values to program into the BaseAddress and Count registers 876 // of the Slave DMA controller 877 // 878 BaseAddress = (UINT32) (*DeviceAddress); 879 Count = (UINT16) (*NumberOfBytes - 1); 880 // 881 // Program the DMA Write Single Mask Register for ChannelNumber 882 // Clear the DMA Byte Pointer Register 883 // 884 DmaMask = R_8237_DMA_WRSMSK_CH0_3; 885 DmaClear = R_8237_DMA_CBPR_CH0_3; 886 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; 887 888 Status = WritePort ( 889 This, 890 DmaMask, 891 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) 892 ); 893 if (EFI_ERROR (Status)) { 894 return Status; 895 } 896 897 Status = WritePort ( 898 This, 899 DmaClear, 900 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) 901 ); 902 if (EFI_ERROR (Status)) { 903 return Status; 904 } 905 906 Status = WritePort (This, DmaChannelMode, DmaMode); 907 if (EFI_ERROR (Status)) { 908 return Status; 909 } 910 911 Status = WriteDmaPort ( 912 This, 913 mDmaRegisters[ChannelNumber].Address, 914 mDmaRegisters[ChannelNumber].Page, 915 mDmaRegisters[ChannelNumber].Count, 916 BaseAddress, 917 Count 918 ); 919 if (EFI_ERROR (Status)) { 920 return Status; 921 } 922 923 Status = WritePort ( 924 This, 925 DmaMask, 926 (UINT8) (ChannelNumber & 0x03) 927 ); 928 if (EFI_ERROR (Status)) { 929 return Status; 930 } 931 932 return EFI_SUCCESS; 933 } 934 935 /** 936 Maps a memory region for DMA. This implementation implement the 937 the full mapping support. 938 939 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. 940 @param Operation Indicates the type of DMA (slave or bus master), and if 941 the DMA operation is going to read or write to system memory. 942 @param ChannelNumber The slave channel number to use for this DMA operation. 943 If Operation and ChannelAttributes shows that this device 944 performs bus mastering DMA, then this field is ignored. 945 The legal range for this field is 0..7. 946 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation 947 @param HostAddress The system memory address to map to the device. 948 @param NumberOfBytes On input the number of bytes to map. On output the number 949 of bytes that were mapped. 950 @param DeviceAddress The resulting map address for the bus master device to use 951 to access the hosts HostAddress. 952 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). 953 954 @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. 955 @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. 956 @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. 957 @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address. 958 @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. 959 **/ 960 EFI_STATUS 961 IsaIoMapFullSupport ( 962 IN EFI_ISA_IO_PROTOCOL *This, 963 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, 964 IN UINT8 ChannelNumber OPTIONAL, 965 IN UINT32 ChannelAttributes, 966 IN VOID *HostAddress, 967 IN OUT UINTN *NumberOfBytes, 968 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 969 OUT VOID **Mapping 970 ) 971 { 972 EFI_STATUS Status; 973 BOOLEAN Master; 974 BOOLEAN Read; 975 EFI_PHYSICAL_ADDRESS PhysicalAddress; 976 ISA_MAP_INFO *IsaMapInfo; 977 UINT8 DmaMode; 978 UINTN MaxNumberOfBytes; 979 UINT32 BaseAddress; 980 UINT16 Count; 981 UINT8 DmaMask; 982 UINT8 DmaClear; 983 UINT8 DmaChannelMode; 984 985 if ((NULL == This) || 986 (NULL == HostAddress) || 987 (NULL == NumberOfBytes) || 988 (NULL == DeviceAddress) || 989 (NULL == Mapping) 990 ) { 991 return EFI_INVALID_PARAMETER; 992 } 993 994 // 995 // Initialize the return values to their defaults 996 // 997 *Mapping = NULL; 998 999 // 1000 // Make sure the Operation parameter is valid 1001 // 1002 if ((UINT32)Operation >= EfiIsaIoOperationMaximum) { 1003 return EFI_INVALID_PARAMETER; 1004 } 1005 1006 if (ChannelNumber >= 8) { 1007 return EFI_INVALID_PARAMETER; 1008 } 1009 1010 // 1011 // See if this is a Slave DMA Operation 1012 // 1013 Master = TRUE; 1014 Read = FALSE; 1015 if (Operation == EfiIsaIoOperationSlaveRead) { 1016 Operation = EfiIsaIoOperationBusMasterRead; 1017 Master = FALSE; 1018 Read = TRUE; 1019 } 1020 1021 if (Operation == EfiIsaIoOperationSlaveWrite) { 1022 Operation = EfiIsaIoOperationBusMasterWrite; 1023 Master = FALSE; 1024 Read = FALSE; 1025 } 1026 1027 if (!Master) { 1028 // 1029 // Make sure that ChannelNumber is a valid channel number 1030 // Channel 4 is used to cascade, so it is illegal. 1031 // 1032 if (ChannelNumber == 4 || ChannelNumber > 7) { 1033 return EFI_INVALID_PARAMETER; 1034 } 1035 // 1036 // This implementation only support COMPATIBLE DMA Transfers 1037 // 1038 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) { 1039 return EFI_INVALID_PARAMETER; 1040 } 1041 1042 if ((ChannelAttributes & 1043 (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | 1044 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | 1045 EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) { 1046 return EFI_INVALID_PARAMETER; 1047 } 1048 1049 if (ChannelNumber < 4) { 1050 // 1051 // If this is Channel 0..3, then the width must be 8 bit 1052 // 1053 if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) || 1054 ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0) 1055 ) { 1056 return EFI_INVALID_PARAMETER; 1057 } 1058 } else { 1059 // 1060 // If this is Channel 4..7, then the width must be 16 bit 1061 // 1062 if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) || 1063 ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) { 1064 return EFI_INVALID_PARAMETER; 1065 } 1066 } 1067 // 1068 // Either Demand Mode or Single Mode must be selected, but not both 1069 // 1070 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { 1071 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { 1072 return EFI_INVALID_PARAMETER; 1073 } 1074 } else { 1075 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) { 1076 return EFI_INVALID_PARAMETER; 1077 } 1078 } 1079 } 1080 // 1081 // Map the HostAddress to a DeviceAddress. 1082 // 1083 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; 1084 if ((PhysicalAddress +*NumberOfBytes) > ISA_MAX_MEMORY_ADDRESS) { 1085 // 1086 // Common Buffer operations can not be remapped. If the common buffer 1087 // is above 16MB, then it is not possible to generate a mapping, so return 1088 // an error. 1089 // 1090 if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { 1091 return EFI_UNSUPPORTED; 1092 } 1093 // 1094 // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() 1095 // is called later. 1096 // 1097 IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); 1098 if (IsaMapInfo == NULL) { 1099 *NumberOfBytes = 0; 1100 return EFI_OUT_OF_RESOURCES; 1101 } 1102 // 1103 // Return a pointer to the MAP_INFO structure in Mapping 1104 // 1105 *Mapping = IsaMapInfo; 1106 1107 // 1108 // Initialize the MAP_INFO structure 1109 // 1110 IsaMapInfo->Operation = Operation; 1111 IsaMapInfo->NumberOfBytes = *NumberOfBytes; 1112 IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); 1113 IsaMapInfo->HostAddress = PhysicalAddress; 1114 IsaMapInfo->MappedHostAddress = ISA_MAX_MEMORY_ADDRESS - 1; 1115 1116 // 1117 // Allocate a buffer below 16MB to map the transfer to. 1118 // 1119 Status = gBS->AllocatePages ( 1120 AllocateMaxAddress, 1121 EfiBootServicesData, 1122 IsaMapInfo->NumberOfPages, 1123 &IsaMapInfo->MappedHostAddress 1124 ); 1125 if (EFI_ERROR (Status)) { 1126 FreePool (IsaMapInfo); 1127 *NumberOfBytes = 0; 1128 *Mapping = NULL; 1129 return Status; 1130 } 1131 // 1132 // If this is a read operation from the DMA agents's point of view, 1133 // then copy the contents of the real buffer into the mapped buffer 1134 // so the DMA agent can read the contents of the real buffer. 1135 // 1136 if (Operation == EfiIsaIoOperationBusMasterRead) { 1137 CopyMem ( 1138 (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, 1139 (VOID *) (UINTN) IsaMapInfo->HostAddress, 1140 IsaMapInfo->NumberOfBytes 1141 ); 1142 } 1143 // 1144 // The DeviceAddress is the address of the maped buffer below 16 MB 1145 // 1146 *DeviceAddress = IsaMapInfo->MappedHostAddress; 1147 } else { 1148 // 1149 // The transfer is below 16 MB, so the DeviceAddress is simply the 1150 // HostAddress 1151 // 1152 *DeviceAddress = PhysicalAddress; 1153 } 1154 // 1155 // If this is a Bus Master operation then return 1156 // 1157 if (Master) { 1158 return EFI_SUCCESS; 1159 } 1160 // 1161 // Figure out what to program into the DMA Channel Mode Register 1162 // 1163 DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); 1164 if (Read) { 1165 DmaMode |= V_8237_DMA_CHMODE_MEM2IO; 1166 } else { 1167 DmaMode |= V_8237_DMA_CHMODE_IO2MEM; 1168 } 1169 1170 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) { 1171 DmaMode |= B_8237_DMA_CHMODE_AE; 1172 } 1173 1174 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { 1175 DmaMode |= V_8237_DMA_CHMODE_DEMAND; 1176 } 1177 1178 if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { 1179 DmaMode |= V_8237_DMA_CHMODE_SINGLE; 1180 } 1181 // 1182 // A Slave DMA transfer can not cross a 64K boundary. 1183 // Compute *NumberOfBytes based on this restriction. 1184 // 1185 MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); 1186 if (*NumberOfBytes > MaxNumberOfBytes) { 1187 *NumberOfBytes = MaxNumberOfBytes; 1188 } 1189 // 1190 // Compute the values to program into the BaseAddress and Count registers 1191 // of the Slave DMA controller 1192 // 1193 if (ChannelNumber < 4) { 1194 BaseAddress = (UINT32) (*DeviceAddress); 1195 Count = (UINT16) (*NumberOfBytes - 1); 1196 } else { 1197 BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); 1198 Count = (UINT16) ((*NumberOfBytes - 1) >> 1); 1199 } 1200 // 1201 // Program the DMA Write Single Mask Register for ChannelNumber 1202 // Clear the DMA Byte Pointer Register 1203 // 1204 if (ChannelNumber < 4) { 1205 DmaMask = R_8237_DMA_WRSMSK_CH0_3; 1206 DmaClear = R_8237_DMA_CBPR_CH0_3; 1207 DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; 1208 } else { 1209 DmaMask = R_8237_DMA_WRSMSK_CH4_7; 1210 DmaClear = R_8237_DMA_CBPR_CH4_7; 1211 DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; 1212 } 1213 1214 Status = WritePort ( 1215 This, 1216 DmaMask, 1217 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) 1218 ); 1219 if (EFI_ERROR (Status)) { 1220 return Status; 1221 } 1222 1223 Status = WritePort ( 1224 This, 1225 DmaClear, 1226 (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) 1227 ); 1228 if (EFI_ERROR (Status)) { 1229 return Status; 1230 } 1231 1232 Status = WritePort (This, DmaChannelMode, DmaMode); 1233 if (EFI_ERROR (Status)) { 1234 return Status; 1235 } 1236 1237 Status = WriteDmaPort ( 1238 This, 1239 mDmaRegisters[ChannelNumber].Address, 1240 mDmaRegisters[ChannelNumber].Page, 1241 mDmaRegisters[ChannelNumber].Count, 1242 BaseAddress, 1243 Count 1244 ); 1245 if (EFI_ERROR (Status)) { 1246 return Status; 1247 } 1248 1249 Status = WritePort ( 1250 This, 1251 DmaMask, 1252 (UINT8) (ChannelNumber & 0x03) 1253 ); 1254 if (EFI_ERROR (Status)) { 1255 return Status; 1256 } 1257 1258 return EFI_SUCCESS; 1259 } 1260 1261 /** 1262 Maps a memory region for DMA 1263 1264 @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. 1265 @param Operation Indicates the type of DMA (slave or bus master), and if 1266 the DMA operation is going to read or write to system memory. 1267 @param ChannelNumber The slave channel number to use for this DMA operation. 1268 If Operation and ChannelAttributes shows that this device 1269 performs bus mastering DMA, then this field is ignored. 1270 The legal range for this field is 0..7. 1271 @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation 1272 @param HostAddress The system memory address to map to the device. 1273 @param NumberOfBytes On input the number of bytes to map. On output the number 1274 of bytes that were mapped. 1275 @param DeviceAddress The resulting map address for the bus master device to use 1276 to access the hosts HostAddress. 1277 @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). 1278 1279 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. 1280 @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. 1281 @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. 1282 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. 1283 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. 1284 **/ 1285 EFI_STATUS 1286 EFIAPI 1287 IsaIoMap ( 1288 IN EFI_ISA_IO_PROTOCOL *This, 1289 IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, 1290 IN UINT8 ChannelNumber OPTIONAL, 1291 IN UINT32 ChannelAttributes, 1292 IN VOID *HostAddress, 1293 IN OUT UINTN *NumberOfBytes, 1294 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, 1295 OUT VOID **Mapping 1296 ) 1297 { 1298 // 1299 // Check if DMA is supported. 1300 // 1301 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { 1302 return EFI_UNSUPPORTED; 1303 } 1304 // 1305 // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for 1306 // ISA Bus Master. 1307 // 1308 // So we just return EFI_UNSUPPORTED for these functions. 1309 // 1310 if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) { 1311 return IsaIoMapOnlySupportSlaveReadWrite ( 1312 This, 1313 Operation, 1314 ChannelNumber, 1315 ChannelAttributes, 1316 HostAddress, 1317 NumberOfBytes, 1318 DeviceAddress, 1319 Mapping 1320 ); 1321 1322 } else { 1323 return IsaIoMapFullSupport ( 1324 This, 1325 Operation, 1326 ChannelNumber, 1327 ChannelAttributes, 1328 HostAddress, 1329 NumberOfBytes, 1330 DeviceAddress, 1331 Mapping 1332 ); 1333 } 1334 } 1335 1336 /** 1337 Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. 1338 1339 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 1340 @param[in] Type The type allocation to perform. 1341 @param[in] MemoryType The type of memory to allocate. 1342 @param[in] Pages The number of pages to allocate. 1343 @param[out] HostAddress A pointer to store the base address of the allocated range. 1344 @param[in] Attributes The requested bit mask of attributes for the allocated range. 1345 1346 @retval EFI_SUCCESS The requested memory pages were allocated. 1347 @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL 1348 @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified 1349 by HostAddress, Pages, and Type is not available for common buffer use. 1350 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. 1351 **/ 1352 EFI_STATUS 1353 EFIAPI 1354 IsaIoAllocateBuffer ( 1355 IN EFI_ISA_IO_PROTOCOL *This, 1356 IN EFI_ALLOCATE_TYPE Type, 1357 IN EFI_MEMORY_TYPE MemoryType, 1358 IN UINTN Pages, 1359 OUT VOID **HostAddress, 1360 IN UINT64 Attributes 1361 ) 1362 { 1363 EFI_STATUS Status; 1364 EFI_PHYSICAL_ADDRESS PhysicalAddress; 1365 1366 // 1367 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for 1368 // ISA Bus Master. 1369 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. 1370 // 1371 if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || 1372 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { 1373 return EFI_UNSUPPORTED; 1374 } 1375 1376 if (HostAddress == NULL) { 1377 return EFI_INVALID_PARAMETER; 1378 } 1379 1380 if ((UINT32)Type >= MaxAllocateType) { 1381 return EFI_INVALID_PARAMETER; 1382 } 1383 // 1384 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData 1385 // 1386 if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { 1387 return EFI_INVALID_PARAMETER; 1388 } 1389 1390 if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) { 1391 return EFI_UNSUPPORTED; 1392 } 1393 1394 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (ISA_MAX_MEMORY_ADDRESS - 1); 1395 if (Type == AllocateAddress) { 1396 if ((UINTN) (*HostAddress) >= ISA_MAX_MEMORY_ADDRESS) { 1397 return EFI_UNSUPPORTED; 1398 } else { 1399 PhysicalAddress = (UINTN) (*HostAddress); 1400 } 1401 } 1402 1403 if (Type == AllocateAnyPages) { 1404 Type = AllocateMaxAddress; 1405 } 1406 1407 Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); 1408 if (EFI_ERROR (Status)) { 1409 REPORT_STATUS_CODE ( 1410 EFI_ERROR_CODE | EFI_ERROR_MINOR, 1411 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 1412 ); 1413 return Status; 1414 } 1415 1416 *HostAddress = (VOID *) (UINTN) PhysicalAddress; 1417 return Status; 1418 } 1419 1420 /** 1421 Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). 1422 1423 @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. 1424 @param[in] Pages The number of pages to free. 1425 @param[in] HostAddress The base address of the allocated range. 1426 1427 @retval EFI_SUCCESS The requested memory pages were freed. 1428 @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). 1429 **/ 1430 EFI_STATUS 1431 EFIAPI 1432 IsaIoFreeBuffer ( 1433 IN EFI_ISA_IO_PROTOCOL *This, 1434 IN UINTN Pages, 1435 IN VOID *HostAddress 1436 ) 1437 { 1438 EFI_STATUS Status; 1439 1440 // 1441 // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for 1442 // ISA Bus Master. 1443 // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. 1444 // 1445 if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || 1446 ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { 1447 return EFI_UNSUPPORTED; 1448 } 1449 1450 Status = gBS->FreePages ( 1451 (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, 1452 Pages 1453 ); 1454 if (EFI_ERROR (Status)) { 1455 REPORT_STATUS_CODE ( 1456 EFI_ERROR_CODE | EFI_ERROR_MINOR, 1457 EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR 1458 ); 1459 } 1460 1461 return Status; 1462 } 1463 1464