PDP-11: RK11のデータアクセスのアドレスの計算メモ
前回はPDP11の磁気ディスクについての概要だったが。今回はアクセス方法について。
ディスクに対してデータを読み書きするためには、RK11の制御レジスタにアクセスして行う。 PDP-11はMemory-mapped I/O なので、ペリフェラルのレジスタは特定のメモリ番地の読み書きをすればよい。
以下はマニュアルからの抜粋。
RK11の制御レジスタ一覧
Name | Abbreviation | Address |
---|---|---|
RK11 Drive Status Register | RKDS | 777400 |
RK11 Error Register | RKER | 777402 |
RK11 Control Status Register | RKCS | 777404 |
RK11 Word Count Register | RKWC | 777406 |
RK11 Bus Address Register | RKBA | 777410 |
RK11 Disk Address Register | RKDA | 777412 |
RK11 Data Buffer Register | RKDB | 777416 |
※アドレスは8進数表記
別の資料を探したら、RK11のコントロール用のレジスタ一覧は以下が見やすい。(RK05 Disk Drive)
まず知りたいのは、ディスク領域の場所指定の仕方だ。 ディスクのアドレス指定は、RKDAレジスタを使う。
777412 Disk address 15-13 Drive select : 3bit (0〜7) 12-5 Cylinder address : 8bit (0〜202) 4 Surface (head) : 1bit (0,1) 3-0 Sector : 4bit (0〜11)
ドライブ番号は0〜7番。シリンダは外周側から0番号が振られ、202まで。 ディスク面は表と裏の0,1指定。あとはセクタ番号のの指定(0〜11)。
でも、これデータを保存するときに、いちいち全パラメータを指定するのは面倒だろう。
UNIX V6の場合はどうしているのかというと、ドライブ番号はデバイスファイルのマイナー番号として使っているが、あとは論理的にはブロック番号というもので統一して扱っている。
あるディスク上のブロック番号は、シリンダ0, 面0, セクタ0 をブロック0として、リニアに増えて行く。(これはハードディスクのLBA方式と同じ考え方ですね。UNIXがベースになってるのかしら)
ブロック番号とセクタ、面、シリンダの関係
Block | Cylinder | Surface | Sector |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 |
2 | 0 | 0 | 2 |
... | |||
11 | 0 | 0 | 11 |
12 | 0 | 1 | 0 |
13 | 0 | 1 | 1 |
... | |||
23 | 0 | 1 | 11 |
24 | 1 | 0 | 0 |
25 | 1 | 0 | 1 |
... |
計算式 (C言語)
- シリンダ番号 = (ブロック番号/12)/2
- 面番号 = (ブロック番号/12)&1
- セクタ番号 = ブロック番号%12
UNIX V6の実装
コードそのままではないが、以下のような実装をしている。
return (d_minor<<13 | (blkno/12)<<4 | blkno%12);
d_minor:デバイスのマイナー番号、blkno:ブロック番号。 またシリンダ番号と面番号はビット的には隣どおしなので、(blkno/12)<<4だけで済んでいる。