www.pudn.com > File_SD_OS.rar > IDE.C


/****************************************Copyright (c)************************************************** 
**                               广州周立功单片机发展有限公司 
**                                     研    究    所 
**                                        产品一部  
** 
**                                 http://www.zlgmcu.com 
** 
**--------------文件信息-------------------------------------------------------------------------------- 
**文   件   名: IDE.c 
**创   建   人: 周立山 
**最后修改日期:  
**描        述: CF卡操作程序。使用到接口函数: 
**				void 	SYS_BusIni(void);			//ATA总线初始化函数 
**				void  	SYS_IdeHardReset(void);		//硬件复位 
**				uint8 	SYS_HaveCard(void);			//控测CF卡是否存在 
**				 
**              GetData()							//读数据寄存器 
**				SetData(x)							//写数据寄存器 
**				GetERR()							//读错误寄存器 
**				SetFeature(x)						//写特征寄存器 
**				GetSECCNT()							//读扇区计数寄存器 
**				SetSECCNT(x)						//写扇区计数寄存器 
**				GetSector()							//读扇区寄存器 
**				SetSector(x)						//写扇区寄存器 
**				GetCylinderLow()					//读柱面低8位寄存器 
**				SetCylinderLow(x)					//写柱面低8位寄存器 
**				GetCylinderHigh()					//读柱面高8位寄存器 
**				SetCylinderHigh(x)					//写柱面高8位寄存器 
**				GetDeviceHead()						//读设备磁头寄存器 
**				SetDeviceHead(x)					//写设备磁头寄存器 
**				GetStatus()							//读状态寄存器 
**				SetCommand(x)						//写命令寄存器 
**				GetAStatus()						//读辅助状态寄存器 
**				SetControl(x)						//写控制寄存器 
**--------------历史版本信息---------------------------------------------------------------------------- 
** 创建人: 周立山 
** 版  本: v1.0  
** 日 期:  
** 描 述:  
** 
**--------------当前版本修订------------------------------------------------------------------------------ 
** 修改人:  
** 日 期: 
** 描 述: 
** 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
#include "config.h" 
 
 
#ifdef UCOSII 
OS_EVENT *CFIDESem;				/*定义一个信号事件*/ 
#endif 
 
 
uint8		ATA_DevReg ;		/*设备磁头寄存器值,通过该寄存器可以确定*/ 
ATADEVICE 	ATA[MAX_DEVICE];	/*设备识别信息识别结构,及设备的状态*/  
 
 
/********************************************************************************************************* 
** 函数名称: ATA_GetStatus					所在文件:IDE.C 
** 功能描述: 读取ATA状态寄程器 
** 输   入: Status,存放状态值的变量指针 
** 输   出: 无 
** 全局变量: THIS_DEVICE,当前选中的设备 
**			 ATA,设备信息数据结构 
** 调用模块: GetAStatus(),读辅助状态寄存器 
**			 GetStatus(),读状态寄存器 
**			 GetERR(),读错误寄存器 
********************************************************************************************************/ 
void ATA_GetStatus(uint8 *Status) 
{	 
	if(SYS_HaveCard())				  
	{	 
		GetAStatus();							/*读助状态寄存器不作处理,以保证读状态寄存器返回有效的值*/ 
		*Status = (uint8)GetStatus();			/*读取ATA设备状态*/ 
 
		if((*Status)&ATA_STAT_REG_BSY)							/*设备状态寄存器BSY位为1,其它位无效*/ 
		{ 
			*Status = ATA_STAT_REG_BSY;							/*BSY位为1其它位无效,屏蔽其它位*/ 
			ATA[THIS_DEVICE].ERRCODE = CARD_IS_TRUE;			/*清错误码率代码*/ 
		} 
		else													/*设备不忙*/ 
		{ 
			if((*Status) & ATA_STAT_REG_ERR)					/*设备是否出错*/ 
			{  													/*设备出错*/ 
				ATA[THIS_DEVICE].ERRCODE  
					= (uint8)GetERR();							/*读取出错代码,保存出错代码,以便查询*/ 
				if(ATA[THIS_DEVICE].ERRCODE & ATA_EER_REG_IDNF)		/*如果是寻址出错,即记录出错的扇区号*/ 
				{	 
					ATA[THIS_DEVICE].ERRSECTOR   
						= (uint8)GetSector();						/*读出首次错误的扇区号LBA7~0*/ 
					ATA[THIS_DEVICE].ERRSECTOR  
					   |= ((uint8)GetCylinderLow())*0x100;			/*读出首次错误的扇区号LBA15~8*/ 
					ATA[THIS_DEVICE].ERRSECTOR  
					   |= ((uint8)GetCylinderHigh())*0x10000;		/*读出首次错误的扇区号LBA23~16*/ 
					ATA[THIS_DEVICE].ERRSECTOR  
					   |= ((uint8)GetDeviceHead()&0x0f)*0x1000000;	/*读出首次错误的扇区号LBA27~4*/ 
				} 
					 
			} 
			else 
				if(*Status==0)										/*如果状态全为0,该设备是无效的*/ 
				{ 
					ATA[THIS_DEVICE].ERRCODE = CARD_IS_FALSE;	/*设备无效*/ 
					*Status = CARD_IS_FALSE;					/*返回函数结果*/ 
				} 
				else 
				{					 
					ATA[THIS_DEVICE].ERRCODE = CARD_IS_TRUE;	/*清错误码率代码*/	 
				} 
		} 
		 
	} 
	else 
	{	 
		*Status = CARD_IS_FALSE;								/*设备不可用*/ 
		ATA[THIS_DEVICE].ERRCODE = CARD_IS_FALSE;				/*设备不可用*/ 
		ATA[THIS_DEVICE].ATAIsOK = FALSE;						/*设备不可用*/ 
	} 
} 
 
 
/********************************************************************************************************* 
** 函数名称: ATA_WaitOnBusyNDrdy					所在文件:IDE.C 
** 功能描述:  设备忙等待直到设备不忙并设备准备好. 
** 输   入: 无 
** 输   出: 设备出错返回0 
** 全局变量: ATA,数据结构体 
** 调用模块: ATA_GetStatus(),读取状态函数 
********************************************************************************************************/ 
uint8 ATA_WaitOnBusyNDrdy(void) 
{	 
   	uint8	ATAStatus; 
   	uint32 	timeout; 
		 
	for(timeout=0;timeout0)										/*选择的为从设备*/ 
		ATA_DevReg = ATA_DevReg_DEV1 + 					/*选择设备0*/ 
    			 	 ATA_DevReg_b5 + 
    			 	 ATA_DevReg_LBA+					/*工作在LAB模式*/ 
    			 	 ATA_DevReg_b7;	 
	else												/*选择的为主设备*/ 
		ATA_DevReg = ATA_DevReg_DEV0 + 					/*选择设备0*/ 
    			 	 ATA_DevReg_b5 + 
    			 	 ATA_DevReg_LBA +					/*工作在LAB模式*/ 
    			 	 ATA_DevReg_b7;			 
    			 	  
    SetDeviceHead(ATA_DevReg);							/*写设备磁头寄存器*/ 
    
    return ATA_WaitOnBusy();							/*等待设备不忙,返回状态*/ 
 
} 
 
 
 
