summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c')
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c1824
1 files changed, 0 insertions, 1824 deletions
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
deleted file mode 100644
index 4b4a8ef0a3..0000000000
--- a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
+++ /dev/null
@@ -1,1824 +0,0 @@
-/** @file
- Copyright (c) 2006, Intel Corporation
- All rights reserved. This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "idebus.h"
-
-BOOLEAN ChannelDeviceDetected = FALSE;
-BOOLEAN SlaveDeviceExist = FALSE;
-UINT8 SlaveDeviceType = INVALID_DEVICE_TYPE;
-BOOLEAN MasterDeviceExist = FALSE;
-UINT8 MasterDeviceType = INVALID_DEVICE_TYPE;
-
-/**
- TODO: Add function description
-
- @param PciIo TODO: add argument description
- @param Port TODO: add argument description
-
- TODO: add return values
-
-**/
-UINT8
-IDEReadPortB (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 Port
- )
-{
- UINT8 Data;
-
- Data = 0;
- //
- // perform 1-byte data read from register
- //
- PciIo->Io.Read (
- PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- (UINT64) Port,
- 1,
- &Data
- );
- return Data;
-}
-
-/**
- Reads multiple words of data from the IDE data port.
- Call the IO abstraction once to do the complete read,
- not one word at a time
-
- @param PciIo Pointer to the EFI_PCI_IO instance
- @param Port IO port to read
- @param Count No. of UINT16's to read
- @param Buffer Pointer to the data buffer for read
-
-**/
-VOID
-IDEReadPortWMultiple (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 Port,
- IN UINTN Count,
- IN VOID *Buffer
- )
-{
- UINT16 *AlignedBuffer;
- UINT16 *WorkingBuffer;
- UINTN Size;
-
- //
- // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
- // not perform actual I/O operations if buffer pointer passed in is not at
- // natural boundary. The "Buffer" argument is passed in by user and may not
- // at 16-bit natural boundary.
- //
- Size = sizeof (UINT16) * Count;
-
- gBS->AllocatePool (
- EfiBootServicesData,
- Size + 1,
- (VOID**)&WorkingBuffer
- );
-
- AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
-
- //
- // Perform UINT16 data read from FIFO
- //
- PciIo->Io.Read (
- PciIo,
- EfiPciIoWidthFifoUint16,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- (UINT64) Port,
- Count,
- (UINT16*)AlignedBuffer
- );
-
- //
- // Copy data to user buffer
- //
- CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);
- gBS->FreePool (WorkingBuffer);
-}
-
-/**
- TODO: Add function description
-
- @param PciIo TODO: add argument description
- @param Port TODO: add argument description
- @param Data TODO: add argument description
-
- TODO: add return values
-
-**/
-VOID
-IDEWritePortB (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 Port,
- IN UINT8 Data
- )
-{
- //
- // perform 1-byte data write to register
- //
- PciIo->Io.Write (
- PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- (UINT64) Port,
- 1,
- &Data
- );
-
-}
-
-/**
- TODO: Add function description
-
- @param PciIo TODO: add argument description
- @param Port TODO: add argument description
- @param Data TODO: add argument description
-
- TODO: add return values
-
-**/
-VOID
-IDEWritePortW (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 Port,
- IN UINT16 Data
- )
-{
- //
- // perform 1-word data write to register
- //
- PciIo->Io.Write (
- PciIo,
- EfiPciIoWidthUint16,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- (UINT64) Port,
- 1,
- &Data
- );
-}
-
-/**
- Write multiple words of data to the IDE data port.
- Call the IO abstraction once to do the complete read,
- not one word at a time
-
- @param PciIo Pointer to the EFI_PCI_IO instance
- @param Port IO port to read
- @param Count No. of UINT16's to read
- @param Buffer Pointer to the data buffer for read
-
-**/
-VOID
-IDEWritePortWMultiple (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINT16 Port,
- IN UINTN Count,
- IN VOID *Buffer
- )
-{
- UINT16 *AlignedBuffer;
- UINT32 *WorkingBuffer;
- UINTN Size;
-
- //
- // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
- // not perform actual I/O operations if buffer pointer passed in is not at
- // natural boundary. The "Buffer" argument is passed in by user and may not
- // at 16-bit natural boundary.
- //
- Size = sizeof (UINT16) * Count;
-
- gBS->AllocatePool (
- EfiBootServicesData,
- Size + 1,
- (VOID **) &WorkingBuffer
- );
-
- AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
-
- //
- // Copy data from user buffer to working buffer
- //
- CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);
-
- //
- // perform UINT16 data write to the FIFO
- //
- PciIo->Io.Write (
- PciIo,
- EfiPciIoWidthFifoUint16,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- (UINT64) Port,
- Count,
- (UINT16 *) AlignedBuffer
- );
-
- gBS->FreePool (WorkingBuffer);
-}
-
-//
-// GetIdeRegistersBaseAddr
-//
-/**
- Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
- use fixed addresses. In Native-PCI mode, get base addresses from BARs in
- the PCI IDE controller's Configuration Space.
-
- The steps to get IDE IO port registers' base addresses for each channel
- as follows:
-
- 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
- controller's Configuration Space to determine the operating mode.
-
- 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
- <pre>
- ___________________________________________
- | | Command Block | Control Block |
- | Channel | Registers | Registers |
- |___________|_______________|_______________|
- | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
- |___________|_______________|_______________|
- | Secondary | 170h - 177h | 376h - 377h |
- |___________|_______________|_______________|
-
- Table 1. Compatibility resource mappings
- </pre>
-
- b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
- in IDE controller's PCI Configuration Space, shown in the Table 2 below.
- <pre>
- ___________________________________________________
- | | Command Block | Control Block |
- | Channel | Registers | Registers |
- |___________|___________________|___________________|
- | Primary | BAR at offset 0x10| BAR at offset 0x14|
- |___________|___________________|___________________|
- | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
- |___________|___________________|___________________|
-
- Table 2. BARs for Register Mapping
- </pre>
- @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
- primary, 0374h for secondary. So 2 bytes extra offset should be
- added to the base addresses read from BARs.
-
- For more details, please refer to PCI IDE Controller Specification and Intel
- ICH4 Datasheet.
-
- @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
- @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to
- receive IDE IO port registers' base addresses
-
-**/
-EFI_STATUS
-GetIdeRegistersBaseAddr (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
- )
-// TODO: EFI_UNSUPPORTED - add return value to function comment
-// TODO: EFI_UNSUPPORTED - add return value to function comment
-// TODO: EFI_SUCCESS - add return value to function comment
-{
- EFI_STATUS Status;
- PCI_TYPE00 PciData;
-
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint8,
- 0,
- sizeof (PciData),
- &PciData
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {
- IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0;
- IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6;
- IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
- (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));
- } else {
- //
- // The BARs should be of IO type
- //
- if ((PciData.Device.Bar[0] & bit0) == 0 ||
- (PciData.Device.Bar[1] & bit0) == 0) {
- return EFI_UNSUPPORTED;
- }
-
- IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr =
- (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);
- IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr =
- (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);
- IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
- (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
- }
-
- if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {
- IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170;
- IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376;
- IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
- (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
- } else {
- //
- // The BARs should be of IO type
- //
- if ((PciData.Device.Bar[2] & bit0) == 0 ||
- (PciData.Device.Bar[3] & bit0) == 0) {
- return EFI_UNSUPPORTED;
- }
-
- IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr =
- (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);
- IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr =
- (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);
- IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
- (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function is used to requery IDE resources. The IDE controller will
- probably switch between native and legacy modes during the EFI->CSM->OS
- transfer. We do this everytime before an BlkIo operation to ensure its
- succeess.
-
- @param IdeDev The BLK_IO private data which specifies the IDE device
-
-**/
-EFI_STATUS
-ReassignIdeResources (
- IN IDE_BLK_IO_DEV *IdeDev
- )
-// TODO: EFI_SUCCESS - add return value to function comment
-{
- EFI_STATUS Status;
- IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
- UINT16 CommandBlockBaseAddr;
- UINT16 ControlBlockBaseAddr;
-
- //
- // Requery IDE IO port registers' base addresses in case of the switch of
- // native and legacy modes
- //
- Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));
- CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;
- ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;
-
- IdeDev->IoPort->Data = CommandBlockBaseAddr;
- (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
- IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
- IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
- IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
- IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
- IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
-
- (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
- (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr;
- IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
- IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);
-
- IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;
- return EFI_SUCCESS;
-}
-
-//
-// DiscoverIdeDevice
-//
-/**
- Detect if there is disk connected to this port
-
- @param IdeDev The BLK_IO private data which specifies the IDE device
-
-**/
-EFI_STATUS
-DiscoverIdeDevice (
- IN IDE_BLK_IO_DEV *IdeDev
- )
-// TODO: EFI_NOT_FOUND - add return value to function comment
-// TODO: EFI_NOT_FOUND - add return value to function comment
-// TODO: EFI_SUCCESS - add return value to function comment
-{
- EFI_STATUS Status;
-
- //
- // If a channel has not been checked, check it now. Then set it to "checked" state
- // After this step, all devices in this channel have been checked.
- //
- if (ChannelDeviceDetected == FALSE) {
- Status = DetectIDEController (IdeDev);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
- }
-
- Status = EFI_NOT_FOUND;
-
- //
- // Device exists. test if it is an ATA device.
- // Prefer the result from DetectIDEController,
- // if failed, try another device type to handle
- // devices that not follow the spec.
- //
- if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {
- if (MasterDeviceType == ATA_DEVICE_TYPE) {
- Status = ATAIdentify (IdeDev);
- if (EFI_ERROR (Status)) {
- Status = ATAPIIdentify (IdeDev);
- if (!EFI_ERROR (Status)) {
- MasterDeviceType = ATAPI_DEVICE_TYPE;
- }
- }
- } else {
- Status = ATAPIIdentify (IdeDev);
- if (EFI_ERROR (Status)) {
- Status = ATAIdentify (IdeDev);
- if (!EFI_ERROR (Status)) {
- MasterDeviceType = ATA_DEVICE_TYPE;
- }
- }
- }
- }
- if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {
- if (SlaveDeviceType == ATA_DEVICE_TYPE) {
- Status = ATAIdentify (IdeDev);
- if (EFI_ERROR (Status)) {
- Status = ATAPIIdentify (IdeDev);
- if (!EFI_ERROR (Status)) {
- SlaveDeviceType = ATAPI_DEVICE_TYPE;
- }
- }
- } else {
- Status = ATAPIIdentify (IdeDev);
- if (EFI_ERROR (Status)) {
- Status = ATAIdentify (IdeDev);
- if (!EFI_ERROR (Status)) {
- SlaveDeviceType = ATA_DEVICE_TYPE;
- }
- }
- }
- }
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
- //
- // Init Block I/O interface
- //
- IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
- IdeDev->BlkIo.Reset = IDEBlkIoReset;
- IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks;
- IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks;
- IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks;
-
- IdeDev->BlkMedia.LogicalPartition = FALSE;
- IdeDev->BlkMedia.WriteCaching = FALSE;
-
- //
- // Init Disk Info interface
- //
- gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));
- IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry;
- IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify;
- IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData;
- IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde;
-
- return EFI_SUCCESS;
-}
-
-/**
- This interface is used to initialize all state data related to the detection of one
- channel.
-
- @retval EFI_SUCCESS Completed Successfully.
-
-**/
-EFI_STATUS
-InitializeIDEChannelData (
- VOID
- )
-{
- ChannelDeviceDetected = FALSE;
- MasterDeviceExist = FALSE;
- MasterDeviceType = 0xff;
- SlaveDeviceExist = FALSE;
- SlaveDeviceType = 0xff;
- return EFI_SUCCESS;
-}
-
-/**
- This function is called by DiscoverIdeDevice(). It is used for detect
- whether the IDE device exists in the specified Channel as the specified
- Device Number.
-
- There is two IDE channels: one is Primary Channel, the other is
- Secondary Channel.(Channel is the logical name for the physical "Cable".)
- Different channel has different register group.
-
- On each IDE channel, at most two IDE devices attach,
- one is called Device 0 (Master device), the other is called Device 1
- (Slave device). The devices on the same channel co-use the same register
- group, so before sending out a command for a specified device via command
- register, it is a must to select the current device to accept the command
- by set the device number in the Head/Device Register.
-
- @param[in] *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @retval TRUE
- successfully detects device.
-
- @retval FALSE
- any failure during detection process will return this
- value.
-
- @note
- TODO: EFI_SUCCESS - add return value to function comment
- TODO: EFI_NOT_FOUND - add return value to function comment
-
-**/
-EFI_STATUS
-DetectIDEController (
- IN IDE_BLK_IO_DEV *IdeDev
- )
-{
- EFI_STATUS Status;
- UINT8 SectorCountReg;
- UINT8 LBALowReg;
- UINT8 LBAMidReg;
- UINT8 LBAHighReg;
- UINT8 InitStatusReg;
- UINT8 StatusReg;
-
- //
- // Select slave device
- //
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- (UINT8) ((1 << 4) | 0xe0)
- );
- gBS->Stall (100);
-
- //
- // Save the init slave status register
- //
- InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
-
- //
- // Select Master back
- //
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- (UINT8) ((0 << 4) | 0xe0)
- );
- gBS->Stall (100);
-
- //
- // Send ATA Device Execut Diagnostic command.
- // This command should work no matter DRDY is ready or not
- //
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
-
- Status = WaitForBSYClear (IdeDev, 3500);
- if (EFI_ERROR (Status)) {
- DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));
- return Status;
- }
- //
- // Read device signature
- //
- //
- // Select Master
- //
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- (UINT8) ((0 << 4) | 0xe0)
- );
- gBS->Stall (100);
- SectorCountReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->SectorCount
- );
- LBALowReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->SectorNumber
- );
- LBAMidReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->CylinderLsb
- );
- LBAHighReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->CylinderMsb
- );
- if ((SectorCountReg == 0x1) &&
- (LBALowReg == 0x1) &&
- (LBAMidReg == 0x0) &&
- (LBAHighReg == 0x0)) {
- MasterDeviceExist = TRUE;
- MasterDeviceType = ATA_DEVICE_TYPE;
- } else {
- if ((LBAMidReg == 0x14) &&
- (LBAHighReg == 0xeb)) {
- MasterDeviceExist = TRUE;
- MasterDeviceType = ATAPI_DEVICE_TYPE;
- }
- }
-
- //
- // For some Hard Drive, it takes some time to get
- // the right signature when operating in single slave mode.
- // We stall 20ms to work around this.
- //
- if (!MasterDeviceExist) {
- gBS->Stall (20000);
- }
-
- //
- // Select Slave
- //
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- (UINT8) ((1 << 4) | 0xe0)
- );
- gBS->Stall (100);
- SectorCountReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->SectorCount
- );
- LBALowReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->SectorNumber
- );
- LBAMidReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->CylinderLsb
- );
- LBAHighReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->CylinderMsb
- );
- StatusReg = IDEReadPortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Reg.Status
- );
- if ((SectorCountReg == 0x1) &&
- (LBALowReg == 0x1) &&
- (LBAMidReg == 0x0) &&
- (LBAHighReg == 0x0)) {
- SlaveDeviceExist = TRUE;
- SlaveDeviceType = ATA_DEVICE_TYPE;
- } else {
- if ((LBAMidReg == 0x14) &&
- (LBAHighReg == 0xeb)) {
- SlaveDeviceExist = TRUE;
- SlaveDeviceType = ATAPI_DEVICE_TYPE;
- }
- }
-
- //
- // When single master is plugged, slave device
- // will be wrongly detected. Here's the workaround
- // for ATA devices by detecting DRY bit in status
- // register.
- // NOTE: This workaround doesn't apply to ATAPI.
- //
- if (MasterDeviceExist && SlaveDeviceExist &&
- (StatusReg & DRDY) == 0 &&
- (InitStatusReg & DRDY) == 0 &&
- MasterDeviceType == SlaveDeviceType &&
- SlaveDeviceType != ATAPI_DEVICE_TYPE) {
- SlaveDeviceExist = FALSE;
- }
-
- //
- // Indicate this channel has been detected
- //
- ChannelDeviceDetected = TRUE;
- return EFI_SUCCESS;
-}
-
-/**
- This function is used to poll for the DRQ bit clear in the Status
- Register. DRQ is cleared when the device is finished transferring data.
- So this function is called after data transfer is finished.
-
- @param[in] *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] TimeoutInMilliSeconds
- used to designate the timeout for the DRQ clear.
-
- @retval EFI_SUCCESS
- DRQ bit clear within the time out.
-
- @retval EFI_TIMEOUT
- DRQ bit not clear within the time out.
-
- @note
- Read Status Register will clear interrupt status.
-
-**/
-EFI_STATUS
-DRQClear (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN TimeoutInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: TimeoutInMilliSeconds - add argument and description to function comment
-// TODO: EFI_ABORTED - add return value to function comment
-{
- UINT32 Delay;
- UINT8 StatusRegister;
- UINT8 ErrorRegister;
-
- Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
-
- StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
-
- //
- // wait for BSY == 0 and DRQ == 0
- //
- if ((StatusRegister & (DRQ | BSY)) == 0) {
- break;
- }
-
- if ((StatusRegister & (BSY | ERR)) == ERR) {
-
- ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
- if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
- return EFI_ABORTED;
- }
- }
-
- //
- // Stall for 30 us
- //
- gBS->Stall (30);
-
- Delay--;
-
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function is used to poll for the DRQ bit clear in the Alternate
- Status Register. DRQ is cleared when the device is finished
- transferring data. So this function is called after data transfer
- is finished.
-
- @param[in] *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] TimeoutInMilliSeconds
- used to designate the timeout for the DRQ clear.
-
- @retval EFI_SUCCESS
- DRQ bit clear within the time out.
-
- @retval EFI_TIMEOUT
- DRQ bit not clear within the time out.
-
- @note
- Read Alternate Status Register will not clear interrupt status.
-
-**/
-EFI_STATUS
-DRQClear2 (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN TimeoutInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: TimeoutInMilliSeconds - add argument and description to function comment
-// TODO: EFI_ABORTED - add return value to function comment
-{
- UINT32 Delay;
- UINT8 AltRegister;
- UINT8 ErrorRegister;
-
- Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
-
- AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
-
- //
- // wait for BSY == 0 and DRQ == 0
- //
- if ((AltRegister & (DRQ | BSY)) == 0) {
- break;
- }
-
- if ((AltRegister & (BSY | ERR)) == ERR) {
-
- ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
- if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
- return EFI_ABORTED;
- }
- }
-
- //
- // Stall for 30 us
- //
- gBS->Stall (30);
-
- Delay--;
-
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function is used to poll for the DRQ bit set in the
- Status Register.
- DRQ is set when the device is ready to transfer data. So this function
- is called after the command is sent to the device and before required
- data is transferred.
-
- @param[in] IDE_BLK_IO_DEV IN *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure,used
- to record all the information of the IDE device.
-
- @param[in] UINTN IN TimeoutInMilliSeconds
- used to designate the timeout for the DRQ ready.
-
- @retval EFI_SUCCESS
- DRQ bit set within the time out.
-
- @retval EFI_TIMEOUT
- DRQ bit not set within the time out.
-
- @retval EFI_ABORTED
- DRQ bit not set caused by the command abort.
-
- @note
- Read Status Register will clear interrupt status.
-
-**/
-EFI_STATUS
-DRQReady (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN TimeoutInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: TimeoutInMilliSeconds - add argument and description to function comment
-{
- UINT32 Delay;
- UINT8 StatusRegister;
- UINT8 ErrorRegister;
-
- Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
- //
- // read Status Register will clear interrupt
- //
- StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
-
- //
- // BSY==0,DRQ==1
- //
- if ((StatusRegister & (BSY | DRQ)) == DRQ) {
- break;
- }
-
- if ((StatusRegister & (BSY | ERR)) == ERR) {
-
- ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
- if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
- return EFI_ABORTED;
- }
- }
-
- //
- // Stall for 30 us
- //
- gBS->Stall (30);
-
- Delay--;
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function is used to poll for the DRQ bit set in the
- Alternate Status Register. DRQ is set when the device is ready to
- transfer data. So this function is called after the command
- is sent to the device and before required data is transferred.
-
- @param[in] IDE_BLK_IO_DEV IN *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] UINTN IN TimeoutInMilliSeconds
- used to designate the timeout for the DRQ ready.
-
- @retval EFI_SUCCESS
- DRQ bit set within the time out.
-
- @retval EFI_TIMEOUT
- DRQ bit not set within the time out.
-
- @retval EFI_ABORTED
- DRQ bit not set caused by the command abort.
-
- @note
- Read Alternate Status Register will not clear interrupt status.
-
-**/
-EFI_STATUS
-DRQReady2 (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN TimeoutInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: TimeoutInMilliSeconds - add argument and description to function comment
-{
- UINT32 Delay;
- UINT8 AltRegister;
- UINT8 ErrorRegister;
-
- Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
-
- do {
- //
- // Read Alternate Status Register will not clear interrupt status
- //
- AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
- //
- // BSY == 0 , DRQ == 1
- //
- if ((AltRegister & (BSY | DRQ)) == DRQ) {
- break;
- }
-
- if ((AltRegister & (BSY | ERR)) == ERR) {
-
- ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
- if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
- return EFI_ABORTED;
- }
- }
-
- //
- // Stall for 30 us
- //
- gBS->Stall (30);
-
- Delay--;
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This function is used to poll for the BSY bit clear in the
- Status Register. BSY is clear when the device is not busy.
- Every command must be sent after device is not busy.
-
- @param[in] IDE_BLK_IO_DEV IN *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] UINTN IN TimeoutInMilliSeconds
- used to designate the timeout for the DRQ ready.
-
- @retval EFI_SUCCESS
- BSY bit clear within the time out.
-
- @retval EFI_TIMEOUT
- BSY bit not clear within the time out.
-
- @note
- Read Status Register will clear interrupt status.
-
-**/
-EFI_STATUS
-WaitForBSYClear (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN TimeoutInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: TimeoutInMilliSeconds - add argument and description to function comment
-{
- UINT32 Delay;
- UINT8 StatusRegister;
-
- Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
-
- StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
- if ((StatusRegister & BSY) == 0x00) {
- break;
- }
-
- //
- // Stall for 30 us
- //
- gBS->Stall (30);
-
- Delay--;
-
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-//
-// WaitForBSYClear2
-//
-/**
- This function is used to poll for the BSY bit clear in the
- Alternate Status Register. BSY is clear when the device is not busy.
- Every command must be sent after device is not busy.
-
- @param[in] IDE_BLK_IO_DEV IN *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] UINTN IN TimeoutInMilliSeconds
- used to designate the timeout for the DRQ ready.
-
- @retval EFI_SUCCESS
- BSY bit clear within the time out.
-
- @retval EFI_TIMEOUT
- BSY bit not clear within the time out.
-
- @note
- Read Alternate Status Register will not clear interrupt status.
-
-**/
-EFI_STATUS
-WaitForBSYClear2 (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN TimeoutInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: TimeoutInMilliSeconds - add argument and description to function comment
-{
- UINT32 Delay;
- UINT8 AltRegister;
-
- Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
- AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
- if ((AltRegister & BSY) == 0x00) {
- break;
- }
-
- gBS->Stall (30);
-
- Delay--;
-
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-//
-// DRDYReady
-//
-/**
- This function is used to poll for the DRDY bit set in the
- Status Register. DRDY bit is set when the device is ready
- to accept command. Most ATA commands must be sent after
- DRDY set except the ATAPI Packet Command.
-
- @param[in] IDE_BLK_IO_DEV IN *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] UINTN IN TimeoutInMilliSeconds
- used to designate the timeout for the DRQ ready.
-
- @retval EFI_SUCCESS
- DRDY bit set within the time out.
-
- @retval EFI_TIMEOUT
- DRDY bit not set within the time out.
-
- @note
- Read Status Register will clear interrupt status.
-
-**/
-EFI_STATUS
-DRDYReady (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN DelayInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: DelayInMilliSeconds - add argument and description to function comment
-// TODO: EFI_ABORTED - add return value to function comment
-{
- UINT32 Delay;
- UINT8 StatusRegister;
- UINT8 ErrorRegister;
-
- Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
- StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
- //
- // BSY == 0 , DRDY == 1
- //
- if ((StatusRegister & (DRDY | BSY)) == DRDY) {
- break;
- }
-
- if ((StatusRegister & (BSY | ERR)) == ERR) {
-
- ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
- if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
- return EFI_ABORTED;
- }
- }
-
- gBS->Stall (30);
-
- Delay--;
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-//
-// DRDYReady2
-//
-/**
- This function is used to poll for the DRDY bit set in the
- Alternate Status Register. DRDY bit is set when the device is ready
- to accept command. Most ATA commands must be sent after
- DRDY set except the ATAPI Packet Command.
-
- @param[in] IDE_BLK_IO_DEV IN *IdeDev
- pointer pointing to IDE_BLK_IO_DEV data structure, used
- to record all the information of the IDE device.
-
- @param[in] UINTN IN TimeoutInMilliSeconds
- used to designate the timeout for the DRQ ready.
-
- @retval EFI_SUCCESS
- DRDY bit set within the time out.
-
- @retval EFI_TIMEOUT
- DRDY bit not set within the time out.
-
- @note
- Read Alternate Status Register will clear interrupt status.
-
-**/
-EFI_STATUS
-DRDYReady2 (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINTN DelayInMilliSeconds
- )
-// TODO: function comment is missing 'Routine Description:'
-// TODO: function comment is missing 'Arguments:'
-// TODO: IdeDev - add argument and description to function comment
-// TODO: DelayInMilliSeconds - add argument and description to function comment
-// TODO: EFI_ABORTED - add return value to function comment
-{
- UINT32 Delay;
- UINT8 AltRegister;
- UINT8 ErrorRegister;
-
- Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
- do {
- AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
- //
- // BSY == 0 , DRDY == 1
- //
- if ((AltRegister & (DRDY | BSY)) == DRDY) {
- break;
- }
-
- if ((AltRegister & (BSY | ERR)) == ERR) {
-
- ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
- if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
- return EFI_ABORTED;
- }
- }
-
- gBS->Stall (30);
-
- Delay--;
- } while (Delay);
-
- if (Delay == 0) {
- return EFI_TIMEOUT;
- }
-
- return EFI_SUCCESS;
-}
-
-//
-// SwapStringChars
-//
-/**
- This function is a helper function used to change the char order in a
- string. It is designed specially for the PrintAtaModuleName() function.
- After the IDE device is detected, the IDE driver gets the device module
- name by sending ATA command called ATA Identify Command or ATAPI
- Identify Command to the specified IDE device. The module name returned
- is a string of ASCII characters: the first character is bit8--bit15
- of the first word, the second character is bit0--bit7 of the first word
- and so on. Thus the string can not be print directly before it is
- preprocessed by this func to change the order of characters in
- each word in the string.
-
- @param[in] CHAR8 IN *Destination
- Indicates the destination string.
-
- @param[in] CHAR8 IN *Source
- Indicates the source string.
-
- @param[in] UINT8 IN Size
- the length of the string
-
-**/
-VOID
-SwapStringChars (
- IN CHAR8 *Destination,
- IN CHAR8 *Source,
- IN UINT32 Size
- )
-{
- UINT32 Index;
- CHAR8 Temp;
-
- for (Index = 0; Index < Size; Index += 2) {
-
- Temp = Source[Index + 1];
- Destination[Index + 1] = Source[Index];
- Destination[Index] = Temp;
- }
-}
-
-//
-// ReleaseIdeResources
-//
-/**
- Release resources of an IDE device before stopping it.
-
- @param[in] *IdeBlkIoDevice Standard IDE device private data structure
-
-**/
-VOID
-ReleaseIdeResources (
- IN IDE_BLK_IO_DEV *IdeBlkIoDevice
- )
-{
- if (IdeBlkIoDevice == NULL) {
- return ;
- }
-
- //
- // Release all the resourses occupied by the IDE_BLK_IO_DEV
- //
-
- if (IdeBlkIoDevice->SenseData != NULL) {
- gBS->FreePool (IdeBlkIoDevice->SenseData);
- IdeBlkIoDevice->SenseData = NULL;
- }
-
- if (IdeBlkIoDevice->Cache != NULL) {
- gBS->FreePool (IdeBlkIoDevice->Cache);
- IdeBlkIoDevice->Cache = NULL;
- }
-
- if (IdeBlkIoDevice->pIdData != NULL) {
- gBS->FreePool (IdeBlkIoDevice->pIdData);
- IdeBlkIoDevice->pIdData = NULL;
- }
-
- if (IdeBlkIoDevice->pInquiryData != NULL) {
- gBS->FreePool (IdeBlkIoDevice->pInquiryData);
- IdeBlkIoDevice->pInquiryData = NULL;
- }
-
- if (IdeBlkIoDevice->ControllerNameTable != NULL) {
- FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);
- IdeBlkIoDevice->ControllerNameTable = NULL;
- }
-
- if (IdeBlkIoDevice->IoPort != NULL) {
- gBS->FreePool (IdeBlkIoDevice->IoPort);
- }
-
- if (IdeBlkIoDevice->DevicePath != NULL) {
- gBS->FreePool (IdeBlkIoDevice->DevicePath);
- }
-
- if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {
- gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);
- IdeBlkIoDevice->ExitBootServiceEvent = NULL;
- }
-
- gBS->FreePool (IdeBlkIoDevice);
- IdeBlkIoDevice = NULL;
-
- return ;
-}
-
-//
-// SetDeviceTransferMode
-//
-/**
- Set the calculated Best transfer mode to a detected device
-
- @param[in] *IdeDev Standard IDE device private data structure
- @param[in] *TransferMode The device transfer mode to be set
-
- @return Set transfer mode Command execute status
-
-**/
-EFI_STATUS
-SetDeviceTransferMode (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN ATA_TRANSFER_MODE *TransferMode
- )
-// TODO: function comment is missing 'Routine Description:'
-{
- EFI_STATUS Status;
- UINT8 DeviceSelect;
- UINT8 SectorCount;
-
- DeviceSelect = 0;
- DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
- SectorCount = *((UINT8 *) TransferMode);
-
- //
- // Send SET FEATURE command (sub command 0x03) to set pio mode.
- //
- Status = AtaNonDataCommandIn (
- IdeDev,
- SET_FEATURES_CMD,
- DeviceSelect,
- 0x03,
- SectorCount,
- 0,
- 0,
- 0
- );
-
- return Status;
-}
-
-/**
- Send ATA command into device with NON_DATA protocol
-
- @param IdeDev Standard IDE device private data structure
- @param AtaCommand The ATA command to be sent
- @param Device The value in Device register
- @param Feature The value in Feature register
- @param SectorCount The value in SectorCount register
- @param LbaLow The value in LBA_LOW register
- @param LbaMiddle The value in LBA_MIDDLE register
- @param LbaHigh The value in LBA_HIGH register
-
- @retval EFI_SUCCESS Reading succeed
- @retval EFI_ABORTED Command failed
- @retval EFI_DEVICE_ERROR Device status error
-
-**/
-EFI_STATUS
-AtaNonDataCommandIn (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINT8 AtaCommand,
- IN UINT8 Device,
- IN UINT8 Feature,
- IN UINT8 SectorCount,
- IN UINT8 LbaLow,
- IN UINT8 LbaMiddle,
- IN UINT8 LbaHigh
- )
-{
- EFI_STATUS Status;
- UINT8 StatusRegister;
-
- Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
- //
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- (UINT8) ((IdeDev->Device << 4) | 0xe0)
- );
-
- //
- // ATA commands for ATA device must be issued when DRDY is set
- //
- Status = DRDYReady (IdeDev, ATATIMEOUT);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Pass parameter into device register block
- //
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
-
- //
- // Send command via Command Register
- //
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
-
- //
- // Wait for command completion
- // For ATA_SMART_CMD, we may need more timeout to let device
- // adjust internal states.
- //
- if (AtaCommand == ATA_SMART_CMD) {
- Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);
- } else {
- Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
- }
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
- if ((StatusRegister & ERR) == ERR) {
- //
- // Failed to execute command, abort operation
- //
- return EFI_ABORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Send ATA Ext command into device with NON_DATA protocol
-
- @param IdeDev Standard IDE device private data structure
- @param AtaCommand The ATA command to be sent
- @param Device The value in Device register
- @param Feature The value in Feature register
- @param SectorCount The value in SectorCount register
- @param LbaAddress The LBA address in 48-bit mode
-
- @retval EFI_SUCCESS Reading succeed
- @retval EFI_ABORTED Command failed
- @retval EFI_DEVICE_ERROR Device status error
-
-**/
-EFI_STATUS
-AtaNonDataCommandInExt (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN UINT8 AtaCommand,
- IN UINT8 Device,
- IN UINT16 Feature,
- IN UINT16 SectorCount,
- IN EFI_LBA LbaAddress
- )
-{
- EFI_STATUS Status;
- UINT8 StatusRegister;
- UINT8 SectorCount8;
- UINT8 Feature8;
- UINT8 LbaLow;
- UINT8 LbaMid;
- UINT8 LbaHigh;
-
- Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
- //
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- (UINT8) ((IdeDev->Device << 4) | 0xe0)
- );
-
- //
- // ATA commands for ATA device must be issued when DRDY is set
- //
- Status = DRDYReady (IdeDev, ATATIMEOUT);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Pass parameter into device register block
- //
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
-
- //
- // Fill the feature register, which is a two-byte FIFO. Need write twice.
- //
- Feature8 = (UINT8) (Feature >> 8);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
-
- Feature8 = (UINT8) Feature;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
-
- //
- // Fill the sector count register, which is a two-byte FIFO. Need write twice.
- //
- SectorCount8 = (UINT8) (SectorCount >> 8);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
-
- SectorCount8 = (UINT8) SectorCount;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
-
- //
- // Fill the start LBA registers, which are also two-byte FIFO
- //
- LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);
- LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);
- LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
-
- LbaLow = (UINT8) LbaAddress;
- LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);
- LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
-
- //
- // Send command via Command Register
- //
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
-
- //
- // Wait for command completion
- //
- Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
- if ((StatusRegister & ERR) == ERR) {
- //
- // Failed to execute command, abort operation
- //
- return EFI_ABORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-//
-// SetDriveParameters
-//
-/**
- Set drive parameters for devices not support PACKETS command
-
- @param[in] IdeDev Standard IDE device private data structure
- @param[in] DriveParameters The device parameters to be set into the disk
-
- @return SetParameters Command execute status
-
-**/
-EFI_STATUS
-SetDriveParameters (
- IN IDE_BLK_IO_DEV *IdeDev,
- IN ATA_DRIVE_PARMS *DriveParameters
- )
-{
- EFI_STATUS Status;
- UINT8 DeviceSelect;
-
- DeviceSelect = 0;
- DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
-
- //
- // Send Init drive parameters
- //
- Status = AtaNonDataCommandIn (
- IdeDev,
- INIT_DRIVE_PARAM_CMD,
- (UINT8) (DeviceSelect + DriveParameters->Heads),
- 0,
- DriveParameters->Sector,
- 0,
- 0,
- 0
- );
-
- //
- // Send Set Multiple parameters
- //
- Status = AtaNonDataCommandIn (
- IdeDev,
- SET_MULTIPLE_MODE_CMD,
- DeviceSelect,
- 0,
- DriveParameters->MultipleSector,
- 0,
- 0,
- 0
- );
- return Status;
-}
-
-/**
- TODO: Add function description
-
- @param IdeDev TODO: add argument description
-
- @retval EFI_SUCCESS TODO: Add description for return value
-
-**/
-EFI_STATUS
-EnableInterrupt (
- IN IDE_BLK_IO_DEV *IdeDev
- )
-{
- UINT8 DeviceControl;
-
- //
- // Enable interrupt for DMA operation
- //
- DeviceControl = 0;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- return EFI_SUCCESS;
-}
-
-/**
- Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
-
- @param[in] Event Pointer to this event
- @param[in] Context Event hanlder private data
-
-**/
-VOID
-EFIAPI
-ClearInterrupt (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- UINT64 IoPortForBmis;
- UINT8 RegisterValue;
- IDE_BLK_IO_DEV *IdeDev;
-
- //
- // Get our context
- //
- IdeDev = (IDE_BLK_IO_DEV *) Context;
-
- //
- // Obtain IDE IO port registers' base addresses
- //
- Status = ReassignIdeResources (IdeDev);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- //
- // Check whether interrupt is pending
- //
-
- //
- // Reset IDE device to force it de-assert interrupt pin
- // Note: this will reset all devices on this IDE channel
- //
- AtaSoftReset (IdeDev);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- //
- // Get base address of IDE Bus Master Status Regsiter
- //
- if (IdePrimary == IdeDev->Channel) {
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
- } else {
- if (IdeSecondary == IdeDev->Channel) {
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
- } else {
- return;
- }
- }
- //
- // Read BMIS register and clear ERROR and INTR bit
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- //
- // Select the other device on this channel to ensure this device to release the interrupt pin
- //
- if (IdeDev->Device == 0) {
- RegisterValue = (1 << 4) | 0xe0;
- } else {
- RegisterValue = (0 << 4) | 0xe0;
- }
- IDEWritePortB (
- IdeDev->PciIo,
- IdeDev->IoPort->Head,
- RegisterValue
- );
-
-}