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; /*返回*/
}