int init_module(void) {下記のpci_find_deviceがコールされます。この中に uni_dev構造体にPCIの情報が入り、
uni_dev = pci_find_device(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, uni_dev);この中のirqをstatic int Irq;で定義されたところに入れます。
Irq = uni_dev->irq;このIrqはこのUniverseチップに1つアサインされています。 ですから、VMEのすべての割り込みはすべてこのラインを通して 行なわれます。
さて、次はこの割り込みが発生した時に呼ばれる割り込みルーチンを 見ましょう。 下記の割り込みルーチン登録処理は同じinit_moduleの中で呼ばれます。
ret = request_irq(Irq, universe_interrupt, SA_SHIRQ, "universe", NULL);ではuniverse_interruptルーチンの中ではどのように処理されているのでしょう。
static void universe_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int lint_stat; lint_stat = read_register(UNIV_LINT_STAT); /* read the interrupt bits */上記のように割り込みビットをチェックしてどこからの割り込みかを 判断します。そしてそのIRQ1-7に従った内部関数を呼んでいます。
if (lint_estat & UNIV_BM_LINT_VIRQ7) { handle_vme_irq(7); multiplicity++; } if (lint_estat & UNIV_BM_LINT_VIRQ6) { handle_vme_irq(6); multiplicity++; } if (lint_estat & UNIV_BM_LINT_VIRQ5) { handle_vme_irq(5); multiplicity++; } if (lint_estat & UNIV_BM_LINT_VIRQ4) { handle_vme_irq(4); multiplicity++; } if (lint_estat & UNIV_BM_LINT_VIRQ3) { handle_vme_irq(3); multiplicity++; } if (lint_estat & UNIV_BM_LINT_VIRQ2) { handle_vme_irq(2); multiplicity++; } if (lint_estat & UNIV_BM_LINT_VIRQ1) { handle_vme_irq(1); multiplicity++; }ではhandle_vme_irqルーチンでは何をしているのでしょう?
handle_vme_irq(int level) { int statid; int vector; Interrupt_counters.virq[level-1]++; statid = read_register(UNIV_V1_STATID + (UNIV_V2_STATID - UNIV_V1_STATID) * (level-1)); if (statid & UNIV_BM_VX_STATID_ERR) /* bus error during IACK cycle */ { printk(KERN_DEBUG "universe: spurious interupt on level %d\n", level); } else { vector = (statid & UNIV_BM_VX_STATID_STATID) >> UNIV_OF_VX_STATID_STATID; irq_device[level-1][vector].number_of_irqs_since_last_read++; irq_device[level-1][vector].vector = vector; wake_up_interruptible(&irq_device[level-1][vector].irqwait); } }複雑に見えますが、肝心な点はstatidをあるレジスタから呼んで Vectorの番号を知ります。そしてその番号をIRQ1-7及びそのベクタ番号 すべてからの割り込みを受けるべくウエイトフラグを持っていて 対応するフラグを立てている(wake_up_interruptible)ことです。