/*********************************************************************** * * MODULE: int1.c * * PURPOSE: CPU and External Level 1 Interrupt Handler for * the BCM97038. * ***********************************************************************/ #include "int1.h" /*********************************************************************** * Local data structures ***********************************************************************/ typedef struct { FN_L1_ISR isr; void *param1; int param2; } Int1Vector; /*********************************************************************** * Local #define's ***********************************************************************/ #define INT1_GET_REG_NUM(id) ((((id)&0xe00) >> 9) | (((id)&0xe0) >> 5)) #define INT1_GET_BIT_NUM(id) ((id)&0x1f) #define INT1_MAX_VECTORS 96 /*********************************************************************** * Static variables ***********************************************************************/ static Int1Control *CpuInt1Control = CPUINT1C; static Int1Vector CpuInt1VectorTable[INT1_MAX_VECTORS]; /*********************************************************************** * void CPUINT1_SetInt1Control() * * Set the interrupt control structure. Normally it is CPUINT1C. * For linux user mode, it should be set to point to a user * structure. If a NULL is passed to this function, it will * use set the control structure to CPUINT1C. ***********************************************************************/ void CPUINT1_SetInt1Control(Int1Control *int1c) { if (int1c) CpuInt1Control = int1c; else CpuInt1Control = CPUINT1C; } /*********************************************************************** * void CPUINT1_SetInt1ControlAddr() * * Get the interrupt control structure address. ***********************************************************************/ unsigned long CPUINT1_GetInt1ControlAddr(void) { return (unsigned long) CpuInt1Control; } /*********************************************************************** * void CPUINT1_Isr() * * Main interrupt handler: Handle all CPU L1 interrupts ***********************************************************************/ void CPUINT1_Isr(void) { unsigned long IntrW0Status; unsigned long IntrW1Status; unsigned long IntrW2Status; unsigned long IntrW0MaskStatus; unsigned long IntrW1MaskStatus; unsigned long IntrW2MaskStatus; Int1Vector *vec; int i; if (((IntrW2Status=CpuInt1Control->IntrW2Status) & ~(IntrW2MaskStatus=CpuInt1Control->IntrW2MaskStatus))) { IntrW2Status &= ~IntrW2MaskStatus; for (i = 64; i < 96; i++) { if (IntrW2Status & 0x1) { vec = &(CpuInt1VectorTable[i]); if (vec->isr!=0) vec->isr(vec->param1, vec->param2); } IntrW2Status >>= 1; } } if (((IntrW1Status=CpuInt1Control->IntrW1Status) & ~(IntrW1MaskStatus=CpuInt1Control->IntrW1MaskStatus))) { IntrW1Status &= ~IntrW1MaskStatus; for (i = 32; i < 64; i++) { if (IntrW1Status & 0x1) { vec = &(CpuInt1VectorTable[i]); if (vec->isr!=0) vec->isr(vec->param1, vec->param2); } IntrW1Status >>= 1; } } if (((IntrW0Status=CpuInt1Control->IntrW0Status) & ~(IntrW0MaskStatus=CpuInt1Control->IntrW0MaskStatus))) { IntrW0Status &= ~IntrW0MaskStatus; for (i = 0; i < 32; i++) { if (IntrW0Status & 0x1) { vec = &(CpuInt1VectorTable[i]); if (vec->isr!=0) vec->isr(vec->param1, vec->param2); } IntrW0Status >>= 1; } } } /*********************************************************************** * void CPUINT1_Disable() * * Disables CPU or external interrupt specified by 'intId'. Valid * intId values/mnemonics can be found in int1.h. ***********************************************************************/ void CPUINT1_Disable(unsigned long intId) { unsigned char reg_num = INT1_GET_REG_NUM(intId); unsigned char bit_num = INT1_GET_BIT_NUM(intId); if (reg_num > 1) CpuInt1Control->IntrW2MaskSet = 0x1 << bit_num; else if (reg_num == 1) CpuInt1Control->IntrW1MaskSet = 0x1 << bit_num; else if (reg_num == 0) CpuInt1Control->IntrW0MaskSet = 0x1 << bit_num; } /*********************************************************************** * void CPUINT1_Enable() * * Enables the CPU or external interrupt specified by 'intId'. Valid * intId values/mnemonics can be found in int1.h. ***********************************************************************/ void CPUINT1_Enable(unsigned long intId) { unsigned char reg_num = INT1_GET_REG_NUM(intId); unsigned char bit_num = INT1_GET_BIT_NUM(intId); if (reg_num > 1) CpuInt1Control->IntrW2MaskClear = 0x1 << bit_num; else if (reg_num == 1) CpuInt1Control->IntrW1MaskClear = 0x1 << bit_num; else if (reg_num == 0) CpuInt1Control->IntrW0MaskClear = 0x1 << bit_num; } /*********************************************************************** * int CPUINT1_ConnectIsr() * * Maps CPU or external interrupts. Takes the ISR function pointer * 'pfunc' and the parameters 'param1' and 'param2' and stores the * values in a vector table, indexed by 'intId'. 'param1' and * 'param2' will be passed as parameters to the function 'pfunc'. * Valid intId values/mnemonics can be found in int1.h. ***********************************************************************/ int CPUINT1_ConnectIsr(unsigned long intId, FN_L1_ISR pfunc, void *param1, int param2) { unsigned char reg_num = INT1_GET_REG_NUM(intId); unsigned char bit_num = INT1_GET_BIT_NUM(intId); if( reg_num == 1 ) { /* This for interrupt in W1 register */ intId = 32 + bit_num; }else if( reg_num > 1 ) { /* This for interrupt in W1 register */ intId = 64 + bit_num; } if (intId > INT1_MAX_VECTORS) return 0; CpuInt1VectorTable[intId].isr = pfunc; CpuInt1VectorTable[intId].param1 = param1; CpuInt1VectorTable[intId].param2 = param2; return (int) pfunc; } #ifdef ACB612 /*********************************************************************** * void CPUINT1_Isr() * * Main interrupt handler: Handle all CPU L1 interrupts ***********************************************************************/ void CPUINT1_Isr_ex(int bit) { Int1Vector *vec; if (8 != bit) { return; } vec = &(CpuInt1VectorTable[bit]); if (vec->isr!=0) vec->isr(vec->param1, vec->param2); } #endif