-
-
[原创]自写的IDE硬盘扇区绝对读写函数及逻辑锁的应用
-
发表于:
2014-2-23 14:54
7695
-
[原创]自写的IDE硬盘扇区绝对读写函数及逻辑锁的应用
读写硬盘可以通过访问硬盘控制器进行,不过在R3下不可以使用in和Out指令只有麻烦一下,写在驱动中。
我们先来看一看IDE硬盘控制器的接口是干啥的。
端口范围0x1f0 到 0x1f7 一共8个 还忘记了两个个3f6 and 3f7。
下面列出了他们具体的用途:
表1 Task File Registers命令寄存器组
I/O地址 读(主机从硬盘读数据) 写(主机数据写入硬盘)
1F0H 数据寄存器 数据寄存器
1F1H 错误寄存器(只读寄存器) 特征寄存器
1F2H 扇区计数寄存器 扇区计数寄存器
1F3H 扇区号寄存器或LBA块地址0~7 扇区号或LBA块地址0~7
1F4H 磁道数低8位或LBA块地址8~15 磁道数低8位或LBA块地址8~15
1F5H 磁道数高8位或LBA块地址16~23 磁道数高8位或LBA块地址16~23
1F6H 驱动器/磁头或LBA块地址24~27 驱动器/磁头或LBA块地址24~27
1F7H 状态寄存器 命令寄存器
表2 Control/Diagnostic Registers控制/诊断寄存器
I/O地址 读 写
3F6H 交换状态寄存器(只读寄存器) 设备控制寄存器(复位)
3F7H 驱动器地址寄存器
----------------------------------
具体资料可以在百度上查找。
在驱动程序里面可以使用 READ_PORT_UCHAR和WRITE_PORT_UCHAR函数来完成端口的读写,具体的说明上MSDN。
需要注意的是1F0H 数据端口,他是一个字型端口,非字节,所以呢,就不可以使用 READ_PORT_UCHAR和WRITE_PORT_UCHAR这两个函数了,因为他们是读取的字节端口。
怎么办呢?用内嵌汇编,in ax,ax (dx=0x1f0)
在读取数据之前一定要判断硬盘是否空闲,详见代码:
do
{
CHAR error;
js++;
if(js>MAX)
{
return 0; //硬盘无响应
}
DbgPrint("等待中!");
tmp_data=READ_PORT_UCHAR(addr);
error=tmp_data&1; //是否有错误
DbgPrint("STATUS : %d",tmp_data);
if(error==1)
{
addr=(PUCHAR)0x1f1;
tmp_data=READ_PORT_UCHAR(addr);
DbgPrint("error Code:%d",tmp_data);
return 0;
}
tmp_data&=0x88; // 提取出 7 3位
}while(tmp_data!=0x8);
typedef struct _LBA28
{
UCHAR A0_7;
UCHAR A8_15;
UCHAR A16_23;
UCHAR A24_27; //低4位有效
UCHAR Attribute; //低4位有效
}LBA28,*PLBA28;
typedef struct _sector
{
UCHAR sector[512];
}SECTOR,*PSECTOR;
int readDisk(LBA28 lba,UCHAR num,PSECTOR pSector)
{
int y,x=0;
LONG js=0,MAX=90000;
PUCHAR addr;
UCHAR tmp_data,tmp_data1;
addr=(PUCHAR)0x1f2;
WRITE_PORT_UCHAR(addr,num);
addr=(PUCHAR)0x1f3;
WRITE_PORT_UCHAR(addr,lba.A0_7);
addr=(PUCHAR)0x1f4;
WRITE_PORT_UCHAR(addr,lba.A8_15);
addr=(PUCHAR)0x1f5;
WRITE_PORT_UCHAR(addr,lba.A16_23);
addr=(PUCHAR)0x1f6;
tmp_data=lba.A24_27;
tmp_data&=0xf;
tmp_data1=lba.Attribute;
tmp_data=((tmp_data1<<4)&0xf0)|tmp_data;
WRITE_PORT_UCHAR(addr,tmp_data);
addr=(PUCHAR)0x1f7;
WRITE_PORT_UCHAR(addr,0x20);
//进入准备状态
do
{
CHAR error;
js++;
if(js>MAX)
{
return 0; //硬盘无响应
}
DbgPrint("等待中!");
tmp_data=READ_PORT_UCHAR(addr);
error=tmp_data&1; //是否有错误
DbgPrint("STATUS : %d",tmp_data);
if(error==1)
{
addr=(PUCHAR)0x1f1;
tmp_data=READ_PORT_UCHAR(addr);
DbgPrint("error Code:%d",tmp_data);
return 0;
}
tmp_data&=0x88; // 提取出 7 3位
}while(tmp_data!=0x8);
//进入读取状态
addr=(PUCHAR)0x1f0;
for(y=0;y<num;y++)
{
int i;
PUCHAR tt;
DbgPrint("Read ing %d",y);
tt=&pSector[y].sector[0]; //sector是UCHAR
for(i=0;i<512;i+=2)
{
short da=0;
_asm
{
push dx
push eax
mov dx,0x1f0
in ax,dx
mov da,ax
pop eax
pop dx
}
RtlCopyMemory(&pSector[y].sector[i],&da,2);
}
}
return 250;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课