Wednesday, July 05, 2006

IPIPE - 1

1. Grab interrups: interrpt.S

In __common_int_entry:

#ifdef CONFIG_IPIPE
call ___ipipe_grab_irq
SP += 12;
cc = r0 == 0;
if cc jump common_restore_context;
#else /* CONFIG_IPIPE */
call _do_irq;
SP += 12;
#endif /* CONFIG_IPIPE */
call return_from_int;
common_restore_context:
RESTORE_CONTEXT
rti;

/--------------------------------
Note: if returns (r0 == 1), should not call return_from_int.
---------------------------------/

2. asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
{
struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
unsigned long sic_status;
ipipe_declare_cpuid;
int irq;

/--------------------------------------------------------
"struct ivgx {
/* irq number for request_irq, available in mach-bf533/irq.h */
int irqno;
/* corresponding bit in the SIC_ISR register */
int isrflag;
} ivg_table[NR_PERI_INTS];

struct ivg_slice {
/* position of first irq in ivg_table for given ivg */
struct ivgx *ifirst;
struct ivgx *istop;
} ivg7_13[IVG13 - IVG7 + 1];"

ivg7_13 is a table stores the mapping of peripheral interrupt to Core
interrupt IVG7-13.

ivg_table contains "IRQ NUM" and "Position in SIC_ISR" of peripheral
interrupts.
------------------------------------/

if (likely(vec == EVT_IVTMR_P)) {
irq = IRQ_CORETMR;
goto handle_irq;
}

/-----------------------------------------
CORETMR interrupt is likely to happen
-----------------------------------------/

__builtin_bfin_ssync();
sic_status = *pSIC_IMASK & *pSIC_ISR;

/----------------------------------------

sic_status: system interrupt happened and not masked.

------------------------------------------/

for(;; ivg++) {
if (ivg >= ivg_stop) {
num_spurious++;
return 0;
}
else if (sic_status & ivg->isrflag)
break;

/---------------------------------------
Find the system interrupt who triggers "vec"
----------------------------------------/
}

irq = ivg->irqno;
/---------------
irq defined:

See irq.h - peripheral interrupts IRQ NUM starts from 7 - sames order as
SIC_ISR
----------------/


ipipe_load_cpuid();

if (irq == IRQ_SYSTMR) {
*pTIMER_STATUS = 1; /* Latch TIMIL0 */
/* for update_process_times() */
__ipipe_tick_regs[cpuid].ipend = regs->ipend;
}
/--------------
IRQ_SYSTMR is peripheral, while CORE TIMER is CORE interrupt.
Why it need regs->ipend here?
-----------------/


handle_irq:

__ipipe_handle_irq(irq, regs);

return (ipipe_percpu_domain[cpuid] == ipipe_root_domain &&
!test_bit(IPIPE_STALL_FLAG,
&ipipe_root_domain->cpudata[cpuid].status));

/--------------
If this is Linux domain and Linux want to handle interrupt - return 1.
That means, this interrupt is handled the same way as Linux
---------------/


}

Blog Archive