⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ata_atapiif.c

📁 epson usb2.0 控制芯片 S1R72V05 固件程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -