0から作るソフトウェア開発
日々勉強中。。。 |
Follow @Nina_Petipa |
0から作るOS開発 フロッピーディスクドライバその2 |
フロッピーディスクコントローラの制御コマンド一覧 | ||||
---|---|---|---|---|
ID | 制御コマンド | 名称 | 種類 | 説明 |
0x02 | READ TRACK | 1トラック読み込み | データ転送 | 指定した1トラックを読み込みます |
0x03 | SPECIFY | 制御時間指定 | 制御 | ドライブを制御する時間を指定するコマンドです |
0x04 | SENSE DRIVE STATUS | ドライブステータス取得 | 制御 | ドライブのステータス情報を取得します |
0x05 | WRITE DATA | データ書き込み | データ転送 | セクター単位でデータを書き込みます |
0x06 | READ DATA | データ読み込み | データ転送 | セクター単位でデータを読み込みます |
0x07 | RECALIBRATE | ヘッド位置再修正 | 制御 | ヘッドをトラック0の位置に修正します(戻します) |
0x08 | SENSE INTERRUPT STATUS | 割り込みステータス情報取得 | 制御 | 割り込みのステータス情報を取得します |
0x09 | WRITE DELETED DATA | 削除済みデータ書き込み | データ転送 | 削除済みマークが付いているセクターにデータを書き込みます |
0x0A | READ ID | ID読み込み | 制御 | ヘッドの位置を取得します |
0x0C | READ DELETED DATA | 削除済みデータ読み込み | データ転送 | 削除済みマークが付いているセクターにデータを読み込みます |
0x0D | FORMAT TRACK | トラックのフォーマット | データ転送 | トラック全体をフォーマットします |
0x0E | DUMPREG | レジスターダンプ |
制御 (拡張) |
レジスターの値を取得します。デバッグ用です |
0x0F | SEEK | シーク | 制御 | ヘッドを現在のトラックから別のトラックに移動します |
0x10 | VERSION | バージョン取得 |
制御 (拡張) |
フロッピーディスクコントローラが旧バージョンか新バージョンかの情報を取得します |
0x11 | SCAN EQUAL | 指定データのスキャン | 制御 | 指定したデータと同じデータがあるかどうか調べます |
0x12 | PERPENDICULAR MODE | 垂直モード |
制御 (拡張) |
フロッピーディスクドライブの垂直モードを制御します |
0x13 | CONFIGURE | 設定 |
制御 (拡張) |
フロッピーディスクコントローラの特定機能を設定します |
0x14 | LOCK | ロック |
制御 (拡張) |
バッファ(FIFO)をロックします |
0x16 | VERIFY | データ検査 |
制御 (拡張) |
データを検査します |
0x19 | SCAN LOW OR EQUAL | 指定データ以下のデータスキャン | データ転送 | 指定したデータと同じかそれより下の値のデータがあるかどうか調べます |
0x1D | SCAN HIGH OR EQUAL | 指定データ以上のデータスキャン | データ転送 | 指定したデータと同じかそれより上の値のデータがあるかどうか調べます |
0x8F | RELATIVE SEEK | 相対シーク |
制御 (拡張) |
現在のヘッド位置から相対位置を指定してシークします |
/********************************************************************************* File:floppy.h Description:definition for floppy disk driver *********************************************************************************/
#ifndef __FLOPPY__H #define __FLOPPY__H
/* =================================================================================== Description:Control Commands for Floppy Disk Controller =================================================================================== */
typedef enum { FDC_CMD_READ_TRACK = 0x02, FDC_CMD_SPECIFY = 0x03, FDC_CMD_SENSE_DRIVE_STATUS = 0x04, FDC_CMD_WRITE_DATA = 0x05, FDC_CMD_READ_DATA = 0x06, FDC_CMD_RECALIBRATE = 0x07, FDC_CMD_SENSE_INTERRUPT_STATUS = 0x08, FDC_CMD_WRITE_DELETED_DATA = 0x09, FDC_CMD_READ_ID = 0x0A, FDC_CMD_READ_DELETED_DATA = 0x0C, FDC_CMD_FORMAT_TRACK = 0x0D, FDC_CMD_DUMPREG = 0x0E, FDC_CMD_SEEK = 0x0F, FDC_CMD_VERSION = 0x10, FDC_CMD_SCAN_EQUAL = 0x11, FDC_CMD_PERPENDICULAR_MODE = 0x12, FDC_CMD_CONFIGURE = 0x13, FDC_CMD_LOCK = 0x14, FDC_CMD_VERIFY = 0x16, FDC_CMD_SCAN_LOW_OR_EQUAL = 0x19, FDC_CMD_SCAN_HIGH_OR_EQUAL = 0x1D, FDC_CMD_RELATIVE_SEEK = 0x8F } E_FDC_CMDS; #endif
/* __FLOPPY__H */
フロッピーディスクコントローラの制御コマンドの拡張ビット | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
シンボル | ラベル | 名称 | 説明 | ||||||||||||||||||
MT | Multi-track selector | マルチトラックセレクター |
両面のトラックを1つのトラックとして操作するかどうかを指定します 0:シングルトラックとして操作します 1:マルチトラックとして操作します。マルチトラック時にはヘッド0とヘッド1の上にあるディスク両面の トラックを1つのトラックとして操作します(合計32セクターとして操作します)。セクターはヘッド0上の トラックから数え始めて、ヘッド1のトラック上の最後のセクターがマルチトラックとしての最終セクターと なります。 |
||||||||||||||||||
MFM | MFM(Modified Frequency Modulation) mode selector | MFMモードセレクター |
倍密度モードとして操作するかどうかを指定します 0:単密度のディスクモードとして操作します(FMモード) 1:倍密度ディスクモードとして操作します(MFMモード)。通常の3.5インチフロッピーディスク(1.44MB)は 倍密度となります。 |
||||||||||||||||||
SK | Skip flag | スキップフラグ |
削除済みデータアドレスマークが付いているセクターを飛ばすかどうかを指定します 0:READ/WRITE DATAコマンド時に削除済みデータアドレスマークが付いているセクターを飛ばしません 1:READ/WRITE DATAコマンド時に削除済みデータアドレスマークが付いているセクターを 自動的に飛ばします。逆にREAD/WRITE DELETED DATAコマンドは削除済みデータアドレス マークが付いているセクターのみアクセスします。 |
||||||||||||||||||
H/HDS | Head | ヘッド |
操作するヘッドを指定します 0:ヘッド0を操作します 1:ヘッド1を操作します |
||||||||||||||||||
DS0、DS1 | Disk Drive | ディスクドライブ |
操作するディスクドライブを指定します
|
/* =================================================================================== Description:Extended Control Command Bit =================================================================================== */
typedef enum { FDC_CMD_EXT_SK = 0x20, FDC_CMD_EXT_MF = 0x40, FDC_CMD_EXT_MT = 0x80 } E_FDC_CMDS_EXT;
/* =================================================================================== Description:1st Parameters of Control Command =================================================================================== */
typedef enum { FDC_CMD_1ST_PRM_DRIVE0 = 0x00, FDC_CMD_1ST_PRM_DRIVE1 = 0x01, FDC_CMD_1ST_PRM_DRIVE2 = 0x02, FDC_CMD_1ST_PRM_DRIVE3 = 0x03, FDC_CMD_1ST_PRM_HEAD0 = 0x00, FDC_CMD_1ST_PRM_HEAD1 = 0x04 } E_FDC_CMDS_1ST_PRM;
制御コマンドのGap3サイズ | |
---|---|
Gap3サイズ | 説明 |
27 | 3.5インチディスクのギャップ3サイズです。この値を使用します |
32 | 5.25インチディスクのギャップ3サイズです |
42 | 標準のギャップ3サイズです |
/* =================================================================================== Description:Gap3 Size of Control Command =================================================================================== */
typedef enum { FDC_CMD_GAP3_SIZE_3_5 = 27, FDC_CMD_GAP3_SIZE_5_25 = 32, FDC_CMD_GAP3_SIZE_STD = 42 } E_FDC_CMDS_GP3_SIZE;
セクターサイズ = 2 ^ N * 128
/* =================================================================================== Description:Sector Size of Control Command =================================================================================== */
typedef enum { FDC_CMD_SECTOR_SIZE_128 = 0, FDC_CMD_SECTOR_SIZE_256 = 1, FDC_CMD_SECTOR_SIZE_512 = 2, FDC_CMD_SECTOR_SIZE_1024 = 3, FDC_CMD_SECTOR_SIZE_2048 = 4, FDC_CMD_SECTOR_SIZE_4096 = 5, FDC_CMD_SECTOR_SIZE_8192 = 6, FDC_CMD_SECTOR_SIZE_16384 = 7 } E_FDC_CMDS_SECTOR_SIZE;
writeFd0Command( FDC_CMD_SEEK ); /* SEEKコマンド書き込み */
writeFd0Command( 0x00 ); /* パラメーターその1(ヘッド0、ドライブ0指定)*/
writeFd0Command( 0x12 ); /* パラメーターその2(移動先シリンダ番号=18) */
#define DEF_FDC_NUM_STATUS 7
unsigned char fdc_status[ DEF_FDC_NUM_STATUS ];
STATUS status;
for( i = 0 ; i < DEF_FDC_NUM_STATUS ; i++ )
{
status = readFd0Status( &fdc_status[ i ] );
}
ステータスレジスターST0のビットアサイン | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ビット | シンボル | 名称 | 説明 | ||||||||||||||||||
0, 1 | DS0, DS1 | 選択ドライブ |
現在選択中のドライブが格納されます
|
||||||||||||||||||
2 | H | 選択ヘッド |
現在のヘッドが格納されます 0:ヘッド0 1:ヘッド1 |
||||||||||||||||||
3 | - | 予約 | 予約ビットです | ||||||||||||||||||
4 | EC | ユニットチェック |
ドライブの制御で次のフォルトが発生した場合1が格納されます。0だと制御成功です。 1:RECALIBRATEコマンドの失敗(80ステップ以上のパルスを出力しました) 2:REALTIVE SEEKコマンドでトラック0を超えるシークをしました |
||||||||||||||||||
5 | SE | シーク終了 |
シークが終了した場合に1が格納されます。1がセットされる条件は次のようになります 1:SEEK、RECALIBRATEコマンドが完了したとき 2:指定したセクターに対してREAD、WRITEが完了したとき |
||||||||||||||||||
6, 7 | IC0, IC1 | 割り込みコード |
割り込みが発生した条件コードが格納されます
|
ステータスレジスターST1のビットアサイン | |||
---|---|---|---|
ビット | シンボル | 名称 | 説明 |
0 | MA | アドレスマーク消失 |
次の条件でアドレスマークが消失した場合に1が格納されます 1:IDXピンが出力するインデックスパルスの後に指定トラックのIDアドレスマークを検出できない場合 2:指定トラックのデータアドレスマークもしくは削除済みデータアドレスマークを検出できない場合 |
1 | NW | 書き込み不可 |
次のコマンドを実行中にWPピンが1になり、このビットに1が格納されます WRITE DATAコマンド WRITE DELETED DATAコマンド FORMAT TRACKコマンド |
2 | ND | データ無し |
次の条件時に1が格納されます 1:READ DATAコマンド、READ DELETED DATAコマンド実行時に指定されたセクターが検出できなかった 2:READ IDコマンド実行時にIDが読み込めなかった(エラーが発生した) 3:READ TRACKコマンドで連続したセクターを検出できなかった |
3 | - | 予約 | 0固定です |
4 | OR | オーバーラン/アンダーラン | オーバーランまたはアンダーランが発生して、時間内にCPUまたはDMAからデータを受信できなかった ときに1が格納されます |
5 | DE | データエラー | セクターのIDフィールドまたはデータフィールドでCRCエラーを検出した場合に1が格納されます |
6 | - | 予約 | 0固定です |
7 | EN | シリンダー終端検出 | READ系コマンド、WRITE系コマンド書き込み後に TCピンの入力(DMAコントローラからのデータ転送中止要求)が無い場合に1が格納されます。 (現在のトラックの最終セクターを越えてアクセスしようとした) |
ステータスレジスターST2のビットアサイン | |||
---|---|---|---|
ビット | シンボル | 名称 | 説明 |
0 | MD | データアドレスマーク消失 | データアドレスマークまたは削除済みデータアドレスマークを検出できなかった場合に1が格納されます |
1 | BC | 不良シリンダー | セクターのIDフィールドからトラックアドレスまでがフロッピーディスクコントローラが保持している トラックアドレスと異なり、トラックアドレスの値が0xFFであった場合に1が格納されます |
2 | SN | スキャン条件不適合 | SCAN系コマンド処理中に指定された条件に適合したセクターを検出できなかった場合に1が格納されます |
3 | SH | スキャンヒット | SCAN系コマンド処理中に指定された条件に適合したセクターを検出できた場合に1が格納されます |
4 | WC | エラーシリンダー | セクターのIDフィールドからトラックアドレスまでがフロッピーディスクコントローラが保持している トラックアドレスと異なった場合に1が格納されます |
5 | DD | データフィールドのデータエラー | データフィールドでCRCエラーを検出した場合に1が格納されます |
6 | CM | コントロールマーク |
次の条件時に1が格納されます 1:READ DATAコマンド時に削除済みデータアドレスマークを検出した場合 2:READ DELETED DATAコマンド時にデータアドレスマークを検出した場合 |
7 | - | 予約 | 0固定です |
ステータスレジスターST3のビットアサイン | |||
---|---|---|---|
ビット | シンボル | 名称 | 説明 |
0, 1 | DS0, DS1 | 選択ドライブ | DS0ピン、DS1ピンの状態が格納されます |
1 | HD | ヘッドアドレス | HDSELピンの状態が格納されます |
3 | - | 予約 | 1固定です |
4 | T0 | トラック0 | TRK0ピンの状態が格納されます |
5 | - | 予約 | 1固定です |
6 | WP | 書き込み保護 | WPピンの状態が格納されます |
7 | - | 予約 | 0固定です |
READ TRACK(0x02) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | MFM | 0 | 0 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | データ長(セクターサイズが0以外の場合は0xFFを指定) |
READ TRACK(0x02)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | ST0 | |||||||
1 | ST1 | |||||||
2 | ST2 | |||||||
3 | シリンダー番号 | |||||||
4 | ヘッド番号 | |||||||
5 | セクター番号 | |||||||
6 | セクターサイズ |
SPECIFY(0x03) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
1 | ステップレート | ヘッドアンロードタイム | ||||||
2 | ヘッドロードタイム | NDM |
ステップレートSRT(Step Rate)[ms] | ||||
---|---|---|---|---|
値 | データ転送レート(DRATE SELで設定したデータレート) | |||
1Mbps | 500Kbps | 300Kbps | 250Kbps | |
0x0 | 8.0 | 16 | 26.7 | 32 |
0x1 | 7.5 | 15 | 25.0 | 30 |
0x2 | 7.0 | 14 | 23.3 | 28 |
0x3 | 6.5 | 13 | 21.7 | 26 |
0x4 | 6.0 | 12 | 20.0 | 24 |
0x5 | 5.5 | 11 | 18.3 | 22 |
0x6 | 5.0 | 10 | 16.7 | 20 |
0x7 | 4.5 | 9 | 15.0 | 18 |
0x8 | 4.0 | 8 | 13.3 | 16 |
0x9 | 3.5 | 7 | 11.7 | 14 |
0xA | 3.0 | 6 | 10.0 | 12 |
0xB | 2.5 | 5 | 8.3 | 10 |
0xC | 2.0 | 4 | 6.7 | 8 |
0xD | 1.5 | 3 | 5.0 | 6 |
0xE | 1.0 | 2 | 3.3 | 4 |
0xF | 0.5 | 1 | 1.2 | 2 |
ヘッドアンロードタイムHUT(Head Unload Time)[ms] | ||||
---|---|---|---|---|
値 | データ転送レート(DRATE SELで設定したデータレート) | |||
1Mbps | 500Kbps | 300Kbps | 250Kbps | |
0x0 | 128 | 256 | 426 | 512 |
0x1 | 8 | 16 | 26.7 | 32 |
0x2 | 16 | 32 | 53.3 | 64 |
0x3 | 24 | 48 | 80 | 96 |
0x4 | 32 | 64 | 106.7 | 128 |
0x5 | 40 | 80 | 133.3 | 160 |
0x6 | 48 | 96 | 160.0 | 192 |
0x7 | 56 | 112 | 186.7 | 224 |
0x8 | 64 | 128 | 213.3 | 256 |
0x9 | 72 | 144 | 240 | 288 |
0xA | 80 | 160 | 266.7 | 320 |
0xB | 88 | 176 | 293.3 | 352 |
0xC | 96 | 192 | 320 | 384 |
0xD | 104 | 208 | 346.7 | 412 |
0xE | 112 | 224 | 373.3 | 448 |
0xF | 120 | 240 | 400 | 480 |
ヘッドロードタイムHLT(Head Load Time)[ms] | ||||
---|---|---|---|---|
値 | データ転送レート(DRATE SELで設定したデータレート) | |||
1Mbps | 500Kbps | 300Kbps | 250Kbps | |
0x00 | 128 | 256 | 426 | 512 |
0x1 | 1 | 2 | 3.3 | 4 |
0x2 | 2 | 4 | 6.6 | 8 |
… | … | … | … | … |
0x7E | 126 | 252 | 420 | 504 |
0x7F | 127 | 254 | 423 | 508 |
NDMビット(Non-DMAビット) | |
---|---|
値 | 説明 |
0 | DMAを使用します |
1 | DMAを使用しません |
#define DEF_FDC_CMD_SPECIFY_MASK_SRT ( 0x0F << 4 ) #define DEF_FDC_CMD_SPECIFY_MASK_HUT ( 0x0F << 0 ) #define DEF_FDC_CMD_SPECIFY_MASK_HLT ( 0x7F << 1 ) #define DEF_FDC_CMD_SPECIFY_NDM 0x01
/* ================================================================================== Funtion :writeFd0CmdSpecify Input :unsigned char step_rate < step rate : input range is between 0x00 and 0x0F 1M : 0.5 - 8.0 msec 500K : 1 - 16 msec 300K : 1.7 - 26.7 msec 250K : 2 - 32 msec > unsigned char head_unload_time < head unload time : input range is between 0x00 and 0x0F 1M : 8 - 128 msec 500K : 16 - 256 msec 300K : 26.7 - 426 msec 250K : 32 - 512 msec > unsigned char head_load_time < head load time : input range is between 0x00 and 0x7F 1M : 1 - 128 msec 500K : 2 - 256 msec 300K : 3.3 - 426 msec 250K : 4 - 512 msec > BOOL non_dma_mode < Non DMA mode : true = non DMA mode, false = DMA mode > Output :void Return :STAUS Description :write specify 0x03 Command ================================================================================== */
PRIVATE STATUS writeFd0CmdSpecify( unsigned char step_rate, unsigned char head_unload_time, unsigned char head_load_time, BOOL non_dma_mode) { STATUS status; unsgined char parameter;
/*--------------------------------------------------------------------------*/ /* write SPECIFY command */ /*--------------------------------------------------------------------------*/
status = writeFd0Command( FDC_CMD_SPECIFY );
/*--------------------------------------------------------------------------*/ /* write srt and hut parameters */ /*--------------------------------------------------------------------------*/
parameter = ( step_rate << 4 ) & DEF_FDC_CMD_SPECIFY_MASK_SRT; parameter |= ( head_unload_time << 0 ) & DEF_FDC_CMD_SPECIFY_MASK_HUT; status |= writeFd0Command( parameter );
/*--------------------------------------------------------------------------*/ /* write hlt and non-dma mode */ /*--------------------------------------------------------------------------*/
parameter = ( head_load_time << 1 ) & DEF_FDC_CMD_SPECIFY_MASK_HLT; if( non_dma_mode ) { parameter |= DEF_FDC_CMD_SPECIFY_NDM; } else { parameter &= ~DEF_FDC_CMD_SPECIFY_NDM; } status |= writeFd0Command( parameter ); return( status ); }
SENSE DRIVE STATUS(0x04) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
SENSE DRIVE STATUS(0x04)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | ST3 |
WRITE DATA(0x05) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | 0 | 0 | 0 | 1 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | データ長(セクターサイズが0以外の場合は0xFFを指定) |
READ DATA(0x06) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | MFM | 0 | 0 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | データ長(セクターサイズが0以外の場合は0xFFを指定) |
#define DEF_FDC_CMDS_PRM_DTL 0xFF #define DEF_FDD_SECTORS_PER_TRACK 18
/* ================================================================================== Funtion :writeFdc0CmdReadData Input :E_FDC_CMDS_1ST_PRM drive E_FDC_CMDS_1ST_PRM head unsigned char track unsigned char sector Output :void Return :STAUS Description :issue Read Data Command ================================================================================== */
PRIVATE STATUS writeFdc0CmdReadData( E_FDC_CMDS_1ST_PRM drive, E_FDC_CMDS_1ST_PRM head, unsigned char track, unsigned char sector ) { int i; STATUS status; unsigned char parameter; unsigned char fdd_statuses[ DEF_FDC_NUM_STATUS ]; unsigned char st0;
/* status of sense interrupt command */
unsigned char pcn;
/* status of sense interrupt command */
/*--------------------------------------------------------------------------*/ /* write read data command */ /*--------------------------------------------------------------------------*/
status = writeFd0Command( FDC_CMD_READ_DATA );
/*--------------------------------------------------------------------------*/ /* write head and drive parameters */ /*--------------------------------------------------------------------------*/
parameter = ( unsigned char )( head | drive ); status |= writeFd0Command( parameter );
/*--------------------------------------------------------------------------*/ /* write specified track */ /*--------------------------------------------------------------------------*/
status |= writeFd0Command( track );
/*--------------------------------------------------------------------------*/ /* write specified drive */ /*--------------------------------------------------------------------------*/
status |= writeFd0Command( ( unsigned char )head >> 2 );
/*--------------------------------------------------------------------------*/ /* write specified sector */ /*--------------------------------------------------------------------------*/
if( DEF_FDD_SECTORS_PER_TRACK < secotr ) { sector = DEF_FDD_SECTORS_PER_TRACK; } status |= writeFd0Command( sector );
/*--------------------------------------------------------------------------*/ /* write sector size */ /*--------------------------------------------------------------------------*/
status |= writeFd0Command( ( unsgined char )FDC_CMD_SECTOR_SIZE_512 );
/*--------------------------------------------------------------------------*/ /* write length of track */ /*--------------------------------------------------------------------------*/
status |= writeFd0Command( DEF_FDD_SECTORS_PER_TRACK );
/*--------------------------------------------------------------------------*/ /* write gap3 length */ /*--------------------------------------------------------------------------*/
status |= writeFd0Command( ( unsgined char )FDC_CMD_GAP3_SIZE_3_5 );
/*--------------------------------------------------------------------------*/ /* write data length( special sector size ) */ /*--------------------------------------------------------------------------*/
status |= writeFd0Command( DEF_FDD_CMDS_PRM_DTL ); if( DEF_FDD_OK == status ) {
/*----------------------------------------------------------------------*/ /* wait until irq of fdd is fired */ /*----------------------------------------------------------------------*/
fddWaitIrq( );
/*----------------------------------------------------------------------*/ /* read statuses */ /*----------------------------------------------------------------------*/
for( i = 0 ; i < DEF_FDC_NUM_STATUS ; i++ ) { status |= readFd0Status( &fdc_statuses[ i ] ); } if( DEF_FDD_OK != status ) { return( status ); }
/*----------------------------------------------------------------------*/ /* issue sense interrupt status command and read its statuses */ /*----------------------------------------------------------------------*/
readFdc0SenseInterruptStatus( &st0, &pcn ); } return( status ); }
/*--------------------------------------------------------------------------*/ /* set up DMA controller for fdd */ /*--------------------------------------------------------------------------*/
initDMAforReadFDD( trasfered_address, data_length - 1 );
/*--------------------------------------------------------------------------*/ /* start the motor of specified dirve */ /*--------------------------------------------------------------------------*/
startFdc0Motor( drive );
/*--------------------------------------------------------------------------*/ /* issue read data command to read a sector */ /*--------------------------------------------------------------------------*/
writeFdc0CmdReadData( drive, head, track, sector );
/*--------------------------------------------------------------------------*/ /* wait until irq of dma is fired */ /*--------------------------------------------------------------------------*/
dmaWaitIrq( E_DMA_CHANNEL2 );
/*--------------------------------------------------------------------------*/ /* stop the motor of specified dirve */ /*--------------------------------------------------------------------------*/
stopFdc0Motor( drive );
RECALIBRATE(0x07) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | DS1 | DS0 |
#define DEF_FDD_CALIBRATE_RETRY 10 #define DEF_FDC_ST0_IC 0xC0
/* ================================================================================== Funtion :writeFd0CmdRecalibrate Input :E_FDC_CMDS_1ST_PRM drive Output :void Return :STAUS Description :recalibrate ================================================================================== */
PRIVATE STATUS writeFd0CmdRecalibrate( E_FDC_CMDS_1ST_PRM drive ) { int i; STATUS status unsigned char st0; unsigned char pcn;
/*--------------------------------------------------------------------------*/ /* start the morter before of a calibration */ /*--------------------------------------------------------------------------*/
status = startFdc0Motor( drive ); if( DEF_FDD_OK == status ) {
/*----------------------------------------------------------------------*/ /* retry a calibration */ /*----------------------------------------------------------------------*/
for( i = 0 ; i < DEF_FDD_CALIBRATE_RETRY ; i++ ) {
/*------------------------------------------------------------------*/ /* issue recalibrate command */ /*------------------------------------------------------------------*/
status = writeFd0Command( FDC_CMD_RECALIBRATE ); status |= writeFd0Command( ( unsigned char )drive );
/*------------------------------------------------------------------*/ /* wait irq of fdd */ /*------------------------------------------------------------------*/
if( DEF_FDD_OK == status ) { fddWaitIrq( ); } else { continue; }
/*------------------------------------------------------------------*/ /* read sense interrupt status */ /*------------------------------------------------------------------*/
status = readFdc0SenseInterruptStatus( &st0, &pcn );
/*------------------------------------------------------------------*/ /* if an error occurs, retry a recalibration */ /*------------------------------------------------------------------*/
if( ( status != DEF_FDD_OK ) || ( ( st0 & DEF_FDC_ST0_IC ) != 0x00 ) ) { continue; }
/*------------------------------------------------------------------*/ /* whether head back to track 0 or not */ /*------------------------------------------------------------------*/
if( 0 == pcn ) {
/*--------------------------------------------------------------*/ /* stop the motor */ /*--------------------------------------------------------------*/
status = stopFdc0Motor( drive ); return( status ); } } }
/*--------------------------------------------------------------------------*/ /* if the drive causes an error, stop the motor */ /*--------------------------------------------------------------------------*/
status = stopFdc0Motor( drive ); return( DEF_FDD_ERROR ); }
割り込みの原因によるステータスレジスターST0のSEビットとICコード | ||
---|---|---|
SEビット | ICコード(ビット) | 割り込み原因 |
0 | 11b | ポーリング |
1 | 00b | SEEK、RECALIBRATEコマンドの正常終了 |
0 | 01b | SEEK、RECALIBRATEコマンドの異常終了 |
SENSE INTERRUPT STATUS(0x08) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
SENSE INTERRUPT STATUS(0x08)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | ST0 | |||||||
1 | シリンダー番号(PCN:Present Cylinder Number) |
/* ================================================================================== Funtion :readFdc0SenseInterruptStatus Input :void Output :unsigned char* st0 < status register st0 > unsigned char* pcn < present cylinder number > Return :STATUS Description :read sense interrupt command status and output them ================================================================================== */
PRIVATE STATUS readFdc0SenseInterruptStatus( unsigned char* st0, unsigned char* pcn ) { STATUS status; if( ( st0 == Null ) || ( pcn == Null ) ) { return( DEF_FDD_ERROR ); }
/*--------------------------------------------------------------------------*/ /* issue sense intterup status command */ /*--------------------------------------------------------------------------*/
status = writeFd0Command( FDC_CMD_SENSE_INTERRUPT_STATUS );
/*--------------------------------------------------------------------------*/ /* read the results */ /*--------------------------------------------------------------------------*/
status |= readFd0Status( st0 ); status |= readFd0Status( pcn ); return( status ); }
WRITE DELETED DATA(0x09) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | 0 | 0 | 1 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | データ長(セクターサイズが0以外の場合は0xFFを指定) |
READ ID(0x0A) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | MFM | 0 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
SKビットとREAD DELETED DATAコマンドのステータスとの関係 | ||||
---|---|---|---|---|
SKビットの値 | 検出したデータアドレスマークのタイプ | READ DELETED DATAコマンドのステータス | ||
セクターが読み込めたか? | ST2のCMビットの値 | 説明 | ||
0 | 通常データ | Yes | 1 | 次のセクターはサーチされていないのでステータスに格納されるセクター番号はインクリメントされていません |
0 | 削除済みデータ | Yes | 0 | コマンドは正常完了しました |
1 | 通常データ | No | 1 |
コマンドは正常完了しましたがセクターは読み込みませんでした (スキップしました) |
1 | 削除済みデータデータ | Yes | 0 | コマンドは正常完了しました |
READ DELETED DATA(0x09) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | SK | 0 | 1 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | データ長(セクターサイズが0以外の場合は0xFFを指定) |
フォーマット時の標準値 | ||||||
---|---|---|---|---|---|---|
ドライブ | ディスク記録密度 |
セクターサイズ (バイト) |
セクターサイズ (コマンドで指定) |
セクター数 (コマンドで指定) |
ギャップ1サイズ | ギャップ2サイズ |
5.25インチ | 倍密度 | 256 | 0x01 | 0x12 | 0x0A | 0x0C |
256 | 0x01 | 0x10 | 0x20 | 0x32 | ||
512 (PC-ATの標準) |
0x02 | 0x09 | 0x2A | 0x50 | ||
1024 | 0x03 | 0x04 | 0x80 | 0xF0 | ||
2048 | 0x04 | 0x02 | 0xC8 | 0xFF | ||
4096 | 0x05 | 0x01 | 0xC8 | 0xFF | ||
4096 | 0x05 | 0x01 | 0xC8 | 0xFF | ||
3.5インチ | 倍密度 | 256 | 0x01 | 0x0F | 0x0E | 0x36 |
512 (PS/2標準) |
0x02 | 0x09 | 0x1B | 0x54 | ||
1024 | 0x03 | 0x05 | 0x35 | 0x74 |
FORMAT TRACK(0x0D) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | MFM | 0 | 0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | セクターサイズ | |||||||
3 | トラック長(1トラック中のセクター数) | |||||||
4 | ギャップ3サイズ | |||||||
5 | フォーマットデータ(この1バイトデータでデータを埋めます) |
FORMAT TRACKのセクター指定コマンド | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | シリンダー番号 | |||||||
1 | ヘッド番号 | |||||||
2 | セクター番号 | |||||||
3 | セクターサイズ |
FORMAT TRACK(0x0D)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | ST0 | |||||||
1 | ST1 | |||||||
2 | ST2 | |||||||
3 | 未定義 | |||||||
4 | 未定義 | |||||||
5 | 未定義 | |||||||
6 | 未定義 |
DUMPREG(0x0E) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 |
DUMPREG(0x0E)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | ドライブ0の現在のシリンダー番号(PCN:Present Cylinder Number) | |||||||
1 | ドライブ1の現在のシリンダー番号(PCN:Present Cylinder Number) | |||||||
2 | ドライブ2の現在のシリンダー番号(PCN:Present Cylinder Number) | |||||||
3 | ドライブ0の現在のシリンダー番号(PCN:Present Cylinder Number) | |||||||
4 | ステップレート | ヘッドアンロードタイム | ||||||
5 | ヘッドロードタイム | NDM | ||||||
6 | セクター数/トラック長(1トラック中のセクター数) | |||||||
7 | LOCK | 0 | D3 | D2 | D1 | D0 | GAP | WGATE |
8 | 0 | EIS | EFIFO | POLL | FIFOTHR | |||
9 | PRETRK |
DUMPREGコマンドステータスの各ビットについて | |
---|---|
ビット名称 | 説明 |
LOCK | CONFIGUREコマンドで使用するEFIFO、FIFOTHR、PRETRKをソフトウェアリセットで デフォルト値にするかどうかを決定するビットです |
D3-D0 |
D0:ドライブ0が選択されているかどうかを示します D1:ドライブ1が選択されているかどうかを示します D2:ドライブ2が選択されているかどうかを示します D3:ドライブ3が選択されているかどうかを示します |
GAP | 垂直(Perpendicular)モード時にギャップ2サイズを変更するかどうかを示します |
WGATE | 垂直(Perpendicular)ドライブで事前消去メカ動作をするために、WEピンのタイミングを変更するかどうかを示します |
EIS | 事前シークが有効になっているかどうかを示します。 詳細はCONFIGUREコマンドの EISを参照してください |
EFIFO | FIFO(ICの内部バッファ)が有効になっているかどうかを示します。 詳細はCONFIGUREコマンドの EFIFOを参照してください |
POLL | ICの内部ポーリング処理が無効になっているかどうか示します。 詳細はCONFIGUREコマンドの POLLを参照してください |
FIFOTHR | READ系/WRITE系コマンドの実行時のFIFO(ICの内部バッファ)閾値が格納されます。 詳細はCONFIGUREコマンドの FIFOTHRを参照してください |
PRETRK | 前補正開始トラック番号が格納されます。 詳細はCONFIGUREコマンドの PRETRKを参照してください |
SEEK(0x0F) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | 移動先のシリンダー番号 |
#define DEF_FDD_SEEK_RETRY 10
/* ================================================================================== Funtion :writeFd0CmdSeek Input :E_FDC_CMDS_1ST_PRM drive < specify drive to seek > E_FDC_CMDS_1ST_PRM head < specify head to seek > unsgined char cylinder < specify cylinder to seek > Output :void Return :void Description :seek ================================================================================== */
PRIVATE STATUS writeFd0CmdSeek( E_FDC_CMDS_1ST_PRM drive, E_FDC_CMDS_1ST_PRM head, unsigned char cylinder) { int i; STATUS status unsigned char st0; unsigned char pcn;
/*--------------------------------------------------------------------------*/ /* retry seek */ /*--------------------------------------------------------------------------*/
for( i = 0 ; i < DEF_FDD_SEEK_RETRY ; i++ ) {
/*----------------------------------------------------------------------*/ /* issue seek command */ /*----------------------------------------------------------------------*/
status = writeFd0Command( FDC_CMD_SEEK ); status |= writeFd0Command( ( unsigned char )( drive | head ) ); status |= writeFd0Command( cylinder );
/*----------------------------------------------------------------------*/ /* wait irq of fdd */ /*----------------------------------------------------------------------*/
if( DEF_FDD_OK == status ) { fddWaitIrq( ); } else { continue; }
/*----------------------------------------------------------------------*/ /* read sense interrupt status */ /*----------------------------------------------------------------------*/
status = fddReadSenseInterruptStatus( &st0, &pcn );
/*----------------------------------------------------------------------*/ /* if an error occurs, retry a seek */ /*----------------------------------------------------------------------*/
if( ( status != DEF_FDD_OK ) || ( ( st0 & DEF_FDC_ST0_IC ) != 0x00 ) ) { continue; }
/*----------------------------------------------------------------------*/ /* whether specified cylinder is sought for or not */ /*----------------------------------------------------------------------*/
if( cylinder == pcn ) {
/*------------------------------------------------------------------*/ /* seek operation is finished! */ /*------------------------------------------------------------------*/
return( status ); } }
/*--------------------------------------------------------------------------*/ /* if the drive causes an error */ /*--------------------------------------------------------------------------*/
return( DEF_FDD_ERROR ); }
VERSION(0x10) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
VERSION(0x10)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
SCANコマンドとST2のSNビット、SHビットの関係 | |||
---|---|---|---|
コマンド | ステータスレジスターST2 | 説明 | |
ビット2 SNビット | ビット3 SHビット | ||
SCAN EQUAL |
0 1 |
1 0 |
ディスク上のデータ = 指定したデータ ディスク上のデータ ≠ 指定したデータ |
SCAN LOW OR EQUAL |
0 0 1 |
1 0 0 |
ディスク上のデータ = 指定したデータ ディスク上のデータ > 指定したデータ ディスク上のデータ ≯ 指定したデータ |
SCAN HIGH OR EQUAL |
0 0 1 |
1 0 0 |
ディスク上のデータ = 指定したデータ ディスク上のデータ < 指定したデータ ディスク上のデータ ≮ 指定したデータ |
SCAN EQUAL(0x11) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | SK | 1 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | STP |
PERPENDICULAR MODEコマンドとパラメーターの効果 | ||||||
---|---|---|---|---|---|---|
GAP | WGATE | モード | インデックスパルス後のVCOをLowにする時間 | Gap2サイズ | WRITEコマンド時のGap2率 | READコマンド時のGap2とVCOをLowにする時間 |
0 | 0 | 従来モード | 33バイト | 22バイト | 0バイト | 24バイト |
0 | 1 |
垂直モード (データレート500Kbps) |
33バイト | 22バイト | 19バイト | 24バイト |
1 | 0 |
予約 (従来モードとの互換のため) |
33バイト | 22バイト | 0バイト | 24バイト |
1 | 1 |
垂直モード (データレート1Mbps) |
18バイト | 41バイト | 38バイト | 43バイト |
PERPENDICULAR MODE(0x12) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
1 | OW | 0 | D3 | D2 | D1 | D0 | GAP | WGATE |
CONFIGURE(0x13) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | EIS | EFIFO | POLL | FIFOTHR | |||
3 | PRETRK |
CONFIGUREコマンドのパラメーター | ||
---|---|---|
ビット | 名称 | 説明 |
EIS | 事前シーク有効 |
0:事前シークを行いません<デフォルト値> 1:READ/WRITEコマンドの前に自動的にSEEK操作します(事前シーク) |
EFIFO | FIFO無効 |
0:FIFOを有効にします 1:FIFOを無効にします。ステータスレジスターの状態を判断して、データレジスターのデータを1バイトずつ読み出します<デフォルト値> |
POLL | ドライブのポーリング無効 |
0:ドライブをポーリングします<デフォルト値>。リセット後IRQ6を1回発生させます。ヘッドロード中とヘッドアンロード中はポーリングしません 1:ドライブのポーリングを無効にします |
FIFOTHR | FIFO閾値 | READ/WRITEコマンド実行中のFIFO閾値を設定します。閾値は1バイトから16バイトまで設定可能です。デフォルトは1が設定されています。 0x00を設定すると16バイトを選択したことになります。 |
PRETRK | トラック番号の開始位置前補正 | トラック0からトラック255まで設定できます。デフォルトはトラック0です。0x00を設定するとトラック0で、0xFFを設定するとトラック255を選択したことになります。 |
LOCK(0x14) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | LOCK | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
LOCK(0x14)ステータス | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | LOCK | 0 | 0 | 0 | 0 |
VERIFY(0x16) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | SK | 1 | 0 | 1 | 1 | 0 |
1 | EC | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | データ長(セクターサイズが0以外の場合は0xFFを指定)/セクター数 |
SCAN LOW OR EQUAL(0x19) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | SK | 1 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | STP |
SCAN HIGH OR EQUAL(0x1D) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | MT | MFM | SK | 1 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | シリンダー番号 | |||||||
3 | ヘッド番号 | |||||||
4 | セクター番号 | |||||||
5 | セクターサイズ | |||||||
6 | トラック長(1トラック中のセクター数) | |||||||
7 | ギャップ3サイズ | |||||||
8 | STP |
RELATIVE SEEK(0x8F) | ||||||||
---|---|---|---|---|---|---|---|---|
Byte/Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 1 | DIR | 0 | 0 | 1 | 1 | 1 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | HDS | DS1 | DS0 |
2 | 相対シリンダー番号 |
writeFdc0Dor( DEF_FDC_DOR_RESET );
writeFdc0Dor( DEF_FDC_DOR_ENABLE );
#define DEF_FDD_STEP_RATE_500K_03 0xD
/* 3msec */
#define DEF_FDD_HEAD_UNLOAD_TIME_500K_032 0x2
/* 32mese */
#define DEF_FDD_HEAD_LOAD_TIME_500K_032 0x10
/* 32msec */
#defnie DEF_FDC_CCR_DRATE_500KBPS 0x00
/* 500Kbps */
#define DEF_FDC_CCR_DRATE_300KBPS 0x01
/* 300Kbps */
#define DEF_FDC_CCR_DRATE_250KBPS 0x02
/* 250Kbps */
#define DEF_FDC_CCR_DRATE_1MBPS 0x03
/* 1Mbps */
/* ================================================================================== Funtion :initFdc0 Input :unsigned char drive < 0x00 : drive0 0x01 : drive1 0x02 : drive2 0x03 : drive3 > Output :void Return :STATUS Description :initialize the fdc0 ================================================================================== */
PRIVATE STATUS initFdc0( unsigned char drive ) { STATUS status; unsigned char st0; unsigned char pcn;
/*--------------------------------------------------------------------------*/ /* reset the controller */ /*--------------------------------------------------------------------------*/
writeFdc0Dor( DEF_FDC_DOR_RESET ); writeFdc0Dor( DEF_FDC_DOR_ENABLE );
/*--------------------------------------------------------------------------*/ /* wait irq after the controller resets */ /*--------------------------------------------------------------------------*/
fddWaitIrq( );
/*--------------------------------------------------------------------------*/ /* issue sense interrupt status commands four times */ /*--------------------------------------------------------------------------*/
/* 1st drive */
status = readFdc0SenseInterruptStatus( &st0, &pcn );
/* 2nd drive */
status |= readFdc0SenseInterruptStatus( &st0, &pcn );
/* 3rd drive */
status |= readFdc0SenseInterruptStatus( &st0, &pcn );
/* 4th drive */
status |= readFdc0SenseInterruptStatus( &st0, &pcn ); if( DEF_FDD_OK != status ) { return( DEF_FDD_ERROR ); }
/*--------------------------------------------------------------------------*/ /* steprate = 3ms, head unload time = 32ms, head load time = 32ms */ /*--------------------------------------------------------------------------*/
status = writeFd0CmdSpecify( DEF_FDD_STEP_RATE_500K_03, DEF_FDD_HEAD_UNLOAD_TIME_500K_032, DEF_FDD_HEAD_LOAD_TIME_500K_032, False ); if( DEF_FDD_OK != status ) { return( DEF_FDD_ERROR ); }
/*--------------------------------------------------------------------------*/ /* set data transfer rate to 500kbps( for 3.5 inch ) */ /*--------------------------------------------------------------------------*/
writeFdc0Ccr( DEF_FDC_CCR_DRATE_500KBPS );
/*--------------------------------------------------------------------------*/ /* calibrate a head position */ /*--------------------------------------------------------------------------*/
status = writeFd0CmdRecalibrate( ( E_FDC_CMDS_1ST_PRM )drive ); if( DEF_FDD_OK != status ) { return( DEF_FDD_ERROR ); } return( status ); }
#define DEF_FDD_SECTORS_PER_TRACK 18 #define DEF_FDD_NUM_HEADS 2
/* ================================================================================== Funtion :convertLBA2Sector Input :unsigned int lba < logical block addressing format > Output :void Return :unsigned char < sector number of converted physical address chs > Description :convert lba to sector number =================================================================================== */
PRIVATE INLINE unsigned char convertLBA2Sector( unsigned int lba ) { return( ( lba % DEF_FDD_SECTORS_PER_TRACK ) + 1 ); }
/* =================================================================================== Funtion :ConvertLBA2Head Input :unsigned int lba < logical block addressing format > Output :void Return :unsigned char < head number of converted physical address chs > Description :convert lba to head number =================================================================================== */
PRIVATE INLINE unsigned char convertLBA2Head( unsigned int lba ) { return( ( lba / ( DEF_FDD_SECTORS_PER_TRACK ) ) % DEF_FDD_NUM_HEADS ); }
/* =================================================================================== Funtion :convertLBA2Track Input :unsigned int lba < logical block addressing format > Output :void Return :unsigned char < cylinder number of converted physical address chs > Description :convert lba to cylinder number =================================================================================== */
PRIVATE INLINE unsigned char convertLBA2Track( unsigned int lba ) { return( lba / ( DEF_FDD_SECTORS_PER_TRACK * DEF_FDD_NUM_HEADS ) ); }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :fddReadSector Input :unsigned char drive < selected drive > unsigned int lba < read address > unsigned char *trans_address < DMA transfers data read from fdd to this address > unsigned int trans_length < DMA transfer count > Output :void Return :STATUS Description :read sector _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
PUBLIC STATUS fddReadSector( unsigned char drive, unsigned int lba, unsigned char *trasfered_address, unsigned int data_length ) { unsigned char head; unsigned char track; unsigned char sector; STATUS status; if( DEF_FDC_DOR_DRIVE3 < drive ) { return( DEF_FDD_ERROR ); }
/*--------------------------------------------------------------------------*/ /* set up DMA controller for fdd */ /*--------------------------------------------------------------------------*/
status = initDMAforReadFDD( trasfered_address, data_length - 1 );
/*--------------------------------------------------------------------------*/ /* start the motor of specified dirve */ /*--------------------------------------------------------------------------*/
startFdc0Motor( drive );
/*--------------------------------------------------------------------------*/ /* convert lba to chs */ /*--------------------------------------------------------------------------*/
head = convertLBA2Head( lba ); track = convertLBA2Track( lba ); sector = convertLBA2Sector( lba );
/*--------------------------------------------------------------------------*/ /* seek specified track */ /*--------------------------------------------------------------------------*/
status = fddSeek( drive, head, track ); if( status != DEF_FDD_OK ) { return( status ); }
/*--------------------------------------------------------------------------*/ /* issue read data command to read a sector */ /*--------------------------------------------------------------------------*/
status = writeFdc0CmdReadData( drive, head, track, sector );
/*--------------------------------------------------------------------------*/ /* wait until irq of dma is fired */ /*--------------------------------------------------------------------------*/
dmaWaitIrq( E_DMA_CHANNEL2 );
/*--------------------------------------------------------------------------*/ /* stop the motor of specified dirve */ /*--------------------------------------------------------------------------*/
stopFdc0Motor( drive ); return( status ); }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :fddInterrupt Input :void Output :void Return :void Description :handlin floppy drive interrupt _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
VOID fddInterrupt( VOID ) {
/* --------------------------------------------------------------------- */ /* entering interrupt */ /* --------------------------------------------------------------------- */
enter_interrupt( );
/* --------------------------------------------------------------------- */ /* inform irq fired */ /* --------------------------------------------------------------------- */
fddIrqFlagSet( True );
/* --------------------------------------------------------------------- */ /* inform end of interrupt to pics */ /* --------------------------------------------------------------------- */
interrupt_done( );
/* --------------------------------------------------------------------- */ /* exit interrupt */ /* --------------------------------------------------------------------- */
exit_interrupt( ); }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :initPIC Input :void Output :void Return :void Description :initialize pics _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
void initPIC( void ) {
/* PIC 初期化関数続き */ /* --------------------------------------------------------------------- */ /* send IMR ot PIC */ /* --------------------------------------------------------------------- */
outPortByte( PORT_MASTER_PIC_IMR, ( ~PIC_IMR_MASK_IRQ0 ) & ( ~PIC_IMR_MASK_IRQ1 ) & ( ~PIC_IMR_MASK_IRQ2 ) & ( ~PIC_IMR_MASK_IRQ6 ) ); outPortByte( PORT_SLAVE_PIC_IMR, PIC_IMR_MASK_IRQ_ALL ); }
#define DEF_IDT_INT_NUM_IRQ6 38
setupInterruptGate( DEF_IDT_INT_NUM_IRQ6, fddInterrupt );