OpenBSD/sgi on octane2 - HEARTというデバイス

octaneではHEARTというデバイスからIPIを送受信するようだ。

こちらはLinuxのIPI送信部分のコード:

/* HEART internal register space */
#define HEART_PIU_BASE		0x900000000FF00000

/* full addresses */
#define HEART_MODE		((volatile unsigned long *)HEART_PIU_BASE)

#define HEART_ISR		((volatile unsigned long *)(HEART_PIU_BASE+0x10030))

/* level 2 interrupts */
#define IRQ_IPI_P(x)		(46+(x))

void core_send_ipi(int cpu, unsigned int action)
{
	unsigned long flags;
#ifdef DEBUG_IPI
	if(action==SMP_CALL_FUNCTION)
		printk("KERN_INFO IPI call_function TX -> %d\n",cpu);
#endif
	spin_lock_irqsave(&ipi_mbx_lock,flags);
	ipi_mailbox[cpu]|=action;
	spin_unlock_irqrestore(&ipi_mbx_lock,flags);
	*HEART_SET_ISR=1UL<<(IRQ_IPI_P(cpu));
}

HEART_SET_ISRというレジスタへビットを立てている。
立てる位置は割り込み番号で決める。

IRQ_IPI_P(x)は単に46をxに足してるだけ。

#define IRQ_TIMER_P(x)		(42+(x))

void prom_smp_finish(void)
{
	int cpu=smp_processor_id();
	if(request_irq(IRQ_IPI_P(cpu),ip30_mailbox_irq,0,"SMP IPI",NULL))
		printk("IP30: IPI allocation for CPU%d failed.\n",cpu);
	if(request_irq(IRQ_TIMER_P(cpu),ip30_secondary_timer_irq,0,"SMP TIMER",NULL))
		printk("IP30: TIMER allocation for CPU%d failed.\n",cpu);
	local_irq_enable();
}

void prom_cpus_done(void)
{
	int cpu=smp_processor_id();
	if(request_irq(IRQ_IPI_P(cpu),ip30_mailbox_irq,0,"SMP IPI",NULL))
		printk("IP30: IPI allocation for CPU%d failed.\n",cpu);
}

初期化のコードでは、単に割り込みをイネーブルしているだけのように見える。
HEART自体の初期化は特に必要ないのかな?

このrequest_irqはどのレベルで割り込みを制御しているんだったか覚えてないのでもう少し見ていく必要あり。
あと、prom_smp_finish()は起動するCPUから呼ばれるのか、起動されるCPUから呼ばれるのか、どちらでもいいのか、とか。

データシートの無いハードは色々めんどい。