CPU-50 割り込みハンドリングについて
- 概要
CPU-50ではRORAにて割り込み開放するには、オールベクター割り込みを
使用する必要があります。
これは、VMEDriverユーザーズ・マニュアルにも記載されている事項でもあり、
Universeを搭載したCPU-50にてRORAの割り込み開放機能をするには
割り込みハンドリングルーチン等を変更する必要があります。
- 解説
Universeの仕様により割り込みハンドリング桙ノIACKサイクルが終了すると
内部の割り込みステータスレジスタの内容がクリアされます。
このとき、Universeは内部の割り込みステータスレジスタのビットがクリアされていて、
VMEbus上でまだ、IRQxラインがアサートされていると、次の割り込みが入ったと判断してしまいます。
このため、Universeの割り込みステータスレジスタのビットがクリアされる前に、
割り込みサービスルーチンにてRORAで割り込み開放が出来ないと
次のIACKサイクルが開始されてしまい、ベクター無しの割り込みが起きてしまいます。
- 対策
RORAにて割り込み開放する際には、ベクター無し割り込みを使用する必要があります。
- VMEでベクター割り込みを使用するときは
割り込みハンドリングルーチン起動 (VMEドライバ) |
↓
割り込みベクタの取得 (VMEドライバ) |
↓
ベクターに対応した割り込みサービスルーチン起動 (VMEドライバ) |
↓
割り込みサービスルーチン実行 (Leafドライバ) |
の順番で実行されます。
- VMEでベクター無しの割り込みを使用するときには
割り込みハンドリングルーチン起動 (VMEドライバ) |
↓
割り込みサービスルーチン起動 (VMEドライバ) |
↓
割り込みベクターの取得 (Leafドライバでdi_intr_acknowledge()を呼び出す) |
↓
ベクターに対応した割り込みサービスルーチンを起動 (Leafドライバ) |
↓
割り込みサービスルーチン実行 (Leafドライバ) |
の順番で実行されます。
[ドライバ設定ファイルの変更]
ベクター無しの割り込みを使用する際には、xxx.confファイルの
”interrupts"プロパティのベクターに"-1"を指定します。
また、ベクター定義用に"vector"プロパティを用意します。
※ドライバ内にddi_getlong_prop()を使用してプロパティを取得する必要があります。
コンフィギュレーションファイルの例
name="pvme332" class="vme" reg=0x2d,0x6000,24 interrupts=1,-1 vector=0xc0,0xc1; |
[ドライバ変更について]
vdi_intr_acknowledge()を呼び出すには、VMEドライバの機能をインクルードする必要があります。
ソースコードの最初の方に追加します。
… … #include <sys/ddi.h> #include <sys/sunddi.h> #include <sys/vdi.h> <- VMEドライバのインクルードファイル … … /* Support Force VMEDriver function */ char _depends_on[]="drv/VME"; |
割り込みサービスルーチン等の変更について
attachルーチンにて
… … ddi_add_intr(dip,0,&pvme332->iblock_cookie1, &pvme332->idevice_cookie1,pvme332_intr,(caddr_t)0) <- 引数6には、割り込みプロパティ番号を代入します。 … … ddi_getlongprop(DDI_DEV_T_NONE,dip,0,"vector", (caddr_t)&pvme332->vector,&len) <- コンフィグレーションファイル中の”vector”より読み込みます。 … … |
intrルーチンにて
static u_int pvme332_intr(int arg) { register pvme332device *pvme332; register int vec; pvme332 = ddi_get_soft_state(pvme332_state,unit); mutex_enter(&pvme332->mutex); if(pvme332->pvme332reg->intstat != INT_STS_ASRT){ <- 割り込みをクリアする。 return (DDI_INTR_UNCLAIMED); } vec = vdi_intr_acknowledge(pvme332->pvme332dip,arg); <- 割り込みベクタを得る。 if(vec != VDI_SUCCESS){ if(vec == VDI_FAILURE) cmn_err(CE_WARN,"pvme332_intr() IACK cycle BusErr or Timeout"); } pvme332->pv_busy &= ~PVME332_INTR_BUSY; pvme332->pvme332reg->intcntrl = INTR_DIS; if(vec == pvme332->vector->vect1){ <- 各ベクターに対応した割り込みサービスルーチンを実行する。 pvme332intr1(); } else if(vec == pvme332->vector->vect2){ pvme332intr2(); } else if(vec == pvme332->vector->vect3){ pvme332intr3(); } cv_broadcast(&pvme332->pv_cv); mutex_exit(&pvme332->mutex); return (DDI_INTR_CLAIMED); } |