首页 > 其他分享 >自己动手从零写桌面操作系统GrapeOS系列教程——19.硬盘读写理论知识

自己动手从零写桌面操作系统GrapeOS系列教程——19.硬盘读写理论知识

时间:2023-03-20 09:44:12浏览次数:484  
标签:LBA 控制器 19 写入 端口 扇区 GrapeOS 桌面操作系统 硬盘

学习操作系统原理最好的方法是自己写一个简单的操作系统。


一、硬盘控制器

我们前面已经讲过硬盘控制器是一种I/O接口,CPU通过它就能间接的读写硬盘。硬盘控制器主要有IDE和SATA两种,我们这里只考虑IDE控制器。
电脑里硬盘控制器有2个,一个叫主控制器,另一个叫从控制器。而每个硬盘控制器能连接两个硬盘,一个叫主盘,另一个叫从盘。所以一般一台电脑里最多能安装4个硬盘。

二、硬盘控制器端口

硬盘控制器上的端口很多,下表中只列出我们可能用到的。

I/O端口号 端口用途 端口位数
主控制器 从控制器 读取操作 写入操作
0x1f00x170DataData16
0x1f10x171ErrorFeatures8
0x1f20x172Sector countSector count8
0x1f30x173LBA lowLBA low8
0x1f40x174LBA midLBA mid8
0x1f50x175LBA highLBA high8
0x1f60x176DeviceDevice8
0x1f70x177StatusCommand8

关于上面这张表,其中的端口号不用记,用的时候翻看一下这里就行。从控制器与主控制器除了端口号不同,其它完全相同,以下我们以主控制器为例讲解。需要注意的是同一个端口在读端口和写端口两种操作下可能用途不一样,比如上表里的0x1f1和0x1f7。

端口0x1f0

首先看第1个端口0x1f0,它是这个表中唯一的16位端口,其它都是8位。从硬盘读取的数据或向硬盘写入的数据都是经过这个端口中转的。之前我们讲过硬盘是按扇区读写的,每个扇区都是512个字节,对硬盘每次读写的数据量都是512字节的整数倍。而这个端口是16位,也就是2个字节。如果你要读取一个扇区的数据,需要从这个端口连续读取256次。同样,写一个扇区,也需要向这个端口连续写入256次。

端口0x1f1

下面来看第二个端口0x1f1,在8个端口中,GrapeOS没有用到这个端口,其它都用到了。虽然没有用到,但还是简单介绍一下。当读操作时,里面保存的是错误信息;当写操作时,曾经需要向该端口写入一些参数,目前已废弃。

端口0x1f2

继续看第三个端口0x1f2,该端口保存的是读取或写入硬盘的扇区数量。该端口是8位端口,取值范围是0~255,但当设置为0时,表示读或写256个扇区。也就是说一次读写操作,最多读写256个扇区。

端口0x1f3~0x1f5

往下3个端口0x1f3、0x1f4、0x1f5是存放读取或写入硬盘时的起始扇区编号。这里用的扇区编号方式叫LBA或LBA28,意思是扇区从0开始编号,用28位二进制数来表示扇区号,最多表示2的28次方个扇区,由于每个扇区512字节,所以最大支持128GB的硬盘。对GrapeOS来说足够了。这里需要注意的是28位是3个半字节,这里的3个端口中,0x1f3存放LBA中的最低1个字节(0 ~ 7位),0x1f4存放中间的那个字节(8 ~ 15位),0x1f5存放高处的那个字节(16 ~ 23位),还剩下最高的半个字节(24 ~ 27位)存放在下个端口0x1f6中。

端口0x1f6

接着看0x1f6端口。这个端口中的低4位存放LBA中的最高4位(24~27位)。第4位0表示主盘,1表示从盘。第6位表示扇区寻址模式,0表示CHS,是一种古老的模式,1表示LBA,我们选LBA。另外第5位和第7位固定为1。参见下表:

bit内容说明
71固定为1。
6MOD选择寻址模式,0为CHS模式,1为LBA模式。
51固定为1。
4DEV选择硬盘驱动器,0为主硬盘,1为从硬盘。
3[27]LBA地址的第24~27位。
2[26]
1[25]
0[24]

端口0x1f7

我们来看最后一个端口0x1f7,这个端口有两种用途。
如果读取该端口,该端口将作为状态端口,可以获得硬盘的状态信息。如下表所示,该端口8个位中已经有4个位废弃了,有用的是另外4个位。

bit 内容 说明
7 BSY 此位为1表示硬盘正忙,勿扰。
6 DRDY 此位为1表示设备就绪,等待指令。
5 已废弃。
4 已废弃。
3 DRQ 此位为1表示可以从数据端口读写硬盘数据了。
2 已废弃。
1 已废弃。
0 ERR 此位为1表示有错误发生,错误信息见Error寄存器。

如果写入该端口时,该端口将作为命令端口,需要向该端口写入合适的命令。在GrapeOS中只用到两个命令:

  • 读命令:0x20
  • 写命令:0x30

三、硬盘操作方法

在GrapeOS中只有一块硬盘,安装在了主硬盘控制器主盘的位置,下面讲解读写硬盘时的操作步骤。

读硬盘操作步骤

  1. 读取Status端口,如果该端口位7为0,第6位为1,进入下一步,否则循环当前步骤。
  2. 向Sector count端口中写入要读入的扇区数。
  3. 向LBA low、LBA mid、LBA high3个端口依次写入LBA起始扇区号的低24位。
  4. 向Device端口写入LBA起始扇区号的24~27位,并置第4位为0,第6位为1。
  5. 向Command端口写入0x20。
  6. 读取Status端口,如果该端口位7为0,位3为1,则进入下一步,否则循环当前步骤。
  7. 从Data端口读取数据。如果读1个扇区,则循环读取该端口256次。

写硬盘操作步骤

  1. 读取Status端口,如果该端口位7为0,第6位为1,进入下一步,否则循环当前步骤。
  2. 向Sector count端口中写入要写入的扇区数。
  3. 向LBA low、LBA mid、LBA high3个端口依次写入LBA起始扇区号的低24位。
  4. 向Device端口写入LBA起始扇区号的24~27位,并置第4位为0,第6位为1。
  5. 向Command端口写入0x30。
  6. 读取Status端口,如果该端口位7为0,位3为1,则进入下一步,否则循环当前步骤。
  7. 向Data端口写入数据。如果写入1个扇区,则循环写入该端口256次。

读硬盘操作和写硬盘操作都是7个步骤,其中只有第5步和第7步不同,其它步骤完全相同。


本讲视频版地址:https://www.bilibili.com/video/BV1854y1M7vx/
配套的代码与资料在:https://gitee.com/jackchengyujia/grapeos-course
GrapeOS操作系统交流QQ群:643474045

标签:LBA,控制器,19,写入,端口,扇区,GrapeOS,桌面操作系统,硬盘
From: https://www.cnblogs.com/chengyujia/p/17235171.html

相关文章

  • 2023.3.19 规划
    规划比赛里面写不出来的,cf和atc打少了,自己模拟少了;但是这东西我得先知道,会写模板才行;主流的算法都得会不能到哪都简单搜索,那就到哪里都坐牢;所以先是去选择最靠......
  • 2023.3.19周学习总结
    一.本周任务进度1.线段树分裂合并学习完,并且练习了几个题2.上周的补题也补完了3.打了一把牛客和两把cf还有一把abc4.学习了斜率优化DP的凸包优化二.......
  • Spring Study-lesson14-事务-2023-03-19
    遵循ACID原则,这样保证批量事务其中一项报错,整个批量事务都不执行。案例:在spring-dao.xml中加载aop和tx注意细节:xmlns:aop(或tx)要有整个名字,另外注意>和“”的位......
  • 2023/3/19 考试总结
    其实今天没有什么好说的,四个半小时全在做第一题前两个小时在推式子,但其中一个半小时的式子是没用的。这时候突然知道正解怎么做了,发现是道水题,就花了一个半小时将代......
  • 3.19学习总结
    1.TextClock(文本时钟)TextClock是在Android4.2(API17)后推出的用来替代DigitalClock的一个控件!TextClock可以以字符串格式显示当前的日期和时间,因此推荐在Android4.2以后......
  • 学习日记23.3.19
    今天在参考大佬前端代码时发现了一个小东西<htmllang="en">直接百度了一波:<htmllang="en">向搜索引擎表示该页面是html语言,并且语言为英文网站,其"lang"的意思就是“lan......
  • 2023/3/19 考试总结
    时间安排8.30~9.00T1一眼乱搞,写了一个随机旋转之后取相邻的点,然后发现过不去1e6.9.00~9.40想了个类平面最近点对的分治做法,大样例跑的起飞。9.40~11.20想了很久T2,还......
  • 每日总结2023/3/19
    今日对页面的布局和背景进行了优化,代码行数大概30行。明日准备验收:   ......
  • C/C++个人收支管理系统[2023-03-19]
    C/C++个人收支管理系统[2023-03-19]5、个人收支管理请用C/C++编写一系统,实现个人收支管理模拟,包括收入、支出、查询与统计等功能。软件应包括如下几个方面:(一)功能要求......
  • 3.19每日总结
     今天学习了1h。数据库操作类新建一个类"UserDBHelper",这个类extendsSQLiteOpenHelperpublicclassUserDBHelperextendsSQLiteOpenHelper{}定义类内的成员变量p......