原作: &a.uhclem; DMA転送の発生と処理の手順の例をあげてみましょう.
この例では, フロッピーディスクコントローラ (FDC)が
ディスケットから1バイト読み込んで, DMAを使って,メモリの0x00123456番地に
格納したいとします. 処理は, FDCが, DRQ2信号(DMAチャンネル2に
対するDRQ線)を有効にして
DMAコントローラに要求を伝えることで開始されます.
DMAコントローラはDRQ2シグナルが有効になったことを記録します.
するとDMAコントローラはDMAチャネル2がプログラムされ, マスクが
かかっていない(有効になっている)ことを確認します.
同様に, DMAコントローラは, 他のDMAチャネルがアクティブまたは
アクティブになろうとしていないこと, そしてより高い優先度を持って
いないことを確認します.
一旦これらのチェックが完了すると, DMACはDMACがバスを使うために
バスを開放するようにCPUに要求します.
DMACはCPUにHRQ信号を送ってバスを要求します.
CPUはHRQ信号を検出し, 現在の指示の実行を完了します.
一旦プロセッサがバスを開放することができる状態になると, 解放を
行います.
通常は CPU により駆動される信号 (-MEMR, -MEMW, -IOR, -IOW, その他)を
すべてハイインピーダンス (ハイともローとも指定しない)状態にした後,
CPUは HLDA信号を有効にして DMAコントローラにバスを明け渡したことを
伝えます.
プロセッサによっては, CPUはバスを使用しないいくつかの
命令を追加して実行することもできますが,
しかし,プロセッサの内部キャッシュやパイプライン以外のメモリから
何か読み出すといった指示に到達したら結局CPUは待たなくてはなりません.
ここで,DMACが バスを「託される」と,
DMACはその -MEMR, -MEMW, -IOR, -IOW 出力信号をアクティブにし,
DMACから出力されるアドレスは 0x3456にセットされます.これは
転送しようとする特定のメモリ番地をバイトで指示するのに使われます.
するとDMACはDMA転送をリクエストしたデバイスに転送が始まることを
知らせます.これは -DACK信号をアクティブにすることで行われます.
フロッピーディスクコントローラの場合は, -DACK2を
アクティブにすることで行われます.
バスのデータ線に転送されるバイトにを出力することについては
フロッピーディスクコントローラが責任をもつことになります.
もし,フロッピーディスクコントローラがバス上にバイトデータを
出力するのに余計な時間を必要としなければ
(もし周辺装置がもっと時間を必要とする場合には, READY信号を
経由してDMACに通知します), DMAは 1 DMAクロック待ち,
メモリにバス上のバイトデータを格納するために
-MEMW および -IOR 信号を解除します. そして
FDCはバイトデータが転送されたことを認識します.
DMAサイクルは1度に1バイトしか転送しないので,
FDCはDRQ2信号を止めて, DMACに転送が終了したことを知らせます.
DMACは-DACK2信号を解除して, FDCはバス上へのデータ出力を
停止しなくてはならないことを知らせます.
次にDMACは他のDMAチャネルのいずれかに要求がきていないか
チェックを行います. もしどのチャネルのDRQも有効になっていなければ,
DMAコントローラは処理を完了して, -MEMR, -MEMW, -IOR, -IOW および
アドレス信号をハイインピーダンス状態にします.
最後に, DMAはHRQ信号を解除します. CPUはこれを見ると,HOLDA信号を
解除します. そしてCPUは自らの -MEMR, -MEMW, -IOR, -IOW 信号および
アドレス線を有効にし, 命令の実行やメインメモリや周辺機器へのアクセスを
再開します.
典型的なフロッピーディスクの1セクタについては, 上記のプロセスが
それぞれのバイトについて1回行われ, 全部で512回繰り返されます.
1バイト転送される毎に,DMAC内のアドレスレジスタはインクリメントされ,
同じくDMAC内にある, 何バイト転送すればよいかを示すカウンタが
デクリメントされます.
カウンタが0になると, DMAはEOP信号を送ります. この信号は
カウンタが0であり, DMAコントローラがCPUによって再び
プログラムされるまで, これ以上データは転送されないことを
示すものです.
このイベントはターミナルカウント(TC)とも呼ばれます.
EOP信号は1本しかありません. そして, 一度にアクティブにできる
DMAチャネルは一本だけなので, 現在アクティブであるDMAチャネルこそが,
たった今処理を終了したDMAチャネルだと言うことができます.
もし, バッファの転送が完了した時に周辺機器から割り込みを発生させたい
とき, 周辺機器は -DACKn信号およびEOP信号の両方が同時に発信されたか
どうかをテストします. その場合, DMACはCPUの介在がなければ
これ以上はその周辺機器についての情報を転送しません.
その後で, 周辺機器はプロセッサに割り込みを生じさせるために,
何らかの割り込み信号を発生させることができます. PCアーキテクチャ
においては, DMAチップ自身が割り込みを生じさせることはできません.
周辺機器とそれに関連するハードウェアが割り込みを生成する責任を
持ちます. また, DMAを使用する周辺機器が割り込みを使用しない
可能性もあります.
DMACが要求を出したときにはCPUは常にバスをDMACに開放しますが,
この動作は, DMACがアクティブになった時にプロセッサが命令を実行するのに
かかる時間がわずかに変化することを除いては, アプリケーション,
オペレーティングシステムの両方からはわからないということを
理解することが重要です.
そのため, プロセッサが確かにDMA転送が完了したことを知るためには,
周辺装置やDMAチップ中のレジスタを調べたり,周辺装置からの割り込みを
受け取る必要があります.
これまで述べたのとは異なり, DMACはアドレス線を 0x0123456 にセットする
代わりに 0x3456 だけをセットすることにあなたは気づいたかも
しれません. この理由について少し説明します.
オリジナルのIBM PCがデザインされた時, IBMは, DMACと割込み制御チップの
両方を, 8085(8ビットプロセッサで, 16ビットのアドレス空間(64k)を持つ)と
組み合わせて使うように設計されたチップを使うことを選びました.
IBM PCが64k以上のメモリをサポートしていたため,
DMACが64kを越えるメモリ番地に読み込み又は書き込みを行うために
変更を行う必要が生じました.
この問題を解決するためにIBMが行ったのは, それぞれのDMAチャネルに,
読み込み元または書き込み先のアドレスの上位ビットを保持するための
外部的なラッチを追加することでした.
DMAチャネルがアクティブな時はいつでも,
このラッチの内容はアドレスバスに書かれて, そのチャネルのDMA操作が
終了するまでそこに保持されます.
IBMはこれらのラッチを「ページレジスタ」と呼んでいます.
そのため上記に示した例では, DMACはアドレスの0x3456の部分をバス上に
置き, DMAチャネル2に対するページレジスタは, 0x0012xxxxをバス上に
置きます. これらの2つの値が組み合わされてアクセスされるメモリ中の完全な
アドレスを形成します.
ページレジスタのラッチはDMAチップとは独立であるので,
読み込まれる又は書き込まれるメモリ領域は, 64kの物理的境界を
またいではなりません. 例えば, もし
DMACがメモリの0xffff番地をアクセスした場合, データの転送後,
DMACはアドレスレジスタをインクリメントし, 0x0000番地にある次のバイトを
アクセスします. 0x10000番地ではありません.
これはおそらく意図されたものとは異なっているでしょう.
8237 DMA はいくつかのモードで動作します. 主なモードは,
以下のとおりです.
プログラムされるDMAチャネルは, 通常, 設定を行う前に
「マスクする」べきです.
これはハードウェアが予期せずそのチャンネルに対してDRQを有効に
した場合, たとえ全てのパラメータが
満たされてない場合や更新されていない場合でも, DMACは
それに応答してしまう可能性があるからです.
マスクを行ってから,ホストは転送の方向(メモリからI/O,
もしくはI/Oからメモリ)と, 転送に使用するDMA操作のモード
(シングル, ブロック, デマンド, カスケードなど)を設定し, 最後に
アドレスや転送の長さを設定します.
設定される長さはDMACに転送させたい量よりも1少なくなります.
アドレスや転送長のLSBとMSBは同じ8ビットI/Oポートに書き込まれます.
そのためDMACが最初のバイトをLSBとして, 2番目のバイトをMSBとして
受け取ることを保証するために, 最初に別のポートに書き込みを行なって
LSBとMSBの判別を行なうフリップフロップをクリアしておく必要があります.
そして,DMAのページレジスタを更新します. これはDMACの外部にあり
I/Oポートの別のセットを通してアクセスされます.
すべての設定ができると, DMAチャネルはマスクを解除することができます.
そのDMAチャネルは「準備ができた」とみなされ, そのチャンネルのDRQが
有効になると応答します.
8237のプログラミングの正確な詳細については,
ハードウェアデータブックを参照してください.
PCシステムにおけるI/Oマップについても参照する必要があるでしょう.
このマップにはDMAおよびページレジスタのポートがどこに位置するのかを
書いてあります. 以下に完全なポートのマップテーブルを示します.
IBM-PCとPC/ATに基づくすべてのシステムでは, 同じI/Oポートに配置された
DMAハードウェアを持っています. その完全なリストを以下に示します.
DMAコントローラ2に割り当てられたポートは, AT以外のデザインでは
未定義になっています.
DMA アドレス および カウントレジスタ
DMA アドレス および カウントレジスタ
Intel 82374 EISA System Component (ESC)は1996年の初めに発表されました. この中
には機能的には8237のスーパーセットであり, 1つのパッケージの中にその他の
PC互換機のコアとなる周辺コンポーネントをも含んだDMAコントローラも含まれています.
このチップはEISAとPCI両方のプラットホームをターゲットにしたものであり,
scatter-gather I/O やリングバッファを始めとして, システムDMAをして32ビットの
アドレス空間全体に直接アクセスする能力も提供しています.
これらの機能を使用する場合でも, 過去16年間のPC互換機で利用されてきた
同等機能を提供するコードも含めておく必要があります. 互換性の問題から, 82374の
レジスタの一部は, 従来の8237のレジスタをプログラムした後に,
転送の度にプログラムされる必要があります. 8237のレジスタに書き込みを行うとき,
ソフトウェアの下位互換性のために, 82374で追加された一部のレジスタの内容が
強制的に0にクリアされるからです.
注: 8237は, 非``fly-by''モードでは, 互いに接続された
2つのチャネルでのメモリ-メモリ間でのDMA操作を許可します.
しかし, PCメーカは, ただでさえ乏しいこのリソースをこんなふうに
使ったりしません。
なぜなら, CPUを使用してメモリ間のデータを動かす方が早いからです.
PCアーキテクチャでは, それぞれのDMAチャネルは, 通常
与えられたDMAチャネルを使用するハードウェアがそのチャネルについて
DRQ線を使って転送を要求した時のみ動作します.
注: 「物理的な」 64Kの境界を 8086モードの
64k「セグメント」と混同してはいけません. セグメントは, セグメント
レジスタに数学的にオフセットレジスタを加算して作られるものです.
ページレジスタにはアドレスのオーバーラップも無く,数学的に
ORを取られることもありません.
さらに複雑なことには, PC/ATでは外部のDMAアドレスのラッチは
8ビットしか保持しません. よって8+16で24ビットになり, これは
DMAが0から16メガの間のメモリ番地しか指し示せないことを
意味します. 16メガ以上のメモリを持ったより新しいマシンにおいても,
標準的なPCコンパチブルなDMAでは16メガ以上のメモリ番地には
アクセスできません.
この制限を避けるために, オペレーティングシステムは
16メガ以下にある物理的な64kの境界をまたがない領域にRAMバッファを
予約します. そして, DMACはデータを周辺機器からそのバッファに
転送するようにプログラムされます. 一旦DMACがこのバッファに
データを動かすと, オペレーティングシステムは本当にデータを
格納したいアドレスにバッファからデータをコピーします.
16メガを越えるアドレスからDMAベースの周辺機器にデータを
書き込む際には, データは16メガ以下に位置したバッファから最初に
コピーされなくてはならず, その後, DMACはバッファからハードウェアに
データをコピーすることができます. FreeBSDでは, これらの予約バッファは
「バウンスバッファ」と呼ばれます. MS-DOSの世界では,
これらは「スマートバッファ」などと呼ばれます.
注意: 82374と呼ばれる8237の新しい実装においては,
ページレジスタを16ビットで指定して, バウンスバッファを使用しなくても,
32ビットのアドレス空間全体にアクセスすることが可能です.
注:
初期のIBM PCコンピュータでは, DMAチャネル0は操作の
リフレッシュのために予約されていますが,
最近のシステムでは通常, 周辺機器によって使用することができます.
周辺機器がバスマスタリングを行っている時は,
システムバスを保持している間絶えずメモリにもしくはメモリから
データを転送することが重要です.もし, 周辺機器がこのように
できないときは, システムがメインメモリのリフレッシュを
行なえるようにしばしばバスを開放しなくてはなりません.
全てのPCでメインメモリとして使われるダイナミックRAMは,
中身が「満たされている」ビットを保持するため
頻繁にアクセスされなくてはなりません.
ダイナミックRAMは, それぞれが1ビットのデータを記憶するコンデンサが
たくさん集まって構成されています. これらのコンデンサは充電された
状態で"1", 充電されていない状態で"0"を表します.
全てのコンデンサは放電するため, "1"の値を保持するために,
一定の間隔で電力を加える必要があります.
実際にRAMチップはRAMの適切な場所に電力を送る作業を行ないますが,
メモリのリフレッシュ作業がRAMを普通にアクセスする時と
衝突しないように, それをいつ行なうかを
コンピュータが休止状態の時に知らせなくてはなりません.
もしコンピュータがメモリのリフレッシュを行なえない場合は,
メモリの中身はわずか数ミリ秒で壊れてしまいます。
メモリの読み込みと書き込みのサイクルはリフレッシュサイクルとして
カウントされる(ダイナミックRAMのリフレッシュサイクルは
実際には不完全なメモリ読み込みサイクルになります)ので,
周辺機器のコントローラが連続するメモリ番地からデータの読み込み
または書き込みを行う間は, メモリの全てがリフレッシュされます.
バスマスタリングはいくつかのSCSIホストインターフェースやその他の
ハイパフォーマンスな周辺機器コントローラに見られます.