このページは、[[OS-Wikiのページ:http://community.osdev.info/index.php?ATA]]のコピーです。
----
* ATAデバイス [#t94949c6]
-ATAは「AT Attachment」の略。
-ATA-1より古い規格がIDEだということになっている
--ATAの名が有名になる前は、ATAでもIDEと言っていたりしたので、その境界はややあいまい。
--Enhanced-IDEという存在が、ややこしさに輪をかける。これはATA-1の制定が遅れて、業界がもっと上位の規格に進み、その時に勝手に名前をつけた(E-IDEはATA-2の内容を部分的に先取りしたようなもの)。

* ATA仕様と転送速度 [#mfae5e57]
|モード|最大転送速度|IDE|ATA-1|E-IDE|ATA-2|ATA-3|ATA-4|
|PIO mode0|3.33MB/s|○|○|○|○|○|○|
|PIO mode1|5.22MB/s|○|○|○|○|○|○|
|PIO mode2|8.33MB/s|△|○|○|○|○|○|
|PIO mode3|11.1MB/s|  |  |○|○|○|○|
|PIO mode4|16.6MB/s|  |  |△|○|○|○|
|SW-DMA mode0|2.08MB/s|○|○|○|○|×|×|
|SW-DMA mode1|4.16MB/s|△|○|○|○|×|×|
|SW-DMA mode2|8.33MB/s|△|○|○|○|×|×|
|MW-DMA mode0|4.16MB/s|  |○|○|○|○|○|
|MW-DMA mode1|13.3MB/s|  |  |○|○|○|○|
|MW-DMA mode2|16.6MB/s|  |  |△|○|○|○|
|U-DMA mode0|16.6MB/s|  |  |  |  |  |○|
|U-DMA mode1|25.0MB/s|  |  |  |  |  |○|
|U-DMA mode2|33.3MB/s|  |  |  |  |  |○|
-(註)転送速度の単位はメガバイト毎秒
-SW-DMA:シングルワードDMA
-MW-DMA:マルチワードDMA
-U-DMA:ウルトラDMA
-○:仕様上で定義されており、サポートの可能性あり
-△:一部のデバイスはサポートしている
-×:この仕様では廃止されたモード
-空欄:仕様上にないので多分サポートされてない
-ATAでは必ずLBAアクセスがサポートされている。IDEではサポートされていないものがある。

* レジスタ [#p6d4e733]
-括弧内は、AT互換機でのプライマリの場合のアドレスです(参考)
-全てのレジスタの全てのbitにおいて、原則としては制御の流れで意味が変わる。ここに挙がっているのは代表例、くらいに思ってほしい。
-Dataレジスタ (16bit, R/W, 0x01f0)
--bit0-15:主にPIO転送時のデータ受け渡しに利用
--Error/Featuresとアクセスがかぶっているように見えるかもしれないが、I/Oポートはメモリとは異なり、16bitアクセス=8bitアクセス+次のアドレスの8bitアクセスの256倍、ではないので、きちんと区別される。
--もちろん、16bitアクセス=8bitアクセス+次のアドレスの8bitアクセスの256倍になるI/Oポートも存在するが、それはデバイス側が工夫しているからにすぎない。
-Errorレジスタ (8bit, R, 0x01f1)
--bit0-1:コマンドによって意味が変わる
--bit2:ABRT たいていの場合、ここはアボートビットになる(1のとき、コマンドもしくはパラメータが不正で、エラー終了したことを意味する)
--bit3-7:コマンドによって意味が変わる
-Featuresレジスタ (8bit, W, 0x01f1)
--bit0-7:コマンドによって意味が変わる
-Sector Countレジスタ (8bit, R/W, 0x01f2)
--bit0-7:たいていの場合、ここに連続処理するセクタ数を入れる
--PACKETコマンド時にはInterrupt Reasonレジスタになる (8bit, R)
---bit0:C/D   0のとき、データ転送中もしくはバス開放   1のとき、パケットコマンド要求中もしくはメッセージ転送中
---bit1:I/O   入出力方向表示ビット 0のとき、ホスト→デバイス   1のとき、デバイス→ホスト
---bit2:REL   バスがリリースされていたら1になる
---bit3-7:TAG   オーバーラップトパケットコマンドのときに、コマンド用のタグを格納
-Sector Numberレジスタ (8bit, R/W, 0x01f3)
--bit0-7:たいていは、CHSのSの値か、もしくはLBAのbit0-7
-Cylinder Lowレジスタ (8bit, R/W, 0x01f4)
--bit0-7:たいていは、CHSのCの値のbit0-7か、もしくはLBAのbit8-15
--PACKETコマンド時にはByte Count Lowレジスタになる
---bit0-7:たいていは、バイトカウント値(転送データバイト数)のbit0-7
-Cylinder Highレジスタ (8bit, R/W, 0x01f5)
--bit0-7:たいていは、CHSのCの値のbit8-15か、もしくはLBAのbit16-23
--PACKETコマンド時にはByte Count Highレジスタになる
---bit0-7:たいていは、バイトカウント値(転送データバイト数)のbit8-15
-Device/Headレジスタ (8bit, R/W, 0x01f6)
--bit0-3:たいていは、ヘッド番号(CHSのH)か、もしくはLBAのbit24-27
--bit4:DEV マスターデバイスならここを0に、スレーブデバイスならここを1に
--bit5:廃止されたビット   ATAの場合は、0にすればよい   ATAPIの場合もほとんどは0で問題ないが、古いデバイスのなかには、1にしないと動かないものもある
--bit6:LBA ここを1にするとLBAモードになり、Sector Number、Cylinder Low、Cylinder High、およびDevice/Headのbit0-3がLBAとして解釈される   0だとCHSとして解釈される
--bit7:これも廃止されたビット   ATAの場合は、0にすればよい   ATAPIの場合もほとんどは0で問題ないが、古いデバイスのなかには、1にしないと動かないものもある
-Statusレジスタ (8bit, R, 0x01f7)
--このレジスタをリードすると、ATAデバイスからの割込み要求はクリアされる。クリアせずに読み出したいときは、Alternate Statusレジスタを使う。
--bit7のBSYが1のとき、bit0-6の内容は意味をなさない。
--bit0:ERR   1のときにエラー発生を意味する
--bit1-2:廃止されたビット
--bit3:DRQ   1のときデータ転送要求あり
--bit4-5:コマンドによって意味が変わる
--bit6:DRDY   1のときデバイスはレディ状態
--bit7:BSY   1のときデバイスはビジー状態
--BSYが1になる条件
---ホストがCommandレジスタにコマンドを書き込んだとき(すぐにDRQが1になるようなコマンドでは、BSYが1になるのを省略することもある)
---RESET信号を入れたとき、またはDevice ControlレジスタのSRSTが1になったのを検出したとき
---PIO-Read制御のコマンドで、ブロック転送中にDRQが0クリアされる前
---PIO-Write制御のコマンドで、ブロック転送後にDRQが0クリアされる前
---DMA転送中にセットされることもある
---PACKETコマンド実行中でコマンドパケットを送り終えた後
--BSYが0になる条件
---デバイスがDRQを1にした後
---コマンドが終了した後
---パワーオン、もしくはリセットの作業中だが、DRDYビットの状態を無視して発行できるコマンドが受付可能になったとき
-Commandレジスタ (8bit, W, 0x01f7)
--bit0-7:コマンド番号
-Alternate Statusレジスタ (8bit, R, 0x03f6)
--基本的にStatusレジスタと同じ。このレジスタを読んでもデバイスからのINT要求をクリアしないことだけが違う。
--bit0-7:Statusレジスタと同じ
-Device Controlレジスタ (8bit, W, 0x03f6)
--このレジスタはマスターとスレーブで共有されている
--このレジスタはコマンドのパラメータとしては利用しない
--bit0:常に0を書く
--bit1:nIEN   1のとき、両方のデバイスについてINTをマスク(割り込みが発生しない)
--bit2:SRST   1のとき、両方のデバイスについてソフトウェアリセット信号を送る
---ソフトウェアリセットを実行する際には、このビットを1にして、その後25マイクロ秒以上これを維持して、そしてこのビットを0に戻すらしい。またリセット後(パワーオン後も含む)の20ミリ秒は、デバイスのどのレジスタにもアクセスしてはいけない。
--bit3:廃止されたビット (たいていは0で問題ないが、1にしないと動かないデバイスもある。気になるなら常に1にしてもいいかもしれない)
--bit4-7:リザーブ (0にする)
* コマンドコード表 [#kafa8046]
|code|制御|type(ATA)|type(ATAPI)|command|
|0x00|No-Data|must|opt|NOP|
|0x01-0x02||||不明|
|0x03|No-Data|opt|no|CFA REQUEST EXTENDED ERROR|
|0x04-0x07||||不明|
|0x08|Dev-Reset|opt|must|DEVICE RESET|
|0x09-0x0f||||不明|
|0x10||||廃止 (Obsolete)|
|0x11-0x1f||||廃止 (Retired)|
|0x20|PIO-Read|must|no|READ SECTOR(S)|
|0x21-0x23||||廃止 (Obsolete)|
|0x24-0x2f||||不明|
|0x30|PIO-Write|must|no|WRITE SECTOR(S)|
|0x31-0x33||||廃止 (Obsolete)|
|0x34-0x37||||不明|
|0x38|PIO-Write|opt|no|CFA WRITE SECTORS WITHOUT ERACE|
|0x39-0x3b||||不明|
|0x3c||||廃止 (Obsolete)|
|0x3d-0x3f||||不明|
|0x40|No-Data|must|no|READ VERIFY SECTOR(S)|
|0x41||||廃止 (Obsolete)|
|0x42-0x4f||||不明|
|0x50||||廃止 (Obsolete)|
|0x51-0x6f||||不明|
|0x70|No-Data|must|no|SEEK|
|0x71-0x7f||||廃止 (Retired)|
|0x80-0x86||||ベンダ定義|
|0x87|PIO-Read|opt|no|CFA TRANSLATE SECTOR (CFA以外ではベンダ定義)|
|0x88-0x8f||||ベンダ定義|
|0x90|Diagnostic|must|must|EXECUTE DEVICE DIAGNOSTIC|
|0x91|No-Data|must|no|INITIALIZE DEVICE PARAMETERS|
|0x92|PIO-Write|opt|no|DOWNLOAD MICROCODE|
|0x93||||不明|
|0x94-0x99||||廃止 (Retired)|
|0x9a||||ベンダ定義|
|0x9b-0x9f||||不明|
|0xa0|Packet|no|must|PACKET|
|0xa1|PIO-Read|no|must|IDENTIFY PACKET DEVICE|
|0xa2|Packet|no|opt|SERVICE|
|0xa3-0xbf||||不明|
|0xc0|No-Data|opt|no|CFA ERACE SECTORS (CFA以外ではベンダ定義)|
|0xc1-0xc3||||ベンダ定義|
|0xc4|PIO-Read|must|no|READ MULTIPLE|
|0xc5|PIO-Write|must|no|WRITE MULTIPLE|
|0xc6|No-Data|must|no|SET MULTIPLE MODE|
|0xc7|Queued-DMA|opt|no|READ DMA QUEUED|
|0xc8|DMA|must|no|READ DMA|
|0xc9||||廃止 (Obsolete)|
|0xca|DMA|must|no|WRITE DMA|
|0xcb||||廃止 (Obsolete)|
|0xcc|Queued-DMA|opt|no|WRITE DMA QUEUED|
|0xcd|PIO-Write|opt|no|CFA WRITE MULTIPLE WITHOUT ERACE|
|0xce-0xd9||||不明|
|0xda|No-Data|opt|opt|GET MEDIA STATUS|
|0xdb-0xdd||||廃止 (Retired)|
|0xde|No-Data|opt|opt|MEDIA LOCK|
|0xdf|No-Data|opt|opt|MEDIA UNLOCK|
|0xe0|No-Data|must|must|STANDBY IMMEDIATE|
|0xe1|No-Data|must|msut|IDLE IMMEDIATE|
|0xe2|No-Data|must|opt|STANDBY|
|0xe3|No-Data|must|opt|IDLE|
|0xe4|PIO-Read|opt|no|READ BUFFER|
|0xe5|No-Data|must|must|CHECK POWER MODE|
|0xe6|No-Data|must|must|SLEEP|
|0xe7|No-Data|must|must|FLUSH CACHE|
|0xe8|PIO-Write|opt|no|WRITE BUFFER|
|0xe9||||廃止 (Retired)|
|0xea-0xeb||||不明|
|0xec|PIO-Read|must|no|IDENTIFY DEVICE|
|0xed|No-Data|opt|opt|MEDIA EJECT|
|0xee||||廃止 (Obsolete)|
|0xef|No-Data|must|must|SET FEATURES|
|0xf0||||ベンダ定義|
|0xf1|PIO-Write|opt|opt|SECURITY SET PASSWORD|
|0xf2|PIO-Write|opt|opt|SECURITY UNLOCK|
|0xf3|No-Data|opt|opt|SECURITY ERACE PREPARE|
|0xf4|PIO-Write|opt|opt|SECURITY ERACE UNIT|
|0xf5|No-Data|opt|opt|SECURITY FREEZE|
|0xf6|PIO-Write|opt|opt|SECURITY DISABLE PASSWORD|
|0xf7||||不明|
|0xf8|No-Data|opt|no|READ NATIVE MAX ADDRESS|
|0xf9|No-Data|opt|no|SET MAX ADDRESS|
|0xfa-0xff||||ベンダ定義|
-制御について
--No-Data:データ転送のない命令系
--PIO-Read:PIO読み込みデータ転送を伴う命令系
--PIO-Write:PIO書き込みデータ転送を伴う命令系
--DMA:DMA転送を伴う命令系
--Queued-DMA:待ち行列付きのDMA転送を伴う命令系
--Dev-Reset:デバイスリセットプロトコル
--Diagnostic:Device Diagnosticプロトコル
-typeについて
--must:必ずサポートされているコマンド
--opt:オプションでサポートされているコマンド
--no:サポートされないコマンド

* データ転送のない命令系の発行のしかた (No-Data) [#r2f95aad]
-(NOPとSLEEPもこれに分類しているが、少し違うところがあるらしい。でもどこが違うのかがまだはっきとは分かっていない。すみません。)
-デバイスセレクションプロトコルを実行。
--まず、StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0 && DRQ == 0になるのを待つ。
--Device/HeadレジスタのDEVにデバイス番号をセットして、400ns以上待つ。
--もう一度、StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0 && DRQ == 0になるのを待つ。
-レジスタにパラメータをセット。書く順序は決まっていないが、Commandレジスタにコマンド番号を書くのは最後にしなければいけないので、まだ書かない。
-Commandレジスタにコマンド番号を書き、400ns以上待つ。
--割り込みを利用する場合は、400nsのwaitは必要なく、割り込み発生を待てばいい。
-ポーリングの場合、StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0を待つ。
-割り込みを利用している場合は、割り込みを検出したらここから再開:
-Statusレジスタを読み込んで正常終了したかどうかとか、そういうことをチェックする(Alternate Statusレジスタではだめ)。
-おしまい。

* PIO読み込みデータ転送を伴う命令系の発行のしかた (PIO-Read) [#ab4d0fbe]
-デバイスセレクションプロトコルを実行。
--No-Dataのところの説明を参照。
-レジスタにパラメータをセット。書く順序は決まっていないが、Commandレジスタにコマンド番号を書くのは最後にしなければいけないので、まだ書かない。
-Commandレジスタにコマンド番号を書く。
-ラベル1:
-割り込みを利用する場合は、割り込み発生を待てばいい。
--割り込みが発生したらラベル2へ(以下はポーリングの場合)。
-400ns以上待つ。
-ポーリングの場合、StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0を待つ。
-Alternate Statusレジスタを空読みする。
-ラベル2:
-Statusレジスタを読む。
--ここでエラーを検出したら、エラー終了。
-もしDRQが1になっていなかったら、ラベル2に戻る(割り込みを利用している場合は、このチェックは不要)。
--本来はポーリングでもこのチェックは不要なはずだけど、まあ念のためってことで。
-1セクタ分を転送。
--Dataレジスタをリードして、メモリに書き込む。これを1セクタ分だけ繰り返す。
--Dataレジスタのリードに当たって、いちいちStatusなどをチェックする必要はない。
-もしSector Countレジスタが2以上だったなどで、複数のセクタを処理する場合は、ラベル1に戻る。全部のセクタを処理しおわったら、下に進む。
-Alternate Statusレジスタを空読みする。
-Statusレジスタを読む。
-おしまい。

* PIO書き込みデータ転送を伴う命令系の発行のしかた (PIO-Write) [#ld03cd59]
-デバイスセレクションプロトコルを実行。
--No-Dataのところの説明を参照。
-レジスタにパラメータをセット。書く順序は決まっていないが、Commandレジスタにコマンド番号を書くのは最後にしなければいけないので、まだ書かない。
-Commandレジスタにコマンド番号を書いて、400ns以上待つ。
-ラベル1:
-StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0を待つ。
--割り込みを利用する場合であっても、このポーリングをやる(デバイスが壊れていなければ、そう待たさせることはない)。
--なおもしこの時点でエラーが検出された場合、割り込みが有効になっていれば割り込みが発生する。だから割り込み利用の場合はややこしいことが起きないように、PICのほうで割り込み禁止にしておくとか、もしくはエラー割り込みを拾ってポーリングの際にはAlternate Statusレジスタのリードを使うとか、そういう工夫をすること。
-エラーが起きていないかどうかをチェック。
--割り込みでエラーを検出した場合は、Statusレジスタリードしておしまい。
--ポーリングでエラーを検出した場合は、Alternate Statusレジスタを空読みして、それからStatusレジスタをリードして、それでおしまい。
-ラベル2:
-ここでStatusレジスタかAlternate Statusレジスタをリードして、もしDRQが1になっていなかったら、ラベル1に戻る。
--まあ念のためってことで。
-1セクタ分を転送。
--メモリを読み込んで、Dataレジスタにライトする。これを1セクタ分だけ繰り返す。
--Dataレジスタのライトに当たって、いちいちStatusなどをチェックする必要はない。
-もしこれが処理すべき最後のセクタならラベル4へ(以下はSector Countが2以上などで、後続するセクタ転送が必要な場合)。
-割り込みを使う場合は、ここから先はすっとばす。割り込みが来たらラベル3へ(以下はポーリングの場合)。
-400ns以上待つ。
-StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0を待つ。
-Alternate Statusレジスタを空読みする。
-ラベル3:
-Statusレジスタを読む。
--ここでエラーを検出したら、エラー終了。
-ラベル2へ。
-ラベル4:
-割り込みを使う場合は、ここから先はすっとばす。割り込みが来たらラベル5へ(以下はポーリングの場合)。
-400ns以上待つ。
-StatusレジスタかAlternate Statusレジスタをリードして、BSY == 0を待つ。
-Alternate Statusレジスタを空読みする。
-ラベル5:
-Statusレジスタを読む。
-おしまい。

* DMAデータ転送を伴う命令系の発行のしかた (DMA) [#g84cd96c]

* ATAPIのパケットコマンドの発行のしかた (Packet) [#kc24b4c6]

* 代表的なコマンドのパラメータ説明 [#a8d1d885]
-0x20:READ SECTOR(S) (セクタのリード:PIO-read)
-0x30:WRITE SECTOR(S) (セクタのライト:PIO-Write)
--この2つのコマンドのパラメータやStatusのbit割り振りは同じなので、まとめて説明。
--どちらのコマンドもStatusのDRDYが1になってないと実行できない。
--Featuresレジスタは利用しない。
--Sector Countレジスタに連続処理するセクタ数(1つなら1)。
--Sector Numberレジスタ、Cylinder Lowレジスタ、Cylinder HighレジスタにLBAのbit0-23、もしくはCHSのSとC。
--Device/HeadレジスタにCHSのHかもしくはLBAの最上位、そしてデバイス番号とLBAフラグをセット。
--(コマンド正常終了時)
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (正常終了時は0)
--そのほかのレジスタは、Device/HeadのDEVビットが保存されることを除いては、すべて未定義。
--(コマンド異常終了時)
--Statusのbit0のERRビットが必ず1になる。
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (デバイスフォルトが発生したら1)
--Errorレジスタの状態
---bit0:廃止 (このビットの意味はないのでチェックしなくてよい)
---bit1:NM ノーメディア (1ならメディアがない)
---bit2:ABRT アボート (アボート終了したら1)
---bit3:MCR メディアチェンジリクエスト (1で発生。イジェクトボタンを押されて、デバイス取り出し要求があるなどの状態のエラー。GET MEDIA STATUSを実行すると、このエラーは収まる)
---bit4:IDNF セクタが見付からない (指定したセクタがアクセス範囲外だったり、もしくはCHSの変換パラメータ設定ミスだと1になる)
---bit5:MC メディアチェンジ (1で発生。前回アクセス時からメディアの交換があったのに、GET MEDIA STATUSを実行していないので、ソフトウェアが交換を検出していないかもしれない。それを通知するためのエラー。GET MEDIA STATUSを実行すると、このエラーは収まる)
---bit6:UNC/WP リードの場合、アンコレクタブルエラー(1で発生。エラー訂正に失敗したことを意味する) ライトの場合、ライトプロテクトエラー(1で発生)
---bit7:未定義
-0x91:INITIALIZE DEVICE PARAMETERS (CHS変換のためのパラメータ設定:No-Data)
--CHS変換をサポートしているデバイスで使用可能。
--StatusのDRDYが1になっていなくても実行可能。
--Sector Countレジスタに最大セクタ番号。
--Device/Headレジスタのbit0-3に最大ヘッド番号、bit4にはデバイス番号をセット。
--Featuresレジスタ、Sector Numberレジスタ、Cylinder Lowレジスタ、Cylinder Highレジスタは参照しないので、どんな値でも構わない。
--(コマンド正常終了時)
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (正常終了時は0)
--そのほかのレジスタは、Device/HeadのDEVビットが保存されることを除いては、すべて未定義。
--(コマンド異常終了時)
--Statusのbit0のERRビットが必ず1になる。
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (デバイスフォルトが発生したら1)
--Errorレジスタの状態
---bit0-1:未定義
---bit2:ABRT アボート (アボート終了したら1)
---bit3-7:未定義
-0xda:GET MEDIA STATUS (メディア状態の取得:No-Data)
--Removable Media featureセットか、もしくはRemovable Media Status Notification featureセットをサポートしているデバイスで使用可能。
--StatusのDRDYが1になっているときにのみ実行可能。
--Device/Headレジスタのbit4にはデバイス番号をセット。bit0-3は参照しないのでなんでもよし。
--Featuresレジスタ、Sector Countレジスタ、Sector Numberレジスタ、Cylinder Lowレジスタ、Cylinder Highレジスタは参照しないので、どんな値でも構わない。
--(コマンド正常終了時)
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (正常終了時は0)
--そのほかのレジスタは、Device/HeadのDEVビットが保存されることを除いては、すべて未定義。
--(コマンド異常終了時)
--Statusのbit0のERRビットが必ず1になる。
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (デバイスフォルトが発生したら1)
--Errorレジスタの状態
---bit0:廃止 (このビットの意味はないのでチェックしなくてよい)
---bit1:NM ノーメディア (1ならメディアがない)
---bit2:ABRT アボート (アボート終了したら1)
---bit3:MCR メディアチェンジリクエスト (1で発生。イジェクトボタンを押されて、デバイス取り出し要求があるなどの状態のエラー。GET MEDIA STATUSが実行されたので、次からはこのエラーは出ない。また新たにイジェクトボタンが押し直されたら発生するが)
---bit4:未定義
---bit5:MC メディアチェンジ (1で発生。前回アクセス時からメディアの交換があったのに、GET MEDIA STATUSを実行していないので、ソフトウェアが交換を検出していないかもしれない。それを通知するためのエラー。GET MEDIA STATUSを実行されたので。次からはこのエラーは出ない。また新たにメディアが交換されたら発生するが)
---bit6:WP ライトの場合、ライトプロテクトエラー(1で発生)
---bit7:未定義
-0xe1:IDLE IMMEDIATE (デバイスを直ちにアイドルモードへ移行:No-Data)
--Power Management featureセットをサポートしているデバイスで使用可能。
--電源管理はモードが色々あってややこしいので下記参照のこと。
--StatusのDRDYが1になっているときにのみ実行可能。
--Device/Headレジスタのbit4にはデバイス番号をセット。bit0-3は参照しないのでなんでもよし。
--Featuresレジスタ、Sector Countレジスタ、Sector Numberレジスタ、Cylinder Lowレジスタ、Cylinder Highレジスタは参照しないので、どんな値でも構わない。
--(コマンド正常終了時)
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (正常終了時は0)
--そのほかのレジスタは、Device/HeadのDEVビットが保存されることを除いては、すべて未定義。
--(コマンド異常終了時)
--Statusのbit0のERRビットが必ず1になる。
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (デバイスフォルトが発生したら1)
--Errorレジスタの状態
---bit0-1:未定義
---bit2:ABRT アボート (アボート終了したら1)
---bit3-7:未定義
-0xe3:IDLE (デバイスを直ちにアイドルモードへ移行:No-Data)
--Power Management featureセットをサポートしているデバイスで使用可能。
--電源管理はモードが色々あってややこしいので下記参照のこと。
--StatusのDRDYが1になっているときにのみ実行可能。
--Device/Headレジスタのbit4にはデバイス番号をセット。bit0-3は参照しないのでなんでもよし。
--Sector Countレジスタには、スタンバイタイマー値をセット。
---この時間だけ待ってみて、その間にアクセスがなければ自動的にIDLEになります。
---0x00:タイマー無効
---0x01~0xf0:値x5[秒] (5秒~20分)
---0xf1~0xfb:(値-0xf0)x30[分] (30分~5時間半)
---0xfc:21[秒]
---0xfd:8時間~12時間(ベンダ定義)
---0xfe:リザーブ
---0xff:21分15秒
--Featuresレジスタ、Sector Numberレジスタ、Cylinder Lowレジスタ、Cylinder Highレジスタは参照しないので、どんな値でも構わない。
--(コマンド正常終了時)
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (正常終了時は0)
--そのほかのレジスタは、Device/HeadのDEVビットが保存されることを除いては、すべて未定義。
--(コマンド異常終了時)
--Statusのbit0のERRビットが必ず1になる。
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (デバイスフォルトが発生したら1)
--Errorレジスタの状態
---bit0-1:未定義
---bit2:ABRT アボート (アボート終了したら1)
---bit3-7:未定義
-0xec:IDENTIFY DEVICE (デバイス情報取得:PIO-Read)
--StatusのDRDYが1になっているときにのみ実行可能。
--Device/Headレジスタのbit4にはデバイス番号をセット。bit0-3は参照しないのでなんでもよし。
--Featuresレジスタ、Sector Countレジスタ、Sector Numberレジスタ、Cylinder Lowレジスタ、Cylinder Highレジスタは参照しないので、どんな値でも構わない。
--得られる512バイトの情報については、下記参照。
--(コマンド正常終了時)
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (正常終了時は0)
--そのほかのレジスタは、Device/HeadのDEVビットが保存されることを除いては、すべて未定義。
--(コマンド異常終了時)
--Statusのbit0のERRビットが必ず1になる。
--Statusのbit4-5の状態:
---bit4:未定義
---bit5:DF デバイスフォルト (デバイスフォルトが発生したら1)
--Errorレジスタの状態
---bit0-1:未定義
---bit2:ABRT アボート (アボート終了したら1)
---bit3-7:未定義
-(以下まだ書き途中)
-0xef:SET FEATURES (デバイスの各種設定:No-Data)

* ATAの電源管理 [#f923141c]
-4つのモードがある
--ACTIVE:すぐにコマンドが受け付けられる状態で一番電気を食う。
--IDLE:全てのコマンドを受け付けられるが、ACTIVEよりは反応が悪い可能性がある。しかし、STANDBYほどはひどくないし、電気消費もちょっと押さえてくれる。ACTIVEのままにするのはよくないと、たいていの資料には書いてある。コマンドを実行するたびにIDLEコマンドを実行するといいだろう(一般のコマンドを実行するとモードがACTIVEに変わってしまうため)。
--STANDBY:全てのコマンドを受け付けられるが、コマンドを実行するまでに最大30秒の遅延がありうる。その代わり結構節約してくれると思う。
--SLEEP:一番電気を食わない。一度この状態に入ると、DEVICE RESETコマンド以外を受け付けない。さらにDEVICE RESETを実行するまでに最大30秒の遅延がありうる。
-普通のデバイスはコマンド実行後にずっとACTIVEのままでいるが、一部のデバイスは自主的にIDLEやSTANDBYになるものもあるらしい。ATA規格ではそういう自主的なモード遷移も一応認めているようだ。しかし当てにはできないので、ソフトウェアでちゃんと制御するのが望ましい。

* IDENTIFY DEVICEで得られる情報 [#hc625802]
-ここではアドレスをバイト単位で書いていますが、データは16ビット単位でやり取りされているため、文字列などはIA-32からするとやや変則的です。複数のワードにまたがるデータは一度適当な機種で実験してみて、観察するといいでしょう。
|アドレス(ビット)|固定/可変|意味|
|0x000 (bit6)|固定|ここが1だと非リムーバブルデバイス|
|0x000 (bit7)|固定|ここが1だとリムーバブルデバイス|
|0x002-0x003|可変|デフォルトモードでの論理シリンダ数|
|0x006-0x007|固定|デフォルトモードでの論理ヘッド数|
|0x00c-0x00d|固定|デフォルトモードでの論理セクタ数|
|0x014-0x027|固定|シリアル番号(20文字のASCIIコード)|
|0x02e-0x035|固定|ファームウェアのリビジョン(8文字のASCIIコード)|
|0x036-0x05d|固定|デバイスの型番(40文字のASCIIコード)|
|0x05e|固定|R/W MULIPLEコマンドで何セクタごとに割り込みを発生させるか(デフォルト)|
|0x063 (bit0-1)|固定|常に1|
|0x063 (bit2)|固定|ここが1だとIORDYは無効|
|0x063 (bit3)|固定|ここが1だとIORDYをサポート|
|0x063 (bit5)|固定|ここが1だと標準のスタンバイタイマーサポート|
|0x064 (bit0)|固定|ここが1だとスタンバイタイマーの値を最小値として扱う|
|0x06a (bit0)|可変|ここが1だとアドレス0x06c~0x075は有効 (現在のCHS)|
|0x06a (bit1)|固定|ここが1だとアドレス0x080~0x08dは有効 (DMA/PIO情報)|
|0x06a (bit2)|固定|ここが1だとアドレス0x0b0~0x0b1は有効 (UDMA情報)|
|0x06c-0x06d|可変|現在のモードでの論理シリンダ数|
|0x06e-0x06f|可変|現在のモードでの論理ヘッド数|
|0x070-0x071|可変|現在のモードでの論理セクタ数|
|0x072-0x075|可変|現在のモードでの全セクタ数|
|0x076|可変|R/W MULIPLEコマンドで何セクタごとに割り込みを発生させるか (現在のモード)|
|0x077 (bit0)|可変|ここが1だとSET MULTIPLEが有効|
//|0x077 (bit1-7)||リザーブ|
|0x078-0x07b|固定|LBAモードでアクセス可能な全セクタ数|
-(以下まだ書き途中)
-(補足)
--0x078-0x07bの「LBAモードでアクセス可能な全セクタ数」というのは、アクセス可能なLBAの最大値を意味するのではなく、本当の意味での全セクタ数である。LBAは0から指定できるので、ここの値から1を減じた値が、指定できるLBAの最大値となる。
---おそらく他の「セクタ数」についても同様であろう。

* その他の補足 [#j6cfa782]
-一部のデバイスは、リセット後にIDENTIFY DEVICEを実行して、さらにINITIALIZE DEVICE PARAMETERSを実行しないとREADやWRITEができないらしいです(このデバイスはLBAモードしか使わないとしても、INITIALIZE DEVICE PARAMETERSで設定しないとだめらしい。変なの~)
--でもまあ僕たちの場合はBIOSがそういうことをやってくれた後だと想定してもいいと思うので、この辺を気にする必要はないかもしれません。

* こめんと欄 [#i1ffe9ba]
-sector number registerについてよく分からないので詳しく説明願えないでしょうか -- [[baramon]] SIZE(10){2004-01-19 (月) 19:12:17}
-ええとLBAのbit0-7という説明では分かりませんか?Cylinder Lowなどが分かるのならこの説明で十分だと思うのですが・・・。 -- [[K]] SIZE(10){2004-01-25 (日) 03:17:50}
-セクタサイズは常に512バイトということでいいんでしょうかね? -- [[I.Tak.]] SIZE(10){2004-02-12 (木) 16:16:51}
-僕の知る範囲では、ATAではそういうことになっているようです。ATAPIだと他のセクタサイズもあります。 -- [[K]] SIZE(10){2004-02-13 (金) 16:17:30}
-sector number registerについてよく分からないので詳しく説明願えないでしょうか -- ''baramon'' SIZE(10){2004-01-19 (月) 19:12:17}
-ええとLBAのbit0-7という説明では分かりませんか?Cylinder Lowなどが分かるのならこの説明で十分だと思うのですが・・・。 -- ''K'' SIZE(10){2004-01-25 (日) 03:17:50}
-セクタサイズは常に512バイトということでいいんでしょうかね? -- ''I.Tak.'' SIZE(10){2004-02-12 (木) 16:16:51}
-僕の知る範囲では、ATAではそういうことになっているようです。ATAPIだと他のセクタサイズもあります。 -- ''K'' SIZE(10){2004-02-13 (金) 16:17:30}
-20=READ W/ RETRYと30=WRITE W/ RETRYのコマンドについて説明していただけないでしょうか -- ''kikeo'' SIZE(10){2005-01-27 (木) 11:40:00}
-20=READ W/ RETRYと30=WRITE W/ RETRYのコマンドについて説明していただけないでしょうか -- ''kikeo'' SIZE(10){2005-01-27 (木) 11:41:10}
-READ(WRITE) SECTORSとREAD(WRITE) MULTIPLEの違いを教えてください。 -- ''GYZ'' SIZE(10){2005-01-27 (木) 13:15:02}
-kikeoさんへ:説明したいのですが、忙しくてしばらくは無理です。GYZさんへ:僕にも違いが良く分かりません。コマンド20/30についてはだいたい分かっているのですが、他のコマンドはコマンド名がなんとか分かった程度でしかないのです。どうもすみません。 -- [[K]] SIZE(10){2005-01-27 (木) 13:30:52}
-あれ?20/30のコマンドについては、上の説明では足りませんか?>kikeoさん -- [[K]] SIZE(10){2005-01-27 (木) 13:34:38}
-非MULTIPLEでは、指定した全セクタの処理が終わるまで、割り込みが発生しませんが、MULTIPLEでは1セクタごとに(もしくは2セクタごと、4セクタごとなど、設定で変更できますが)、割り込みが来るようです。そういう中間報告の有無が違いなのかもしれません。ただの想像ですので、間違っている可能性大ですが。 -- [[K]] SIZE(10){2005-01-27 (木) 13:41:25}
-kikeoさんへ:説明したいのですが、忙しくてしばらくは無理です。GYZさんへ:僕にも違いが良く分かりません。コマンド20/30についてはだいたい分かっているのですが、他のコマンドはコマンド名がなんとか分かった程度でしかないのです。どうもすみません。 -- ''K'' SIZE(10){2005-01-27 (木) 13:30:52}
-あれ?20/30のコマンドについては、上の説明では足りませんか?>kikeoさん -- ''K'' SIZE(10){2005-01-27 (木) 13:34:38}
-非MULTIPLEでは、指定した全セクタの処理が終わるまで、割り込みが発生しませんが、MULTIPLEでは1セクタごとに(もしくは2セクタごと、4セクタごとなど、設定で変更できますが)、割り込みが来るようです。そういう中間報告の有無が違いなのかもしれません。ただの想像ですので、間違っている可能性大ですが。 -- ''K'' SIZE(10){2005-01-27 (木) 13:41:25}
-Read DMAとWrite DMAとは転送モードが指定しているのとしていないの違いだけですか? -- ''kikeo'' SIZE(10){2005-01-27 (木) 16:15:03}
-上記のコマンド表を見れば分かりますが、DMA系命令はプロトコルもPIO系命令とは違いますよ。 -- [[K]] SIZE(10){2005-01-27 (木) 16:58:46}
-上記のコマンド表を見れば分かりますが、DMA系命令はプロトコルもPIO系命令とは違いますよ。 -- ''K'' SIZE(10){2005-01-27 (木) 16:58:46}
-すみません、もう少し勉強してみます。ありがとうございました。 -- ''kikeo'' SIZE(10){2005-01-27 (木) 17:42:12}
-割り込みの有無等、細かい点で差異があるのですね。Web上に情報が少なくて困っていたところなんで、非常に参考になります。ありがとうございました。 -- ''GYZ'' SIZE(10){2005-01-27 (木) 19:42:43}
-READ MULTIPLEやWRITE MULTIPLEコマンドはSET MULTIPLE MODEコマンドで指定したセクタ数(2~128の間で2^nの値で指定)だけまとめて読み書きします。指定セクタ分読み書きした後に割り込みが発生する以外に違いは無いようですよ。 -- ''ZwergSpitz'' SIZE(10){2005-01-27 (木) 20:09:32}
-読み込む単位が違うんですね。ソースと照らし合わせて、ようやく納得出来ました。ありがとうございます! -- ''GYZ'' SIZE(10){2005-01-28 (金) 17:47:11}
-WRITE DMAで割り込みを利用したいのですが詳しい説明とかサンプルのあるサイトとかご存知ではないでしょうか? -- ''Nhat'' SIZE(10){2006-06-02 (金) 23:10:15}

//#comment

[Reload]   [New] [Edit] [Diff] [Upload]   [Front page] [List of pages] [Search] [Recent changes] [Backup]   [RSS of recent changes]