第10回 8169-2
続き。
前回のまとめとしては、ディスクリプタを適切に設定しましょう、という話であった。
今回はそこらへんを組み合わせて、ドライバを作っていくべきではないでしょうか。
まずは割り込みだなー。割り込みは14個あって、
- System Error Interrupt : PCIバスの問題発生
- Time Out : 内蔵してるタイマがタイムアウト
- Software Interrupt : どっかのレジスタに値を書いたとき
- Tx Descriptor Unavailable : OWN = 0のTx ディスクリプタを読んだ
- Rx FIFO Overflow : 中のFIFO(ソフトウェアからは直接見えない)があふれた
- PUN/LinkChg : リンク状態が変わった
- Rx Descript Unavailable : OWN = 0のRxディスクリプタを読んだ
- Tx Error : Txで衝突とかした
- Tx OK : おk
- Rx Error : CRCエラーとか
- Rx OK : おk
説明してなかったが、この文章は、あまりドライバの設計には踏み込まないようにしているが、典型的なドライバ設計を書くぐらい許されると期待している…
通信する系のデバイスの典型的なドライバは、以下のようになるなー
- 送信
- 受信
- 受信割り込みが来るまで待つ
- 受信が来たら処理する
- 処理が遅くて受信データが溢れたら適切な処理をやる
8169の場合はそれぞれ、
- FIFOにデータを入れる → ディスクリプタを設定して、OWN = 1にする
- FIFOが一杯だったら… → ディスクリプタに空きが無い
- FIFOが空く割り込みが起こるまで待つ → Tx OK/Tx Error発生まで待つ
- 完了まで待つ → Tx OK/Tx Error発生まで待つ
- 受信割り込みが来るまで待つ → Rx OK発生まで待つ
- 受信が来たら処理する → デバイスが設定したディスクリプタの値を読む
- 処理が遅くて受信データが溢れたら… → Rx FIFO Overflowが発生したら
- 適切な処理をやる → (ドライバ依存だぞ)
という感じだなー。
ちなみに、8169には、Rx FIFO Overflowで失ったパケットの数をカウントするMPC(Missed Packet Counter)というカウンタがあるのんだが、これはマイナバージョンごとに有ったり無かったりであり、ものによっては、クロックごとにカウントされてるみたいな実装があるなー(詳細は調べてない)。
その昔、Linuxの8169のドライバで、errorのカウントが凄いことになってたのを見たことある人もいるかもしれないが、それはそういうのが原因だなー。
あと、8169のFIFO Overflowでいう、「FIFO」はソフトウェアからは直接観測できない内部にあるFIFOのことで、それとドライバのFIFOを混同しないようにね!
前回も含めて、以上を踏まえると、ドライバは大体以下のようになる
- 初期化
- デバイスリセット
- MII設定
- Tx Configuratin/Rx Configuration設定(て何?)
- ディスクリプタ領域確保
- OWN = 0にしてTx/Rxディスクリプタ初期化
- RDSAR/TNPDS設定
- Tx/Rxを有効にする
- 送信
- 送信割り込み
- OWN = 0になってるディスクリプタを処理完了とする
- 受信開始
- 受信割り込み
- OWN = 0になってるディスクリプタが指すデータを受信データとする
そういえば書き忘れていたが、送信/受信が完了すると、そのディスクリプタのOWNは0になるのである。
前回「まだまだ続くよ」みたいな書きかたしたけど、実際書いてみると、そんなに書くことあらへんね…
基本的にはただのシリアルなわけで、そんなに、難しいものではない、という感じでしょうかね…
8169対応したコードを、ここに置いておくわ。
r8169_rxコマンドで、データを受信してダンプ、r8169_txコマンドで、謎のデータ(未初期値だが…)を送信するわね。
さて、次回は…N450が64bit対応することが判明したので、
http://ark.intel.com/Product.aspx?id=42503&processor=N450&spec-codes=
x86-64の予定である。もちろん予定は未定であり、そもそもやる気が続くだろうかという問題もござるよ。