📄 ide_func.c
字号:
/* Get ATA Status */
result = ATA_IFGetStatus( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave, &status );
if(result != STATUS_SUCCESS ){
return result;
}
/* STATUS Check */
if( (status.status & 0x01) ){
/* ERROR COMPLETE */
return IDE_FUNC_STATUS_ERROR;
}
if( (status.status & 0x80) ){
/* DEVICE BSY */
return IDE_FUNC_STATUS_BSY;
}
if( !(status.status & 0x08) ){
/* DRQ negate */
return IDE_FUNC_STATUS_NOT_READY;
}
if( SelectDeviceNo[deviceNo].type == IDE_FUNC_HDD ){
/* Hard disk */
ataFuncTranPara.direction = pTranPara->direction;
ataFuncTranPara.dataPointer = pTranPara->dataPointer;
ataFuncTranPara.transfersize = pTranPara->dataSize;
}
else{
/* Not hard disk */
/* Check the transfer direction */
if( (status.IntReasen & 0x02) ){
if( pTranPara->direction != ATA_IF_IDE_IN ){
/* Parameter error */
return STATUS_INVALID_PARAMETER;
}
}else{
if( pTranPara->direction != ATA_IF_IDE_OUT ){
/* Parameter error */
return STATUS_INVALID_PARAMETER;
}
}
ataFuncTranPara.direction = pTranPara->direction;
ataFuncTranPara.dataPointer = pTranPara->dataPointer;
ataFuncTranPara.transfersize = status.transfersize;
}
/* Start PIO data transmission */
result = ATA_IFPIODataTransfer( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave, &ataFuncTranPara );
if( result == STATUS_SUCCESS ){
/* Set the number of data actually transfered(number of bytes) */
pTranPara->transferSize = (ULONG)( status.transfersize );
}
return result;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncGetStatus
//
// description : Get the status information of the specified device
//
// argument : USHORT id Identifier of the upper layer
// USHORT deviceNo No. of the device that executing DMA transfer
// UCHAR *pStatus Memory for saving the status
// UCHAR *pSenseData Memory for saving resuest sense data
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncGetStatus( USHORT id, USHORT deviceNo, ULONG *pStatus,ULONG *pTrasferSize, UCHAR *pSenseData )
{
LONG result;
ATA_IFSTATUS status;
/* Device No. Check */
if( deviceNo >= DeviceCnt ){
/* Parameter error */
return STATUS_INVALID_PARAMETER;
}
/* DMA STATE Check */
if( DMAState[deviceNo].status == IDE_FUNC_DMA_EXEC ){
/* IDE DMA in operating */
return IDE_FUNC_STATUS_DMA_EXEC;
}
/* Check the Command Executing ID */
if( CMDState[deviceNo].id != id ){
if( CMDState[deviceNo].status != IDE_FUNC_CMD_STOP ){
/* Parameter error */
return IDE_FUNC_STATUS_CMD_EXEC;
}else{
*pStatus = IDE_FUNC_CMD_STOP;
return STATUS_SUCCESS;
}
}
/* Check the Command STATE */
if( CMDState[deviceNo].status != IDE_FUNC_CMD_EXEC ){
/* Check Command STOP or COMPLETE */
if( CMDState[deviceNo].status == IDE_FUNC_CMD_STOP ){
/* Set to Command Stop status */
*pStatus = IDE_FUNC_CMD_STOP;
return STATUS_SUCCESS;
}else{
/* Command State STOP Set */
CMDState[deviceNo].status = IDE_FUNC_CMD_STOP;
/* Set Command Complete status */
*pStatus = IDE_FUNC_CMD_COMP;
return STATUS_SUCCESS;
}
}
/* Get ATA Status */
result = ATA_IFGetStatus( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave, &status );
*pTrasferSize = status.transfersize;
if( result != STATUS_SUCCESS ){
return result;
}
if( ( status.busStatus & IDE_FUNC_DMAREQ ) ){
*pStatus = IDE_FUNC_TRAN_READY;
return STATUS_SUCCESS;
}
/* STATUS Check */
if( ( status.status & 0x01 ) ){
/* ERROR Complete */
CMDState[deviceNo].status = IDE_FUNC_CMD_STOP;
/* Device Type Check */
if( SelectDeviceNo[deviceNo].type == IDE_FUNC_HDD ){
/* ERROR CODE Set */
*pStatus = ATAErrorStatusSet( status.error );
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return STATUS_SUCCESS;
}else{
/* Device Error Set */
*pStatus = IDE_FUNC_DEVICE_ERR;
/* Get Requset Sense Data */
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return( ATAPIRequestSense( deviceNo, pSenseData ) );
}
}
if( ( status.status & 0x80 ) ){
/* STATUS BSY */
*pStatus = IDE_FUNC_BSY;
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return STATUS_SUCCESS;
}
if( ( status.status & 0x08 ) ){
if( SelectDeviceNo[deviceNo].type == IDE_FUNC_HDD ){
/* ATA device */
*pStatus = IDE_FUNC_TRAN_READY;
}
else{
/* Other than ATA device */
if( (status.IntReasen & 0x02) ){
/* Assert DRQ */
*pStatus = IDE_FUNC_PIOIN_READY;
}else{
*pStatus = IDE_FUNC_PIOOUT_READY;
}
}
return STATUS_SUCCESS;
}
/* Command Complete */
if( DMAState[deviceNo].status != IDE_FUNC_DMA_EXEC ){
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
IDEDMA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
}
/* Command Complete */
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
CMDState[deviceNo].status = IDE_FUNC_CMD_STOP;
*pStatus = IDE_FUNC_CMD_COMP;
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATAErrorStatusSet
//
// description : Get HDD error code
//
// argument : UCHAR ERROR the contents of ATA ERROR Register
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
static LONG ATAErrorStatusSet( UCHAR error )
{
if( (error & 0x80) ){
return IDE_FUNC_CRC_ERR;
}
if( (error & 0x40) ){
return IDE_FUNC_WP_ERR;
}
if( (error & 0x20) ){
return IDE_FUNC_MC_ERR;
}
if( (error & 0x10) ){
return IDE_FUNC_IDNF_ERR;
}
if( (error & 0x08) ){
return IDE_FUNC_MCR_ERR;
}
if( (error & 0x02) ){
return IDE_FUNC_NM_ERR;
}
if( (error & 0x04) ){
return IDE_FUNC_ABORT_ERR;
}
return IDE_FUNC_ABORT_ERR;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATAPIRequestSense
//
// description : Get ATAPI request sense data
//
// argument : USHORT deviceNo No. of the device from which to get the request sense data
// UCHAR *pSenseDara Memory field of the request sense data
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
static LONG ATAPIRequestSense( USHORT deviceNo, UCHAR *pSenseData )
{
LONG result;
UCHAR i;
ATA_IFTRANPARA ataFuncTranPara;
ATA_IFSTATUS status;
/* ATAPI Command Block Set */
for( i=0; i<0x0c; i++ ){
ATAPICmd[i] = 0x00;
}
ATAPICmd[0] = 0x03;
ATAPICmd[4] = 0x20;
/* Send ATAPI Command */
result = ATA_IFAtapiCommandOutA( SelectDeviceNo[deviceNo].portNumber,
SelectDeviceNo[deviceNo].MasterSlave,
ATA_IF_PIO, DevicePara[deviceNo].PioMode, ATAPICmd );
if( result != STATUS_SUCCESS ){
return result;
}
/* Waiting DRQ assert*/
while(1){
/* Get ATA STATUS */
ATA_IFGetStatus( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave, &status );
if( (status.status & 0x08) ){
break;
}
}
/* ATA PIO data transfer */
ataFuncTranPara.direction = ATA_IF_IDE_IN;
ataFuncTranPara.dataPointer = (ULONG)( pSenseData );
ataFuncTranPara.transfersize = status.transfersize;
result = ATA_IFPIODataTransfer( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave, &ataFuncTranPara );
if( result != STATUS_SUCCESS ){
return result;
}
/* Waiting for BSY negate */
while(1){
/* Get ATA STATUS */
ATA_IFGetStatus( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave, &status );
if( !(status.status & 0x80) ){
break;
}
}
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncNotifyDmaComp
//
// description : Process IDEDMA CALLBACK
//
//
// argument : ULONG portNumber The port No. When DMA completed
// ULONG lReserve1 Reserved
// ULONG VOID *pReserve Reserved
//
// return : none
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncNotifyDmaComp(ULONG portNumber, ULONG lReserve1, VOID *pReserve )
{
USHORT i;
/* CALL BACK Pointer Check */
for( i=0; i<DeviceCnt; i++ ){
if( SelectDeviceNo[i].portNumber == portNumber ){
if( DMAState[i].status == IDE_FUNC_DMA_EXEC ){
/* DMA STATE COMPLETE Set */
DMAState[i].status =IDE_FUNC_DMA_COMP;
break;
}
}
}
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncNotifyIntrq
//
// description : Process ATA INTRQ CALL BACK
//
// argument : ULONG portNumber The port No. When INTRQ completed
// ULONG lReserve1 Reserved
// ULONG VOID *pReserve Reserved
//
// return : none
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncNotifyIntrq( ULONG portNumber, ULONG lReserve1, VOID *pReserve )
{
USHORT i;
/* CALL BACK Pointer Check */
for( i=0; i<DeviceCnt; i++ ){
if( SelectDeviceNo[i].portNumber == portNumber ){
if( CMDState[i].status == IDE_FUNC_CMD_EXEC ){
/* CALL BACK */
break;
}
}
}
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncXferRateSet
//
// description : Set the data transfer mode of the specified device
//
// argument : USHORT id Identifier
// USHORT deviceNo The No. of the device that deletes callback
//
// return : none
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncXferRateSet( USHORT id, USHORT deviceNo )
{
LONG result;
result = ATA_IFLockPort( SelectDeviceNo[deviceNo].portNumber );
if( result != STATUS_SUCCESS ){
return result;
}
/* Device PIO Transfer Mode Set */
ATACmd.reg01 = 0x03;
ATACmd.reg02 = 0x08 | DevicePara[deviceNo].PioMode;
ATACmd.reg07 = SET_FEATURS;
result = ATA_IFATACommandOutA( SelectDeviceNo[deviceNo].portNumber,
SelectDeviceNo[deviceNo].MasterSlave,
ATA_IF_PIO_MODE2, &ATACmd );
if( result != STATUS_SUCCESS ){
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return result;
}
/* BSY negate wait */
result = StatusWait( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave );
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return STATUS_SUCCESS;
}
if( DevicePara[deviceNo].UltraEnb == ENABLE){
/* Device UltraDMA Mode Set */
ATACmd.reg01 = 0x03;
ATACmd.reg02 = 0x40 | DevicePara[deviceNo].UltraMode;
ATACmd.reg07 = SET_FEATURS;
result = ATA_IFATACommandOutA( SelectDeviceNo[deviceNo].portNumber,
SelectDeviceNo[deviceNo].MasterSlave,
ATA_IF_PIO_MODE2, &ATACmd );
if( result != STATUS_SUCCESS ){
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return result;
}
/* BSY negate wait */
result = StatusWait( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave );
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return STATUS_SUCCESS;
}
}else{
/* Device MultiWordDma Mode Set */
ATACmd.reg01 = 0x03;
ATACmd.reg02 = 0x20 | DevicePara[deviceNo].DmaMode;
ATACmd.reg07 = SET_FEATURS;
result = ATA_IFATACommandOutA( SelectDeviceNo[deviceNo].portNumber,
SelectDeviceNo[deviceNo].MasterSlave,
ATA_IF_PIO_MODE2, &ATACmd );
if( result != STATUS_SUCCESS ){
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return result;
}
/* BSY negate wait */
result = StatusWait( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave );
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return STATUS_SUCCESS;
}
}
ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncXferRateChange
//
// description : Modify the transfer mode of the specified device
//
// argument :
//
// return :
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncXferRateChange( USHORT deviceNo, IDE_FUNCXFERPARA *pXferPara )
{
DevicePara[deviceNo].PioMode = pXferPara->PIOMode;
DevicePara[deviceNo].UltraMode = pXferPara->ultraDMAMode;
DevicePara[deviceNo].DmaMode = pXferPara->multiDMAMode;
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncGetInterrupt
//
// description : Get the interrupt factor
//
// argument :
//
// return :
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncGetInterrupt( UCHAR mainIntEnb, UCHAR *pStatus )
{
ATA_IFGetInterrupt( mainIntEnb, &IntStat);
if( IntStat.ide_int_stat & 0x80 ){
*pStatus |= IDE_FUNC_INT_REGCMP;
}
if( IntStat.ide_int_stat & 0x40 ){
*pStatus |= IDE_FUNC_INT_REGERR;
}
if( IntStat.ide_int_stat & 0x20 ){
*pStatus |= IDE_FUNC_INT_SEQWRREGCMP;
}
if( IntStat.ide_int_stat & 0x10 ){
*pStatus |= IDE_FUNC_INT_CMPINTRQ;
}
if( IntStat.ide_int_stat & 0x04 ){
*pStatus |= IDE_FUNC_INT_IDECMP;
}
if( IntStat.ide_int_stat & 0x02 ){
*pStatus |= IDE_FUNC_INT_DETECTINTRQ;
}
if( IntStat.ide_int_stat & 0x01 ){
*pStatus |= IDE_FUNC_INT_DETECTTERM;
}
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -