首页
社区
课程
招聘
[原创]自写的IDE硬盘扇区绝对读写函数及逻辑锁的应用
发表于: 2014-2-23 14:54 7695

[原创]自写的IDE硬盘扇区绝对读写函数及逻辑锁的应用

2014-2-23 14:54
7695

读写硬盘可以通过访问硬盘控制器进行,不过在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直播授课

上传的附件:
收藏
免费 5
支持
分享
最新回复 (6)
雪    币: 6911
活跃值: (9079)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
2
给我自己一个鼓励。
2014-2-23 14:57
0
雪    币: 1904
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好贴啊!!!
2014-2-24 21:00
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习了楼主,谢谢辛苦分享!!
2014-2-25 19:08
0
雪    币: 219
活跃值: (793)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
5
这个 东西很复杂,每个寄存器都有他的标志位,有的 还没定义,看的眼都花了
2014-12-21 02:16
0
雪    币: 6911
活跃值: (9079)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
6
IDE接口应该算是最简单了,最近几年出现的sata协议根据复杂。
2015-7-17 18:06
0
雪    币: 19
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错文章,所然看懂一点的
2015-7-17 18:22
0
游客
登录 | 注册 方可回帖
返回
//