ATA技术是一个关于IDE(Integrated Device Electronics)的技术规范族。最初,IDE只是一项企图把控制器与盘体集成在一起为主要意图的硬盘接口技术。 随着IDE/EIDE得到的日益广泛的应用,全球标准化协议将该接口自诞生以来使用的技术规范归纳成为全球硬盘标准,这样就产生了ATA(Advanced Technology Attachment)。(来自百度搜索)
ATA传输模式有两种:Legacy Mode 和 Native Mode。本文中编写的程序是基于Native Mode的。
实现步骤:
1.寻址
首先,找到ATA设备所对应的bus#,device#和function#。这边使用到的是bus# = 0x11,device# = 0,function# = 0。这样就可以得到ATA设备对应的地址。
2.找到ATA传输对应的 Control Block 和 Command Block
图 3.1
如图3.1所示,Control Block 和 Command Block所对应的地址 = ATA设备地址 + 0x10(或0x14)。这样就可以对某一扇区下命令了。
图 3.2
如图3.2所示即为"Read Sector Command "。
3.在读取某一扇区信息时,最重要的就是要对Status Port进行判断。Status Port如图3.3所示。其中Bit7表示Bus是否忙碌,Bit6表示ATA设备是否准备好了,Bit3表示是否有数据传输请求,Bit0表示传输过程中是否有错误发生。
图 3.3
判断流程可以分为以下3步:
1,Reset后,判断Bit6,若Bit6 = 1表示设备准备好了;接着判断BIt7,若为0则表示总线空闲,可以下传输命令,否则等待直到总线空闲。
2,下控制命令后,接着判断Status Port,在第一步的判断基础上,判断BIt0,若为1表示下命令出错,这次操作结束。若Bit0 = 0,则继续判断Bit3,若Bit 3= 1,则开始发送数据,否则等待,直到有数据传输请求发生。
3,数据传输结束后,判断Bit7、Bit3和Bit0,若三者任一位为1,则表示这次数据传输出错。
代码如下:
#include <stdio.h>
#include <dos.h>
#include <PCI_Acc.h>
#include <IO_Acc.h>
typedef unsigned long DWORD;
typedef unsigned int WORD;
typedef unsigned char uchar;
void ResetAll(DWORD PCNL,DWORD PCMD)
{
/* Native Mode Identify */
/* Reset */
WORD cnl_01 = (WORD)PCNL + 0x02;
Write_IO_Word(cnl_01,0x04); /* 第3位置1 */
delay(1000);
Write_IO_Word(cnl_01,0x00); /* Reset Complete */
/* Choose Master */
WORD cmd_06 = (WORD)PCMD + 0x06;
Write_IO_Word(cmd_06,0x0a0);
}
/* Befor data transform,compare with 0x50 */
uchar JudgeStatus_Before(DWORD PCMD)
{
uchar flag = 0;
/* Read cmd_07 to get status */
WORD cmd_07 = (WORD)PCMD + 0x07;
uchar jud_data = Read_IO_Byte(cmd_07);
uchar num_7,num_6;
/* Get the numbs at 7th,6th */
num_7 = (jud_data>>7)&0x01;
num_6 = (jud_data>>6)&0x01;
printf("num_7 = %d,num_6 = %d\n",num_7,num_6);
/* judge process */
if(1==num_6) /* DRDY==1 stands for device ready */
{
if(0==num_7) /* BSY==0 stands for bus is not busy */
{
flag = 1;
}
else /* if bus is busy,wait until bus is free */
{
while(num_7!=0)
{
jud_data = Read_IO_Byte(cmd_07);
num_7 = (jud_data>>7)&0x01;
}
}
printf("BUS is not busy.Command!\n");
flag = 1;
}
else
{
flag = 0;
}
return flag;
}
/* CommandBlock */
void CommandBlock(DWORD PCMD)
{
Write_IO_Byte(WORD(PCMD + 0x02),0x01);
Write_IO_Byte(WORD(PCMD + 0x03),0x00);
Write_IO_Byte(WORD(PCMD + 0x04),0x00);
Write_IO_Byte(WORD(PCMD + 0x05),0x00);
Write_IO_Byte(WORD(PCMD + 0x06),0xe0);
Write_IO_Byte(WORD(PCMD + 0x07),0x20);
}
/* output data */
void Print(DWORD PCMD)
{
WORD Data;
WORD cmd_00 = (WORD)PCMD + 0x00;
int count = 0;
while(count<256)
{
Data = Read_IO_Word(cmd_00);
printf("%04x\t",Data);
count++;
if(count%9==0)
{
printf("\n");
}
}
}
void Run(DWORD PCNL,DWORD PCMD)
{
int flag = 0;
uchar jud_data = 0;
WORD cmd_07 = (WORD)PCMD + 0x07;
uchar num_7,num_6,num_3,num_0;
ResetAll(PCNL,PCMD);
printf("CommandBlock.\n");
uchar p = JudgeStatus_Before(PCMD);
if(1==p) /* 50-HD exist */
{
CommandBlock(PCMD);
jud_data = Read_IO_Byte(cmd_07);
num_7 = (jud_data>>7)&0x1;
num_6 = (jud_data>>6)&0x1;
num_3 = (jud_data>>3)&0x1;
num_0 = (jud_data)&0x1;
if(num_6==1)
{
if (num_7==0)
{
if (num_0==0)
{
if (num_3==1)
{
flag = 1;
}
else
{
while(num_3!=1)
{
jud_data = Read_IO_Byte(cmd_07);
num_3 = (jud_data>>3)&0x1;
}
flag = 1;
}
}
else
{
flag = 0;
}
}
else
{
while(num_7!=0)
{
jud_data = Read_IO_Byte(cmd_07);
num_7 = (jud_data>>7)&0x1;
}
if (num_0==0)
{
if (num_3==1)
{
flag = 1;
}
else
{
while(num_3!=1)
{
jud_data = Read_IO_Byte(cmd_07);
num_3 = (jud_data>>3)&0x1;
}
flag = 1;
}
}
else
{
flag = 0;
}
}
}
else
{
printf("Device is not ready!\n");
flag = 0;
}
if (flag == 1)
{
Print(PCMD);
}
else
{
Run(PCNL,PCMD);
}
}
else
{
Run(PCNL,PCMD);
}
}
void Run_02(DWORD PCNL,DWORD PCMD)
{
int flag = 0;
uchar jud_data = 0;
WORD cmd_07 = (WORD)PCMD + 0x07;
uchar num_7,num_6,num_3,num_0;
/* Read Size info...*/
ResetAll(PCNL,PCMD);
uchar p = JudgeStatus_Before(PCMD);
if (1==p)
{
WORD cmd_06 = (WORD)PCMD + 0x06;
uchar cmd_06_data = Read_IO_Byte(cmd_06);
cmd_06_data = cmd_06_data|0xa0;
Write_IO_Byte(cmd_06,cmd_06_data);
Write_IO_Byte(WORD(PCMD + 0x07),0xEC);
jud_data = Read_IO_Byte(cmd_07);
num_7 = (jud_data>>7)&0x1;
num_6 = (jud_data>>6)&0x1;
num_3 = (jud_data>>3)&0x1;
num_0 = (jud_data)&0x1;
if(num_6==1)
{
if (num_7==0)
{
if (num_0==0)
{
if (num_3==1)
{
flag = 1;
}
else
{
while(num_3!=1)
{
jud_data = Read_IO_Byte(cmd_07);
num_3 = (jud_data>>3)&0x1;
}
flag = 1;
}
}
else
{
flag = 0;
}
}
else
{
while(num_7!=0)
{
jud_data = Read_IO_Byte(cmd_07);
num_7 = (jud_data>>7)&0x1;
}
if (num_0==0)
{
if (num_3==1)
{
flag = 1;
}
else
{
while(num_3!=1)
{
jud_data = Read_IO_Byte(cmd_07);
num_3 = (jud_data>>3)&0x1;
}
flag = 1;
}
}
else
{
flag = 0;
}
}
}
else
{
printf("Device is not ready!\n");
flag = 0;
}
while(flag==0)
{
Run_02(PCNL,PCMD);
}
WORD Data[64] = {0};
for(int count = 0;count<64;count++)
{
WORD cmd_00 = (WORD)PCMD + 0x00;
Data[count] = Read_IO_Word(cmd_00);
}
printf("S/N = ");
for(int j=10;j<=19;j++)
{
printf("%c%c",uchar(Data[j]>>8),Data[j]);
}
printf("\n");
printf("Size = ");
DWORD sum = ((DWORD)Data[61]<<16) + Data[60];
sum = sum/1e9*512;
printf("%d GB\n",sum);
}
}
int main()
{
WORD bus,dev,func,reg1,reg2;
bus = 0;
dev = 0x11;
func = 0x0;
reg1 = 0x10;
reg2 = 0x14;
DWORD PCMD = Read_PCI_Dword(bus,dev,func,reg1)&0xFFFFFFFE;
DWORD PCNL = Read_PCI_Dword(bus,dev,func,reg2)&0xFFFFFFFE;
/* 读某一扇区的信息,512Byte */
Run(PCNL,PCMD);
/* 输出ATA设备的S/N和设备的大小,以GB表示 */
Run_02(PCNL,PCMD);
return 0;
}
输出结果如下图3.4所示:
图 3.4