0から作るソフトウェア開発

日々勉強中。。。

0から作るOS開発

環境準備

環境設定

ブートローダ

カーネルローダ

GRUB

カーネル

ドライバーその他

0から作るOS開発 フロッピーディスクドライバその1

前回までの内容

これまでで、 についてわかりました。それではカーネルを0から開発していきましょう!

今回はフロッピーディスクドライバについて見ていきます

フロッピーディスクについて”またか”と思われるかと思いますが、ちょっとここはこらえてください。。。

フロッピーディスクはディスクのなかで結構古く、扱いやすいドライブです

フロッピーディスクもディスクですので、AT仕様に従います。CDドライブ、HDDドライブ、CFカードなども

同様にAT仕様に従って設計されていますので、単純なフロッピーディスクドライブの制御が

分かっていると、他のドライブの制御も簡単に分かってきます。

というわけで興味のない方は飛ばして頂いてもいいかもしれません。。。

フロッピーディスクの歴史

フロッピーディスクは主な規格として8インチディスク、5.25インチディスク、3.5インチディスクが開発されてきました

左から8インチクフロッピーディスク、5.25インチフロッピーディスク、3.5インチフロッピーディスク


(左から8インチ、5.25インチ、3.5インチフロッピーディスク)

8インチフロッピーディスク

最初に開発されたのが8インチのフロッピーディスクです。1967年頃からIBMが初期化制御プログラム起動処理

(ICPL:Initial Control Program Loadと呼ばれています)でパンチカードより読み込み速度の速く、安価な

記憶媒体からブートローダをロードするシステムの開発をはじめました。そして”メモリーディスク”と呼ばれる

直径8インチ(200mm)の読み込み専用のディスクを開発しました。この初の8インチディスクはディスク剥き出しの

ものでほこりを防ぐため後に現在見られるようなプラスティックカバーが付けられるようになりました。初期の8インチ

ディスクは容量は80KBでした。8インチのディスクをシステムをIBMは1971年にフロッピーディスクとして商用化しました。

この開発に携わったのがアラン・シュガートという方です。

読み書き可能なフロッピーディスク

IBMのアラン・シュガートがMemorex社に転籍し、1972年に初となる読み書き可能なフロッピーディスクを搭載した

Memorex 650が開発されました。Memorexのディスクは容量が175KB、50トラック、1トラックにつき8セクター、

1セクターにつき448バイトでした。このディスクは”ハードセクター”と呼ばれる磁気ディスクにセクターの印として

8個の穴があり(インデックス用にもう1つ穴があります)、セクターの開始位置を検出する機構になっていました。

1973年にはIBMは3740データエントリーシステムに33FDと呼ばれる読み書き可能なフロッピーディスクを

搭載しています。このフロッピーディスクは容量は250.25KB、77トラック、1トラックにつき26セクター、

1セクターにつき128バイトのディスクに改良されていきました。まだこの頃はフロッピーディスクは高価で

デープドライブが主流でした。そして、同じく1973年、シュガートが設立したシュガートアソシエーツの

8インチフロッピーディスクはデファクトスタンダードとなり、8インチフロッピーディスクの標準となりました

5.25インチフロッピーディスク

8インチのディスクではワードプロセッサなどの机上で操作するコンピュータには大きすぎるため、

シュガートアソシエーツが5.25インチのフロッピーディスクを開発しました。当時のディスク容量は

98.5KBで、後にトラックを5増やし110KBまで容量が増えていきました。5.25インチディスクドライブは

8インチディスクドライブよりも安価に製造できたため、1978年頃には8インチに代わって5.25インチが

主流となりました。同年、Appleが5.25インチフロッピーディスクドライブをApple IIに採用したため

パソコンにも普及していきました。また、同じく同年に、タンドン社がディスク両面が使用でき、

ディスク容量を倍にした”倍密度”を導入しました。これによりディスクの容量は360KBまで増えました

70年代、80年代ではフロッピーディスクが主な記憶媒体として使用され、ハードディスクが搭載されていない

コンピュータはフロッピーディスクからOSを起動し、OSが起動した後はOSのフロッピーディスクを抜いて

アプリケーションのフロッピーディスクを必要に応じて取り替えて使用していました。

1984年にはIBM PC/AT機で高密度ディスクが搭載されました。

3.5インチフロッピーディスク

1980年代初頭には5.25インチディスクドライブは8インチディスクよりも小さく安価ではあったのですが、

やはりまだまだ大きい機械でした。そして、磁気ディスクの高密度化技術もだんだんと進化してきて

いましたので、より小型が望まれていました。また、5.25インチは8インチディスクと同じ設計思想で

プラスティックケースでは使用しているとゴミなどで使用できなくなることもありました。そこで、新たに

2インチ、2.5インチ、3インチ、3.5インチディスクが開発されましたが、ソニーが開発した3.5インチの

ディスクを基にした仕様が1982年にMicrofloppy Industry Committeeで採択されたために

後に3.5インチディスクが主流となりました。その後ソニーを交えたMicro Floppy Standard

CommitteeがANSIに規格提案し1984年に規格承認されました。 3.5インチディスクは当初720kBの容量でしたが、後に1.2MB、1.44MBが出現し、1.44MBが

主流となりました。

フロッピーディスクの構造

フロッピードライブ

主流となった3.5インチフロッピーディスクドライブです。

3.5インチフロッピーディスクドライブ


3.5インチフロッピーディスクの構造

このドライブに3.5インチのディスクを挿入して使用します

3.5インチフロッピーディスクは次のような構造となっています。

フロッピーディスクの構造
3.5インチフロッピーディスク
画像の番号 説明
1 この穴が空いていると、フロッピーディスクドライブはこのディスクが 高密度ディスクであることを検出します
2 フロッピーディスクドライブのモーターと連結するハブです
3 フロッピーディスクをドライブから抜くときに保護するシャッターです
4 プラスティックケースです
5 ディスクが回転するときに生じる摩擦を軽減するためのポリエステルシートです
6 磁性体をコーティングしたディスクです。データはここに記録されます
7 ディスク上のセクタです。セクタは実際には見えません。
8 左上のスイッチをスライドすることで書き込み保護ができます(図上に番号はありません)


フロッピーディスクの物理フォーマット

フロッピーディスクの物理フォーマットは下記のようになります。

このフォーマットはディスク両面にあり、データを読み取る磁気ヘッドは2つあります

フロッピーディスクの物理フォーマット


このようにフロッピーディスクの片面のトラックは全部で80あり、1つのトラックにつきセクターは18あります

1セクタは512バイトで、片面には合計1440セクターあります。

そして、フロッピーディスクには両目ありますので、磁気ヘッドのヘッド0、ヘッド1があります

両面あわせて合計2880セクターとなります

シリンダ(トラック)/ヘッド/セクター(CHS:Cylinder/Head/Sector)

フロッピードライブコントローラにフロッピーディスクのデータを読み書きするときにはCHSで指定します

シリンダ(トラック)

シリンダはディスクの円筒上にある領域をいいます。特にディスクが1枚のときにはトラックといいます

フロッピーディスクの場合は片面にシリンダが80あります。また、シリンダ(トラック)のなかにセクターが18あります。

シリンダ(トラック)は0から数えます

ヘッド

ディスクからデータを読み書きする磁気ヘッドです。ディスク両目を読み取るためにフロッピードライブには

ヘッドが2つあります。ヘッドは0から数えます

セクター

セクターは512バイトあり、ディスクの最小単位のデータのまとまりです。セクターは1から数えます

LBA(Linear Block Addressing)

LBAはディスクをセクターのみでアドレス付けします。ソフトウェアで通常指定するのはLBAで抽象化したほうが

処理が簡単になります。(但し、フロッピードライブコントローラに直接アクセスする低レベルドライバはCHSで

処理を行う必要があります)。フロッピーディスクの場合は合計で2880セクターありますので、LBSのアドレス

範囲は0-2879となります

LBAについてはブートローダその10にも記載しております

フロッピーディスクコントローラ

フロッピードライブを制御するICがフロッピーディスクコントローラとなります。8272AというICが代表的なICと

なります。それでは8272Aを見て行きましょう

8272Aフロッピーディスクコントローラ

フロッピーディスクコントローラの代表的なICとして8272AというICがあります。

8272AのIC


8272Aのブロック図は次のようになります

8272Aのデータシート がダウンロードできますので、興味の有る方はご参照ください。

また、8272Aと下位互換性のある 82078 というICもIntelのサイトからダウンロードできます。)

8272Aフロッピーディスクコントローラブロック図


このICの各ピンの機能は下記となります

8272Aのピンアサイン
シンボル ピン番号 名称 入出力 接続先 説明
RESET 1 リセット 入力 CPU 8272Aをアイドル状態にします。8272Aとフロッピーディスクドライブが接続しているラインは全て”0”(Low)になります 最後に書き込まれた制御コマンドは保持されます。
RD 2 リード 入力 CPU 8272Aからのデータをデータバスに出力させ転送ための読み込み制御信号です。 LowアクティブでCSがHighのときは無効です。
WR 3 ライト 入力 CPU データバスに書き込んだデータを8272Aに転送する制御信号です。 LowアクティブでCSがHighのときは無効です。
CS 4 チップセレクト 入力 CPU Lowアクティブで、このラインがLowになっている間RDとWRが有効となります。
A0 5 データ/ステータスレジスタセレクト 入力 CPU データレジスタとステータスレジスタを選択する信号です。
0:ステータスレジスタのデータがデータバスに出力されます
1:データレジスタのデータがデータバスに出力されます
CSがHighのときは無効です。
DB0-DB7 6-13 データバス 入力/出力 CPU 双方向の8ビットデータバスです
DRQ 14 データDMA要求 出力 DMA DMA要求が必要なときにHighにします
DACK 15 DMA確認 入力 DMA DMAコントローラがデータ転送中にLowにします。
TC 16 ターミナルカウント 入力 DMA DMAコントローラがデータ転送を完了したときにHighにします
IDX 17 インデックス 入力 フロッピーディスクドライブ フロッピーディスクドライブがトラックの開始を検出するとHighにします。
INT 18 割り込み 出力 CPU(PIC) IRQをPICに要求します。
CLK 19 クロック 入力   8MHz(ミニフロッピーディスクの場合は4MHz)の矩形波クロックです。
GND 20 グラウンド     グラウンドに接続します
WR CLK 21 ライトクロック 入力   FM=500kHz、MFM=1MHzでフロッピーディスクドライブにデータを書き込むときに使用するクロックです。 (FMとMFMのインターバルは250nsとなります)。読み込み時書き込み時など操作するときには 有効にしておく必要があります
DW 22 データウィンドウ 入力 PLL PLLによって生成される信号です。フロッピーディスクドライブからのデータを 取得するときに使用します
RD DATA 23 リードデータ 入力 フロッピーディスクドライブ フロッピーディスクドライブからデータを読み込む時にHighにします。 クロックとデータビットが入力されます
VCO 24 VCO同期 出力 PLL Low”0”にすることでPLLのVCOを禁止します。High”1”にすると有効になります
WE 25 ライトイネーブル 出力 フロッピーディスクドライブ フロッピーディスクドライブへのデータ書き込みを有効にします
MFM 26 MFMモード 出力 PLL MFMの有効/無効を設定します
0:FMモードを設定します
1:MFMモードを設定します
HDSEL 27 ヘッドセレクト 出力 フロッピーディスクドライブ ヘッドを指定します
0:ヘッド0を指定します
1:ヘッド1を指定します
DS0-DS1 28-29 ドライブセレクト 出力 フロッピーディスクドライブ フロッピーディスクドライブを選択します
WR DATA 30 ライトデータ 出力 フロッピーディスクドライブ フロッピーディスクドライブへのデータ書き込み時のデータを転送します
PS0-PS1 31-32 プレシフト 出力 フロッピーディスクドライブ MFMモード中にプレシフトステータスを書き込みます。 早期、後期、通常時間を決定します
FLT/TRK0 33 フォルト/トラック0 入力 フロッピーディスクドライブ 読み込み/書き込み時のフロッピーディスクドライブのエラーや シークモード中にトラック0を検出します。
WP/TS 34 ライトプロテクト/両面 入力 フロッピーディスクドライブ 読み込み/書き込み時にライトプロテクトまたは シークモード時の両面メディアの検出に使用します
RDY 35 レディ 入力 フロッピーディスクドライブ フロッピーディスクドライブがデータ受信可能状態であることを検出します
HDL 36 ヘッドロード 出力 フロッピーディスクドライブ フロッピーディスクドライブからデータを読み込み/書き込みするときに使用します
FR/STP 37 フォルトリセット/ステップ 出力 フロッピーディスクドライブ 読み込み/書き込み時のフォルトをリセットします。または、 シークモードで他のシリンダにヘッドを移動するパルスを出力します
LCT/DIR 38 低電圧/方向 出力 フロッピーディスクドライブ 書き込み/読み込みモード時にトラック上の電圧を下げます。また、 シークモード時のヘッドの移動する方向を決定します
RW/SEEK 39 読み込み・書き込み/シーク 出力 フロッピーディスクドライブ 0:読み込み/書き込みモード
1:シークモード
VCC 40 電源     +5V電源です


