PDP-11の磁気ディスクRK11からブロック読み出しする

以前、”[PDP-11の磁気ディスク装置RK11の勉強メモ](http://qiita.com/hifistar/items/3b79566feebfec2f93bd)”では、アセンブラのサンプルを書いたが、今度は、C言語でRK11のディスクドライブをUNIX V6的なブロック読み出しをする関数を実装してみる。
ソースコードがメモ代わり。

####ソースコード
```c:main.c
typedef unsigned int uint16_t;

typedef struct {
    uint16_t rkds; // Drive Status Register
    uint16_t rker; // Error Register
    uint16_t rkcs; // Control Status Register
    uint16_t rkwc; // Word Count Register
    uint16_t rkba; // Bus Address Register
    uint16_t rkda; // Disk Address Register
} RK11register_t;

#define RK11_CTL_REG_ADDR (0177400)
static volatile RK11register_t *rk11_p = (RK11register_t*)RK11_CTL_REG_ADDR;

enum rk11_cs {
    CS_GO         = (1),
    CS_WRITE      = (1<<1),
    CS_READ       = (1<<2),
    CS_READ_RDY   = (1<<7)
};

static const int BLK_WORD_SIZE=256;

void
read_blk(int drv_no, int blk_no, void *dst_buf)
{
    uint16_t cylnder = (blk_no / 12) >> 1;
    uint16_t surface = (blk_no / 12) & 1;
    uint16_t sector  = (blk_no % 12);

    rk11_p->rkda = (drv_no << 13) | (cylnder << 5) | (surface << 4) | sector;
    rk11_p->rkba = (uint16_t)dst_buf;
    rk11_p->rkwc = -(BLK_WORD_SIZE);
    rk11_p->rkcs = CS_READ | CS_GO;

    while(!(rk11_p->rkcs & CS_READ_RDY))
        ;
}

int
cstart()
{
    static volatile void *buf1 = (void*)02000;
    static volatile void *buf2 = (void*)03000;
    read_blk(0, 1, (void*)buf1);
    read_blk(1, 0, (void*)buf2);
    while(1);
    return 0;
}
```
上記、やっていることは、ディスク０のブロック１を02000番地に読み込み、ディスク１のブロック０を03000番地に読み込んでいるだけ。

```as:start.S
    .GLOBAL _cstart

    STACK = 07000

    .text
    .even
    .globl  start
start:
    mov     $STACK, sp
    jsr     pc, _cstart
    mov     $start,-(sp)
    clr     pc

    .end
```


```mf:Makefile
TARGET = read_blk

OBJS = start.o main.o

CC = pdp11-aout-gcc
AS = pdp11-aout-as

CFLAGS = -Wall -nostdinc -nostdlib -fno-builtin
CFLAGS += -std=c99

all: $(TARGET).lda

$(TARGET).lda: $(TARGET).out
	aout2simhbin $(TARGET).out $(TARGET).lda

$(TARGET).out: $(OBJS)
	pdp11-aout-ld -T ld.scr $(OBJS) -o $(TARGET).out

.c.o:
	$(CC) $(CFLAGS) -c $<

.s.o:
	$(CC) -c $<

clean:
	rm *.lda
	rm *.out
	rm *.o
```
```ld.scr
ENTRY(start)
SECTIONS
{
  . = 01000;
  .text : {
    *(.text)
    *(.rodata)
  }
  .data : {
    *(.data)
  }
  .bss :  {
    *(.bss)
  }
  end = .;
}
```


以下は、pdp11エミュに渡す設定ファイル：

```:rc-pdp11
set cpu 11/40
set cpu u18
att rk0 unix0_v6_rk.dsk
att rk1 unix1_v6_rk.dsk
l read_blk.lda
```
上記の``unix0_v6_rk.dsk``、``unix1_v6_rk.dsk``は、PDP-11用のUNIX V6のディスクイメージで、下記から入手できる。
http://simh.trailing-edge.com/software.html


##### 実行確認
正しく読み込んでいるかどうか、実行したあとに、メモリダンプして確認。


```
$pdp11 rc-pdp11

PDP-11 simulator V3.9-0
Disabling XQ
sim> g
** C-eで抜ける **

Simulation stopped, PC: 001362 (BR 1362)
sim> e 2000:2040
2000:	000144
2002:	007640
2004:	000057
2006:	002412
2010:	002371
2012:	002442
2014:	002141
...

sim> e 3000:3040
3000:	012706
3002:	137000
3004:	010601
3006:	005000
3010:	020701
3012:	103012
3014:	021027
...
```
比較先は``unix0_v6_rk.dsk``、``unix1_v6_rk.dsk``ファイルを``od``のダンプだ。（手順は省略）


####必要な道具
(1) PDP-11のgccクロス環境構築
http://qiita.com/hifistar/items/187fd7ad780c6aa26141
(2) aout2simhbin
http://qiita.com/hifistar/items/e43878172d8c7c6595fb
(3) simh
http://simh.trailing-edge.com/