Programmer's Note

コード読み書きの備忘録。

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だけで済んでいる。

参考資料