![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-10-31 21:27 |
共 47,815 主题排行 / 349,930 发帖 / 今日 0 篇 / 48,290 会员排行 |
| DOS开发编程 & 发展交流 (开发室) » 扩展int 13h 访问大硬盘问题 |
| 可打印版本 1,458 / 5 |
| 第1楼 beiyuly | 发表于 2007-04-20 23:33 |
| 初级用户 发帖 40 积分 95 | |
|
扩展int 13h 访问大硬盘问题 扩展int 13h 访问大硬盘问题
一般小硬盘的访问之需要int13h就可以了。通过c/h/s的3级访问方式,就可以访问整个硬盘,那么怎么访问大于8.2gb的硬盘数据空间呢? 通过扩展int13可以实现,那么扩展int13的机制是什么? 大虾出来看看了!` xiexie! |
|
| 第2楼 GOTOmsdos | 发表于 2007-04-21 00:22 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
以下是我写的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,®s,®s,&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); |
|
| 第3楼 beiyuly | 发表于 2007-04-22 02:42 |
| 初级用户 发帖 40 积分 95 | |
|
thanks,
但是扩展int13的机制原理,这位大虾知道么? |
|
| 第4楼 GOTOmsdos | 发表于 2007-04-22 05:17 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
其中,主要的一条是扩展中断13不通过寄存器存放数据,而是通过包,而只是把这个包的地址传给寄存器,这样就没有突破了原有的限制
|
|
| 第5楼 zyl910 | 发表于 2007-04-24 22:24 |
| 中级用户 发帖 126 积分 282 | |
|
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模式。 |
|
| 第6楼 beiyuly | 发表于 2007-04-26 00:24 |
| 初级用户 发帖 40 积分 95 | |
Originally posted by zyl910 at 2007-4-24 22:24: 谢谢了. |
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |