frankpan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-08
  • 最后登录2005-09-28
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2019回复:18

关于底层硬盘读写的问题

楼主#
更多 发布于:2003-01-09 09:37
我用ATA指令对硬盘进行操作,对读出来的MBR扇区数据和用DEBUG读出来的比较,发现我的程序读出来的数据中每个WORD的高8位都丢掉了, 为什么会这样呢?我的程序是用inport函数读硬盘的16bit data register的,和DEBUG一样运行在98下的DOS session中。

有哪位做过相似的开发?是否要先设置一下寄存器的参数?
紧急!紧急!请高手不吝赐教!

最新喜欢:

okincnokincn
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-01-09 16:25
shyeagle:
你贴的那个程序是在dos下运行的么?
不能在win98下运行?

是的。
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
ruozhen
驱动牛犊
驱动牛犊
  • 注册日期2002-11-27
  • 最后登录2005-08-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-01-09 16:09
shyeagle:
你贴的那个程序是在dos下运行的么?
不能在win98下运行?
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-01-09 14:15
skyeagle:
果然象你说的,在纯DOS下读扇区的数据是正常的,无丢失的.
DEBUG对磁盘的操作可能是比较高层的函数,如absread等来
读写扇区,所以可以是正常的.

可以知道你的信箱吗?我的是frankpan@21cn.com
QQ:28483120.
多多指教

shyeagle2003@vip.sina.com
另外我的ID是shyeagle,不是skyeagle。
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
frankpan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-08
  • 最后登录2005-09-28
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-01-09 13:53
skyeagle:
果然象你说的,在纯DOS下读扇区的数据是正常的,无丢失的.
DEBUG对磁盘的操作可能是比较高层的函数,如absread等来
读写扇区,所以可以是正常的.

可以知道你的信箱吗?我的是frankpan@21cn.com
QQ:28483120.
多多指教
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-01-09 13:25
在纯dos下没有问题
这让我很郁闷
据有人说,windows对ide端口进行了保护
不知道你们碰到过这种问题没有?
 

那就对了。以前做的东西基本上都是与操作系统无关的。98下得用驱动。
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-01-09 13:23
这是我以前做的程序片段。
//Ata IO port
#define IOBASE_IDE0              0x1F7
#define IOBASE_IDE1              0x177
#define ATAP_DATA            0       //I/O  for data IO
#define ATAP_ERR             1       //O    for error output
#define ATAP_FEATURES        1       //I    for features set
#define ATAP_SECCOUNT        2       //I/O  for sector count
#define ATAP_SECNUMBER       3       //I/O  for sector number/LBA:a7-a0
#define ATAP_CYLINDERLOW     4       //I/O  for cylinder:a0-a7/LBA:a15-a8
#define ATAP_CYLINDERHIGH    5       //I/O  for cylinder:a8-a15/LBA:a23-a16
#define ATAP_DEVICE          6       //I/O  D6: 0=CHS  D3-D0:head number
                                     //         1=LBA  D3-D0:LBA:a27-a24
                                     //     D4: device number
#define ATAP_STATUS          7       //O    for status output
#define ATAP_COMMAND         7       //I    for command issue
//Ata IO port end
#define ATAC_READ            0x20
#define ATAC_WRITE           0x30
//Ata struct
typedef struct ATA_INFO
{
        BYTE    mode;       //LBA or CHS
        BYTE    funcmode;       //if ata mode
        BYTE    FuncNo;
        BYTE    DeviceNo;              
        WORD    iobase;
        BYTE    cylindershigh;
        BYTE    cylinderslow;
        BYTE    sectorspertrace;
        BYTE    headspercylinder;
}ATA_INFO;

ATA_INFO Atainfo={ATAM_LBA,ATAC_IDENTIFY,ATA_DEVICE0,IOBASE_IDE0};
far WORD    * DiskBuffer;
/////////////////////////////////////////////////////////////////
//name:         FuncHDRW
//function:     read sectors from of write sectors to harddisk
//parameter:    function number
//              device number 0 through 3
//              address mode LBA or CHS
//              address of begin sector
//              sum of  sectors to read or write
//input:        iobase+ATAP_DEVICE<=device number  (d4)
//              iobase+ATAP_COMMAND<=function number
//output:       iobase+ATAP_DEVICE=>device number  (d4)
//              iobase+ATAP_STATUS=>0x58
//return:       return YES
//error:        return NO
/////////////////////////////////////////////////////////////////
int     FuncHDRW(BYTE theFunc,BYTE theDevice,BYTE theMode,DWORD theAddr,BYTE theSecSum)
{
        long    i,thesum;
        BYTE    thech;

        Atainfo.FuncNo=theFunc;
        if(theDevice&0x01)
                Atainfo.DeviceNo=ATA_DEVICE1;
        else    Atainfo.DeviceNo=ATA_DEVICE0;
        Atainfo.DeviceNo|=theMode;
        if(theDevice&0x02)
                Atainfo.iobase=IOBASE_IDE1;
        else    Atainfo.iobase=IOBASE_IDE0;
        Atainfo.sectorspertrace=theAddr & 0x0f;
        theAddr >>= 8;
        Atainfo.cylinderslow = theAddr & 0x0f;
        theAddr >>= 8;
        Atainfo.cylindershigh = theAddr & 0x0f;
        theAddr >>=8;
        Atainfo.DeviceNo += theAddr;
        outp(Atainfo.iobase+ATAP_SECCOUNT,theSecSum);
        outp(Atainfo.iobase+ATAP_SECNUMBER,Atainfo.sectorspertrace);
        outp(Atainfo.iobase+ATAP_CYLINDERLOW,Atainfo.cylinderslow);
        outp(Atainfo.iobase+ATAP_CYLINDERHIGH,Atainfo.cylindershigh);
        outp(Atainfo.iobase+ATAP_DEVICE,Atainfo.DeviceNo;
        outp(Atainfo.iobase+ATAP_COMMAND,Atainfo.FuncNo);
        i=0;
        thech=YES;
        while(inp(Atainfo.iobase+ATAP_STATUS)!=0x58)
        {
                i++;
                if(i==256)
                        thech=NO;
        }
        if(thech)
        {
                if(theSecSum==0)
                        thesum=256;
                else    thesum=theSecSum;
                thesun *= 256;
                if(theFunc=ATAC_READ)
                        for(i=0;i<thesum;i++,DiskBuffer++)
                                *DiskBuffer=inpw(Atainfo.iobase+ATAP_DATA);
                else
                        if(theFunc=ATAC_WRITE
                                for(i=0;i<thesum;i++,DiskBuffer++)
                                                outpw(Atainfo.iobase+ATAP_DATA,*DiskBuffer);
        }
        return  thech;
}
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
ruozhen
驱动牛犊
驱动牛犊
  • 注册日期2002-11-27
  • 最后登录2005-08-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-01-09 13:20
在纯dos下没有问题
这让我很郁闷
据有人说,windows对ide端口进行了保护
不知道你们碰到过这种问题没有?
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-01-09 13:12
skyeagle:
我是在TC3下做的,也试过用INPW代替INPORT,但结果一样.
你做的开发在对硬盘读写前要先设置些什么吗?
谢谢!

就是设置地址、读写方式(LBA/CHS)和设备号。从你的情况来看应该不是设置的问题,是不是因为在98下才出现这样的问题?直接用MS-DOS方式启动试试。
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
ruozhen
驱动牛犊
驱动牛犊
  • 注册日期2002-11-27
  • 最后登录2005-08-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-01-09 12:11
我也编写了程序
在VC下面,console程序
另外,在BC下面也编了一样的16bit程序

但是我的程序有时候工作正常,有时候不工作(无法写硬盘)
下面是我的代码():
           unsigned short out_buffer[512];
int i;

memset(out_buffer,\'\\0\',512 );
out_buffer[0]=0xA;
out_buffer[1]=0xB;

_outp(0x1f6,0xB0);//对ide0上的从盘进行写

_outp(0x1F2,0x1);
_outp(0x1f3,0x3);
_outp(0x1F4,0x0);
_outp(0x1F5,0x0);
_outp(0x1F7,0x30);

do
{}
while((_inp(0x1F7))==8);

for(i=0;i<512;i++)
{
_outp(0x1F0,out_buffer);
}
我的代码抄自http://www.nondot.org/sabre/os/files/Disk/HD_PORTS.asm

这段代码在纯dos下运行没问题,在98下时好时怀
你们帮我看看吧
frankpan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-08
  • 最后登录2005-09-28
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-01-09 12:08
skyeagle:
我是在TC3下做的,也试过用INPW代替INPORT,但结果一样.
你做的开发在对硬盘读写前要先设置些什么吗?
谢谢!
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2003-01-09 11:50
shyeagle:
你理解的和我说的好像相反了。我用DEBUG读出来的是正常的,但我用inport(字读写)读丢了高8位。我也用inportb(字节读写)试过,但是也发现每两个字节中有一个字节没有读出来,因为1FO寄存器认为读一次就把两个字节读走了。

抱歉,我是理解反了,我以为你在DEBUG下用I命令的。
你用的是TC吧,我在MSC6.0下用inpw是没问题的。只要地址和读写模式对了就应该没问题。
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
frankpan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-08
  • 最后登录2005-09-28
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2003-01-09 11:22
rouzhen:
你想要的是正常的MBR数据是吧.
你可以在98的dos下用DEBUG进行查看:
debug 回车
-d 5000 看5000地址有没有数据,如果有就换另外无数据的内存
-l 5000 2 0 1 把c盘逻辑0扇区读到5000地址中
-d 5000 查看5000内容就是MBR数据了, d 命令一次显示0x80个byte
        所以你要连续敲d 回车,就可以查完余下的数据
        (5000 - 5200, 512bytes)

ruozhen
驱动牛犊
驱动牛犊
  • 注册日期2002-11-27
  • 最后登录2005-08-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2003-01-09 10:56
如果你编一个写的程序就非常明显了
只能对某个sector的偶数字节能读写
frankpan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-08
  • 最后登录2005-09-28
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2003-01-09 10:52
shyeagle:
你理解的和我说的好像相反了。我用DEBUG读出来的是正常的,但我用inport(字读写)读丢了高8位。我也用inportb(字节读写)试过,但是也发现每两个字节中有一个字节没有读出来,因为1FO寄存器认为读一次就把两个字节读走了。
ruozhen
驱动牛犊
驱动牛犊
  • 注册日期2002-11-27
  • 最后登录2005-08-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2003-01-09 10:49
这位兄弟:能否把你的读MBR(用port)的代码贴出来?
我想跟我的比较比较(我的工作不正常)
谢谢
shyeagle
驱动老牛
驱动老牛
  • 注册日期2002-04-30
  • 最后登录2007-07-31
  • 粉丝1
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2003-01-09 10:40
因为你用DEBUG命令是字节读写,而ATA指令的I/O是字读写,所以你在DEBUG下读出来的数据每个字都丢掉了高半个字。在程序中对与端口1F0H或170H一定要用字读写。
[url=http://www.01study.com]01空间网[/url] [url=http://www.01study.com/forum/dispbbs.asp?boardID=73&ID=193&skin=0]版主招募[/url] [img]http://shy2003.vip.sina.com/map/yjs.gif[/img]
frankpan
驱动牛犊
驱动牛犊
  • 注册日期2003-01-08
  • 最后登录2005-09-28
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2003-01-09 10:40
是呀, 我是读1f0端口的。
我想是有些地方没设置好吧,不然怎么DEBUG在同样的环境可以正常工作呢?
ruozhen
驱动牛犊
驱动牛犊
  • 注册日期2002-11-27
  • 最后登录2005-08-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2003-01-09 10:21
你是对port:1f0-1f6进行读写吧?
我也碰到过这种问题,目前没法解决
另外,我得程序在98下工作不太正常,有时候能工作,有时候不能工作
游客

返回顶部