/********************************************************************************************************* 
** 函数名称: ATA_CommandSet 
** 功能描述: 指令设置相关的寄存器。 
** 输   入: Feature,特征寄存器 
**			 SecCnt,扇区计数寄存器 
**			 SecNum,扇区号寄存器 
**			 CylLow,柱面低寄存器 
**			 CylHigh,柱面高寄存器 
**			 C_D_H,设备磁头寄存器 
**			 Command,指令寄存器  
** 输   出: 无 
** 全局变量: 无 
** 调用模块: SetFeature(),写Feature,特征寄存器 
**			 SetSECCNT(),写SecCnt,扇区计数寄存器 
**			 SetSector(),写扇区号寄存器 
**			 SetCylinderLow(),写柱面低寄存器 
**			 SetCylinderHigh(),写柱面高寄存器 
**    		 SetDeviceHead(),写设备磁头寄存器 
**			 SetCommand(),写指令寄存器 
********************************************************************************************************/ 
void ATA_CommandSet(uint8 Feature, 
					uint8 SecCnt, 
					uint8 SecNum, 
					uint8 CylLow, 
					uint8 CylHigh, 
					uint8 C_D_H, 
					uint8 Command  
					) 
{ 
	SetFeature(Feature);			/*Feature,特征寄存器*/ 
   	SetSECCNT(SecCnt);				/*SecCnt,扇区计数寄存器*/ 
	SetSector(SecNum);				/*SecNum,扇区号寄存器*/ 
	SetCylinderLow(CylLow);			/*CylLow,柱面低寄存器*/ 
	SetCylinderHigh(CylHigh);		/*CylHigh,柱面高寄存器*/ 
    SetDeviceHead(C_D_H );			/*C_D_H,设备磁头寄存器*/ 
	SetCommand(Command);			/*Command,指令寄存器 */ 
} 
 
 
 
/********************************************************************************************************* 
** 函数名称: ATA_DriveBasicInfo					所在文件:IDE.C 
** 功能描述: 获取设备基本信息 
** 输   入: 无 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: ATA[Device].INFODATA,设备信息结构体 
** 调用模块: GetData(),读ATA一个字的数据 
**			 ATA_GetStatus(),获取状态 
**			 ATA_WaitOnBusyNDrq(),等设备请求数据传输 
********************************************************************************************************/ 
uint8 ATA_DriveBasicInfo(uint8 Device) 
{ 
    	uint8 c,Status; 
 
   	if(ATA_WaitOnBusyNDrq()) 
   	{ 
		GetData();											//*Word 00 
		ATA[Device].INFODATA.NumberOfCylinders = GetData();	//*Word 01 
		GetData();											// Word 02 
		ATA[Device].INFODATA.NumberOfHeads = GetData();		//*Word 03 
		GetData();											// Word 04 
		GetData();											// Word 05 
		ATA[Device].INFODATA.SectorsPerTrack = GetData();	//*Word 06 
 
		for(c=7;c< 57;c++)	GetData(); 
 
		ATA[Device].INFODATA.CurrentSectorCapacity =(uint32)GetData();	   	//*Word 57 
        ATA[Device].INFODATA.CurrentSectorCapacity|=(uint32)GetData()<<16; 	//*Word 58 
 
		for(c=59;c< 255;c++)	GetData(); 
 
		ATA_GetStatus(&Status);						/*获取设备状态寄存器*/ 
		if(Status==CARD_IS_FALSE) 					/*如果设备失败返回*/ 
			return	(FALSE);						/*返回FALSE*/ 
		for(c = 0;Status&ATA_STAT_REG_DRQ;c++)		/*如果设备还有数据需要传输,有些设备需传输多于256字,那并不是协议所规范的*/ 
        {	        		 
        	GetData();				/*读取一个字数据并丢弃*/ 
        	ATA_GetStatus(&Status);					/*获取设备状态寄存器*/ 
        	if(Status==CARD_IS_FALSE) 				/*如果设备失败返回*/ 
				return	(FALSE);					/*返回FALSE*/ 
        } 
        		 
        if( ATA[Device].INFODATA.CurrentSectorCapacity == 0)	/*如果CurrentSectorCapacity值为,即无效,可以通过以下值计算出*/ 
        { 
         	ATA[Device].INFODATA.CurrentSectorCapacity = 
         		(uint32)ATA[Device].INFODATA.NumberOfCylinders *	/*柱面数*/ 
        		(uint32)ATA[Device].INFODATA.NumberOfHeads  *		/*磁头数*/ 
            		    ATA[Device].INFODATA.SectorsPerTrack;		/*磁道数*/ 
        } 
        return(TRUE); 
    } 
    else 
        return(FALSE); 
} 
 
/********************************************************************************************************* 
** 函数名称: ATA_DriveAllInfo					所在文件:IDE.C 
** 功能描述: 该函数获取IDE设备的特征信息, 
** 输   入: 结构体保存起始指针 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: 无 
** 调用模块: GetData(),读ATA一个字的数据 
**			 ATA_GetStatus(),获取状态 
**			 ATA_WaitOnBusyNDrq(),等设备请求数据传输 
********************************************************************************************************/ 
uint8 ATA_DriveAllInfo(void * PTR) 
{ 
    	uint8 c,Status; 
 
   	if(ATA_WaitOnBusyNDrq())												/*设备准备好传输数据*/ 
   	{ 
#define	DEVICEINFO 								((PCF_IDENTIFY_DATA)PTR)			/*宏定义结构指针*/ 
       	DEVICEINFO->GeneralConfiguration 	 	= GetData();			//*Word 00 
		DEVICEINFO->NumberOfCylinders        	= GetData();			//*Word 01 
 
		DEVICEINFO->Reserved1     			 	= GetData();			// Word 02 
		DEVICEINFO->NumberOfHeads 		 		= GetData();			//*Word 03 
 
		DEVICEINFO->UnformattedBytesPerTrack   	= GetData();			// Word 04 
       	DEVICEINFO->UnformattedBytesPerSector  	= GetData();			// Word 05 
		DEVICEINFO->SectorsPerTrack 		 	= GetData();			//*Word 06 
 
		DEVICEINFO->SectorsPerCard 	= (uint32) GetData()<<16;		// Word 07 
		DEVICEINFO->SectorsPerCard 	|=(uint32) GetData(); 			// Word 08 
		DEVICEINFO->VendorUnique				= GetData();			//Word 09 
     	for(c = 0 ; c <10 ; c++)  
       		DEVICEINFO->SerialNumber[c]		 	= GetData();			// Word 10-19 
		DEVICEINFO->BufferType				 		= GetData();		// Word 20 
		DEVICEINFO->BufferSectorSize		 	= GetData();			// Word 21 
		DEVICEINFO->NumberOfEccBytes		 	= GetData();			// Word 22 
 		for(c = 0 ; c <4 ; c++)  
 			DEVICEINFO->FirmwareRevision[c]	 	= GetData(); 		// Word 23-26 
 	    for(c = 0 ; c <20 ; c++) 
        	DEVICEINFO->ModelNumber[c] 		 	= GetData(); 		// Word 27-46 
  		DEVICEINFO->MaximumBlockTransfer 	 	= GetData();			//*Word 47 
  		DEVICEINFO->Reserved2				 	= GetData();			// Word 48 
  		DEVICEINFO->Capabilities             	= GetData();			//*Word 49 
		DEVICEINFO->Reserved3                	= GetData(); 		// Word 50       
		DEVICEINFO->PioCycleTimingMode       	= GetData();			//*Word 51 
		DEVICEINFO->DmaCycleTimingMode    	 	= GetData();			// Word 52 
        DEVICEINFO->TranslationFieldsValid   	= GetData();			//*Word 53 
 
		DEVICEINFO->NumberOfCurrentCylinders 	= GetData();			//*Word 54 
        DEVICEINFO->NumberOfCurrentHeads     	= GetData();			//*Word 55 
        DEVICEINFO->CurrentSectorsPerTrack   	= GetData();			//*Word 56 
 
		DEVICEINFO->CurrentSectorCapacity	 =(uint32)GetData();	   	//*Word 57 
        DEVICEINFO->CurrentSectorCapacity   |=(uint32)GetData()<<16; //*Word 58 
 
		DEVICEINFO->CurrentMultiSectorSetting	= GetData();			//*Word 59 
		DEVICEINFO->UserAddressableSectors =(uint32)GetData();		//Word 60 
		DEVICEINFO->UserAddressableSectors|=(uint32)GetData()<<16;	//Word 61 
		DEVICEINFO->Reserved4[0] 			 	= GetData();			// Word 62 
		DEVICEINFO->Reserved4[1] 			 	= GetData();			// Word 63 
		DEVICEINFO->AdvancedPIOModes 	    	= GetData();			//*Word 64 
		DEVICEINFO->Reserved6[0] 			 	= GetData();			// Word 65 
		DEVICEINFO->Reserved6[1] 			 	= GetData();			// Word 66 
		DEVICEINFO->MinimumPIOCycleTime 	 	= GetData();			//*Word 67 
		DEVICEINFO->MinimumPIOCycleTimeIORDY 	= GetData();			//*Word 68 
		for(c = 0 ; c <10 ; c++) 
			DEVICEINFO->Reserved7[c] 		 	= GetData();			// Word 69-79 
		DEVICEINFO->AtaVersion 	        = (uint32)GetData();			// Word 80 
		DEVICEINFO->AtaVersion		   |= (uint32)GetData();			// Word 81 
		DEVICEINFO->FeaturesCommandSupported[0] = GetData();			// Word 82 
		DEVICEINFO->FeaturesCommandSupported[1] = GetData();			// Word 83 
		DEVICEINFO->FeaturesCommandSupported[2] = GetData();			// Word 84 
		DEVICEINFO->FeaturesCommandEnabled[0]   = GetData();			// Word 85 
		DEVICEINFO->FeaturesCommandEnabled[1]   = GetData();			// Word 86 
		DEVICEINFO->FeaturesCommandEnabled[2]   = GetData();			// Word 87 
		DEVICEINFO->Reserved8				  	= GetData();			// Word 88 
		DEVICEINFO->MajorRevision				= GetData();			// Word 89 
		DEVICEINFO->MinorRevision				= GetData();			// Word 90 
		 
		DEVICEINFO->PowerManagementValue		= GetData();			// Word 91 
		for(c = 0 ; c <36 ; c++) 
			DEVICEINFO->Reserved9[c]			= GetData();			// Word 92-127 
		DEVICEINFO->SecurityStatus   			= GetData();			//*Word 128 
		for(c = 0 ; c <32 ; c++) 
			DEVICEINFO->VendorUniqueBytes[c]	= GetData();			// Word 129-159 
		DEVICEINFO->PowerRequirementDescription	= GetData();			//*Word 160 
		DEVICEINFO->Reserved10				  	= GetData();			// Word 161 
		DEVICEINFO->KeyManagementSupported	  	= GetData();			// Word 162 
		for(c = 0 ; c <83 ; c++) 
			DEVICEINFO->Reserved11[c]			= GetData();			// Word 163-255 
 
		ATA_GetStatus(&Status);						/*获取设备状态寄存器*/ 
		if(Status==CARD_IS_FALSE) 					/*如果设备失败返回*/ 
			return	(FALSE);						/*返回FALSE*/ 
		for(c = 0;Status&ATA_STAT_REG_DRQ;c++)		/*如果设备还有数据需要传输,有些设备需传输多于256字,那并不是协议所规范的*/ 
        {	        		 
        	GetData();				/*读取一个字数据并抛弃*/ 
        	ATA_GetStatus(&Status);					/*获取设备状态寄存器*/ 
        	if(Status==CARD_IS_FALSE) 				/*如果设备失败返回*/ 
				return	(FALSE);					/*返回FALSE*/ 
        } 
        		 
       	return TRUE; 
    } 
    else 
        return FALSE; 
#undef	DEVICEINFO 
} 
 
 
/********************************************************************************************************* 
** 函数名称: ATA_IssueIDEIdentify					所在文件:IDE.C 
** 功能描述: 确认IDE设备,获取IDE设备信息 
** 输   入: Device,设备号 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: ATA_DevReg,选择设备 
** 调用模块: ATA_CommandSet(),指令设置 
**      	 ATA_SelectDevice(),选择设备 
**			 ATA_WaitOnBusyNDrdy(),等设备准备好 
**			 ATA_DriveBasicInfo(),初始化设备信息 
********************************************************************************************************/ 
uint8 ATA_IssueIDEIdentify(uint8 Device) 
{			 
	uint8 retStatus = FALSE; 
  	if(ATA_SelectDevice(Device))		/*选择设备*/ 
    { 
 	   	ATA_CommandSet( 				/*ATA指令设置*/ 
 	   		NULL,						/*Feature,特征寄存器*/ 
			NULL, 						/*SecCnt,扇区计数寄存器*/ 
			NULL, 						/*SecNum,扇区号寄存器*/ 
			NULL,						/*CylLow,柱面低寄存器*/ 
			NULL,						/*CylHigh,柱面高寄存器*/ 
			ATA_DevReg,					/*C_D_H,设备磁头寄存器*/ 
			IDE_CMD_IDENTIFY 			/*Command,指令寄存器*/  
				  	  ); 
       	if(ATA_DriveBasicInfo(Device))	/*初始化设备信息*/ 
    		if(ATA_WaitOnBusyNDrdy())	/*等待设备准备好,检测指令执行结果*/ 
    	   		retStatus = TRUE; 
    } 
	return retStatus; 
}  
 
 
/********************************************************************************************************* 
** 函数名称: ATA_IdentifyDrive					所在文件:IDE.C 
** 功能描述: 确认IDE设备,获取IDE设备信息 
** 输   入: Device:设备号,0为主设备,1为从设备 
**			 PTR:保存设备信息的指针 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: CFIDESem,信号量指针 
**			 ATA_DevReg,选择设备 
**			 ATA[Device].ATAIsOK,设备状态 
** 调用模块: OSSemPend(),等待信号量 
**			 ATA_SelectDevice(),选择设备 
**      	 ATA_CommandSet(),指令设置 
**			 ATA_WaitOnBusyNDrdy(),等设备准备好 
**			 ATA_DriveAllInfo(),初始化设备信息 
**			 OSSemPost(),发送信号量 
********************************************************************************************************/ 
uint8 ATA_IdentifyDrive(uint8 Device,void *PTR) 
{			 
	uint8 retStatus = FALSE; 
 
#ifdef UCOSII 
	uint8	err; 
#endif 
 
	if(ATA[Device].ATAIsOK==FALSE) 											 
		return	FALSE;	 
 
 
#ifdef UCOSII																 
	OSSemPend(CFIDESem, 0, &err);		/*等待信号量*/									 
#endif 
 
 
  	if(ATA_SelectDevice(Device))		/*选择设备*/ 
    { 
 	   	ATA_CommandSet( 				/*ATA指令设置*/ 
 	   		NULL,						/*Feature,特征寄存器*/ 
			NULL, 						/*SecCnt,扇区计数寄存器*/ 
			NULL, 						/*SecNum,扇区号寄存器*/ 
			NULL,						/*CylLow,柱面低寄存器*/ 
			NULL,						/*CylHigh,柱面高寄存器*/ 
			ATA_DevReg,					/*C_D_H,设备磁头寄存器*/ 
			IDE_CMD_IDENTIFY 			/*Command,指令寄存器*/  
				  	  ); 
       	if(ATA_DriveAllInfo(PTR))		/*初始化设备信息*/ 
        	if( ATA_WaitOnBusyNDrdy())	/*等待设备准备好*/ 
          		retStatus = TRUE; 
    } 
     
#ifdef UCOSII 
	OSSemPost(CFIDESem);				/*发送信号量*/											 
#endif 
     
	return retStatus; 
} 
 
 
 
 
/********************************************************************************************************* 
** 函数名称: ATA_SetFeature					所在文件:IDE.C 
** 功能描述: 设置CF卡功能特性命令(如使用CF卡特有的8位数据总线) 
** 输   入: 无 
** 输   出: 指令正常完成返回TURE,出错返回FALSE 
** 全局变量: ATA_DevReg,选择的设备 
** 调用模块: ATA_CommandSet(),ATA指令设置 
**			 ATA_SelectDevice(),选择设备 
********************************************************************************************************/ 
uint8 ATA_SetFeature(uint8 Device) 
{    
	uint8 retStatus = FALSE; 
    if(ATA_SelectDevice(Device))	/*等待设备准备好*/ 
   	{ 
#ifdef ATA_BUS_AT_8bit   			/*使用8位总线*/ 
   		 ATA_CommandSet( 			/*ATA指令设置*/ 
 	   		0x01,					/*Feature,特征寄存器*/ 
			NULL, 					/*SecCnt,扇区计数寄存器*/ 
			NULL, 					/*SecNum,扇区号寄存器*/ 
			NULL,					/*CylLow,柱面低寄存器*/ 
			NULL,					/*CylHigh,柱面高寄存器*/ 
			ATA_DevReg,				/*C_D_H,设备磁头寄存器*/ 
			IDE_CMD_SETFEATURES 	/*Command,指令寄存器*/  
				  	  ); 
#else								/*使用16位*/ 
   		 ATA_CommandSet( 			/*ATA指令设置*/ 
 	   		0x81,					/*Feature,特征寄存器*/ 
			NULL, 					/*SecCnt,扇区计数寄存器*/ 
			NULL, 					/*SecNum,扇区号寄存器*/ 
			NULL,					/*CylLow,柱面低寄存器*/ 
			NULL,					/*CylHigh,柱面高寄存器*/ 
			ATA_DevReg,				/*C_D_H,设备磁头寄存器*/ 
			IDE_CMD_SETFEATURES 	/*Command,指令寄存器*/  
					   ); 
#endif				 
	retStatus = ATA_WaitOnBusyNDrdy();			/*等待设备准备好*/ 
	} 
	return retStatus; 
} 
  
 
 
/********************************************************************************************************* 
** 函数名称: ATA_INI					所在文件:IDE.C 
** 功能描述: ATA设备初始化 
** 输   入: 无 
** 输   出: 无 
** 全局变量: ATA,设备状态信息结构体 
**			 CFIDESem,信号量 
** 调用模块: OSSemCreate(),建立信号量 
**			 ATA_FindIDEDevice(),查找ATA设备 
********************************************************************************************************/ 
void ATA_INI(void) 
{ 
	uint8 Device; 
	for(Device=0;DeviceDevice;Device++)	/*初始化各设备,MAX_DEVICE最大值为1,即只能有主和从两个设备*/ 
			{ 
				ATA_SetFeature(Device);					/*特性设备,(总线设置)*/ 
				if(ATA_IssueIDEIdentify(Device))		/*ATA设备识别,获取CF卡内部信息*/ 
					ATA[Device].ATAIsOK = TRUE;			/*ATA设备可用,置位其标志位*/ 
				else 
					ATA[Device].ATAIsOK = FALSE;		/**ATA设备不可用,清ATA设备准备好标志*/ 
			} 
		} 
	} 
}  
 
 
/********************************************************************************************************* 
** 函数名称: ATA_ReadSetting					所在文件:IDE.C 
** 功能描述: 读扇区指令设置相关的寄存器。 
** 输   入: Sectors ,读设备的起始扇区号 
**			 Count ,扇区数 
** 输   出: 无 
** 全局变量: ATA_DevReg,确定选择的是主设备或是从设备和地址模式(本驱动使用LBA模式) 
** 调用模块: ATA_CommandSet(),写命令设置 
********************************************************************************************************/ 
void ATA_ReadSetting(uint32 Sectors , uint8 Count) 
{ 
   	ATA_CommandSet( 									/*ATA指令设置*/ 
 		NULL,											/*Feature,特征寄存器*/ 
		(uint8)Count, 									/*SecCnt,扇区计数寄存器*/ 
		(uint8)Sectors, 								/*SecNum,扇区号寄存器*/ 
		(uint8)(Sectors/0x100),							/*CylLow,柱面低寄存器*/ 
		(uint8)(Sectors/0x10000),						/*CylHigh,柱面高寄存器*/ 
		(uint8)(((Sectors/0x1000000)&0x0f)|ATA_DevReg),	/*C_D_H,设备磁头寄存器*/ 
		(uint8)IDE_CMD_READ 							/*Command,指令寄存器*/  
				  ); 
} 
 
/********************************************************************************************************* 
** 函数名称: ATA_ReadData512B 
** 功能描述: 从硬盘读出一个512B,在指定的缓冲区里 
** 输   入: Buffer,缓冲区地址 
** 输   出: 无 
** 全局变量: 无 
** 调用模块: GetData(),从ATA数据寄存器读取一个字节 
********************************************************************************************************/ 
void ATA_ReadData512B(uint16 * Buffer) 
{ 	uint16 i; 
	for(i = 0; i < 256; i ++)					/*连续读256个字(512字节)数据*/ 
    { 
    	*(Buffer ++) = GetData();				/*读数据寄存器一个字数据*/ 
    } 
} 
 
/********************************************************************************************************* 
** 函数名称: ATA_ReadSector					所在文件:IDE.C 
** 功能描述: 从硬盘读取一或多个扇区,放入到形参指定的内存中 
** 输   入: Device,设备号 
**			 Buffer,读出数据存放的缓冲区地址 
**			 Sector,读扇区号 
**			 count, 读扇区数 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: ATA,设备状态及信息结构体 
** 调用模块: OSSemPend(),等待信号量 
**			 ATA_SelDevice(),选择设备 
**			 ATA_ReadSetting(),读扇区设置 
**			 ATA_WaitOnBusyNDrq(),等待数据请求 
**			 ATA_ReadData512B(),读512字节数据 
**			 ATA_WaitOnBusyNDrdy(),等待设备准备好 
**			 OSSemPost(),发送信号量 
********************************************************************************************************/ 
uint8 ATA_ReadSector(uint8 Device,uint16 *Buffer,uint32 Sector,uint8 count) 
{	 
#ifdef UCOSII 
	uint8	err; 
#endif 
 
	uint8	Status=FALSE; 
	if(ATA[Device].ATAIsOK==FALSE) 				/*设备不可用,立即返回*/ 
		return	FALSE;							/*设备无效直接返回*/ 
 
#ifdef UCOSII 
	OSSemPend(CFIDESem, 0, &err);				/*等待信号量*/ 
#endif 
 
	if(ATA_SelectDevice(Device))				/*选择主从设备*/ 
	{ 
		ATA_ReadSetting( Sector, count);		/*读扇区设置*/ 
		do 
		{	 
			count--;							/*扇区数减1*/ 
			if(ATA_WaitOnBusyNDrq())			/* 等待设备请求数据传输*/ 
		    {	 
			   	ATA_ReadData512B( Buffer );		/*连续读取一扇区的数据*/ 
			   	Buffer +=256;					/*调整数据格式*/ 
			} 
			else 
			   	break;							/*出错,退出d0...while*/ 
		}while(count>0);						/*所有扇区数据传输完成*/ 
			 
		if(ATA_WaitOnBusyNDrdy())				/*等待设备就绪,读取状态寄存器同时检测设备是否出错*/ 
			Status = TRUE;						/*操作正确*/ 
	}	 
	 
	 
#ifdef UCOSII 
	OSSemPost(CFIDESem);						/*发送信号量*/ 
#endif 
 
	return Status;								/*返回*/ 
} 
 
/********************************************************************************************************* 
** 函数名称: ATA_WriteSetting					所在文件:IDE.C 
** 功能描述: 写扇区指令设置相关的寄存器。 
** 输   入: Sectors,写入的起始扇区号 
**           Count,扇区数 
** 输   出: 无 
** 全局变量: ATA_DevReg,确定选择的是主设备或是从设备和地址模式(本驱动使用LBA模式) 
** 调用模块: ATA_CommandSet(),写命令设置 
********************************************************************************************************/ 
void ATA_WriteSetting(uint32 Sectors , uint8 Count) 
{ 
	ATA_CommandSet( 									/*ATA指令设置*/ 
 		NULL,											/*Feature,特征寄存器*/ 
		(uint8)Count, 									/*SecCnt,扇区计数寄存器*/ 
		(uint8)Sectors, 								/*SecNum,扇区号寄存器*/ 
		(uint8)(Sectors/0x100),							/*CylLow,柱面低寄存器*/ 
		(uint8)(Sectors/0x10000),						/*CylHigh,柱面高寄存器*/ 
		(uint8)(((Sectors/0x1000000)&0x0f)|ATA_DevReg),	/*C_D_H,设备磁头寄存器*/ 
		(uint8)IDE_CMD_WRITE 							/*Command,指令寄存器*/  
				  );	 
}  
 
/********************************************************************************************************* 
** 函数名称: ATA_WriteData512B 
** 功能描述: 写入ATA设备512字节数据 
** 输   入: Buffer,缓冲区地址 
** 输   出: 无 
** 全局变量: 无 
** 调用模块: SetData(),从ATA数据寄存器读取一个字节 
********************************************************************************************************/ 
void ATA_WriteData512B(uint16 * Buffer) 
{   	 
	uint16 i; 
   	for(i = 0; i < 256; i ++)			/*连续写256个字(512字节)数据*/ 
   	{ 
     	SetData(*(Buffer++)); 			/*写数据寄存器一个字数据*/    	 
   	} 
} 
 
