📄 ide_func.c
字号:
break;
case VERIFY10:
/* ATAPI Verify10 Command -> ATA READ VERIFY Command */
if( DevicePara[deviceNo].BigDrive == ENABLE ){
/* HDD BIG Drive */
ATACmd.reg01 = 0x00;
ATACmd.reg02 = pCmdBlock->commandBlock[8];
ATACmd.reg03 = pCmdBlock->commandBlock[5];
ATACmd.reg04 = pCmdBlock->commandBlock[4];
ATACmd.reg05 = pCmdBlock->commandBlock[3];
ATACmd.reg06 = 0x00;
}else{
/* HDD Drive */
ATACmd.reg01 = 0x00;
ATACmd.reg02 = pCmdBlock->commandBlock[8];
ATACmd.reg03 = pCmdBlock->commandBlock[5];
ATACmd.reg04 = pCmdBlock->commandBlock[4];
ATACmd.reg05 = pCmdBlock->commandBlock[3];
ATACmd.reg06 = pCmdBlock->commandBlock[2];
}
break;
case SEEK:
if( DevicePara[deviceNo].BigDrive == ENABLE ){
ATACmd.reg01 = 0x00;
ATACmd.reg02 = pCmdBlock->commandBlock[8];
ATACmd.reg03 = pCmdBlock->commandBlock[5];
ATACmd.reg04 = pCmdBlock->commandBlock[4];
ATACmd.reg05 = pCmdBlock->commandBlock[3];
ATACmd.reg06 = 0x00;
}else{
ATACmd.reg01 = 0x00;
ATACmd.reg02 = pCmdBlock->commandBlock[8];
ATACmd.reg03 = pCmdBlock->commandBlock[5];
ATACmd.reg04 = pCmdBlock->commandBlock[4];
ATACmd.reg05 = pCmdBlock->commandBlock[3];
ATACmd.reg06 = pCmdBlock->commandBlock[2];
}
break;
case START_STOP:
if( DevicePara[deviceNo].BigDrive == ENABLE ){
ATACmd.reg01 = 0x00;
ATACmd.reg02 = 0x00;
ATACmd.reg03 = 0x00;
ATACmd.reg04 = 0x00;
ATACmd.reg05 = 0x00;
ATACmd.reg06 = 0x00;
}else{
ATACmd.reg01 = 0x00;
ATACmd.reg02 = 0x00;
ATACmd.reg03 = 0x00;
ATACmd.reg04 = 0x00;
ATACmd.reg05 = 0x00;
ATACmd.reg06 = 0x00;
}
break;
default:
return STATUS_INVALID_PARAMETER;
}
driveSelect = SelectDeviceNo[deviceNo].MasterSlave; /* correspond to warning */
switch( pCmdBlock->commandBlock[0] )
{
case READ10:
case READ12:
if( DevicePara[deviceNo].BigDrive == ENABLE ){
if( transferMode == IDE_FUNC_DMA_MODE ){
ATACmd.reg07 = HDD_BIGDRV_READ;
}
else{
ATACmd.reg07 = READ_SECTOR_BIG;
}
driveSelect = SelectDeviceNo[deviceNo].MasterSlave | SEL_BIG_DRIVE;
}
else{
if( transferMode == IDE_FUNC_DMA_MODE ){
ATACmd.reg07 = READ_DMA;
}
else{
ATACmd.reg07 = READ_SECTOR;
}
driveSelect = SelectDeviceNo[deviceNo].MasterSlave;
}
break;
case WRITE10:
case WRITE12:
if( DevicePara[deviceNo].BigDrive == ENABLE ){
if( transferMode == IDE_FUNC_DMA_MODE ){
ATACmd.reg07 = HDD_BIGDRV_WRITE;
}
else{
ATACmd.reg07 = WRITE_SECTOR_BIG;
}
driveSelect = SelectDeviceNo[deviceNo].MasterSlave | SEL_BIG_DRIVE;
}
else{
if( transferMode == IDE_FUNC_DMA_MODE ){
ATACmd.reg07 = WRITE_DMA;
}
else{
ATACmd.reg07 = WRITE_SECTOR;
}
driveSelect = SelectDeviceNo[deviceNo].MasterSlave;
}
break;
case VERIFY10:
ATACmd.reg07 = READ_VERIFY;
if( DevicePara[deviceNo].BigDrive == ENABLE ){
driveSelect = SelectDeviceNo[deviceNo].MasterSlave | SEL_BIG_DRIVE;
}
else{
driveSelect = SelectDeviceNo[deviceNo].MasterSlave;
}
break;
case SEEK:
ATACmd.reg07 = SEEK_ATA;
if( DevicePara[deviceNo].BigDrive == ENABLE ){
driveSelect = SelectDeviceNo[deviceNo].MasterSlave | SEL_BIG_DRIVE;
}
else{
driveSelect = SelectDeviceNo[deviceNo].MasterSlave;
}
break;
case START_STOP:
if (( pCmdBlock->commandBlock[4] & 0x01 ) == 0x01) {
/* Start Bit */
/* IDLE Immediate Command */
ATACmd.reg07 = IDLE_IMMEDIATE;
} else {
/* Standby Immediate Command */
ATACmd.reg07 = STANDBY_IMMEDIATE;
}
if (( pCmdBlock->commandBlock[1] & 0x01) == 0x00 ) {
/* IF Immed bite is 0,Idle and the Standby command are specified. */
ATACmd.reg07 |= 0x02;
}
if( DevicePara[deviceNo].BigDrive == ENABLE ){
driveSelect = SelectDeviceNo[deviceNo].MasterSlave | SEL_BIG_DRIVE;
}
else{
driveSelect = SelectDeviceNo[deviceNo].MasterSlave;
}
break;
default:
break;
}
/* Issue ATA command */
return( ATA_IFATACommandOutA( SelectDeviceNo[deviceNo].portNumber, driveSelect,
DevicePara[deviceNo].PioMode, &ATACmd ) );
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATAPICommandSet
//
// description : Send ATAPI command to thespecified command.
//
// argument : USHORT deviceNo No. of the device that issues command
// UCHAR transferMode Data transfer mode(PIO/DMA)
// IDE_FUNCCMDPARA *pCmdBlock Command block
//
// return : LONG status 4Processing result
//
////////////////////////////////////////////////////////////////////////
*/
static LONG ATAPICommandSet( USHORT deviceNo, UCHAR transferMode, IDE_FUNCCMDPARA *pCmdBlock )
{
UCHAR i;
/* Command Block Copy */
for( i=0; i<0x0c; i++ ){
ATAPICmd[i] = pCmdBlock->commandBlock[i];
}
/* Check command group */
if( (ATAPICmd[0] & 0xE0) ){
/* Set group 0 sector address */
TransferLba = (ULONG)( ( ATAPICmd[2] * 0x1000000) + ( ATAPICmd[3] * 0x10000) +
( ATAPICmd[4] * 0x100) + ATAPICmd[5] );
}else{
/* Set sector address of group 1-7 */
TransferLba = (ULONG)( ( ATAPICmd[1] * 0x10000) + ( ATAPICmd[2] * 0x100) + ATAPICmd[3] );
}
TransferLba = TransferLba * 4;
/* Send ATAPI command */
return( ATA_IFAtapiCommandOutA( SelectDeviceNo[deviceNo].portNumber,
SelectDeviceNo[deviceNo].MasterSlave,
transferMode, DevicePara[deviceNo].PioMode, ATAPICmd ) );
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncCommandStop
//
// description : Interrupt the command that corresponds to the specified deivce
//
// argument : USHORT id Identifier of the upper layer
// USHORT deviceNo No. of the device.The command of this device is stopped.
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncCommandStop( USHORT id, USHORT deviceNo )
{
ULONG status;
/* DeviceNo Check */
if( deviceNo >= DeviceCnt ){
/* Parameter error */
return STATUS_INVALID_PARAMETER;
}
/* Check if the comamand is on executing */
if( CMDState[deviceNo].status != IDE_FUNC_CMD_EXEC ){
/* Parameter error */
return STATUS_SUCCESS;
}
/* Check the issue ID of the command. */
if( CMDState[deviceNo].id != id ){
/* Parameter error */
return IDE_FUNC_STATUS_CMD_EXEC;
}
/* check if it is executing DMA transfer */
if( DMAState[deviceNo].status == IDE_FUNC_DMA_EXEC ){
/* Get the DMA transfer status */
IDEDMA_IFGetTransferStatus( SelectDeviceNo[deviceNo].portNumber, &status );
/* Check if the H/W is operating */
if( status == IDEDMA_IF_EXEC ){
/* Stop DMA transfer */
IDEDMA_IFTransferStop( SelectDeviceNo[deviceNo].portNumber );
}
/* DMA PORT Unlock */
IDEDMA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
/* Check DMA status. */
if( status == IDEDMA_IF_COMP ){
/* The DMA state is set to the comp route. */
DMAState[deviceNo].status = IDE_FUNC_DMA_COMP;
}else{
/* Set DMA state to STOP */
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
}
}
/* Device Type Check */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncDMAStartA
//
// description : Start the DMA transfer with the specified device.
/
// argument : USHORT id Identifier of the upper layer
// USHORT deviceNo No. of the device that executing DMA transfer
// UCHAR transferMode UltraDma/MultiWordDma/PIO
// IDE_FUNCTRANPARA *pTranPara Transfer parameter
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncDMAStartA( USHORT id, USHORT deviceNo, UCHAR transferMode, IDE_FUNCTRANPARA *pTranPara )
{
LONG result;
UCHAR setTranMode;
ULONG transferSize;
/* 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 is running. */
return IDE_FUNC_STATUS_DMA_EXEC;
}
/* COMMAND STATE Check */
if( CMDState[deviceNo].status != IDE_FUNC_CMD_EXEC ){
/* executin gcommand */
return IDE_FUNC_STATUS_CMD_STOP;
}
/* Check the COMMAND ISSUE ID */
if( CMDState[deviceNo].id != id ){
/* Parameter error */
return IDE_FUNC_STATUS_CMD_EXEC;
}
IDEDMA_IFLockPort( SelectDeviceNo[deviceNo].portNumber );
/* Transfer Rate Set */
IDEDMA_IFSetTransferRate( SelectDeviceNo[deviceNo].portNumber, DevicePara[deviceNo].PioMode,
DevicePara[deviceNo].DmaMode, DevicePara[deviceNo].UltraMode );
/* DMA Transfer Start */
if( transferMode != IDEDMA_IF_PIO ){
if( DevicePara[deviceNo].UltraEnb == ENABLE ){
setTranMode = IDEDMA_IF_ULTRA;
transferSize = pTranPara->dataSize;
}else{
setTranMode = IDEDMA_IF_MULTI;
transferSize = pTranPara->dataSize;
}
}else{
setTranMode = IDEDMA_IF_PIO;
transferSize = pTranPara->dataSize;
}
/* DMA STATE EXEC Set */
DMAState[deviceNo].id = id;
DMAState[deviceNo].status = IDE_FUNC_DMA_EXEC;
result = IDEDMA_IFTransferStartA( SelectDeviceNo[deviceNo].portNumber,
pTranPara->direction, setTranMode, transferSize, TransferLba );
if( result == STATUS_SUCCESS ){
if( transferMode != IDEDMA_IF_PIO ){
pTranPara->dataSize = 0x00;
}else{
pTranPara->dataSize -= transferSize;
}
}else{
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
}
return result;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncDmaStop
//
// description : Stop the DMA transfer with the specified device.
//
// argument : USHORT id Identifier of the upper layer
// USHORT deviceNo No. of the device.The DMA transfer of this device is stopped.
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncDMAStop( USHORT id, USHORT deviceNo )
{
LONG result;
/* 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 under suspension */
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
return STATUS_SUCCESS;
}
/* Check ID During DMA starting */
if( DMAState[deviceNo].id != id ){
/* IDE DMA in operating */
return IDE_FUNC_STATUS_DMA_EXEC;
}
/* DMA Transfer Stop */
result = IDEDMA_IFTransferStop( SelectDeviceNo[deviceNo].portNumber );
if( result == STATUS_SUCCESS ){
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
IDEDMA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
}
return result;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncGetDMAStatus
//
// description : Get the DMA transfer state of the specified device.
//
// argument : USHORT id Identifier of the upper layer
// USHORT deviceNo No. of the device. The DMA transfer of this device is stopped.
// ULONG *pStatus Status memory field
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncGetDMAStatus( USHORT id, USHORT deviceNo, ULONG *pStatus )
{
LONG result;
ULONG status;
/* Device No. Check */
if( deviceNo >= DeviceCnt ){
/* Parameter error */
return STATUS_INVALID_PARAMETER;
}
/* Get DMA Transfer status */
result = IDEDMA_IFGetTransferStatus( SelectDeviceNo[deviceNo].portNumber, &status );
if(result != STATUS_SUCCESS ){
return result;
}
/* Status Check */
if( status == IDEDMA_IF_EXEC ){
/* DMA is operating */
*pStatus = IDEDMA_IF_EXEC;
}else{
/* ID Check */
if( DMAState[deviceNo].id != id ){
/* Mismatched ID */
/* STATUS Check */
if( status == IDEDMA_IF_COMP ){
/* DMA STATE COMP Set */
DMAState[deviceNo].status = IDE_FUNC_DMA_COMP;
/* Set to DMA Executing */
*pStatus = IDEDMA_IF_EXEC;
}else{
/* DMA State Check */
if( DMAState[deviceNo].status == IDE_FUNC_DMA_COMP ){
/* Set to DMA EXECUTING */
*pStatus = IDEDMA_IF_EXEC;
}else{
/* Set to DMA STOP */
*pStatus = IDEDMA_IF_STOP;
}
}
}else{
if( status == IDEDMA_IF_COMP ){
/* DMA STATE STOP Set */
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
/* DMA Complete Set */
*pStatus = IDEDMA_IF_COMP;
}else{
/* DMA STATE Check */
if( DMAState[deviceNo].status == IDE_FUNC_DMA_COMP ){
/* DMA STATE STOP Set */
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
/* DMA Complete Set */
*pStatus = IDEDMA_IF_COMP;
}else{
*pStatus = status;
}
}
}
}
if( DMAState[deviceNo].status == IDE_FUNC_DMA_STOP ){
IDEDMA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
}
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncSoftDataTransfer
//
// description : Execut PIO data transfer on the specified device.
//
// argument : USHORT id Identifier of the upper layer
// USHORT deviceNo No. of the device that executing DMA transfer
// UCHAR transferMode UltraDma/MultiWordDma/PIO
// IDE_FUNCTRANPARA *pTranPara Transfer parameter
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncSoftDataTransfer( USHORT id, USHORT deviceNo, UCHAR transferMode, IDE_FUNCTRANPARA *pTranPara )
{
LONG result;
ATA_IFTRANPARA ataFuncTranPara;
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;
}
/* COMMAND State Check */
if( CMDState[deviceNo].status != IDE_FUNC_CMD_EXEC ){
/* Command is not executed. */
return IDE_FUNC_STATUS_CMD_STOP;
}
/* Check Command running ID. */
if( CMDState[deviceNo].id != id ){
/* Parameter error */
return IDE_FUNC_STATUS_CMD_EXEC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -