📄 excep.c
字号:
if( cpu_int == EXCEP_DEFAULT_HANDLER )
{
h = &table.default_int;
}
else if( cpu_int >= MAX_INTERRUPTS )
{
/* Interrupt specified is unknown */
rc = ERROR_EXCEP_ILLEGAL_INTERRUPT;
}
else
{
/* Specific interrupt */
if( handler == NULL )
{
rc = ERROR_EXCEP_ILLEGAL_HANDLER;
}
else if( table.interrupt[cpu_int].list_size == INT_HANDLERS_PER_LINE )
{
/* Too many handlers have been registered */
rc = ERROR_EXCEP_NO_SPACE;
}
else
{
/* Find unused entry in array */
for( i = 0, h = &table.interrupt[cpu_int].int_handler[0];
(i < INT_HANDLERS_PER_LINE) && (h->handler != NULL);
i++, h++)
{
;
}
table.interrupt[cpu_int].list_size++;
enable = TRUE;
}
}
if( rc == OK )
{
h->handler = handler;
h->data = data;
if( ref )
*ref = (t_EXCEP_ref)h;
/* Enable interrupt mask */
if( enable )
sys_enable_int_mask( cpu_int );
}
/* Restore interrupt enable status */
if(old_ie)
sys_enable_int();
return rc;
}
/************************************************************************
*
* EXCEP_deregister_cpu_isr
* Description :
* -------------
*
* Deregisters interrupt handler.
* It is OK to call this function even if we are in interrupt context.
*
* Parameters :
* ------------
*
* 'ref', IN, Handle obtained when calling EXCEP_register_cpu_isr
*
* Return values :
* ---------------
*
* 'OK'(=0)
* 'ERROR_EXCEP_ILLEGAL_HANDLER': ref is unknown
*
************************************************************************/
INT32
EXCEP_deregister_cpu_isr(
t_EXCEP_ref ref ) /* In : Handle for deregistration */
{
UINT32 old_ie;
t_INT_handler *h = (t_INT_handler *)ref;
t_EXCEP_int_handler_list *list;
INT32 rc = ERROR_EXCEP_ILLEGAL_HANDLER;
UINT32 i, t;
/* Disable interrupts */
old_ie = sys_disable_int();
/* Find and deregister handler pointed to by ref (h) */
if( h == &table.default_int )
{
h->handler = NULL;
rc = OK;
}
else
{
for( i=0; (i<MAX_INTERRUPTS) && (rc != OK); i++ )
{
list = &table.interrupt[ i ];
for( t=0; (t<INT_HANDLERS_PER_LINE) && (rc != OK); t++ )
{
if( &list->int_handler[t] == h )
{
(list->list_size)--;
h->handler = NULL;
if( list->list_size == 0 )
{
if( interrupt_context )
{
/* Function called in interrupt context,
* so interrupts are unmasked by updating
* the context that will be restored when
* we return from exception.
*/
EXCEP_gdb_regs.cp0_status &=
~(1 << (i + C0_STATUS_IM_SHF));
}
else
{
/* Disable interrupt mask */
sys_disable_int_mask( i );
}
}
rc = OK;
}
}
}
}
/* Restore interrupt enable status */
if(old_ie)
sys_enable_int();
return rc;
}
/************************************************************************
*
* EXCEP_register_ic_isr
* Description :
* -------------
*
* Registers an interrupt handler for the specified source in the
* interrupt controller.
*
* A special ID is defined :
* EXCEP_DEFAULT_HANDLER used for a default handler.
*
* The default handler is called if no other handler is registered
* for an interrupt.
*
* Deregistration of the default handler may be done by calling
* this function with 'handler' set to NULL.
* Also, a new default handler may be registered even if a
* previously registered handler has not been deregistered.
* Handlers for specific interrupts must be deregistered using
* EXCEP_deregister_ic_isr.
* Parameters :
* ------------
*
* 'ic_int_line', IN, Interrupt source line in Int. Controller
* or EXCEP_DEFAULT_HANDLER for a default handler.
* 'handler', IN, Function pointer for user defined handler
* 'data', IN, Data pointer; may be NULL
* 'ref', OUT, Handle used for deregistration of handler.
*
* Return values :
* ---------------
*
* 'OK'(=0)
* 'ERROR_EXCEP_ILLEGAL_INTERRUPT': Int. source line is unknown
* 'ERROR_EXCEP_ILLEGAL_HANDLER': Handler reference is NULL
* 'ERROR_EXCEP_NO_SPACE': Too many handlers have been registered
*
************************************************************************/
INT32
EXCEP_register_ic_isr(
UINT32 ic_int_line, /* Exception identification */
t_EXCEP_isr handler, /* ISR to be registered */
void *data, /* Data reference to be registered */
t_EXCEP_ref *ref ) /* OUT : Handle for deregistration */
{
UINT32 old_ie;
t_INT_handler *h;
bool enable = FALSE;
UINT32 rc = OK;
int i;
/* Disable interrupts */
old_ie = sys_disable_int();
if( ic_int_line == EXCEP_DEFAULT_HANDLER )
{
h = &table.default_ctrl;
}
else if( ic_int_line >= excep_ic_count )
{
/* Interrupt specified is unknown */
rc = ERROR_EXCEP_ILLEGAL_INTERRUPT;
}
else
{
/* Specific interrupt */
if( handler == NULL )
{
rc = ERROR_EXCEP_ILLEGAL_HANDLER;
}
else if( table.controller[ic_int_line].list_size == CTRL_HANDLERS_PER_LINE )
{
/* Too many handlers have been registered */
rc = ERROR_EXCEP_NO_SPACE;
}
else
{
/* Find unused entry in array */
for( i = 0, h = &table.controller[ic_int_line].ctrl_handler[0];
(i < CTRL_HANDLERS_PER_LINE) && (h->handler != NULL);
i++, h++)
{
;
}
table.controller[ic_int_line].list_size++;
enable = TRUE;
}
}
if( rc == OK )
{
h->handler = handler;
h->data = data;
if( ref )
*ref = (t_EXCEP_ref)h;
/* add this source to enable mask of interrupt controller */
if( enable )
arch_excep_enable_int(ic_int_line);
}
/* Restore interrupt enable status */
if(old_ie)
sys_enable_int();
return rc;
}
/************************************************************************
*
* EXCEP_deregister_ic_isr
* Description :
* -------------
*
* Deregisters interrupt handler for source in interrupt controller
* It is OK to call this function even if we are in interrupt context.
*
* Parameters :
* ------------
*
* 'ref', IN, Handle obtained when calling EXCEP_register_ic_isr
*
* Return values :
* ---------------
*
* 'OK'(=0)
* 'ERROR_EXCEP_ILLEGAL_HANDLER': ref is unknown
*
************************************************************************/
INT32
EXCEP_deregister_ic_isr(
t_EXCEP_ref ref ) /* In : Handle for deregistration */
{
UINT32 old_ie;
t_INT_handler *h = (t_INT_handler *)ref;
t_EXCEP_ctrl_handler_list *list;
INT32 rc = ERROR_EXCEP_ILLEGAL_HANDLER;
UINT32 i, t;
/* Disable interrupts */
old_ie = sys_disable_int();
/* Find and deregister handler pointed to by ref (h) */
if( h == &table.default_ctrl )
{
h->handler = NULL;
rc = OK;
}
else
{
for( i=0; (i<MAX_IC) && (rc != OK); i++ )
{
list = &table.controller[ i ];
for( t=0; (t<CTRL_HANDLERS_PER_LINE) && (rc != OK); t++ )
{
if( &list->ctrl_handler[t] == h )
{
(list->list_size)--;
h->handler = NULL;
if( list->list_size == 0 )
{
/* Disable interrupt mask */
arch_excep_disable_int( i );
}
rc = OK;
}
}
}
}
/* Restore interrupt enable status */
if(old_ie)
sys_enable_int();
return rc;
}
/************************************************************************
*
* EXCEP_toggle_handlers
* Description :
* -------------
*
* Based on 'store' parameter, the current setup of registered
* exception handlers is stored or restored.
*
************************************************************************/
void
EXCEP_toggle_handlers(
bool store ) /* TRUE -> Store current setup, FALSE -> Restore setup */
{
UINT32 old_ie;
/* Disable interrupts */
old_ie = sys_disable_int();
if( store )
memcpy( &table_copy, &table, sizeof(t_table) );
else
memcpy( &table, &table_copy, sizeof(t_table) );
/* Restore interrupt enable status */
if(old_ie)
sys_enable_int();
}
/************************************************************************
*
* EXCEP_print_context
* Description :
* -------------
*
* Print context
*
* Note : The EXCEP module in installed before the serial drivers
* (see initmodules.h), so if an exception occurs before the serial
* drivers are installed, printf, which is used in this function, will
* not work. printf ultimately causes IO module to be called, and since
* the IO module initialises write function pointers to dummy functions,
* everything is OK.
*
* Return values :
* ---------------
*
* None
*
************************************************************************/
void
EXCEP_print_context(
t_gdb_regs *context, /* Context to print */
char *msg, /* Special msg to be printed (or NULL) */
bool user, /* In user context */
bool display ) /* TRUE -> Print EPC in ASCII display */
{
char *s;
UINT64 *regs;
UINT64 reg64;
UINT32 i,j;
bool nmi;
UINT32 werr;
if( msg )
printf( "\n* %s *\n\n", msg );
else
{
printf( "\n* Exception " );
printf( user ? "(user) : " : ": " );
}
if( SYSCON_read( SYSCON_BOARD_NMI_STATUS_ID,
(void *)&nmi,
sizeof(bool) ) != OK )
{
nmi = FALSE;
}
if( SYSCON_read( SYSCON_BOARD_NMI_WERR_ID,
(void *)&werr,
sizeof(UINT32) ) != OK )
{
werr = 0;
}
if( nmi )
{
s = werr ? "NMI - write access error" :
"NMI";
}
else
{
if( display )
DISP( (UINT32)context->cp0_epc );
s = cause_names[ REGFIELD((UINT32)context->cp0_cause, C0_CAUSE_CODE) ];
}
if( msg == NULL )
{
if( !EXCEP_ejtag )
{
if( s )
printf("%s", s);
else
printf("Unknown exception code : 0x%02x",
REGFIELD((UINT32)context->cp0_cause, C0_CAUSE_CODE) );
}
else
printf( "EJTAG" );
printf( " *\n\n" );
}
if( sys_64bit )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -