UNIX 6th code reading - RKディスクドライバ

はじめに

今回は16章を見ていきます。

PDP11で採用しているRKディスクのドライバを追います。

なんとこのデバイスドライバは150行くらいで書かれています。

RKのレジスタ

RKをコントロールするためのレジスタがあります。これらのレジスタに適切な値をセットすることでディスクシステムを操作します。

この章を読むのに必要なレジスタの必要なビット情報だけ記しておきます。RKのhandbookにはindicator(たぶん状態を示すライト)の説明なんかもありますので興味のある方はそちらを見てみてください。

RKCS

Control Status Register. RKをコントロールするためのレジスタ

bit description
15 RKER(エラーレジスタ)のいずれかがされたらこのbitがセットされる
7 コマンドを受け付ける準備ができていたらセットされる
6 セットされているとRK動作終了時vector 220で割り込みをかける
5-4 メモリ拡張。物理アドレスの上位2bitが格納される
3-1 RK実行の種類。000ならリセット。010なら読み込み。001なら書き込み。その他色々
0 セットされるとRKの動作が開始される
RKWC

Word Count Register. 転送を行うワード数の2の補数が格納されます。

RKDA

Disk Address Register. 読み書きを行うディスクのアドレスを格納する。

bit description
15-13 ドライブ番号
12-5 シリンダ番号
4 面番号
3-0 セクタアドレス

devtab

Lions本では15章で扱っているdevtabですが、前回のエントリでは触れなかったのでここで触れておきます。

devtabは4551行から宣言されている構造体で、各デバイスの状態フラグやキュー、バッファを管理しています。

rkstrategy

ディスクの読み書きを行う関数です。カーネルはこの関数を実行して読み書きを行うようです。

  • 5397 - 5398 : PDP11/40ではno operationらしい
  • 5399 - 5406 : バッファのb_blknoが大きすぎた場合エラー。dはRKのブロックサイズを示す? ここではdevice minor numberはサブデバイスを示している?
    • The Unix I/O Systemより引用 Typically the minor number selects a subdevice attached to a given controller, or one of several similar hardware interfaces.
  • 5407 : バッファのavリストの後段に0をセット(後段はないの意)
  • 5408 : プロセッサ優先度を5に上げる。RKの割り込み優先度は5。つまり、RKによる割り込みを防ぐためにプロセッサ優先度を上げていると思われる
  • 5409-5412 : rktabはRK用のdevtab構造体。5386行目で宣言されている。RKのキューが空だったらキューの先頭にバッファを追加。空でなければ最後尾につける。
  • 5413 : rktabの最後尾にbpを設定
  • 5414 - 5415 : rktabl.d_activeが0ならば(RKが動作中でなければ)rkstart( )を呼び出してRKディスクの読み書きを開始
  • 5416 : プロセッサ優先度を0に戻す


ここでのqueueの処理を絵で書いてみました。FIFOで最初に入ったd_actf(action first?)から順に処理されていきます。次章でav-listについての説明がありますが、どうやらRK queueの中では本来の目的と違う使い方をされているようです。


rkstart

  • 5444 - 5445 : 実行すべきバッファがなければreturnする
  • 5446 : rktab.d_activeをインクリメント。ディスクが稼動中であることを示す
  • 5447 : devstart( )を読んでディスクの動作を開始する
    • 第一引数 : キューの先頭のバッファのポインタ
    • 第二引数 : RKDAのアドレス。RKADDRは0177400なので(5363行参照)RKDAのアドレスは0177412(5382行参照)
    • 第三引数 : rkaddr(bp)で計算されるディスクのアドレス

rkaddr

引数で渡されたバッファポインタのb_blkno, b_devからディスク中の対象アドレスを計算します。RKDAに直接渡せるのフォーマットでreturnします。

b_dev.minorの扱いがよくわからないので詳細は省略します。後でRKのhandbookとにらめっこしてみようと思います。

devstart

バイスの動作を開始します。RKDA, RKBA, RKWC, RKCSレジスタをセットします。

  • RKDA, RKBA, RKWC, RKCSに値をセットする。RKBA, RKWC, RKCSにはRKDAのアドレスからシフトしてアクセスする。これらのレジスタのアドレスの関係は5376-5383を参考
    • 5106 : devblkはRKDAのアドレス
    • 5107 : RKDAのアドレスをデクリメントしてRKBAにアクセス。バッファのアドレスを格納する
    • 5108 : さらにデクリメントしてRKWCにアクセス。ワードカウントをセットする
    • 5109 - 5115 : RKCSに値をセットする。RKCSの0bit目に1がセットされるとRKディスクが動き出す


RKCSにセットする値を以下に記してみました。

まずは5109-5110行目。IENABLEはRKディスク動作終了時に220で割り込みをかけることを示します。GOはRKディスク起動を示します。b_xmemは物理アドレスの上位2bitを表します。

000000000|hbcom(0) << 8
001000000|IENABLE
000000001|GO
000xx0000|(rbp->b_xmem & 03) << 4
----------
001xx0001


この値に、読み出し(RCOM)、書き込み(WCOM)でそれぞれ適切な値を計算します。

まずは読み込みの場合。

001xx0001
000000100|RCOM
---------
001xx0101


書き込みの場合。

001xx0001
000000010|WCOM
---------
001xx0011


これがRKCSにセットされます。上で書いたRKCSの説明と見比べてみると理解が深まると思います。

rkintr

RKディスクの動作が終了するvector 220で割り込みがかかります。rkintr( )実行までの流れを簡単に書きます。割り込みの章を思い出すと理解が深まると思います。

  • 544 : rkio(576)にジャンプ
  • 577 : call(766)へジャンプ
  • 785 or 799 : rkintr(5451)へジャンプ


rkintr( )の中を見ていきます。

  • 5455 - 5456 : RKが動いていなかったらreturnする。どういうときにこういうケースがあり得る? やろうと思えばどの周辺デバイスでもvector 220で割り込むことは可能だから、不正な割り込みを弾くため?
  • 5457 : rktabのqueueからfirstのバッファを取得
  • 5458 : rktab.d_activeを0に戻す。RKが動作していないことを示す?
  • 5459 : rkcsが負ならば。RKCSの先頭bit(15bit)はerrorを示す。これが1になっていたらという意味
    • 5460 : deverror( )を呼び出しエラーメッセージを出力
    • 5461 : RKCSに01をセット
    • 5462 : 5461のRK動作が終了するまでbusy waiting
    • 5463 - 5467 : エラーカウント(リトライカウント)をインクリメント。このカウンタが10以下ならリトライ。10以上ならb_flagsにエラーフラグを立てる。10という数字にはどういう意味がある?10という数字を見ると、ディスクのアクセスに失敗するケースが結構ありそうな気がするが(タイムアウトとか?)
  • 5469 : エラーカウントを0に戻す
  • 5470 : rktabのqueueからfirstのバッファを取り除く
  • 5471 : iodone( )を呼び出してバッファの完了フラグを立てる
  • 5472 : rkstart( )を呼び出して、queueの次のバッファの動作を開始する。もしqueueが空なら5444-5445行目returnする


FIFOの先頭から処理されていくことを絵で表すとこんな感じです。

iodone

バッファのB_DONEを立てます。このバッファのライトバック書き込みを示すフラグが立っていたらバッファを解放します。そうでなければB_WANTEDフラグをリセットして、このバッファを待っているプロセスを起こします。

終わりに

約150行しかなかったので、思っていたより簡単に理解できました。まさかデバイスドライバを理解できる日が来るとは思っていませんでした。最近のデバイスドライバも同じようなロジックなのか気になるところです。

RK handbookなどを読んで、RKディスク自体の理解も深めたいです。