フロッピーディスクコントローラはDMA(Direct Memory Access)コントローラを使用するか

しないかを設定することができます。DMAを使用しない場合には、フロッピーディスクコントローラは

データをCPUに1バイト転送する毎にIRQ6を発生させます。DMAを使用する場合は、DMAコントローラに

データ転送を任せることができます。DMAについては別回での説明とさせていただきます。

今回はフロッピーディスクコントローラのみの制御をまず見ていきます。フロッピーディスクコントローラは

IRQを発生させますので、割り込みのラインは当然PIC(Programmable Interrupt Controller)に

接続されています。PICについては割り込みその2割り込みその3をご参照ください。

フロッピーディスクコントローラはFSB(Front Side Bus)に接続されていますので、今までと同様に

IN命令OUT命令で制御していきます。

(フロッピーディスクコントローラはFSB、ISAバスに接続されていましたが、最近のシステムでは

いくつかのICを統合したスーパーI/O ICが使用されています。)



上記表のを見てみますとフロッピーディスクコントローラはINTピンがあります。このピンは前述のように

PICのIRQ6に接続されています。フロッピーディスクコントローラはフロッピーディスクに1バイトのデータが

読み込み可能となった場合、1バイトのデータが書き込みできた場合にこのピンをHighにします。

これによりPICのIRQ6がHighになり、PICはCPUに割り込みを要求するような仕組みとなっています

その後の割り込み処理については割り込みその2に詳細を説明しています

最終的には割り込みその1で設定しました、 割り込み番号38のIDTに設定したフロッピーディスク割り込み

ハンドラが呼び出されます



フロッピーディスクドライブはシステムに通常4つまで接続することができます。ですので、プログラムするときは

この4つのドライブのなかからどのドライブかを指定します

フロッピーディスクドライブの接続

フロッピーディスクコントローラ8272Aとフロッピーディスクドライブとケーブルで接続します

現在主流となっているパソコンではシリアルATAを使用していますので、限りなく少なくなってしまいましたが、

パラレルATAケーブルで接続することができました。(パラレルATAケーブルはIDE:Integrated Drive

Electronicsケーブルとも言います)

それではパラレルATAケーブルを見て行きましょう。下記図は3.5インチドライブ(フロッピーディスクドライブなど)を

接続するケーブルです

パラレルATAケーブル3.5インチドライブコネクタ


上図の”Twist”と書かれていいる箇所はケーブルをねじっている箇所です

このねじれた箇所は40ピンで、同時に接続されている他のドライブと通信をするピンとなります



補足として、5インチドライブのケーブルを下記に載せます。

パラレルATAケーブル5インチドライブコネクタ


5インチ用のケーブルはCD/DVDドライブやHDDドライブを接続します



上記3.5インチケーブルを接続する3.5インチドライブ(フロッピーディスクドライブなど)の

ピンアサインを簡単に見ていきます

パラレルATAコネクタの形状は下記のようになっています

パラレルATAコネクタ


パラレルATAのコネクタピンアサイン(フロッピーディスクドライブのI/F)
ピン番号 ラベル 説明
1 RESET リセット
Lowアクティブ
2 Ground グランド
3 DATA pin 7 データピン7
4 DATA pin 8 データピン8
5 DATA pin 6 データピン6
6 DATA pin 9 データピン9
7 DATA pin 5 データピン5
8 DATA pin 10 データピン10
9 DATA pin 4 データピン4
10 DATA pin 11 データピン11
11 DATA pin 3 データピン3
12 DATA pin 12 データピン12
13 DATA pin 2 データピン2
14 DATA pin 13 データピン13
15 DATA pin 1 データピン1
16 DATA pin 14 データピ14
17 DATA pin 0 データピン0
18 DATA pin 15 データピン15
19 Ground グランド
20 Key/Vcc_in キー/VCC入力
21 DMARQ DMA要求
22 Ground グランド
23 DIOW データ書き込み時にLowにします
Lowアクティブ
24 Ground グランド
25 DIOR データ読み込み可能なときにLowにします
Lowアクティブ
26 Ground グランド
27 IORDY DMA転送可能なときにLowにします
Lowアクティブ
28 CSEL ケーブルセレクト
マスター:このピンをがホストにグランド接続されているかどうか検出します
スレーブ:このピンを検出しません
29 DMACK DMAの確認応答です
30 Ground グランド
31 INTRQ 割り込み要求
32 NC(Reserved) 接続無し(予約)
33 DA1 アドレスバスピン1
34 PDIAG/CBLID 80ピンIDE/ATAケーブルのウルトラDMA検出用ピン
35 DA0 アドレスピン0
36 DA2 アドレスピン2
37 CS0 チップセレクト0
Lowアクティブ
38 CS1 チップセレクト1
Lowアクティブ
39 DASP アクティビティ
40 Ground グランド


パラレルATAケーブルのピンはフロッピーディスクドライブとフロッピーディスクコントローラおよび

DMAコントローラとの通信に使用します。フロッピーディスクコントローラを制御することで

パラレルATAケーブルを通してフロッピーディスクドライブを制御していきます

フロッピーディスクコントローラのポートアドレス

フロッピーディスクドライブは通常4つまで接続できます。それぞれのドライブをコントロールする

フロッピーディスクコントローラはx86のポートアドレスにマップされます。
4つ以上接続できるシステムもありますがここでは割愛させていただきます。

ポートアドレスにマップされるフロッピーディスクコントローラは2つあります。

フロッピーディスクコントローラはオリジナルの8272Aから更に改良されてきました

(上で見てきましたIntelの82078もその内の1つです)

改良されたICはピン数が追加されていて、特定のモードのときだけアクセスできるレジスターが

あります。例えば下記表のステータスレジスターAはPS/2モードのときのみアクセスできます

(モードはピンの状態で決定されます。例えば82077ですとIDENTピンとMFMピンで決まります。通常はPS/2モードです)

それでは、それぞれのレジスタについて見ていきます

フロッピーディスクコントローラのポートアドレス(FDC0)
ポートアドレス IN/OUT 説明
0x3F0 IN ステータスレジスターA
(SRA:Status Register A)
PS/2のみ
0x3F1 IN ステータスレジスターB
(Status Register B)
PS/2のみ
0x3F2 OUT デジタルアウトプットレジスター
(DOR:Digital Output Register)
0x3F3 IN/OUT テープドライブレジスター
(TDR:Tape Drive Register)
0x3F4 IN メインステータスレジスター
(MSR:Main Status Register)
PS/2のみ
0x3F4 OUT データレートセレクトレジスター
(DSR:Data Rate Select Register)
0x3F5 IN/OUT データレジスター。読み込み時はフロッピーディスクコントローラからのデータやステータスを読み込みます。書き込み時は フロッピーディスクコントローラに制御コマンドを書き込みます。
0x3F6   予約
0x3F7 IN 制御設定レジスター
(CCR:Configuration Control Register)
ATのみ
0x3F7 OUT デジタルインプットレジスター
(DIR:Digital Input Register)
ATのみ


フロッピーディスクコントローラのポートアドレス(FDC1)
ポートアドレス IN/OUT 説明
0x370 IN ステータスレジスターA
(SRA:Status Register A)
PS/2のみ
0x371 IN ステータスレジスターB
(Status Register B)
PS/2のみ
0x372 OUT デジタルアウトプットレジスター
(DOR:Digital Output Register)
0x373 IN/OUT テープドライブレジスター
(TDR:Tape Drive Register)
0x374 IN メインステータスレジスター
(MSR:Main Status Register)
PS/2のみ
0x374 OUT データレートセレクトレジスター
(DSR:Data Rate Select Register)
0x375 IN/OUT データレジスター。 読み込み時はフロッピーディスクコントローラからのデータやステータスを読み込みます。書き込み時は フロッピーディスクコントローラに制御コマンドを書き込みます。
0x376   予約
0x377 IN 制御設定レジスター
(CCR:Configuration Control Register)
ATのみ
0x377 OUT デジタルインプットレジスター
(DIR:Digital Input Register)
ATのみ


上記のレジスタに書き込み/読み込みすることでフロッピーディスクドライブを制御することができます

フロッピーディスクコントローラのポートアドレス定義

レジスターのポートアドレスを定義していきます


/*********************************************************************************
    File:portAddress.h
    Description:Definition of port address

*********************************************************************************/
#ifndef __PORTADDRESS__H
#define __PORTADDRESS__H

/*
==================================================================================

    Description :Floppy Disc Controller( 2nd )

==================================================================================
*/
#define	DEF_PORT_FDC1_SRA       0x0370  /* status register A                    */
#define	DEF_PORT_FDC1_SRB       0x0371  /* status register B                    */
#define	DEF_PORT_FDC1_DOR       0x0372  /* Digital output register              */
#define	DEF_PORT_FDC1_TAPE      0x0373  /* tapa drive register                  */
#define	DEF_PORT_FDC1_MSR       0x0374  /* main status register                 */
#define	DEF_PORT_FDC1_DRS       0x0374  /* data rate select register            */
#define	DEF_PORT_FDC1_STS       0x0375  /* status register 0,1,2,3( ST0,1,2,3 ) */
#define	DEF_PORT_FDC1_DATA      0x0375  /* data( status ) register              */
#define	DEF_PORT_FDC1_CMD       0x0375  /* command register                     */
#define	DEF_PORT_FDC1_RESERVED  0x0376  /* reserved                             */
#define	DEF_PORT_FDC1_DIR       0x0377  /* digital input register               */
#define	DEF_PORT_FDC1_CCR       0x0377  /* configuration control register       */

/*
==================================================================================

    Description :Floppy Disc Controller( 1st )

==================================================================================
*/
#define	DEF_PORT_FDC0_SRA       0x03F0  /* status register A                    */
#define	DEF_PORT_FDC0_SRB       0x03F1  /* status register B                    */
#define	DEF_PORT_FDC0_DOR       0x03F2  /* Digital output register              */
#define	DEF_PORT_FDC0_TAPE      0x03F3  /* tapa drive register                  */
#define	DEF_PORT_FDC0_MSR       0x03F4  /* main status register                 */
#define	DEF_PORT_FDC0_DRS       0x03F4  /* data rate select register            */
#define	DEF_PORT_FDC0_STS       0x03F5  /* status register 0,1,2,3( ST0,1,2,3 ) */
#define	DEF_PORT_FDC0_DATA      0x03F5  /* data( status ) register              */
#define	DEF_PORT_FDC0_CMD       0x03F5  /* command register                     */
#define	DEF_PORT_FDC0_RESERVED  0x03F6  /* reserved                             */
#define	DEF_PORT_FDC0_DIR       0x03F7  /* digital input register               */
#define	DEF_PORT_FDC0_CCR       0x03F7  /* configuration control register       */

#endif /* __PORTADDRESS__H */



この定義を使って各レジスタにアクセスしていきます

通常のパソコンは最大で4つのフロッピーディスクドライブを搭載できますので、

FDC0のみ使用すればよいことになります

それでは、フロッピーディスクコントローラのレジスタについて詳細を見ていきます。

フロッピーディスクコントローラのレジスタ

フロッピーディスクコントローラのレジスタの各ビットの役割について見ていきます

ステータスレジスターA(SRA:Status Register A)(PS/2モードのみ)

ステータスレジスターAは読み込み専用のレジスターです。ステータスレジスターAの値を読み込むことで

割り込みの状態やフロッピーディスクドライブと接続されているピンの状態を知ることができます

このレジスターについてはプログラム上あまり有用ではありませんので、飛ばして頂いて問題ありません

ステータスレジスターAはPS/2モード時のみアクセスできます。PC-ATモード時にはアクセスできません

(このレジスターの内容はICのピン構成によって異なります。下記はIntelの82077を基に記載しています)

ステータスレジスターA SRAのビットアサイン


フロッピーディスクコントローラのステータスレジスターA SRA
ビット シンボル 名称 説明
0 DIR ヘッド移動方向 DIRピンの状態を反映しています。シークモード時のヘッドの移動する方向です
0:ディスク外側に向けて移動しています
1:ディスク中心に向けて移動しています
1 WP ライトプロテクト WPピンの状態を反転して反映しています。ディスク・ドライブがライトプロテクトを検出しているかどうかを示します。
0:ディスクはライトプロテクトがかかっています
1:ディスクは読み書き可能です
2 INDX インデックス INDXピンの状態を反転して反映しています。トラックの開始かどうかを示します
0:トラックの開始です
1:トラックの開始ではありません
3 HDSEL ヘッド選択 HDSELピンの状態を反映しています。ディスクの表/裏のどちらかを使用しているのかを示します
0:ヘッド0を使用しています
1:ヘッド1を使用しています
4 TRK0 トラック0 TRK0ピンの状態を反転して反映しています。トラック0かどうかを示しています
0:トラック0ではありません
1:トラック0です
5 STEP ステップ STEPピンの状態を反映しています。ドライブにステップ(ヘッド移動)パルスを出力しているかどうかを示します
0:ステップパルスを出力していません
1:ステップパルスを出力しています
6 DRV2 ドライブ2 DRV2ピンの状態を反転して反映しています。システムに2個目のドライブがあるかどうかを示します
0:2個目のドライブがあります
1:2個目のドライブはありません
7 INT PENDING 割り込み状態 INTピンの状態を反映しています。
0:DMAを使用していない場合、データ転送中ではありません
1:DMAを使用していない場合、データ転送中です


ステータスレジスターB(SRA:Status Register B)(PS/2モードのみ)

ステータスレジスターBは読み込み専用のレジスターです。ステータスレジスターBの値を読み込むことで

ステータスレジスターA以外のピンの状態を知ることができます

このレジスターについてはプログラム上あまり有用ではありませんので、飛ばして頂いて問題ありません

ステータスレジスターBはPS/2モード時のみアクセスできます。PC-ATモード時にはアクセスできません

(このレジスターの内容はICのピン構成によって異なります。下記はIntelの82077を基に記載しています)

ステータスレジスターB SRBのビットアサイン


フロッピーディスクコントローラのステータスレジスターB SRB
ビット シンボル 名称 説明
0 MOT EN0 モーター0有効 ME0ピンの状態を反映しています。モーターが有効かどうかを示します。ME0はデジタルアウトプットレジスター DORで有効にできます
0:モーター0は無効です
1:モーター0は有効です
1 MOT EN1 モーター1有効 ME1ピンの状態を反映しています。モーターが有効かどうかを示します。ME1はデジタルアウトプットレジスター DORで有効にできます
0:モーター1は無効です
1:モーター1は有効です
2 WE 書き込み有効 WEピンの状態を反映しています。ディスクへの書き込みが可能かどうかを示します
0:ディスクへの書き込みは無効です
1:ディスクへの書き込みは有効です
3 RD DATA TOGGLE リードデータトグル RD DATAピンの状態を反映していますが、直接反映されるのではなくて、 一旦フリップフロップを通します。
4 WR DATA TOGGLE ライトデータトグル WR DATAピンの状態を反映していますが、直接反映されるのではなくて、 一旦フリップフロップを通します。
5 DRIVE SEL0 ドライブ選択0 4つのドライブの内どのドライブを選択しているかをDRIVE SEL0、DRIVE SEL1の2ビットで 知ることができます。この内のDRIVE SEL0ビットとなります。DRIVE SELxビットは デジタルアウトプットレジスターDORで2ビットとも取得することができますので、通常 DORのビットを参照します
6 Reserved 予約 1固定です
7 Reserved 予約 1固定です


データレートセレクトレジスター(DSR:Data Rate Select Register)

データレートセレクトレジスターDSRは書き込み専用のレジスターです

DSRの値を変更することでドライブ制御信号のタイミングを変更することができます

このレジスターについてはプログラム上あまり有用ではありませんので、飛ばして頂いて問題ありません

データレートレジスターDSRのビットアサイン


フロッピーディスクコントローラのデータレートレジスターDSR
ビット シンボル 名称 説明
0-1 DRATE SEL0-1 データレートセレクタ0-1 データ転送速度を2ビットで設定します。デフォルトは250Kbpsでハードウェアリセット後はデフォルト値になります。 ソフトウェアリセットでは設定値は変わりません
データレートセレクタ設定
DRATE SEL1 DRATE SEL0 データレートMFM
1 1 1Mbps
0 0 500Kbps
0 1 300Kbps
1 0 250Kbps(デフォルト)
2-4 PRECOMP0-2 前補正 WR DATAピンからドライブに出力するときのビットシフト現象を補正するためのディレイを設定します。
前補正遅延設定
PRECOMP2 PRECOMP1 PRECOMP0 前補正遅延
1 1 1 0.00ns(無効値)
0 0 1 41.67ns
0 1 0 83.34ns
0 1 1 125.00ns
1 0 0 166.67ns
1 0 1 208.33ns
1 1 0 250.00ns
0 0 0 DEFAULT(デフォルト)

デフォルトのディレイは実際にはドライブとメディアの種類によって変わります。
5 Reserved 予約 0固定です。
6 POWER DOWN パワーダウン フロッピーディスクコントローラの内部クロックとオシレーターの発振を停止します。 フロッピーディスクドライブに接続されているピンの電圧状態は維持します。 リセット後パワーダウン状態は解除されます。
7 S/W RESET ソフトウェアリセット ソフトウェアでリセットをかけます。デジタルアウトプットレジスターDORのRESETビットと 同様の動作をしますが、このレジスターによるリセットはハードウェアリセットと同様に 設定値はクリアされます


デジタルアウトプットレジスター(DOR:Digital Output Register)

デジタルアウトプットレジスターDORに値を設定することでドライブの選択、モーターを有効にするなどができます。

このレジスターはソフトウェアで重要な制御をします

デジタルアウトプットレジスターDORのビットアサイン


フロッピーディスクコントローラのデジタルアウトプットレジスターDOR
ビット シンボル 名称 説明
0-1 DRIVE SEL0-1 ドライブ選択0-1 DORで制御する対象のドライブを選択します
ドライブ選択とドライブ
DRIVE SEL1 DRIVE SEL0 選択ドライブ
0 0 ドライブ0
0 1 ドライブ1
1 0 ドライブ2
1 1 ドライブ3
2 RESET リセット LOCKビットが0のときにRESETを0に設定することでICをリセット(バッファクリアなど)します
0:フロッピーディスクコントローラをリセットします
1:フロッピーディスクコントローラを通常稼働させます
LOCKビットにつきましてはフロッピーディスクドライバその2をご参照ください
3 DMA GATE DMAゲート DMAゲートビットはPC-ATモード時のときに操作できます。(PS/2モードでは操作しても影響はありません) DMAゲートを0に設定するとINTピン、DRQピンの出力がトリステートになり、 DACKピン、TCピンの入力が無効になります。DMAゲートを1にすると INTピン、DRQピン、TCピン、DACKピンが有効になります。 (PS/2モードでは各ピンは常にアクティブとなります)
4-7 MOT EN0-3 モーター有効 このビットを設定することでICのME0-3ピンを操作することができます
0:モーターを無効にします
1:モーターを有効にします
このビットは他のビットと排他的に設定する必要があります。(同時に2つ以上のMOT ENビットを 1にしてはダメです)。また、1に設定する場合はMOT EN0-3に対応するドライブを 同時に選択する必要があります。その組合は下記表の通り決まっています(DMA GATE、RESETの ビットはとりあえず0として値を記載しています)
モーターとドライブの設定値組み合わせ
ドライブ DOR設定値
0 0x1C
1 0x2D
2 0x4E
3 0x8F


このレジスターはフロッピーディスクドライブを制御する上で重要なレジスターです。

DORのビットMOT ENでフロッピーディスクから読み込み/書き込みする前に必ずモーターを

有効にしておく必要があります。(モーターを動かさないと目的のセクターが読み込みできません)。

モーターを有効にするにはMOT ENビットを1にして、該当のドライブ(通常ドライブ0です)を選択すれば

よいだけとなります。DORはポートにマッピングされていますので、 OUT命令を使用します。

OUT命令で書き込みする関数は割り込みその2 PICとIRQ で作ったoutPortByte関数を使用していきます

デジタルアウトプットレジスターDORの実装

まずは、DORに値を書き込むためにビットを定義していきます


/*
===============================================================================

    Description :DOR(Digital Output Register)

    bit number  label       description
    0-1         DRIVE SEL   Drive select
                            00 = drive0, 01 = drive1, 10 = drive2, 11 = drive3
    2           RESET       Controller reset
                            0 = execute controller rest, 1 = controller enable
    3           DMA         DMA Gate
                            invalid for PS/2 mode
    4           MOT EN0     Motorcontrol for floppy drive0
    5           MOT EN1     for drive1
    6           MOT EN2     for drive2
    7           MOT EN3     for drive3
===============================================================================
*/
#define DEF_FDC_DOR_DRIVE0  0x00    /* b00000000    */
#define DEF_FDC_DOR_DRIVE1  0x01    /* b00000001    */
#define DEF_FDC_DOR_DRIVE2  0x02    /* b00000010    */
#define DEF_FDC_DOR_DRIVE3  0x03    /* b00000011    */

#define DEF_FDC_DOR_ENABLE  0x04    /* b00000100    */

#define DEF_FDC_DOR_DMA     0x08    /* b00001000    */
#define DEF_FDC_DOR_MOTOR0  0x10    /* b00010000    */
#define DEF_FDC_DOR_MOTOR1  0x20    /* b00100000    */
#define DEF_FDC_DOR_MOTOR2  0x40    /* b01000000    */
#define DEF_FDC_DOR_MOTOR3  0x80    /* b10000000    */

#define DEF_FDC_DOR_RESET   0x00



そして、デジタルアウトプットレジスターDORに値を書き込む関数を準備します


/*
==============================================================================
    Funtion     :writeFdc0Dor
    Input       :unsigned char dor
                 < a value to write to digital output register >
    Output      :void
    Return      :void

    Description :write dor value to digital output register
==============================================================================
*/
PRIVATE INLINE writeFdc0Dor( unsigned char dor )
{
    outPortByte( DEF_PORT_FDC0_DOR, dor );
}



この関数と定義を使って、ドライブ0のモーター0をONにしてみます


    writeFdc0Dor( DEF_FDC_DOR_DRIVE0 | DEF_FDC_DOR_ENABLE | DEF_FDC_DOR_MOTOR0 );



単純な例ですが、これでモーターが始動します。RESETビットを1にすることに注意します

モーターを止めるには該当ドライブ選択ビットを0にしてモータービットも0にします


    writeFdc0Dor( ~DEF_FDC_DOR_ENABLE );



フロッピーディスクドライブの制御の最初の一歩となりますが、非常にシンプルに制御できる

かと思います。基本的にはHDDもこのような感じで制御できますので、興味の有る方は

調べてみてはいかがでしょうか。

ここで注意していただきたいのですが、モーターの制御はメカ動作が発生します

メカの動作はCPUの処理速度に比べて非常に遅いです。モーターを動かしたり

止めたりするときにはDORに書き込んでからウェイトしてあげる必要があります

ですので、ヘッドを動かしてシークするときなど随分長い間処理待ちすることになります

ウェイトについては後述します

メインステータスレジスター(MSR:Main Status Register)

メインステータスレジスターは読み込み専用のレジスターです。制御コマンドの書き込み後に

その制御コマンドの処理結果を格納します。制御コマンドについての詳細は

フロッピーディスクドライバその2 で見ていきます

メインステータスレジスターMSRのビットアサイン


フロッピーディスクコントローラのメインステータスレジスターMSR
ビット シンボル 名称 説明
0-3 DRV0-3 BUSY ドライブ0-3ビジー ドライブ0-3がビジー状態であるかどうかを示します。 このビットはSEEKやRECALIBRATEなどの制御コマンドによって、ドライブが動作中である場合に1にセットされます。
0:ドライブはアイドル状態です
1:ドライブはビジー状態です
4 CMD BSY コマンドビジー コントローラが、制御コマンドを処理中かどうかを示します。 制御コマンドを受け付けた時に1にし、制御コマンドを処理した結果を出力したときに0に戻ります
0:アイドル状態です
1:制御コマンド処理中です
5 NON-DMA DMAモード コントローラがDMA転送中かどうかを示します DMA転送中以外の制御コマンド処理中に1がセットされます。 制御コマンドによりデータ転送中か制御コマンドの処理結果格納後かの判別にも使用できます。
0:DMA転送中か制御コマンドの結果格納後です
1:DMA転送中でないか制御コマンド処理中です
6 DIO データ転送方向 データ転送方向を示します。ビット7のRQMビットが1から0にセットされた後にこのビットを参照して データ転送方向を判断します。
0:フロッピーディスクコントローラからCPUへのデータ転送です(読み込み)
1:CPUからフロッピーディスクコントローラへのデータ転送です(書き込み)
7 RQM マスター(CPU)への要求 CPUとフロッピーディスクコントローラとのデータ転送が可能かどうかを示します
0:CPUとフロッピーディスクコントローラとのデータ転送はできません
1:CPUとフロッピーディスクコントローラとのデータ転送が可能です


RQMビットでデータ転送が可能か判断し、可能な場合DIOビットでリードかライトを判断します。

メインステータスレジスターMSRの実装

簡単な実装例について見ていきます。まずはMSRのビットを定義していきます


/*
===============================================================================

    Description :MSR(Main Status Register)

    bit number  label       description
    0-3         DRV0-3 BUSY Drive Busy
                            0 = non-busy, 1 = busy
    4           CMD BSY     Command Busy
                            0 = non-busy, 1 = busy
    5           NON-DMA     NON-DMA State
                            0 = in data transfer by dma, 1 = non-dma
    6           DIO         Data I/O
                            0 = read, 1 = write
    7           RQM         Request for Master
                            0 = cannot transfer, 1 = data ready
===============================================================================
*/
#define DEF_FDC_MSR_DRIVE0_BUSY  0x01    /* b00000001    */
#define DEF_FDC_MSR_DRIVE1_BUSY  0x02    /* b00000010    */
#define DEF_FDC_MSR_DRIVE2_BUSY  0x04    /* b00000100    */
#define DEF_FDC_MSR_DRIVE3_BUSY  0x08    /* b00001000    */
#define DEF_FDC_MSR_MASK_DRIVE   0x0F    /* b00001111    */

#define DEF_FDC_MSR_COMMAND_BUSY 0x10    /* b00010000    */
#define DEF_FDC_MSR_NON_DMA      0x20    /* b00100000    */
#define DEF_FDC_MSR_DIO          0x40    /* b01000000    */
#define DEF_FDC_MSR_RQM          0x80    /* b10000000    */



次にメインステータスレジスターMSRを読み込む関数を作ります。inPortByte関数は

割り込みその2で作成しました。

	
/*
==================================================================================
    Funtion     :readFd0MSR
    Input       :void
    Output      :void
    Return      :unsigned char
                 < value of MSR >

    Description :read MSR from fdc0
==================================================================================
*/
PRIVATE INLINE unsinged char readFd0MSR( void )
{
    return( inPortByte( DEF_PORT_FDC0_MSR ) );
}



MSRを読み込んで、FDC0のドライブ0がビジー状態かを判定する関数例を作ります


/*
===================================================================================

    Description :Floppy Disk Drive

===================================================================================
*/
typedef enum
{
    E_FDD_DRIVE0 = 0x00000000,
    E_FDD_DRIVE1 = 0x00000001,
    E_FDD_DRIVE2 = 0x00000002,
    E_FDD_DRIVE3 = 0x00000003
} E_FDD_DRIVE;

/*
==================================================================================
    Funtion     :checkFdc0DriveBusy
    Input       :E_FDD_DRIVE drive
    Output      :void
    Return      :BOOL

    Description :test  DRV0 BUSY bit of MSR of fd0
==================================================================================
*/
PRIVATE INLINE BOOL checkFdc0DriveBusy( E_FDD_DRIVE drive )
{
    unsigned char read_data;
    unsigned char check_drive;

    read_data   = readFd0MSR( );

    check_drive = ( unsigned char )( 0x01 << drive );

    read_data &= DEF_FDC_MSR_MASK_DRIVE;

    return( check_drive == ( check_drive & read_data ) );
}



そして、ドライブがビジー中の場合にウェイトする関数を作成しておきます


/*
===================================================================================

    Description :Status of Floppy Disk Drive

===================================================================================
*/
#define DEF_FDD_OK             0
#define DEF_FDD_ERROR          (-1)
#define DEF_FDD_RETRY_COUNT    500

/*
==================================================================================
    Funtion     :waitFdc0
    Input       :void
    Output      :void
    Return      :STATUS

    Description :wait until fdc0 is free 
==================================================================================
*/
PRIVATE STATUS waitFdc0( void )
{
    int	i;

    for( i = 0 ; i < DEF_FDD_RETRY_COUNT ; i++ )
    {
        if( False == checkFdc0DriveBusy( E_FDD_DRIVE0 ) )
        {
            return( DEF_FDD_OK );
        }
    }

    return( DEF_FDD_ERROR );
}



テープドライブレジスターTDR

テープドライブレジスターTDRは初期化時、特定のドライブにテープドライブサポートを

割り当てるときに使用します。ハードウェアリセットで初期化されますが、ソフトウェアリセットでは

初期化されません。このレジスターは特に使用しなくても問題ありません

このレジスターは読み込み/書き込みが可能です。

テープドライブレジスターTDRのビットアサイン


フロッピーディスクコントローラのテープドライブレジスターTDR
ビット シンボル 名称 説明
0-1 Tape SEL0-1 テープドライブ選択 テープドライブを選択します。ハードウェアリセット後は0x00に初期化されます
テープドライブ選択
Tape SEL1 Tape SEL0 選択ドライブ
0 0 選択無し
0 1 ドライブ1
1 0 ドライブ2
1 1 ドライブ3
ドライブ0はフロッピーディスクからのブートに使用するため、選択するこはできません
2-7 Reserved 予約 書き込み/読み込みしても不定値です


データレジスター

データレジスターは8ビット(ICによっては16ビット)の読み込み/書き込みができるレジスターです。

フロッピーディスクドライブを制御する制御コマンドを書き込み、またその結果が格納される重要なレジスターです

このレジスターにアクセスする前にメインステータスレジスターMSRのRQMビットとDIOビットを調べ、

読み込みまたは書き込み可能かどうか確認してからアクセスします。

制御コマンドのコマンドとそのパラメーターをこのレジスターに書き込みます。書き込む制御コマンドは

フロッピーディスクドライバその2で詳細を見ていきます

不正な(仕様に無いコマンドなど)をデータレジスターに書き込むと結果としてフロッピーディスクコントローラは

0x80をデータレジスターに格納します

データレジスターの実装

では実際にデータレジスターに1バイトの制御コマンドを書き込む実装例を見ていきます

(制御コマンドは複数のパラメーターがあるので、数回この関数をコールすることになります)


#define DEF_FDD_WRITE_CMD_RETRY     500

/*
==================================================================================
    Funtion     :writeFd0Command
    Input       : unsigned char command
                 < a command to send >
    Output      :void
    Return      :STATUS

    Description :write a control command
==================================================================================
*/
PRIVATE STATUS writeFd0Command( unsigned char command )
{
    int           i;
    unsigned char msr;

    for( i = 0 ; i < DEF_FDD_WRITE_CMD_RETRY ; i++ )
    {
        /*----------------------------------------------------------------------*/
        /* check whether DIO = 0, RQM = 1                                       */
        /*----------------------------------------------------------------------*/
        msr = inPortByte( DEF_PORT_FDC0_MSR );
        msr = msr & ( DEF_FDC_MSR_DIO | DEF_FDC_MSR_RQM );
        if( DEF_FDC_MSR_RQM == msr )
        {
            outPortByte( DEF_PORT_FDC0_CMD, command );
            return( DEF_FDD_OK );
        }
    }

    return( DEF_FDD_ERROR );
}



次に制御コマンドを書き込んだ後の処理結果(ステータス)を読み込む関数を作ります

(ステータスも複数バイトの場合がありますので、数回関数をコールするときがあります)


#define DEF_FDD_READ_DATA_RETRY     500

/*
==============================================================================
    Funtion     :readFd0Status
    Input       : unsigned char *data
                 < buffer >
    Output      :unsigned char *data
                 < received data >
    Return      :STATUS

    Description :read data from floppy disk controller
==============================================================================
*/
PRIVATE STATUS readFd0Status( unsigned char *data )
{
    int           i;
    unsigned char msr;

    for( i = 0 ; i < DEF_FDD_READ_DATA_RETRY ; i++ )
    {
        msr = inPortByte( DEF_PORT_FDC0_MSR );
        msr = msr & ( DEF_FDC_MSR_DIO | DEF_FDC_MSR_RQM );
        if( DEF_FDD_MSR_MRQ == msr )
        {
            *data = inPortByte( DEF_PORT_FDC0_STS );
            return( DEF_FDD_OK );
        }
    }

    return( DEF_FDD_ERROR );
}



デジタルインプットレジスターDIR

デジタルインプットレジスターDIRは読み込み専用のレジスターです

デジタルインプットレジスターDIRのビットアサイン


フロッピーディスクコントローラのデジタルインプットレジスターDIR
ビット シンボル 名称 説明
0 HIGH DENS 高密度 IDENTピンの入力が0(通常3.5インチドライブ)のときにHIGH DENS はドライブのビットレートに応じて下記値をとります
DIRのHIGH DENSビット
データレート HIGH DENS
1Mbps 0
500Kbps 0
300Kbps 1
250Kbps 1

IDENTピンの入力が1(通常5.25インチドライブ)の場合はビットレートに応じてHIGH DENSの値 は逆の値となります
1-2 DRATE SEL0-1 データレートセレクタ データレートセレクタレジスターDSRのDRATE SEL0-1ビットで選択したデータレート設定値が 反映されます。
データレートセレクタ
DRATE SEL1 DRATE SEL0 データレートMFM
1 1 1Mbps
0 0 500Kbps
0 1 300Kbps
1 0 250Kbps(デフォルト)
3-6 Reserved 予約 1固定です。
7 DSK CHG ディスク変化 ドライブと接続しているDSK CHGピンの値が反映されます。DSK CHGピンはオリジナルの8272Aには 無いピンとなります。このピンは後継のICで追加されました。


制御設定レジスター(CCR:Configuration Control Register)

制御設定レジスターCCRは書き込み専用のレジスターです。

制御設定レジスターCCRのビットアサイン


フロッピーディスクコントローラの制御設定レジスターCCR
ビット シンボル 名称 説明
0-1 DRATE SEL0-1 データレートセレクター データレートセレクタービットはデータレートセレクターDSRのDRATE SEL0-1ビットと 同様の役割となります。
データレートセレクター
DRATE SEL1 DRATE SEL0 データレートMFM
1 1 1Mbps
0 0 500Kbps
0 1 300Kbps
1 0 250Kbps(デフォルト)


ここまでで、フロッピーディスクコントローラのレジスターを制御できるようになりました

次回はデータレジスターに制御コマンドを書き込んでフロッピーディスクからデータを読み込んだり

してみたいと思います

inserted by FC2 system