1 /** @file 2 The file ontaining the helper functions implement of the Ide Bus driver 3 4 Copyright (c) 2006 - 2008, 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 "IdeBus.h" 16 17 BOOLEAN ChannelDeviceDetected = FALSE; 18 BOOLEAN SlaveDeviceExist = FALSE; 19 UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE; 20 BOOLEAN MasterDeviceExist = FALSE; 21 UINT8 MasterDeviceType = INVALID_DEVICE_TYPE; 22 23 /** 24 read a one-byte data from a IDE port. 25 26 @param PciIo The PCI IO protocol instance 27 @param Port the IDE Port number 28 29 @return the one-byte data read from IDE port 30 **/ 31 UINT8 32 IDEReadPortB ( 33 IN EFI_PCI_IO_PROTOCOL *PciIo, 34 IN UINT16 Port 35 ) 36 { 37 UINT8 Data; 38 39 Data = 0; 40 // 41 // perform 1-byte data read from register 42 // 43 PciIo->Io.Read ( 44 PciIo, 45 EfiPciIoWidthUint8, 46 EFI_PCI_IO_PASS_THROUGH_BAR, 47 (UINT64) Port, 48 1, 49 &Data 50 ); 51 return Data; 52 } 53 /** 54 Reads multiple words of data from the IDE data port. 55 Call the IO abstraction once to do the complete read, 56 not one word at a time 57 58 @param PciIo Pointer to the EFI_PCI_IO instance 59 @param Port IO port to read 60 @param Count No. of UINT16's to read 61 @param Buffer Pointer to the data buffer for read 62 63 **/ 64 VOID 65 IDEReadPortWMultiple ( 66 IN EFI_PCI_IO_PROTOCOL *PciIo, 67 IN UINT16 Port, 68 IN UINTN Count, 69 OUT VOID *Buffer 70 ) 71 { 72 UINT16 *AlignedBuffer; 73 UINT16 *WorkingBuffer; 74 UINTN Size; 75 76 // 77 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and 78 // not perform actual I/O operations if buffer pointer passed in is not at 79 // natural boundary. The "Buffer" argument is passed in by user and may not 80 // at 16-bit natural boundary. 81 // 82 Size = sizeof (UINT16) * Count; 83 84 gBS->AllocatePool ( 85 EfiBootServicesData, 86 Size + 1, 87 (VOID**)&WorkingBuffer 88 ); 89 90 AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); 91 92 // 93 // Perform UINT16 data read from FIFO 94 // 95 PciIo->Io.Read ( 96 PciIo, 97 EfiPciIoWidthFifoUint16, 98 EFI_PCI_IO_PASS_THROUGH_BAR, 99 (UINT64) Port, 100 Count, 101 (UINT16*)AlignedBuffer 102 ); 103 104 // 105 // Copy data to user buffer 106 // 107 CopyMem (Buffer, (UINT16*)AlignedBuffer, Size); 108 gBS->FreePool (WorkingBuffer); 109 } 110 111 /** 112 write a 1-byte data to a specific IDE port. 113 114 @param PciIo PCI IO protocol instance 115 @param Port The IDE port to be writen 116 @param Data The data to write to the port 117 **/ 118 VOID 119 IDEWritePortB ( 120 IN EFI_PCI_IO_PROTOCOL *PciIo, 121 IN UINT16 Port, 122 IN UINT8 Data 123 ) 124 { 125 // 126 // perform 1-byte data write to register 127 // 128 PciIo->Io.Write ( 129 PciIo, 130 EfiPciIoWidthUint8, 131 EFI_PCI_IO_PASS_THROUGH_BAR, 132 (UINT64) Port, 133 1, 134 &Data 135 ); 136 137 } 138 139 /** 140 write a 1-word data to a specific IDE port. 141 142 @param PciIo PCI IO protocol instance 143 @param Port The IDE port to be writen 144 @param Data The data to write to the port 145 **/ 146 VOID 147 IDEWritePortW ( 148 IN EFI_PCI_IO_PROTOCOL *PciIo, 149 IN UINT16 Port, 150 IN UINT16 Data 151 ) 152 { 153 // 154 // perform 1-word data write to register 155 // 156 PciIo->Io.Write ( 157 PciIo, 158 EfiPciIoWidthUint16, 159 EFI_PCI_IO_PASS_THROUGH_BAR, 160 (UINT64) Port, 161 1, 162 &Data 163 ); 164 } 165 166 /** 167 Write multiple words of data to the IDE data port. 168 Call the IO abstraction once to do the complete read, 169 not one word at a time 170 171 @param PciIo Pointer to the EFI_PCI_IO instance 172 @param Port IO port to read 173 @param Count No. of UINT16's to read 174 @param Buffer Pointer to the data buffer for read 175 176 **/ 177 VOID 178 IDEWritePortWMultiple ( 179 IN EFI_PCI_IO_PROTOCOL *PciIo, 180 IN UINT16 Port, 181 IN UINTN Count, 182 IN VOID *Buffer 183 ) 184 { 185 UINT16 *AlignedBuffer; 186 UINT32 *WorkingBuffer; 187 UINTN Size; 188 189 // 190 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and 191 // not perform actual I/O operations if buffer pointer passed in is not at 192 // natural boundary. The "Buffer" argument is passed in by user and may not 193 // at 16-bit natural boundary. 194 // 195 Size = sizeof (UINT16) * Count; 196 197 gBS->AllocatePool ( 198 EfiBootServicesData, 199 Size + 1, 200 (VOID **) &WorkingBuffer 201 ); 202 203 AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); 204 205 // 206 // Copy data from user buffer to working buffer 207 // 208 CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size); 209 210 // 211 // perform UINT16 data write to the FIFO 212 // 213 PciIo->Io.Write ( 214 PciIo, 215 EfiPciIoWidthFifoUint16, 216 EFI_PCI_IO_PASS_THROUGH_BAR, 217 (UINT64) Port, 218 Count, 219 (UINT16 *) AlignedBuffer 220 ); 221 222 gBS->FreePool (WorkingBuffer); 223 } 224 /** 225 Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, 226 use fixed addresses. In Native-PCI mode, get base addresses from BARs in 227 the PCI IDE controller's Configuration Space. 228 229 The steps to get IDE IO port registers' base addresses for each channel 230 as follows: 231 232 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE 233 controller's Configuration Space to determine the operating mode. 234 235 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. 236 <pre> 237 ___________________________________________ 238 | | Command Block | Control Block | 239 | Channel | Registers | Registers | 240 |___________|_______________|_______________| 241 | Primary | 1F0h - 1F7h | 3F6h - 3F7h | 242 |___________|_______________|_______________| 243 | Secondary | 170h - 177h | 376h - 377h | 244 |___________|_______________|_______________| 245 246 Table 1. Compatibility resource mappings 247 </pre> 248 249 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs 250 in IDE controller's PCI Configuration Space, shown in the Table 2 below. 251 <pre> 252 ___________________________________________________ 253 | | Command Block | Control Block | 254 | Channel | Registers | Registers | 255 |___________|___________________|___________________| 256 | Primary | BAR at offset 0x10| BAR at offset 0x14| 257 |___________|___________________|___________________| 258 | Secondary | BAR at offset 0x18| BAR at offset 0x1C| 259 |___________|___________________|___________________| 260 261 Table 2. BARs for Register Mapping 262 </pre> 263 @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for 264 primary, 0374h for secondary. So 2 bytes extra offset should be 265 added to the base addresses read from BARs. 266 267 For more details, please refer to PCI IDE Controller Specification and Intel 268 ICH4 Datasheet. 269 270 @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance 271 @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to 272 receive IDE IO port registers' base addresses 273 274 @retval EFI_UNSUPPORTED return this value when the BARs is not IO type 275 @retval EFI_SUCCESS Get the Base address successfully 276 @retval other read the pci configureation data error 277 278 **/ 279 EFI_STATUS 280 GetIdeRegistersBaseAddr ( 281 IN EFI_PCI_IO_PROTOCOL *PciIo, 282 OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr 283 ) 284 { 285 EFI_STATUS Status; 286 PCI_TYPE00 PciData; 287 288 Status = PciIo->Pci.Read ( 289 PciIo, 290 EfiPciIoWidthUint8, 291 0, 292 sizeof (PciData), 293 &PciData 294 ); 295 296 if (EFI_ERROR (Status)) { 297 return Status; 298 } 299 300 if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) { 301 IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0; 302 IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6; 303 IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = 304 (UINT16)((PciData.Device.Bar[4] & 0x0000fff0)); 305 } else { 306 // 307 // The BARs should be of IO type 308 // 309 if ((PciData.Device.Bar[0] & BIT0) == 0 || 310 (PciData.Device.Bar[1] & BIT0) == 0) { 311 return EFI_UNSUPPORTED; 312 } 313 314 IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 315 (UINT16) (PciData.Device.Bar[0] & 0x0000fff8); 316 IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 317 (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2); 318 IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = 319 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); 320 } 321 322 if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) { 323 IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170; 324 IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376; 325 IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = 326 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); 327 } else { 328 // 329 // The BARs should be of IO type 330 // 331 if ((PciData.Device.Bar[2] & BIT0) == 0 || 332 (PciData.Device.Bar[3] & BIT0) == 0) { 333 return EFI_UNSUPPORTED; 334 } 335 336 IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 337 (UINT16) (PciData.Device.Bar[2] & 0x0000fff8); 338 IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 339 (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2); 340 IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = 341 (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); 342 } 343 344 return EFI_SUCCESS; 345 } 346 347 /** 348 This function is used to requery IDE resources. The IDE controller will 349 probably switch between native and legacy modes during the EFI->CSM->OS 350 transfer. We do this everytime before an BlkIo operation to ensure its 351 succeess. 352 353 @param IdeDev The BLK_IO private data which specifies the IDE device 354 355 @retval EFI_INVALID_PARAMETER return this value when the channel is invalid 356 @retval EFI_SUCCESS reassign the IDE IO resource successfully 357 @retval other get the IDE current base address effor 358 359 **/ 360 EFI_STATUS 361 ReassignIdeResources ( 362 IN IDE_BLK_IO_DEV *IdeDev 363 ) 364 { 365 EFI_STATUS Status; 366 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; 367 UINT16 CommandBlockBaseAddr; 368 UINT16 ControlBlockBaseAddr; 369 370 if (IdeDev->Channel >= IdeMaxChannel) { 371 return EFI_INVALID_PARAMETER; 372 } 373 374 // 375 // Requery IDE IO port registers' base addresses in case of the switch of 376 // native and legacy modes 377 // 378 Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr); 379 if (EFI_ERROR (Status)) { 380 return Status; 381 } 382 383 ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS)); 384 CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr; 385 ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr; 386 387 IdeDev->IoPort->Data = CommandBlockBaseAddr; 388 (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); 389 IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); 390 IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); 391 IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); 392 IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); 393 IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); 394 395 (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); 396 (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr; 397 IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); 398 IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0); 399 400 IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr; 401 return EFI_SUCCESS; 402 } 403 404 /** 405 This function is called by DiscoverIdeDevice(). It is used for detect 406 whether the IDE device exists in the specified Channel as the specified 407 Device Number. 408 409 There is two IDE channels: one is Primary Channel, the other is 410 Secondary Channel.(Channel is the logical name for the physical "Cable".) 411 Different channel has different register group. 412 413 On each IDE channel, at most two IDE devices attach, 414 one is called Device 0 (Master device), the other is called Device 1 415 (Slave device). The devices on the same channel co-use the same register 416 group, so before sending out a command for a specified device via command 417 register, it is a must to select the current device to accept the command 418 by set the device number in the Head/Device Register. 419 420 @param IdeDev pointer to IDE_BLK_IO_DEV data structure, used to record all the 421 information of the IDE device. 422 423 @retval EFI_SUCCESS successfully detects device. 424 425 @retval other any failure during detection process will return this value. 426 427 **/ 428 EFI_STATUS 429 DetectIDEController ( 430 IN IDE_BLK_IO_DEV *IdeDev 431 ) 432 { 433 EFI_STATUS Status; 434 UINT8 SectorCountReg; 435 UINT8 LBALowReg; 436 UINT8 LBAMidReg; 437 UINT8 LBAHighReg; 438 UINT8 InitStatusReg; 439 UINT8 StatusReg; 440 441 // 442 // Select slave device 443 // 444 IDEWritePortB ( 445 IdeDev->PciIo, 446 IdeDev->IoPort->Head, 447 (UINT8) ((1 << 4) | 0xe0) 448 ); 449 gBS->Stall (100); 450 451 // 452 // Save the init slave status register 453 // 454 InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); 455 456 // 457 // Select Master back 458 // 459 IDEWritePortB ( 460 IdeDev->PciIo, 461 IdeDev->IoPort->Head, 462 (UINT8) ((0 << 4) | 0xe0) 463 ); 464 gBS->Stall (100); 465 466 // 467 // Send ATA Device Execut Diagnostic command. 468 // This command should work no matter DRDY is ready or not 469 // 470 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90); 471 472 Status = WaitForBSYClear (IdeDev, 3500); 473 if (EFI_ERROR (Status)) { 474 DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status)); 475 return Status; 476 } 477 // 478 // Read device signature 479 // 480 // 481 // Select Master 482 // 483 IDEWritePortB ( 484 IdeDev->PciIo, 485 IdeDev->IoPort->Head, 486 (UINT8) ((0 << 4) | 0xe0) 487 ); 488 gBS->Stall (100); 489 SectorCountReg = IDEReadPortB ( 490 IdeDev->PciIo, 491 IdeDev->IoPort->SectorCount 492 ); 493 LBALowReg = IDEReadPortB ( 494 IdeDev->PciIo, 495 IdeDev->IoPort->SectorNumber 496 ); 497 LBAMidReg = IDEReadPortB ( 498 IdeDev->PciIo, 499 IdeDev->IoPort->CylinderLsb 500 ); 501 LBAHighReg = IDEReadPortB ( 502 IdeDev->PciIo, 503 IdeDev->IoPort->CylinderMsb 504 ); 505 if ((SectorCountReg == 0x1) && 506 (LBALowReg == 0x1) && 507 (LBAMidReg == 0x0) && 508 (LBAHighReg == 0x0)) { 509 MasterDeviceExist = TRUE; 510 MasterDeviceType = ATA_DEVICE_TYPE; 511 } else { 512 if ((LBAMidReg == 0x14) && 513 (LBAHighReg == 0xeb)) { 514 MasterDeviceExist = TRUE; 515 MasterDeviceType = ATAPI_DEVICE_TYPE; 516 } 517 } 518 519 // 520 // For some Hard Drive, it takes some time to get 521 // the right signature when operating in single slave mode. 522 // We stall 20ms to work around this. 523 // 524 if (!MasterDeviceExist) { 525 gBS->Stall (20000); 526 } 527 528 // 529 // Select Slave 530 // 531 IDEWritePortB ( 532 IdeDev->PciIo, 533 IdeDev->IoPort->Head, 534 (UINT8) ((1 << 4) | 0xe0) 535 ); 536 gBS->Stall (100); 537 SectorCountReg = IDEReadPortB ( 538 IdeDev->PciIo, 539 IdeDev->IoPort->SectorCount 540 ); 541 LBALowReg = IDEReadPortB ( 542 IdeDev->PciIo, 543 IdeDev->IoPort->SectorNumber 544 ); 545 LBAMidReg = IDEReadPortB ( 546 IdeDev->PciIo, 547 IdeDev->IoPort->CylinderLsb 548 ); 549 LBAHighReg = IDEReadPortB ( 550 IdeDev->PciIo, 551 IdeDev->IoPort->CylinderMsb 552 ); 553 StatusReg = IDEReadPortB ( 554 IdeDev->PciIo, 555 IdeDev->IoPort->Reg.Status 556 ); 557 if ((SectorCountReg == 0x1) && 558 (LBALowReg == 0x1) && 559 (LBAMidReg == 0x0) && 560 (LBAHighReg == 0x0)) { 561 SlaveDeviceExist = TRUE; 562 SlaveDeviceType = ATA_DEVICE_TYPE; 563 } else { 564 if ((LBAMidReg == 0x14) && 565 (LBAHighReg == 0xeb)) { 566 SlaveDeviceExist = TRUE; 567 SlaveDeviceType = ATAPI_DEVICE_TYPE; 568 } 569 } 570 571 // 572 // When single master is plugged, slave device 573 // will be wrongly detected. Here's the workaround 574 // for ATA devices by detecting DRY bit in status 575 // register. 576 // NOTE: This workaround doesn't apply to ATAPI. 577 // 578 if (MasterDeviceExist && SlaveDeviceExist && 579 (StatusReg & ATA_STSREG_DRDY) == 0 && 580 (InitStatusReg & ATA_STSREG_DRDY) == 0 && 581 MasterDeviceType == SlaveDeviceType && 582 SlaveDeviceType != ATAPI_DEVICE_TYPE) { 583 SlaveDeviceExist = FALSE; 584 } 585 586 // 587 // Indicate this channel has been detected 588 // 589 ChannelDeviceDetected = TRUE; 590 return EFI_SUCCESS; 591 } 592 /** 593 Detect if there is disk attached to this port 594 595 @param IdeDev The BLK_IO private data which specifies the IDE device. 596 597 @retval EFI_NOT_FOUND The device or channel is not found 598 @retval EFI_SUCCESS The device is found 599 600 **/ 601 EFI_STATUS 602 DiscoverIdeDevice ( 603 IN IDE_BLK_IO_DEV *IdeDev 604 ) 605 { 606 EFI_STATUS Status; 607 EFI_STATUS LongPhyStatus; 608 609 // 610 // If a channel has not been checked, check it now. Then set it to "checked" state 611 // After this step, all devices in this channel have been checked. 612 // 613 if (!ChannelDeviceDetected) { 614 Status = DetectIDEController (IdeDev); 615 if (EFI_ERROR (Status)) { 616 return EFI_NOT_FOUND; 617 } 618 } 619 620 Status = EFI_NOT_FOUND; 621 622 // 623 // Device exists. test if it is an ATA device. 624 // Prefer the result from DetectIDEController, 625 // if failed, try another device type to handle 626 // devices that not follow the spec. 627 // 628 if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) { 629 if (MasterDeviceType == ATA_DEVICE_TYPE) { 630 Status = ATAIdentify (IdeDev); 631 if (EFI_ERROR (Status)) { 632 Status = ATAPIIdentify (IdeDev); 633 if (!EFI_ERROR (Status)) { 634 MasterDeviceType = ATAPI_DEVICE_TYPE; 635 } 636 } 637 } else { 638 Status = ATAPIIdentify (IdeDev); 639 if (EFI_ERROR (Status)) { 640 Status = ATAIdentify (IdeDev); 641 if (!EFI_ERROR (Status)) { 642 MasterDeviceType = ATA_DEVICE_TYPE; 643 } 644 } 645 } 646 } 647 if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) { 648 if (SlaveDeviceType == ATA_DEVICE_TYPE) { 649 Status = ATAIdentify (IdeDev); 650 if (EFI_ERROR (Status)) { 651 Status = ATAPIIdentify (IdeDev); 652 if (!EFI_ERROR (Status)) { 653 SlaveDeviceType = ATAPI_DEVICE_TYPE; 654 } 655 } 656 } else { 657 Status = ATAPIIdentify (IdeDev); 658 if (EFI_ERROR (Status)) { 659 Status = ATAIdentify (IdeDev); 660 if (!EFI_ERROR (Status)) { 661 SlaveDeviceType = ATA_DEVICE_TYPE; 662 } 663 } 664 } 665 } 666 if (EFI_ERROR (Status)) { 667 return EFI_NOT_FOUND; 668 } 669 // 670 // Init Block I/O interface 671 // 672 LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev); 673 if (!EFI_ERROR (LongPhyStatus)) { 674 IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; 675 } else { 676 IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; 677 } 678 IdeDev->BlkIo.Reset = IDEBlkIoReset; 679 IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks; 680 IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks; 681 IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks; 682 683 IdeDev->BlkMedia.LogicalPartition = FALSE; 684 IdeDev->BlkMedia.WriteCaching = FALSE; 685 686 // 687 // Init Disk Info interface 688 // 689 gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID)); 690 IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry; 691 IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify; 692 IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData; 693 IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde; 694 695 return EFI_SUCCESS; 696 } 697 698 /** 699 This interface is used to initialize all state data related to the detection of one 700 channel. 701 **/ 702 VOID 703 InitializeIDEChannelData ( 704 VOID 705 ) 706 { 707 ChannelDeviceDetected = FALSE; 708 MasterDeviceExist = FALSE; 709 MasterDeviceType = 0xff; 710 SlaveDeviceExist = FALSE; 711 SlaveDeviceType = 0xff; 712 } 713 /** 714 This function is used to poll for the DRQ bit clear in the Status 715 Register. DRQ is cleared when the device is finished transferring data. 716 So this function is called after data transfer is finished. 717 718 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used 719 to record all the information of the IDE device. 720 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. 721 722 @retval EFI_SUCCESS DRQ bit clear within the time out. 723 724 @retval EFI_TIMEOUT DRQ bit not clear within the time out. 725 726 @note 727 Read Status Register will clear interrupt status. 728 729 **/ 730 EFI_STATUS 731 DRQClear ( 732 IN IDE_BLK_IO_DEV *IdeDev, 733 IN UINTN TimeoutInMilliSeconds 734 ) 735 { 736 UINT32 Delay; 737 UINT8 StatusRegister; 738 UINT8 ErrorRegister; 739 740 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 741 do { 742 743 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); 744 745 // 746 // wait for BSY == 0 and DRQ == 0 747 // 748 if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { 749 break; 750 } 751 752 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { 753 754 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); 755 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 756 return EFI_ABORTED; 757 } 758 } 759 760 // 761 // Stall for 30 us 762 // 763 gBS->Stall (30); 764 765 Delay--; 766 767 } while (Delay > 0); 768 769 if (Delay == 0) { 770 return EFI_TIMEOUT; 771 } 772 773 return EFI_SUCCESS; 774 } 775 /** 776 This function is used to poll for the DRQ bit clear in the Alternate 777 Status Register. DRQ is cleared when the device is finished 778 transferring data. So this function is called after data transfer 779 is finished. 780 781 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used 782 to record all the information of the IDE device. 783 784 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. 785 786 @retval EFI_SUCCESS DRQ bit clear within the time out. 787 788 @retval EFI_TIMEOUT DRQ bit not clear within the time out. 789 @note Read Alternate Status Register will not clear interrupt status. 790 791 **/ 792 EFI_STATUS 793 DRQClear2 ( 794 IN IDE_BLK_IO_DEV *IdeDev, 795 IN UINTN TimeoutInMilliSeconds 796 ) 797 { 798 UINT32 Delay; 799 UINT8 AltRegister; 800 UINT8 ErrorRegister; 801 802 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 803 do { 804 805 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); 806 807 // 808 // wait for BSY == 0 and DRQ == 0 809 // 810 if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { 811 break; 812 } 813 814 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { 815 816 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); 817 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 818 return EFI_ABORTED; 819 } 820 } 821 822 // 823 // Stall for 30 us 824 // 825 gBS->Stall (30); 826 827 Delay--; 828 829 } while (Delay > 0); 830 831 if (Delay == 0) { 832 return EFI_TIMEOUT; 833 } 834 835 return EFI_SUCCESS; 836 } 837 838 /** 839 This function is used to poll for the DRQ bit set in the 840 Status Register. 841 DRQ is set when the device is ready to transfer data. So this function 842 is called after the command is sent to the device and before required 843 data is transferred. 844 845 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to 846 record all the information of the IDE device. 847 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. 848 849 @retval EFI_SUCCESS DRQ bit set within the time out. 850 @retval EFI_TIMEOUT DRQ bit not set within the time out. 851 @retval EFI_ABORTED DRQ bit not set caused by the command abort. 852 853 @note Read Status Register will clear interrupt status. 854 855 **/ 856 EFI_STATUS 857 DRQReady ( 858 IN IDE_BLK_IO_DEV *IdeDev, 859 IN UINTN TimeoutInMilliSeconds 860 ) 861 { 862 UINT32 Delay; 863 UINT8 StatusRegister; 864 UINT8 ErrorRegister; 865 866 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 867 do { 868 // 869 // read Status Register will clear interrupt 870 // 871 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); 872 873 // 874 // BSY==0,DRQ==1 875 // 876 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { 877 break; 878 } 879 880 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { 881 882 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); 883 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 884 return EFI_ABORTED; 885 } 886 } 887 888 // 889 // Stall for 30 us 890 // 891 gBS->Stall (30); 892 893 Delay--; 894 } while (Delay > 0); 895 896 if (Delay == 0) { 897 return EFI_TIMEOUT; 898 } 899 900 return EFI_SUCCESS; 901 } 902 /** 903 This function is used to poll for the DRQ bit set in the Alternate Status Register. 904 DRQ is set when the device is ready to transfer data. So this function is called after 905 the command is sent to the device and before required data is transferred. 906 907 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to 908 record all the information of the IDE device. 909 910 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. 911 912 @retval EFI_SUCCESS DRQ bit set within the time out. 913 @retval EFI_TIMEOUT DRQ bit not set within the time out. 914 @retval EFI_ABORTED DRQ bit not set caused by the command abort. 915 @note Read Alternate Status Register will not clear interrupt status. 916 917 **/ 918 EFI_STATUS 919 DRQReady2 ( 920 IN IDE_BLK_IO_DEV *IdeDev, 921 IN UINTN TimeoutInMilliSeconds 922 ) 923 { 924 UINT32 Delay; 925 UINT8 AltRegister; 926 UINT8 ErrorRegister; 927 928 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 929 930 do { 931 // 932 // Read Alternate Status Register will not clear interrupt status 933 // 934 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); 935 // 936 // BSY == 0 , DRQ == 1 937 // 938 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { 939 break; 940 } 941 942 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { 943 944 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); 945 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 946 return EFI_ABORTED; 947 } 948 } 949 950 // 951 // Stall for 30 us 952 // 953 gBS->Stall (30); 954 955 Delay--; 956 } while (Delay > 0); 957 958 if (Delay == 0) { 959 return EFI_TIMEOUT; 960 } 961 962 return EFI_SUCCESS; 963 } 964 965 /** 966 This function is used to poll for the BSY bit clear in the Status Register. BSY 967 is clear when the device is not busy. Every command must be sent after device is not busy. 968 969 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used 970 to record all the information of the IDE device. 971 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. 972 973 @retval EFI_SUCCESS BSY bit clear within the time out. 974 @retval EFI_TIMEOUT BSY bit not clear within the time out. 975 976 @note Read Status Register will clear interrupt status. 977 **/ 978 EFI_STATUS 979 WaitForBSYClear ( 980 IN IDE_BLK_IO_DEV *IdeDev, 981 IN UINTN TimeoutInMilliSeconds 982 ) 983 { 984 UINT32 Delay; 985 UINT8 StatusRegister; 986 987 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 988 do { 989 990 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); 991 if ((StatusRegister & ATA_STSREG_BSY) == 0x00) { 992 break; 993 } 994 995 // 996 // Stall for 30 us 997 // 998 gBS->Stall (30); 999 1000 Delay--; 1001 1002 } while (Delay > 0); 1003 1004 if (Delay == 0) { 1005 return EFI_TIMEOUT; 1006 } 1007 1008 return EFI_SUCCESS; 1009 } 1010 /** 1011 This function is used to poll for the BSY bit clear in the Alternate Status Register. 1012 BSY is clear when the device is not busy. Every command must be sent after device is 1013 not busy. 1014 1015 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record 1016 all the information of the IDE device. 1017 @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. 1018 1019 @retval EFI_SUCCESS BSY bit clear within the time out. 1020 @retval EFI_TIMEOUT BSY bit not clear within the time out. 1021 @note Read Alternate Status Register will not clear interrupt status. 1022 1023 **/ 1024 EFI_STATUS 1025 WaitForBSYClear2 ( 1026 IN IDE_BLK_IO_DEV *IdeDev, 1027 IN UINTN TimeoutInMilliSeconds 1028 ) 1029 { 1030 UINT32 Delay; 1031 UINT8 AltRegister; 1032 1033 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 1034 do { 1035 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); 1036 if ((AltRegister & ATA_STSREG_BSY) == 0x00) { 1037 break; 1038 } 1039 1040 gBS->Stall (30); 1041 1042 Delay--; 1043 1044 } while (Delay > 0); 1045 1046 if (Delay == 0) { 1047 return EFI_TIMEOUT; 1048 } 1049 1050 return EFI_SUCCESS; 1051 } 1052 /** 1053 This function is used to poll for the DRDY bit set in the Status Register. DRDY 1054 bit is set when the device is ready to accept command. Most ATA commands must be 1055 sent after DRDY set except the ATAPI Packet Command. 1056 1057 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used 1058 to record all the information of the IDE device. 1059 @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. 1060 1061 @retval EFI_SUCCESS DRDY bit set within the time out. 1062 @retval EFI_TIMEOUT DRDY bit not set within the time out. 1063 1064 @note Read Status Register will clear interrupt status. 1065 **/ 1066 EFI_STATUS 1067 DRDYReady ( 1068 IN IDE_BLK_IO_DEV *IdeDev, 1069 IN UINTN DelayInMilliSeconds 1070 ) 1071 { 1072 UINT32 Delay; 1073 UINT8 StatusRegister; 1074 UINT8 ErrorRegister; 1075 1076 Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 1077 do { 1078 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); 1079 // 1080 // BSY == 0 , DRDY == 1 1081 // 1082 if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { 1083 break; 1084 } 1085 1086 if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { 1087 1088 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); 1089 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 1090 return EFI_ABORTED; 1091 } 1092 } 1093 1094 gBS->Stall (30); 1095 1096 Delay--; 1097 } while (Delay > 0); 1098 1099 if (Delay == 0) { 1100 return EFI_TIMEOUT; 1101 } 1102 1103 return EFI_SUCCESS; 1104 } 1105 /** 1106 This function is used to poll for the DRDY bit set in the Alternate Status Register. 1107 DRDY bit is set when the device is ready to accept command. Most ATA commands must 1108 be sent after DRDY set except the ATAPI Packet Command. 1109 1110 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used 1111 to record all the information of the IDE device. 1112 @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. 1113 1114 @retval EFI_SUCCESS DRDY bit set within the time out. 1115 @retval EFI_TIMEOUT DRDY bit not set within the time out. 1116 1117 @note Read Alternate Status Register will clear interrupt status. 1118 1119 **/ 1120 EFI_STATUS 1121 DRDYReady2 ( 1122 IN IDE_BLK_IO_DEV *IdeDev, 1123 IN UINTN DelayInMilliSeconds 1124 ) 1125 { 1126 UINT32 Delay; 1127 UINT8 AltRegister; 1128 UINT8 ErrorRegister; 1129 1130 Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); 1131 do { 1132 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); 1133 // 1134 // BSY == 0 , DRDY == 1 1135 // 1136 if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { 1137 break; 1138 } 1139 1140 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { 1141 1142 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); 1143 if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { 1144 return EFI_ABORTED; 1145 } 1146 } 1147 1148 gBS->Stall (30); 1149 1150 Delay--; 1151 } while (Delay > 0); 1152 1153 if (Delay == 0) { 1154 return EFI_TIMEOUT; 1155 } 1156 1157 return EFI_SUCCESS; 1158 } 1159 /** 1160 Release resources of an IDE device before stopping it. 1161 1162 @param IdeBlkIoDevice Standard IDE device private data structure 1163 1164 **/ 1165 VOID 1166 ReleaseIdeResources ( 1167 IN IDE_BLK_IO_DEV *IdeBlkIoDevice 1168 ) 1169 { 1170 if (IdeBlkIoDevice == NULL) { 1171 return ; 1172 } 1173 1174 // 1175 // Release all the resourses occupied by the IDE_BLK_IO_DEV 1176 // 1177 1178 if (IdeBlkIoDevice->SenseData != NULL) { 1179 gBS->FreePool (IdeBlkIoDevice->SenseData); 1180 IdeBlkIoDevice->SenseData = NULL; 1181 } 1182 1183 if (IdeBlkIoDevice->Cache != NULL) { 1184 gBS->FreePool (IdeBlkIoDevice->Cache); 1185 IdeBlkIoDevice->Cache = NULL; 1186 } 1187 1188 if (IdeBlkIoDevice->IdData != NULL) { 1189 gBS->FreePool (IdeBlkIoDevice->IdData); 1190 IdeBlkIoDevice->IdData = NULL; 1191 } 1192 1193 if (IdeBlkIoDevice->InquiryData != NULL) { 1194 gBS->FreePool (IdeBlkIoDevice->InquiryData); 1195 IdeBlkIoDevice->InquiryData = NULL; 1196 } 1197 1198 if (IdeBlkIoDevice->ControllerNameTable != NULL) { 1199 FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable); 1200 IdeBlkIoDevice->ControllerNameTable = NULL; 1201 } 1202 1203 if (IdeBlkIoDevice->IoPort != NULL) { 1204 gBS->FreePool (IdeBlkIoDevice->IoPort); 1205 } 1206 1207 if (IdeBlkIoDevice->DevicePath != NULL) { 1208 gBS->FreePool (IdeBlkIoDevice->DevicePath); 1209 } 1210 1211 if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) { 1212 gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent); 1213 IdeBlkIoDevice->ExitBootServiceEvent = NULL; 1214 } 1215 1216 gBS->FreePool (IdeBlkIoDevice); 1217 IdeBlkIoDevice = NULL; 1218 1219 return ; 1220 } 1221 /** 1222 Set the calculated Best transfer mode to a detected device. 1223 1224 @param IdeDev Standard IDE device private data structure 1225 @param TransferMode The device transfer mode to be set 1226 @return Set transfer mode Command execute status. 1227 1228 **/ 1229 EFI_STATUS 1230 SetDeviceTransferMode ( 1231 IN IDE_BLK_IO_DEV *IdeDev, 1232 IN ATA_TRANSFER_MODE *TransferMode 1233 ) 1234 { 1235 EFI_STATUS Status; 1236 UINT8 DeviceSelect; 1237 UINT8 SectorCount; 1238 1239 DeviceSelect = 0; 1240 DeviceSelect = (UINT8) ((IdeDev->Device) << 4); 1241 SectorCount = *((UINT8 *) TransferMode); 1242 1243 // 1244 // Send SET FEATURE command (sub command 0x03) to set pio mode. 1245 // 1246 Status = AtaNonDataCommandIn ( 1247 IdeDev, 1248 ATA_CMD_SET_FEATURES, 1249 DeviceSelect, 1250 0x03, 1251 SectorCount, 1252 0, 1253 0, 1254 0 1255 ); 1256 1257 return Status; 1258 } 1259 /** 1260 Set drive parameters for devices not support PACKETS command. 1261 1262 @param IdeDev Standard IDE device private data structure 1263 @param DriveParameters The device parameters to be set into the disk 1264 @return SetParameters Command execute status. 1265 1266 **/ 1267 EFI_STATUS 1268 SetDriveParameters ( 1269 IN IDE_BLK_IO_DEV *IdeDev, 1270 IN ATA_DRIVE_PARMS *DriveParameters 1271 ) 1272 { 1273 EFI_STATUS Status; 1274 UINT8 DeviceSelect; 1275 1276 DeviceSelect = 0; 1277 DeviceSelect = (UINT8) ((IdeDev->Device) << 4); 1278 1279 // 1280 // Send Init drive parameters 1281 // 1282 Status = AtaNonDataCommandIn ( 1283 IdeDev, 1284 ATA_CMD_INIT_DRIVE_PARAM, 1285 (UINT8) (DeviceSelect + DriveParameters->Heads), 1286 0, 1287 DriveParameters->Sector, 1288 0, 1289 0, 1290 0 1291 ); 1292 1293 // 1294 // Send Set Multiple parameters 1295 // 1296 Status = AtaNonDataCommandIn ( 1297 IdeDev, 1298 ATA_CMD_SET_MULTIPLE_MODE, 1299 DeviceSelect, 1300 0, 1301 DriveParameters->MultipleSector, 1302 0, 1303 0, 1304 0 1305 ); 1306 return Status; 1307 } 1308 1309 /** 1310 Enable Interrupt on IDE controller. 1311 1312 @param IdeDev Standard IDE device private data structure 1313 1314 @retval EFI_SUCCESS Enable Interrupt successfully 1315 **/ 1316 EFI_STATUS 1317 EnableInterrupt ( 1318 IN IDE_BLK_IO_DEV *IdeDev 1319 ) 1320 { 1321 UINT8 DeviceControl; 1322 1323 // 1324 // Enable interrupt for DMA operation 1325 // 1326 DeviceControl = 0; 1327 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); 1328 1329 return EFI_SUCCESS; 1330 } 1331