1 /** @file 2 This driver is used for Opal Password Feature support at IDE mode. 3 4 Copyright (c) 2016, 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 "OpalPasswordSmm.h" 16 17 /** 18 Write multiple words of Data to the IDE Data port. 19 Call the IO abstraction once to do the complete read, 20 not one word at a time 21 22 @param Port IO port to read 23 @param Count No. of UINT16's to read 24 @param Buffer Pointer to the Data Buffer for read 25 26 **/ 27 VOID 28 EFIAPI 29 IdeWritePortWMultiple ( 30 IN UINT16 Port, 31 IN UINTN Count, 32 IN UINT16 *Buffer 33 ) 34 { 35 UINTN Index; 36 37 for (Index = 0; Index < Count; Index++) { 38 IoWrite16 (Port, Buffer[Index]); 39 } 40 } 41 42 /** 43 Reads multiple words of Data from the IDE Data port. 44 Call the IO abstraction once to do the complete read, 45 not one word at a time 46 47 @param Port IO port to read 48 @param Count Number of UINT16's to read 49 @param Buffer Pointer to the Data Buffer for read 50 51 **/ 52 VOID 53 EFIAPI 54 IdeReadPortWMultiple ( 55 IN UINT16 Port, 56 IN UINTN Count, 57 IN UINT16 *Buffer 58 ) 59 { 60 UINTN Index; 61 62 for (Index = 0; Index < Count; Index++) { 63 Buffer[Count] = IoRead16 (Port); 64 } 65 } 66 67 /** 68 This function is used to analyze the Status Register and print out 69 some debug information and if there is ERR bit set in the Status 70 Register, the Error Register's Value is also be parsed and print out. 71 72 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 73 74 **/ 75 VOID 76 EFIAPI 77 DumpAllIdeRegisters ( 78 IN EFI_IDE_REGISTERS *IdeRegisters 79 ) 80 { 81 ASSERT (IdeRegisters != NULL); 82 83 DEBUG_CODE_BEGIN (); 84 if ((IoRead8 (IdeRegisters->CmdOrStatus) & ATA_STSREG_DWF) != 0) { 85 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Write Fault\n", IoRead8 (IdeRegisters->CmdOrStatus))); 86 } 87 88 if ((IoRead8 (IdeRegisters->CmdOrStatus) & ATA_STSREG_CORR) != 0) { 89 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Corrected Data\n", IoRead8 (IdeRegisters->CmdOrStatus))); 90 } 91 92 if ((IoRead8 (IdeRegisters->CmdOrStatus) & ATA_STSREG_ERR) != 0) { 93 if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_BBK) != 0) { 94 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Bad Block Detected\n", IoRead8 (IdeRegisters->ErrOrFeature))); 95 } 96 97 if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_UNC) != 0) { 98 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Uncorrectable Data\n", IoRead8 (IdeRegisters->ErrOrFeature))); 99 } 100 101 if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_MC) != 0) { 102 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Media Change\n", IoRead8 (IdeRegisters->ErrOrFeature))); 103 } 104 105 if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_ABRT) != 0) { 106 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Abort\n", IoRead8 (IdeRegisters->ErrOrFeature))); 107 } 108 109 if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_TK0NF) != 0) { 110 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Track 0 Not Found\n", IoRead8 (IdeRegisters->ErrOrFeature))); 111 } 112 113 if ((IoRead8 (IdeRegisters->ErrOrFeature) & ATA_ERRREG_AMNF) != 0) { 114 DEBUG ((EFI_D_ERROR, "CheckRegisterStatus()-- %02x : Error : Address Mark Not Found\n", IoRead8 (IdeRegisters->ErrOrFeature))); 115 } 116 } 117 DEBUG_CODE_END (); 118 } 119 120 /** 121 This function is used to analyze the Status Register and print out 122 some debug information and if there is ERR bit set in the Status 123 Register, the Error Register's Value is also be parsed and print out. 124 125 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 126 127 @retval EFI_SUCCESS No err information in the Status Register. 128 @retval EFI_DEVICE_ERROR Any err information in the Status Register. 129 130 **/ 131 EFI_STATUS 132 EFIAPI 133 CheckStatusRegister ( 134 IN EFI_IDE_REGISTERS *IdeRegisters 135 ) 136 { 137 EFI_STATUS Status; 138 UINT8 StatusRegister; 139 140 ASSERT (IdeRegisters != NULL); 141 142 StatusRegister = IoRead8 (IdeRegisters->CmdOrStatus); 143 144 if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) { 145 Status = EFI_SUCCESS; 146 } else { 147 Status = EFI_DEVICE_ERROR; 148 } 149 150 return Status; 151 } 152 153 /** 154 This function is used to poll for the DRQ bit clear in the Status 155 Register. DRQ is cleared when the device is finished transferring Data. 156 So this function is called after Data transfer is finished. 157 158 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 159 @param Timeout The time to complete the command. 160 161 @retval EFI_SUCCESS DRQ bit clear within the time out. 162 @retval EFI_TIMEOUT DRQ bit not clear within the time out. 163 164 @note 165 Read Status Register will clear interrupt status. 166 167 **/ 168 EFI_STATUS 169 EFIAPI 170 DRQClear ( 171 IN EFI_IDE_REGISTERS *IdeRegisters, 172 IN UINT64 Timeout 173 ) 174 { 175 UINT32 Delay; 176 UINT8 StatusRegister; 177 178 ASSERT (IdeRegisters != NULL); 179 180 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); 181 do { 182 StatusRegister = IoRead8 (IdeRegisters->CmdOrStatus); 183 184 // 185 // wait for BSY == 0 and DRQ == 0 186 // 187 if ((StatusRegister & ATA_STSREG_BSY) == 0) { 188 189 if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { 190 return EFI_DEVICE_ERROR; 191 } else { 192 return EFI_SUCCESS; 193 } 194 } 195 196 // 197 // Stall for 100 microseconds. 198 // 199 MicroSecondDelay (100); 200 201 Delay--; 202 203 } while (Delay > 0); 204 205 return EFI_TIMEOUT; 206 } 207 /** 208 This function is used to poll for the DRQ bit clear in the Alternate 209 Status Register. DRQ is cleared when the device is finished 210 transferring Data. So this function is called after Data transfer 211 is finished. 212 213 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 214 @param Timeout The time to complete the command. 215 216 @retval EFI_SUCCESS DRQ bit clear within the time out. 217 218 @retval EFI_TIMEOUT DRQ bit not clear within the time out. 219 @note Read Alternate Status Register will not clear interrupt status. 220 221 **/ 222 EFI_STATUS 223 EFIAPI 224 DRQClear2 ( 225 IN EFI_IDE_REGISTERS *IdeRegisters, 226 IN UINT64 Timeout 227 ) 228 { 229 UINT32 Delay; 230 UINT8 AltRegister; 231 232 ASSERT (IdeRegisters != NULL); 233 234 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); 235 do { 236 AltRegister = IoRead8 (IdeRegisters->AltOrDev); 237 238 // 239 // wait for BSY == 0 and DRQ == 0 240 // 241 if ((AltRegister & ATA_STSREG_BSY) == 0) { 242 if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { 243 return EFI_DEVICE_ERROR; 244 } else { 245 return EFI_SUCCESS; 246 } 247 } 248 249 // 250 // Stall for 100 microseconds. 251 // 252 MicroSecondDelay (100); 253 254 Delay--; 255 256 } while (Delay > 0); 257 258 return EFI_TIMEOUT; 259 } 260 261 262 /** 263 This function is used to poll for the DRQ bit set in the Alternate Status Register. 264 DRQ is set when the device is ready to transfer Data. So this function is called after 265 the command is sent to the device and before required Data is transferred. 266 267 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 268 @param Timeout The time to complete the command. 269 270 @retval EFI_SUCCESS DRQ bit set within the time out. 271 @retval EFI_TIMEOUT DRQ bit not set within the time out. 272 @retval EFI_ABORTED DRQ bit not set caused by the command abort. 273 @note Read Alternate Status Register will not clear interrupt status. 274 275 **/ 276 EFI_STATUS 277 EFIAPI 278 DRQReady2 ( 279 IN EFI_IDE_REGISTERS *IdeRegisters, 280 IN UINT64 Timeout 281 ) 282 { 283 UINT32 Delay; 284 UINT8 AltRegister; 285 UINT8 ErrorRegister; 286 287 ASSERT (IdeRegisters != NULL); 288 289 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); 290 291 do { 292 // 293 // Read Alternate Status Register will not clear interrupt status 294 // 295 AltRegister = IoRead8 (IdeRegisters->AltOrDev); 296 // 297 // BSY == 0 , DRQ == 1 298 // 299 if ((AltRegister & ATA_STSREG_BSY) == 0) { 300 if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { 301 ErrorRegister = IoRead8 (IdeRegisters->ErrOrFeature); 302 303 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 304 return EFI_ABORTED; 305 } 306 return EFI_DEVICE_ERROR; 307 } 308 309 if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { 310 return EFI_SUCCESS; 311 } else { 312 return EFI_NOT_READY; 313 } 314 } 315 316 // 317 // Stall for 100 microseconds. 318 // 319 MicroSecondDelay (100); 320 321 Delay--; 322 } while (Delay > 0); 323 324 return EFI_TIMEOUT; 325 } 326 327 /** 328 This function is used to poll for the BSY bit clear in the Status Register. BSY 329 is clear when the device is not busy. Every command must be sent after device is not busy. 330 331 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 332 @param Timeout The time to complete the command. 333 334 @retval EFI_SUCCESS BSY bit clear within the time out. 335 @retval EFI_TIMEOUT BSY bit not clear within the time out. 336 337 @note Read Status Register will clear interrupt status. 338 **/ 339 EFI_STATUS 340 EFIAPI 341 WaitForBSYClear ( 342 IN EFI_IDE_REGISTERS *IdeRegisters, 343 IN UINT64 Timeout 344 ) 345 { 346 UINT32 Delay; 347 UINT8 StatusRegister; 348 349 ASSERT (IdeRegisters != NULL); 350 351 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); 352 do { 353 StatusRegister = IoRead8 (IdeRegisters->CmdOrStatus); 354 355 if ((StatusRegister & ATA_STSREG_BSY) == 0x00) { 356 return EFI_SUCCESS; 357 } 358 359 // 360 // Stall for 100 microseconds. 361 // 362 MicroSecondDelay (100); 363 364 Delay--; 365 366 } while (Delay > 0); 367 368 return EFI_TIMEOUT; 369 } 370 371 /** 372 Get IDE i/o port registers' base addresses by mode. 373 374 In 'Compatibility' mode, use fixed addresses. 375 In Native-PCI mode, get base addresses from BARs in the PCI IDE controller's 376 Configuration Space. 377 378 The steps to get IDE i/o port registers' base addresses for each channel 379 as follows: 380 381 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE 382 controller's Configuration Space to determine the operating mode. 383 384 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. 385 ___________________________________________ 386 | | Command Block | Control Block | 387 | Channel | Registers | Registers | 388 |___________|_______________|_______________| 389 | Primary | 1F0h - 1F7h | 3F6h - 3F7h | 390 |___________|_______________|_______________| 391 | Secondary | 170h - 177h | 376h - 377h | 392 |___________|_______________|_______________| 393 394 Table 1. Compatibility resource mappings 395 396 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs 397 in IDE controller's PCI Configuration Space, shown in the Table 2 below. 398 ___________________________________________________ 399 | | Command Block | Control Block | 400 | Channel | Registers | Registers | 401 |___________|___________________|___________________| 402 | Primary | BAR at offset 0x10| BAR at offset 0x14| 403 |___________|___________________|___________________| 404 | Secondary | BAR at offset 0x18| BAR at offset 0x1C| 405 |___________|___________________|___________________| 406 407 Table 2. BARs for Register Mapping 408 409 @param[in] Bus The bus number of ata host controller. 410 @param[in] Device The device number of ata host controller. 411 @param[in] Function The function number of ata host controller. 412 @param[in, out] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to 413 store the IDE i/o port registers' base addresses 414 415 @retval EFI_UNSUPPORTED Return this Value when the BARs is not IO type 416 @retval EFI_SUCCESS Get the Base address successfully 417 @retval Other Read the pci configureation Data error 418 419 **/ 420 EFI_STATUS 421 EFIAPI 422 GetIdeRegisterIoAddr ( 423 IN UINTN Bus, 424 IN UINTN Device, 425 IN UINTN Function, 426 IN OUT EFI_IDE_REGISTERS *IdeRegisters 427 ) 428 { 429 UINT16 CommandBlockBaseAddr; 430 UINT16 ControlBlockBaseAddr; 431 UINT8 ClassCode; 432 UINT32 BaseAddress[4]; 433 434 if (IdeRegisters == NULL) { 435 return EFI_INVALID_PARAMETER; 436 } 437 438 ClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x9)); 439 BaseAddress[0] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x10)); 440 BaseAddress[1] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x14)); 441 BaseAddress[2] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x18)); 442 BaseAddress[3] = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x1C)); 443 444 if ((ClassCode & IDE_PRIMARY_OPERATING_MODE) == 0) { 445 CommandBlockBaseAddr = 0x1f0; 446 ControlBlockBaseAddr = 0x3f6; 447 } else { 448 // 449 // The BARs should be of IO type 450 // 451 if ((BaseAddress[0] & BIT0) == 0 || 452 (BaseAddress[1] & BIT0) == 0) { 453 return EFI_UNSUPPORTED; 454 } 455 456 CommandBlockBaseAddr = (UINT16) (BaseAddress[0] & 0x0000fff8); 457 ControlBlockBaseAddr = (UINT16) ((BaseAddress[1] & 0x0000fffc) + 2); 458 } 459 460 // 461 // Calculate IDE primary channel I/O register base address. 462 // 463 IdeRegisters[EfiIdePrimary].Data = CommandBlockBaseAddr; 464 IdeRegisters[EfiIdePrimary].ErrOrFeature = (UINT16) (CommandBlockBaseAddr + 0x01); 465 IdeRegisters[EfiIdePrimary].SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); 466 IdeRegisters[EfiIdePrimary].SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); 467 IdeRegisters[EfiIdePrimary].CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); 468 IdeRegisters[EfiIdePrimary].CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); 469 IdeRegisters[EfiIdePrimary].Head = (UINT16) (CommandBlockBaseAddr + 0x06); 470 IdeRegisters[EfiIdePrimary].CmdOrStatus = (UINT16) (CommandBlockBaseAddr + 0x07); 471 IdeRegisters[EfiIdePrimary].AltOrDev = ControlBlockBaseAddr; 472 473 if ((ClassCode & IDE_SECONDARY_OPERATING_MODE) == 0) { 474 CommandBlockBaseAddr = 0x170; 475 ControlBlockBaseAddr = 0x376; 476 } else { 477 // 478 // The BARs should be of IO type 479 // 480 if ((BaseAddress[2] & BIT0) == 0 || 481 (BaseAddress[3] & BIT0) == 0) { 482 return EFI_UNSUPPORTED; 483 } 484 485 CommandBlockBaseAddr = (UINT16) (BaseAddress[2] & 0x0000fff8); 486 ControlBlockBaseAddr = (UINT16) ((BaseAddress[3] & 0x0000fffc) + 2); 487 } 488 489 // 490 // Calculate IDE secondary channel I/O register base address. 491 // 492 IdeRegisters[EfiIdeSecondary].Data = CommandBlockBaseAddr; 493 IdeRegisters[EfiIdeSecondary].ErrOrFeature = (UINT16) (CommandBlockBaseAddr + 0x01); 494 IdeRegisters[EfiIdeSecondary].SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); 495 IdeRegisters[EfiIdeSecondary].SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); 496 IdeRegisters[EfiIdeSecondary].CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); 497 IdeRegisters[EfiIdeSecondary].CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); 498 IdeRegisters[EfiIdeSecondary].Head = (UINT16) (CommandBlockBaseAddr + 0x06); 499 IdeRegisters[EfiIdeSecondary].CmdOrStatus = (UINT16) (CommandBlockBaseAddr + 0x07); 500 IdeRegisters[EfiIdeSecondary].AltOrDev = ControlBlockBaseAddr; 501 502 return EFI_SUCCESS; 503 } 504 505 /** 506 Send ATA Ext command into device with NON_DATA protocol. 507 508 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 509 @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK Data structure. 510 @param Timeout The time to complete the command. 511 512 @retval EFI_SUCCESS Reading succeed 513 @retval EFI_DEVICE_ERROR Error executing commands on this device. 514 515 **/ 516 EFI_STATUS 517 EFIAPI 518 AtaIssueCommand ( 519 IN EFI_IDE_REGISTERS *IdeRegisters, 520 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, 521 IN UINT64 Timeout 522 ) 523 { 524 EFI_STATUS Status; 525 UINT8 DeviceHead; 526 UINT8 AtaCommand; 527 528 ASSERT (IdeRegisters != NULL); 529 ASSERT (AtaCommandBlock != NULL); 530 531 DeviceHead = AtaCommandBlock->AtaDeviceHead; 532 AtaCommand = AtaCommandBlock->AtaCommand; 533 534 Status = WaitForBSYClear (IdeRegisters, Timeout); 535 if (EFI_ERROR (Status)) { 536 return EFI_DEVICE_ERROR; 537 } 538 539 // 540 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) 541 // 542 IoWrite8 (IdeRegisters->Head, (UINT8) (0xe0 | DeviceHead)); 543 544 // 545 // set all the command parameters 546 // Before write to all the following registers, BSY and DRQ must be 0. 547 // 548 Status = DRQClear2 (IdeRegisters, Timeout); 549 if (EFI_ERROR (Status)) { 550 return EFI_DEVICE_ERROR; 551 } 552 553 // 554 // Fill the feature register, which is a two-byte FIFO. Need write twice. 555 // 556 IoWrite8 (IdeRegisters->ErrOrFeature, AtaCommandBlock->AtaFeaturesExp); 557 IoWrite8 (IdeRegisters->ErrOrFeature, AtaCommandBlock->AtaFeatures); 558 559 // 560 // Fill the sector count register, which is a two-byte FIFO. Need write twice. 561 // 562 IoWrite8 (IdeRegisters->SectorCount, AtaCommandBlock->AtaSectorCountExp); 563 IoWrite8 (IdeRegisters->SectorCount, AtaCommandBlock->AtaSectorCount); 564 565 // 566 // Fill the start LBA registers, which are also two-byte FIFO 567 // 568 IoWrite8 (IdeRegisters->SectorNumber, AtaCommandBlock->AtaSectorNumberExp); 569 IoWrite8 (IdeRegisters->SectorNumber, AtaCommandBlock->AtaSectorNumber); 570 571 IoWrite8 (IdeRegisters->CylinderLsb, AtaCommandBlock->AtaCylinderLowExp); 572 IoWrite8 (IdeRegisters->CylinderLsb, AtaCommandBlock->AtaCylinderLow); 573 574 IoWrite8 (IdeRegisters->CylinderMsb, AtaCommandBlock->AtaCylinderHighExp); 575 IoWrite8 (IdeRegisters->CylinderMsb, AtaCommandBlock->AtaCylinderHigh); 576 577 // 578 // Send command via Command Register 579 // 580 IoWrite8 (IdeRegisters->CmdOrStatus, AtaCommand); 581 582 // 583 // Stall at least 400 microseconds. 584 // 585 MicroSecondDelay (400); 586 587 return EFI_SUCCESS; 588 } 589 590 /** 591 This function is used to send out ATA commands conforms to the PIO Data In Protocol. 592 593 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 594 @param Buffer A pointer to the source Buffer for the Data. 595 @param ByteCount The Length of the Data. 596 @param Read Flag used to determine the Data transfer direction. 597 Read equals 1, means Data transferred from device to host; 598 Read equals 0, means Data transferred from host to device. 599 @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK Data structure. 600 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK Data structure. 601 @param Timeout The time to complete the command. 602 603 @retval EFI_SUCCESS send out the ATA command and device send required Data successfully. 604 @retval EFI_DEVICE_ERROR command sent failed. 605 606 **/ 607 EFI_STATUS 608 EFIAPI 609 AtaPioDataInOut ( 610 IN EFI_IDE_REGISTERS *IdeRegisters, 611 IN OUT VOID *Buffer, 612 IN UINT64 ByteCount, 613 IN BOOLEAN Read, 614 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, 615 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, 616 IN UINT64 Timeout 617 ) 618 { 619 UINTN WordCount; 620 UINTN Increment; 621 UINT16 *Buffer16; 622 EFI_STATUS Status; 623 624 if ((IdeRegisters == NULL) || (Buffer == NULL) || (AtaCommandBlock == NULL)) { 625 return EFI_INVALID_PARAMETER; 626 } 627 628 // 629 // Issue ATA command 630 // 631 Status = AtaIssueCommand (IdeRegisters, AtaCommandBlock, Timeout); 632 if (EFI_ERROR (Status)) { 633 Status = EFI_DEVICE_ERROR; 634 goto Exit; 635 } 636 637 Buffer16 = (UINT16 *) Buffer; 638 639 // 640 // According to PIO Data in protocol, host can perform a series of reads to 641 // the Data register after each time device set DRQ ready; 642 // The Data Size of "a series of read" is command specific. 643 // For most ATA command, Data Size received from device will not exceed 644 // 1 sector, hence the Data Size for "a series of read" can be the whole Data 645 // Size of one command request. 646 // For ATA command such as Read Sector command, the Data Size of one ATA 647 // command request is often larger than 1 sector, according to the 648 // Read Sector command, the Data Size of "a series of read" is exactly 1 649 // sector. 650 // Here for simplification reason, we specify the Data Size for 651 // "a series of read" to 1 sector (256 words) if Data Size of one ATA command 652 // request is larger than 256 words. 653 // 654 Increment = 256; 655 656 // 657 // used to record bytes of currently transfered Data 658 // 659 WordCount = 0; 660 661 while (WordCount < RShiftU64(ByteCount, 1)) { 662 // 663 // Poll DRQ bit set, Data transfer can be performed only when DRQ is ready 664 // 665 Status = DRQReady2 (IdeRegisters, Timeout); 666 if (EFI_ERROR (Status)) { 667 Status = EFI_DEVICE_ERROR; 668 goto Exit; 669 } 670 671 // 672 // Get the byte count for one series of read 673 // 674 if ((WordCount + Increment) > RShiftU64(ByteCount, 1)) { 675 Increment = (UINTN)(RShiftU64(ByteCount, 1) - WordCount); 676 } 677 678 if (Read) { 679 IdeReadPortWMultiple ( 680 IdeRegisters->Data, 681 Increment, 682 Buffer16 683 ); 684 } else { 685 IdeWritePortWMultiple ( 686 IdeRegisters->Data, 687 Increment, 688 Buffer16 689 ); 690 } 691 692 Status = CheckStatusRegister (IdeRegisters); 693 if (EFI_ERROR (Status)) { 694 Status = EFI_DEVICE_ERROR; 695 goto Exit; 696 } 697 698 WordCount += Increment; 699 Buffer16 += Increment; 700 } 701 702 Status = DRQClear (IdeRegisters, Timeout); 703 if (EFI_ERROR (Status)) { 704 Status = EFI_DEVICE_ERROR; 705 goto Exit; 706 } 707 708 Exit: 709 // 710 // Dump All Ide registers to ATA_STATUS_BLOCK 711 // 712 DumpAllIdeRegisters (IdeRegisters); 713 714 return Status; 715 } 716 717 /** 718 Sends out an ATA Identify Command to the specified device. 719 720 This function sends out the ATA Identify Command to the 721 specified device. Only ATA device responses to this command. If 722 the command succeeds, it returns the Identify Data structure which 723 contains information about the device. This function extracts the 724 information it needs to fill the IDE_BLK_IO_DEV Data structure, 725 including device type, media block Size, media capacity, and etc. 726 727 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure. 728 @param Channel The channel number of device. 729 @param Device The device number of device. 730 @param Buffer A pointer to Data Buffer which is used to contain IDENTIFY Data. 731 732 @retval EFI_SUCCESS Identify ATA device successfully. 733 @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. 734 @retval EFI_OUT_OF_RESOURCES Allocate memory failed. 735 **/ 736 EFI_STATUS 737 EFIAPI 738 AtaIdentify ( 739 IN EFI_IDE_REGISTERS *IdeRegisters, 740 IN UINT8 Channel, 741 IN UINT8 Device, 742 IN OUT ATA_IDENTIFY_DATA *Buffer 743 ) 744 { 745 EFI_STATUS Status; 746 EFI_ATA_COMMAND_BLOCK AtaCommandBlock; 747 748 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK)); 749 750 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE; 751 AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4); 752 753 Status = AtaPioDataInOut ( 754 IdeRegisters, 755 Buffer, 756 sizeof (ATA_IDENTIFY_DATA), 757 TRUE, 758 &AtaCommandBlock, 759 NULL, 760 ATA_TIMEOUT 761 ); 762 763 return Status; 764 } 765 766 767 768