中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
作者:
标题: 扩展int 13h 访问大硬盘问题 上一主题 | 下一主题
beiyuly
初级用户





积分 95
发帖 40
注册 2006-10-8
状态 离线
『楼 主』:  扩展int 13h 访问大硬盘问题

扩展int 13h 访问大硬盘问题

一般小硬盘的访问之需要int13h就可以了。通过c/h/s的3级访问方式,就可以访问整个硬盘,那么怎么访问大于8.2gb的硬盘数据空间呢?
通过扩展int13可以实现,那么扩展int13的机制是什么?

大虾出来看看了!`

xiexie!



http://beiyu.bokee.com
2007-4-20 23:33
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 2 楼』:  

以下是我写的TOdisk/miniTO中使用的扩展中断13的函数组,请参考

/* 检测是否支持扩展13中断 */

#include <dos.h>
/* return 1 if supports, return 0 if not */
int checkExtInt13(int driveNum)
{
       
        union REGS in,out;
       
        in.h.ah=0x41;
        in.h.dl=driveNum;
        in.x.bx=0x55AA;
       
        int86(0x13,&in,&out);
       
        if(out.x.bx==0xAA55) return 1;
        else return 0;
       
}


/* 用扩展13中断获取硬盘参数 */
/* #include "zlib.h" */
#include <dos.h>
#include <stdio.h>
/* #include "zlib.h" */
/*
#define  BYTE unsigned char /*定义字节数据类型名

#define  unsigned short unsigned short /*定义字数据类型名

#define  Dunsigned short unsigned long /*定义双字数据类型名
*/

/* return 0 if succeeds, return non-0 if fails */
int extInt13DriveParameter(int driveNum,
                                                   unsigned long *maxCylinder,
                                                   unsigned long *maxHead,
                                                   unsigned long *maxSector,
                                                   unsigned long *totalSector)
{

        /*
        unsigned long cylinder=0;
        unsigned long head=0;
        unsigned long sector=0;
        unsigned long totalSectorVar=0;  */

        union REGS regs;
    struct SREGS sregs;
       
    struct {
               
                unsigned short size; /*地址包大小*/
               
                unsigned short inforflags; /*信息标志*/
               
                unsigned long cylns; /*物理柱面数*/

                unsigned long heads; /*物理磁头数*/
               
                unsigned long sects; /*物理每柱扇区数*/
               
                unsigned long tslow; /*扇区总数低位*/
               
                unsigned long tshi; /*扇区总数高位*/
               
                unsigned short  bps; /*每扇区字节数*/
               
    } package; /*LBA地址包定义*/
       
    regs.h.ah=0x48;
       
    regs.h.dl=(unsigned char)driveNum;
       
    sregs.ds=FP_SEG(&package); /*获得package的段地址*/
       
    regs.x.si=FP_OFF(&package); /*获得package的偏移量*/
       
    int86x(0x13,&regs,&regs,&sregs); /*调用中断*/
       
    if(regs.h.ah!=0) return regs.h.ah;


        *maxCylinder=package.cylns;
*maxHead=package.heads;
*maxSector=package.sects;
*totalSector=package.tslow;

        /*
        printf("Cylinders=%lu Heads=%lu Sectors=%lu\nTotal sectors=%lu (%lu.3f GB)\n",cylinder,head,sector,totalSectorVar,totalSectorVar*512);
        */
  /*
        printf("Cylinders=%lu Heads=%lu Sectors=%lu\nTotal sectors=%lu (%lu MB)\n\n",
                package.cylns,package.heads,package.sects,package.tslow,package.tslow/2/1024);
        /*
        printf("Cylinders=%lu Heads=%lu Sectors=%lu\nTotal sectors=%lu (%lu.3f GB)\n",*maxCylinder,*maxHead,*maxSector,*totalSector,(*totalSector)*512);
        */


   /*
*maxCylinder=cylinder;
*maxHead=head;
*maxSector=sector;
          *totalSector=totalSectorVar;
        */

        return 0;

}

/* 扩展13中断,可读写大硬盘 */
#include <dos.h>
/* return 0 if succeeds, return non-0 if fails */
int extInt13(unsigned int cmd,
                         int driveNum,
                         unsigned long startSector,
                         unsigned int sectorToDo,
                         char *buf)
{
        union REGS in,out;
        struct SREGS sregs;
        struct DiskAddressPacket
        {
                unsigned char PacketSize; /* 数据包尺寸(16字节) */
                unsigned char Reserved; /* ==0 */
                unsigned int BlockCount; /* 要传输的数据块个数(以扇区为单位) */
                unsigned int BufferAddrOFF; /* 缓冲地址偏移 */
                unsigned int BufferAddrSEG; /* 缓冲地址段地址 */
                unsigned long BlockNumLow; /* 磁盘起始绝对块地址低位,支持4G的扇区数,就是2048G字节 */
                unsigned long BlockNumHigh; /* 磁盘起始绝对块地址高位,可支持天文数字的GB,本程序未用,置0 */
        }dap;
        dap.PacketSize=16;
        dap.Reserved=0;
        dap.BlockCount=sectorToDo;
        dap.BufferAddrOFF=FP_OFF(buf);
        dap.BufferAddrSEG=FP_SEG(buf);
        dap.BlockNumLow=startSector;
        dap.BlockNumHigh=0;
       
        in.h.ah = cmd;
        in.h.dl = driveNum;
        in.h.al = 0; /* 0 为无写校验,1为有 */
        in.x.si = FP_OFF(&dap);
        sregs.ds =  FP_SEG(&dap);
       
        int86x(0x13,&in,&out,&sregs);
        return out.h.ah;
       
}

/* 13中断的出错提示 */
void int13Error(int cmd, int drive, unsigned long start, int returnValue)
{       
   /*        if(cmd==0x42)*/
   printf("\n%s drive:%d sector:%lu error\n",(cmd==0x42 ? "Read" : "Write"),drive,start);
        /*else
        {
        if(cmd==0x43) printf("\nWrite drive error : \n");
        }    */
       
        /* 基本13中断 */
        switch(returnValue)
        {
        case 0x01 : printf("Bad command.\n"); break;
               
        case 0x02 : printf("Address mark not found.\n"); break;
               
        case 0x03 : printf("Attempt to write to write-protected disk.\n"); break;
               
        case 0x04 : printf("Sector not found.\n"); break;
               
        case 0x05 : printf("Reset failed (hard disk).\n"); break;
               
        case 0x06 : printf("Disk changed since last operation.\n"); break;
               
        case 0x07 : printf("Drive parameter activity failed.\n"); break;
               
        case 0x08 : printf("Direct memory access (DMA) overrun.\n"); break;
               
        case 0x09 : printf("Attempt to perform DMA across 64K boundary.\n"); break;
               
        case 0x0A : printf("Bad sector detected.\n"); break;
               
        case 0x0B : printf("Bad track detected.\n"); break;
               
        case 0x0C : printf("Unsupported track.\n"); break;
               
        case 0x10 : printf("Bad CRC/ECC on disk read.\n"); break;
               
        case 0x11 : printf("CRC/ECC corrected data error.\n"); break;
               
        case 0x20 : printf("Controller has failed.\n"); break;
               
        case 0x40 : printf("Seek operation failed.\n"); break;

        case 0x80 : printf("Attachment failed to respond.\n"); break;
               
        case 0xAA : printf("Drive not ready (hard disk only).\n"); break;
               
        case 0xBB : printf("Undefined error occurred (hard disk only).\n"); break;
               
        case 0xCC : printf("Write fault occurred.\n"); break;
               
        case 0xE0 : printf("Status error.\n"); break;
               
        case 0xFF : printf("Sense operation failed.\n"); break;
               
                /* 扩展的13中断 */
        case 0xB0 : printf("Media in drive not locked.\n"); break;
               
        case 0xB1 : printf("Media in drive locked.\n"); break;
               
        case 0xB2 : printf("Media portable.\n"); break;
               
        case 0xB3 : printf("Media being in use.\n"); break;
               
        case 0xB4 : printf("Count of lock overflow.\n"); break;
               
        case 0xB5 : printf("legal request of ejection failed.\n"); break;
        }
       
}

使用:

操作: 0x42 读 0x43 写

if(extInt13(操作,drive+127,0,1,pBuffer))
int13Error(操作,int13Return);

2007-4-21 00:22
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
beiyuly
初级用户





积分 95
发帖 40
注册 2006-10-8
状态 离线
『第 3 楼』:  

thanks,

但是扩展int13的机制原理,这位大虾知道么?



http://beiyu.bokee.com
2007-4-22 02:42
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
GOTOmsdos
铂金会员

C++启程者


积分 5154
发帖 1827
注册 2003-7-18
状态 离线
『第 4 楼』:  

其中,主要的一条是扩展中断13不通过寄存器存放数据,而是通过包,而只是把这个包的地址传给寄存器,这样就没有突破了原有的限制

2007-4-22 05:17
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
zyl910
中级用户





积分 282
发帖 126
注册 2006-5-17
状态 离线
『第 5 楼』:  

http://blog.csdn.net/xqd2006/articles/914053.aspx
ATA 接口技术

伍红兵 沈鑫剡


……

4 IDE寄存器及IDE命令

……

  (4)扇区号寄存器(1F3H R/W):它记录读、写和校验命令指定的起始扇区号。如果驱动器使用逻辑块寻址(LBA,logical lock address)方式,该寄存器记录逻辑扇区号的0字节。
  (5)柱面号寄存器:(1F4H 1F5H R/W):它记录读、写、校验、寻址和格式化命令指定的柱面号,ATA标准允许65536柱面,但早期的IDE控制器中只允许1024个柱面。低8位在1F4H寄存器中,高8位在1F5H寄存器中。如果是LBA寻址方式,这2个寄存器包含起始扇区的1和2字节。
  (6)驱动器/磁头寄存器(1F6H R/W):它记录读、写、校验、寻道和格式化命令指定的驱动器号、磁头号和寻址方式。其定义如表5所示。

表5 驱动器/磁头寄存器定义

D7 D6 D5 D4 D3 D2 D1 D0
1 L 1 DRV HS3 HS2 HS1 HS0

  HS0~HS3(磁头选择):在LBA方式中,是逻辑扇区号的高4位。
  DRV(驱动器选择):0选择主驱动器,1选择从驱动器。
  L(LBA方式):L=1,置驱动器为LBA模式;L=0,置驱动器为CHS模式。



人类存在的目的就是试图理解人类为何存在
2007-4-24 22:24
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
beiyuly
初级用户





积分 95
发帖 40
注册 2006-10-8
状态 离线
『第 6 楼』:  



  Quote:
Originally posted by zyl910 at 2007-4-24 22:24:
http://blog.csdn.net/xqd2006/articles/914053.aspx
ATA 接口技术

伍红兵 沈鑫剡


……

4 IDE寄存器及IDE命令

……

  (4)扇区号寄存器(1F3H ...

谢谢了.



http://beiyu.bokee.com
2007-4-26 00:24
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: