第二部分 技術資料
第一章 擴展 Int13H 技術資料
一. 簡介
設計擴展 Int13H 接口的目的是爲了擴展 BIOS 的功能, 使其支持
多於1024柱面的硬盤, 以及可移動介質的瑣定, 解鎖及彈出等功能.
二. 數據結構
1. 數據類型約定
BYTE 1 字節整型 ( 8 位 )
WORD 2 字節整型 ( 16 位 )
DWORD 4 字節整型 ( 32 位 )
QWORD 8 字節整型 ( 64 位 )
2. 磁盤地址數據包 Disk Address Packet (DAP)
DAP 是基於絕對扇區地址的, 因此利用 DAP, Int13H 可以輕鬆地逾
越 1024 柱面的限制, 因爲它根本就不需要 CHS 的概念.
DAP 的結構如下:
struct DiskAddressPacket
{
BYTE PacketSize; // 數據包尺寸(16字節)
BYTE Reserved; // ==0
WORD BlockCount; // 要傳輸的數據塊個數(以扇區爲單位)
DWORD BufferAddr; // 傳輸緩衝地址(segment:offset)
QWORD BlockNum; // 磁盤起始絕對塊地址
};
PacketSize 保存了 DAP 結構的尺寸, 以便將來對其進行擴充. 在
目前使用的擴展 Int13H 版本中 PacketSize 恆等於 16. 如果它小於
16, 擴展 Int13H 將返回錯誤碼( AH=01, CF=1 ).
BlockCount 對於輸入來說是需要傳輸的數據塊總數, 對於輸出來說
是實際傳輸的數據塊個數. BlockCount = 0 表示不傳輸任何數據塊.
BufferAddr 是傳輸數據緩衝區的 32 位地址 (段地址:偏移量). 數據
緩衝區必須位於常規內存以內(1M).
BlockNum 表示的是從磁盤開始算起的絕對塊地址(以扇區爲單位),
與分區無關. 第一個塊地址爲 0. 一般來說, BlockNum 與 CHS 地址的關係
是:
BlockNum = cylinder * NumberOfHeads +
head * SectorsPerTrack +
sector - 1;
其中 cylinder, head, sector 是 CHS 地址, NumberOfHeads 是磁盤
的磁頭數, SectorsPerTrack 是磁盤每磁道的扇區數.
也就是說 BlockNum 是沿着 扇區->磁道->柱面 的順序記數的. 這一順
序是由磁盤控制器虛擬的, 磁盤表面數據塊的實際排列順序可能與此不同
(如爲了提高磁盤速度而設置的間隔因子將會打亂扇區的排列順序).
3. 驅動器參數數據包 Drive Parameters Packet
驅動器參數數據包是在擴展 Int13H 的取得驅動器參數子功能調用中
使用的數據包. 格式如下:
struct DriveParametersPacket
{
WORD InfoSize; // 數據包尺寸 (26 字節)
WORD Flags; // 信息標誌
DWORD Cylinders; // 磁盤柱面數
DWORD Heads; // 磁盤磁頭數
DWORD SectorsPerTrack; // 每磁道扇區數
QWORD Sectors; // 磁盤總扇區數
WORD SectorSize; // 扇區尺寸 (以字節爲單位)
};
信息標誌用於返回磁盤的附加信息, 每一位的定義如下:
0 位:
0 = 可能發生 DMA 邊界錯誤
1 = DMA 邊界錯誤將被透明處理
如果這位置 1, 表示 BIOS 將自動處理 DMA 邊界錯誤, 也就是說
錯誤代碼 09H 永遠也不會出現.
1 位:
0 = 未提供 CHS 信息
1 = CHS 信息合法
如果塊設備的傳統 CHS 幾何信息不適當的話, 該位將置 0.
2 位:
0 = 驅動器不可移動
1 = 驅動器可移動
3 位: 表示該驅動器是否支持寫入時校驗.
4 位:
0 = 驅動器不具備介質更換檢測線
1 = 驅動器具備介質更換檢測線
5 位:
0 = 驅動器不可鎖定
1 = 驅動器可以鎖定
要存取驅動器號大於 0x80 的可移動驅動器, 該位必須置 1
(某些驅動器號爲 0 到 0x7F 的設備也需要置位)
6 位:
0 = CHS 值是當前存儲介質的值 (僅對於可移動介質), 如果
驅動器中有存儲介質, CHS 值將被返回.
1 = CHS 值是驅動器支持的最大值 (此時驅動器中沒有介質).
7 - 15 位: 保留, 必須置 0.
三. 接口規範
1. 寄存器約定
在擴展 Int13H 調用中一般使用如下寄存器約定:
ds:di ==> 磁盤地址數據包( disk address packet )
dl ==> 驅動器號
ah ==> 功能代碼 / 返回碼
在基本 Int13H 調用中, 0 - 0x7F 之間的驅動器號代表可移動驅動器
0x80 - 0xFF 之間的驅動器號代表固定驅動器. 但在擴展 Int13H 調用中
0x80 - 0xFF 之間還包括一些新出現的可移動驅動器, 比如活動硬盤等.
這些驅動器支持先進的鎖定,解鎖等功能.
Ah 返回的錯誤碼除了標準 Int13H 調用規定的基本錯誤碼以外,又增加
了以下錯誤碼:
B0h 驅動器中的介質未被鎖定
B1h 驅動器中的介質已經鎖定
B2h 介質是可移動的
B3h 介質正在被使用
B4h 鎖定記數溢出
B5h 合法的彈出請求失敗
2. API 子集介紹
1.x 版的擴展 Int13H 調用中規定了兩個主要的 API 子集.
第一個子集提供了訪問大硬盤所必須的功能, 包括 檢查擴展 In13H
是否存在( 41h ), 擴展讀( 42h ), 擴展寫( 43h ), 校驗扇區( 44h ),
擴展定位( 47h ) 和 取得驅動器參數( 48h ).
第二個子集提供了對軟件控制驅動器鎖定和彈出的支持, 包括 檢查擴展
Int13H 是否存在( 41h ), 鎖定/解鎖驅動器( 45h ), 彈出驅動器( 46h ),
取得驅動器參數( 48h ), 取得擴展驅動器改變狀態( 49h ), int 15h.
如果使用了調用規範中不支持的功能, BIOS 將返回錯誤碼 ah = 01h,
CF = 1.
3. API 詳解
1) 檢驗擴展功能是否存在
入口:
AH = 41h
BX = 55AAh
DL = 驅動器號
返回:
CF = 0
AH = 擴展功能的主版本號
AL = 內部使用
BX = AA55h
CX = API 子集支持位圖
CF = 1
AH = 錯誤碼 01h, 無效命令
這個調用檢驗對特定的驅動器是否存在擴展功能. 如果進位標誌置 1
則此驅動器不支持擴展功能. 如果進位標誌爲 0, 同時 BX = AA55h, 則
存在擴展功能. 此時 CX 的 0 位表示是否支持第一個子集, 1位表示是否
支持第二個子集.
對於 1.x 版的擴展 Int13H 來說, 主版本號 AH = 1. AL 是副版本號,
但這僅限於 BIOS 內部使用, 任何軟件不得檢查 AL 的值.
2) 擴展讀
入口:
AH = 42h
DL = 驅動器號
DS:DI = 磁盤地址數據包(Disk Address Packet)
返回:
CF = 0, AH = 0 成功
CF = 1, AH = 錯誤碼
這個調用將磁盤上的數據讀入內存. 如果出現錯誤, DAP 的 BlockCount
項中則記錄了出錯前實際讀取的數據塊個數.
3) 擴展寫
入口:
AH = 43h
AL
0 位 = 0 關閉寫校驗
1 打開寫校驗
1 - 7 位保留, 置 0
DL = 驅動器號
DS:DI = 磁盤地址數據包(DAP)
返回:
CF = 0, AH = 0 成功
CF = 1, AH = 錯誤碼
這個調用將內存中的數據寫入磁盤. 如果打開了寫校驗選項, 但 BIOS
不支持, 則會返回錯誤碼 AH = 01h, CF = 1. 功能 48h 可以檢測BIOS是否
支持寫校驗.
如果出現錯誤, DAP 的 BlockCount 項中則記錄了出錯前實際寫入的數
據塊個數.
4) 校驗扇區
入口:
AH = 44h
DL = 驅動器號
DS:DI = 磁盤地址數據包(Disk Address Packet)
返回:
CF = 0, AH = 0 成功
CF = 1, AH = 錯誤碼
這個調用校驗磁盤數據, 但並不將數據讀入內存.如果出現錯誤, DAP 的
BlockCount 項中則記錄了出錯前實際校驗的數據塊個數.
5) 鎖定/解鎖驅動器
入口:
AH = 45h
AL
= 0 鎖定驅動器
= 1 驅動器解鎖
= 02 返回鎖定/解鎖狀態
= 03h-FFh - 保留
DL = 驅動器號
返回:
CF = 0, AH = 0 成功
CF = 1, AH = 錯誤碼
這個調用用來縮定指定驅動器中的介質.
所有標號大於等於 0x80 的可移動驅動器必須支持這個功能. 如果
在支持可移動驅動器控制功能子集的固定驅動器上使用這個功能調用, 將
會成功返回.
驅動器必須支持最大255次鎖定, 在所有鎖定被解鎖之前, 不能在物理上
將驅動器解鎖. 解鎖一個未鎖定的驅動器,將返回錯誤碼 AH= B0h. 如果鎖定一
個已鎖定了255次的驅動器, 將返回錯誤碼 AH = B4h.
鎖定一個沒有介質的驅動器是合法的.
6) 彈出可移動驅動器中的介質
入口:
AH = 46h
AL = 0 保留
DL = 驅動器號
返回:
CF = 0, AH = 0 成功
CF = 1, AH = 錯誤碼
這個調用用來彈出指定的可移動驅動器中的介質.
所有標號大於等於 0x80 的可移動驅動器必須支持這個功能. 如果
在支持可移動驅動器控制功能子集的固定驅動器上使用這個功能調用, 將
會返回錯誤碼 AH = B2h (介質不可移動). 如果試圖彈出一個被鎖定的介質
將返回錯誤碼 AH = B1h (介質被鎖定).
如果試圖彈出一個沒有介質的驅動器, 則返回錯誤碼 Ah = 31h (驅動器
中沒有介質).
如果試圖彈出一個未鎖定的可移動驅動器中的介質, Int13h會調用 Int15h
(AH = 52h) 來檢查彈出請求能否執行. 如果彈出請求被拒絕則返回錯誤碼(同
Int15h). 如果彈出請求被接受,但出現了其他錯誤, 則返回錯誤碼 AH = B5h.
|