/* * Timer Service Routine * * If we are in an ISR, then this is a normal clock tick. * If we are not, then it is the test case. */ rtems_timer_service_routine test_unblock_task( rtems_id timer, void *arg ) { bool in_isr; rtems_status_code status; in_isr = rtems_interrupt_is_in_progress(); status = rtems_task_is_suspended( blocked_task_id ); if ( in_isr ) { status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL ); directive_failed( status, "timer_fire_after failed" ); return; } if ( (status != RTEMS_ALREADY_SUSPENDED) ) { status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL ); directive_failed( status, "timer_fire_after failed" ); return; } blocked_task_status = 2; _Thread_Disable_dispatch(); status = rtems_task_resume( blocked_task_id ); _Thread_Unnest_dispatch(); #if defined( RTEMS_SMP ) directive_failed_with_level( status, "rtems_task_resume", 1 ); #else directive_failed( status, "rtems_task_resume" ); #endif }
void check_isr_in_progress_inline(void) { bool in_isr; in_isr = rtems_interrupt_is_in_progress(); isr_in_progress_inline = ( in_isr ) ? 1 : 2; }
/* test bodies */ void test_interrupt_inline(void) { rtems_interrupt_level level; rtems_attribute level_attribute, level_attribute_macro; bool in_isr; puts( "interrupt is in progress (use body)" ); in_isr = rtems_interrupt_is_in_progress(); if ( in_isr ) { puts( "interrupt reported to be is in progress (body)" ); rtems_test_exit( 0 ); } puts( "interrupt disable (use inline)" ); rtems_interrupt_disable( level ); puts( "interrupt flash (use inline)" ); rtems_interrupt_flash( level ); puts( "interrupt enable (use inline)" ); rtems_interrupt_enable( level ); puts( "interrupt level attribute (use inline)" ); level_attribute = rtems_interrupt_level_attribute( level ); level_attribute_macro = RTEMS_INTERRUPT_LEVEL(level); if ( level_attribute_macro == level_attribute ) { puts( "test case working.." ); } }
rtems_status_code rtems_io_register_driver( rtems_device_major_number major, const rtems_driver_address_table *driver_table, rtems_device_major_number *registered_major ) { rtems_device_major_number major_limit = _IO_Number_of_drivers; if ( rtems_interrupt_is_in_progress() ) return RTEMS_CALLED_FROM_ISR; if ( registered_major == NULL ) return RTEMS_INVALID_ADDRESS; /* Set it to an invalid value */ *registered_major = major_limit; if ( driver_table == NULL ) return RTEMS_INVALID_ADDRESS; if ( rtems_io_is_empty_table( driver_table ) ) return RTEMS_INVALID_ADDRESS; if ( major >= major_limit ) return RTEMS_INVALID_NUMBER; _Thread_Disable_dispatch(); if ( major == 0 ) { rtems_status_code sc = rtems_io_obtain_major_number( registered_major ); if ( sc != RTEMS_SUCCESSFUL ) { _Thread_Enable_dispatch(); return sc; } major = *registered_major; } else { rtems_driver_address_table *const table = _IO_Driver_address_table + major; if ( !rtems_io_is_empty_table( table ) ) { _Thread_Enable_dispatch(); return RTEMS_RESOURCE_IN_USE; } *registered_major = major; } _IO_Driver_address_table [major] = *driver_table; _Thread_Enable_dispatch(); return rtems_io_initialize( major, 0, NULL ); }
rtems_timer_service_routine test_isr_in_progress( rtems_id timer, void *arg ) { bool in_isr; check_isr_in_progress_inline(); in_isr = rtems_interrupt_is_in_progress(); isr_in_progress_body = ( in_isr ) ? 1 : 2; }
/** * @brief Iterates over all installed interrupt handler of a vector. * * @ingroup bsp_interrupt * * @return In addition to the standard status codes this function returns * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized. * * @see rtems_interrupt_handler_iterate(). */ static rtems_status_code bsp_interrupt_handler_iterate( rtems_vector_number vector, rtems_interrupt_per_handler_routine routine, void *arg ) { rtems_status_code sc = RTEMS_SUCCESSFUL; bsp_interrupt_handler_entry *current = NULL; rtems_option options = 0; rtems_vector_number index = 0; /* Check parameters and system state */ if (!bsp_interrupt_is_initialized()) { return RTEMS_INTERNAL_ERROR; } else if (!bsp_interrupt_is_valid_vector(vector)) { return RTEMS_INVALID_ID; } else if (rtems_interrupt_is_in_progress()) { return RTEMS_CALLED_FROM_ISR; } /* Lock */ sc = bsp_interrupt_lock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } /* Interate */ index = bsp_interrupt_handler_index(vector); current = &bsp_interrupt_handler_table [index]; if (!bsp_interrupt_is_empty_handler_entry(current)) { do { options = bsp_interrupt_is_handler_unique(index) ? RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED; routine(arg, current->info, options, current->handler, current->arg); current = current->next; } while (current != NULL); } /* Unlock */ sc = bsp_interrupt_unlock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } return RTEMS_SUCCESSFUL; }
void test_interrupt_inline(void) { rtems_interrupt_level level; rtems_mode level_mode_body; rtems_mode level_mode_macro; bool in_isr; puts( "interrupt is in progress (use body)" ); in_isr = rtems_interrupt_is_in_progress(); if ( in_isr ) { puts( "interrupt reported to be is in progress (body)" ); rtems_test_exit( 0 ); } puts( "interrupt disable (use inline)" ); _Thread_Disable_dispatch(); rtems_interrupt_disable( level ); _Thread_Enable_dispatch(); puts( "interrupt flash (use inline)" ); _Thread_Disable_dispatch(); rtems_interrupt_flash( level ); _Thread_Enable_dispatch(); puts( "interrupt enable (use inline)" ); _Thread_Disable_dispatch(); rtems_interrupt_enable( level ); _Thread_Enable_dispatch(); puts( "interrupt level mode (use inline)" ); level_mode_body = rtems_interrupt_level_body( level ); level_mode_macro = RTEMS_INTERRUPT_LEVEL(level); if ( level_mode_macro == level_mode_body ) { puts( "test case working.." ); } }
rtems_task Init( rtems_task_argument argument ) { rtems_time_of_day time; rtems_status_code status; rtems_interrupt_level level; rtems_mode level_mode_body; rtems_mode level_mode_macro; bool in_isr; rtems_id timer; int i; puts( "\n\n*** TEST 37 ***" ); test_isr_level(); test_isr_locks(); test_interrupt_locks(); build_time( &time, 12, 31, 1988, 9, 0, 0, 0 ); status = rtems_clock_set( &time ); directive_failed( status, "rtems_clock_set" ); /* * Timer used in multiple ways */ status = rtems_timer_create( 1, &timer ); directive_failed( status, "rtems_timer_create" ); /* * Test clock tick from outside ISR */ status = rtems_clock_tick(); directive_failed( status, "rtems_clock_tick" ); puts( "clock_tick from task level" ); /* * Now do a dispatch directly out of a clock tick that is * called from a task. We need to create a task that will * block so we have one to unblock. Then we schedule a TSR * to run in the clock tick but it has to be careful to * make sure it is not called from an ISR and that the * dispatching critical section is managed properly to * make the dispatch happen. */ blocked_task_status = -1; status = rtems_task_create( rtems_build_name( 'T', 'A', '1', ' ' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &blocked_task_id ); directive_failed( status, "rtems_task_create" ); status = rtems_task_start( blocked_task_id, blocked_task, 0 ); directive_failed( status, "rtems_task_start" ); status = rtems_task_wake_after( 10 ); directive_failed( status, "rtems_task_wake_after" ); status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL ); directive_failed( status, "timer_fire_after failed" ); /* we expect to be preempted from this call */ for ( i=0 ; i<100 && blocked_task_status != 3 ; i++ ) { status = rtems_clock_tick(); directive_failed( status, "rtems_clock_tick" ); } switch ( blocked_task_status ) { case -1: puts( "clock_tick with task preempt -- task blocked, timer did not fire" ); rtems_test_exit(0); break; case 1: puts( "clock_tick with task preempt -- timer fired case 1" ); rtems_test_exit(0); break; case 2: puts( "clock_tick with task preempt -- timer fired case 2" ); rtems_test_exit(0); break; case 3: puts( "clock_tick from task level with preempt -- OK" ); break; } /* * Test interrupt inline versions */ test_interrupt_inline(); /* * Test interrupt bodies */ puts( "interrupt is in progress (use body)" ); in_isr = rtems_interrupt_is_in_progress(); if ( in_isr ) { puts( "interrupt reported to be is in progress (body)" ); rtems_test_exit( 0 ); } puts( "interrupt disable (use body)" ); _Thread_Disable_dispatch(); level = rtems_interrupt_disable(); _Thread_Enable_dispatch(); puts( "interrupt disable (use body)" ); _Thread_Disable_dispatch(); level = rtems_interrupt_disable(); _Thread_Enable_dispatch(); puts( "interrupt flash (use body)" ); _Thread_Disable_dispatch(); rtems_interrupt_flash( level ); _Thread_Enable_dispatch(); puts( "interrupt enable (use body)" ); _Thread_Disable_dispatch(); rtems_interrupt_enable( level ); _Thread_Enable_dispatch(); puts( "interrupt level mode (use body)" ); level_mode_body = rtems_interrupt_level_body( level ); level_mode_macro = RTEMS_INTERRUPT_LEVEL(level); if ( level_mode_macro == level_mode_body ) { puts("test seems to work"); } /* * Test ISR in progress from actual ISR */ isr_in_progress_body = -1; isr_in_progress_inline = -1; status = rtems_timer_fire_after( timer, 10, test_isr_in_progress, NULL ); directive_failed( status, "timer_fire_after failed" ); status = rtems_task_wake_after( 100 ); directive_failed( status, "wake_after failed" ); check_isr_worked( "inline", isr_in_progress_body ); check_isr_worked( "body", isr_in_progress_body ); puts( "*** END OF TEST 37 ***" ); rtems_test_exit( 0 ); }
void BSP_exceptionHandler(BSP_Exception_frame* excPtr) { uint32_t note; BSP_ExceptionExtension ext=0; rtems_id id=0; int recoverable = 0; char *fmt="Uhuuuh, Exception %d in unknown task???\n"; int quiet=0; if (!quiet) printk("In BSP_exceptionHandler()\n"); /* If we are in interrupt context, we are in trouble - skip the user * hook and panic */ if (rtems_interrupt_is_in_progress()) { fmt="Aieeh, Exception %d in interrupt handler\n"; } else if ( !_Thread_Executing) { fmt="Aieeh, Exception %d in initialization code\n"; } else { /* retrieve the notepad which possibly holds an extention pointer */ if (RTEMS_SUCCESSFUL==rtems_task_ident(RTEMS_SELF,RTEMS_LOCAL,&id) && #if 0 /* Must not use a notepad due to unknown initial value (notepad memory is allocated from the * workspace)! */ RTEMS_SUCCESSFUL==rtems_task_get_note(id, BSP_EXCEPTION_NOTEPAD, ¬e) #else RTEMS_SUCCESSFUL==rtems_task_variable_get(id, (void*)&BSP_exceptionExtension, (void**)¬e) #endif ) { ext = (BSP_ExceptionExtension)note; if (ext) quiet=ext->quiet; if (!quiet) { printk("Task (Id 0x%08x) got ",id); } fmt="exception %d\n"; } } if (ext && ext->lowlevelHook && ext->lowlevelHook(excPtr,ext,0)) { /* they did all the work and want us to do nothing! */ printk("they did all the work and want us to do nothing!\n"); return; } if (!quiet) { /* message about exception */ printk(fmt, excPtr->_EXC_number); /* register dump */ printk("\t Next PC or Address of fault = %x, ", excPtr->EXC_SRR0); printk("Mvme5500 Saved MSR = %x\n", excPtr->EXC_SRR1); printk("\t R0 = %08x", excPtr->GPR0); printk(" R1 = %08x", excPtr->GPR1); printk(" R2 = %08x", excPtr->GPR2); printk(" R3 = %08x\n", excPtr->GPR3); printk("\t R4 = %08x", excPtr->GPR4); printk(" R5 = %08x", excPtr->GPR5); printk(" R6 = %08x", excPtr->GPR6); printk(" R7 = %08x\n", excPtr->GPR7); printk("\t R8 = %08x", excPtr->GPR8); printk(" R9 = %08x", excPtr->GPR9); printk(" R10 = %08x", excPtr->GPR10); printk(" R11 = %08x\n", excPtr->GPR11); printk("\t R12 = %08x", excPtr->GPR12); printk(" R13 = %08x", excPtr->GPR13); printk(" R14 = %08x", excPtr->GPR14); printk(" R15 = %08x\n", excPtr->GPR15); printk("\t R16 = %08x", excPtr->GPR16); printk(" R17 = %08x", excPtr->GPR17); printk(" R18 = %08x", excPtr->GPR18); printk(" R19 = %08x\n", excPtr->GPR19); printk("\t R20 = %08x", excPtr->GPR20); printk(" R21 = %08x", excPtr->GPR21); printk(" R22 = %08x", excPtr->GPR22); printk(" R23 = %08x\n", excPtr->GPR23); printk("\t R24 = %08x", excPtr->GPR24); printk(" R25 = %08x", excPtr->GPR25); printk(" R26 = %08x", excPtr->GPR26); printk(" R27 = %08x\n", excPtr->GPR27); printk("\t R28 = %08x", excPtr->GPR28); printk(" R29 = %08x", excPtr->GPR29); printk(" R30 = %08x", excPtr->GPR30); printk(" R31 = %08x\n", excPtr->GPR31); printk("\t CR = %08x\n", excPtr->EXC_CR); printk("\t CTR = %08x\n", excPtr->EXC_CTR); printk("\t XER = %08x\n", excPtr->EXC_XER); printk("\t LR = %08x\n", excPtr->EXC_LR); BSP_printStackTrace(excPtr); } if (ASM_MACH_VECTOR == excPtr->_EXC_number) { /* ollah , we got a machine check - this could either * be a TEA, MCP or internal; let's see and provide more info */ if (!quiet) printk("Machine check; reason:"); if ( ! (excPtr->EXC_SRR1 & (SRR1_TEA_EXC | SRR1_MCP_EXC)) ) { if (!quiet) printk("SRR1\n"); } else { if (excPtr->EXC_SRR1 & (SRR1_TEA_EXC)) { if (!quiet) printk(" TEA"); } if (excPtr->EXC_SRR1 & (SRR1_MCP_EXC)) { unsigned long gerr; if (!quiet) printk(" MCP\n"); /* it's MCP; gather info from the host bridge */ gerr=_BSP_clear_hostbridge_errors(0,0); if (gerr&0x80000000) printk("GT64260 Parity error\n"); if (gerr&0x40000000) printk("GT64260 SysErr\n"); if ((!quiet) && (!gerr)) printk("GT64260 host bridge seems OK\n"); } } } else if (ASM_DEC_VECTOR == excPtr->_EXC_number) { recoverable = 1; } else if (ASM_SYS_VECTOR == excPtr->_EXC_number) { #ifdef TEST_RAW_EXCEPTION_CODE recoverable = 1; #else recoverable = 0; #endif } /* call them for a second time giving a chance to intercept * the task_suspend */ if (ext && ext->lowlevelHook && ext->lowlevelHook(excPtr, ext, 1)) return; if (!recoverable) { if (id) { /* if there's a highlevel hook, install it */ if (ext && ext->highlevelHook) { excPtr->EXC_SRR0 = (uint32_t)ext->highlevelHook; excPtr->GPR3 = (uint32_t)ext; return; } if (excPtr->EXC_SRR1 & MSR_FP) { /* thread dispatching is _not_ disabled at this point; hence * we must make sure we have the FPU enabled... */ _write_MSR( _read_MSR() | MSR_FP ); __asm__ __volatile__("isync"); } printk("unrecoverable exception!!! task %08x suspended\n",id); rtems_task_suspend(id); } else { printk("PANIC, rebooting...\n"); bsp_reset(); } } }
rtems_task Init( rtems_task_argument argument ) { rtems_status_code sc; rtems_device_major_number registered; rtems_device_major_number registered_not; rtems_device_major_number invalid_major = _IO_Number_of_drivers + 1; rtems_interrupt_level level; bool do_interrupt_context_test = true; TEST_BEGIN(); /* Ensure that this test works as expected */ test_interrupt_context_enter( level ); do_interrupt_context_test = rtems_interrupt_is_in_progress(); test_interrupt_context_leave( level ); /* * Register a driver with init == NULL and open != NULL */ puts( "Init - rtems_io_register_driver - init == NULL, open != NULL OK" ); sc = rtems_io_register_driver( 0, &test_driver, ®istered ); printf( "Init - Major slot returned = %d\n", (int) registered ); directive_failed( sc, "rtems_io_register_driver" ); puts( "Init - rtems_io_register_driver - init == NULL, open != NULL OK" ); sc = rtems_io_register_driver( 0, &test_driver, ®istered_not ); printf( "Init - Major slot returned = %d\n", (int) registered_not ); fatal_directive_status( sc, RTEMS_TOO_MANY, "rtems_io_register_driver too many" ); puts( "Init - rtems_io_register_driver - used slot" ); sc = rtems_io_register_driver( registered, &test_driver, ®istered_not ); fatal_directive_status( sc, RTEMS_RESOURCE_IN_USE, "rtems_io_register_driver slot in use" ); puts( "Init - rtems_io_unregister_driver - used slot" ); sc = rtems_io_unregister_driver( registered ); directive_failed( sc, "rtems_io_unregister_driver" ); puts( "Init - rtems_io_register_driver - free slot" ); sc = rtems_io_register_driver( registered, &test_driver, ®istered ); directive_failed( sc, "rtems_io_register_driver" ); puts( "Init - rtems_io_register_driver - called from interrupt context" ); if ( do_interrupt_context_test ) { test_interrupt_context_enter( level ); sc = rtems_io_register_driver( 0, NULL, NULL ); test_interrupt_context_leave( level ); fatal_directive_status( sc, RTEMS_CALLED_FROM_ISR, "rtems_io_register_driver" ); } puts( "Init - rtems_io_register_driver - invalid registered major pointer" ); sc = rtems_io_register_driver( 0, NULL, NULL ); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "rtems_io_register_driver" ); puts( "Init - rtems_io_register_driver - invalid driver table pointer" ); sc = rtems_io_register_driver( 0, NULL, ®istered ); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "rtems_io_register_driver" ); puts( "Init - rtems_io_register_driver - invalid empty driver table" ); test_driver.open_entry = NULL; sc = rtems_io_register_driver( 0, &test_driver, ®istered ); test_driver.open_entry = test_open; fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "rtems_io_register_driver" ); puts( "Init - rtems_io_register_driver - invalid major" ); sc = rtems_io_register_driver( invalid_major, &test_driver, ®istered ); fatal_directive_status( sc, RTEMS_INVALID_NUMBER, "rtems_io_register_driver" ); puts( "Init - rtems_io_unregister_driver - called from interrupt context" ); if ( do_interrupt_context_test ) { test_interrupt_context_enter( level ); sc = rtems_io_unregister_driver( 0 ); test_interrupt_context_leave( level ); fatal_directive_status( sc, RTEMS_CALLED_FROM_ISR, "rtems_io_unregister_driver" ); } puts( "Init - rtems_io_unregister_driver - invalid major number" ); sc = rtems_io_unregister_driver( invalid_major ); fatal_directive_status( sc, RTEMS_UNSATISFIED, "rtems_io_unregister_driver" ); TEST_END(); rtems_test_exit( 0 ); }
/** * @brief Removes an interrupt handler. * * @ingroup bsp_interrupt * * @return In addition to the standard status codes this function returns * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized. * * @see rtems_interrupt_handler_remove(). */ static rtems_status_code bsp_interrupt_handler_remove( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg ) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_interrupt_level level; rtems_vector_number index = 0; bsp_interrupt_handler_entry *head = NULL; bsp_interrupt_handler_entry *current = NULL; bsp_interrupt_handler_entry *previous = NULL; bsp_interrupt_handler_entry *match = NULL; /* Check parameters and system state */ if (!bsp_interrupt_is_initialized()) { return RTEMS_INTERNAL_ERROR; } else if (!bsp_interrupt_is_valid_vector(vector)) { return RTEMS_INVALID_ID; } else if (handler == NULL) { return RTEMS_INVALID_ADDRESS; } else if (rtems_interrupt_is_in_progress()) { return RTEMS_CALLED_FROM_ISR; } /* Lock */ sc = bsp_interrupt_lock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } /* Get handler table index */ index = bsp_interrupt_handler_index(vector); /* Get head entry of the handler list for current vector */ head = &bsp_interrupt_handler_table [index]; /* Search for a matching entry */ current = head; do { if (current->handler == handler && current->arg == arg) { match = current; break; } previous = current; current = current->next; } while (current != NULL); /* Remove the matching entry */ if (match != NULL) { if (match->next != NULL) { /* * The match has a successor. A successor is always * allocated. So replace the match with its successor * and free the successor entry. */ current = match->next; rtems_interrupt_disable(level); *match = *current; rtems_interrupt_enable(level); bsp_interrupt_free_handler_entry(current); } else if (match == head) { /* * The match is the list head and has no successor. * The list head is stored in a static table so clear * this entry. Since now the list is empty disable the * vector. */ /* Disable the vector */ sc = bsp_interrupt_vector_disable(vector); /* Clear entry */ rtems_interrupt_disable(level); bsp_interrupt_clear_handler_entry(head); #ifdef BSP_INTERRUPT_USE_INDEX_TABLE bsp_interrupt_handler_index_table [vector] = 0; #endif rtems_interrupt_enable(level); /* Allow shared handlers */ bsp_interrupt_set_handler_unique(index, false); /* Check status code */ if (sc != RTEMS_SUCCESSFUL) { bsp_interrupt_unlock(); return sc; } } else { /* * The match is the list tail and has a predecessor. * So terminate the predecessor and free the match. */ rtems_interrupt_disable(level); previous->next = NULL; rtems_interrupt_enable(level); bsp_interrupt_free_handler_entry(match); } } else { /* No matching entry found */ bsp_interrupt_unlock(); return RTEMS_UNSATISFIED; } /* Unlock */ sc = bsp_interrupt_unlock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } return RTEMS_SUCCESSFUL; }
/** * @brief Installs an interrupt handler. * * @ingroup bsp_interrupt * * @return In addition to the standard status codes this function returns: * - If the BSP interrupt support is not initialized RTEMS_INTERNAL_ERROR will * be returned. * - If not enough memory for a new handler is available RTEMS_NO_MEMORY will * be returned * * @see rtems_interrupt_handler_install() */ static rtems_status_code bsp_interrupt_handler_install( rtems_vector_number vector, const char *info, rtems_option options, rtems_interrupt_handler handler, void *arg ) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_interrupt_level level; rtems_vector_number index = 0; bsp_interrupt_handler_entry *head = NULL; bsp_interrupt_handler_entry *tail = NULL; bsp_interrupt_handler_entry *current = NULL; bsp_interrupt_handler_entry *match = NULL; bool enable_vector = false; /* Check parameters and system state */ if (!bsp_interrupt_is_initialized()) { return RTEMS_INTERNAL_ERROR; } else if (!bsp_interrupt_is_valid_vector(vector)) { return RTEMS_INVALID_ID; } else if (handler == NULL) { return RTEMS_INVALID_ADDRESS; } else if (rtems_interrupt_is_in_progress()) { return RTEMS_CALLED_FROM_ISR; } /* Lock */ sc = bsp_interrupt_lock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } /* Get handler table index */ index = bsp_interrupt_handler_index(vector); /* Get head entry of the handler list for current vector */ head = &bsp_interrupt_handler_table [index]; if (bsp_interrupt_is_empty_handler_entry(head)) { /* * No real handler installed yet. So allocate a new index in * the handler table and fill the entry with life. */ if (bsp_interrupt_allocate_handler_index(vector, &index)) { rtems_interrupt_disable(level); bsp_interrupt_handler_table [index].handler = handler; bsp_interrupt_handler_table [index].arg = arg; #ifdef BSP_INTERRUPT_USE_INDEX_TABLE bsp_interrupt_handler_index_table [vector] = index; #endif rtems_interrupt_enable(level); bsp_interrupt_handler_table [index].info = info; } else { /* Handler table is full */ bsp_interrupt_unlock(); return RTEMS_NO_MEMORY; } /* This is the first handler so enable the vector later */ enable_vector = true; } else { /* Ensure that a unique handler remains unique */ if ( RTEMS_INTERRUPT_IS_UNIQUE(options) || bsp_interrupt_is_handler_unique(index) ) { /* * Tried to install a unique handler on a not empty * list or there is already a unique handler installed. */ bsp_interrupt_unlock(); return RTEMS_RESOURCE_IN_USE; } /* * Search for the list tail and check if the handler is already * installed. */ current = head; do { if (current->handler == handler && current->arg == arg) { match = current; } tail = current; current = current->next; } while (current != NULL); /* Ensure the handler is not already installed */ if (match != NULL) { /* The handler is already installed */ bsp_interrupt_unlock(); return RTEMS_TOO_MANY; } /* Allocate a new entry */ current = bsp_interrupt_allocate_handler_entry(); if (current == NULL) { /* Not enough memory */ bsp_interrupt_unlock(); return RTEMS_NO_MEMORY; } /* Set entry */ current->handler = handler; current->arg = arg; current->info = info; current->next = NULL; /* Link to list tail */ rtems_interrupt_disable(level); tail->next = current; rtems_interrupt_enable(level); } /* Make the handler unique if necessary */ bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options)); /* Enable the vector if necessary */ if (enable_vector) { sc = bsp_interrupt_vector_enable(vector); if (sc != RTEMS_SUCCESSFUL) { bsp_interrupt_unlock(); return sc; } } /* Unlock */ sc = bsp_interrupt_unlock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } return RTEMS_SUCCESSFUL; }
rtems_status_code rtems_io_register_driver( rtems_device_major_number major, const rtems_driver_address_table *driver_table, rtems_device_major_number *registered_major ) { rtems_device_major_number major_limit = _IO_Number_of_drivers; if ( rtems_interrupt_is_in_progress() ) return RTEMS_CALLED_FROM_ISR; if ( registered_major == NULL ) return RTEMS_INVALID_ADDRESS; /* Set it to an invalid value */ *registered_major = major_limit; if ( driver_table == NULL ) return RTEMS_INVALID_ADDRESS; if ( rtems_io_is_empty_table( driver_table ) ) return RTEMS_INVALID_ADDRESS; if ( major >= major_limit ) return RTEMS_INVALID_NUMBER; _Thread_Disable_dispatch(); if ( major == 0 ) { rtems_status_code sc = rtems_io_obtain_major_number( registered_major ); if ( sc != RTEMS_SUCCESSFUL ) { _Thread_Enable_dispatch(); return sc; } major = *registered_major; } else { rtems_driver_address_table *const table = _IO_Driver_address_table + major; if ( !rtems_io_is_empty_table( table ) ) { _Thread_Enable_dispatch(); return RTEMS_RESOURCE_IN_USE; } *registered_major = major; } _IO_Driver_address_table [major] = *driver_table; _Thread_Enable_dispatch(); if ( _IO_All_drivers_initialized ) { /* Other drivers have already been initialized, we initialize * the driver directly. */ return rtems_io_initialize( major, 0, NULL ); } else { /* The driver will be initialized together with all other drivers * in a later stage by _IO_Initialize_all_drivers(). */ return RTEMS_SUCCESSFUL; } }
void C_exception_handler(BSP_Exception_frame *excPtr) { static int nest = 0; int recoverable = 0; rtems_id id = 0; int synch; unsigned n; rtems_status_code sc; /* Catch recursion */ nest++; if (nest > 2) { /* maybe printk() or dereferencing excPtr caused an exception; * die silently... */ while (1); } synch = (int) excPtr->_EXC_number >= 0; n = excPtr->_EXC_number & 0x7fff; printk("Exception handler called for exception %d (0x%x)\n", n, n); printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0); printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1); if (nest > 1) { printk("Recursion in the exception handler detected; I'll spin now...\n"); while (1); } /* Try to find out more about the context where this happened */ printk("\t Context: "); if (rtems_interrupt_is_in_progress()) { printk("ISR"); } else if (!_Thread_Executing) { printk("Initialization (_Thread_Executing not available yet)"); } else { if (RTEMS_SUCCESSFUL != (sc = rtems_task_ident(RTEMS_SELF, RTEMS_LOCAL, &id))) { printk("Unable to determine faulting task; rtems_task_ident() returned %u", sc); id = 0; } else { printk("Task ID 0x%08x", id); } } printk("\n"); /* Dump registers */ printk("\t R0 = %08x", GET_GPR(excPtr->GPR0)); if (synch) { printk(" R1 = %08x", GET_GPR(excPtr->GPR1)); printk(" R2 = %08x", GET_GPR(excPtr->GPR2)); } else { printk(" "); printk(" "); } printk(" R3 = %08x\n", GET_GPR(excPtr->GPR3)); printk("\t R4 = %08x", GET_GPR(excPtr->GPR4)); printk(" R5 = %08x", GET_GPR(excPtr->GPR5)); printk(" R6 = %08x", GET_GPR(excPtr->GPR6)); printk(" R7 = %08x\n", GET_GPR(excPtr->GPR7)); printk("\t R8 = %08x", GET_GPR(excPtr->GPR8)); printk(" R9 = %08x", GET_GPR(excPtr->GPR9)); printk(" R10 = %08x", GET_GPR(excPtr->GPR10)); printk(" R11 = %08x\n", GET_GPR(excPtr->GPR11)); printk("\t R12 = %08x", GET_GPR(excPtr->GPR12)); if (synch) { printk(" R13 = %08x", GET_GPR(excPtr->GPR13)); printk(" R14 = %08x", GET_GPR(excPtr->GPR14)); printk(" R15 = %08x\n", GET_GPR(excPtr->GPR15)); printk("\t R16 = %08x", GET_GPR(excPtr->GPR16)); printk(" R17 = %08x", GET_GPR(excPtr->GPR17)); printk(" R18 = %08x", GET_GPR(excPtr->GPR18)); printk(" R19 = %08x\n", GET_GPR(excPtr->GPR19)); printk("\t R20 = %08x", GET_GPR(excPtr->GPR20)); printk(" R21 = %08x", GET_GPR(excPtr->GPR21)); printk(" R22 = %08x", GET_GPR(excPtr->GPR22)); printk(" R23 = %08x\n", GET_GPR(excPtr->GPR23)); printk("\t R24 = %08x", GET_GPR(excPtr->GPR24)); printk(" R25 = %08x", GET_GPR(excPtr->GPR25)); printk(" R26 = %08x", GET_GPR(excPtr->GPR26)); printk(" R27 = %08x\n", GET_GPR(excPtr->GPR27)); printk("\t R28 = %08x", GET_GPR(excPtr->GPR28)); printk(" R29 = %08x", GET_GPR(excPtr->GPR29)); printk(" R30 = %08x", GET_GPR(excPtr->GPR30)); printk(" R31 = %08x\n", GET_GPR(excPtr->GPR31)); } else { printk("\n"); } printk("\t CR = %08x\n", excPtr->EXC_CR); printk("\t CTR = %08x\n", excPtr->EXC_CTR); printk("\t XER = %08x\n", excPtr->EXC_XER); printk("\t LR = %08x\n", excPtr->EXC_LR); /* Would be great to print DAR but unfortunately, * that is not portable across different CPUs. * AFAIK on classic PPC DAR is SPR 19, on the * 405 we have DEAR = SPR 0x3d5 and booE says * DEAR = SPR 61 :-( */ if (ppc_exc_get_DAR) { printk("\t DAR = %08x\n", ppc_exc_get_DAR()); } BSP_printStackTrace(excPtr); if (excPtr->_EXC_number == ASM_DEC_VECTOR) recoverable = 1; if (excPtr->_EXC_number == ASM_SYS_VECTOR) #ifdef TEST_RAW_EXCEPTION_CODE recoverable = 1; #else recoverable = 0; #endif if (!recoverable) { if (id) { printk("Suspending faulting task (0x%08x)\n", id); /* Unnest here because rtems_task_suspend() never returns */ nest--; rtems_task_suspend(id); } else { printk("unrecoverable exception!!! Push reset button\n"); while (1); } } else { nest--; } }