babildrv

babildrvはコントローラごとに書き方がことなるので、結構なやむ。
V7768はVMIVMEに属しており、何たらunivとつく関数を使うことになる。
SBS620とかとは違い、先にメモリ上でアドレスのmapを作っておいてからアクセスする。
http://ribf.riken.jp/RIBFDAQ/index.php?DAQ%2FManual%2FSetup%2FFrontEnd%2FVMIVME
上記urlに詳細が乗っている様でやっぱりよくわからない。
ということで以下に具体例を示す。

babildrvのモト

babildrvを各場合に何かベースとなるsrcが必要。 そこで候補となるのが、 babirlではnbbqcpyもなければnbbqinstもなく、babirl/babidrv以下のディレクトリをcopyして、make、
その後にbabiesを起動するとbabiesが勝手にinsmodするようになっている(babies.cを見るとあからさまにinsmodが書いてある)。
そこで、まずは上記のうちどれかしらを適当なディレクトリ(/home/daq/expがおすすめ)にコピーし、
とりあえずmakeしてみる。
exp/tsやexp/qdcの場合は普通にコンパイルが通るが、babirl以下にあった物はmakeでいろいろ怒られる。
exp/tsを基本に、exp/qdcのstartup.c,evt.c,clear.c,stop.cを使うのおそらく一番BUGがなくて簡単と思われる。
これならとりあえずアドレスを適切に書き換えるだけでQDCのデータが何か読めるはず。

babirl以下のものを使う場合は、 とするとコンパイルが通るかも。
exp/qdcを元にする場合も注意が必要で、babildrv.cの中の336行目に
  case BABIL_STOPB
が抜けているのでstopが正常に行われない。
これはexp/tsを参考に修正する(babilio.hにBABIL_STOPBの定義も書き加える)。

startup,c,evt,clear.c,stop.c,bbmoduoles.hの編集

そんなこんなでとりあえずコンパイルできたら、今度は手元にあるであろうV792とrpv130用のコードを書いてみる。
コンパイルが通っているのであれば、基本的にはstartup.c,evt.c,clear.c,stop.c,bbmodules.hを適切に準備するだけ。

V792の読み出しはexp/qdcを参考にすれば簡単にできてしまう。
問題はrpv130(repicのi/o register)で、これはサンプルがなかったので少し迷った。
babirl/babirtdrvの中にrpv130.cがあり、これを単純に持ってきてrpv130_writeなどの関数を使うと
システムごと落ちる(実際にはstartup.c、stop.cでは問題ないが、evt.c、clear.cとかだと固まる)
結局これもV792と同様にmapを定義してmap用の関数で読み出せば良いだけだった。
ということで、startup.c,evt.c,clear.c,stop.c,bbmodules.hはこんな感じ。
//bbmodules.h
#include "segidlist.h"

#define BBRL
#define MAXBUFF 4000
#define DBUFF

#define DMASIZE 4000

#define EFN 82

#define VME
#define VMEINT
#define INTLEVEL 1
#define INTVEC   0
#define UNIV

#define A32 0x09
#define A16 0x29

#define RPV130REGSIZE 0x10
#define RPV130ADDR  0x8ff0
#define RPV130MAPN 1
#define OPBUSYCL  0x03
#define OPVSSTART 0x20
#define OPVSSTOP  0x40
#define OPVSRESET 0x80

#define QDCREGSIZE 0x2000
#define QDCADDR 0x20000000
#define QDCMAPN 3

// startup.c
void map(void){
  univ_init_window(QDCADDR, QDCREGSIZE, A32, QDCMAPN);
  univ_init_window(RPV130ADDR, RPV130REGSIZE, A16, RPV130MAPN);
}

void startup(void){
  //  printk("babildrv: start\n");

  vme_define_intlevel(INTLEVEL);

  v7XX_map_clear(QDCMAPN);
  v7XX_map_event(1, QDCMAPN);
  v7XX_map_intlevel(INTLEVEL, QDCMAPN);

  rpv130_map_output(OPBUSYCL, RPV130MAPN);
  rpv130_map_output(OPVSRESET, RPV130MAPN);
  rpv130_map_output(OPVSSTART, RPV130MAPN);
}

// evt.c
void evt(void){
  //  printk("babildrv: evt\n");

  init_event();

  init_segment(MKSEGID(0,0,0,V792));
  v7XX_map_segdata(QDCMAPN);
  end_segment();
}

// clear.c
void clear(void){
  //  printk("babildrv: clear\n");

  v7XX_map_clear(QDCMAPN);

  rpv130_map_output(OPBUSYCL, RPV130MAPN);
}

// stop.c
void unmap(void){
  univ_end_window(QDCMAPN);
  univ_end_window(RPV130MAPN);
}

void stop(void){
  //  printk("babildrv: stop\n");

  rpv130_map_output(OPVSSTOP, RPV130MAPN);

  v7XX_map_intlevel(0, QDCMAPN);
  v7XX_map_clear(QDCMAPN);
}

//rpv130.c
int rpv130_map_output(short l, int n){
  univ_map_write16(0x8, &l, n);

  return 1;
}
map numberは1から8までしか使えない。つまりこのままでは8のmoduleからしか読めないが、
http://ribf.riken.jp/RIBFDAQ/index.php?DAQ%2FManual%2FSetup%2FFrontEnd%2FVMIVME
にその解決法が乗っている。
概念としては同じmoduleを連続するアドレス空間に並べておいて、まとめて読み出す、という感じかと。

REGSIZEは実際にアクセスするメモリ空間のサイズより大きければ良さそう。
V792ならばbase address+0x0000 からbase address+0x10BFまで、
rpv130ならばbase address+0x0 からbase address+0x0Fまで、とマニュアルからに読めるので
これが収まるSIZEにしておく。

rpv130.cを真似してmap読み出し用の関数を綺麗に書いてもよいと思うがやっていない。