學習操作系統原理最好的方法是自己寫一個簡單的操作系統。
一、硬盤控制器
我們前面已經講過硬盤控制器是一種I/O接口,CPU通過它就能間接的讀寫硬盤。硬盤控制器主要有IDE和SATA兩種,我們這裏只考慮IDE控制器。
電腦裏硬盤控制器有2個,一個叫主控制器,另一個叫從控制器。而每個硬盤控制器能連接兩個硬盤,一個叫主盤,另一個叫從盤。所以一般一臺電腦裏最多能安裝4個硬盤。
二、硬盤控制器端口
硬盤控制器上的端口很多,下表中只列出我們可能用到的。
I/O端口號 | 端口用途 | 端口位數 | |||
---|---|---|---|---|---|
主控制器 | 從控制器 | 讀取操作 | 寫入操作 | ||
0x1f0 | 0x170 | Data | Data | 16 | |
0x1f1 | 0x171 | Error | Features | 8 | |
0x1f2 | 0x172 | Sector count | Sector count | 8 | |
0x1f3 | 0x173 | LBA low | LBA low | 8 | |
0x1f4 | 0x174 | LBA mid | LBA mid | 8 | |
0x1f5 | 0x175 | LBA high | LBA high | 8 | |
0x1f6 | 0x176 | Device | Device | 8 | |
0x1f7 | 0x177 | Status | Command | 8 |
關於上面這張表,其中的端口號不用記,用的時候翻看一下這裏就行。從控制器與主控制器除了端口號不同,其它完全相同,以下我們以主控制器爲例講解。需要注意的是同一個端口在讀端口和寫端口兩種操作下可能用途不一樣,比如上表裏的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 | 內容 | 說明 |
---|---|---|
7 | 1 | 固定爲1。 |
6 | MOD | 選擇尋址模式,0爲CHS模式,1爲LBA模式。 |
5 | 1 | 固定爲1。 |
4 | DEV | 選擇硬盤驅動器,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中只有一塊硬盤,安裝在了主硬盤控制器主盤的位置,下面講解讀寫硬盤時的操作步驟。
讀硬盤操作步驟
- 讀取Status端口,如果該端口位7爲0,第6位爲1,進入下一步,否則循環當前步驟。
- 向Sector count端口中寫入要讀入的扇區數。
- 向LBA low、LBA mid、LBA high3個端口依次寫入LBA起始扇區號的低24位。
- 向Device端口寫入LBA起始扇區號的24~27位,並置第4位爲0,第6位爲1。
- 向Command端口寫入0x20。
- 讀取Status端口,如果該端口位7爲0,位3爲1,則進入下一步,否則循環當前步驟。
- 從Data端口讀取數據。如果讀1個扇區,則循環讀取該端口256次。
寫硬盤操作步驟
- 讀取Status端口,如果該端口位7爲0,第6位爲1,進入下一步,否則循環當前步驟。
- 向Sector count端口中寫入要寫入的扇區數。
- 向LBA low、LBA mid、LBA high3個端口依次寫入LBA起始扇區號的低24位。
- 向Device端口寫入LBA起始扇區號的24~27位,並置第4位爲0,第6位爲1。
- 向Command端口寫入0x30。
- 讀取Status端口,如果該端口位7爲0,位3爲1,則進入下一步,否則循環當前步驟。
- 向Data端口寫入數據。如果寫入1個扇區,則循環寫入該端口256次。
讀硬盤操作和寫硬盤操作都是7個步驟,其中只有第5步和第7步不同,其它步驟完全相同。
本講視頻版地址:https://www.bilibili.com/video/BV1854y1M7vx/
配套的代碼與資料在:https://gitee.com/jackchengyujia/grapeos-course
GrapeOS操作系統交流QQ羣:643474045