📄 ata.c
字号:
// Function Name: ATAExecuteDeviceDiagnostic
//
// Function Description: Function implements the ATA Execute Device
// Diagnostic command. Returns the device
// diagnostic code.
//
//*******************************************************************
unsigned char ATAExecuteDeviceDiagnostic(void)
{
unsigned char ucReturnValue;
//
// Wait for the BSY and DRQ bits in the Status register to be low.
//
while(ATAReadCommandRegister(STATUSREGISTER) & (ATABSY | ATADRQ));
//
// Write the execute device diagnostic command into the
// Command register.
//
ATAWriteCommandRegister(COMMANDREGISTER, 0x90);
//
// Wait for the command to complete.
//
while(ATAReadCommandRegister(STATUSREGISTER) & (ATABSY | ATADRQ));
//
// Read and return the diagnostic code out.
//
ucReturnValue = ATAReadCommandRegister(ERRORREGISTER);
return(ucReturnValue);
}
//*******************************************************************
//
// Function Name: ATAIdentifyPacketDevice
//
// Function Description: Function retruns a 256 word chunk of data
// about the device.
//
//*******************************************************************
int ATAIdentifyPacketDevice(unsigned short * RV)
{
unsigned long returncount;
//
// Wait for the BSY and DRQ bits in the Status register to be low.
//
while(ATAReadCommandRegister(STATUSREGISTER) & (ATABSY | ATADRQ));
//
// Write the identify packet device command into the Command register.
//
ATAWriteCommandRegister(COMMANDREGISTER, 0xa1);
//
// Wait for the command to complete.
//
while(ATAReadCommandRegister(STATUSREGISTER) & (ATABSY));
//
// Read and return the data.
//
returncount = ATAReadDataRegister(RV,256);
return(returncount);
}
//*****************************************************************
//
// Function Name: ATASimpleRegPacket
//
// Function Description:
//
//******************************************************************
unsigned int ATASimpleRegPacket(int dev, unsigned int uiCommandPacketByteCount,
unsigned short cfp[6], unsigned int uiTransferDir,
unsigned int uiDataPacketByteCount,
unsigned short * data_pointer )
{
unsigned long ulCount = 0;
unsigned long ulTotalTransfered = 0;
unsigned short usWordCount = 0;
unsigned short usByteCount = 0;
unsigned char ucDevCtrl = 0;
unsigned char ucDevHead = 0;
unsigned char ucCylLow = 0;
unsigned char ucCylHigh = 0;
unsigned char ucFrReg = 0;
unsigned char ucScReg = 0;
unsigned char ucSnReg = 0;
unsigned char ucStatus = 0;
unsigned char ucReason = 0;
unsigned char ucLowCyl = 0;
unsigned char ucHighCyl = 0;
ucDevCtrl = CB_DC_HD15 | CB_DC_NIEN;
ucDevHead = dev ? CB_DH_DEV1 : CB_DH_DEV0 ;
ucCylLow = uiDataPacketByteCount & 0x00ff;
ucCylHigh = ( uiDataPacketByteCount & 0xff00 ) >> 8;
ucFrReg = reg_atapi_reg_fr;
ucScReg = reg_atapi_reg_sc;
ucSnReg = reg_atapi_reg_sn;
reg_atapi_reg_fr = 0;
reg_atapi_reg_sc = 0;
reg_atapi_reg_sn = 0;
reg_atapi_reg_dh = 0;
reg_cmd_info.cmd = 0;
reg_cmd_info.fr1 = 0;
reg_cmd_info.sc1 = 0;
reg_cmd_info.sn1 = 0;
reg_cmd_info.cl1 = 0;
reg_cmd_info.ch1 = 0;
reg_cmd_info.dh1 = 0;
reg_cmd_info.dc1 = 0;
reg_cmd_info.ec = 0;
reg_cmd_info.to = 0;
reg_cmd_info.st2 = 0;
reg_cmd_info.as2 = 0;
reg_cmd_info.er2 = 0;
reg_cmd_info.sc2 = 0;
reg_cmd_info.sn2 = 0;
reg_cmd_info.cl2 = 0;
reg_cmd_info.ch2 = 0;
reg_cmd_info.dh2 = 0;
reg_cmd_info.totalBytesXfer = 0L;
reg_cmd_info.failbits = 0;
reg_cmd_info.drqPackets = 0L;
reg_cmd_info.cmd = CMD_PACKET;
reg_cmd_info.fr1 = ucFrReg;
reg_cmd_info.sc1 = ucScReg;
reg_cmd_info.sn1 = ucSnReg;
reg_cmd_info.cl1 = ucCylLow;
reg_cmd_info.ch1 = ucCylHigh;
reg_cmd_info.dh1 = ucDevHead;
reg_cmd_info.dc1 = ucDevCtrl;
//
// Set up all the registers except the command register.
//
while (1)
{
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
//
// Wait for BSY=0 & DRQ=0
//
if (!(ucStatus & (ATABSY | ATADRQ)))
break;
}
ATAWriteControlRegister( DEVICECONTROLREGISTER, ucDevCtrl );
ATAWriteCommandRegister( FEATURESREGISTER, ucFrReg );
ATAWriteCommandRegister( SECTORCOUNTREGISTER, ucScReg );
ATAWriteCommandRegister( SECTORNUMBERREGISTER, ucSnReg );
ATAWriteCommandRegister( CYLINDERLOWREGISTER, ucCylLow );
ATAWriteCommandRegister( CYLINDERHIGHREGISTER, ucCylHigh );
ATAWriteCommandRegister( DEVICEHEADREGISTER, ucDevHead );
//
// Start the command by setting the Command register. The drive
// should immediately set BUSY status. Write 0xA0 ATA command
//
ATAWriteCommandRegister( COMMANDREGISTER, CMD_PACKET );
//
// Command packet transfer...
// Check for protocol failures,
// the device should have BSY=1 now but any number of
// strange things can happen on ATAPI devices:
// 1) the device may not set BSY=1 or DRQ=1 for awhile.
// 2) the device may go directly to DRQ=1 status,
// 3) the device may reject the command (maybe it is
// not really an ATAPI device or has some error).
//
while ( 1 )
{
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
//
// BSY = 1, that's ok
//
if ( ucStatus & ATABSY )
break;
//
// BSY = 0
//
else
{
//
// DRQ = 1, that's Ok
//
if ( ucStatus & ATADRQ )
break;
//
// ERR = 1, error, this is Ok
//
if ( ucStatus & ATAERR )
{
reg_cmd_info.ec = 77;
break;
}
//
// This is not Ok
//
reg_cmd_info.failbits |= FAILBIT0;
}
}
while ( 1 )
{
ucReason = ATAReadCommandRegister( SECTORCOUNTREGISTER );
//
// CoD = 1, I/O = 1
//
if ((ucReason & (CB_SC_P_IO | CB_SC_P_CD)) == CB_SC_P_CD)
break;
}
//
// Command packet transfer...
// Poll Alternate Status for BSY=0.
//
while ( 1 )
{
//
// Poll for not busy, was ASTAT
//
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
if ( ( ucStatus & ATABSY ) == 0 )
break;
}
//
// Command packet transfer...
// If no error, transfer the command packet.
//
if ( reg_cmd_info.ec == 0 )
{
//
// Command packet transfer...
// Read the primary status register and the other ATAPI registers.
//
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
ucReason = ATAReadCommandRegister( SECTORCOUNTREGISTER );
ucLowCyl = ATAReadCommandRegister( CYLINDERLOWREGISTER );
ucHighCyl = ATAReadCommandRegister( CYLINDERHIGHREGISTER );
//
// Command packet transfer...
// check status: must have BSY=0, DRQ=1 now
//
if ( ( ucStatus & ( ATABSY | ATADRQ ) ) != ATADRQ )
{
reg_cmd_info.ec = 52;
//
// command done
//
uiTransferDir = -1;
}
else
{
ulCount = ATAWriteDataRegister( cfp, uiCommandPacketByteCount >> 1 );
}
}
while ( 1 )
{
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
//
//wait for BSY to clear
//
if (!(ucStatus & ATABSY))
break;
}
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
//
// If data transfer
//
if (ucStatus & ATADRQ)
{
//
// Data transfer loop
//
while (1)
{
ucReason = ATAReadCommandRegister( SECTORCOUNTREGISTER );
//
// Device has set amount to transfer in these registers
//
ucLowCyl = ATAReadCommandRegister( CYLINDERLOWREGISTER );
ucHighCyl = ATAReadCommandRegister( CYLINDERHIGHREGISTER );
//
// write to memory buffer here and increment memory pointer by byte count
//
usByteCount = (ucHighCyl << 8) | ucLowCyl;
usWordCount = (usByteCount >> 1) + (usByteCount & 0x0001);
ulCount = ATAReadDataRegister(data_pointer,usWordCount);
ulTotalTransfered += ulCount;
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
if(!(ucStatus & (ATABSY | ATADRQ)))
{
break;
}
}
}
//
// Set IO, CD, DRY; Clear BSY, DRQ
//
while ( 1 )
{
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
ucReason = ATAReadCommandRegister( SECTORCOUNTREGISTER );
if (ucStatus & ATABSY)
{
}
else
{
//
// DRDY = 1 and DRQ = 0
//
if ((ucStatus & (ATADRDY | ATADRQ)) == ATADRDY)
//
// IO = 1, and CD = 1
//
if (ucReason & (CB_SC_P_IO | CB_SC_P_CD) == (CB_SC_P_IO | CB_SC_P_CD))
break;
}
}
ucStatus = ATAReadCommandRegister( STATUSREGISTER );
if ( reg_cmd_info.ec )
return 1;
else
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -