📄 ide_ata.c
字号:
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 5: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 5: 0x%x\n", retval);
}
// lba low
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_LOW, lba_low);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 6: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 6: 0x%x\n", retval);
}
// lba mid
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_MID, lba_mid);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 7: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 7: 0x%x\n", retval);
}
// lba high
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_HIGH, lba_high);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 8: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 8: 0x%x\n", retval);
}
// device
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_DRIVE_SEL, device);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 9: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 9: 0x%x\n", retval);
}
}
// command
retval = ATA_WriteRegister(cmd->driveID, ATA_REG_COMMAND, hd_cmd);
if (retval == ATA_FAIL)
{
TRACE_ERROR("retval 10: 0x%x\n", retval);
LOG_DIAG_ERROR("retval 10: 0x%x\n", retval);
}
// Better not be an ATAPI command
if (ATA_WaitDriveDRdy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL)
{
status = ATA_ReadRegister(cmd->driveID, ATA_REG_STATUS);
TRACE_ERROR("Drive Busy, status = %x 11\n", status);
LOG_DIAG_ERROR("Drive Busy, status = %x 11\n", status);
return (IDE_ERRORCODE_TIMEOUT);
}
status = ATA_ReadRegister(cmd->driveID, ATA_REG_STATUS);
if (status & ATA_STATUS_ERR) {
error = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR);
//TRACE_ERROR("ATA_STATUS_CHECK status = %x, error: %x 12\n", status, error);
//LOG_DIAG_ERROR("ATA_STATUS_CHECK status = %x, error: %x 12\n", status, error);
return error;
}
if ((cmd->cmdCode == IDE_CMD_DIAG) ||
(cmd->cmdCode == IDE_CMD_STANDBY_IMMEDIATE))
{
error = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR);
if (cmd->cmdCode == IDE_CMD_STANDBY_IMMEDIATE)
{
TRACE_STDBY("!!!!!!!!!!!!!!!!!!!!!!!! Done standby immediate\n");
}
if (error == 0x01) // Everything is good
return 0;
else {
//DEBUG_OUT("Diagnostics failed %x\n", error);
return 0;
}
}
if (!cmd->readWrite)
return 0;
switch (cmd->cmdCode) { // get the maximum number of sector to transfer at a time before checking for DRQ or BSY again
case IDE_CMD_READM :
case IDE_CMD_READM_EXT:
soft_assert(buf != NULL);
maxTransfer = MAX_READ_DMA_SIZE / HD_SECTOR_SIZE;
if (diskDesc[cmd->driveID].currentMultipleTransfer < maxTransfer)
maxTransfer = diskDesc[cmd->driveID].currentMultipleTransfer;
break;
case IDE_CMD_WRITEM :
case IDE_CMD_WRITEM_EXT:
if (buf == NULL)
{
// for DMA from RIO, we always do 32K chunk
maxTransfer = 32 * 1024;
}
else
{
maxTransfer = MAX_WRITE_DMA_SIZE / HD_SECTOR_SIZE;
if (diskDesc[cmd->driveID].currentMultipleTransfer < maxTransfer)
maxTransfer = diskDesc[cmd->driveID].currentMultipleTransfer;
}
break;
case IDE_CMD_WRITEDMA:
case IDE_CMD_WRITEDMA_EXT:
// tango to do this should be a define
maxTransfer = 32 * 1024;
soft_assert((cmd->sectorCntReg * HD_SECTOR_SIZE) <= maxTransfer);
break;
default :
maxTransfer = 1;
break;
}
//DbgPrint2("cmd %x, max %d\n", cmd->cmdCode, maxTransfer);
//DEBUG_OUT("ATA_Send() code: %x, LBA: %x, secNum: %x\n", cmd->cmdCode, cmd->lba, cmd->sectorCntReg);
if (ATA_WaitDriveRdy(cmd->driveID, ATA_STATUS_DRQ, HD_WAIT_TIMEOUT) == ATA_FAIL) {
status = ATA_ReadRegister (cmd->driveID, ATA_REG_STATUS);
if (status & ATA_STATUS_ERR) {
error = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR);
//TRACE_ERROR("ATA_STATUS_CHECK status = %x, error: %x 13\n", status, error);
//LOG_DIAG_ERROR("ATA_STATUS_CHECK status = %x, error: %x 13\n", status, error);
return error;
}
DEBUG_OUT("Waiting for data, DRQ = 0, status = %x\n", status);
return 0;
}
byteCnt = cmd->sectorCntReg * HD_SECTOR_SIZE;
if ((byteCnt > cmd->maxDataSize) && (cmd->readWrite & IDE_CMD_READ))
{
TRACE_ERROR("ATA_Send(%x) data requested(0x%x) > maxDataSize(0x%x) 14\n", cmd->cmdCode, byteCnt, cmd->maxDataSize);
LOG_DIAG_ERROR("ATA_Send(%x) data requested(0x%x) > maxDataSize(0x%x) 14\n", cmd->cmdCode, byteCnt, cmd->maxDataSize);
return IDE_ERRORCODE_INSUFFICIENT_BUF_SIZE;
}
// make some adjustment: If the cmd->sectorCntReg is zero, the IDE device actually expects
// 256 sectors of data. Set the totalSecNum to 256.
totalSecNum = (cmd->sectorCntReg == 0) ? 256 : cmd->sectorCntReg;
i = 0;
while ( i < totalSecNum ) {
if (ATA_WaitDriveRdy(cmd->driveID, ATA_STATUS_DRQ, HD_WAIT_TIMEOUT) == ATA_FAIL) {
TRACE_ERROR("Missing some data 15\n");
LOG_DIAG_ERROR("Missing some data 15\n");
return -1;
}
if ((totalSecNum - i) >= maxTransfer)
byteCnt = maxTransfer * HD_SECTOR_SIZE;
else
byteCnt = (totalSecNum - i) * HD_SECTOR_SIZE;
// here
if (cmd->readWrite & IDE_CMD_READ)
{
ATA_ReadDataDMA(cmd->driveID, (void *)(buf + byteTx), byteCnt);
}
else
{
#ifdef STREAM_ENABLE
if (buf == NULL)
{
// Do FPGA dma transfer
#ifndef RIO_APP
StartFPGADMATransfer(byteCnt);
#else
#ifdef RIO_PIO_MODE
if (1)
{
int i;
soft_assert((byteCnt % 0x2000) == 0);
for (i = 0; i < (byteCnt / 0x2000); i++)
{
if (i)
{
if (ATA_WaitNotBusy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL) {
TRACE_ERROR("Drive Busy after reading data: 18\n");
LOG_DIAG_ERROR("Drive Busy after reading data 18\n");
return -1;
}
if (ATA_WaitDriveRdy(cmd->driveID, ATA_STATUS_DRQ, HD_WAIT_TIMEOUT) == ATA_FAIL) {
TRACE_ERROR("Missing some data 19\n");
LOG_DIAG_ERROR("Missing some data 19\n");
return -1;
}
}
StartDMATransfer(0x2000);
}
}
#else
StartDMATransfer(byteCnt);
#endif // RIO_PIO_MODE
#endif
}
else
#endif
{
// it's a write
ATA_WriteDataDMA(cmd->driveID, (void *)(buf + byteTx), byteCnt);
}
}
byteTx += byteCnt;
i += byteCnt / HD_SECTOR_SIZE;
if (ATA_WaitNotBusy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL) {
TRACE_ERROR("Drive Busy after reading data 16\n");
LOG_DIAG_ERROR("Drive Busy after reading data 16\n");
return -1;
}
}
while (ATA_WaitDriveRdy(cmd->driveID, 0, HD_WAIT_TIMEOUT) == ATA_FAIL) {
TRACE_ERROR("Still some data ... 17\n");
LOG_DIAG_ERROR("Still some data ... 17\n");
return -1;
}
cmd->dataSize = byteTx;
return 0;
}
Int32 ide_command_standby_immediate(Uint8 driveID)
{
IDE_Cmd cmd;
cmd.cmdCode = IDE_CMD_STANDBY_IMMEDIATE;
cmd.sectorCntReg = 0;
cmd.lba = 0;
cmd.driveID = driveID;
cmd.featureReg = 0x0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = NULL;
cmd.deviceReg = 0;
cmd.readWrite = 0;
cmd.maxDataSize = 0;
if(IDE_SendCmd(&cmd))
return IDE_IO_ERROR;
else
return SUCCESS;
}
Int32 ide_command_check_power_mode(Uint8 driveID, Uint8* mode)
{
IDE_Cmd cmd;
cmd.cmdCode = IDE_CMD_CHECK_POWER_MODE;
cmd.sectorCntReg = 0;
cmd.lba = 0;
cmd.driveID = driveID;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = NULL;
cmd.deviceReg = 0;
cmd.readWrite = 0;
cmd.maxDataSize = 0;
cmd.ext_cmd = FALSE;
if (IDE_SendCmd(&cmd))
{
*mode = 0;
return ATA_FAIL;
}
else
{
*mode = ATA_ReadRegister(driveID, ATA_REG_SECTOR_CNT) & 0xFF;
return ATA_SUCCESS;
}
}
Int32 ide_command_idle_immediate(Uint8 driveID)
{
Uint32 status;
ATA_LockBus (driveID);
ATA_LockDevice(driveID);
// Select the appropriate drive
ATA_WriteRegister (
driveID, //
ATA_REG_DRIVE_SEL, //
ATA_DRIVE_SELECT(driveID) //
);
if (ATA_WaitDriveDRdy(driveID, HD_WAIT_TIMEOUT) == ATA_FAIL)
{
TRACE_ERROR("<ide_command_idle_immediate> Timeout Waiting For Drive Drdy driveID %d\n", driveID);
ATA_ReleaseDevice(driveID);
ATA_ReleaseBus (driveID);
return (IDE_ERRORCODE_TIMEOUT);
}
// issue the command
ATA_WriteRegister (
driveID, //
ATA_REG_COMMAND, //
IDE_CMD_IDLE_IMMEDIATE //
);
// Better not be an ATAPI command
if (ATA_WaitDriveDRdy(driveID, HD_WAIT_TIMEOUT * 20) == ATA_FAIL)
{
status = ATA_ReadRegister(driveID, ATA_REG_STATUS);
TRACE_ERROR("<ide_command_idle_immediate> Drive Busy,driveID = %d status = %x\n", driveID, status);
ATA_ReleaseDevice(driveID);
ATA_ReleaseBus (driveID);
return (IDE_ERRORCODE_TIMEOUT);
}
ATA_ReleaseDevice(driveID);
ATA_ReleaseBus (driveID);
return SUCCESS;
}
//-----------------------------------------------------------------------------
// Function: ide_command_identify
//
// Description:
// Read drive characteristics
//
// This routine requests the drive parameters from the IDE drive at
// driveno and places them in the buffer at address. See an IDE drive
// data for a description of the command.
//
// Note: buffer must be at least 512 bytes.
//
// This routine is optional. It is not needed by the device driver interface.
//
// This routine is portable
//
//
//
//-----------------------------------------------------------------------------
Int32 ide_command_identify (Uint8 driveID, Uint8 * address)
{
IDE_Cmd cmd;
cmd.cmdCode = IDE_CMD_IDENT;
cmd.sectorCntReg = 1;
cmd.lba = 0;
cmd.driveID = driveID;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = address;
cmd.deviceReg = 0;
cmd.readWrite = IDE_CMD_READ;
cmd.maxDataSize = 512;
cmd.ext_cmd =FALSE;
if(IDE_SendCmd(&cmd))
return IDE_IO_ERROR;
else
return SUCCESS;
}
//-----------------------------------------------------------------------------
// Function: ide_command_diags
//
// Description:
// Execute drive diagnostics
//
// This routine execute a diagnostic request. If the diagnostic succeeds
// it returns SUCCESS
//
//-----------------------------------------------------------------------------
static Int32 ide_command_diags(Uint8 driveID)
{
IDE_Cmd cmd;
if (( diskDesc[driveID].MediaDeviceBrand == MEDIADEVICE_BRAND_SAIN) ||
( diskDesc[driveID].MediaDeviceBrand == MEDIADEVICE_BRAND_ONSPEC))
{
return SUCCESS;
}
cmd.cmdCode = IDE_CMD_DIAG;
cmd.sectorCntReg = 0;
cmd.lba = 0;
cmd.driveID = driveID;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = NULL;
cmd.deviceReg = 0;
cmd.readWrite = 0;
cmd.maxDataSize = 0;
cmd.ext_cmd = FALSE;
if(IDE_SendCmd(&cmd))
return IDE_IO_ERROR;
else
return SUCCESS;
}
Int32 ide_command_seek(Uint8 driveID)
{
IDE_Cmd cmd;
cmd.cmdCode = IDE_CMD_SEEK;
cmd.sectorCntReg = 0;
cmd.lba = 0;
cmd.driveID = driveID;
cmd.featureReg = 0;
cmd.pktCmd = NULL;
cmd.pktCmdSize = 0;
cmd.data = NULL;
cmd.deviceReg = 0;
cmd.readWrite = 0;
cmd.maxDataSize = 0;
cmd.ext_cmd =FALSE;
if(IDE_SendCmd(&cmd))
return IDE_IO_ERROR;
else
return SUCCESS;
}
#if 1
Int32 ide_command_media(Uint8 driveID)
{
Int32 retVal;
Uint32 status;
Uint32 tickCnt;
ATA_LockBus (driveID);
ATA_LockDevice(driveID);
// Select the appropriate drive
ATA_WriteRegister (
driveID, //
ATA_REG_DRIVE_SEL, //
ATA_DRIVE_SELECT(driveID) //
);
if (ATA_WaitDriveDRdy(driveID, HD_WAIT_TIMEOUT * 2) == ATA_FAIL)
{
TRACE_ERROR("<ide_command_media> Timeout Waiting For Drive Drdy 1\n");
//soft_assert(0);
ATA_WriteRegister(driveID, ATA_REG_DEVICE_CONTROL, ATA_DEVICE_CTRL_SRT_BIT | ATA_DEVICE_CTRL_nIEN_BIT);
ATA_ReleaseDevice(driveID);
ATA_ReleaseBus (driveID);
return (IDE_ERRORCODE_TIMEOUT);
}
if( diskDesc[driveID].MediaDeviceBrand == MEDIADEVICE_BRAND_ONSPEC)
{
ATA_WriteRegister(driveID, ATA_REG_FEATURE, 0);
}
else
{
ATA_WriteRegister(driveID, ATA_REG_FEATURE, 1);
}
// issue the command
ATA_WriteRegister (
driveID, //
ATA_REG_COMMAND, //
IDE_CMD_MEDIA //
);
tickCnt = tickGet();
while (1)
{
status = ATA_ReadRegister (
driveID,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -