您好,欢迎访问三七文档
DOS下BIOS中断INT13H、IO端口直接编程读取IDE、SATA硬盘的参数和TC语言程序wxleasyland@sina.com2015.4一、背景华硕笔记本电脑A45VD,640GBSATA机械硬盘放在硬盘位,120GBSSDSATA硬盘放在光驱位。BIOS中设置SATA为AHCI方式(不是IDE兼容方式)。在WIN7看,SATA控制器是Intel7Series/C216ChipsetFamilySATAAHCIController,硬件ID是VEN_8086&DEV_1E03&CC_010601,位置在PCI总线0,设备31,功能2。640GB机械硬盘是在CHANNEL0(通道0,即安装在SATA控制器接口PORT0上)。120GBSSD硬盘是在通道2(即安装在SATA控制器接口PORT2上)。SSD设置成为启动盘。因为BIOS启动设置是SSD硬盘,故在DOS下,机械硬盘就排第2了,即磁盘号81H。以下均是对640GB机械硬盘进行分析。二、INT13H传统中断,AH=08H(1)读取驱动器参数AH=08H入口:DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘返回:CF=1——操作失败,AH=状态代码CF=0成功BL=01H—360K=02H—1.2M=03H—720K=04H—1.44M=05H??=06H2.88M=10HATAPI可移动介质CH=最大柱面号的低8位loweightbitsofmaximumcylindernumber(柱面号从0开始算)CL的位7-6=最大柱面号的高2位hightwobitsofmaximumcylindernumberCL的位5-0=最大扇区号maximumsectornumber(扇区号从1开始算)DH=最大磁头号maximumheadnumber(磁头号从0开始算)DL=驱动器数numberofdrivesES:DI=磁盘驱动器参数表地址(只软驱)(2)注意:1.得到的数值是“编号”、不是“总个数”!“总个数”是numberof...“编号”是xxxnumber扇区号从1开始,故扇区数=最大扇区号磁头号从0开始,故磁头数=最大磁头号+12.BIOS保留最后1个柱用于测试目的,这个柱不报告出来,而且柱面号从0开始,所以柱面总个数=最大柱面号+2!Thereisonetestcylinder,Itislastcylinderondrive,whichisalwaysreservedfortestpurposes,andthereforenotreportedbyBIOStobe.(这点说明在)这两点说明看似简单,但是是经过研究很久才知道的!!!(3)实测U盘软驱启动,98版DOS下DEBUG,INT13H,AH=08H,DL=81H硬盘:得到AX=0,BX=0,CH=FE(1022,即0~1022+1柱号),CL=FF(63,即1~63扇号),DH=FE(254,即0~254头号),DL=2(即2个硬盘),ES:DI没有数据。即1024柱×255头×63扇=16450560扇,合8.4G硬盘,总容量不一致。可以看出,除柱面个数外,磁头数、扇区数与后面DISKMAN一致。可以将柱面个数单独计算,柱面个数=实际LBA总扇区数÷头数÷每道扇区数,DISKMAN就是这么做的。三、INT13H扩展中断,AH=48H(1)获取磁盘参数入口:AH=48HDL=驱动器号DS:SI=指向缓冲区的指针(即返回的数据会保存在这个缓冲区中)返回:失败:AH=错误号CF置位成功:AH=0CF=0缓冲区中偏移量:04H双字柱面总个数――注意:是“总个数”08H双字物理磁头总个数0CH双字物理每道扇区总个数10H4字扇区总个数18H字每扇区字节数(2)实测U盘软驱启动,98版DOS下DEBUG,INT13H扩展,AH=48H,DL=81H硬盘,得到:16383柱,16头,63扇,乘起来是16514064总扇区,即8.4G的硬盘,总容量不一致。总扇区数是1250263728扇区,OK,总扇区数与AIDA,DISKMAN检测是一致的。(3)分析“INT13H扩展”返回的是16头,而“INT13传统”返回的是255头!!“INT13H扩展”返回的直接就是硬盘的ATA参数,即与直接访问硬盘端口得到的参数是一样的!而“INT13传统”返回的数值是BIOS加工转换后的,与分区表中的格式相一致。ATA参数一般是16头最多了,而分区表中参数会是255头。也就是说,硬盘的ATA参数格式,与分区表参数格式是不一样的,所以造成了早期硬盘的一些容量限制问题。四、DISKMAN用USB软驱启动到DOS,运行DISKMAN(打开时提示分区不对,忽略之),显示是“第2硬盘”。DISKMAN得到的参数说明下:DISKMAN的CMOS参数CHS,12289柱面,255磁头,63扇区,是按照“传统INT13H”AH=08来得到的。其中,柱面数是反算的,去掉小数,转成16进制,因变量只有2字节,只能保存低2字节,即1250263728总扇÷255头÷63扇=77825.32柱→0x13001,只能保存2字节,故是0x3001→12289柱。“总扇区数”1250263728,是按“INT13H扩展”得到的。五、分区表与“传统INT13H”兼容分区表中,主分区和扩展分区必须要从新柱面开始(扩展分区中的逻辑盘不用)。通过研究640GB机械硬盘上分区表中的分区起始LBA地址,看能不能被头、扇整除。发现分区是按255头、63扇来分的,而不是16头。即与“传统INT13H”兼容。即分区软件分区时,要以“传统INT13H”得到的参数(柱面数除外)去进行分区。六、BIOS是支持SATA硬盘读写的从前面可看出,BIOS是直接支持SATA硬盘的读写的,用“INT13H扩展”访问即可!!因为主板厂家自己知道是用什么型号的SATA控制器,知道如何去控制它,并且它还要读取硬盘的MBR进行启动,所以BIOS必须支持SATA硬盘读写。所以DOS下直接用INT13H即可读写SATA硬盘扇区,用GHOST软件克隆就不是问题了。那为什么XP安装时,需要加载SATA驱动?因为WINDOWS不使用INT13H去访问硬盘,而是自己要去底层访问SATA控制器,如果它不认识SATA控制器,就访问不了硬盘了。七、直接IO读取IDE硬盘(1)ATA控制器、IDE硬盘在电脑上,连接结构是这样的:CPU――数据总线、地址总线、控制总线――PCI控制器――PCI总线――ATA控制器∧∧|硬盘线|∨∨IDE接口硬盘硬盘IDE接口的数据线、控制线、地址线是分开的,IDE硬盘线有40芯之多,数据口直接挂在PCI的总线上,所以CPU可以直接访问到它。ATA控制器是把IO端口地址转换到IDE硬盘接口上,从而CPU可以IN、OUT这些IO端口,直接访问到硬盘!因此,IDE硬盘的IO端口是固定的,一组为命令寄存器组(TaskFileRegisters),I/O的端口地址为1F0H~1F7H,其作用是传送命令与命令参数。另一组为控制/诊断寄存器(Control/DiagnosticRegisters),I/O的端口地址为3F6H~3F7H,其作用是控制硬盘驱动器。可以直接用单片机直接控制IDE硬盘:单片机――40芯硬盘线――IDE硬盘这个比较容易就能实现,将IDE接口的数据线、控制线、地址线分别连线控制就可以,物理电气信号连接不复杂。注:ATA应是指协议标准,IDE应是指接口相关详细说明可参考《如何在MCS-51系统中使用IDE硬盘》、《IDE接口硬盘读写技术》、《基于单片机的IDE硬盘控制的研究与设计》等文章。(2)访问方法引用别人说的(有修改):①向端口3F6H写入控制字节,建立相应的硬盘控制方式;②检验硬盘控制器和驱动器的状态(检测端口的第7和第6两位),如果控制器空闲而且驱动器就绪,即可输入命令;③完整的输入7个字节长度的命令块,一次写入端口1F1H-1F7H,不论是否需要,端口1F1H-1F6H对应的6个字节的参数必须给出,端口1F7H的输出命令码为“0ECH”;④检测端口1F7H的第7和第3两位,如果控制器空闲且第3位置1,表示操作结束,即可读取结果;⑤通过端口1F0H读取数据,读取256个WORD到缓冲区,注意这里的数据是WORD16位(2字节)的;⑥再次读取端口1F7H,判断第0位是否为0,如果为0,表示命令成功,否则表示命令失败;读出的256字节信息的主要内容如下:偏移量内容长度(字节)00-01H2字节02H-03H柱面总个数2字节04-05H2字节06H-07H磁头总个数2字节08H-09H每磁道所含的字节数2字节0AH-0BH每扇区所含的字节数2字节0CH-0DH每磁道所含的扇区个数2字节0EH-13H6字节14H-27H产品的序列号20字节28H-29H2字节2AH-2BH硬盘缓冲区容量2字节2CH-2DHECC校验码的长度2字节2EH-35H硬件软体版本号8字节36H-5DH硬盘型号40字节(3)程序引用别人的(有修改),wxlhd1.c:#includestdio.h#includebios.h#includestdlib.h#includeconio.h#includedos.h#defineBASEADDR1F00x1F0#defineBASEADDR3F60x3F6voidhdinfor2(){unsignedinti,j;unsignedcharp;j=0;p=0;while(p!=0x40)/*必须RDY,并且不忙。读1f7H状态寄存器01000000bit6=1表示RDY*/{j++;if(j=255){printf(error1!NOTRDY&NOTBSY.ERRREG=%02X,inportb(BASEADDR1F0+1));exit(0);}p=inportb(BASEADDR1F0+7);printf(%02X,p);p&=0xc0;/*11000000bit6=1表示RDY,BIT7=1是忙*/}printf(ok1\n);outportb(BASEADDR3F6,0);/*写3F6H设备控制寄存器00000000BIT1中断允许BIT2非复位*/for(i=0;i5;i++)outportb(BASEADDR1F0+1+i,0);/*写1F1H~1F5H*/outportb(BASEADDR1F0+6,0xa0);/*驱动器/磁头寄存器10100000BIT6=0非LBA方式*/outportb(BASEADDR1F0+7,0xec);/*写命令寄存器*/j=0;p=0;while(p!=0x8)/*必须有中断请求产生,并且不忙*/{j++;if(j=255){printf(error2!NOTRDY&NOTIRQ.ERRREG=%02X,inportb(BASEADDR1F0+1));exit(0);}p=inportb(BASEADDR1F0+7);printf(%02X,p);p&=0x88;/*10001000BIT3=1是有中断请求,BIT7=1是忙*/}printf(ok2\n);/*读1F0H数据寄存器*/p=0;for(i=0;i256;i++){j=inport(BASEADDR1F0);/*应该要一次读出2字节,而不是1字节!所以用inport。硬盘中就是高字节在后,inport读出来就是高字节放在高字节上。比如硬盘中是1122,inport读出来就是0x2211*/printf(%02X%02X,(unsignedchar)j,(unsignedchar)(j8));p++;if(p=8){/*printf(\n);*/p=0;}}return;}voidmain(){hdinfor2();}(4)DOS下运行在DOS下运行,肯定
本文标题:DOS下BIOS中断INT13H、IO端口直接编程读取IDE、SATA硬盘的参数和TC语言程序
链接地址:https://www.777doc.com/doc-5470090 .html