UNIX 6th code reading - RKディスクドライバ
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になっていたらという意味
- 5469 : エラーカウントを0に戻す
- 5470 : rktabのqueueからfirstのバッファを取り除く
- 5471 : iodone( )を呼び出してバッファの完了フラグを立てる
- 5472 : rkstart( )を呼び出して、queueの次のバッファの動作を開始する。もしqueueが空なら5444-5445行目returnする
FIFOの先頭から処理されていくことを絵で表すとこんな感じです。
iodone
バッファのB_DONEを立てます。このバッファのライトバック書き込みを示すフラグが立っていたらバッファを解放します。そうでなければB_WANTEDフラグをリセットして、このバッファを待っているプロセスを起こします。