/********************************************************************************************************* 
** 函数名称: WriteSector					所在文件:IDE.C 
** 功能描述: 向硬盘写入一或多个扇区 
** 输   入: Device,选择主设备或从设备 
**			 Buffer,缓冲区地址 
**			 Sector,写入扇区号 
**			 count, 写入扇区数 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: ATA,设备状态及信息结构体 
** 调用模块: OSSemPend(),等待信号量 
**			 ATA_SelDevice(),选择设备 
**			 ATA_ReadSetting(),读扇区设置 
**			 ATA_WaitOnBusyNDrq(),等待数据请求 
**			 ATA_WriteData512B(),写512字节数据 
**			 ATA_WaitOnBusyNDrdy(),等待设备准备好 
**			 OSSemPost(),发送信号量 
********************************************************************************************************/ 
uint8 ATA_WriteSector(uint8 Device,uint16 * Buffer, uint32 Sector ,uint8 count) 
{	 
#ifdef UCOSII 
	uint8	err; 
#endif 
	uint8	Status=FALSE; 
	if(ATA[Device].ATAIsOK==FALSE) 			/*CF卡不可用,立即返回*/ 
		return	FALSE; 
 
#ifdef UCOSII 
	OSSemPend(CFIDESem, 0, &err);			/*等待信号量*/ 
#endif 
	 
	if(ATA_SelectDevice(Device))			/*选择需要操作的设备*/ 
	{ 
		ATA_WriteSetting( Sector, count);	/*写扇区设置*/ 
	    do 
	    {	count--; 
	    	if(ATA_WaitOnBusyNDrq())		/*等待设备请求数据传输*/ 
			{ 
	    		ATA_WriteData512B(Buffer);	/*写入一个扇区数据*/ 
	    		Buffer +=256;				/*调要写入数据缓冲区的指针*/ 
			} 
			else 
				break;						/*出错退出*/ 
		}while(count>0); 
 
		if(ATA_WaitOnBusyNDrdy())			/*等待设备就绪,读取状态寄存器同时检测设备是否出错*/ 
			Status = TRUE;					/*操作正确*/ 
	} 
	 
#ifdef UCOSII 
	OSSemPost(CFIDESem);					/*发信号量*/ 
#endif 
 
	return Status;							/*返回*/ 
} 
 
 
/********************************************************************************************************* 
** 函数名称: ATA_IdleImmediate					所在文件:IDE.C 
** 功能描述: 直接进入空闲状态(硬件转动) 
** 输   入: Device,选择主设备或从设备 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: ATA,设备状态及信息结构体 
**			 CFIDESem,信号量 
**			 ATA_DevReg,确定选择的是主设备或是从设备和地址模式(本驱动使用LBA模式) 
** 调用模块: OSSemPend(),等待信号量 
**			 ATA_SelDevice(),选择设备 
**			 ATA_CommandSet(),ATA指令设置 
**			 ATA_WaitOnBusyNDrdy(),等待设备就绪 
**			 OSSemPost(),发送信号量 
********************************************************************************************************/ 
uint8 ATA_IdleImmediate(uint8 Device) 
{ 
#ifdef UCOSII 
	uint8	err; 
#endif 
	uint8 	retStatus = FALSE; 
	if(ATA[Device].ATAIsOK==FALSE) 			/*CF卡不可用,立即返回*/ 
		return	FALSE; 
 
#ifdef UCOSII 
	OSSemPend(CFIDESem, 0, &err);			/*等待信号量*/ 
#endif 
	if(ATA_SelectDevice(Device))			/*选择设备*/ 
	{	 
   		ATA_CommandSet( 					/*ATA指令设置*/ 
 	   		NULL,							/*Feature,特征寄存器*/ 
			NULL, 							/*SecCnt,扇区计数寄存器*/ 
			NULL, 							/*SecNum,扇区号寄存器*/ 
			NULL,							/*CylLow,柱面低寄存器*/ 
			NULL,							/*CylHigh,柱面高寄存器*/ 
			ATA_DevReg,						/*C_D_H,设备磁头寄存器*/ 
			IDE_CMD_IDLE_IMMEDIATE			/*Command,指令寄存器*/  
					   ); 
    	 
    	retStatus =ATA_WaitOnBusyNDrdy();	/*指令执行后状态*/ 
	} 
 
#ifdef UCOSII 
	OSSemPost(CFIDESem);					/*发信号量*/ 
#endif 
 
	return retStatus;						/*返回*/ 
} 
 
/********************************************************************************************************* 
** 函数名称: ATA_StandbyImmediate	所在文件:IDE.C 
** 功能描述: 立即进入空闲(硬盘停转) 
** 输   入: Device,主设备或从设备 
** 输   出: TRUE,正常返回 
**			 FALSE,出错返回 
** 全局变量: ATA,设备状态及信息结构体 
**			 CFIDESem,信号量 
**			 ATA_DevReg,确定选择的是主设备或是从设备和地址模式(本驱动使用LBA模式) 
** 调用模块: OSSemPend(),等待信号量 
**			 ATA_SelDevice(),选择设备 
**			 ATA_CommandSet(),ATA指令设置 
**			 ATA_WaitOnBusyNDrdy(),等待设备就绪 
**			 OSSemPost(),发送信号量 
********************************************************************************************************/ 
uint8 ATA_StandbyImmediate(uint8 Device) 
{	 
#ifdef UCOSII 
	uint8	err; 
#endif 
	uint8 retStatus = FALSE; 
	if(ATA[Device].ATAIsOK==FALSE) 			/*CF卡不可用,立即返回*/ 
		return	FALSE; 
 
#ifdef UCOSII 
	OSSemPend(CFIDESem, 0, &err);			/*等待信号量*/ 
#endif 
	 
	if(ATA_SelectDevice(Device))			/*选择设备*/ 
	{	 
   		ATA_CommandSet( 					/*ATA指令设置*/ 
 	   		NULL,							/*Feature,特征寄存器*/ 
			NULL, 							/*SecCnt,扇区计数寄存器*/ 
			NULL, 							/*SecNum,扇区号寄存器*/ 
			NULL,							/*CylLow,柱面低寄存器*/ 
			NULL,							/*CylHigh,柱面高寄存器*/ 
			ATA_DevReg,						/*C_D_H,设备磁头寄存器*/ 
			IDE_CMD_STANDBY_IMMEDIATE		/*Command,指令寄存器*/  
					   ); 
					    
    	retStatus =ATA_WaitOnBusyNDrdy();	/*等待设备不忙*/	 
	} 
 
#ifdef UCOSII 
	OSSemPost(CFIDESem);					/*发信号量*/ 
#endif 
 
	return retStatus;						/*返回*/ 
}