📄 excep.c
字号:
return OK; } else return ERROR_EXCEP_ILLEGAL_HANDLER;}/************************************************************************ * * EXCEP_register_cpu_isr * Description : * ------------- * * Registers an interrupt handler for the specified CPU interrupt. * The highest service priority is attached to HW-INT5, which is * connected to the CPU-built-in CP0-timer. SW_INT0 gets the lowest * service priority. During registration, the interrupt mask field * in the CPU CP0-status register is updated to enable interrupts * from the specified interrupt source. * * 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 a CPU 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 CPU interrupts must be deregistered using * EXCEP_deregister_cpu_isr. * * Parameters : * ------------ * * 'cpu_int', IN, CPU interrupt (C0_STATUS_IM_HW[0..5] | * C0_STATUS_IM_SW[0..1]) * 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': CPU interrupt source is unknown * 'ERROR_EXCEP_ILLEGAL_HANDLER': Handler reference is NULL * 'ERROR_EXCEP_NO_SPACE': Too many handlers have been registered * ************************************************************************/INT32 EXCEP_register_cpu_isr( UINT32 cpu_int, /* CPU interrupt, 0..7 */ 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 = NULL; UINT32 rc = OK; UINT32 i; bool enable = FALSE; /* Disable interrupts */ old_ie = sys_disable_int(); 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 ) { /* 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 = NULL; 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_store_handlers * Description : * ------------- * * The current setup of registered exception handlers is copied to * a table so that it may later be restored using EXCEP_set_handlers(). * ************************************************************************/void EXCEP_store_handlers( UINT32 set ) /* table where setup is copied */{ UINT32 old_ie; /* Disable interrupts */ old_ie = sys_disable_int(); switch( set ) { case EXCEP_HANDLERS_SHELL : memcpy( &table_shell, &table, sizeof(t_table) ); break; case EXCEP_HANDLERS_GDB : memcpy( &table_gdb, &table, sizeof(t_table) ); break; default : /* Should not happen */ } /* Restore interrupt enable status */ if(old_ie) sys_enable_int();}/************************************************************************ * * EXCEP_set_handlers * Description : * ------------- * * The setup of registered exception handlers is restored to the * state stored previously using EXCEP_store_handlers(). * ************************************************************************/void EXCEP_set_handlers( UINT32 set ) /* table where setup is copied */{ UINT32 old_ie; /* Disable interrupts */ old_ie = sys_disable_int(); switch( set ) { case EXCEP_HANDLERS_SHELL : memcpy( &table, &table_shell, sizeof(t_table) ); break; case EXCEP_HANDLERS_GDB : memcpy( &table, &table_gdb, sizeof(t_table) ); break; default : /* Should not happen */ } /* Restore interrupt enable status */ if(old_ie) sys_enable_int();}/************************************************************************ * * EXCEP_print_context * Description : * ------------- * * Print context * * Note : Printout is done by printf() through the IO module, so if * this routine is entered before serial drivers are installed, * no printout will take place - and no harm is done. * * Return values : * --------------- * * None * ************************************************************************/voidEXCEP_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; UINT32 werr; UINT32 shadowset; if (!context) context = EXCEP_get_context_ptr(); if( msg ) printf( "\n* %s *\n", msg ); else { printf( "\n* Exception " ); printf( user ? "(user) : " : ": " ); } if( EXCEP_nmi ) { s = "NMI"; if( SYSCON_read( SYSCON_BOARD_NMI_WERR_ID, (void *)&werr, sizeof(UINT32) ) == OK ) { if (werr != 0) { s = "NMI - write access error"; } } } else if( EXCEP_cacheerr ) { s = "CacheErr"; } else { if( display ) DISP( (UINT32)context->cp0_epc );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -