日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

bios x86保护模式下的软盘操作floppy

發(fā)布時(shí)間:2025/6/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bios x86保护模式下的软盘操作floppy 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Cpu啟動(dòng)時(shí),如果在bios中設(shè)置了從軟盤(pán)啟動(dòng),則bios會(huì)自動(dòng)把軟盤(pán)的第一個(gè)扇區(qū)(512字節(jié))搬移到0x7c00,然后會(huì)從0x7c00開(kāi)始運(yùn)行,我們需要在這512字節(jié)的程序中實(shí)現(xiàn)把boot從軟盤(pán)中搬移到內(nèi)存中的功能。

此時(shí)x86系列的cpu還處在實(shí)模式中,可以利用bios提供的中斷完成軟盤(pán)讀寫(xiě),也就是著名的int 13

1???軟盤(pán)操作 1.1 ???? 軟盤(pán)結(jié)構(gòu)

1.44M軟盤(pán)為例,軟盤(pán)有上、下兩個(gè)盤(pán)面,每個(gè)盤(pán)面被劃分為80個(gè)track,每個(gè)track被劃分為18個(gè)Sector,每個(gè)Sector大小為512 BYTES

2×80×18×5121440×10241.44MB

如果是單純的進(jìn)行軟盤(pán)讀寫(xiě)操作,知道軟盤(pán)的這些知識(shí)就夠了。

1.2 ???? 軟盤(pán)讀寫(xiě)

中斷號(hào)

寄存器

作用

13h

ah=00h??? ??al=驅(qū)動(dòng)器號(hào)(0表示A盤(pán))

復(fù)位軟驅(qū)

ah=02h??? ??al=要讀扇區(qū)數(shù)

ch=磁道號(hào)?? cl=起始扇區(qū)號(hào)

dh=磁頭號(hào)?? dl=驅(qū)動(dòng)器號(hào)

es:bx=數(shù)據(jù)緩沖區(qū)

cl/ch/dh/dl指向的扇區(qū)開(kāi)始讀取al個(gè)扇區(qū)的數(shù)據(jù)到es:bx指向的緩沖區(qū)

ah=03h??? ??al=要寫(xiě)扇區(qū)數(shù)

ch=磁道號(hào)?? cl=起始扇區(qū)號(hào)

dh=磁頭號(hào)?? dl=驅(qū)動(dòng)器號(hào)

es:bx=數(shù)據(jù)緩沖區(qū)

es:bx指向的緩沖區(qū)讀取al個(gè)扇區(qū)的數(shù)據(jù)寫(xiě)入cl/ch/dh/dl指向的al個(gè)扇區(qū)

對(duì)于軟盤(pán)來(lái)說(shuō), DL=00表示A盤(pán))

CL的取值范圍是:1—18

CH的取值范圍是:0—79

DH?的取值范圍是:0—1

如果軟盤(pán)的CLCHDH取值超過(guò)了范圍,中斷調(diào)用出錯(cuò)。

使用int13時(shí)對(duì)應(yīng)扇區(qū)數(shù)的計(jì)算方法如下:

?

1.3 ???? 軟盤(pán)編程

用軟盤(pán)存放操作系統(tǒng)時(shí),bios只會(huì)把前512個(gè)字節(jié)(即第一個(gè)扇區(qū),引導(dǎo)區(qū))讀入內(nèi)存的0x7c00處執(zhí)行。程序的長(zhǎng)度也被限制在了512字節(jié)大小,一個(gè)出入保護(hù)模式的程序就會(huì)超出。

為了突破512字節(jié)的限制,需要在這個(gè)扇區(qū)內(nèi)放置一段引導(dǎo)程序,用于把后面的程序加載到內(nèi)存中。這也是第一個(gè)扇區(qū)被稱(chēng)為引導(dǎo)區(qū)的原因。

下面的就是一段簡(jiǎn)單的加載程序,reset軟驅(qū)后從LABEL_SECTOR2開(kāi)始讀入17個(gè)扇區(qū)。加上0號(hào)扇區(qū)(引導(dǎo)區(qū)),一共是18個(gè)扇區(qū),也就是第一個(gè)磁道。這是因?yàn)?span style="font-family:Times New Roman">13號(hào)中斷不能跨磁道讀取,所以這里只讀入第一個(gè)磁道剩下的17個(gè)扇區(qū)。

??? ; reset floppy

??? xor ah, ah

??? xor dl,? dl

??? int 13h

???

??? ; read sector 2 to memory

??? mov ah, 03h

??? mov al, 11h

??? mov ch, 00h

??? mov cl, 03h

??? mov dh, 00h

??? mov dl, 00h

??? mov bx, 0100h

??? int 13h

下面的程序用于保證除引導(dǎo)程序外的所有程序都在引導(dǎo)區(qū)之外,完成把磁盤(pán)內(nèi)容拷貝入memory的操作后,就會(huì)跳入LABEL_SECTOR2

?????? jmp LABEL_SECTOR2

?

; fill boot sector

??? times 510 - ($ - $$) db 1

??? dw 0xaa55

?

; Sector 2

LABEL_SECTOR2:

下面是完整的程序代碼

?????? org 07c00h

??? jmp LABEL_BEGIN

?

LABEL_BEGIN:

??? mov ax, cs

??? mov ds, ax

??? mov ss, ax

??? mov es, ax

???

??? ; reset floppy

??? xor ah, ah

??? xor dl,? dl

??? int 13h

???

??? ; read sector 2

??? mov ah, 02h

??? mov al, 01h

??? mov ch, 00h

??? mov cl, 02h

??? mov dh, 00h

??? mov dl, 00h

??? mov bx, LABEL_SECTOR2

??? int 13h

?

?????? jmp LABEL_SECTOR2

?

; fill boot sector

??? uutimes 510 - ($ - $$) db 0

??? dw 0xaa55

?

; Sector 2 jmp into loader

;????? org 0100h

LABEL_SECTOR2:

?????? mov ax, cs

?????? mov ds, ax

?????? mov es, ax

?????? call? DispStr???????????????? ; 調(diào)用顯示字符串例程

?????? jmp? $?????????????????? ; 無(wú)限循環(huán)

DispStr:

?????? mov ax, BootMessage

?????? mov bp, ax?????????????????? ; ES:BP = 串地址

?????? mov cx, 16?????????????????? ; CX = 串長(zhǎng)度

?????? mov ax, 01301h??????????? ; AH = 13,? AL = 01h

?????? mov bx, 000ch????????????? ; 頁(yè)號(hào)為0(BH = 0) 黑底紅字(BL = 0Ch,高亮)

?????? mov dl, 0

?????? int?? 10h??????????????? ; 10h 號(hào)中斷

?????? ret

BootMessage:???????? db??? "Hello, OS world!"

?

; fill floppy

??? times (2 * 18 * 80 * 512 - ($ - $$)) db 0

?

?

軟盤(pán),INT 13HIMG文件

1:軟盤(pán)

?軟盤(pán)是以扇區(qū)為基本單位來(lái)進(jìn)行操作的,每扇區(qū)512字節(jié),共2880個(gè)扇區(qū),空間大小為1.44M.

?2880個(gè)扇區(qū)又可以用(磁頭、磁道、扇區(qū))這三個(gè)參數(shù)來(lái)描述。我們簡(jiǎn)單記(磁頭、磁道、扇區(qū))為(x,y,z),那么

??X的取值范圍是:0—1

??Y的取值范圍是:0--79

??Z的取值范圍是:1—18

也就是說(shuō)軟盤(pán)有2磁頭、每磁頭有80磁道、每磁道有18扇區(qū),2880個(gè)扇區(qū)(2880=2*80*18)。

如果把2880個(gè)扇區(qū)從0開(kāi)始編號(hào),一直到2879結(jié)束,那么

編號(hào)為i的扇區(qū)和(X,Y,Z)的換算公式為:i=80*18*x+18*y+z-1

2:INT?13H

??INT13H是磁盤(pán)的BOIS中斷,對(duì)于讀寫(xiě)扇區(qū)操作,中斷的完整調(diào)用參數(shù)如下:

??AL=扇區(qū)數(shù)????

??AH=中斷子功能號(hào)?????;2=讀扇區(qū),3=寫(xiě)扇區(qū)

??CL67,CH?=?磁道號(hào)??;每磁頭最多可以有2^10=1024個(gè)磁道

??CL的低6???=??扇區(qū)號(hào)??;每磁道最多可以有2^6=64個(gè)扇區(qū)

??DH?=?磁頭號(hào)?????;最多可以有256個(gè)磁頭

??DL?=?驅(qū)動(dòng)器號(hào)?????;0=軟盤(pán),80H=硬盤(pán)

??ES:BX=數(shù)據(jù)緩沖區(qū)的地址

其他:

1).

??對(duì)于軟盤(pán)來(lái)說(shuō),實(shí)際的INT?13HDL=0,而CLCHDH的取值范圍也不可能取到上面的數(shù)值,根據(jù)1:中的數(shù)據(jù),有

CL的取值范圍是:1--18

CH的取值范圍是:0-79

DH?的取值范圍是:0—1

如果軟盤(pán)的CLCHDH取值超過(guò)了范圍,中斷調(diào)用出錯(cuò)。

AL的取值也不是任意的,一次調(diào)用INT13H進(jìn)行讀寫(xiě)扇區(qū)的只可以在一個(gè)磁道內(nèi)的扇區(qū)進(jìn)行。如果超出了一個(gè)磁道,必須要更新INT13H的中寄存器,重復(fù)調(diào)用INT13H

對(duì)于軟盤(pán)來(lái)說(shuō)?AL必須要小于19-CL

下面是一個(gè)從軟盤(pán)的(x,y,z)扇區(qū)中連續(xù)讀出n個(gè)扇區(qū)的內(nèi)容到緩沖區(qū)BUFFER中的代碼片段(?代碼使用了一些80386的指令和MASM6.0才支持的偽指令)

?MOV??AX,DS

?MOV??ES,AX

MOV??BX,OFFSET

MOV???BP,??n?

MOV?CLz

MOV?CHy

MOV?DL0?

MOV?DHx

.WHILE??BP??;bp記錄的是還沒(méi)有進(jìn)行讀操作的扇區(qū)數(shù)量

;WHILE偽指令,和高級(jí)語(yǔ)言的WHILE一樣理解就可以了,下面的。IF也一樣

?;對(duì)AL的取值進(jìn)行計(jì)算

?MOV?AL,19

????SUB?AL,CL?;最多可以讀19-CL個(gè)扇區(qū)

????XOR?AH,AH

?.IF?AX>BP??

??????MOV?AX,BP

???XOR?BP,BP?

????.ELSE??

??SUB?BP,AX?;更新BP

???????.ENDIF????

??MOV?AH,2

INT?13H???;讀扇區(qū)

?;更新CLCHDH

MOV?CL,1??

.IF??CH==79?

???INC?DH

???XOR?CH,CH

??.ELSE

??????INC?CH

??.ENDIF

??XOR?AH,AH

??SHL?AL,9?;AX=AL*512,等于已經(jīng)處理的字節(jié)數(shù)

?????;SHL?AL,9SHL?AX4都是80386+才支持的指令

????????SHR?AX,4???;AX=AX/16

??ADD?ES,AX??;更新ESBX,這里是更新了ES,也可以更新BX

?.endw

2).

??INT13H只理論上最多處理?2^24個(gè)扇區(qū)*512字節(jié)/扇區(qū)=8G的磁盤(pán)空間,這對(duì)現(xiàn)在的硬盤(pán)來(lái)說(shuō),是遠(yuǎn)遠(yuǎn)不夠的,于是后來(lái)對(duì)INT13H進(jìn)行了擴(kuò)展,用AH=42HAH=43H分別對(duì)大硬盤(pán)進(jìn)行操作,這里就不詳細(xì)討論了。

3:IMG文件

?IMG文件是軟盤(pán)的鏡像文件,文件大小也是1.44M,它和軟盤(pán)是一種線性的對(duì)應(yīng)關(guān)系。

軟盤(pán)上一個(gè)編號(hào)為(x,y,z)512字節(jié)的扇區(qū),對(duì)應(yīng)IMG文件中的以2400H*x+4800H*y+(z-1)*512為基址的512個(gè)字節(jié)(注意,2400H,4800H16進(jìn)制數(shù))。

IMG文件的字節(jié)和軟盤(pán)的扇區(qū)對(duì)應(yīng)關(guān)系也可以如下圖所示(注意那些是十進(jìn)制,那些是16進(jìn)制)

?

對(duì)于擴(kuò)展INT?13中斷,參數(shù)如下:

中斷號(hào)?功能???????????????????????調(diào)用寄存器?返回寄存器???????備注

INT?13

AH=41H?檢測(cè)擴(kuò)展中斷功能是否安裝?AH?=?41h

?????????????????BX=55AAh

??????????????? DL?=?驅(qū)動(dòng)器號(hào)(80hFFH)

?????????????????失敗:AH=1

?????????????????CF置位

?????????????????成功:AH=版本號(hào)

?????????????????CF=0?BX=AA55H?

INT?13

AH=42H?磁盤(pán)擴(kuò)展讀操作??????????????AH?=?42H

????????????????? ??DL?=?驅(qū)動(dòng)器號(hào)

????????????????? ??DS:SI=指向LBA地址包的指針?失敗:AH=錯(cuò)誤號(hào)

????????????????? ??CF置位

?????????????? ?????成功:AH=0

????????????????? ??CF=0

??地址包定義:

??????????????????? 偏移?大小?描述

????????????????? ??00H?字節(jié)?地址包大小

????????????????? ??01H?字節(jié)?保留(為0

????????????????? ??02H??????傳輸包個(gè)數(shù)

????????????????? ??04H?雙字?指向數(shù)據(jù)指針

????????????????? ??08H?4?????起始地址

?????? ?????????????其中LBA=((柱面*磁頭/柱面+磁頭)*扇區(qū)/柱面)+扇區(qū)-1

INT?13

AH=43H?磁盤(pán)擴(kuò)展寫(xiě)操作???????????????AH=43H

????????????????? ???????AL=寫(xiě)標(biāo)志

????????????????? ????DL?=?驅(qū)動(dòng)器號(hào)

????????????????? ????DS:SI=指向LBA地址包的指針?失敗:AH=錯(cuò)誤號(hào)

????????????????? ???????????????????CF置位

?????????? ????????????????????成功:AH=0

????????????????? ???????????????????????????????????CF =0?同上

INT?13

AH=48H?獲取磁盤(pán)參數(shù)?AH=48H

???????????????????????????????????? DL=驅(qū)動(dòng)器號(hào)

????????????????????????????????????? DS:SI=指向保存參數(shù)緩沖區(qū)的指針

??? ??? ??? ??? ??? ??? ??? ??? ??? ?? 失敗:AH=錯(cuò)誤號(hào)

????????????????? ???????? CF置位

?????????????????????????????????????? 成功:AH=0

????????????????? ???????? CF=0

?參數(shù)緩沖區(qū)定義:

????????????????? ??偏移?大小?描述

????????????????? ??00H??緩沖區(qū)大小

????????????????? ??02H??信息標(biāo)志位

????????????????? ??04H?雙字?物理柱面數(shù)

????????????????? ??08H?雙字?物理磁頭數(shù)

????????????????? ??0CH?雙字?物理每柱扇區(qū)數(shù)

????????????????? ??10H?4?扇區(qū)總數(shù)

????????????????? ??18H??每扇區(qū)字節(jié)數(shù)


1.1 ???? 保護(hù)模式下實(shí)現(xiàn)軟盤(pán)編程

要發(fā)揮x86芯片的功能,必須要進(jìn)入保護(hù)模式。

系統(tǒng)啟動(dòng)時(shí)所加載的512字節(jié)的MBR區(qū)為bootloader區(qū),用于加載真正的boot程序。在bootloader區(qū)中,cpu還運(yùn)行于實(shí)模式,因此bootloader通過(guò)bios中斷加載boot。進(jìn)入boot區(qū)后,一般來(lái)說(shuō)已經(jīng)完成了切換入保護(hù)模式的動(dòng)作。

在保護(hù)模式下,不能使用bios中斷,需要通過(guò)讀寫(xiě)軟盤(pán)控制器芯片8237來(lái)完成。

1.1.1 ? 軟盤(pán)控制器

I/O address

Read or Write

Register

0x3f2

Write

DOR: Digital Output Register

0x3f4

Read

FDC Status: Floppy Disk Status Register

0x3f5

Read/Write

FDC Data: Floppy Disk Data Register

0x3f7

Read

DIR: Digital Input Register

Write

DCR: Disk Control Register

注:FDC為軟盤(pán)控制器

1.1.1.1 ???????? DOR數(shù)字輸出寄存器

DOR是一個(gè)8為寄存器,他控制驅(qū)動(dòng)器馬達(dá)的開(kāi)啟、驅(qū)動(dòng)器選擇、啟動(dòng)/復(fù)位FDC以及允許/禁止DMA請(qǐng)求

Name

Description

7

MOT_EN3

Driver D motor:1-start;0-stop

6

MOT_EN2

Driver C motor:1-start;0-stop

5

MOT_EN1

Driver B motor:1-start;0-stop

4

MOT_EN0

Driver A motor:1-start;0-stop

3

DMA_INT

DMA interrupt; 1 enable; 0-disable

2

RESET

FDC Reset

1

DRV_SEL1

Select driver

0

DRV_SEL0

?

1.1.1.2 ???????? FDC Status:FDC狀態(tài)寄存器

FDC status用于反映軟盤(pán)驅(qū)動(dòng)器FDC的基本狀態(tài)。通常,在CPU想FDC發(fā)送命令或從FDC獲取結(jié)果前,都要讀取FDC的狀態(tài)為,以判斷當(dāng)前的FDC data寄存器是否就需,以及確定數(shù)據(jù)傳輸方向。

Name

Description

7

RQM

Data ready: FDD ready

6

DIO

Direction: 1 - FDD to CPU; 0 – CPU to FDD

5

NDM

DMA set: 1-not DMA; 0-DMA

4

CB

Controller busy

3

DDB

Driver D busy

2

DCB

Driver C busy

1

DBB

Driver B busy

0

DAB

Driver A busy

?

1.1.1.3 ???????? FDC Data:FDC數(shù)據(jù)寄存器

FDC Data寄存器用于向FDC發(fā)送控制命令或從FDC讀取狀態(tài),實(shí)現(xiàn)數(shù)據(jù)讀寫(xiě)等。FDC的使用比較復(fù)雜,可支持多種命令。每個(gè)命令都通過(guò)一個(gè)命令序列實(shí)現(xiàn):命令階段、執(zhí)行階段和結(jié)果階段。

1)? 重新校正命令(FD_RECALIBRATE)

軟盤(pán)啟動(dòng)時(shí)調(diào)用

階段

D7

D6

D5

D4

D3

D2

D1

D0

說(shuō)明

cmd

0

0

0

0

0

0

1

1

1

0x07

1

0

0

0

0

0

0

US1

US2

Drive no.

執(zhí)行

?

?

磁頭移動(dòng)到track0

結(jié)果

?

無(wú)

無(wú)

2)? 磁頭尋道命令(FD_SEEK)

把磁頭定位到制定位置,在讀寫(xiě)前執(zhí)行

階段

D7

D6

D5

D4

D3

D2

D1

D0

說(shuō)明

cmd

0

0

0

0

0

0

1

1

1

0x0F

1

0

0

0

0

0

HD

US1

US2

磁頭號(hào)、驅(qū)動(dòng)器號(hào)

2

C

磁道號(hào)

執(zhí)行

?

?

磁頭移動(dòng)到制定磁道

結(jié)果

?

無(wú)

無(wú)

3)? 讀扇區(qū)數(shù)據(jù)命令(FD_READ)

階段

D7

D6

D5

D4

D3

D2

D1

D0

說(shuō)明

cmd

0

MT

MF

SK

0

0

1

1

0

0xE6(MT=MF=SK=1)

1

0

0

0

0

0

0

US1

US2

驅(qū)動(dòng)器號(hào)

2

C

磁道號(hào)track

3

H

磁頭號(hào)head

4

R

起始扇區(qū)號(hào)start sector

5

N

扇區(qū)字節(jié)數(shù)

6

EOT

磁道最大扇區(qū)號(hào)

7

GPL

扇區(qū)建間隔長(zhǎng)度(3)

8

DTL

N=0時(shí),制定扇區(qū)字節(jié)書(shū)

執(zhí)行

?

?

從軟盤(pán)讀取扇區(qū)

結(jié)果

1

ST0

狀態(tài)字節(jié)0

2

ST1

狀態(tài)字節(jié)1

3

ST2

狀態(tài)字節(jié)2

4

C

磁道號(hào)track

5

H

磁頭號(hào)head

6

R

起始扇區(qū)號(hào)

7

N

扇區(qū)字節(jié)數(shù)

注:

MT:多磁道操作。MT=1表示允許多磁道操作

MF:記錄方式。MF=1表示選用MFM記錄方式,否則是FM記錄方式d

SK:是否跳過(guò)有刪除標(biāo)志的扇區(qū)。SK=1表示跳過(guò)。

返回的返回的狀態(tài)ST0、ST1和ST2的含義如下:

ST0:

名稱(chēng)

說(shuō)明

7

ST0_INTR

中斷原因。00-正常結(jié)束;01-異常結(jié)束;10-命令無(wú)效;11-軟盤(pán)驅(qū)動(dòng)器狀態(tài)改變

6

5

ST0_SE

尋道操作或重新校正操作結(jié)束(seek end)

4

ST0_ECE

設(shè)備檢查錯(cuò)誤(0磁道校正錯(cuò)誤)(Equip. Check Error)

3

ST0_NR

軟盤(pán)未就緒(Not Ready)

2

ST0_HA

磁頭地址。中斷時(shí)磁頭地址(Head Address)

1

ST0_DS

驅(qū)動(dòng)器號(hào)(Driver Select)

0

?

ST1:

名稱(chēng)

說(shuō)明

7

ST1_EOC

范文超過(guò)磁道最大扇區(qū)號(hào)(End of Cylinder)

6

?

Reserve

5

ST1_CRC

CRC校驗(yàn)出錯(cuò)

4

ST1_OR

數(shù)據(jù)傳輸超時(shí)(Over Run)

3

?

Reserve

2

ST1_ND

未找到制定扇區(qū)(No Data)

1

ST1_WP

寫(xiě)保護(hù)(Write Protect)

0

ST1_MAM

未找到扇區(qū)地址標(biāo)志ID(Miss Address Mask)

?

ST2:

名稱(chēng)

說(shuō)明

7

?

Reserve

6

ST2_CM

SK=0時(shí),讀數(shù)據(jù)遇到刪除標(biāo)志(Control Mark)

5

ST2_CRC

CRC校驗(yàn)出錯(cuò)

4

ST2_WC

扇區(qū)ID信息的磁道號(hào)C不不符(Wrong Cylinder)

3

ST2_SEH

檢索條件滿(mǎn)足(Scan Equal Hit)

2

ST2_SNS

檢索條件不滿(mǎn)足(Scan Not Satisfied)

1

ST2_BC

磁道壞(Bad Cylinder)

0

ST2_MAM

未找到扇區(qū)地址標(biāo)志ID(Miss Address Mask)

?

4)? 寫(xiě)扇區(qū)數(shù)據(jù)命令(FD_WRITE)

階段

D7

D6

D5

D4

D3

D2

D1

D0

說(shuō)明

cmd

0

MT

MF

0

0

0

1

0

1

0xC5(MT=MF=1)

1

0

0

0

0

0

0

US1

US2

磁頭號(hào)、驅(qū)動(dòng)器號(hào)

2

C

磁道號(hào)track

3

H

磁頭號(hào)head

4

R

起始扇區(qū)號(hào)start sector

5

N

扇區(qū)字節(jié)數(shù)

6

EOT

磁道最大扇區(qū)號(hào)

7

GPL

扇區(qū)建間隔長(zhǎng)度(3)

8

DTL

N=0時(shí),制定扇區(qū)字節(jié)書(shū)

執(zhí)行

?

?

向軟盤(pán)寫(xiě)入扇區(qū)

結(jié)果

1

ST0

狀態(tài)字節(jié)0

2

ST1

狀態(tài)字節(jié)1

3

ST2

狀態(tài)字節(jié)2

5)? 檢測(cè)中斷狀態(tài)命令(FD_SENSEI)

階段

D7

D6

D5

D4

D3

D2

D1

D0

說(shuō)明

cmd

0

0

0

0

0

0

1

1

1

0x08

執(zhí)行

?

?

?

結(jié)果

1

ST0

狀態(tài)字節(jié)0

2

?

磁頭所在磁道號(hào)

6)? 設(shè)定驅(qū)動(dòng)器參數(shù)命令(FD_SPECIFY)

階段

D7

D6

D5

D4

D3

D2

D1

D0

說(shuō)明

cmd

0

0

0

0

0

0

1

1

1

0x03

1

SRT(單位2ms)

HUT(單位32ms)

馬達(dá)速度、磁頭卸載時(shí)間

2

HLT(單位4ms)

ND

磁頭加載時(shí)間,非DMA模式

執(zhí)行

?

?

設(shè)置控制器

結(jié)果

?

無(wú)

無(wú)

?

1.1.1.4 ???????? DIR:數(shù)字輸入寄存器

DIR寄存器只有D7位有效,用于表示軟盤(pán)更換狀態(tài),其余用于硬盤(pán)控制器。

1.1.1.5 ???????? DCR:磁盤(pán)控制寄存器

DCR僅是用戶(hù)D0與D1位,用于表示數(shù)據(jù)傳輸率。

00-500kpbs, 01-300kpbs, 10-250kpbs。

1.1.2 ? 保護(hù)模式下代碼實(shí)現(xiàn) 1.1.2.1 ???????? 初始化

1)? Reset

?

  • outb(FLOPPY_REG_DOR, 0x08); // 重啟

  • for (i=0 ; i<100 ; i++)

  • __asm__("nop"); // 延時(shí),保證重啟完成

  • outb(FLOPPY_REG_DOR, 0xc); // 選擇DMA模式,選擇軟驅(qū)A
  • 1)? 設(shè)置磁盤(pán)數(shù)據(jù)傳輸速度

    outb(FD_DCR, 0); // 500kpbs

    2)? Output_byte函數(shù)

    用于FDC命令的輸出,FDC的每條命令需要確保上條命令已經(jīng)完成

    ?

  • static void output_byte(char byte)

  • {

  • ?????int counter;

  • ?????unsigned char status;



  • ?????for(counter = 0 ; counter < 10000 ; counter++) {

  • ????????????status = inb(FD_STATUS) & (STATUS_READY | STATUS_DIR);

  • ????????????if (status == STATUS_READY) {

  • ???????????????????outb(FD_DATA, byte);

  • ???????????????????return;

  • ????????????}

  • ?????}

  • ?????printf("Unable to send byte to FDC\r");

  • }
  • 3)? 設(shè)置驅(qū)動(dòng)器參數(shù)

    ?

  • output_byte(FD_SPECIFY);

  • output_byte(0xCF); /* 馬達(dá)步進(jìn)速度、磁頭卸載時(shí)間=32ms */

  • output_byte(6); /* Head load time =6ms, DMA */
  • ?

    1.1.2.2 ???????? 讀扇區(qū)

    ?

  • typedef struct {

  • ???????unsigned int size, sect, head, track, stretch;

  • ???????unsigned char gap,rate,spec1;

  • }floppy_struct;



  • static floppy_struct floppy_type =

  • ????{2880,18,2,80,0,0x1B,0x00,0xCF }; /* 1.44MB diskette */



  • static u32 current_dev = 0;



  • /* (2 * 18 * 80 * 512) */

  • void FloppyReadSector(u32 sectNo, u8 *buf)

  • {

  • ????u32 head, track, block, sector, seek_track;



  • ????if (NULL == buf)

  • ????{

  • ????????printf("FloppyReadSector para error.\r");

  • ????????return;

  • ????}



  • ????if (sectNo >= (floppy_type.head * floppy_type.track * floppy_type.sect))

  • ????{

  • ????????printf("FloppyReadSector sectNo error: %x.\r", sectNo);

  • ????????return;

  • ????}



  • ????/* 計(jì)算參數(shù) */

  • ????sector = sectNo % floppy_type.sect + 1;

  • ????block = sectNo / floppy_type.sect;

  • ????track = block / floppy_type.head;

  • ????head = block % floppy_type.head;

  • ????seek_track = track << floppy_type.stretch;

  • ????

  • ????/* 軟盤(pán)重新校正 */

  • ????output_byte(FD_RECALIBRATE);

  • ????output_byte(current_dev);

  • ????

  • ????/* 尋找磁道 */

  • ????output_byte(FD_SEEK);

  • ????output_byte(current_dev);

  • ????output_byte(seek_track);

  • ????

  • ????/* 設(shè)置DMA,準(zhǔn)備傳送數(shù)據(jù) */

  • ????SetDMA(buf, FD_READ);



  • ????/* 發(fā)送讀扇區(qū)命令 */

  • ????output_byte(FD_READ); /* command */

  • ????output_byte(current_dev); /* driver no. */

  • ????output_byte(track); /* track no. */

  • ????output_byte(head); /* head */

  • ????output_byte(sector); /* start sector */

  • ????output_byte(2); /* sector size = 512 */

  • ????output_byte(floppy_type.sect); /* Max sector */

  • ????output_byte(floppy_type.gap); /* sector gap */

  • ????output_byte(0xFF); /* sector size (0xff when n!=0 ?) */

  • }
  • ?

    程序很清楚,不再多說(shuō),寫(xiě)命令于此類(lèi)似。

    唯一不清楚的是SetDMA函數(shù)。

    我們?cè)谠O(shè)置DOR時(shí)設(shè)置的DMA工作方式為enable,也就是說(shuō)數(shù)據(jù)會(huì)通過(guò)DMA方式傳送,因此必須設(shè)置DMA控制器。

    ?

    1.1.2.3 ???????? DMA傳輸
  • /* DMA commands */

  • #define DMA_READ 0x46

  • #define DMA_WRITE 0x4A



  • #define immoutb_p(val,port) \

  • __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))



  • void SetDMA(u8 *buf, u8 cmd)

  • {

  • ????long addr = (long)buf;



  • ????Cli();

  • ????/* mask DMA 2 */

  • ????immoutb_p(4|2,10);

  • ????/* output command byte. I don't know why, but everyone (minix, */

  • ????/* sanches & canton) output this twice, first to 12 then to 11 */

  • ????__asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t"

  • ????"outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:"::

  • ????"a" ((char) ((cmd == FD_READ)?DMA_READ:DMA_WRITE)));

  • ????/* 8 low bits of addr */

  • ????immoutb_p(addr,4);

  • ????addr >>= 8;

  • ????/* bits 8-15 of addr */

  • ????immoutb_p(addr,4);

  • ????addr >>= 8;

  • ????/* bits 16-19 of addr */

  • ????immoutb_p(addr,0x81);

  • ????/* low 8 bits of count-1 (1024-1=0x3ff) */

  • ????immoutb_p(0xff,5);

  • ????/* high 8 bits of count-1 */

  • ????immoutb_p(3,5);

  • ????/* activate DMA 2 */

  • ????immoutb_p(0|2,10);

  • ????Sti();

  • }
  • 該函數(shù)由linux0.11移植而來(lái),可參照DMA控制器手冊(cè)進(jìn)行設(shè)置。不看也可以,注釋寫(xiě)得很清楚,拿過(guò)來(lái)用就是了





    總結(jié)

    以上是生活随笔為你收集整理的bios x86保护模式下的软盘操作floppy的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。