⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide.c

📁 EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是EFI BIOS源代码中的与平台无关部分的代码
💻 C
📖 第 1 页 / 共 4 页
字号:
  }

  //
  // 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) {
    EfiLibFreeUnicodeStringTable (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
//
EFI_STATUS
SetDeviceTransferMode (
  IN IDE_BLK_IO_DEV       *IdeDev,
  IN ATA_TRANSFER_MODE    *TransferMode
  )
/*++
Routing Description:

  Set the calculated Best transfer mode to a detected device

Arguments:

  IdeDev       --  Standard IDE device private data structure
  TransferMode --  The device transfer mode to be set

Returns:

    Set transfer mode Command execute status
    
---*/
// 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;
}

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
  )
/*++

Routine Description:

  Send ATA command into device with NON_DATA protocol

Arguments:

  IdeDev      - Standard IDE device private data structure
  AtaCommand  - The ATA command to be sent
  Device      - The value in Device register
  Feature     - The value in Feature register
  SectorCount - The value in SectorCount register 
  LbaLow      - The value in LBA_LOW register
  LbaMiddle   - The value in LBA_MIDDLE register
  LbaHigh     - The value in LBA_HIGH register

Returns:

  EFI_SUCCESS      - Reading succeed
  EFI_ABORTED      - Command failed
  EFI_DEVICE_ERROR - Device status error

--*/
{
  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;
}

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
  )
/*++

Routine Description:

  Send ATA Ext command into device with NON_DATA protocol

Arguments:

  IdeDev      - Standard IDE device private data structure
  AtaCommand  - The ATA command to be sent
  Device      - The value in Device register
  Feature     - The value in Feature register
  SectorCount - The value in SectorCount register 
  LbaAddress - The LBA address in 48-bit mode

Returns:

  EFI_SUCCESS      - Reading succeed
  EFI_ABORTED      - Command failed
  EFI_DEVICE_ERROR - Device status error

--*/
{
  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
//
EFI_STATUS
SetDriveParameters (
  IN IDE_BLK_IO_DEV       *IdeDev,
  IN ATA_DRIVE_PARMS      *DriveParameters
  )
/*++
Routine Description: 

  Set drive parameters for devices not support PACKETS command

Arguments:

  IdeDev       --  Standard IDE device private data structure
  DriveParameters --  The device parameters to be set into the disk

Returns:

  SetParameters Command execute status
    
--*/
{
  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;
}

EFI_STATUS
EnableInterrupt (
  IN IDE_BLK_IO_DEV       *IdeDev
  )
/*++

Routine Description:

  TODO: Add function description

Arguments:

  IdeDev  - TODO: add argument description

Returns:

  EFI_SUCCESS - TODO: Add description for return value

--*/
{
  UINT8 DeviceControl;

  //
  // Enable interrupt for DMA operation
  //
  DeviceControl = 0;
  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);

  return EFI_SUCCESS;
}

VOID
ClearInterrupt (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
/*++

Routine Description:

  Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.

Arguments:

  Event   - Pointer to this event
  Context - Event hanlder private data

Returns:


--*/
{
  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
    );

  return ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -