1、硬盘驱动程序功能简介1.1 对硬盘操作的 I/O 端口对硬盘控制器的操作是通过 I/O 端口来进行的,这些端口分为两组,它们对应命令块寄存器(Command Block Registers)和控制块寄存器(Control Block Registers) ,如下表表 1.硬盘 I/O 端口及寄存器I/O 端口组别Primary Secondary 读时 写时1F0h 170h Data Data1F1h 171h Error Feature1F2h 172h Sector Count Sector Count1F3h 173h LAB Low LAB Low1F4h 174h LAB Mid
2、LAB Mid1F5h 175h LAB High LAB High1F6h 176h Device DeviceCommad Block Register1F7h 177h Status CommandControl Block Register 3F6h 376hAlternate StatusDeviceControl我们只需先往命令块寄存器(Commad Block Register)写入正确的值,在通过控制块寄存器(Control Block Register )发送命令就可以了。1.2 硬盘的启动、打开驱动程序收到 DEV_OPEN 消息之后调用 hd_identify(),在这里
3、我们改成了调用函数hd_oped()们这是新加的一个函数,它接受的参数即为设备的次设备号。在 hd_oped()中,我们首先由设备次设备号得到驱动器号,由于我们的 Bochs 只定义了一个硬盘,所以这里的驱动器号一定是 0。在程序中我们通过调用一系列函数结合 DEV_OPEN 消息完成硬盘的启动工作。1.3 获取硬盘参数驱动程序的作用在于隐藏硬件细节,向上层京城提供统一的接口。由于我们的进程通过收发消息相互通信,那么驱动程序的接口自然也是消息了。所以只要我们定义了驱动程序可以接收消息,也就定义了驱动程序的接口。为简单起见,我们先之定义一种消息:DEV_OPEN。可是硬盘驱动程序受到这个消息后干
4、点什么呢?我们先来干点简单的工作:向硬盘驱动器发送 IDENTIFY 命令,到硬盘参数。向硬盘发送 IDENTIFY 命令很简单,只需要通过 Device 寄存器的第四位指定驱动器0 表示 Master,1 表示 Slave然后往Command 寄存器写入十六进制 ECh 就可以。硬盘准备好参数之后,会产生一个中断,这时我们就可以通过 Data 寄存器读取数据了。参数有很多,总共是 256 个字,我们仅仅取出其中的几个值显示。参数打印出来效果如图 3.1 下图 3.11.4 硬盘的分区1.4.1 为什么要分区其实可以直接利用整个硬盘的。但是,那样未免太浪费了。我们有个想法:就是将来将我们的这个
5、操作系统装到自己的计算机上,虽然简陋了点,不过到时候稍微设置一下Grub,实现多引导,让我们的操作系统跟 Linux,Windows 等并存,岂不美哉?!硬盘分区表其实是一个结构体数组,数组的每个成员是一个 16 字节的结构体,其构成如下表 1.分区表结构偏移 长度 描述0 1 状态(80h=可引导,00h= 不可引导,其他= 不合法)1 1 起始磁头号2 1 起始扇区号(仅用低 6 位,高 2 位位起始柱面号的第 8,9 位)3 1 起始柱面号的低 8 位4 1 分区类型(System ID)5 1 结束磁头号6 1 结束扇区号(仅用低 6 位,高 2 位位结束柱面号的第 8,9 位)7 1
6、 结束柱面号的低 8 位8 1 起始扇区的 LBA12 1 扇区数目我们的文件系统最终是安装在扩展分区的第一个分区里1.4.2 分区效果这里我们把硬盘分为了五个分区即:PART_0、PART_1、PART_2、PART_3、PART_4图 3.21.4.3 引导扇区这里有必要介绍一下引导扇区的概念。硬盘的引导扇区是计算机启动时首先读取的扇区,它的主要功能是首先装入引导操作系统的扇区,然后将控制权转交给装入的引导操作系统的扇区,引导操作系统安装它不属于任何操作系统,因此一般的命令等不能直接读取它,但在 Windows DOS 状态下运行DEBUGEXE 程序,并输入如下程序段,即可读取主引导扇区
7、。硬盘的第一个扇区被保留为主引导扇区,它位于整个硬盘的 0 磁道 0 柱面 1 扇区,包括硬盘主引导记录 MBR(Main Boot Record)和分区表 DPT(Disk Partition Table)。其中主引导记录的作用就是检查分区表是否正确以及确定哪个分区为引导分区,并在程序结束时把该分区的启动程序(也就是操作系统引导扇区)调入内存加以执行。至于分区表,很多人都知道,以 80H 或 00H 为开始标志,以 55AAH 为结束标志,共 64 字节,位于本扇区的最末端。 大致的结构如图 3.2 所示图 3.3硬盘主引导扇区 = 硬盘主引导记录(MBR) + 硬盘分区表(DPT)用 FD
8、ISK 进行硬盘分区时产生的, 它属于整个硬盘而不属于某个独立的 DOS 分区, 是硬盘正确引导和使用的必要条件。物理位置:0 柱面 0 磁头 1 扇区(Cylinder 0, Head 0, Sector 1) 系统扇区(System Secotrs) : 0C-0H-2S,0C-0H-63S, 共 62 Sectors 大小:512 字节其中:MBR 446 字节(0000-01BD),DPT 64 字节(01BE-01FD),结束标志 2 字节(55 AA)功能:MBR 通过检查 DPT 分区信息引导系统跳转至 DBR详解: (DEBUG -A: MOV AX,0201 MOV BX,0
9、200 MOV CX,0001 MOV DX,0080 INT 13)000H-08AH MBR 启动程序(寻找开机分区)08BH-0D9H MBR 启动字符串0DAH-1BCH 保留( “0 “)1BEH-1FDH 硬盘分区表1FEH-1FFH 结束标志(55AA)硬盘 DBR(操作系统引导记录区),它通常位于硬盘的 0 磁道 1 柱面 1 扇区,是操作系统可以直接访问的第一个扇区,它包括一个引导程序和一个被称为 BPB(Bios Parameter Block)的本分区参数记录表。引导程序的主要任务是当 MBR 将系统控制权交给它时,判断本分区根目录前两个文件是不是操作系统的引导文件(以
10、DOS 为例,即是 IO.sys 和 Msdos.sys)。如果确定存在,就把其读入内存,并把控制权交给该文件。BPB 参数块记录着本分区的起始扇区、结束扇区、文件存储格式、硬盘介质描述符、根目录大小、FAT 个数、分配单元的大小等重要参数。1.5 硬盘的关闭(处理 DEV_CLOSE 消息)硬盘的关闭与打开类似,使用的是硬盘支持的五种消息出来,DEV_CLOSE 消息是其中的一种,驱动程序收到 DEV_CLOSE 消息之后调用 hd_identify(),在这里我们改成了调用函数 hd_close()们这是新加的一个函数。1.6 硬盘驱动程序主循环这里我把我们硬盘驱动程序的主循环的程序给大家
11、分享。需要说明的是我们的程序是基于消息机制的,通过发送消息与处理消息实现需要的功能。至于消息机制是如何实现的不是本文讨论的内容。PUBLIC void task_hd()MESSAGE msg;init_hd();while (1) send_recv(RECEIVE, ANY, int src = msg.source;switch (msg.type) case DEV_OPEN:hd_open(msg.DEVICE);break;case DEV_CLOSE:hd_close(msg.DEVICE);break;case DEV_READ:case DEV_WRITE:hd_rdwt(break;case DEV_IOCTL:hd_ioctl(break;default:dump_msg(“HD driver:unknown msg“, spin(“FS:main_loop (invalid msg.type)“);break;send_recv(SEND, src,