📄 ata_atapiif.c
字号:
/*
* description : ATA/ATAPI Interface
* Maker : Hideyuki Nekoshima
* Copyright : (C)2003,SEIKO EPSON Corp. All Rights Reserved.
* description : ATA/ATAPI Interface
* Maker : Hideyuki Nekoshima
* Copyright : (C)2003,SEIKO EPSON Corp. All Rights Reserved.
*/
#include "SPRDEF.h"
#include "SPRSTS.h"
#include "OSCall.h"
#include "ATA_ATAPIIF.h"
#include "Reg72V05.h"
#define BIT_ON 0x01 /* Bit */
#define BIT_OFF 0x00 /* Bit */
#define PORT_EXEC 0x01 /* PORT Execution */
#define PORT_STOP 0x00 /* PORT STOP */
#define DEVICE_RESET 0x04 /* DEVICE RESET */
#define ATAPI_CMD 0xA0 /* ATAPI Packet Command */
#define CHECK_SELECT_DRIVE 0xFE /* Master/Slave Select Check */
#define CHECK_BIG_DRIVE 0x01 /* Big Drive Select Check */
#define DIRECT_B(a) *(unsigned char *)&(a)
static UCHAR PortLock[ATA_IF_MAX_PORT];
static UCHAR PortExecFlag[ATA_IF_MAX_PORT]; /* PORT Execution Flag */
Inline void SEQ_WR_REG_SET( UCHAR adr, UCHAR val );
Inline void SEQ_WR_GO( void );
Inline void SEQ_WR_REG_CMP_WAIT( void );
Inline void SEQ_WR_REG_CMP_CLEAR( void );
Inline UCHAR RD_REG_VAL_L( UCHAR adr );
Inline UCHAR RD_REG_VAL_H( UCHAR adr );
Inline void WR_REG_VAL_L( UCHAR adr, UCHAR val );
Inline void WR_REG_VAL_H( UCHAR adr, UCHAR val );
Inline void RD_REG_SET( UCHAR adr );
Inline void RD_GO( void );
Inline void RD_REG_CMP_WAIT( void );
Inline void REG_CMP_CLEAR( void );
Inline LONG REG_RMOD_SET( UCHAR );
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFReset
//
// description : Initialize ATA/ATAPI Interface Module.
//
// : Initialize the internal varibles of ATA/ATAPI Interface Module,
// then initilalize the Hardware.
//
// argument : none
//
// return : LONG status Processing result
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFReset( void )
{
UCHAR i;
/* Register Initialize */
/* Activate IDE Bus */
RegSet( REG08_IDE_Config_1, BIT_ActiveIDE );
/* XHRESET Asserted */
RegSet( REG08_IDE_Config_0, BIT_IDE_BusReset );
while( RegRead( REG08_IDE_Config_0 ) & BIT_IDE_BusReset ){
;
}
OS_DlyTsk( 2 ); /* 2ms Delay */
/* InActivated IDE Bus */
RegClear( REG08_IDE_Config_1, BIT_ActiveIDE );
RegWrite( REG08_IDE_Rmod, 0x00 ); /* IDE Register Mode */
/* PORT Execution Flag Clear */
for( i = 0; i < ATA_IF_MAX_PORT; i++ ){
PortLock[i] = ATA_IF_PORT_UNLOCK;
PortExecFlag[i] = PORT_STOP;
}
/* Complete */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFOpen
//
// description : Open ATA/ATAPI Interface Module.
//
// Open ATA/ATAPI Interface Module,enter the usable state.
// In the state of not opened,can not process the API of the Module .
//
// argument : non
//
// return : LONG status Processing result
//
// flag : UCHAR OpenFlag PASS Interface Module usable status flag.
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFOpen( void )
{
UCHAR i;
/* PORT Execution Flag Clear */
for( i = 0; i < ATA_IF_MAX_PORT; i++ ){
PortLock[i] = ATA_IF_PORT_UNLOCK;
PortExecFlag[i] = PORT_STOP;
}
/* Clear the interrupt factor(IDE Interrupts) */
RegWrite( REG08_MainIntStat, BIT_IDE_IntStat );
/* Clear the interrupt factor(IDE Interrupt Status) */
RegWrite( REG08_IDE_IntStat,
( BIT_IDE_RegCmp |
BIT_IDE_RegErr |
BIT_IDE_SeqWrRegCmp |
BIT_CompleteINTRQ |
BIT_IDE_Cmp |
BIT_DetectINTRQ |
BIT_DetectTerm
) );
/* Enable interrupts(Enable IDE Interrupts) */
RegSet( REG08_MainIntEnb, BIT_EnIDE_IntStat );
/* Complete */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFLockPort
//
// description : Lock the specified port.
//
// : The following function has no meaning as long
// as the port is not locked.
//
// argument : USHORT portNumber The port No to be locked
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFLockPort( USHORT portNumber )
{
if( PortLock[portNumber] == ATA_IF_PORT_LOCK ){
/* The specified port is already locked. */
return STATUS_LOCKED_PORT;
}
PortLock[portNumber] = ATA_IF_PORT_LOCK;
/* Activate IDE Bus */
RegSet( REG08_IDE_Config_1, BIT_ActiveIDE );
// Corresponding to IDE SWAP(SWAP Bit is on for default)
#ifdef IDE_SWAP_BIT_OFF
RegClear( REG08_IDE_Config_1, BIT_Swap_None );
#else
RegSet( REG08_IDE_Config_1, BIT_Swap_None );
#endif
/* Compelte */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFUnlockPort
//
// description : Unlock the specified port.
// : When the port is released, the functions follow
// is worthless.
//
// argument : USHORT portNumber The port No to be unlocked
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFUnlockPort( USHORT portNumber )
{
if( PortLock[portNumber] == ATA_IF_PORT_UNLOCK ){
/* The specified port is not locked. */
return STATUS_UNLOCK_PORT;
}
if( PortExecFlag[portNumber] == PORT_EXEC ){
/* the specified port is in operating */
return STATUS_EXECUTION_PORT;
}
PortLock[portNumber] = ATA_IF_PORT_UNLOCK;
/* Compelte */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFSelResetDevice
//
// description : Reset Specified device.
//
// : Reset Specified device.
// After sending the reset,return to the upper layer at once.
//
// argument : USHORT portNumber The Port No that the device is connected
// USHORT selectDevice Master/Slave selection
//
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFSelResetDevice( USHORT portNumber, UCHAR selectDevice )
{
UCHAR i;
if( PortLock[portNumber] == ATA_IF_PORT_UNLOCK ){
/* The specified port is not locked. */
return STATUS_UNLOCK_PORT;
}
if( selectDevice != ATA_IF_MASTER && selectDevice != ATA_IF_SLAVE ){
/* Select Device Parameter Error */
return STATUS_INVALID_PARAMETER;
}
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/* Reset Device Select(Master/Slave)*/
/*----------------------------------------------------------------------*/
/* SRST Bit Set */
/*----------------------------------------------------------------------*/
SEQ_WR_REG_SET( IDE_CS06, selectDevice );
/* Device Reset (SRST) */
SEQ_WR_REG_SET( IDE_CS16, DEVICE_RESET );
SEQ_WR_GO(); /* IDE Sequence Write Go */
SEQ_WR_REG_CMP_WAIT(); /* Waiting for the write operation complete */
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/*----------------------------------------------------------------------*/
OS_DlyTsk( 1 ); /* 1ms(SRST is actually clear after 5 micro seconds. ) */
/*----------------------------------------------------------------------*/
/* SRST Bit Clear */
/*----------------------------------------------------------------------*/
SEQ_WR_REG_SET( IDE_CS06, selectDevice );
/* Device Reset (SRST) */
SEQ_WR_REG_SET( IDE_CS16, 0x00 );
SEQ_WR_GO(); /* IDE Sequence Write Go */
SEQ_WR_REG_CMP_WAIT(); /* waiting for the Write operation complete */
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/*----------------------------------------------------------------------*/
OS_DlyTsk( 2 ); /* 2ms(delay after SRST is cleared) */
for( i = 0; i < ATA_IF_MAX_PORT; i++ ){
PortExecFlag[i] = PORT_STOP;
}
return STATUS_SUCCESS; /* Complete */
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFATACommandOutA
//
// description : send ATA command
//
// : Send the ATA command to specified device.
// After sending the command, the control return to the upper layer at once.
// Return error when the specified port is in operating.
//
// argument : USHORT portNumber The port No that the device is connected.
// UCHAR selectDevice Master/Slave and BigDrive selection
// UCHAR pioMode PIOtransfer mode
// ATA_IFATACMD *pATAIFATACmd ATA command flag.
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFATACommandOutA( USHORT portNumber, UCHAR selectDevice, UCHAR pioMode, ATA_IFATACMD *pATAIFATACmd )
{
LONG result;
if( PortLock[portNumber] == ATA_IF_PORT_UNLOCK ){
/* The specified port is not locked. */
return STATUS_UNLOCK_PORT;
}
if( PortExecFlag[portNumber] == PORT_EXEC ){
/* The specified port is in operating */
return STATUS_EXECUTION_PORT;
}
if( (selectDevice&CHECK_SELECT_DRIVE) != ATA_IF_MASTER &&
(selectDevice&CHECK_SELECT_DRIVE) != ATA_IF_SLAVE ){
/* Select Device Parameter Error */
return STATUS_INVALID_PARAMETER;
}
/*
// Because the SWAP bit is removed fsRevives SWAP bit
// For IDE SWAP(SWAP Bit is ON by default.)
*/
#ifdef IDE_SWAP_BIT_OFF
/* Swap None */
RegClear( REG08_IDE_Config_1, BIT_Swap_None );
#endif
/* ATA Register Access Cycle Set */
result = REG_RMOD_SET( pioMode );
if( result != STATUS_SUCCESS ){
return result;
}
PortExecFlag[portNumber] = PORT_EXEC; /* ATA/ATAPI PORT is in operating */
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/* Device Select (Master/Slave) */
SEQ_WR_REG_SET( IDE_CS06, (selectDevice & CHECK_SELECT_DRIVE) );
if( (selectDevice & CHECK_BIG_DRIVE) ){
/* Big Drive Command Out */
SEQ_WR_REG_SET( IDE_CS02, pATAIFATACmd->BigDriveReg02 );
SEQ_WR_REG_SET( IDE_CS03, pATAIFATACmd->BigDriveReg03 );
SEQ_WR_REG_SET( IDE_CS04, pATAIFATACmd->BigDriveReg04 );
SEQ_WR_REG_SET( IDE_CS05, pATAIFATACmd->BigDriveReg05 );
SEQ_WR_REG_SET( IDE_CS02, pATAIFATACmd->reg02 );
SEQ_WR_REG_SET( IDE_CS03, pATAIFATACmd->reg03 );
SEQ_WR_REG_SET( IDE_CS04, pATAIFATACmd->reg04 );
SEQ_WR_REG_SET( IDE_CS05, pATAIFATACmd->reg05 );
SEQ_WR_REG_SET( IDE_CS07, pATAIFATACmd->reg07 );
}else{
/* Nomal Drive Command Out */
SEQ_WR_REG_SET( IDE_CS01, pATAIFATACmd->reg01 );
SEQ_WR_REG_SET( IDE_CS02, pATAIFATACmd->reg02 );
SEQ_WR_REG_SET( IDE_CS03, pATAIFATACmd->reg03 );
SEQ_WR_REG_SET( IDE_CS04, pATAIFATACmd->reg04 );
SEQ_WR_REG_SET( IDE_CS05, pATAIFATACmd->reg05 );
SEQ_WR_REG_SET( IDE_CS06, selectDevice | ( pATAIFATACmd->reg06 & 0x0F ) );
SEQ_WR_REG_SET( IDE_CS07, pATAIFATACmd->reg07 );
}
SEQ_WR_GO(); /* IDE Sequence Write Go */
SEQ_WR_REG_CMP_WAIT(); /* Waiting for the end of write operation*/
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/* Complete */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFAtapiCommandOutA
//
// description : Send the ATAPI command
//
// : Send the ATAPI command to specified device.
// After sending the command, the control return to the upper layer at once.
// Return error when the specified port is in operating.
//
// argument : USHORT portNumber The port No that the device is connected.
// UCHAR selectDevice Master/Slave and BigDrive selection
// UCHAR transferMode DMA/PIO transfer selection
// UCHAR pioMode PIOtransfer mode
// UCHAR *pATAIFAtapiCmd ATAPI command block
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFAtapiCommandOutA( USHORT portNumber, UCHAR selectDevice, UCHAR transferMode, UCHAR pioMode, UCHAR *pATAIFAtapiCmd )
{
UCHAR i;
LONG result;
ATA_IFSTATUS status;
if( PortLock[portNumber] == ATA_IF_PORT_UNLOCK ){
/* The specified port is not locked. */
return STATUS_UNLOCK_PORT;
}
if( PortExecFlag[portNumber] == PORT_EXEC ){
/* The specified port is in operating */
return STATUS_EXECUTION_PORT;
}
if( selectDevice != ATA_IF_MASTER && selectDevice != ATA_IF_SLAVE ){
/* Select Device Parameter Error */
return STATUS_INVALID_PARAMETER;
}
/*
// Because the SWAP bit is removed Revives SWAP bit
// For IDE SWAP(SWAP Bit is ON by default.)
*/
#ifdef IDE_SWAP_BIT_OFF
/* Swap None */
RegClear( REG08_IDE_Config_1, BIT_Swap_None );
#endif
/* ATA Register Access Cycle Set */
result = REG_RMOD_SET( pioMode );
if( result != STATUS_SUCCESS ){
return result;
}
PortExecFlag[portNumber] = PORT_EXEC; /* ATA/ATAPI PORT in executing */
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
SEQ_WR_REG_SET( IDE_CS06, selectDevice );
if( transferMode == ATA_IF_PIO ){
SEQ_WR_REG_SET( IDE_CS01, ATA_IF_PIO );
}else{
SEQ_WR_REG_SET( IDE_CS01, ATA_IF_DMA );
}
/* ATAPI Packet Command Set*/
SEQ_WR_REG_SET( IDE_CS02, 0x00 );
SEQ_WR_REG_SET( IDE_CS03, 0x00 );
SEQ_WR_REG_SET( IDE_CS04, 0xFF );
SEQ_WR_REG_SET( IDE_CS05, 0xFF );
SEQ_WR_REG_SET( IDE_CS07, ATAPI_CMD );
SEQ_WR_GO(); /* IDE Sequence Write Go */
SEQ_WR_REG_CMP_WAIT(); /* Waiting for the end of write operation */
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/* WAIT DRQ */
REG_CMP_CLEAR(); /* Interrupt Status Clear */
status.status = RD_REG_VAL_L( IDE_CS16 );/* Alternate Status register */
REG_CMP_CLEAR(); /* Interrupt Status Clear */
while( !( status.status & 0x08 ) )
{
status.status = RD_REG_VAL_L( IDE_CS16 );/* Alternate Status register */
REG_CMP_CLEAR(); /* Interrupt Status Clear */
}
for( i = 0; i < 6 ; i++ ){
// For IDE SWAP(SWAP Bit is ON by default.)
#ifdef IDE_SWAP_BIT_OFF
RegWrite( REG08_IDE_SeqWrRegAdrs, IDE_CS00 );
RegWrite( REG08_IDE_SeqWrRegValue, *pATAIFAtapiCmd++ );
RegWrite( REG08_IDE_SeqWrRegAdrs, IDE_CS00 );
RegWrite( REG08_IDE_SeqWrRegValue, *pATAIFAtapiCmd++ );
#else
RegWrite( REG08_IDE_SeqWrRegAdrs, IDE_CS00 );
RegWrite( REG08_IDE_SeqWrRegValue, *pATAIFAtapiCmd++ );
RegWrite( REG08_IDE_SeqWrRegAdrs, IDE_CS00 );
RegWrite( REG08_IDE_SeqWrRegValue, *pATAIFAtapiCmd++ );
#endif
}
SEQ_WR_GO(); /* IDE Sequence Write Go */
SEQ_WR_REG_CMP_WAIT(); /* Waiting of the end of write operation */
SEQ_WR_REG_CMP_CLEAR(); /* Interrupt Status Clear */
/* Complete */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: ATA_IFGetStatus
//
// description : Get the ATA status
//
// : Get the ATA status of the specified device.
//
// argument : USHORT portNumber The port No that the device is connected.
// UCHAR selectDevice Master/Slave and BigDrive selection
// ATA_IFSTATUS *pATAIFStatus Area for saving status
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG ATA_IFGetStatus( USHORT portNumber, UCHAR selectDevice, ATA_IFSTATUS *pATAIFStatus )
{
if( PortLock[portNumber] == ATA_IF_PORT_UNLOCK ){
/* The specified port is not locked. */
return STATUS_UNLOCK_PORT;
}
if( selectDevice != ATA_IF_MASTER && selectDevice != ATA_IF_SLAVE ){
/* Select Device Parameter Error */
return STATUS_INVALID_PARAMETER;
}
REG_CMP_CLEAR(); /* Interrupt Status Clear */
// For IDE SWAP(SWAP Bit is ON by default.)
#ifdef IDE_SWAP_BIT_OFF
WR_REG_VAL_L( IDE_CS06, selectDevice );/* Device/Head Register */
#else
WR_REG_VAL_H( IDE_CS06, selectDevice );/* Device/Head Register */
#endif
REG_CMP_CLEAR(); /* Interrupt Status Clear */
// For IDE SWAP(SWAP Bit is ON by default.)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -