硬盘驱动程序功能简介
1.1 对硬盘操作的I/O端口
对硬盘控制器的操作是通过I/O端口来进行的,这些端口分为两组,它们对应命令块寄存器(Command Block Registers)和控制块寄存器(Control Block Registers),如下表
表1.硬盘I/O端口及寄存器
组别
I/O端口
读时
写时
Primary
Secondary
Commad Block Register
1F0h
170h
Data
Data
1F1h
171h
Error
Feature
1F2h
172h
Sector Count
Sector Count
1F3h
173h
LAB Low
LAB Low
1F4h
174h
LAB Mid
LAB Mid
1F5h
175h
LAB High
LAB High
1F6h
176h
Device
Device
1F7h
177h
Status
Command
Control Block Register
3F6h
376h
Alternate
Status
Device
Control
我们只需先往命令块寄存器(Commad Block Register)写入正确的值,在通过控制块寄存器(Control Block Register)发送命令就可以了。
1.2 硬盘的启动、打开
驱动程序收到DEV_OPEN消息之后调用hd_identify(),在这里我们改成了调用函数hd_oped()们这是新加的一个函数,它接受的参数即为设备的次设备号。在hd_oped()中,我们首先由设备次设备号得到驱动器号,由于我们的Bochs只定义了一个硬盘,所以这里的驱动器号一定是0。在程序中我们通过调用一系列函数结合DEV_OPEN消息完成硬盘的启动工作。
1.3 获取硬盘参数
驱动程序的作用在于隐藏硬件细节,向上层京城提供统一的接口。由于我们的进程通过收发消息相互通信,那么驱动程序的接口自然也是消息了。所以只要我们定义了驱动程序可以接收消息,也就定义了驱动程序的接口。为简单起见,我们先之定义一种消息:DEV_OPEN。可是硬盘驱动程序受到这个消息后干点什么呢?我们先来干点简单的工作:向硬盘驱动器发送IDENTIFY命令,到硬盘参数。向硬盘发送IDENTIFY命令很简单,只需要通过Device寄存器的第四位指定驱动器——0表示Master,1表示Slave——然后往Command寄存器写入十六进制ECh就可以。硬盘准备好参数之后,会产生一个中断,这时我们就可以通过Data寄存器读取数据了。参数有很多,总共是256个字,我们仅仅取出其中的几个值显示。
参数打印出来效果如图3.1下
图3.1
1.4 硬盘的分区
1.4.1 为什么要分区
其实可以直接利用整个硬盘的。但是,那样未免太浪费了。我们有个想法:就是将来将我们的这个操作系统装到自己的计算机上,虽然简陋了点,不过到时候稍微设置一下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
结束柱面号的低8位
8
1
起始扇区的LBA
12
1
扇区数目
我们的文件系统最终是安装在扩展分区的第一个分区里
1.4.2 分区效果
这里我们把硬盘分为了五个分区即:PART_0、PART_1、PART_2、PART_3、PART_4
图3.2
1.4.3 引导扇区
这里有必要介绍一下引导扇区的概念。
硬盘的引导扇区是计算机启动时首先读取的扇区,它的主要功能是首先装入引导操作系统的扇区,然后将控制权转交给装入的引导操作系统的扇区,引导操作系统安装.它不属于任何操作系统,因此一般的命令等不能直接读取它,但在Windows DOS状态下运行DEBUG.EXE程序,并输入如下程序段,即可读取主引导扇区。硬盘的第一个扇区被保留为主引导扇区,它位于整个硬盘的0磁道0柱面1扇区,包括硬盘主引导记录MBR(Main Boot Record)和分区表DPT(Disk Partition Table)。其中主引导记录的作用就是检查分区表是否正确以及确定哪个分区为引导分区,并在程序结束时把该分区的启动程序(也就是操作系统引导扇区)调入内存加以执行。至于分区表,很多人都知道,以80H或00H为开始标志,以55AAH为结束标志,共64字节,位于本扇区的最末端。
大致的结构如图3.2所示
图3.3
硬盘主引导扇区 = 硬盘主引导记录(MBR) + 硬盘分区表(DPT)
用FDISK 进行硬盘分区时产生的, 它属于整个硬盘而不属于某个独立的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,0200 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将系统控制权交给它时,判断本分区根目录前两个文件是不是操作系统的引导文件(以DOS为例,即是IO.sys 和Msdos.sys)。如果确定存在,就把其读入内存,并把控制权交给该文件。BPB参数块记录着本分区的起始扇区、结束扇区、文件存储
格式
pdf格式笔记格式下载页码格式下载公文格式下载简报格式下载
、硬盘介质描述符、根目录大小、FAT个数、分配单元的大小等重要参数。
1.5 硬盘的关闭(处理DEV_CLOSE消息)
硬盘的关闭与打开类似,使用的是硬盘支持的五种消息出来,DEV_CLOSE消息是其中的一种,驱动程序收到DEV_CLOSE消息之后调用hd_identify(),在这里我们改成了调用函数hd_close()们这是新加的一个函数。
1.6 硬盘驱动程序主循环
这里我把我们硬盘驱动程序的主循环的程序给大家分享。需要说明的是我们的程序是基于消息机制的,通过发送消息与处理消息实现需要的功能。至于消息机制是如何实现的不是本文讨论的内容。
PUBLIC void task_hd()
{
MESSAGE msg;
init_hd();
while (1) {
send_recv(RECEIVE, ANY, &msg);
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(&msg);
break;
case DEV_IOCTL:
hd_ioctl(&msg);
break;
default:
dump_msg("HD driver::unknown msg", &msg);
spin("FS::main_loop (invalid msg.type)");
break;
}
send_recv(SEND, src, &msg);
}
}