From 97005786d89fd7a57b5fe82f713cea739916f3da Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 30 Oct 1995 21:54:45 +0000 Subject: SPARC port passes all tests --- c/ACKNOWLEDGEMENTS | 3 +- c/src/exec/libcsupport/include/ringbuf.h | 25 +- c/src/exec/posix/headers/intr.h | 3 +- c/src/exec/posix/include/rtems/posix/intr.h | 3 +- c/src/exec/rtems/src/event.c | 202 +++++ c/src/exec/score/cpu/hppa1.1/cpu.h | 10 +- c/src/exec/score/cpu/i386/cpu.h | 10 +- c/src/exec/score/cpu/i960/cpu.h | 10 +- c/src/exec/score/cpu/m68k/cpu.h | 12 +- c/src/exec/score/cpu/m68k/cpu_asm.s | 3 - c/src/exec/score/cpu/no_cpu/cpu.h | 26 +- c/src/exec/score/cpu/powerpc/cpu.h | 14 +- c/src/exec/score/cpu/sparc/README | 118 +++ c/src/exec/score/cpu/sparc/asm.h | 16 +- c/src/exec/score/cpu/sparc/cpu.c | 370 ++++++--- c/src/exec/score/cpu/sparc/cpu.h | 674 ++++++++-------- c/src/exec/score/cpu/sparc/cpu_asm.s | 881 +++++++++++++++------ c/src/exec/score/cpu/sparc/erc32.h | 503 ++++++++++++ c/src/exec/score/cpu/sparc/rtems.s | 16 +- c/src/exec/score/cpu/sparc/sparc.h | 150 +++- c/src/exec/score/cpu/sparc/sparctypes.h | 26 +- c/src/exec/score/cpu/unix/cpu.c | 52 +- c/src/exec/score/cpu/unix/cpu.h | 49 +- c/src/exec/score/headers/bitfield.h | 49 ++ c/src/exec/score/headers/context.h | 5 +- c/src/exec/score/headers/isr.h | 15 +- c/src/exec/score/headers/priority.h | 45 ++ c/src/exec/score/include/rtems/score/bitfield.h | 49 ++ c/src/exec/score/include/rtems/score/context.h | 5 +- c/src/exec/score/include/rtems/score/isr.h | 15 +- c/src/exec/score/include/rtems/score/priority.h | 45 ++ c/src/exec/score/inline/isr.inl | 2 +- c/src/exec/score/inline/priority.inl | 41 +- c/src/exec/score/inline/rtems/score/isr.inl | 2 +- c/src/exec/score/inline/rtems/score/priority.inl | 41 +- c/src/exec/score/macros/isr.inl | 2 +- c/src/exec/score/macros/priority.inl | 32 +- c/src/exec/score/macros/rtems/score/isr.inl | 2 +- c/src/exec/score/macros/rtems/score/priority.inl | 32 +- c/src/exec/score/src/thread.c | 6 +- c/src/lib/include/ringbuf.h | 25 +- .../lib/libbsp/hppa1.1/simhppa/startup/bspstart.c | 31 +- c/src/lib/libbsp/i386/force386/clock/ckinit.c | 16 +- c/src/lib/libbsp/i386/force386/startup/bspstart.c | 11 +- c/src/lib/libbsp/i386/go32/clock/ckinit.c | 16 +- c/src/lib/libbsp/i386/go32/startup/bspstart.c | 11 +- c/src/lib/libbsp/i960/cvme961/clock/ckinit.c | 12 +- c/src/lib/libbsp/i960/cvme961/startup/bspstart.c | 11 +- c/src/lib/libbsp/m68k/dmv152/clock/ckinit.c | 16 +- c/src/lib/libbsp/m68k/dmv152/startup/bspstart.c | 11 +- c/src/lib/libbsp/m68k/efi332/clock/ckinit.c | 16 +- c/src/lib/libbsp/m68k/efi332/startup/bspstart.c | 11 +- c/src/lib/libbsp/m68k/efi68k/clock/ckinit.c | 16 +- c/src/lib/libbsp/m68k/efi68k/startup/bspstart.c | 11 +- c/src/lib/libbsp/m68k/gen68302/clock/ckinit.c | 18 +- c/src/lib/libbsp/m68k/gen68302/start/start302.s | 9 - c/src/lib/libbsp/m68k/gen68302/start302/start302.s | 9 - c/src/lib/libbsp/m68k/gen68302/startup/bspstart.c | 11 +- c/src/lib/libbsp/m68k/idp/clock/ckinit.c | 15 +- c/src/lib/libbsp/m68k/idp/console/duart.c | 6 +- c/src/lib/libbsp/m68k/idp/startup/bspstart.c | 11 +- c/src/lib/libbsp/m68k/mvme136/clock/ckinit.c | 16 +- c/src/lib/libbsp/m68k/mvme136/startup/bspstart.c | 13 +- c/src/lib/libbsp/m68k/mvme162/clock/ckinit.c | 14 +- c/src/lib/libbsp/m68k/mvme162/startup/bspstart.c | 11 +- c/src/lib/libbsp/no_cpu/no_bsp/clock/ckinit.c | 31 +- c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c | 11 +- .../lib/libbsp/powerpc/papyrus/startup/bspstart.c | 11 +- c/src/lib/libbsp/unix/posix/clock/clock.c | 31 +- c/src/lib/libbsp/unix/posix/startup/bspstart.c | 11 +- c/src/lib/libcpu/sparc/include/erc32.h | 503 ++++++++++++ c/src/tests/sptests/sp04/task1.c | 10 +- c/src/tests/sptests/sp09/screen09.c | 6 +- c/src/tests/sptests/sp11/sp11.scn | 2 +- c/src/tests/sptests/sp11/task2.c | 6 +- c/src/tests/sptests/sp12/system.h | 1 + c/src/tests/sptests/sp19/system.h | 2 + c/src/tests/sptests/sp20/init.c | 2 +- c/src/tests/sptests/sp24/init.c | 2 +- c/src/tests/sptests/spsize/init.c | 7 +- c/src/tests/sptests/spsize/size.c | 27 +- c/src/tests/tmtests/tm08/task1.c | 2 +- c/src/tests/tmtests/tm27/task1.c | 47 +- cpukit/libcsupport/include/ringbuf.h | 25 +- cpukit/posix/include/rtems/posix/intr.h | 3 +- cpukit/rtems/src/event.c | 202 +++++ cpukit/score/cpu/sparc/README | 118 +++ cpukit/score/cpu/sparc/asm.h | 16 +- cpukit/score/cpu/sparc/cpu.c | 370 ++++++--- cpukit/score/cpu/sparc/rtems/asm.h | 16 +- cpukit/score/cpu/unix/cpu.c | 52 +- cpukit/score/include/rtems/score/bitfield.h | 49 ++ cpukit/score/include/rtems/score/context.h | 5 +- cpukit/score/include/rtems/score/isr.h | 15 +- cpukit/score/include/rtems/score/priority.h | 45 ++ cpukit/score/inline/rtems/score/isr.inl | 2 +- cpukit/score/inline/rtems/score/priority.inl | 41 +- cpukit/score/macros/rtems/score/isr.inl | 2 +- cpukit/score/macros/rtems/score/priority.inl | 32 +- cpukit/score/src/thread.c | 6 +- testsuites/sptests/sp04/task1.c | 10 +- testsuites/sptests/sp09/screen09.c | 6 +- testsuites/sptests/sp11/sp11.scn | 2 +- testsuites/sptests/sp11/task2.c | 6 +- testsuites/sptests/sp12/system.h | 1 + testsuites/sptests/sp19/system.h | 2 + testsuites/sptests/sp20/init.c | 2 +- testsuites/sptests/sp24/init.c | 2 +- testsuites/sptests/spsize/init.c | 7 +- testsuites/sptests/spsize/size.c | 27 +- testsuites/tmtests/tm08/task1.c | 2 +- testsuites/tmtests/tm27/task1.c | 47 +- 112 files changed, 4366 insertions(+), 1370 deletions(-) create mode 100644 c/src/exec/score/cpu/sparc/README create mode 100644 c/src/exec/score/cpu/sparc/erc32.h create mode 100644 c/src/lib/libcpu/sparc/include/erc32.h create mode 100644 cpukit/score/cpu/sparc/README diff --git a/c/ACKNOWLEDGEMENTS b/c/ACKNOWLEDGEMENTS index bee6d1d526..9e6f885acb 100644 --- a/c/ACKNOWLEDGEMENTS +++ b/c/ACKNOWLEDGEMENTS @@ -68,7 +68,8 @@ The following persons/organizations have made contributions: to port RTEMS to the SPARC V7 architecture for use with their ERC32 radiation-hardened CPU. Jiri Gaisler (jgais@wd.estec.esa.nl) deserves special thanks for championing this port within the ESA was well as - for developing the SPARC Instruction Simulator used to test this port. + for developing and supporting the SPARC Instruction Simulator used to + develop and test this port. Finally, the RTEMS project would like to thank those who have contributed to the other free software efforts which RTEMS utilizes. The primary RTEMS diff --git a/c/src/exec/libcsupport/include/ringbuf.h b/c/src/exec/libcsupport/include/ringbuf.h index b2494c1527..8c80aaf9c8 100644 --- a/c/src/exec/libcsupport/include/ringbuf.h +++ b/c/src/exec/libcsupport/include/ringbuf.h @@ -10,13 +10,13 @@ #define __RINGBUF_H__ #ifndef RINGBUF_QUEUE_LENGTH -#define RINGBUF_QUEUE_LENGTH 200 +#define RINGBUF_QUEUE_LENGTH 128 #endif typedef struct { char buffer[RINGBUF_QUEUE_LENGTH]; - int head; - int tail; + volatile int head; + volatile int tail; } Ring_buffer_t; #define Ring_buffer_Initialize( _buffer ) \ @@ -27,16 +27,27 @@ typedef struct { #define Ring_buffer_Is_empty( _buffer ) \ ( (_buffer)->head == (_buffer)->tail ) +#define Ring_buffer_Is_full( _buffer ) \ + ( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH ) + #define Ring_buffer_Add_character( _buffer, _ch ) \ do { \ - (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \ - (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \ + rtems_unsigned32 isrlevel; \ + \ + rtems_interrupt_disable( isrlevel ); \ + (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \ + (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \ + rtems_interrupt_enable( isrlevel ); \ } while ( 0 ) #define Ring_buffer_Remove_character( _buffer, _ch ) \ do { \ - (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \ - (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \ + rtems_unsigned32 isrlevel; \ + \ + rtems_interrupt_disable( isrlevel ); \ + (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \ + (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \ + rtems_interrupt_enable( isrlevel ); \ } while ( 0 ) #endif diff --git a/c/src/exec/posix/headers/intr.h b/c/src/exec/posix/headers/intr.h index b940148999..ae1690f676 100644 --- a/c/src/exec/posix/headers/intr.h +++ b/c/src/exec/posix/headers/intr.h @@ -60,8 +60,7 @@ EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information; * interrupt handlers installed on each vector. */ -EXTERN POSIX_Interrupt_Control - _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ]; +EXTERN POSIX_Interrupt_Control _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ]; /* * _POSIX_Interrupt_Manager_initialization diff --git a/c/src/exec/posix/include/rtems/posix/intr.h b/c/src/exec/posix/include/rtems/posix/intr.h index b940148999..ae1690f676 100644 --- a/c/src/exec/posix/include/rtems/posix/intr.h +++ b/c/src/exec/posix/include/rtems/posix/intr.h @@ -60,8 +60,7 @@ EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information; * interrupt handlers installed on each vector. */ -EXTERN POSIX_Interrupt_Control - _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ]; +EXTERN POSIX_Interrupt_Control _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ]; /* * _POSIX_Interrupt_Manager_initialization diff --git a/c/src/exec/rtems/src/event.c b/c/src/exec/rtems/src/event.c index 2786d6b8dc..101162bec6 100644 --- a/c/src/exec/rtems/src/event.c +++ b/c/src/exec/rtems/src/event.c @@ -108,3 +108,205 @@ rtems_status_code rtems_event_receive( _Thread_Enable_dispatch(); return( _Thread_Executing->Wait.return_code ); } + + +/*PAGE + * + * _Event_Seize + * + * This routine attempts to satisfy the requested event condition + * for the running thread. + * + * Input parameters: + * event_in - the event condition to satisfy + * option_set - acquire event options + * ticks - interval to wait + * event_out - pointer to event set output area + * + * Output parameters: NONE + * *event_out - event set output area filled in + * + * INTERRUPT LATENCY: + * available + * wait + * check sync + */ + +void _Event_Seize( + rtems_event_set event_in, + rtems_option option_set, + rtems_interval ticks, + rtems_event_set *event_out +) +{ + Thread_Control *executing; + rtems_event_set seized_events; + rtems_event_set pending_events; + ISR_Level level; + RTEMS_API_Control *api; + + executing = _Thread_Executing; + executing->Wait.return_code = RTEMS_SUCCESSFUL; + + api = executing->API_Extensions[ THREAD_API_RTEMS ]; + + _ISR_Disable( level ); + pending_events = api->pending_events; + seized_events = _Event_sets_Get( pending_events, event_in ); + + if ( !_Event_sets_Is_empty( seized_events ) && + (seized_events == event_in || _Options_Is_any( option_set )) ) { + api->pending_events = + _Event_sets_Clear( pending_events, seized_events ); + _ISR_Enable( level ); + *event_out = seized_events; + return; + } + + if ( _Options_Is_no_wait( option_set ) ) { + _ISR_Enable( level ); + executing->Wait.return_code = RTEMS_UNSATISFIED; + *event_out = seized_events; + return; + } + + _Event_Sync = TRUE; + executing->Wait.option = (unsigned32) option_set; + executing->Wait.count = (unsigned32) event_in; + executing->Wait.return_argument = event_out; + + _ISR_Enable( level ); + _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT ); + + if ( ticks ) { + _Watchdog_Initialize( + &executing->Timer, + _Event_Timeout, + executing->Object.id, + NULL + ); + _Watchdog_Insert_ticks( + &executing->Timer, + ticks, + WATCHDOG_NO_ACTIVATE + ); + } + + _ISR_Disable( level ); + if ( _Event_Sync == TRUE ) { + _Event_Sync = FALSE; + if ( ticks ) + _Watchdog_Activate( &executing->Timer ); + _ISR_Enable( level ); + return; + } + _ISR_Enable( level ); + (void) _Watchdog_Remove( &executing->Timer ); + _Thread_Unblock( executing ); + return; +} + +/*PAGE + * + * _Event_Surrender + * + * This routines remove a thread from the specified threadq. + * + * Input parameters: + * the_thread - pointer to thread to be dequeued + * + * Output parameters: NONE + * + * INTERRUPT LATENCY: + * before flash + * after flash + * check sync + */ + +void _Event_Surrender( + Thread_Control *the_thread +) +{ + ISR_Level level; + rtems_event_set pending_events; + rtems_event_set event_condition; + rtems_event_set seized_events; + rtems_option option_set; + RTEMS_API_Control *api; + + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + + option_set = (rtems_option) the_thread->Wait.option; + + _ISR_Disable( level ); + pending_events = api->pending_events; + event_condition = (rtems_event_set) the_thread->Wait.count; + + seized_events = _Event_sets_Get( pending_events, event_condition ); + + if ( !_Event_sets_Is_empty( seized_events ) ) { + if ( _States_Is_waiting_for_event( the_thread->current_state ) ) { + if ( seized_events == event_condition || _Options_Is_any( option_set ) ) { + api->pending_events = + _Event_sets_Clear( pending_events, seized_events ); + *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; + + _ISR_Flash( level ); + + if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { + _ISR_Enable( level ); + _Thread_Unblock( the_thread ); + } + else { + _Watchdog_Deactivate( &the_thread->Timer ); + _ISR_Enable( level ); + (void) _Watchdog_Remove( &the_thread->Timer ); + _Thread_Unblock( the_thread ); + } + return; + } + } + else if ( _Thread_Is_executing( the_thread ) && _Event_Sync == TRUE ) { + if ( seized_events == event_condition || _Options_Is_any( option_set ) ) { + api->pending_events = _Event_sets_Clear( pending_events,seized_events ); + *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; + _Event_Sync = FALSE; + } + } + } + _ISR_Enable( level ); +} + +/*PAGE + * + * _Event_Timeout + * + * This routine processes a thread which timeouts while waiting to + * receive an event_set. It is called by the watchdog handler. + * + * Input parameters: + * id - thread id + * + * Output parameters: NONE + */ + +void _Event_Timeout( + Objects_Id id, + void *ignored +) +{ + Thread_Control *the_thread; + Objects_Locations location; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + case OBJECTS_ERROR: + case OBJECTS_REMOTE: /* impossible */ + break; + case OBJECTS_LOCAL: + the_thread->Wait.return_code = RTEMS_TIMEOUT; + _Thread_Unblock( the_thread ); + _Thread_Unnest_dispatch(); + break; + } +} diff --git a/c/src/exec/score/cpu/hppa1.1/cpu.h b/c/src/exec/score/cpu/hppa1.1/cpu.h index 67e7f5b89c..87be960606 100644 --- a/c/src/exec/score/cpu/hppa1.1/cpu.h +++ b/c/src/exec/score/cpu/hppa1.1/cpu.h @@ -278,7 +278,8 @@ EXTERN void *_CPU_Interrupt_stack_high; * interrupts (genie, rhino, etc) */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS (HPPA_INTERRUPT_MAX) +#define CPU_INTERRUPT_NUMBER_OF_VECTORS (HPPA_INTERRUPT_MAX) +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Don't be chintzy here; we don't want to debug these problems @@ -387,7 +388,7 @@ unsigned32 _CPU_ISR_Get_level( void ); */ #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ - _new_level, _entry_point ) \ + _new_level, _entry_point, _is_fp ) \ do { \ unsigned32 _stack; \ \ @@ -456,6 +457,9 @@ void hppa_cpu_halt(unsigned32 type_of_halt, unsigned32 the_error); * is implemented in software. */ +#define CPU_USE_GENERIC_BITFIELD_CODE FALSE +#define CPU_USE_GENERIC_BITFIELD_DATA FALSE + int hppa_rtems_ffs(unsigned int value); #define _CPU_Bitfield_Find_first_bit( _value, _output ) \ _output = hppa_rtems_ffs(_value) @@ -477,7 +481,7 @@ int hppa_rtems_ffs(unsigned int value); #define _CPU_Priority_Mask( _bit_number ) \ ( 1 << (_bit_number) ) -#define _CPU_Priority_Bits_index( _priority ) \ +#define _CPU_Priority_bits_index( _priority ) \ (_priority) /* end of Priority handler macros */ diff --git a/c/src/exec/score/cpu/i386/cpu.h b/c/src/exec/score/cpu/i386/cpu.h index 2ac3b1970c..a13040ad79 100644 --- a/c/src/exec/score/cpu/i386/cpu.h +++ b/c/src/exec/score/cpu/i386/cpu.h @@ -143,7 +143,8 @@ EXTERN void *_CPU_Interrupt_stack_high; * i386 family supports 256 distinct vectors. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Minimum size of a thread's stack. @@ -208,7 +209,7 @@ unsigned32 _CPU_ISR_Get_level( void ); #define CPU_EFLAGS_INTERRUPTS_OFF 0x00003002 #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ - _isr, _entry_point ) \ + _isr, _entry_point, _is_fp ) \ do { \ unsigned32 _stack; \ \ @@ -265,6 +266,9 @@ unsigned32 _CPU_ISR_Get_level( void ); * + scan for the highest numbered (MSB) set in a 16 bit bitfield */ +#define CPU_USE_GENERIC_BITFIELD_CODE FALSE +#define CPU_USE_GENERIC_BITFIELD_DATA FALSE + #define _CPU_Bitfield_Find_first_bit( _value, _output ) \ { \ register unsigned16 __value_in_register = (_value); \ @@ -292,7 +296,7 @@ unsigned32 _CPU_ISR_Get_level( void ); #define _CPU_Priority_Mask( _bit_number ) \ ( 1 << (_bit_number) ) -#define _CPU_Priority_Bits_index( _priority ) \ +#define _CPU_Priority_bits_index( _priority ) \ (_priority) /* functions */ diff --git a/c/src/exec/score/cpu/i960/cpu.h b/c/src/exec/score/cpu/i960/cpu.h index 4ec7547e2d..f08fa694b8 100644 --- a/c/src/exec/score/cpu/i960/cpu.h +++ b/c/src/exec/score/cpu/i960/cpu.h @@ -185,7 +185,8 @@ EXTERN void *_CPU_Interrupt_stack_high; * i960 family supports 256 distinct vectors. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Minimum size of a thread's stack. @@ -252,7 +253,7 @@ unsigned32 _CPU_ISR_Get_level( void ); */ #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ - _isr, _entry ) \ + _isr, _entry, _is_fp ) \ { CPU_Call_frame *_texit_frame; \ unsigned32 _mask; \ unsigned32 _base_pc; \ @@ -318,6 +319,9 @@ unsigned32 _CPU_ISR_Get_level( void ); * + scan for the highest numbered (MSB) set in a 16 bit bitfield */ +#define CPU_USE_GENERIC_BITFIELD_CODE FALSE +#define CPU_USE_GENERIC_BITFIELD_DATA FALSE + #define _CPU_Bitfield_Find_first_bit( _value, _output ) \ { unsigned32 _search = (_value); \ \ @@ -341,7 +345,7 @@ unsigned32 _CPU_ISR_Get_level( void ); #define _CPU_Priority_Mask( _bit_number ) \ ( 0x8000 >> (_bit_number) ) -#define _CPU_Priority_Bits_index( _priority ) \ +#define _CPU_Priority_bits_index( _priority ) \ ( 15 - (_priority) ) /* end of Priority handler macros */ diff --git a/c/src/exec/score/cpu/m68k/cpu.h b/c/src/exec/score/cpu/m68k/cpu.h index da62255987..6eb3aac708 100644 --- a/c/src/exec/score/cpu/m68k/cpu.h +++ b/c/src/exec/score/cpu/m68k/cpu.h @@ -175,7 +175,8 @@ extern char _VBR[]; * m68k family supports 256 distinct vectors. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Minimum size of a thread's stack. @@ -237,7 +238,7 @@ unsigned32 _CPU_ISR_Get_level( void ); */ #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ - _isr, _entry_point ) \ + _isr, _entry_point, _is_fp ) \ do { \ void *_stack; \ \ @@ -301,6 +302,9 @@ unsigned32 _CPU_ISR_Get_level( void ); * have a real 16 bit wide bitfield which operates "correctly." */ +#define CPU_USE_GENERIC_BITFIELD_CODE FALSE +#define CPU_USE_GENERIC_BITFIELD_DATA FALSE + #if ( M68K_HAS_BFFFO == 1 ) #ifdef NO_UNINITIALIZED_WARNINGS @@ -327,7 +331,7 @@ unsigned32 _CPU_ISR_Get_level( void ); #else /* duplicates BFFFO results for 16 bits (i.e., 15-(_priority) in - _CPU_Priority_Bits_index is not needed), handles the 0 case, and + _CPU_Priority_bits_index is not needed), handles the 0 case, and does not molest _value -- jsg */ #ifndef m68000 #define _CPU_Bitfield_Find_first_bit( _value, _output ) \ @@ -386,7 +390,7 @@ unsigned32 _CPU_ISR_Get_level( void ); #define _CPU_Priority_Mask( _bit_number ) \ ( 0x8000 >> (_bit_number) ) -#define _CPU_Priority_Bits_index( _priority ) \ +#define _CPU_Priority_bits_index( _priority ) \ (_priority) /* end of Priority handler macros */ diff --git a/c/src/exec/score/cpu/m68k/cpu_asm.s b/c/src/exec/score/cpu/m68k/cpu_asm.s index fb8ba678b2..8cce6e5ca5 100644 --- a/c/src/exec/score/cpu/m68k/cpu_asm.s +++ b/c/src/exec/score/cpu/m68k/cpu_asm.s @@ -174,9 +174,6 @@ SYM (_ISR_Handler): * in place to know what vector we got on a 68000 core. */ - .global SYM (_ISR_Exit) -SYM (_ISR_Exit): - subql #1,SYM (_ISR_Nest_level) | one less nest level subql #1,SYM (_Thread_Dispatch_disable_level) | unnest multitasking diff --git a/c/src/exec/score/cpu/no_cpu/cpu.h b/c/src/exec/score/cpu/no_cpu/cpu.h index eabe7ba2a0..cda536249d 100644 --- a/c/src/exec/score/cpu/no_cpu/cpu.h +++ b/c/src/exec/score/cpu/no_cpu/cpu.h @@ -412,7 +412,8 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * by RTEMS. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32 +#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32 +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Should be large enough to run all RTEMS tests. This insures @@ -536,7 +537,7 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); */ #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ - _isr, _entry_point ) \ + _isr, _entry_point, _is_fp ) \ { \ } @@ -621,11 +622,11 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * * RTEMS guarantees that (1) will never happen so it is not a concern. * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and - * _CPU_Priority_Bits_index(). These three form a set of routines + * _CPU_Priority_bits_index(). These three form a set of routines * which must logically operate together. Bits in the _value are * set and cleared based on masks built by _CPU_Priority_mask(). * The basic major and minor values calculated by _Priority_Major() - * and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index() + * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index() * to properly range between the values returned by the "find first bit" * instruction. This makes it possible for _Priority_Get_highest() to * calculate the major and directly index into the minor table. @@ -660,11 +661,18 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * bit set */ +#define CPU_USE_GENERIC_BITFIELD_CODE TRUE +#define CPU_USE_GENERIC_BITFIELD_DATA TRUE + +#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) + #define _CPU_Bitfield_Find_first_bit( _value, _output ) \ { \ (_output) = 0; /* do something to prevent warnings */ \ } +#endif + /* end of Bitfield handler macros */ /* @@ -673,9 +681,13 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * for that routine. */ +#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) + #define _CPU_Priority_Mask( _bit_number ) \ ( 1 << (_bit_number) ) +#endif + /* * This routine translates the bit numbers returned by * _CPU_Bitfield_Find_first_bit() into something suitable for use as @@ -683,9 +695,13 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * for that routine. */ -#define _CPU_Priority_Bits_index( _priority ) \ +#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) + +#define _CPU_Priority_bits_index( _priority ) \ (_priority) +#endif + /* end of Priority handler macros */ /* functions */ diff --git a/c/src/exec/score/cpu/powerpc/cpu.h b/c/src/exec/score/cpu/powerpc/cpu.h index 99673952a3..8bbc341268 100644 --- a/c/src/exec/score/cpu/powerpc/cpu.h +++ b/c/src/exec/score/cpu/powerpc/cpu.h @@ -541,7 +541,8 @@ EXTERN struct { * by RTEMS. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX) +#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX) +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Should be large enough to run all RTEMS tests. This insures @@ -682,7 +683,7 @@ EXTERN struct { #if PPC_ABI == PPC_ABI_POWEROPEN #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ - _isr, _entry_point ) \ + _isr, _entry_point, _is_fp ) \ { \ unsigned32 sp, *desc; \ \ @@ -816,11 +817,11 @@ EXTERN struct { * * RTEMS guarantees that (1) will never happen so it is not a concern. * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and - * _CPU_Priority_Bits_index(). These three form a set of routines + * _CPU_Priority_bits_index(). These three form a set of routines * which must logically operate together. Bits in the _value are * set and cleared based on masks built by _CPU_Priority_mask(). * The basic major and minor values calculated by _Priority_Major() - * and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index() + * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index() * to properly range between the values returned by the "find first bit" * instruction. This makes it possible for _Priority_Get_highest() to * calculate the major and directly index into the minor table. @@ -855,6 +856,9 @@ EXTERN struct { * bit set */ +#define CPU_USE_GENERIC_BITFIELD_CODE FALSE +#define CPU_USE_GENERIC_BITFIELD_DATA FALSE + #define _CPU_Bitfield_Find_first_bit( _value, _output ) \ { \ asm volatile ("cntlzw %0, %1" : "=r" ((_output)), "=r" ((_value)) : \ @@ -879,7 +883,7 @@ EXTERN struct { * for that routine. */ -#define _CPU_Priority_Bits_index( _priority ) \ +#define _CPU_Priority_bits_index( _priority ) \ (_priority) /* end of Priority handler macros */ diff --git a/c/src/exec/score/cpu/sparc/README b/c/src/exec/score/cpu/sparc/README new file mode 100644 index 0000000000..0c481d67c1 --- /dev/null +++ b/c/src/exec/score/cpu/sparc/README @@ -0,0 +1,118 @@ +# +# $Id$ +# + +This file discusses SPARC specific issues which are important to +this port. The primary topics in this file are: + + + Global Register Usage + + Stack Frame + + EF bit in the PSR + + +Global Register Usage +===================== + +This information on register usage is based heavily on a comment in the +file gcc-2.7.0/config/sparc/sparc.h in the the gcc 2.7.0 source. + + + g0 is hardwired to 0 + + On non-v9 systems: + - g1 is free to use as temporary. + - g2-g4 are reserved for applications. Gcc normally uses them as + temporaries, but this can be disabled via the -mno-app-regs option. + - g5 through g7 are reserved for the operating system. + + On v9 systems: + - g1 and g5 are free to use as temporaries. + - g2-g4 are reserved for applications (the compiler will not normally use + them, but they can be used as temporaries with -mapp-regs). + - g6-g7 are reserved for the operating system. + + NOTE: As of gcc 2.7.0 register g1 was used in the following scenarios: + + + as a temporary by the 64 bit sethi pattern + + when restoring call-preserved registers in large stack frames + +RTEMS places no constraints on the usage of the global registers. Although +gcc assumes that either g5-g7 (non-V9) or g6-g7 (V9) are reserved for the +operating system, RTEMS does not assume any special use for them. + + + +Stack Frame +=========== + +The stack grows downward (i.e. to lower addresses) on the SPARC architecture. + +The following is the organization of the stack frame: + + + + | ............... | + fp | | + +-------------------------------+ + | | + | Local registers, temporaries, | + | and saved floats | x bytes + | | + sp + x +-------------------------------+ + | | + | outgoing parameters past | + | the sixth one | x bytes + | | + sp + 92 +-------------------------------+ * + | | * + | area for callee to save | * + | register arguments | * 24 bytes + | | * + sp + 68 +-------------------------------+ * + | | * + | structure return pointer | * 4 bytes + | | * + sp + 64 +-------------------------------+ * + | | * + | local register set | * 32 bytes + | | * + sp + 32 +-------------------------------+ * + | | * + | input register set | * 32 bytes + | | * + sp +-------------------------------+ * + + +* = minimal stack frame + +x = optional components + +EF bit in the PSR +================= + +The EF (enable floating point unit) in the PSR is utilized in this port to +prevent non-floating point tasks from performing floating point +operations. This bit is maintained as part of the integer context. +However, the floating point context is switched BEFORE the integer +context. Thus the EF bit in place at the time of the FP switch may +indicate that FP operations are disabled. This occurs on certain task +switches, when the EF bit will be 0 for the outgoing task and thus a fault +will be generated on the first FP operation of the FP context save. + +The remedy for this is to enable FP access as the first step in both the +save and restore of the FP context area. This bit will be subsequently +reloaded by the integer context switch. + +Two of the scenarios which demonstrate this problem are outlined below: + +1. When the first FP task is switched to. The system tasks are not FP and +thus would be unable to restore the FP context of the incoming task. + +2. On a deferred FP context switch. In this case, the system might switch +from FP Task A to non-FP Task B and then to FP Task C. In this scenario, +the floating point state must technically be saved by a non-FP task. + + + + + + + + diff --git a/c/src/exec/score/cpu/sparc/asm.h b/c/src/exec/score/cpu/sparc/asm.h index 10157171c5..a3d62416b8 100644 --- a/c/src/exec/score/cpu/sparc/asm.h +++ b/c/src/exec/score/cpu/sparc/asm.h @@ -28,7 +28,9 @@ */ #define ASM + #include +#include /* * Recent versions of GNU cpp define variables which indicate the @@ -37,7 +39,9 @@ * have to define these as appropriate. */ -/* XXX This does not appear to work on gcc 2.7.0 on the sparc */ +/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */ +/* XXX The following ifdef magic fixes the problem but results in a warning */ +/* XXX when compiling assembly code. */ #undef __USER_LABEL_PREFIX__ #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ @@ -91,6 +95,16 @@ #define PUBLIC(sym) .globl SYM (sym) #define EXTERN(sym) .globl SYM (sym) +/* + * Entry for traps which jump to a programmer-specified trap handler. + */ + +#define TRAP(_vector, _handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + mov _vector, %l3 + #endif /* end of include file */ diff --git a/c/src/exec/score/cpu/sparc/cpu.c b/c/src/exec/score/cpu/sparc/cpu.c index cf70913d5e..23d998cab5 100644 --- a/c/src/exec/score/cpu/sparc/cpu.c +++ b/c/src/exec/score/cpu/sparc/cpu.c @@ -7,52 +7,115 @@ #include #include -/* _CPU_Initialize +#if defined(erc32) +#include +#endif + +/* + * This initializes the set of opcodes placed in each trap + * table entry. The routine which installs a handler is responsible + * for filling in the fields for the _handler address and the _vector + * trap type. + * + * The constants following this structure are masks for the fields which + * must be filled in when the handler is installed. + */ + +const CPU_Trap_table_entry _CPU_Trap_slot_template = { + 0xa1480000, /* mov %psr, %l0 */ + 0x29000000, /* sethi %hi(_handler), %l4 */ + 0x81c52000, /* jmp %l4 + %lo(_handler) */ + 0xa6102000 /* mov _vector, %l3 */ +}; + +/*PAGE + * + * _CPU_Initialize * * This routine performs processor dependent initialization. * - * INPUT PARAMETERS: + * Input Parameters: * cpu_table - CPU table to initialize * thread_dispatch - address of disptaching routine + * + * Output Parameters: NONE + * + * NOTE: There is no need to save the pointer to the thread dispatch routine. + * The SPARC's assembly code can reference it directly with no problems. */ - void _CPU_Initialize( rtems_cpu_table *cpu_table, - void (*thread_dispatch) /* ignored on this CPU */ + void (*thread_dispatch) /* ignored on this CPU */ ) { - void *pointer; + void *pointer; + unsigned32 trap_table_start; + unsigned32 tbr_value; + CPU_Trap_table_entry *old_tbr; + CPU_Trap_table_entry *trap_table; /* - * The thread_dispatch argument is the address of the entry point - * for the routine called at the end of an ISR once it has been - * decided a context switch is necessary. On some compilation - * systems it is difficult to call a high-level language routine - * from assembly. This allows us to trick these systems. - * - * If you encounter this problem save the entry point in a CPU - * dependent variable. + * Install the executive's trap table. All entries from the original + * trap table are copied into the executive's trap table. This is essential + * since this preserves critical trap handlers such as the window underflow + * and overflow handlers. It is the responsibility of the BSP to provide + * install these in the initial trap table. */ + + trap_table_start = (unsigned32) &_CPU_Trap_Table_area; + if (trap_table_start & (SPARC_TRAP_TABLE_ALIGNMENT-1)) + trap_table_start = (trap_table_start + SPARC_TRAP_TABLE_ALIGNMENT) & + ~(SPARC_TRAP_TABLE_ALIGNMENT-1); + + trap_table = (CPU_Trap_table_entry *) trap_table_start; + + sparc_get_tbr( tbr_value ); - _CPU_Thread_dispatch_pointer = thread_dispatch; + old_tbr = (CPU_Trap_table_entry *) (tbr_value & 0xfffff000); + + memcpy( trap_table, (void *) old_tbr, 256 * sizeof( CPU_Trap_table_entry ) ); + + sparc_set_tbr( trap_table_start ); /* - * If there is not an easy way to initialize the FP context - * during Context_Initialize, then it is usually easier to - * save an "uninitialized" FP context here and copy it to - * the task's during Context_Initialize. + * This seems to be the most appropriate way to obtain an initial + * FP context on the SPARC. The NULL fp context is copied it to + * the task's FP context during Context_Initialize. */ pointer = &_CPU_Null_fp_context; _CPU_Context_save_fp( &pointer ); + /* + * Grab our own copy of the user's CPU table. + */ + _CPU_Table = *cpu_table; + +#if defined(erc32) + + /* + * ERC32 specific initialization + */ + + _ERC32_MEC_Timer_Control_Mirror = 0; + ERC32_MEC.Timer_Control = 0; + + ERC32_MEC.Control |= ERC32_CONFIGURATION_POWER_DOWN_ALLOWED; + +#endif + } /*PAGE * * _CPU_ISR_Get_level + * + * Input Parameters: NONE + * + * Output Parameters: + * returns the current interrupt level (PIL field of the PSR) */ unsigned32 _CPU_ISR_Get_level( void ) @@ -64,134 +127,263 @@ unsigned32 _CPU_ISR_Get_level( void ) return level; } -/* _CPU_ISR_install_vector +/*PAGE + * + * _CPU_ISR_install_raw_handler + * + * This routine installs the specified handler as a "raw" non-executive + * supported trap handler (a.k.a. interrupt service routine). + * + * Input Parameters: + * vector - trap table entry number plus synchronous + * vs. asynchronous information + * new_handler - address of the handler to be installed + * old_handler - pointer to an address of the handler previously installed + * + * Output Parameters: NONE + * *new_handler - address of the handler previously installed + * + * NOTE: + * + * On the SPARC, there are really only 256 vectors. However, the executive + * has no easy, fast, reliable way to determine which traps are synchronous + * and which are asynchronous. By default, synchronous traps return to the + * instruction which caused the interrupt. So if you install a software + * trap handler as an executive interrupt handler (which is desirable since + * RTEMS takes care of window and register issues), then the executive needs + * to know that the return address is to the trap rather than the instruction + * following the trap. + * + * So vectors 0 through 255 are treated as regular asynchronous traps which + * provide the "correct" return address. Vectors 256 through 512 are assumed + * by the executive to be synchronous and to require that the return address + * be fudged. + * + * If you use this mechanism to install a trap handler which must reexecute + * the instruction which caused the trap, then it should be installed as + * an asynchronous trap. This will avoid the executive changing the return + * address. + */ + +void _CPU_ISR_install_raw_handler( + unsigned32 vector, + proc_ptr new_handler, + proc_ptr *old_handler +) +{ + unsigned32 real_vector; + CPU_Trap_table_entry *tbr; + CPU_Trap_table_entry *slot; + unsigned32 u32_tbr; + unsigned32 u32_handler; + + /* + * Get the "real" trap number for this vector ignoring the synchronous + * versus asynchronous indicator included with our vector numbers. + */ + + real_vector = SPARC_REAL_TRAP_NUMBER( vector ); + + /* + * Get the current base address of the trap table and calculate a pointer + * to the slot we are interested in. + */ + + sparc_get_tbr( u32_tbr ); + + u32_tbr &= 0xfffff000; + + tbr = (CPU_Trap_table_entry *) u32_tbr; + + slot = &tbr[ real_vector ]; + + /* + * Get the address of the old_handler from the trap table. + * + * NOTE: The old_handler returned will be bogus if it does not follow + * the RTEMS model. + */ + +#define HIGH_BITS_MASK 0xFFFFFC00 +#define HIGH_BITS_SHIFT 10 +#define LOW_BITS_MASK 0x000003FF + + if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) { + u32_handler = + ((slot->sethi_of_handler_to_l4 & HIGH_BITS_MASK) << HIGH_BITS_SHIFT) | + (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK); + *old_handler = (proc_ptr) u32_handler; + } else + *old_handler = 0; + + /* + * Copy the template to the slot and then fix it. + */ + + *slot = _CPU_Trap_slot_template; + + u32_handler = (unsigned32) new_handler; + + slot->mov_vector_l3 |= vector; + slot->sethi_of_handler_to_l4 |= + (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT; + slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK); +} + +/*PAGE + * + * _CPU_ISR_install_vector * * This kernel routine installs the RTEMS handler for the * specified vector. * * Input parameters: - * vector - interrupt vector number - * old_handler - former ISR for this vector number - * new_handler - replacement ISR for this vector number + * vector - interrupt vector number + * new_handler - replacement ISR for this vector number + * old_handler - pointer to former ISR for this vector number * - * Output parameters: NONE + * Output parameters: + * *old_handler - former ISR for this vector number * */ - void _CPU_ISR_install_vector( unsigned32 vector, proc_ptr new_handler, proc_ptr *old_handler ) { - *old_handler = _ISR_Vector_table[ vector ]; + unsigned32 real_vector; + proc_ptr ignored; + + /* + * Get the "real" trap number for this vector ignoring the synchronous + * versus asynchronous indicator included with our vector numbers. + */ + + real_vector = SPARC_REAL_TRAP_NUMBER( vector ); /* - * If the interrupt vector table is a table of pointer to isr entry - * points, then we need to install the appropriate RTEMS interrupt - * handler for this vector number. + * Return the previous ISR handler. */ + *old_handler = _ISR_Vector_table[ real_vector ]; + /* - * We put the actual user ISR address in '_ISR_vector_table'. This will - * be used by the _ISR_Handler so the user gets control. + * Install the wrapper so this ISR can be invoked properly. */ - _ISR_Vector_table[ vector ] = new_handler; -} + _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored ); -/*PAGE - * - * _CPU_Install_interrupt_stack - */ + /* + * We put the actual user ISR address in '_ISR_vector_table'. This will + * be used by the _ISR_Handler so the user gets control. + */ -void _CPU_Install_interrupt_stack( void ) -{ + _ISR_Vector_table[ real_vector ] = new_handler; } /*PAGE * * _CPU_Context_Initialize + * + * This kernel routine initializes the basic non-FP context area associated + * with each thread. + * + * Input parameters: + * the_context - pointer to the context area + * stack_base - address of memory for the SPARC + * size - size in bytes of the stack area + * new_level - interrupt level for this context area + * entry_point - the starting execution point for this this context + * is_fp - TRUE if this context is associated with an FP thread + * + * Output parameters: NONE */ -/* - * The following constants assist in building a thread's initial context. - */ - -#define CPU_FRAME_SIZE (112) /* based on disassembled test code */ -#define ADDR_ADJ_OFFSET -8 - void _CPU_Context_Initialize( - Context_Control *_the_context, - unsigned32 *_stack_base, - unsigned32 _size, - unsigned32 _new_level, - void *_entry_point + Context_Control *the_context, + unsigned32 *stack_base, + unsigned32 size, + unsigned32 new_level, + void *entry_point, + boolean is_fp ) { - unsigned32 jmp_addr; - unsigned32 _stack_high; /* highest "stack aligned" address */ - unsigned32 _the_size; + unsigned32 stack_high; /* highest "stack aligned" address */ + unsigned32 the_size; unsigned32 tmp_psr; - jmp_addr = (unsigned32) _entry_point; - /* * On CPUs with stacks which grow down (i.e. SPARC), we build the stack - * based on the _stack_high address. + * based on the stack_high address. */ - _stack_high = ((unsigned32)(_stack_base) + _size); - _stack_high &= ~(CPU_STACK_ALIGNMENT - 1); + stack_high = ((unsigned32)(stack_base) + size); + stack_high &= ~(CPU_STACK_ALIGNMENT - 1); - _the_size = _size & ~(CPU_STACK_ALIGNMENT - 1); + the_size = size & ~(CPU_STACK_ALIGNMENT - 1); -/* XXX following code is based on unix port */ /* - * XXX SPARC port needs a diagram like this one... - * See /usr/include/sys/stack.h in Solaris 2.3 for a nice - * diagram of the stack. + * See the README in this directory for a diagram of the stack. */ - _the_context->o7 = jmp_addr + ADDR_ADJ_OFFSET; - _the_context->o6 = (unsigned32)(_stack_high - CPU_FRAME_SIZE); - _the_context->i6 = (unsigned32)(_stack_high); -#if 0 - _the_context->rp = jmp_addr + ADDR_ADJ_OFFSET; - _the_context->sp = (unsigned32)(_stack_high - CPU_FRAME_SIZE); - _the_context->fp = (unsigned32)(_stack_high); -#endif + the_context->o7 = ((unsigned32) entry_point) - 8; + the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE; + the_context->i6_fp = stack_high; - _the_context->wim = 0x01; + /* + * Build the PSR for the task. Most everything can be 0 and the + * CWP is corrected during the context switch. + * + * The EF bit determines if the floating point unit is available. + * The FPU is ONLY enabled if the context is associated with an FP task + * and this SPARC model has an FPU. + */ sparc_get_psr( tmp_psr ); - tmp_psr &= ~SPARC_PIL_MASK; - tmp_psr |= (((_new_level) << 8) & SPARC_PIL_MASK); - tmp_psr = (tmp_psr & ~0x07) | 0x07; /* XXX should use num windows */ - _the_context->psr = tmp_psr; + tmp_psr &= ~SPARC_PSR_PIL_MASK; + tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK; + tmp_psr &= ~SPARC_PSR_EF_MASK; /* disabled by default */ + +#if (SPARC_HAS_FPU == 1) + /* + * If this bit is not set, then a task gets a fault when it accesses + * a floating point register. This is a nice way to detect floating + * point tasks which are not currently declared as such. + */ + + if ( is_fp ) + tmp_psr |= SPARC_PSR_EF_MASK; +#endif + the_context->psr = tmp_psr; } /*PAGE * * _CPU_Internal_threads_Idle_thread_body * - * NOTES: - * - * 1. This is the same as the regular CPU independent algorithm. - * - * 2. If you implement this using a "halt", "idle", or "shutdown" - * instruction, then don't forget to put it in an infinite loop. + * Some SPARC implementations have low power, sleep, or idle modes. This + * tries to take advantage of those models. + */ + +#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE) + +/* + * This is the implementation for the erc32. * - * 3. Be warned. Some processors with onboard DMA have been known - * to stop the DMA if the CPU were put in IDLE mode. This might - * also be a problem with other on-chip peripherals. So use this - * hook with caution. + * NOTE: Low power mode was enabled at initialization time. */ +#if defined(erc32) + void _CPU_Internal_threads_Idle_thread_body( void ) { - - for( ; ; ) - /* insert your "halt" instruction here */ ; + while (1) { + ERC32_MEC.Power_Down = 0; /* value is irrelevant */ + } } + +#endif + +#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */ diff --git a/c/src/exec/score/cpu/sparc/cpu.h b/c/src/exec/score/cpu/sparc/cpu.h index 6b9890d132..c631d6a85f 100644 --- a/c/src/exec/score/cpu/sparc/cpu.h +++ b/c/src/exec/score/cpu/sparc/cpu.h @@ -1,7 +1,7 @@ /* cpu.h * - * This include file contains information pertaining to the XXX - * processor. + * This include file contains information pertaining to the port of + * the executive to the SPARC processor. * * $Id$ */ @@ -25,16 +25,6 @@ extern "C" { * * If TRUE, then they are inlined. * If FALSE, then a subroutine call is made. - * - * Basically this is an example of the classic trade-off of size - * versus speed. Inlining the call (TRUE) typically increases the - * size of the executive while speeding up the enabling of dispatching. - * [NOTE: In general, the _Thread_Dispatch_disable_level will - * only be 0 or 1 unless you are in an interrupt handler and that - * interrupt handler invokes the executive.] When not inlined - * something calls _Thread_Enable_dispatch which in turns calls - * _Thread_Dispatch. If the enable dispatch is inlined, then - * one subroutine call is avoided entirely.] */ #define CPU_INLINE_ENABLE_DISPATCH TRUE @@ -48,13 +38,10 @@ extern "C" { * If TRUE, then the loops are unrolled. * If FALSE, then the loops are not unrolled. * - * The primary factor in making this decision is the cost of disabling - * and enabling interrupts (_ISR_Flash) versus the cost of rest of the - * body of the loop. On some CPUs, the flash is more expensive than - * one iteration of the loop body. In this case, it might be desirable - * to unroll the loop. It is important to note that on some CPUs, this - * code is the longest interrupt disable period in the executive. So it is - * necessary to strike a balance when setting this parameter. + * This parameter could go either way on the SPARC. The interrupt flash + * code is relatively lengthy given the requirements for nops following + * writes to the psr. But if the clock speed were high enough, this would + * not represent a great deal of time. */ #define CPU_UNROLL_ENQUEUE_PRIORITY TRUE @@ -65,25 +52,11 @@ extern "C" { * If TRUE, then a stack is allocated in _Interrupt_Manager_initialization. * If FALSE, nothing is done. * - * If the CPU supports a dedicated interrupt stack in hardware, - * then it is generally the responsibility of the BSP to allocate it - * and set it up. - * - * If the CPU does not support a dedicated interrupt stack, then - * the porter has two options: (1) execute interrupts on the stack of - * the interrupted task, and (2) have the executive manage a dedicated - * interrupt stack. - * - * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE. - * - * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and - * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is - * possible that both are FALSE for a particular CPU. Although it - * is unclear what that would imply about the interrupt processing - * procedure on that CPU. + * The SPARC does not have a dedicated HW interrupt stack and one has + * been implemented in SW. */ -#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE /* XXX */ +#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE /* * Does this CPU have hardware support for a dedicated interrupt stack? @@ -91,25 +64,16 @@ extern "C" { * If TRUE, then it must be installed during initialization. * If FALSE, then no installation is performed. * - * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE. - * - * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and - * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is - * possible that both are FALSE for a particular CPU. Although it - * is unclear what that would imply about the interrupt processing - * procedure on that CPU. + * The SPARC does not have a dedicated HW interrupt stack. */ -#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE /* XXX */ +#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE /* * Do we allocate a dedicated interrupt stack in the Interrupt Manager? * * If TRUE, then the memory is allocated during initialization. * If FALSE, then the memory is allocated during initialization. - * - * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE - * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE. */ #define CPU_ALLOCATE_INTERRUPT_STACK TRUE @@ -119,15 +83,6 @@ extern "C" { * * If TRUE, then the FLOATING_POINT task attribute is supported. * If FALSE, then the FLOATING_POINT task attribute is ignored. - * - * If there is a FP coprocessor such as the i387 or mc68881, then - * the answer is TRUE. - * - * The macro name "SPARC_HAS_FPU" should be made CPU specific. - * It indicates whether or not this CPU model has FP support. For - * example, it would be possible to have an i386_nofp CPU model - * which set this to false to indicate that you have an i386 without - * an i387 and wish to leave floating point support out. */ #if ( SPARC_HAS_FPU == 1 ) @@ -141,15 +96,6 @@ extern "C" { * * If TRUE, then the FLOATING_POINT task attribute is assumed. * If FALSE, then the FLOATING_POINT task attribute is followed. - * - * So far, the only CPU in which this option has been used is the - * HP PA-RISC. The HP C compiler and gcc both implicitly use the - * floating point registers to perform integer multiplies. If - * a function which you would not think utilize the FP unit DOES, - * then one can not easily predict which tasks will use the FP hardware. - * In this case, this option should be TRUE. - * - * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well. */ #define CPU_ALL_TASKS_ARE_FP FALSE @@ -160,10 +106,6 @@ extern "C" { * If TRUE, then the IDLE task is created as a FLOATING_POINT task * and it has a floating point context which is switched in and out. * If FALSE, then the IDLE task does not have a floating point context. - * - * Setting this to TRUE negatively impacts the time required to preempt - * the IDLE task from an interrupt because the floating point context - * must be saved as part of the preemption. */ #define CPU_IDLE_TASK_IS_FP FALSE @@ -181,17 +123,6 @@ extern "C" { * point task is switched out and restored when the next floating point * task is restored. The state of the floating point registers between * those two operations is not specified. - * - * If the floating point context does NOT have to be saved as part of - * interrupt dispatching, then it should be safe to set this to TRUE. - * - * Setting this flag to TRUE results in using a different algorithm - * for deciding when to save and restore the floating point context. - * The deferred FP switch algorithm minimizes the number of times - * the FP context is saved and restored. The FP context is not saved - * until a context switch is made to another, different FP task. - * Thus in a system with only one FP task, the FP context will never - * be saved or restored. */ #define CPU_USE_DEFERRED_FP_SWITCH TRUE @@ -205,19 +136,13 @@ extern "C" { * * If FALSE, then use the generic IDLE thread body if the BSP does * not provide one. - * - * This is intended to allow for supporting processors which have - * a low power or idle mode. When the IDLE thread is executed, then - * the CPU can be powered down. - * - * The order of precedence for selecting the IDLE thread body is: - * - * 1. BSP provided - * 2. CPU dependent (if provided) - * 3. generic (if no BSP and no CPU dependent) */ +#if (SPARC_HAS_LOW_POWER_MODE == 1) +#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE +#else #define CPU_PROVIDES_IDLE_THREAD_BODY FALSE +#endif /* * Does the stack grow up (toward higher addresses) or down @@ -225,6 +150,8 @@ extern "C" { * * If TRUE, then the grows upward. * If FALSE, then the grows toward smaller addresses. + * + * The stack grows to lower addresses on the SPARC. */ #define CPU_STACK_GROWS_UP FALSE @@ -236,17 +163,8 @@ extern "C" { * the minimum requirements of the compiler in order to have as * much of the critical data area as possible in a cache line. * - * The placement of this macro in the declaration of the variables - * is based on the syntactically requirements of the GNU C - * "__attribute__" extension. For example with GNU C, use - * the following to force a structures to a 32 byte boundary. - * - * __attribute__ ((aligned (32))) - * - * NOTE: Currently only the Priority Bit Map table uses this feature. - * To benefit from using this, the data must be heavily - * used so it will stay in the cache and used frequently enough - * in the executive to justify turning this on. + * The SPARC does not appear to have particularly strict alignment + * requirements. This value was chosen to take advantages of caches. */ #define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (16))) @@ -255,18 +173,80 @@ extern "C" { * The following defines the number of bits actually used in the * interrupt field of the task mode. How those bits map to the * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level(). + * + * The SPARC has 16 interrupt levels in the PIL field of the PSR. */ #define CPU_MODES_INTERRUPT_MASK 0x0000000F /* - * Processor defined structures - * - * Examples structures include the descriptor tables from the i386 - * and the processor control structure on the i960ca. + * This structure represents the organization of the minimum stack frame + * for the SPARC. More framing information is required in certain situaions + * such as when there are a large number of out parameters or when the callee + * must save floating point registers. */ -/* XXX may need to put some structures here. */ +#ifndef ASM + +typedef struct { + unsigned32 l0; + unsigned32 l1; + unsigned32 l2; + unsigned32 l3; + unsigned32 l4; + unsigned32 l5; + unsigned32 l6; + unsigned32 l7; + unsigned32 i0; + unsigned32 i1; + unsigned32 i2; + unsigned32 i3; + unsigned32 i4; + unsigned32 i5; + unsigned32 i6_fp; + unsigned32 i7; + void *structure_return_address; + /* + * The following are for the callee to save the register arguments in + * should this be necessary. + */ + unsigned32 saved_arg0; + unsigned32 saved_arg1; + unsigned32 saved_arg2; + unsigned32 saved_arg3; + unsigned32 saved_arg4; + unsigned32 saved_arg5; + unsigned32 pad0; +} CPU_Minimum_stack_frame; + +#endif /* ASM */ + +#define CPU_STACK_FRAME_L0_OFFSET 0x00 +#define CPU_STACK_FRAME_L1_OFFSET 0x04 +#define CPU_STACK_FRAME_L2_OFFSET 0x08 +#define CPU_STACK_FRAME_L3_OFFSET 0x0c +#define CPU_STACK_FRAME_L4_OFFSET 0x10 +#define CPU_STACK_FRAME_L5_OFFSET 0x14 +#define CPU_STACK_FRAME_L6_OFFSET 0x18 +#define CPU_STACK_FRAME_L7_OFFSET 0x1c +#define CPU_STACK_FRAME_I0_OFFSET 0x20 +#define CPU_STACK_FRAME_I1_OFFSET 0x24 +#define CPU_STACK_FRAME_I2_OFFSET 0x28 +#define CPU_STACK_FRAME_I3_OFFSET 0x2c +#define CPU_STACK_FRAME_I4_OFFSET 0x30 +#define CPU_STACK_FRAME_I5_OFFSET 0x34 +#define CPU_STACK_FRAME_I6_FP_OFFSET 0x38 +#define CPU_STACK_FRAME_I7_OFFSET 0x3c +#define CPU_STRUCTURE_RETURN_ADDRESS_OFFSET 0x40 +#define CPU_STACK_FRAME_SAVED_ARG0_OFFSET 0x44 +#define CPU_STACK_FRAME_SAVED_ARG1_OFFSET 0x48 +#define CPU_STACK_FRAME_SAVED_ARG2_OFFSET 0x4c +#define CPU_STACK_FRAME_SAVED_ARG3_OFFSET 0x50 +#define CPU_STACK_FRAME_SAVED_ARG4_OFFSET 0x54 +#define CPU_STACK_FRAME_SAVED_ARG5_OFFSET 0x58 +#define CPU_STACK_FRAME_PAD0_OFFSET 0x5c + +#define CPU_MINIMUM_STACK_FRAME_SIZE 0x60 /* * Contexts @@ -280,35 +260,21 @@ extern "C" { * 2. floating point task stuff:: Context_Control_fp * 3. special interrupt level context :: Context_Control_interrupt * - * On some processors, it is cost-effective to save only the callee - * preserved registers during a task context switch. This means - * that the ISR code needs to save those registers which do not - * persist across function calls. It is not mandatory to make this - * distinctions between the caller/callee saves registers for the - * purpose of minimizing context saved during task switch and on interrupts. - * If the cost of saving extra registers is minimal, simplicity is the - * choice. Save the same context on interrupt entry as for tasks in - * this case. - * - * Additionally, if gdb is to be made aware of tasks for this CPU, then - * care should be used in designing the context area. - * - * On some CPUs with hardware floating point support, the Context_Control_fp - * structure will not be used or it simply consist of an array of a - * fixed number of bytes. This is done when the floating point context - * is dumped by a "FP save context" type instruction and the format - * is not really defined by the CPU. In this case, there is no need - * to figure out the exact format -- only the size. Of course, although - * this is enough information for context switches, it is probably not - * enough for a debugger such as gdb. But that is another problem. + * On the SPARC, we are relatively conservative in that we save most + * of the CPU state in the context area. The ET (enable trap) bit and + * the CWP (current window pointer) fields of the PSR are considered + * system wide resources and are not maintained on a per-thread basis. */ #ifndef ASM -/* XXX */ typedef struct { - unsigned32 g0; - unsigned32 g1; + /* + * Using a double g0_g1 will put everything in this structure on a + * double word boundary which allows us to use double word loads + * and stores safely in the context switch. + */ + double g0_g1; unsigned32 g2; unsigned32 g3; unsigned32 g4; @@ -331,7 +297,7 @@ typedef struct { unsigned32 i3; unsigned32 i4; unsigned32 i5; - unsigned32 i6; + unsigned32 i6_fp; unsigned32 i7; unsigned32 o0; @@ -340,10 +306,9 @@ typedef struct { unsigned32 o3; unsigned32 o4; unsigned32 o5; - unsigned32 o6; + unsigned32 o6_sp; unsigned32 o7; - unsigned32 wim; unsigned32 psr; } Context_Control; @@ -377,7 +342,7 @@ typedef struct { #define I3_OFFSET 0x4C #define I4_OFFSET 0x50 #define I5_OFFSET 0x54 -#define I6_OFFSET 0x58 +#define I6_FP_OFFSET 0x58 #define I7_OFFSET 0x5C #define O0_OFFSET 0x60 @@ -386,15 +351,19 @@ typedef struct { #define O3_OFFSET 0x6C #define O4_OFFSET 0x70 #define O5_OFFSET 0x74 -#define O6_OFFSET 0x78 +#define O6_SP_OFFSET 0x78 #define O7_OFFSET 0x7C -#define WIM_OFFSET 0x80 -#define PSR_OFFSET 0x84 +#define PSR_OFFSET 0x80 + +#define CONTEXT_CONTROL_SIZE 0x84 + +/* + * The floating point context area. + */ #ifndef ASM -/* XXX */ typedef struct { double f0_f1; double f2_f3; @@ -439,10 +408,39 @@ typedef struct { #define F3O_F31_OFFSET 0x78 #define FSR_OFFSET 0x80 +#define CONTEXT_CONTROL_FP_SIZE 0x84 + #ifndef ASM +/* + * Context saved on stack for an interrupt. + * + * NOTE: The PSR, PC, and NPC are only saved in this structure for the + * benefit of the user's handler. + */ + typedef struct { - unsigned32 special_interrupt_register_XXX; + CPU_Minimum_stack_frame Stack_frame; + unsigned32 psr; + unsigned32 pc; + unsigned32 npc; + unsigned32 g1; + unsigned32 g2; + unsigned32 g3; + unsigned32 g4; + unsigned32 g5; + unsigned32 g6; + unsigned32 g7; + unsigned32 i0; + unsigned32 i1; + unsigned32 i2; + unsigned32 i3; + unsigned32 i4; + unsigned32 i5; + unsigned32 i6_fp; + unsigned32 i7; + unsigned32 y; + unsigned32 pad0_offset; } CPU_Interrupt_frame; #endif /* ASM */ @@ -451,11 +449,34 @@ typedef struct { * Offsets of fields with CPU_Interrupt_frame for assembly routines. */ +#define ISF_STACK_FRAME_OFFSET 0x00 +#define ISF_PSR_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x00 +#define ISF_PC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x04 +#define ISF_NPC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x08 +#define ISF_G1_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x0c +#define ISF_G2_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x10 +#define ISF_G3_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x14 +#define ISF_G4_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x18 +#define ISF_G5_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x1c +#define ISF_G6_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x20 +#define ISF_G7_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x24 +#define ISF_I0_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x28 +#define ISF_I1_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x2c +#define ISF_I2_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x30 +#define ISF_I3_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x34 +#define ISF_I4_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x38 +#define ISF_I5_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x3c +#define ISF_I6_FP_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x40 +#define ISF_I7_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x44 +#define ISF_Y_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x48 +#define ISF_PAD0_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x4c + +#define CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE CPU_MINIMUM_STACK_FRAME_SIZE + 0x50 #ifndef ASM /* * The following table contains the information required to configure - * the XXX processor specific parameters. + * the processor specific parameters. * * NOTE: The interrupt_stack_size field is required if * CPU_ALLOCATE_INTERRUPT_STACK is defined as TRUE. @@ -472,61 +493,97 @@ typedef struct { boolean do_zero_of_workspace; unsigned32 interrupt_stack_size; unsigned32 extra_system_initialization_stack; - unsigned32 some_other_cpu_dependent_info_XXX; } rtems_cpu_table; /* - * This variable is optional. It is used on CPUs on which it is difficult - * to generate an "uninitialized" FP context. It is filled in by - * _CPU_Initialize and copied into the task's FP context area during - * _CPU_Context_Initialize. + * This variable is contains the initialize context for the FP unit. + * It is filled in by _CPU_Initialize and copied into the task's FP + * context area during _CPU_Context_Initialize. */ EXTERN Context_Control_fp _CPU_Null_fp_context CPU_STRUCTURE_ALIGNMENT; /* - * On some CPUs, software managed interrupt stack is supported. * This stack is allocated by the Interrupt Manager and the switch * is performed in _ISR_Handler. These variables contain pointers * to the lowest and highest addresses in the chunk of memory allocated * for the interrupt stack. Since it is unknown whether the stack * grows up or down (in general), this give the CPU dependent - * code the option of picking the version it wants to use. + * code the option of picking the version it wants to use. Thus + * both must be present if either is. * - * NOTE: These two variables are required if the macro - * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE. + * The SPARC supports a software based interrupt stack and these + * are required. */ -EXTERN void *_CPU_Interrupt_stack_low; -EXTERN void *_CPU_Interrupt_stack_high; +EXTERN void *_CPU_Interrupt_stack_low; +EXTERN void *_CPU_Interrupt_stack_high; + +#if defined(erc32) /* - * With some compilation systems, it is difficult if not impossible to - * call a high-level language routine from assembly language. This - * is especially true of commercial Ada compilers and name mangling - * C++ ones. This variable can be optionally defined by the CPU porter - * and contains the address of the routine _Thread_Dispatch. This - * can make it easier to invoke that routine at the end of the interrupt - * sequence (if a dispatch is necessary). + * ERC32 Specific Variables */ -EXTERN void (*_CPU_Thread_dispatch_pointer)(); +EXTERN unsigned32 _ERC32_MEC_Timer_Control_Mirror; +#endif + +/* + * The following type defines an entry in the SPARC's trap table. + * + * NOTE: The instructions chosen are RTEMS dependent although one is + * obligated to use two of the four instructions to perform a + * long jump. The other instructions load one register with the + * trap type (a.k.a. vector) and another with the psr. + */ + +typedef struct { + unsigned32 mov_psr_l0; /* mov %psr, %l0 */ + unsigned32 sethi_of_handler_to_l4; /* sethi %hi(_handler), %l4 */ + unsigned32 jmp_to_low_of_handler_plus_l4; /* jmp %l4 + %lo(_handler) */ + unsigned32 mov_vector_l3; /* mov _vector, %l3 */ +} CPU_Trap_table_entry; + /* - * Nothing prevents the porter from declaring more CPU specific variables. + * This is the set of opcodes for the instructions loaded into a trap + * table entry. The routine which installs a handler is responsible + * for filling in the fields for the _handler address and the _vector + * trap type. + * + * The constants following this structure are masks for the fields which + * must be filled in when the handler is installed. */ + +extern const CPU_Trap_table_entry _CPU_Trap_slot_template; -/* XXX: if needed, put more variables here */ +/* + * This is the executive's trap table which is installed into the TBR + * register. + * + * NOTE: Unfortunately, this must be aligned on a 4096 byte boundary. + * The GNU tools as of binutils 2.5.2 and gcc 2.7.0 would not + * align an entity to anything greater than a 512 byte boundary. + * + * Because of this, we pull a little bit of a trick. We allocate + * enough memory so we can grab an address on a 4096 byte boundary + * from this area. + */ + +#define SPARC_TRAP_TABLE_ALIGNMENT 4096 + +EXTERN unsigned8 _CPU_Trap_Table_area[ 8192 ] + __attribute__ ((aligned (SPARC_TRAP_TABLE_ALIGNMENT))); + /* - * The size of the floating point context area. On some CPUs this - * will not be a "sizeof" because the format of the floating point - * area is not defined -- only the size is. This is usually on - * CPUs with a "floating point save context" instruction. + * The size of the floating point context area. */ #define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp ) +#endif + /* * Amount of extra stack (above minimum stack size) required by * system initialization thread. Remember that in a multiprocessor @@ -538,23 +595,55 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * This defines the number of entries in the ISR_Vector_table managed * by the executive. + * + * On the SPARC, there are really only 256 vectors. However, the executive + * has no easy, fast, reliable way to determine which traps are synchronous + * and which are asynchronous. By default, synchronous traps return to the + * instruction which caused the interrupt. So if you install a software + * trap handler as an executive interrupt handler (which is desirable since + * RTEMS takes care of window and register issues), then the executive needs + * to know that the return address is to the trap rather than the instruction + * following the trap. + * + * So vectors 0 through 255 are treated as regular asynchronous traps which + * provide the "correct" return address. Vectors 256 through 512 are assumed + * by the executive to be synchronous and to require that the return address + * be fudged. + * + * If you use this mechanism to install a trap handler which must reexecute + * the instruction which caused the trap, then it should be installed as + * an asynchronous trap. This will avoid the executive changing the return + * address. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS 255 +#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256 +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER 511 + +#define SPARC_SYNCHRONOUS_TRAP_BIT_MASK 0x100 +#define SPARC_ASYNCHRONOUS_TRAP( _trap ) (_trap) +#define SPARC_SYNCHRONOUS_TRAP( _trap ) ((_trap) + 256 ) + +#define SPARC_REAL_TRAP_NUMBER( _trap ) ((_trap) % 256) /* * Should be large enough to run all tests. This insures * that a "reasonable" small application should not have any problems. + * + * This appears to be a fairly generous number for the SPARC since + * represents a call depth of about 20 routines based on the minimum + * stack frame. */ -#define CPU_STACK_MINIMUM_SIZE (1024*2) +#define CPU_STACK_MINIMUM_SIZE (1024*2) /* * CPU's worst alignment requirement for data types on a byte boundary. This * alignment does not take into account the requirements for the stack. + * + * On the SPARC, this is required for double word loads and stores. */ -#define CPU_ALIGNMENT 8 +#define CPU_ALIGNMENT 8 /* * This number corresponds to the byte alignment requirement for the @@ -591,12 +680,15 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * is strict enough for the stack, then this should be set to 0. * * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT. + * + * The alignment restrictions for the SPARC are not that strict but this + * should unsure that the stack is always sufficiently alignment that the + * window overflow, underflow, and flush routines can use double word loads + * and stores. */ #define CPU_STACK_ALIGNMENT 16 -#endif /* ASM */ - #ifndef ASM /* ISR handler macros */ @@ -631,12 +723,7 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); /* * Map interrupt level in task mode onto the hardware that the CPU * actually provides. Currently, interrupt levels which do not - * map onto the CPU in a generic fashion are undefined. Someday, - * it would be nice if these were "mapped" by the application - * via a callout. For example, m68k has 8 levels 0 - 7, levels - * 8 - 255 would be available for bsp/application specific meaning. - * This could be used to manage a programmable interrupt controller - * via the rtems_task_mode directive. + * map onto the CPU in a straight fashion are undefined. */ #define _CPU_ISR_Set_level( _newlevel ) \ @@ -659,46 +746,33 @@ unsigned32 _CPU_ISR_Get_level( void ); * - setting the proper interrupt level in the context * - initializing the floating point context * - * This routine generally does not set any unnecessary register - * in the context. The state of the "general data" registers is - * undefined at task start time. - * * NOTE: Implemented as a subroutine for the SPARC port. */ void _CPU_Context_Initialize( - Context_Control *_the_context, - unsigned32 *_stack_base, - unsigned32 _size, - unsigned32 _new_level, - void *_entry_point + Context_Control *the_context, + unsigned32 *stack_base, + unsigned32 size, + unsigned32 new_level, + void *entry_point, + boolean is_fp ); /* * This routine is responsible for somehow restarting the currently - * executing task. If you are lucky, then all that is necessary - * is restoring the context. Otherwise, there will need to be - * a special assembly routine which does something special in this - * case. Context_Restore should work most of the time. It will - * not work if restarting self conflicts with the stack frame - * assumptions of restoring a context. + * executing task. + * + * On the SPARC, this is is relatively painless but requires a small + * amount of wrapper code before using the regular restore code in + * of the context switch. */ #define _CPU_Context_Restart_self( _the_context ) \ _CPU_Context_restore( (_the_context) ); /* - * The purpose of this macro is to allow the initial pointer into - * a floating point context area (used to save the floating point - * context) to be at an arbitrary place in the floating point - * context area. - * - * This is necessary because some FP units are designed to have - * their context saved as a stack which grows into lower addresses. - * Other FP units can be saved by simply moving registers into offsets - * from the base of the context area. Finally some FP units provide - * a "dump context" instruction which could fill in from high to low - * or low to high based on the whim of the CPU designers. + * The FP context area for the SPARC is a simple structure and nothing + * special is required to find the "starting load point" */ #define _CPU_Context_Fp_start( _base, _offset ) \ @@ -706,20 +780,17 @@ void _CPU_Context_Initialize( /* * This routine initializes the FP context area passed to it to. - * There are a few standard ways in which to initialize the - * floating point context. The code included for this macro assumes - * that this is a CPU in which a "initial" FP context was saved into - * _CPU_Null_fp_context and it simply copies it to the destination - * context passed to it. * - * Other models include (1) not doing anything, and (2) putting - * a "null FP status word" in the correct place in the FP context. + * The SPARC allows us to use the simple initialization model + * in which an "initial" FP context was saved into _CPU_Null_fp_context + * at CPU initialization and it is simply copied into the destination + * context. */ #define _CPU_Context_Initialize_fp( _destination ) \ - { \ + do { \ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \ - } + } while (0) /* end of Context handler macros */ @@ -732,122 +803,42 @@ void _CPU_Context_Initialize( */ #define _CPU_Fatal_halt( _error ) \ - { \ - } + do { \ + unsigned32 level; \ + \ + sparc_disable_interrupts( level ); \ + asm volatile ( "mov %0, %%g1 " : "=r" (level) : "0" (level) ); \ + while (1); /* loop forever */ \ + } while (0) /* end of Fatal Error manager macros */ /* Bitfield handler macros */ /* - * This routine sets _output to the bit number of the first bit - * set in _value. _value is of CPU dependent type Priority_Bit_map_control. - * This type may be either 16 or 32 bits wide although only the 16 - * least significant bits will be used. - * - * There are a number of variables in using a "find first bit" type - * instruction. - * - * (1) What happens when run on a value of zero? - * (2) Bits may be numbered from MSB to LSB or vice-versa. - * (3) The numbering may be zero or one based. - * (4) The "find first bit" instruction may search from MSB or LSB. - * - * The executive guarantees that (1) will never happen so it is not a concern. - * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and - * _CPU_Priority_Bits_index(). These three form a set of routines - * which must logically operate together. Bits in the _value are - * set and cleared based on masks built by _CPU_Priority_mask(). - * The basic major and minor values calculated by _Priority_Major() - * and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index() - * to properly range between the values returned by the "find first bit" - * instruction. This makes it possible for _Priority_Get_highest() to - * calculate the major and directly index into the minor table. - * This mapping is necessary to ensure that 0 (a high priority major/minor) - * is the first bit found. - * - * This entire "find first bit" and mapping process depends heavily - * on the manner in which a priority is broken into a major and minor - * components with the major being the 4 MSB of a priority and minor - * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest - * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next - * to the lowest priority. - * - * If your CPU does not have a "find first bit" instruction, then - * there are ways to make do without it. Here are a handful of ways - * to implement this in software: - * - * - a series of 16 bit test instructions - * - a "binary search using if's" - * - _number = 0 - * if _value > 0x00ff - * _value >>=8 - * _number = 8; - * - * if _value > 0x0000f - * _value >=8 - * _number += 4 - * - * _number += bit_set_table[ _value ] - * - * where bit_set_table[ 16 ] has values which indicate the first - * bit set - */ - -#ifndef INIT - extern const unsigned char __log2table[256]; + * The SPARC port uses the generic C algorithm for bitfield scan if the + * CPU model does not have a scan instruction. + */ + +#if ( SPARC_HAS_BITSCAN == 0 ) +#define CPU_USE_GENERIC_BITFIELD_CODE TRUE +#define CPU_USE_GENERIC_BITFIELD_DATA TRUE #else -const unsigned char __log2table[256] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; +#error "scan instruction not currently supported by RTEMS!!" #endif -#define _CPU_Bitfield_Find_first_bit( _value, _output ) \ - { \ - register __value = (_value); \ - \ - if ( !(__value & 0xff00) ) \ - (_output) = __log2table[ __value ]; \ - else \ - (_output) = __log2table[ __value >> 8 ] + 8; \ - } - - /* end of Bitfield handler macros */ -/* - * This routine builds the mask which corresponds to the bit fields - * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion - * for that routine. - */ - -#define _CPU_Priority_Mask( _bit_number ) \ - ( 0x8000 >> (_bit_number) ) +/* Priority handler handler macros */ /* - * This routine translates the bit numbers returned by - * _CPU_Bitfield_Find_first_bit() into something suitable for use as - * a major or minor component of a priority. See the discussion - * for that routine. + * The SPARC port uses the generic C algorithm for bitfield scan if the + * CPU model does not have a scan instruction. */ -#define _CPU_Priority_Bits_index( _priority ) \ - (15 - (_priority)) +#if ( SPARC_HAS_BITSCAN == 1 ) +#error "scan instruction not currently supported by RTEMS!!" +#endif /* end of Priority handler macros */ @@ -865,38 +856,42 @@ void _CPU_Initialize( ); /* - * _CPU_ISR_install_vector + * _CPU_ISR_install_raw_handler * - * This routine installs an interrupt vector. + * This routine installs new_handler to be directly called from the trap + * table. */ - -void _CPU_ISR_install_vector( + +void _CPU_ISR_install_raw_handler( unsigned32 vector, proc_ptr new_handler, proc_ptr *old_handler ); /* - * _CPU_Install_interrupt_stack - * - * This routine installs the hardware interrupt stack pointer. + * _CPU_ISR_install_vector * - * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK - * is TRUE. + * This routine installs an interrupt vector. */ -void _CPU_Install_interrupt_stack( void ); +void _CPU_ISR_install_vector( + unsigned32 vector, + proc_ptr new_handler, + proc_ptr *old_handler +); +#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE) + /* * _CPU_Internal_threads_Idle_thread_body * - * This routine is the CPU dependent IDLE thread body. - * - * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY - * is TRUE. + * Some SPARC implementations have low power, sleep, or idle modes. This + * tries to take advantage of those models. */ - + void _CPU_Internal_threads_Idle_thread_body( void ); + +#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */ /* * _CPU_Context_switch @@ -913,9 +908,7 @@ void _CPU_Context_switch( * _CPU_Context_restore * * This routine is generallu used only to restart self in an - * efficient manner. It may simply be a label in _CPU_Context_switch. - * - * NOTE: May be unnecessary to reload some registers. + * efficient manner. */ void _CPU_Context_restore( @@ -942,24 +935,23 @@ void _CPU_Context_restore_fp( void **fp_context_ptr ); -/* The following routine swaps the endian format of an unsigned int. +/* + * CPU_swap_u32 + * + * The following routine swaps the endian format of an unsigned int. * It must be static because it is referenced indirectly. * - * This version will work on any processor, but if there is a better - * way for your CPU PLEASE use it. The most common way to do this is to: + * This version will work on any processor, but if you come across a better + * way for the SPARC PLEASE use it. The most common way to swap a 32-bit + * entity as shown below is not any more efficient on the SPARC. * * swap least significant two bytes with 16-bit rotate * swap upper and lower 16-bits * swap most significant two bytes with 16-bit rotate * - * Some CPUs have special instructions which swap a 32-bit quantity in - * a single instruction (e.g. i486). It is probably best to avoid - * an "endian swapping control bit" in the CPU. One good reason is - * that interrupts would probably have to be disabled to insure that - * an interrupt does not try to access the same "chunk" with the wrong - * endian. Another good reason is that on some CPUs, the endian bit - * endianness for ALL fetches -- both code and data -- so the code - * will be fetched incorrectly. + * It is not obvious how the SPARC can do significantly better than the + * generic code. gcc 2.7.0 only generates about 12 instructions for the + * following code at optimization level four (i.e. -O4). */ static inline unsigned int CPU_swap_u32( diff --git a/c/src/exec/score/cpu/sparc/cpu_asm.s b/c/src/exec/score/cpu/sparc/cpu_asm.s index d1e275ca3f..045157b074 100644 --- a/c/src/exec/score/cpu/sparc/cpu_asm.s +++ b/c/src/exec/score/cpu/sparc/cpu_asm.s @@ -2,7 +2,7 @@ * * This file contains the basic algorithms for all assembly code used * in an specific CPU port of RTEMS. These algorithms must be implemented - * in assembly language + * in assembly language. * * $Id$ */ @@ -10,319 +10,680 @@ #include #include +#if (SPARC_HAS_FPU == 1) + /* - * _CPU_Context_save_fp + * void _CPU_Context_save_fp( + * void **fp_context_ptr + * ) * * This routine is responsible for saving the FP context * at *fp_context_ptr. If the point to load the FP context * from is changed then the pointer is modified by this routine. * - * Sometimes a macro implementation of this is in cpu.h which dereferences - * the ** and a similarly named routine in this file is passed something - * like a (Context_Control_fp *). The general rule on making this decision - * is to avoid writing assembly language. - * - * void _CPU_Context_save_fp( - * void **fp_context_ptr - * ) - * { - * } + * NOTE: See the README in this directory for information on the + * management of the "EF" bit in the PSR. */ .align 4 PUBLIC(_CPU_Context_save_fp) SYM(_CPU_Context_save_fp): - save %sp,-104,%sp - ld [%i0],%l0 - std %f0,[%l0+FO_F1_OFFSET] - std %f2,[%l0+F2_F3_OFFSET] - std %f4,[%l0+F4_F5_OFFSET] - std %f6,[%l0+F6_F7_OFFSET] - std %f8,[%l0+F8_F9_OFFSET] - std %f10,[%l0+F1O_F11_OFFSET] - std %f12,[%l0+F12_F13_OFFSET] - std %f14,[%l0+F14_F15_OFFSET] - std %f16,[%l0+F16_F17_OFFSET] - std %f18,[%l0+F18_F19_OFFSET] - std %f20,[%l0+F2O_F21_OFFSET] - std %f22,[%l0+F22_F23_OFFSET] - std %f24,[%l0+F24_F25_OFFSET] - std %f26,[%l0+F26_F27_OFFSET] - std %f28,[%l0+F28_F29_OFFSET] - std %f30,[%l0+F3O_F31_OFFSET] - st %fsr,[%l0+FSR_OFFSET] + save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp + + /* + * The following enables the floating point unit. + */ + + mov %psr, %l0 + sethi %hi(SPARC_PSR_EF_MASK), %l1 + or %l1, %lo(SPARC_PSR_EF_MASK), %l1 + or %l0, %l1, %l0 + mov %l0, %psr ! **** ENABLE FLOAT ACCESS **** + + ld [%i0], %l0 + std %f0, [%l0 + FO_F1_OFFSET] + std %f2, [%l0 + F2_F3_OFFSET] + std %f4, [%l0 + F4_F5_OFFSET] + std %f6, [%l0 + F6_F7_OFFSET] + std %f8, [%l0 + F8_F9_OFFSET] + std %f10, [%l0 + F1O_F11_OFFSET] + std %f12, [%l0 + F12_F13_OFFSET] + std %f14, [%l0 + F14_F15_OFFSET] + std %f16, [%l0 + F16_F17_OFFSET] + std %f18, [%l0 + F18_F19_OFFSET] + std %f20, [%l0 + F2O_F21_OFFSET] + std %f22, [%l0 + F22_F23_OFFSET] + std %f24, [%l0 + F24_F25_OFFSET] + std %f26, [%l0 + F26_F27_OFFSET] + std %f28, [%l0 + F28_F29_OFFSET] + std %f30, [%l0 + F3O_F31_OFFSET] + st %fsr, [%l0 + FSR_OFFSET] ret restore /* - * _CPU_Context_restore_fp + * void _CPU_Context_restore_fp( + * void **fp_context_ptr + * ) * * This routine is responsible for restoring the FP context * at *fp_context_ptr. If the point to load the FP context * from is changed then the pointer is modified by this routine. * - * Sometimes a macro implementation of this is in cpu.h which dereferences - * the ** and a similarly named routine in this file is passed something - * like a (Context_Control_fp *). The general rule on making this decision - * is to avoid writing assembly language. - * - * void _CPU_Context_restore_fp( - * void **fp_context_ptr - * ) - * { - * } + * NOTE: See the README in this directory for information on the + * management of the "EF" bit in the PSR. */ .align 4 PUBLIC(_CPU_Context_restore_fp) SYM(_CPU_Context_restore_fp): - save %sp,-104,%sp - ld [%o0],%l0 - ldd [%l0+FO_F1_OFFSET],%f0 - ldd [%l0+F2_F3_OFFSET],%f2 - ldd [%l0+F4_F5_OFFSET],%f4 - ldd [%l0+F6_F7_OFFSET],%f6 - ldd [%l0+F8_F9_OFFSET],%f8 - ldd [%l0+F1O_F11_OFFSET],%f10 - ldd [%l0+F12_F13_OFFSET],%f12 - ldd [%l0+F14_F15_OFFSET],%f14 - ldd [%l0+F16_F17_OFFSET],%f16 - ldd [%l0+F18_F19_OFFSET],%f18 - ldd [%l0+F2O_F21_OFFSET],%f20 - ldd [%l0+F22_F23_OFFSET],%f22 - ldd [%l0+F24_F25_OFFSET],%f24 - ldd [%l0+F26_F27_OFFSET],%f26 - ldd [%l0+F28_F29_OFFSET],%f28 - ldd [%l0+F3O_F31_OFFSET],%f30 - ld [%l0+FSR_OFFSET],%fsr + save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE , %sp + + /* + * The following enables the floating point unit. + */ + + mov %psr, %l0 + sethi %hi(SPARC_PSR_EF_MASK), %l1 + or %l1, %lo(SPARC_PSR_EF_MASK), %l1 + or %l0, %l1, %l0 + mov %l0, %psr ! **** ENABLE FLOAT ACCESS **** + + ld [%i0], %l0 + ldd [%l0 + FO_F1_OFFSET], %f0 + ldd [%l0 + F2_F3_OFFSET], %f2 + ldd [%l0 + F4_F5_OFFSET], %f4 + ldd [%l0 + F6_F7_OFFSET], %f6 + ldd [%l0 + F8_F9_OFFSET], %f8 + ldd [%l0 + F1O_F11_OFFSET], %f10 + ldd [%l0 + F12_F13_OFFSET], %f12 + ldd [%l0 + F14_F15_OFFSET], %f14 + ldd [%l0 + F16_F17_OFFSET], %f16 + ldd [%l0 + F18_F19_OFFSET], %f18 + ldd [%l0 + F2O_F21_OFFSET], %f20 + ldd [%l0 + F22_F23_OFFSET], %f22 + ldd [%l0 + F24_F25_OFFSET], %f24 + ldd [%l0 + F26_F27_OFFSET], %f26 + ldd [%l0 + F28_F29_OFFSET], %f28 + ldd [%l0 + F3O_F31_OFFSET], %f30 + ld [%l0 + FSR_OFFSET], %fsr ret restore -/* _CPU_Context_switch - * - * This routine performs a normal non-FP context switch. - * +#endif /* SPARC_HAS_FPU */ + +/* * void _CPU_Context_switch( * Context_Control *run, * Context_Control *heir * ) - * { - * } + * + * This routine performs a normal non-FP context switch. */ -/* from gcc-2.7.0/config/sparc/sparc.h on register usage */ - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - g0 is used for the condition code and not to represent %g0, which is - hardwired to 0, so reg 0 is *not* fixed. - On non-v9 systems: - g1 is free to use as temporary. - g2-g4 are reserved for applications. Gcc normally uses them as - temporaries, but this can be disabled via the -mno-app-regs option. - g5 through g7 are reserved for the operating system. - On v9 systems: - g1 and g5 are free to use as temporaries. - g2-g4 are reserved for applications (the compiler will not normally use - them, but they can be used as temporaries with -mapp-regs). - g6-g7 are reserved for the operating system. - ??? Register 1 is used as a temporary by the 64 bit sethi pattern, so must - currently be a fixed register until this pattern is rewritten. - Register 1 is also used when restoring call-preserved registers in large - stack frames. */ - - .align 4 PUBLIC(_CPU_Context_switch) SYM(_CPU_Context_switch): - ta 0x03 /* flush registers */ - - /* skip g0 */ - st %g1,[%o0+G1_OFFSET] /* globals */ - st %g2,[%o0+G2_OFFSET] - st %g3,[%o0+G3_OFFSET] - st %g4,[%o0+G4_OFFSET] - st %g5,[%o0+G5_OFFSET] - st %g6,[%o0+G6_OFFSET] - st %g7,[%o0+G7_OFFSET] - - st %l0,[%o0+L0_OFFSET] - st %l1,[%o0+L1_OFFSET] - st %l2,[%o0+L2_OFFSET] - st %l3,[%o0+L3_OFFSET] - st %l4,[%o0+L4_OFFSET] - st %l5,[%o0+L5_OFFSET] - st %l6,[%o0+L6_OFFSET] - st %l7,[%o0+L7_OFFSET] - - st %i0,[%o0+I0_OFFSET] - st %i1,[%o0+I1_OFFSET] - st %i2,[%o0+I2_OFFSET] - st %i3,[%o0+I3_OFFSET] - st %i4,[%o0+I4_OFFSET] - st %i5,[%o0+I5_OFFSET] - st %i6,[%o0+I6_OFFSET] - st %i7,[%o0+I7_OFFSET] - - st %o0,[%o0+O0_OFFSET] - st %o1,[%o0+O1_OFFSET] - st %o2,[%o0+O2_OFFSET] - st %o3,[%o0+O3_OFFSET] - st %o4,[%o0+O4_OFFSET] - st %o5,[%o0+O5_OFFSET] - st %o6,[%o0+O6_OFFSET] - st %o7,[%o0+O7_OFFSET] - - rd %psr,%o2 - st %o2,[%o0+PSR_OFFSET] /* save status register */ - - /* enter here with o1 = context to restore */ - /* o2 = psr */ -restore: - - ld [%o1+PSR_OFFSET],%o0 - and %o2,31,%o2 /* g1 = cwp */ - and %o0,-32,%o0 /* o0 = psr w/o cwp */ - or %o0,%o2,%o2 /* o2 = new psr */ - wr %o2,0,%psr /* restore status register */ - - /* skip g0 */ - ld [%o1+G1_OFFSET],%g1 - ld [%o1+G2_OFFSET],%g2 - ld [%o1+G3_OFFSET],%g3 - ld [%o1+G4_OFFSET],%g4 - ld [%o1+G5_OFFSET],%g5 - ld [%o1+G6_OFFSET],%g6 - ld [%o1+G7_OFFSET],%g7 - - ld [%o1+L0_OFFSET],%l0 - ld [%o1+L1_OFFSET],%l1 - ld [%o1+L2_OFFSET],%l2 - ld [%o1+L3_OFFSET],%l3 - ld [%o1+L4_OFFSET],%l4 - ld [%o1+L5_OFFSET],%l5 - ld [%o1+L6_OFFSET],%l6 - ld [%o1+L7_OFFSET],%l7 - - ld [%o1+I0_OFFSET],%i0 - ld [%o1+I1_OFFSET],%i1 - ld [%o1+I2_OFFSET],%i2 - ld [%o1+I3_OFFSET],%i3 - ld [%o1+I4_OFFSET],%i4 - ld [%o1+I5_OFFSET],%i5 - ld [%o1+I6_OFFSET],%i6 - ld [%o1+I7_OFFSET],%i7 - - ld [%o1+O0_OFFSET],%o0 - /* do o1 last to avoid destroying heir context pointer */ - ld [%o1+O2_OFFSET],%o2 - ld [%o1+O3_OFFSET],%o3 - ld [%o1+O4_OFFSET],%o4 - ld [%o1+O5_OFFSET],%o5 - ld [%o1+O6_OFFSET],%o6 - ld [%o1+O7_OFFSET],%o7 - - ld [%o1+O1_OFFSET],%o1 /* overwrite heir pointer */ - - jmp %o7 + 8 /* return */ - nop /* delay slot */ - + ! skip g0 + st %g1, [%o0 + G1_OFFSET] ! save the global registers + std %g2, [%o0 + G2_OFFSET] + std %g4, [%o0 + G4_OFFSET] + std %g6, [%o0 + G6_OFFSET] + + std %l0, [%o0 + L0_OFFSET] ! save the local registers + std %l2, [%o0 + L2_OFFSET] + std %l4, [%o0 + L4_OFFSET] + std %l6, [%o0 + L6_OFFSET] + + std %i0, [%o0 + I0_OFFSET] ! save the input registers + std %i2, [%o0 + I2_OFFSET] + std %i4, [%o0 + I4_OFFSET] + std %i6, [%o0 + I6_FP_OFFSET] + + std %o0, [%o0 + O0_OFFSET] ! save the output registers + std %o2, [%o0 + O2_OFFSET] + std %o4, [%o0 + O4_OFFSET] + std %o6, [%o0 + O6_SP_OFFSET] + + rd %psr, %o2 + st %o2, [%o0 + PSR_OFFSET] ! save status register + + /* + * This is entered from _CPU_Context_restore with: + * o1 = context to restore + * o2 = psr + */ + + PUBLIC(_CPU_Context_restore_heir) +SYM(_CPU_Context_restore_heir): + /* + * Flush all windows with valid contents except the current one. + * In examining the set register windows, one may logically divide + * the windows into sets (some of which may be empty) based on their + * current status: + * + * + current (i.e. in use), + * + used (i.e. a restore would not trap) + * + invalid (i.e. 1 in corresponding bit in WIM) + * + unused + * + * Either the used or unused set of windows may be empty. + * + * NOTE: We assume only one bit is set in the WIM at a time. + * + * Given a CWP of 5 and a WIM of 0x1, the registers are divided + * into sets as follows: + * + * + 0 - invalid + * + 1-4 - unused + * + 5 - current + * + 6-7 - used + * + * In this case, we only would save the used windows -- 6 and 7. + * + * Traps are disabled for the same logical period as in a + * flush all windows trap handler. + * + * Register Usage while saving the windows: + * g1 = current PSR + * g2 = current wim + * g3 = CWP + * g4 = wim scratch + * g5 = scratch + */ + + ld [%o1 + PSR_OFFSET], %g1 ! g1 = saved psr + + and %o2, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP + ! g1 = psr w/o cwp + andn %g1, SPARC_PSR_ET_MASK | SPARC_PSR_CWP_MASK, %g1 + or %g1, %g3, %g1 ! g1 = heirs psr + mov %g1, %psr ! restore status register and + ! **** DISABLE TRAPS **** + mov %wim, %g2 ! g2 = wim + mov 1, %g4 + sll %g4, %g3, %g4 ! g4 = WIM mask for CW invalid + +save_frame_loop: + sll %g4, 1, %g5 ! rotate the "wim" left 1 + srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4 + or %g4, %g5, %g4 ! g4 = wim if we do one restore + + /* + * If a restore would not underflow, then continue. + */ + + andcc %g4, %g2, %g0 ! Any windows to flush? + bnz done_flushing ! No, then continue + nop + + restore ! back one window + + /* + * Now save the window just as if we overflowed to it. + */ + + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + ba save_frame_loop + nop + +done_flushing: + + add %g3, 1, %g3 ! calculate desired WIM + and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3 + mov 1, %g4 + sll %g4, %g3, %g4 ! g4 = new WIM + mov %g4, %wim + + or %g1, SPARC_PSR_ET_MASK, %g1 + mov %g1, %psr ! **** ENABLE TRAPS **** + ! and restore CWP + nop + nop + nop + + ! skip g0 + ld [%o1 + G1_OFFSET], %g1 ! restore the global registers + ldd [%o1 + G2_OFFSET], %g2 + ldd [%o1 + G4_OFFSET], %g4 + ldd [%o1 + G6_OFFSET], %g6 + + ldd [%o1 + L0_OFFSET], %l0 ! restore the local registers + ldd [%o1 + L2_OFFSET], %l2 + ldd [%o1 + L4_OFFSET], %l4 + ldd [%o1 + L6_OFFSET], %l6 + + ldd [%o1 + I0_OFFSET], %i0 ! restore the output registers + ldd [%o1 + I2_OFFSET], %i2 + ldd [%o1 + I4_OFFSET], %i4 + ldd [%o1 + I6_FP_OFFSET], %i6 + + ldd [%o1 + O2_OFFSET], %o2 ! restore the output registers + ldd [%o1 + O4_OFFSET], %o4 + ldd [%o1 + O6_SP_OFFSET], %o6 + ! do o0/o1 last to avoid destroying heir context pointer + ldd [%o1 + O0_OFFSET], %o0 ! overwrite heir pointer + + jmp %o7 + 8 ! return + nop ! delay slot /* - * _CPU_Context_restore - * - * This routine is generallu used only to restart self in an - * efficient manner. It may simply be a label in _CPU_Context_switch. - * - * NOTE: May be unnecessary to reload some registers. - * * void _CPU_Context_restore( * Context_Control *new_context * ) - * { - * } + * + * This routine is generally used only to perform restart self. + * + * NOTE: It is unnecessary to reload some registers. */ .align 4 PUBLIC(_CPU_Context_restore) SYM(_CPU_Context_restore): - save %sp, -104, %sp /* save a stack frame */ - ta 0x03 /* flush registers */ - rd %psr,%o2 - ba restore - mov %i0,%o1 /* in the delay slot */ + save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp + rd %psr, %o2 + ba SYM(_CPU_Context_restore_heir) + mov %i0, %o1 ! in the delay slot -/* void _ISR_Handler() +/* + * void _ISR_Handler() * * This routine provides the RTEMS interrupt management. * - * void _ISR_Handler() - * { - * } + * We enter this handler from the 4 instructions in the trap table with + * the following registers assumed to be set as shown: + * + * l0 = PSR + * l1 = PC + * l2 = nPC + * l3 = trap type + * + * NOTE: By an executive defined convention, trap type is between 0 and 255 if + * it is an asynchonous trap and 256 and 511 if it is synchronous. */ .align 4 PUBLIC(_ISR_Handler) SYM(_ISR_Handler): - ret + /* + * Fix the return address for synchronous traps. + */ + + andcc %l3, SPARC_SYNCHRONOUS_TRAP_BIT_MASK, %g0 + ! Is this a synchronous trap? + be,a win_ovflow ! No, then skip the adjustment + nop ! DELAY + mov %l2, %l1 ! do not return to the instruction + add %l2, 4, %l2 ! indicated + +win_ovflow: + /* + * Save the globals this block uses. + * + * These registers are not restored from the locals. Their contents + * are saved directly from the locals into the ISF below. + */ + + mov %g4, %l4 ! save the globals this block uses + mov %g5, %l5 + + /* + * When at a "window overflow" trap, (wim == (1 << cwp)). + * If we get here like that, then process a window overflow. + */ + + rd %wim, %g4 + srl %g4, %l0, %g5 ! g5 = win >> cwp ; shift count and CWP + ! are LS 5 bits ; how convenient :) + cmp %g5, 1 ! Is this an invalid window? + bne dont_do_the_window ! No, then skip all this stuff + ! we are using the delay slot + + /* + * The following is same as a 1 position right rotate of WIM + */ + + srl %g4, 1, %g5 ! g5 = WIM >> 1 + sll %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %g4 + ! g4 = WIM << (Number Windows - 1) + or %g4, %g5, %g4 ! g4 = (WIM >> 1) | + ! (WIM << (Number Windows - 1)) + + /* + * At this point: + * + * g4 = the new WIM + * g5 is free + */ + + /* + * Since we are tinkering with the register windows, we need to + * make sure that all the required information is in global registers. + */ + + save ! Save into the window + wr %g4, 0, %wim ! WIM = new WIM + nop ! delay slots + nop + nop + + /* + * Now save the window just as if we overflowed to it. + */ + + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + restore + nop + +dont_do_the_window: + /* + * Global registers %g4 and %g5 are saved directly from %l4 and + * %l5 directly into the ISF below. + */ + +save_isf: + + /* + * Save the state of the interrupted task -- especially the global + * registers -- in the Interrupt Stack Frame. Note that the ISF + * includes a regular minimum stack frame which will be used if + * needed by register window overflow and underflow handlers. + * + * REGISTERS SAME AS AT _ISR_Handler + */ + + sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp + ! make space for ISF + + std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC + st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC + st %g1, [%sp + ISF_G1_OFFSET] ! save g1 + std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3 + std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above + std %g6, [%sp + ISF_G6_OFFSET] ! save g6, g7 + + std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1 + std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3 + std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5 + std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7 + + rd %y, %g1 + st %g1, [%sp + ISF_Y_OFFSET] ! save y + + mov %sp, %o1 ! 2nd arg to ISR Handler + + /* + * Increment ISR nest level and Thread dispatch disable level. + * + * Register usage for this section: + * + * l4 = _Thread_Dispatch_disable_level pointer + * l5 = _ISR_Nest_level pointer + * l6 = _Thread_Dispatch_disable_level value + * l7 = _ISR_Nest_level value + * + * NOTE: It is assumed that l4 - l7 will be preserved until the ISR + * nest and thread dispatch disable levels are unnested. + */ + + sethi %hi(SYM(_Thread_Dispatch_disable_level)), %l4 + ld [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))], %l6 + sethi %hi(SYM(_ISR_Nest_level)), %l5 + ld [%l5 + %lo(SYM(_ISR_Nest_level))], %l7 + + add %l6, 1, %l6 + st %l6, [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))] + + add %l7, 1, %l7 + st %l7, [%l5 + %lo(SYM(_ISR_Nest_level))] + + /* + * If ISR nest level was zero (now 1), then switch stack. + */ + + mov %sp, %fp + subcc %l7, 1, %l7 ! outermost interrupt handler? + bnz dont_switch_stacks ! No, then do not switch stacks + + sethi %hi(SYM(_CPU_Interrupt_stack_high)), %g4 + ld [%g4 + %lo(SYM(_CPU_Interrupt_stack_high))], %sp + +dont_switch_stacks: + /* + * Make sure we have a place on the stack for the window overflow + * trap handler to write into. At this point it is safe to + * enable traps again. + */ + + sub %sp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp + + wr %l0, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** + + /* + * Vector to user's handler. + * + * NOTE: TBR may no longer have vector number in it since + * we just enabled traps. It is definitely in l3. + */ + + sethi %hi(SYM(_ISR_Vector_table)), %g4 + or %g4, %lo(SYM(_ISR_Vector_table)), %g4 + and %l3, 0xFF, %g5 ! remove synchronous trap indicator + sll %g5, 2, %g5 ! g5 = offset into table + ld [%g4 + %g5], %g4 ! g4 = _ISR_Vector_table[ vector ] + + + ! o1 = 2nd arg = address of the ISF + ! WAS LOADED WHEN ISF WAS SAVED!!! + mov %l3, %o0 ! o0 = 1st arg = vector number + call %g4, 0 + nop ! delay slot + + /* + * Redisable traps so we can finish up the interrupt processing. + * This is a VERY conservative place to do this. + * + * NOTE: %l0 has the PSR which was in place when we took the trap. + */ + + mov %l0, %psr ! **** DISABLE TRAPS **** + + /* + * Decrement ISR nest level and Thread dispatch disable level. + * + * Register usage for this section: + * + * l4 = _Thread_Dispatch_disable_level pointer + * l5 = _ISR_Nest_level pointer + * l6 = _Thread_Dispatch_disable_level value + * l7 = _ISR_Nest_level value + */ + + sub %l6, 1, %l6 + st %l6, [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))] + + st %l7, [%l5 + %lo(SYM(_ISR_Nest_level))] + + /* + * If dispatching is disabled (includes nested interrupt case), + * then do a "simple" exit. + */ + + orcc %l6, %g0, %g0 ! Is dispatching disabled? + bnz simple_return ! Yes, then do a "simple" exit + nop ! delay slot + + /* + * If a context switch is necessary, then do fudge stack to + * return to the interrupt dispatcher. + */ + + sethi %hi(SYM(_Context_Switch_necessary)), %l4 + ld [%l4 + %lo(SYM(_Context_Switch_necessary))], %l5 + + orcc %l5, %g0, %g0 ! Is thread switch necessary? + bnz SYM(_ISR_Dispatch) ! yes, then invoke the dispatcher + nop ! delay slot + + /* + * Finally, check to see if signals were sent to the currently + * executing task. If so, we need to invoke the interrupt dispatcher. + */ + + sethi %hi(SYM(_ISR_Signals_to_thread_executing)), %l6 + ld [%l6 + %lo(SYM(_ISR_Signals_to_thread_executing))], %l7 + + orcc %l7, %g0, %g0 ! Were signals sent to the currently + ! executing thread? + bz simple_return ! yes, then invoke the dispatcher + nop ! delay slot + + /* + * Invoke interrupt dispatcher. + */ + + PUBLIC(_ISR_Dispatch) +SYM(_ISR_Dispatch): + + /* + * The following subtract should get us back on the interrupted + * tasks stack and add enough room to invoke the dispatcher. + * When we enable traps, we are mostly back in the context + * of the task and subsequent interrupts can operate normally. + */ + + sub %fp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp + + or %l0, SPARC_PSR_ET_MASK, %l7 ! l7 = PSR with ET=1 + mov %l7, %psr ! **** ENABLE TRAPS **** + nop + nop + nop + + call SYM(_Thread_Dispatch), 0 + nop + + /* + * The CWP in place at this point may be different from + * that which was in effect at the beginning of the ISR if we + * have been context switched between the beginning of this invocation + * of _ISR_Handler and this point. Thus the CWP and WIM should + * not be changed back to their values at ISR entry time. Any + * changes to the PSR must preserve the CWP. + */ + +simple_return: + ld [%fp + ISF_Y_OFFSET], %l5 ! restore y + wr %l5, 0, %y + + ldd [%fp + ISF_PSR_OFFSET], %l0 ! restore psr, PC + ld [%fp + ISF_NPC_OFFSET], %l2 ! restore nPC + rd %psr, %l3 + and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP + andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task + or %l3, %l0, %l0 ! install it later... + andn %l0, SPARC_PSR_ET_MASK, %l0 + + /* + * Restore tasks global and out registers + */ + + mov %fp, %g1 + + ! g1 is restored later + ldd [%fp + ISF_G2_OFFSET], %g2 ! restore g2, g3 + ldd [%fp + ISF_G4_OFFSET], %g4 ! restore g4, g5 + ldd [%fp + ISF_G6_OFFSET], %g6 ! restore g6, g7 + + ldd [%fp + ISF_I0_OFFSET], %i0 ! restore i0, i1 + ldd [%fp + ISF_I2_OFFSET], %i2 ! restore i2, i3 + ldd [%fp + ISF_I4_OFFSET], %i4 ! restore i4, i5 + ldd [%fp + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7 + + /* + * Registers: + * + * ALL global registers EXCEPT G1 and the input registers have + * already been restored and thuse off limits. + * + * The following is the contents of the local registers: + * + * l0 = original psr + * l1 = return address (i.e. PC) + * l2 = nPC + * l3 = CWP + */ + + /* + * if (CWP + 1) is an invalid window then we need to reload it. + * + * WARNING: Traps should now be disabled + */ + + mov %l0, %psr ! **** DISABLE TRAPS **** + nop + nop + nop + rd %wim, %l4 + add %l0, 1, %l6 ! l6 = cwp + 1 + and %l6, SPARC_PSR_CWP_MASK, %l6 ! do the modulo on it + srl %l4, %l6, %l5 ! l5 = win >> cwp + 1 ; shift count + ! and CWP are conveniently LS 5 bits + cmp %l5, 1 ! Is tasks window invalid? + bne good_task_window + + /* + * The following code is the same as a 1 position left rotate of WIM. + */ + + sll %l4, 1, %l5 ! l5 = WIM << 1 + srl %l4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4 + ! l4 = WIM >> (Number Windows - 1) + or %l4, %l5, %l4 ! l4 = (WIM << 1) | + ! (WIM >> (Number Windows - 1)) + + /* + * Now restore the window just as if we underflowed to it. + */ + + wr %l4, 0, %wim ! WIM = new WIM + restore ! now into the tasks window + + ldd [%g1 + CPU_STACK_FRAME_L0_OFFSET], %l0 + ldd [%g1 + CPU_STACK_FRAME_L2_OFFSET], %l2 + ldd [%g1 + CPU_STACK_FRAME_L4_OFFSET], %l4 + ldd [%g1 + CPU_STACK_FRAME_L6_OFFSET], %l6 + ldd [%g1 + CPU_STACK_FRAME_I0_OFFSET], %i0 + ldd [%g1 + CPU_STACK_FRAME_I2_OFFSET], %i2 + ldd [%g1 + CPU_STACK_FRAME_I4_OFFSET], %i4 + ldd [%g1 + CPU_STACK_FRAME_I6_FP_OFFSET], %i6 + ! reload of sp clobbers ISF + save ! Back to ISR dispatch window + +good_task_window: + + mov %l0, %psr ! **** DISABLE TRAPS **** + ! and restore condition codes. + ld [%g1 + ISF_G1_OFFSET], %g1 ! restore g1 + jmp %l1 ! transfer control and + rett %l2 ! go back to tasks window - /* - * This discussion ignores a lot of the ugly details in a real - * implementation such as saving enough registers/state to be - * able to do something real. Keep in mind that the goal is - * to invoke a user's ISR handler which is written in C and - * uses a certain set of registers. - * - * Also note that the exact order is to a large extent flexible. - * Hardware will dictate a sequence for a certain subset of - * _ISR_Handler while requirements for setting - */ - - /* - * At entry to "common" _ISR_Handler, the vector number must be - * available. On some CPUs the hardware puts either the vector - * number or the offset into the vector table for this ISR in a - * known place. If the hardware does not give us this information, - * then the assembly portion of RTEMS for this port will contain - * a set of distinct interrupt entry points which somehow place - * the vector number in a known place (which is safe if another - * interrupt nests this one) and branches to _ISR_Handler. - * - * save some or all context on stack - * may need to save some special interrupt information for exit - * - * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) - * if ( _ISR_Nest_level == 0 ) - * switch to software interrupt stack - * #endif - * - * _ISR_Nest_level++; - * - * _Thread_Dispatch_disable_level++; - * - * (*_ISR_Vector_table[ vector ])( vector ); - * - * --_ISR_Nest_level; - * - * if ( _ISR_Nest_level ) - * goto the label "exit interrupt (simple case)" - * - * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) - * restore stack - * #endif - * - * if ( !_Context_Switch_necessary ) - * goto the label "exit interrupt (simple case)" - * - * if ( !_ISR_Signals_to_thread_executing ) - * goto the label "exit interrupt (simple case)" - * - * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch - * - * prepare to get out of interrupt - * return from interrupt (maybe to _ISR_Dispatch) - * - * LABEL "exit interrupt (simple case): - * prepare to get out of interrupt - * return from interrupt - */ +/* end of file */ diff --git a/c/src/exec/score/cpu/sparc/erc32.h b/c/src/exec/score/cpu/sparc/erc32.h new file mode 100644 index 0000000000..9a8b875c49 --- /dev/null +++ b/c/src/exec/score/cpu/sparc/erc32.h @@ -0,0 +1,503 @@ +/* erc32.h + * + * This include file contains information pertaining to the ERC32. + * The ERC32 is a custom SPARC V7 implementation based on the Cypress + * 601/602 chipset. This CPU has a number of on-board peripherals and + * was developed by the European Space Agency to target space applications. + * + * NOTE: Other than where absolutely required, this version currently + * supports only the peripherals and bits used by the basic board + * support package. This includes at least significant pieces of + * the following items: + * + * + UART Channels A and B + * + General Purpose Timer + * + Real Time Clock + * + Watchdog Timer (so it can be disabled) + * + Control Register (so powerdown mode can be enabled) + * + Memory Control Register + * + Interrupt Control + * + * $Id$ + */ + +#ifndef _INCLUDE_ERC32_h +#define _INCLUDE_ERC32_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interrupt Sources + * + * The interrupt source numbers directly map to the trap type and to + * the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + */ + +#define ERC32_INTERRUPT_MASKED_ERRORS 1 +#define ERC32_INTERRUPT_EXTERNAL_1 2 +#define ERC32_INTERRUPT_EXTERNAL_2 3 +#define ERC32_INTERRUPT_UART_A_RX_TX 4 +#define ERC32_INTERRUPT_UART_B_RX_TX 5 +#define ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR 6 +#define ERC32_INTERRUPT_UART_ERROR 7 +#define ERC32_INTERRUPT_DMA_ACCESS_ERROR 8 +#define ERC32_INTERRUPT_DMA_TIMEOUT 9 +#define ERC32_INTERRUPT_EXTERNAL_3 10 +#define ERC32_INTERRUPT_EXTERNAL_4 11 +#define ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER 12 +#define ERC32_INTERRUPT_REAL_TIME_CLOCK 13 +#define ERC32_INTERRUPT_EXTERNAL_5 14 +#define ERC32_INTERRUPT_WATCHDOG_TIMEOUT 15 + +#ifndef ASM + +/* + * Trap Types for on-chip peripherals + * + * Source: Table 8 - Interrupt Trap Type and Default Priority Assignments + * + * NOTE: The priority level for each source corresponds to the least + * significant nibble of the trap type. + */ + +#define ERC32_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10) + +#define ERC32_TRAP_SOURCE( _trap ) ((_trap) - 0x10) + +#define ERC32_Is_MEC_Trap( _trap ) \ + ( (_trap) >= ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ) && \ + (_trap) <= ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ) ) + +/* + * Structure for ERC32 memory mapped registers. + * + * Source: Section 3.25.2 - Register Address Map + * + * NOTE: There is only one of these structures per CPU, its base address + * is 0x01f80000, and the variable MEC is placed there by the + * linkcmds file. + */ + +typedef struct { + volatile unsigned32 Control; /* offset 0x00 */ + volatile unsigned32 Software_Reset; /* offset 0x04 */ + volatile unsigned32 Power_Down; /* offset 0x08 */ + volatile unsigned32 Unimplemented_0; /* offset 0x0c */ + volatile unsigned32 Memory_Configuration; /* offset 0x10 */ + volatile unsigned32 IO_Configuration; /* offset 0x14 */ + volatile unsigned32 Wait_State_Configuration; /* offset 0x18 */ + volatile unsigned32 Unimplemented_1; /* offset 0x1c */ + volatile unsigned32 Memory_Access_0; /* offset 0x20 */ + volatile unsigned32 Memory_Access_1; /* offset 0x24 */ + volatile unsigned32 Unimplemented_2[ 7 ]; /* offset 0x28 */ + volatile unsigned32 Interrupt_Shape; /* offset 0x44 */ + volatile unsigned32 Interrupt_Pending; /* offset 0x48 */ + volatile unsigned32 Interrupt_Mask; /* offset 0x4c */ + volatile unsigned32 Interrupt_Clear; /* offset 0x50 */ + volatile unsigned32 Interrupt_Force; /* offset 0x54 */ + volatile unsigned32 Unimplemented_3[ 2 ]; /* offset 0x58 */ + /* offset 0x60 */ + volatile unsigned32 Watchdog_Program_and_Timeout_Acknowledge; + volatile unsigned32 Watchdog_Trap_Door_Set; /* offset 0x64 */ + volatile unsigned32 Unimplemented_4[ 6 ]; /* offset 0x68 */ + volatile unsigned32 Real_Time_Clock_Counter; /* offset 0x80 */ + volatile unsigned32 Real_Time_Clock_Scalar; /* offset 0x84 */ + volatile unsigned32 General_Purpose_Timer_Counter; /* offset 0x88 */ + volatile unsigned32 General_Purpose_Timer_Scalar; /* offset 0x8c */ + volatile unsigned32 Unimplemented_5[ 2 ]; /* offset 0x90 */ + volatile unsigned32 Timer_Control; /* offset 0x98 */ + volatile unsigned32 Unimplemented_6; /* offset 0x9c */ + volatile unsigned32 System_Fault_Status; /* offset 0xa0 */ + volatile unsigned32 First_Failing_Address; /* offset 0xa4 */ + volatile unsigned32 First_Failing_Data; /* offset 0xa8 */ + volatile unsigned32 First_Failing_Syndrome_and_Check_Bits;/* offset 0xac */ + volatile unsigned32 Error_and_Reset_Status; /* offset 0xb0 */ + volatile unsigned32 Error_Mask; /* offset 0xb4 */ + volatile unsigned32 Unimplemented_7[ 2 ]; /* offset 0xb8 */ + volatile unsigned32 Debug_Control; /* offset 0xc0 */ + volatile unsigned32 Breakpoint; /* offset 0xc4 */ + volatile unsigned32 Watchpoint; /* offset 0xc8 */ + volatile unsigned32 Unimplemented_8; /* offset 0xcc */ + volatile unsigned32 Test_Control; /* offset 0xd0 */ + volatile unsigned32 Test_Data; /* offset 0xd4 */ + volatile unsigned32 Unimplemented_9[ 2 ]; /* offset 0xd8 */ + volatile unsigned32 UART_Channel_A; /* offset 0xe0 */ + volatile unsigned32 UART_Channel_B; /* offset 0xe4 */ + volatile unsigned32 UART_Status; /* offset 0xe8 */ +} ERC32_Register_Map; + +#endif + +/* + * The following constants are intended to be used ONLY in assembly + * language files. + * + * NOTE: The intended style of usage is to load the address of MEC + * into a register and then use these as displacements from + * that register. + */ + +#ifdef ASM + +#define ERC32_MEC_CONTROL_OFFSET 0x00 +#define ERC32_MEC_SOFTWARE_RESET_OFFSET 0x04 +#define ERC32_MEC_POWER_DOWN_OFFSET 0x08 +#define ERC32_MEC_UNIMPLEMENTED_0_OFFSET 0x0C +#define ERC32_MEC_MEMORY_CONFIGURATION_OFFSET 0x10 +#define ERC32_MEC_IO_CONFIGURATION_OFFSET 0x14 +#define ERC32_MEC_WAIT_STATE_CONFIGURATION_OFFSET 0x18 +#define ERC32_MEC_UNIMPLEMENTED_1_OFFSET 0x1C +#define ERC32_MEC_MEMORY_ACCESS_0_OFFSET 0x20 +#define ERC32_MEC_MEMORY_ACCESS_1_OFFSET 0x24 +#define ERC32_MEC_UNIMPLEMENTED_2_OFFSET 0x28 +#define ERC32_MEC_INTERRUPT_SHAPE_OFFSET 0x44 +#define ERC32_MEC_INTERRUPT_PENDING_OFFSET 0x48 +#define ERC32_MEC_INTERRUPT_MASK_OFFSET 0x4C +#define ERC32_MEC_INTERRUPT_CLEAR_OFFSET 0x50 +#define ERC32_MEC_INTERRUPT_FORCE_OFFSET 0x54 +#define ERC32_MEC_UNIMPLEMENTED_3_OFFSET 0x58 +#define ERC32_MEC_WATCHDOG_PROGRAM_AND_TIMEOUT_ACKNOWLEDGE_OFFSET 0x60 +#define ERC32_MEC_WATCHDOG_TRAP_DOOR_SET_OFFSET 0x64 +#define ERC32_MEC_UNIMPLEMENTED_4_OFFSET 0x6C +#define ERC32_MEC_REAL_TIME_CLOCK_COUNTER_OFFSET 0x80 +#define ERC32_MEC_REAL_TIME_CLOCK_SCALAR_OFFSET 0x84 +#define ERC32_MEC_GENERAL_PURPOSE_TIMER_COUNTER_OFFSET 0x88 +#define ERC32_MEC_GENERAL_PURPOSE_TIMER_SCALAR_OFFSET 0x8C +#define ERC32_MEC_UNIMPLEMENTED_5_OFFSET 0x90 +#define ERC32_MEC_TIMER_CONTROL_OFFSET 0x98 +#define ERC32_MEC_UNIMPLEMENTED_6_OFFSET 0x9C +#define ERC32_MEC_SYSTEM_FAULT_STATUS_OFFSET 0xA0 +#define ERC32_MEC_FIRST_FAILING_ADDRESS_OFFSET 0xA4 +#define ERC32_MEC_FIRST_FAILING_DATA_OFFSET 0xA8 +#define ERC32_MEC_FIRST_FAILING_SYNDROME_AND_CHECK_BITS_OFFSET 0xAC +#define ERC32_MEC_ERROR_AND_RESET_STATUS_OFFSET 0xB0 +#define ERC32_MEC_ERROR_MASK_OFFSET 0xB4 +#define ERC32_MEC_UNIMPLEMENTED_7_OFFSET 0xB8 +#define ERC32_MEC_DEBUG_CONTROL_OFFSET 0xC0 +#define ERC32_MEC_BREAKPOINT_OFFSET 0xC4 +#define ERC32_MEC_WATCHPOINT_OFFSET 0xC8 +#define ERC32_MEC_UNIMPLEMENTED_8_OFFSET 0xCC +#define ERC32_MEC_TEST_CONTROL_OFFSET 0xD0 +#define ERC32_MEC_TEST_DATA_OFFSET 0xD4 +#define ERC32_MEC_UNIMPLEMENTED_9_OFFSET 0xD8 +#define ERC32_MEC_UART_CHANNEL_A_OFFSET 0xE0 +#define ERC32_MEC_UART_CHANNEL_B_OFFSET 0xE4 +#define ERC32_MEC_UART_STATUS_OFFSET 0xE8 + +#endif + +/* + * The following defines the bits in the Configuration Register. + */ + +#define ERC32_CONFIGURATION_POWER_DOWN_MASK 0x00000001 +#define ERC32_CONFIGURATION_POWER_DOWN_ALLOWED 0x00000001 +#define ERC32_CONFIGURATION_POWER_DOWN_DISABLED 0x00000000 + +#define ERC32_CONFIGURATION_SOFTWARE_RESET_MASK 0x00000002 +#define ERC32_CONFIGURATION_SOFTWARE_RESET_ALLOWED 0x00000002 +#define ERC32_CONFIGURATION_SOFTWARE_RESET_DISABLED 0x00000000 + +#define ERC32_CONFIGURATION_BUS_TIMEOUT_MASK 0x00000004 +#define ERC32_CONFIGURATION_BUS_TIMEOUT_ENABLED 0x00000004 +#define ERC32_CONFIGURATION_BUS_TIMEOUT_DISABLED 0x00000000 + +#define ERC32_CONFIGURATION_ACCESS_PROTECTION_MASK 0x00000008 +#define ERC32_CONFIGURATION_ACCESS_PROTECTION_ENABLED 0x00000008 +#define ERC32_CONFIGURATION_ACCESS_PROTECTION_DISABLED 0x00000000 + + +/* + * The following defines the bits in the Memory Configuration Register. + */ + +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001C00 +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_256K ( 0 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_512K ( 1 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_1MB ( 2 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_2MB ( 3 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_4MB ( 4 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_8MB ( 5 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_16MB ( 6 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_32MB ( 7 << 10 ) + +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x001C0000 +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_4K ( 0 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_8K ( 1 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_16K ( 2 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_32K ( 3 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_64K ( 4 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_128K ( 5 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_256K ( 6 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_512K ( 7 << 18 ) + +/* + * The following defines the bits in the Timer Control Register. + */ + +#define ERC32_MEC_TIMER_CONTROL_GCR 0x00000001 /* 1 = reload at 0 */ + /* 0 = stop at 0 */ +#define ERC32_MEC_TIMER_CONTROL_GCL 0x00000002 /* 1 = load and start */ + /* 0 = no function */ +#define ERC32_MEC_TIMER_CONTROL_GSE 0x00000004 /* 1 = enable counting */ + /* 0 = hold scalar and counter */ +#define ERC32_MEC_TIMER_CONTROL_GSL 0x00000008 /* 1 = load scalar and start */ + /* 0 = no function */ + +#define ERC32_MEC_TIMER_CONTROL_RTCCR 0x00000100 /* 1 = reload at 0 */ + /* 0 = stop at 0 */ +#define ERC32_MEC_TIMER_CONTROL_RTCCL 0x00000200 /* 1 = load and start */ + /* 0 = no function */ +#define ERC32_MEC_TIMER_CONTROL_RTCSE 0x00000400 /* 1 = enable counting */ + /* 0 = hold scalar and counter */ +#define ERC32_MEC_TIMER_CONTROL_RTCSL 0x00000800 /* 1 = load scalar and start */ + /* 0 = no function */ + +/* + * The following defines the bits in the UART Control Registers. + * + * NOTE: Same bits in UART channels A and B. + */ + +#define ERC32_MEC_UART_CONTROL_RTD 0x000000FF /* RX/TX data */ +#define ERC32_MEC_UART_CONTROL_DR 0x00000100 /* RX Data Ready */ +#define ERC32_MEC_UART_CONTROL_TSE 0x00000200 /* TX Send Empty */ + /* (i.e. no data to send) */ +#define ERC32_MEC_UART_CONTROL_THE 0x00000400 /* TX Hold Empty */ + /* (i.e. ready to load) */ + +/* + * The following defines the bits in the MEC UART Control Registers. + */ + +#define ERC32_MEC_UART_STATUS_DR 0x00000001 /* Data Ready */ +#define ERC32_MEC_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */ +#define ERC32_MEC_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */ +#define ERC32_MEC_UART_STATUS_FE 0x00000010 /* RX Framing Error */ +#define ERC32_MEC_UART_STATUS_PE 0x00000020 /* RX Parity Error */ +#define ERC32_MEC_UART_STATUS_OE 0x00000040 /* RX Overrun Error */ +#define ERC32_MEC_UART_STATUS_CU 0x00000080 /* Clear Errors */ +#define ERC32_MEC_UART_STATUS_TXE 0x00000006 /* TX Empty */ + +#define ERC32_MEC_UART_STATUS_DRA (ERC32_MEC_UART_STATUS_DR << 0) +#define ERC32_MEC_UART_STATUS_TSEA (ERC32_MEC_UART_STATUS_TSE << 0) +#define ERC32_MEC_UART_STATUS_THEA (ERC32_MEC_UART_STATUS_THE << 0) +#define ERC32_MEC_UART_STATUS_FEA (ERC32_MEC_UART_STATUS_FE << 0) +#define ERC32_MEC_UART_STATUS_PEA (ERC32_MEC_UART_STATUS_PE << 0) +#define ERC32_MEC_UART_STATUS_OEA (ERC32_MEC_UART_STATUS_OE << 0) +#define ERC32_MEC_UART_STATUS_CUA (ERC32_MEC_UART_STATUS_CU << 0) +#define ERC32_MEC_UART_STATUS_TXEA (ERC32_MEC_UART_STATUS_TXE << 0) + +#define ERC32_MEC_UART_STATUS_DRB (ERC32_MEC_UART_STATUS_DR << 16) +#define ERC32_MEC_UART_STATUS_TSEB (ERC32_MEC_UART_STATUS_TSE << 16) +#define ERC32_MEC_UART_STATUS_THEB (ERC32_MEC_UART_STATUS_THE << 16) +#define ERC32_MEC_UART_STATUS_FEB (ERC32_MEC_UART_STATUS_FE << 16) +#define ERC32_MEC_UART_STATUS_PEB (ERC32_MEC_UART_STATUS_PE << 16) +#define ERC32_MEC_UART_STATUS_OEB (ERC32_MEC_UART_STATUS_OE << 16) +#define ERC32_MEC_UART_STATUS_CUB (ERC32_MEC_UART_STATUS_CU << 16) +#define ERC32_MEC_UART_STATUS_TXEB (ERC32_MEC_UART_STATUS_TXE << 16) + +#ifndef ASM + +/* + * This is used to manipulate the on-chip registers. + * + * The following symbol must be defined in the linkcmds file and point + * to the correct location. + */ + +extern ERC32_Register_Map ERC32_MEC; + +/* + * Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + * + * NOTE: For operations which are not atomic, this code disables interrupts + * to guarantee there are no intervening accesses to the same register. + * The operations which read the register, modify the value and then + * store the result back are vulnerable. + */ + +#define ERC32_Clear_interrupt( _source ) \ + do { \ + ERC32_MEC.Interrupt_Clear = (1 << (_source)); \ + } while (0) + +#define ERC32_Force_interrupt( _source ) \ + do { \ + ERC32_MEC.Interrupt_Force = (1 << (_source)); \ + } while (0) + +#define ERC32_Is_interrupt_pending( _source ) \ + (ERC32_MEC.Interrupt_Pending & (1 << (_source))) + +#define ERC32_Is_interrupt_masked( _source ) \ + (ERC32_MEC.Interrupt_Masked & (1 << (_source))) + +#define ERC32_Mask_interrupt( _source ) \ + do { \ + unsigned32 _level; \ + \ + sparc_disable_interrupts( _level ); \ + ERC32_MEC.Interrupt_Mask |= (1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define ERC32_Unmask_interrupt( _source ) \ + do { \ + unsigned32 _level; \ + \ + sparc_disable_interrupts( _level ); \ + ERC32_MEC.Interrupt_Mask &= ~(1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define ERC32_Disable_interrupt( _source, _previous ) \ + do { \ + unsigned32 _level; \ + unsigned32 _mask = 1 << (_source); \ + \ + sparc_disable_interrupts( _level ); \ + (_previous) = ERC32_MEC.Interrupt_Mask; \ + ERC32_MEC.Interrupt_Mask = _previous | _mask; \ + sparc_enable_interrupts( _level ); \ + (_previous) &= ~_mask; \ + } while (0) + +#define ERC32_Restore_interrupt( _source, _previous ) \ + do { \ + unsigned32 _level; \ + unsigned32 _mask = 1 << (_source); \ + \ + sparc_disable_interrupts( _level ); \ + ERC32_MEC.Interrupt_Mask = \ + (ERC32_MEC.Interrupt_Mask & ~_mask) | (_previous); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +/* + * The following macros attempt to hide the fact that the General Purpose + * Timer and Real Time Clock Timer share the Timer Control Register. Because + * the Timer Control Register is write only, we must mirror it in software + * and insure that writes to one timer do not alter the current settings + * and status of the other timer. + * + * This code promotes the view that the two timers are completely independent. + * By exclusively using the routines below to access the Timer Control + * Register, the application can view the system as having a General Purpose + * Timer Control Register and a Real Time Clock Timer Control Register + * rather than the single shared value. + * + * Each logical timer control register is organized as follows: + * + * D0 - Counter Reload + * 1 = reload counter at zero and restart + * 0 = stop counter at zero + * + * D1 - Counter Load + * 1 = load counter with preset value and restart + * 0 = no function + * + * D2 - Enable + * 1 = enable counting + * 0 = hold scaler and counter + * + * D2 - Scaler Load + * 1 = load scalar with preset value and restart + * 0 = no function + * + * To insure the management of the mirror is atomic, we disable interrupts + * around updates. + */ + +#define ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000001 +#define ERC32_MEC_TIMER_COUNTER_STOP_AT_ZERO 0x00000000 + +#define ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER 0x00000002 + +#define ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING 0x00000004 +#define ERC32_MEC_TIMER_COUNTER_DISABLE_COUNTING 0x00000000 + +#define ERC32_MEC_TIMER_COUNTER_LOAD_SCALER 0x00000008 + +#define ERC32_MEC_TIMER_COUNTER_RELOAD_MASK 0x00000001 +#define ERC32_MEC_TIMER_COUNTER_ENABLE_MASK 0x00000004 + +#define ERC32_MEC_TIMER_COUNTER_DEFINED_MASK 0x0000000F +#define ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000005 + +extern unsigned32 _ERC32_MEC_Timer_Control_Mirror; + +/* + * This macros manipulate the General Purpose Timer portion of the + * Timer Control register and promote the view that there are actually + * two independent Timer Control Registers. + */ + +#define ERC32_MEC_Set_General_Purpose_Timer_Control( _value ) \ + do { \ + unsigned32 _level; \ + unsigned32 _control; \ + unsigned32 __value; \ + \ + __value = ((_value) & 0x0f); \ + sparc_disable_interrupts( _level ); \ + _control = _ERC32_MEC_Timer_Control_Mirror; \ + _control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK << 8; \ + _ERC32_MEC_Timer_Control_Mirror = _control | _value; \ + _control &= (ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK << 8); \ + _control |= __value; \ + /* printf( "GPT 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \ + ERC32_MEC.Timer_Control = _control; \ + sparc_enable_interrupts( _level ); \ + } while ( 0 ) + +#define ERC32_MEC_Get_General_Purpose_Timer_Control( _value ) \ + do { \ + (_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \ + } while ( 0 ) + +/* + * This macros manipulate the Real Timer Clock Timer portion of the + * Timer Control register and promote the view that there are actually + * two independent Timer Control Registers. + */ + +#define ERC32_MEC_Set_Real_Time_Clock_Timer_Control( _value ) \ + do { \ + unsigned32 _level; \ + unsigned32 _control; \ + unsigned32 __value; \ + \ + __value = ((_value) & 0x0f) << 8; \ + sparc_disable_interrupts( _level ); \ + _control = _ERC32_MEC_Timer_Control_Mirror; \ + _control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK; \ + _ERC32_MEC_Timer_Control_Mirror = _control | _value; \ + _control &= ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK; \ + _control |= __value; \ + /* printf( "RTC 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \ + ERC32_MEC.Timer_Control = _control; \ + sparc_enable_interrupts( _level ); \ + } while ( 0 ) + +#define ERC32_MEC_Get_Real_Time_Clock_Timer_Control( _value ) \ + do { \ + (_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \ + } while ( 0 ) + + +#endif /* !ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_INCLUDE_ERC32_h */ +/* end of include file */ + diff --git a/c/src/exec/score/cpu/sparc/rtems.s b/c/src/exec/score/cpu/sparc/rtems.s index 2b9bd10454..75aa41f83b 100644 --- a/c/src/exec/score/cpu/sparc/rtems.s +++ b/c/src/exec/score/cpu/sparc/rtems.s @@ -22,12 +22,22 @@ * is used to look up the directive. * * void RTEMS() - * { - * } */ .align 4 PUBLIC(RTEMS) SYM(RTEMS): - ret + /* + * g2 was chosen because gcc uses it as a scratch register in + * similar code scenarios and the other locals, ins, and outs + * are off limits to this routine unless it does a "save" and + * copies its in registers to the outs which only works up until + * 6 parameters. Best to take the simple approach in this case. + */ + sethi SYM(_Entry_points), %g2 + or %g2, %lo(SYM(_Entry_points)), %g2 + sll %g1, 2, %g1 + add %g1, %g2, %g2 + jmp %g2 + nop diff --git a/c/src/exec/score/cpu/sparc/sparc.h b/c/src/exec/score/cpu/sparc/sparc.h index 3c5f0574f5..d6f263643b 100644 --- a/c/src/exec/score/cpu/sparc/sparc.h +++ b/c/src/exec/score/cpu/sparc/sparc.h @@ -1,7 +1,7 @@ /* sparc.h * - * This include file contains information pertaining to the Motorola - * SPARC processor family. + * This include file contains information pertaining to the SPARC + * processor family. * * $Id$ */ @@ -37,8 +37,7 @@ extern "C" { /* * This file contains the information required to build - * RTEMS for a particular member of the "sparc" - * family when executing in protected mode. It does + * RTEMS for a particular member of the "sparc" family. It does * this by setting variables to indicate which implementation * dependent features are present in a particular member * of the family. @@ -51,15 +50,25 @@ extern "C" { * * + SPARC_HAS_BITSCAN * 0 - does not have scan instructions - * 1 - has scan instruction (no support implemented) + * 1 - has scan instruction (not currently implemented) * + * + SPARC_NUMBER_OF_REGISTER_WINDOWS + * 8 is the most common number supported by SPARC implementations. + * SPARC_PSR_CWP_MASK is derived from this value. + * + * + SPARC_HAS_LOW_POWER_MODE + * 0 - does not have low power mode support (or not supported) + * 1 - has low power mode and thus a CPU model dependent idle task. + * */ #if defined(erc32) -#define CPU_MODEL_NAME "erc32" -#define SPARC_HAS_FPU 1 -#define SPARC_HAS_BITSCAN 0 +#define CPU_MODEL_NAME "erc32" +#define SPARC_HAS_FPU 1 +#define SPARC_HAS_BITSCAN 0 +#define SPARC_NUMBER_OF_REGISTER_WINDOWS 8 +#define SPARC_HAS_LOW_POWER_MODE 1 #else @@ -73,6 +82,49 @@ extern "C" { #define CPU_NAME "SPARC" +/* + * Miscellaneous constants + */ + +/* + * PSR masks and starting bit positions + * + * NOTE: Reserved bits are ignored. + */ + +#if (SPARC_NUMBER_OF_REGISTER_WINDOWS == 8) +#define SPARC_PSR_CWP_MASK 0x07 /* bits 0 - 4 */ +#elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 16) +#define SPARC_PSR_CWP_MASK 0x0F /* bits 0 - 4 */ +#elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 32) +#define SPARC_PSR_CWP_MASK 0x1F /* bits 0 - 4 */ +#else +#error "Unsupported number of register windows for this cpu" +#endif + +#define SPARC_PSR_ET_MASK 0x00000020 /* bit 5 */ +#define SPARC_PSR_PS_MASK 0x00000040 /* bit 6 */ +#define SPARC_PSR_S_MASK 0x00000080 /* bit 7 */ +#define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */ +#define SPARC_PSR_EF_MASK 0x00001000 /* bit 12 */ +#define SPARC_PSR_EC_MASK 0x00002000 /* bit 13 */ +#define SPARC_PSR_ICC_MASK 0x00F00000 /* bits 20 - 23 */ +#define SPARC_PSR_VER_MASK 0x0F000000 /* bits 24 - 27 */ +#define SPARC_PSR_IMPL_MASK 0xF0000000 /* bits 28 - 31 */ + +#define SPARC_PSR_CWP_BIT_POSITION 0 /* bits 0 - 4 */ +#define SPARC_PSR_ET_BIT_POSITION 5 /* bit 5 */ +#define SPARC_PSR_PS_BIT_POSITION 6 /* bit 6 */ +#define SPARC_PSR_S_BIT_POSITION 7 /* bit 7 */ +#define SPARC_PSR_PIL_BIT_POSITION 8 /* bits 8 - 11 */ +#define SPARC_PSR_EF_BIT_POSITION 12 /* bit 12 */ +#define SPARC_PSR_EC_BIT_POSITION 13 /* bit 13 */ +#define SPARC_PSR_ICC_BIT_POSITION 20 /* bits 20 - 23 */ +#define SPARC_PSR_VER_BIT_POSITION 24 /* bits 24 - 27 */ +#define SPARC_PSR_IMPL_BIT_POSITION 28 /* bits 28 - 31 */ + +#ifndef ASM + /* * Standard nop */ @@ -83,7 +135,7 @@ extern "C" { } while ( 0 ) /* - * Some macros to aid in accessing special registers. + * Get and set the PSR */ #define sparc_get_psr( _psr ) \ @@ -94,26 +146,56 @@ extern "C" { #define sparc_set_psr( _psr ) \ do { \ - asm volatile ( "wr %%g0,%0,%%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \ - nop(); nop(); nop(); \ + asm volatile ( "mov %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \ + nop(); \ + nop(); \ + nop(); \ } while ( 0 ) +/* + * Get and set the TBR + */ + #define sparc_get_tbr( _tbr ) \ do { \ + (_tbr) = 0; /* to avoid unitialized warnings */ \ asm volatile( "rd %%tbr, %0" : "=r" (_tbr) : "0" (_tbr) ); \ } while ( 0 ) #define sparc_set_tbr( _tbr ) \ do { \ + asm volatile( "wr %0, 0, %%tbr" : "=r" (_tbr) : "0" (_tbr) ); \ } while ( 0 ) +/* + * Get and set the WIM + */ + #define sparc_get_wim( _wim ) \ do { \ - asm volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \ + asm volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \ } while ( 0 ) #define sparc_set_wim( _wim ) \ do { \ + asm volatile( "wr %0, %%wim" : "=r" (_wim) : "0" (_wim) ); \ + nop(); \ + nop(); \ + nop(); \ + } while ( 0 ) + +/* + * Get and set the Y + */ + +#define sparc_get_y( _y ) \ + do { \ + asm volatile( "rd %%y, %0" : "=r" (_y) : "0" (_y) ); \ + } while ( 0 ) + +#define sparc_set_y( _y ) \ + do { \ + asm volatile( "wr %0, %%y" : "=r" (_y) : "0" (_y) ); \ } while ( 0 ) /* @@ -121,42 +203,41 @@ extern "C" { * */ -#define SPARC_PIL_MASK 0x00000F00 - #define sparc_disable_interrupts( _level ) \ - do { register unsigned int _mask = SPARC_PIL_MASK; \ - (_level) = 0; \ + do { \ + register unsigned int _newlevel; \ \ - asm volatile ( "rd %%psr,%0 ; \ - wr %0,%1,%%psr " \ - : "=r" ((_level)), "=r" (_mask) \ - : "0" ((_level)), "1" (_mask) \ - ); \ - nop(); nop(); nop(); \ + sparc_get_psr( _level ); \ + (_newlevel) = (_level) | SPARC_PSR_PIL_MASK; \ + sparc_set_psr( _newlevel ); \ } while ( 0 ) #define sparc_enable_interrupts( _level ) \ - do { unsigned int _tmp; \ + do { \ + unsigned int _tmp; \ + \ sparc_get_psr( _tmp ); \ - _tmp &= ~SPARC_PIL_MASK; \ - _tmp |= (_level) & SPARC_PIL_MASK; \ + _tmp &= ~SPARC_PSR_PIL_MASK; \ + _tmp |= (_level) & SPARC_PSR_PIL_MASK; \ sparc_set_psr( _tmp ); \ } while ( 0 ) - #define sparc_flash_interrupts( _level ) \ do { \ - register unsigned32 _ignored = 0; \ - sparc_enable_interrupts( (_level) ); \ - sparc_disable_interrupts( _ignored ); \ + register unsigned32 _ignored = 0; \ + \ + sparc_enable_interrupts( (_level) ); \ + sparc_disable_interrupts( _ignored ); \ } while ( 0 ) #define sparc_set_interrupt_level( _new_level ) \ - do { register unsigned32 _new_psr_level = 0; \ + do { \ + register unsigned32 _new_psr_level = 0; \ \ sparc_get_psr( _new_psr_level ); \ - _new_psr_level &= ~SPARC_PIL_MASK; \ - _new_psr_level |= (((_new_level) << 8) & SPARC_PIL_MASK); \ + _new_psr_level &= ~SPARC_PSR_PIL_MASK; \ + _new_psr_level |= \ + (((_new_level) << SPARC_PSR_PIL_BIT_POSITION) & SPARC_PSR_PIL_MASK); \ sparc_set_psr( _new_psr_level ); \ } while ( 0 ) @@ -165,9 +246,12 @@ extern "C" { register unsigned32 _psr_level = 0; \ \ sparc_get_psr( _psr_level ); \ - (_level) = (_psr_level & SPARC_PIL_MASK) >> 8; \ + (_level) = \ + (_psr_level & SPARC_PSR_PIL_MASK) >> SPARC_PSR_PIL_BIT_POSITION; \ } while ( 0 ) +#endif + #ifdef __cplusplus } #endif diff --git a/c/src/exec/score/cpu/sparc/sparctypes.h b/c/src/exec/score/cpu/sparc/sparctypes.h index d07501f483..13aeb2473e 100644 --- a/c/src/exec/score/cpu/sparc/sparctypes.h +++ b/c/src/exec/score/cpu/sparc/sparctypes.h @@ -1,6 +1,6 @@ /* sparctypes.h * - * This include file contains type definitions pertaining to the Intel + * This include file contains type definitions pertaining to the * SPARC processor family. * * $Id$ @@ -19,22 +19,22 @@ extern "C" { * This section defines the basic types for this processor. */ -typedef unsigned char unsigned8; /* unsigned 8-bit integer */ -typedef unsigned short unsigned16; /* unsigned 16-bit integer */ -typedef unsigned int unsigned32; /* unsigned 32-bit integer */ -typedef unsigned long long unsigned64; /* unsigned 64-bit integer */ +typedef unsigned char unsigned8; /* unsigned 8-bit integer */ +typedef unsigned short unsigned16; /* unsigned 16-bit integer */ +typedef unsigned int unsigned32; /* unsigned 32-bit integer */ +typedef unsigned long long unsigned64; /* unsigned 64-bit integer */ -typedef unsigned16 Priority_Bit_map_control; +typedef unsigned16 Priority_Bit_map_control; -typedef signed char signed8; /* 8-bit signed integer */ -typedef signed short signed16; /* 16-bit signed integer */ -typedef signed int signed32; /* 32-bit signed integer */ -typedef signed long long signed64; /* 64 bit signed integer */ +typedef signed char signed8; /* 8-bit signed integer */ +typedef signed short signed16; /* 16-bit signed integer */ +typedef signed int signed32; /* 32-bit signed integer */ +typedef signed long long signed64; /* 64 bit signed integer */ -typedef unsigned32 boolean; /* Boolean value */ +typedef unsigned32 boolean; /* Boolean value */ -typedef float single_precision; /* single precision float */ -typedef double double_precision; /* double precision float */ +typedef float single_precision; /* single precision float */ +typedef double double_precision; /* double precision float */ typedef void sparc_isr; typedef void ( *sparc_isr_entry )( void ); diff --git a/c/src/exec/score/cpu/unix/cpu.c b/c/src/exec/score/cpu/unix/cpu.c index 347882ddcc..c77276020b 100644 --- a/c/src/exec/score/cpu/unix/cpu.c +++ b/c/src/exec/score/cpu/unix/cpu.c @@ -341,17 +341,10 @@ void _CPU_Install_interrupt_stack( void ) * * _CPU_Internal_threads_Idle_thread_body * - * NOTES: - * - * 1. This is the same as the regular CPU independent algorithm. - * - * 2. If you implement this using a "halt", "idle", or "shutdown" - * instruction, then don't forget to put it in an infinite loop. - * - * 3. Be warned. Some processors with onboard DMA have been known - * to stop the DMA if the CPU were put in IDLE mode. This might - * also be a problem with other on-chip peripherals. So use this - * hook with caution. + * Stop until we get a signal which is the logically the same thing + * entering low-power or sleep mode on a real processor and waiting for + * an interrupt. This significantly reduces the consumption of host + * CPU cycles which is again similar to low power mode. */ void _CPU_Internal_threads_Idle_thread_body( void ) @@ -370,7 +363,8 @@ void _CPU_Context_Initialize( unsigned32 *_stack_base, unsigned32 _size, unsigned32 _new_level, - void *_entry_point + void *_entry_point, + boolean _is_fp ) { void *source; @@ -697,49 +691,15 @@ void _CPU_Fatal_error(unsigned32 error) _exit(error); } -/*PAGE - * - * _CPU_ffs - */ - -int _CPU_ffs(unsigned32 value) -{ - int output; - extern int ffs( int ); - - output = ffs(value); - output = output - 1; - - return output; -} - - /* * Special Purpose Routines to hide the use of UNIX system calls. */ -#if 0 -/* XXX clock had this set of #define's */ - -/* - * In order to get the types and prototypes used in this file under - * Solaris 2.3, it is necessary to pull the following magic. - */ - -#if defined(solaris) -#warning "Ignore the undefining __STDC__ warning" -#undef __STDC__ -#define __STDC__ 0 -#undef _POSIX_C_SOURCE -#endif -#endif - int _CPU_Get_clock_vector( void ) { return SIGALRM; } - void _CPU_Start_clock( int microseconds ) diff --git a/c/src/exec/score/cpu/unix/cpu.h b/c/src/exec/score/cpu/unix/cpu.h index b4b34d4eff..e002a73f65 100644 --- a/c/src/exec/score/cpu/unix/cpu.h +++ b/c/src/exec/score/cpu/unix/cpu.h @@ -549,7 +549,8 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)(); * by RTEMS. */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS 64 +#define CPU_INTERRUPT_NUMBER_OF_VECTORS 64 +#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* * Should be large enough to run all RTEMS tests. This insures @@ -721,7 +722,8 @@ extern void _CPU_Context_Initialize( unsigned32 *_stack_base, unsigned32 _size, unsigned32 _new_level, - void *_entry_point + void *_entry_point, + boolean _is_fp ); /* end of Context handler macros */ @@ -757,11 +759,11 @@ extern void _CPU_Context_Initialize( * * RTEMS guarantees that (1) will never happen so it is not a concern. * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and - * _CPU_Priority_Bits_index(). These three form a set of routines + * _CPU_Priority_bits_index(). These three form a set of routines * which must logically operate together. Bits in the _value are * set and cleared based on masks built by _CPU_Priority_mask(). * The basic major and minor values calculated by _Priority_Major() - * and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index() + * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index() * to properly range between the values returned by the "find first bit" * instruction. This makes it possible for _Priority_Get_highest() to * calculate the major and directly index into the minor table. @@ -796,30 +798,25 @@ extern void _CPU_Context_Initialize( * bit set */ -#define _CPU_Bitfield_Find_first_bit( _value, _output ) \ - _output = _CPU_ffs( _value ) - -/* end of Bitfield handler macros */ - /* - * This routine builds the mask which corresponds to the bit fields - * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion - * for that routine. + * The UNIX port uses the generic C algorithm for bitfield scan to avoid + * dependencies on either a native bitscan instruction or an ffs() in the + * C library. */ - -#define _CPU_Priority_Mask( _bit_number ) \ - ( 1 << (_bit_number) ) - + +#define CPU_USE_GENERIC_BITFIELD_CODE TRUE +#define CPU_USE_GENERIC_BITFIELD_DATA TRUE + +/* end of Bitfield handler macros */ + +/* Priority handler handler macros */ + /* - * This routine translates the bit numbers returned by - * _CPU_Bitfield_Find_first_bit() into something suitable for use as - * a major or minor component of a priority. See the discussion - * for that routine. + * The UNIX port uses the generic C algorithm for bitfield scan to avoid + * dependencies on either a native bitscan instruction or an ffs() in the + * C library. */ - -#define _CPU_Priority_Bits_index( _priority ) \ - (_priority) - + /* end of Priority handler macros */ /* functions */ @@ -935,10 +932,6 @@ void _CPU_Fatal_error( unsigned32 _error ); -int _CPU_ffs( - unsigned32 _value -); - /* The following routine swaps the endian format of an unsigned int. * It must be static because it is referenced indirectly. * diff --git a/c/src/exec/score/headers/bitfield.h b/c/src/exec/score/headers/bitfield.h index a74ea97735..6dbf1e0ba0 100644 --- a/c/src/exec/score/headers/bitfield.h +++ b/c/src/exec/score/headers/bitfield.h @@ -38,9 +38,58 @@ extern "C" { * significant impact on the performance of the executive as a whole. */ +#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE ) + +#ifndef INIT + extern const unsigned char __log2table[256]; +#else +const unsigned char __log2table[256] = { + 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#endif + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE ) + #define _Bitfield_Find_first_bit( _value, _bit_number ) \ _CPU_Bitfield_Find_first_bit( _value, _bit_number ) +#else + +/* + * The following must be a macro because if a CPU specific version + * is used it will most likely use inline assembly. + */ + +#define _Bitfield_Find_first_bit( _value, _bit_number ) \ + { \ + register __value = (_value); \ + register const unsigned char *__p = __log2table; \ + \ + if ( __value < 0x100 ) \ + (_bit_number) = __p[ __value ] + 8; \ + else \ + (_bit_number) = __p[ __value >> 8 ]; \ + } + +#endif + #ifdef __cplusplus } #endif diff --git a/c/src/exec/score/headers/context.h b/c/src/exec/score/headers/context.h index b3a423bb47..4cd1f1e4c5 100644 --- a/c/src/exec/score/headers/context.h +++ b/c/src/exec/score/headers/context.h @@ -47,8 +47,9 @@ EXTERN boolean _Context_Switch_necessary; * thread's initial state. */ -#define _Context_Initialize( _the_context, _stack, _size, _isr, _entry ) \ - _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry ) +#define \ + _Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \ + _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) /* * _Context_Switch diff --git a/c/src/exec/score/headers/isr.h b/c/src/exec/score/headers/isr.h index 2409ed394a..bb80823cfb 100644 --- a/c/src/exec/score/headers/isr.h +++ b/c/src/exec/score/headers/isr.h @@ -50,11 +50,18 @@ typedef ISR_Handler ( *ISR_Handler_entry )( ISR_Vector_number ); /* - * This constant promotes out the number of vectors supported by - * the current CPU being used. + * This constant promotes out the number of vectors truly supported by + * the current CPU being used. This is usually the number of distinct vectors + * the cpu can vector. */ -#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS +#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS + +/* + * This constant promotes out the highest valid interrupt vector number. + */ + +#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER /* * The following is TRUE if signals have been sent to the currently @@ -75,7 +82,7 @@ EXTERN unsigned32 _ISR_Nest_level; * interrupt service routines are vectored by the ISR Handler via this table. */ -EXTERN ISR_Handler_entry _ISR_Vector_table[CPU_INTERRUPT_NUMBER_OF_VECTORS]; +EXTERN ISR_Handler_entry _ISR_Vector_table[ ISR_NUMBER_OF_VECTORS ]; /* * _ISR_Handler_initialization diff --git a/c/src/exec/score/headers/priority.h b/c/src/exec/score/headers/priority.h index 6639d56e0a..a4a96045d5 100644 --- a/c/src/exec/score/headers/priority.h +++ b/c/src/exec/score/headers/priority.h @@ -113,6 +113,51 @@ STATIC INLINE unsigned32 _Priority_Minor ( Priority_Control the_priority ); +/* + * _Priority_Mask + * + * DESCRIPTION: + * + * This function returns the mask associated with the major or minor + * number passed to it. + */ + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +STATIC INLINE unsigned32 _Priority_Mask ( + unsigned32 bit_number +); + +#else + +#define _Priority_Mask( _bit_number ) \ + _CPU_Priority_Mask( _bit_number ) + +#endif + +/* + * _Priority_Bits_index + * + * DESCRIPTION: + * + * This function translates the bit numbers returned by the bit scan + * of a priority bit field into something suitable for use as + * a major or minor component of a priority. + */ + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +STATIC INLINE unsigned32 _Priority_Bits_index ( + unsigned32 bit_number +); + +#else + +#define _Priority_Bits_index( _priority ) \ + _CPU_Priority_bits_index( _priority ) + +#endif + /* * _Priority_Add_to_bit_map * diff --git a/c/src/exec/score/include/rtems/score/bitfield.h b/c/src/exec/score/include/rtems/score/bitfield.h index a74ea97735..6dbf1e0ba0 100644 --- a/c/src/exec/score/include/rtems/score/bitfield.h +++ b/c/src/exec/score/include/rtems/score/bitfield.h @@ -38,9 +38,58 @@ extern "C" { * significant impact on the performance of the executive as a whole. */ +#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE ) + +#ifndef INIT + extern const unsigned char __log2table[256]; +#else +const unsigned char __log2table[256] = { + 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#endif + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE ) + #define _Bitfield_Find_first_bit( _value, _bit_number ) \ _CPU_Bitfield_Find_first_bit( _value, _bit_number ) +#else + +/* + * The following must be a macro because if a CPU specific version + * is used it will most likely use inline assembly. + */ + +#define _Bitfield_Find_first_bit( _value, _bit_number ) \ + { \ + register __value = (_value); \ + register const unsigned char *__p = __log2table; \ + \ + if ( __value < 0x100 ) \ + (_bit_number) = __p[ __value ] + 8; \ + else \ + (_bit_number) = __p[ __value >> 8 ]; \ + } + +#endif + #ifdef __cplusplus } #endif diff --git a/c/src/exec/score/include/rtems/score/context.h b/c/src/exec/score/include/rtems/score/context.h index b3a423bb47..4cd1f1e4c5 100644 --- a/c/src/exec/score/include/rtems/score/context.h +++ b/c/src/exec/score/include/rtems/score/context.h @@ -47,8 +47,9 @@ EXTERN boolean _Context_Switch_necessary; * thread's initial state. */ -#define _Context_Initialize( _the_context, _stack, _size, _isr, _entry ) \ - _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry ) +#define \ + _Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \ + _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) /* * _Context_Switch diff --git a/c/src/exec/score/include/rtems/score/isr.h b/c/src/exec/score/include/rtems/score/isr.h index 2409ed394a..bb80823cfb 100644 --- a/c/src/exec/score/include/rtems/score/isr.h +++ b/c/src/exec/score/include/rtems/score/isr.h @@ -50,11 +50,18 @@ typedef ISR_Handler ( *ISR_Handler_entry )( ISR_Vector_number ); /* - * This constant promotes out the number of vectors supported by - * the current CPU being used. + * This constant promotes out the number of vectors truly supported by + * the current CPU being used. This is usually the number of distinct vectors + * the cpu can vector. */ -#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS +#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS + +/* + * This constant promotes out the highest valid interrupt vector number. + */ + +#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER /* * The following is TRUE if signals have been sent to the currently @@ -75,7 +82,7 @@ EXTERN unsigned32 _ISR_Nest_level; * interrupt service routines are vectored by the ISR Handler via this table. */ -EXTERN ISR_Handler_entry _ISR_Vector_table[CPU_INTERRUPT_NUMBER_OF_VECTORS]; +EXTERN ISR_Handler_entry _ISR_Vector_table[ ISR_NUMBER_OF_VECTORS ]; /* * _ISR_Handler_initialization diff --git a/c/src/exec/score/include/rtems/score/priority.h b/c/src/exec/score/include/rtems/score/priority.h index 6639d56e0a..a4a96045d5 100644 --- a/c/src/exec/score/include/rtems/score/priority.h +++ b/c/src/exec/score/include/rtems/score/priority.h @@ -113,6 +113,51 @@ STATIC INLINE unsigned32 _Priority_Minor ( Priority_Control the_priority ); +/* + * _Priority_Mask + * + * DESCRIPTION: + * + * This function returns the mask associated with the major or minor + * number passed to it. + */ + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +STATIC INLINE unsigned32 _Priority_Mask ( + unsigned32 bit_number +); + +#else + +#define _Priority_Mask( _bit_number ) \ + _CPU_Priority_Mask( _bit_number ) + +#endif + +/* + * _Priority_Bits_index + * + * DESCRIPTION: + * + * This function translates the bit numbers returned by the bit scan + * of a priority bit field into something suitable for use as + * a major or minor component of a priority. + */ + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +STATIC INLINE unsigned32 _Priority_Bits_index ( + unsigned32 bit_number +); + +#else + +#define _Priority_Bits_index( _priority ) \ + _CPU_Priority_bits_index( _priority ) + +#endif + /* * _Priority_Add_to_bit_map * diff --git a/c/src/exec/score/inline/isr.inl b/c/src/exec/score/inline/isr.inl index 222fcadb17..2b4969a5db 100644 --- a/c/src/exec/score/inline/isr.inl +++ b/c/src/exec/score/inline/isr.inl @@ -38,7 +38,7 @@ STATIC INLINE boolean _ISR_Is_vector_number_valid ( unsigned32 vector ) { - return ( vector < CPU_INTERRUPT_NUMBER_OF_VECTORS ); + return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER ); } /*PAGE diff --git a/c/src/exec/score/inline/priority.inl b/c/src/exec/score/inline/priority.inl index 64a6c1cf66..413e3b6724 100644 --- a/c/src/exec/score/inline/priority.inl +++ b/c/src/exec/score/inline/priority.inl @@ -78,6 +78,37 @@ STATIC INLINE unsigned32 _Priority_Minor ( return ( the_priority % 16 ); } +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +/*PAGE + * + * _Priority_Mask + * + */ + +STATIC INLINE unsigned32 _Priority_Mask ( + unsigned32 bit_number +) +{ + return (0x8000 >> bit_number); +} + + +/*PAGE + * + * _Priority_Bits_index + * + */ + +STATIC INLINE unsigned32 _Priority_Bits_index ( + unsigned32 bit_number +) +{ + return bit_number; +} + +#endif + /*PAGE * * _Priority_Add_to_bit_map @@ -121,8 +152,8 @@ STATIC INLINE Priority_Control _Priority_Get_highest( void ) _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); - return (_CPU_Priority_Bits_index( major ) << 4) + - _CPU_Priority_Bits_index( minor ); + return (_Priority_Bits_index( major ) << 4) + + _Priority_Bits_index( minor ); } /*PAGE @@ -144,13 +175,13 @@ STATIC INLINE void _Priority_Initialize_information( minor = _Priority_Minor( new_priority ); the_priority_map->minor = - &_Priority_Bit_map[ _CPU_Priority_Bits_index(major) ]; + &_Priority_Bit_map[ _Priority_Bits_index(major) ]; - mask = _CPU_Priority_Mask( major ); + mask = _Priority_Mask( major ); the_priority_map->ready_major = mask; the_priority_map->block_major = ~mask; - mask = _CPU_Priority_Mask( minor ); + mask = _Priority_Mask( minor ); the_priority_map->ready_minor = mask; the_priority_map->block_minor = ~mask; } diff --git a/c/src/exec/score/inline/rtems/score/isr.inl b/c/src/exec/score/inline/rtems/score/isr.inl index 222fcadb17..2b4969a5db 100644 --- a/c/src/exec/score/inline/rtems/score/isr.inl +++ b/c/src/exec/score/inline/rtems/score/isr.inl @@ -38,7 +38,7 @@ STATIC INLINE boolean _ISR_Is_vector_number_valid ( unsigned32 vector ) { - return ( vector < CPU_INTERRUPT_NUMBER_OF_VECTORS ); + return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER ); } /*PAGE diff --git a/c/src/exec/score/inline/rtems/score/priority.inl b/c/src/exec/score/inline/rtems/score/priority.inl index 64a6c1cf66..413e3b6724 100644 --- a/c/src/exec/score/inline/rtems/score/priority.inl +++ b/c/src/exec/score/inline/rtems/score/priority.inl @@ -78,6 +78,37 @@ STATIC INLINE unsigned32 _Priority_Minor ( return ( the_priority % 16 ); } +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +/*PAGE + * + * _Priority_Mask + * + */ + +STATIC INLINE unsigned32 _Priority_Mask ( + unsigned32 bit_number +) +{ + return (0x8000 >> bit_number); +} + + +/*PAGE + * + * _Priority_Bits_index + * + */ + +STATIC INLINE unsigned32 _Priority_Bits_index ( + unsigned32 bit_number +) +{ + return bit_number; +} + +#endif + /*PAGE * * _Priority_Add_to_bit_map @@ -121,8 +152,8 @@ STATIC INLINE Priority_Control _Priority_Get_highest( void ) _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); - return (_CPU_Priority_Bits_index( major ) << 4) + - _CPU_Priority_Bits_index( minor ); + return (_Priority_Bits_index( major ) << 4) + + _Priority_Bits_index( minor ); } /*PAGE @@ -144,13 +175,13 @@ STATIC INLINE void _Priority_Initialize_information( minor = _Priority_Minor( new_priority ); the_priority_map->minor = - &_Priority_Bit_map[ _CPU_Priority_Bits_index(major) ]; + &_Priority_Bit_map[ _Priority_Bits_index(major) ]; - mask = _CPU_Priority_Mask( major ); + mask = _Priority_Mask( major ); the_priority_map->ready_major = mask; the_priority_map->block_major = ~mask; - mask = _CPU_Priority_Mask( minor ); + mask = _Priority_Mask( minor ); the_priority_map->ready_minor = mask; the_priority_map->block_minor = ~mask; } diff --git a/c/src/exec/score/macros/isr.inl b/c/src/exec/score/macros/isr.inl index 975487c98b..95f0319396 100644 --- a/c/src/exec/score/macros/isr.inl +++ b/c/src/exec/score/macros/isr.inl @@ -33,7 +33,7 @@ */ #define _ISR_Is_vector_number_valid( _vector ) \ - ( (_vector) < CPU_INTERRUPT_NUMBER_OF_VECTORS ) + ( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER ) /*PAGE * diff --git a/c/src/exec/score/macros/priority.inl b/c/src/exec/score/macros/priority.inl index 3db8aee4fa..4c5d32b3b3 100644 --- a/c/src/exec/score/macros/priority.inl +++ b/c/src/exec/score/macros/priority.inl @@ -64,6 +64,28 @@ #define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 ) +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +/*PAGE + * + * _Priority_Mask + * + */ + +#define _Priority_Mask( _bit_number ) \ + (0x8000 >> _bit_number) + +/*PAGE + * + * _Priority_Bits_index + * + */ + +#define _Priority_Bits_index( _bit_number ) \ + (_bit_number) + +#endif + /*PAGE * * _Priority_Add_to_bit_map @@ -103,8 +125,8 @@ _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \ _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \ \ - (_high_priority) = (_CPU_Priority_Bits_index( major ) * 16) + \ - _CPU_Priority_Bits_index( minor ); \ + (_high_priority) = (_Priority_Bits_index( major ) * 16) + \ + _Priority_Bits_index( minor ); \ } /*PAGE @@ -124,13 +146,13 @@ _minor = _Priority_Minor( (_new_priority) ); \ \ (_the_priority_map)->minor = \ - &_Priority_Bit_map[ _CPU_Priority_Bits_index(_major) ]; \ + &_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \ \ - _mask = _CPU_Priority_Mask( _major ); \ + _mask = _Priority_Mask( _major ); \ (_the_priority_map)->ready_major = _mask; \ (_the_priority_map)->block_major = ~_mask; \ \ - _mask = _CPU_Priority_Mask( _minor ); \ + _mask = _Priority_Mask( _minor ); \ (_the_priority_map)->ready_minor = _mask; \ (_the_priority_map)->block_minor = ~_mask; \ } diff --git a/c/src/exec/score/macros/rtems/score/isr.inl b/c/src/exec/score/macros/rtems/score/isr.inl index 975487c98b..95f0319396 100644 --- a/c/src/exec/score/macros/rtems/score/isr.inl +++ b/c/src/exec/score/macros/rtems/score/isr.inl @@ -33,7 +33,7 @@ */ #define _ISR_Is_vector_number_valid( _vector ) \ - ( (_vector) < CPU_INTERRUPT_NUMBER_OF_VECTORS ) + ( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER ) /*PAGE * diff --git a/c/src/exec/score/macros/rtems/score/priority.inl b/c/src/exec/score/macros/rtems/score/priority.inl index 3db8aee4fa..4c5d32b3b3 100644 --- a/c/src/exec/score/macros/rtems/score/priority.inl +++ b/c/src/exec/score/macros/rtems/score/priority.inl @@ -64,6 +64,28 @@ #define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 ) +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +/*PAGE + * + * _Priority_Mask + * + */ + +#define _Priority_Mask( _bit_number ) \ + (0x8000 >> _bit_number) + +/*PAGE + * + * _Priority_Bits_index + * + */ + +#define _Priority_Bits_index( _bit_number ) \ + (_bit_number) + +#endif + /*PAGE * * _Priority_Add_to_bit_map @@ -103,8 +125,8 @@ _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \ _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \ \ - (_high_priority) = (_CPU_Priority_Bits_index( major ) * 16) + \ - _CPU_Priority_Bits_index( minor ); \ + (_high_priority) = (_Priority_Bits_index( major ) * 16) + \ + _Priority_Bits_index( minor ); \ } /*PAGE @@ -124,13 +146,13 @@ _minor = _Priority_Minor( (_new_priority) ); \ \ (_the_priority_map)->minor = \ - &_Priority_Bit_map[ _CPU_Priority_Bits_index(_major) ]; \ + &_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \ \ - _mask = _CPU_Priority_Mask( _major ); \ + _mask = _Priority_Mask( _major ); \ (_the_priority_map)->ready_major = _mask; \ (_the_priority_map)->block_major = ~_mask; \ \ - _mask = _CPU_Priority_Mask( _minor ); \ + _mask = _Priority_Mask( _minor ); \ (_the_priority_map)->ready_minor = _mask; \ (_the_priority_map)->block_minor = ~_mask; \ } diff --git a/c/src/exec/score/src/thread.c b/c/src/exec/score/src/thread.c index d384b75788..b44da17c67 100644 --- a/c/src/exec/score/src/thread.c +++ b/c/src/exec/score/src/thread.c @@ -805,9 +805,12 @@ void _Thread_Load_environment( Thread_Control *the_thread ) { + boolean is_fp = FALSE; + if ( the_thread->Start.fp_context ) { the_thread->fp_context = the_thread->Start.fp_context; _Context_Initialize_fp( &the_thread->fp_context ); + is_fp = TRUE; } the_thread->is_preemptible = the_thread->Start.is_preemptible; @@ -818,7 +821,8 @@ void _Thread_Load_environment( the_thread->Start.Initial_stack.area, the_thread->Start.Initial_stack.size, the_thread->Start.isr_level, - _Thread_Handler + _Thread_Handler, + is_fp ); } diff --git a/c/src/lib/include/ringbuf.h b/c/src/lib/include/ringbuf.h index b2494c1527..8c80aaf9c8 100644 --- a/c/src/lib/include/ringbuf.h +++ b/c/src/lib/include/ringbuf.h @@ -10,13 +10,13 @@ #define __RINGBUF_H__ #ifndef RINGBUF_QUEUE_LENGTH -#define RINGBUF_QUEUE_LENGTH 200 +#define RINGBUF_QUEUE_LENGTH 128 #endif typedef struct { char buffer[RINGBUF_QUEUE_LENGTH]; - int head; - int tail; + volatile int head; + volatile int tail; } Ring_buffer_t; #define Ring_buffer_Initialize( _buffer ) \ @@ -27,16 +27,27 @@ typedef struct { #define Ring_buffer_Is_empty( _buffer ) \ ( (_buffer)->head == (_buffer)->tail ) +#define Ring_buffer_Is_full( _buffer ) \ + ( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH ) + #define Ring_buffer_Add_character( _buffer, _ch ) \ do { \ - (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \ - (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \ + rtems_unsigned32 isrlevel; \ + \ + rtems_interrupt_disable( isrlevel ); \ + (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \ + (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \ + rtems_interrupt_enable( isrlevel ); \ } while ( 0 ) #define Ring_buffer_Remove_character( _buffer, _ch ) \ do { \ - (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \ - (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \ + rtems_unsigned32 isrlevel; \ + \ + rtems_interrupt_disable( isrlevel ); \ + (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \ + (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \ + rtems_interrupt_enable( isrlevel ); \ } while ( 0 ) #endif diff --git a/c/src/lib/libbsp/hppa1.1/simhppa/startup/bspstart.c b/c/src/lib/libbsp/hppa1.1/simhppa/startup/bspstart.c index 0c19667b1f..bfdb429ef8 100644 --- a/c/src/lib/libbsp/hppa1.1/simhppa/startup/bspstart.c +++ b/c/src/lib/libbsp/hppa1.1/simhppa/startup/bspstart.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include @@ -243,19 +243,22 @@ bsp_pretasking_hook(void) void bsp_postdriver_hook(void) { - int stdin_fd, stdout_fd, stderr_fd; - - if ((stdin_fd = __open("/dev/tty00", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); - - if ((stdout_fd = __open("/dev/tty00", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); - - if ((stderr_fd = __open("/dev/tty00", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); - - if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; + + if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); + + if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); + + if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); + + if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } /* diff --git a/c/src/lib/libbsp/i386/force386/clock/ckinit.c b/c/src/lib/libbsp/i386/force386/clock/ckinit.c index 45a64f6f14..9bfad8991a 100644 --- a/c/src/lib/libbsp/i386/force386/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/force386/clock/ckinit.c @@ -75,17 +75,6 @@ void Install_clock( atexit( Clock_exit ); } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel = 0; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { if ( BSP_Configuration.ticks_per_timeslice ) { @@ -119,6 +108,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -135,7 +125,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/i386/force386/startup/bspstart.c b/c/src/lib/libbsp/i386/force386/startup/bspstart.c index 1433e5e02a..3f001fb109 100644 --- a/c/src/lib/libbsp/i386/force386/startup/bspstart.c +++ b/c/src/lib/libbsp/i386/force386/startup/bspstart.c @@ -122,18 +122,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/i386/go32/clock/ckinit.c b/c/src/lib/libbsp/i386/go32/clock/ckinit.c index fa6a8bf057..70c564fabc 100644 --- a/c/src/lib/libbsp/i386/go32/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/go32/clock/ckinit.c @@ -108,17 +108,6 @@ void Install_clock( atexit( Clock_exit ); } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel = 0; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { if ( BSP_Configuration.ticks_per_timeslice ) { @@ -161,6 +150,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -177,7 +167,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/i386/go32/startup/bspstart.c b/c/src/lib/libbsp/i386/go32/startup/bspstart.c index 17a10b4193..602b7bdfd6 100644 --- a/c/src/lib/libbsp/i386/go32/startup/bspstart.c +++ b/c/src/lib/libbsp/i386/go32/startup/bspstart.c @@ -129,18 +129,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } /* This is the original command line passed from DOS */ diff --git a/c/src/lib/libbsp/i960/cvme961/clock/ckinit.c b/c/src/lib/libbsp/i960/cvme961/clock/ckinit.c index b479ad137c..3f2ba718bc 100644 --- a/c/src/lib/libbsp/i960/cvme961/clock/ckinit.c +++ b/c/src/lib/libbsp/i960/cvme961/clock/ckinit.c @@ -60,13 +60,6 @@ void Install_clock( } } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); -} - void Clock_exit() { unsigned char *victimer; @@ -105,6 +98,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -121,7 +115,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/i960/cvme961/startup/bspstart.c b/c/src/lib/libbsp/i960/cvme961/startup/bspstart.c index ec4f8b601d..1c9c29f29e 100644 --- a/c/src/lib/libbsp/i960/cvme961/startup/bspstart.c +++ b/c/src/lib/libbsp/i960/cvme961/startup/bspstart.c @@ -124,18 +124,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/m68k/dmv152/clock/ckinit.c b/c/src/lib/libbsp/m68k/dmv152/clock/ckinit.c index 8715cdcc26..128bed84d7 100644 --- a/c/src/lib/libbsp/m68k/dmv152/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/dmv152/clock/ckinit.c @@ -97,17 +97,6 @@ void Install_clock( } } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel = 0 ; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { rtems_unsigned8 data; @@ -145,6 +134,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -161,7 +151,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/dmv152/startup/bspstart.c b/c/src/lib/libbsp/m68k/dmv152/startup/bspstart.c index 44ad6b6f7e..0f0ecbf00d 100644 --- a/c/src/lib/libbsp/m68k/dmv152/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/dmv152/startup/bspstart.c @@ -123,18 +123,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/m68k/efi332/clock/ckinit.c b/c/src/lib/libbsp/m68k/efi332/clock/ckinit.c index 2bfa34d32d..8b46fc283d 100644 --- a/c/src/lib/libbsp/m68k/efi332/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/efi332/clock/ckinit.c @@ -70,17 +70,6 @@ void Install_clock( } } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel = 0 ; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { @@ -120,6 +109,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -136,7 +126,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/efi332/startup/bspstart.c b/c/src/lib/libbsp/m68k/efi332/startup/bspstart.c index 6a7830bcfe..7a291ef02e 100644 --- a/c/src/lib/libbsp/m68k/efi332/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/efi332/startup/bspstart.c @@ -123,18 +123,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/m68k/efi68k/clock/ckinit.c b/c/src/lib/libbsp/m68k/efi68k/clock/ckinit.c index c90eba1e22..9c698cd0ba 100644 --- a/c/src/lib/libbsp/m68k/efi68k/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/efi68k/clock/ckinit.c @@ -93,17 +93,6 @@ void Install_clock( } } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel = 0 ; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { @@ -141,6 +130,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -157,7 +147,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/efi68k/startup/bspstart.c b/c/src/lib/libbsp/m68k/efi68k/startup/bspstart.c index e08f78baff..366a6502e7 100644 --- a/c/src/lib/libbsp/m68k/efi68k/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/efi68k/startup/bspstart.c @@ -130,18 +130,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/m68k/gen68302/clock/ckinit.c b/c/src/lib/libbsp/m68k/gen68302/clock/ckinit.c index f842bbc83c..386fc026a7 100644 --- a/c/src/lib/libbsp/m68k/gen68302/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/gen68302/clock/ckinit.c @@ -89,7 +89,7 @@ void Install_clock( Clock_isrs = BSP_Configuration.microseconds_per_tick / 1000; if ( BSP_Configuration.ticks_per_timeslice ) { -/* set_vector( clock_isr, CLOCK_VECTOR, 1 );*/ + set_vector( clock_isr, CLOCK_VECTOR, 1 ); m302.reg.trr1 = TRR1_VAL; /* set timer reference register */ m302.reg.tmr1 = TMR1_VAL; /* set timer mode register & enable */ @@ -102,17 +102,6 @@ void Install_clock( } } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel; - - rtems_interrupt_disable( isrlevel ); - /* (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); */ - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { if ( BSP_Configuration.ticks_per_timeslice ) { @@ -145,6 +134,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -161,7 +151,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/gen68302/start/start302.s b/c/src/lib/libbsp/m68k/gen68302/start/start302.s index d92ed1ce6b..311cd3fa39 100644 --- a/c/src/lib/libbsp/m68k/gen68302/start/start302.s +++ b/c/src/lib/libbsp/m68k/gen68302/start/start302.s @@ -193,7 +193,6 @@ cpy_Bad1: move.l d1,(a0)+ | move.l #_cnsl_isr,vbase+0x028 | SCC2 move.l #timerisr,vbase+0x018 | Timer ISR - move.l #RTC_ISR,vbase+0x024 | Real Time Clock ISR | | zero out uninitialized data area @@ -236,14 +235,6 @@ loop: movel d0,a1@+ | to zero out uninitialized Bad: bra Bad nop -RTC_ISR: - movem.l d0-d1/a0-a1,a7@- | save d0-d1,a0-a1 - addql #1,_ISR_Nest_level | one nest level deeper - addql #1,_Thread_Dispatch_disable_level - | disable multitasking - - jbsr Clock_isr | invoke the user ISR - jmp _ISR_Exit END_CODE diff --git a/c/src/lib/libbsp/m68k/gen68302/start302/start302.s b/c/src/lib/libbsp/m68k/gen68302/start302/start302.s index d92ed1ce6b..311cd3fa39 100644 --- a/c/src/lib/libbsp/m68k/gen68302/start302/start302.s +++ b/c/src/lib/libbsp/m68k/gen68302/start302/start302.s @@ -193,7 +193,6 @@ cpy_Bad1: move.l d1,(a0)+ | move.l #_cnsl_isr,vbase+0x028 | SCC2 move.l #timerisr,vbase+0x018 | Timer ISR - move.l #RTC_ISR,vbase+0x024 | Real Time Clock ISR | | zero out uninitialized data area @@ -236,14 +235,6 @@ loop: movel d0,a1@+ | to zero out uninitialized Bad: bra Bad nop -RTC_ISR: - movem.l d0-d1/a0-a1,a7@- | save d0-d1,a0-a1 - addql #1,_ISR_Nest_level | one nest level deeper - addql #1,_Thread_Dispatch_disable_level - | disable multitasking - - jbsr Clock_isr | invoke the user ISR - jmp _ISR_Exit END_CODE diff --git a/c/src/lib/libbsp/m68k/gen68302/startup/bspstart.c b/c/src/lib/libbsp/m68k/gen68302/startup/bspstart.c index 94973ea4cc..af512c0d8e 100644 --- a/c/src/lib/libbsp/m68k/gen68302/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/gen68302/startup/bspstart.c @@ -130,18 +130,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/m68k/idp/clock/ckinit.c b/c/src/lib/libbsp/m68k/idp/clock/ckinit.c index 7966fc61d1..6d93523563 100644 --- a/c/src/lib/libbsp/m68k/idp/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/idp/clock/ckinit.c @@ -130,16 +130,6 @@ rtems_isr_entry clock_isr; } } -void ReInstall_clock( clock_isr ) -rtems_isr_entry clock_isr; -{ - rtems_unsigned32 isrlevel = 0 ; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - /* The following was added for debugging purposes */ void Clock_exit( void ) { @@ -181,6 +171,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -197,7 +188,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/idp/console/duart.c b/c/src/lib/libbsp/m68k/idp/console/duart.c index fe4b657b37..2d82590a49 100644 --- a/c/src/lib/libbsp/m68k/idp/console/duart.c +++ b/c/src/lib/libbsp/m68k/idp/console/duart.c @@ -1,6 +1,6 @@ -# -# $Id$ -# +/* + * $Id$ + */ /*######################################################### # diff --git a/c/src/lib/libbsp/m68k/idp/startup/bspstart.c b/c/src/lib/libbsp/m68k/idp/startup/bspstart.c index b4f4928f7d..9c79960580 100644 --- a/c/src/lib/libbsp/m68k/idp/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/idp/startup/bspstart.c @@ -131,18 +131,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/m68k/mvme136/clock/ckinit.c b/c/src/lib/libbsp/m68k/mvme136/clock/ckinit.c index 61069a8627..0ba674aee9 100644 --- a/c/src/lib/libbsp/m68k/mvme136/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/mvme136/clock/ckinit.c @@ -108,17 +108,6 @@ void Install_clock( } -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { volatile struct z8036_map *timer; @@ -157,6 +146,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -173,7 +163,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/mvme136/startup/bspstart.c b/c/src/lib/libbsp/m68k/mvme136/startup/bspstart.c index 3465f72416..ea8eb56db6 100644 --- a/c/src/lib/libbsp/m68k/mvme136/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/mvme136/startup/bspstart.c @@ -124,18 +124,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; - + int error_code; + + error_code = 'S' << 24 | 'T' << 16; + if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } diff --git a/c/src/lib/libbsp/m68k/mvme162/clock/ckinit.c b/c/src/lib/libbsp/m68k/mvme162/clock/ckinit.c index df0a13d52f..57afd71292 100644 --- a/c/src/lib/libbsp/m68k/mvme162/clock/ckinit.c +++ b/c/src/lib/libbsp/m68k/mvme162/clock/ckinit.c @@ -89,15 +89,6 @@ void Install_clock(rtems_isr_entry clock_isr ) } } -void ReInstall_clock(rtems_isr_entry clock_isr) -{ - rtems_unsigned32 isrlevel; - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - void Clock_exit( void ) { /* Dummy for now. See other m68k BSP's for code examples */ @@ -127,6 +118,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -143,7 +135,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/m68k/mvme162/startup/bspstart.c b/c/src/lib/libbsp/m68k/mvme162/startup/bspstart.c index 123cd413d2..211ce19032 100644 --- a/c/src/lib/libbsp/m68k/mvme162/startup/bspstart.c +++ b/c/src/lib/libbsp/m68k/mvme162/startup/bspstart.c @@ -130,18 +130,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/no_cpu/no_bsp/clock/ckinit.c b/c/src/lib/libbsp/no_cpu/no_bsp/clock/ckinit.c index efe0225520..7c8f9617e7 100644 --- a/c/src/lib/libbsp/no_cpu/no_bsp/clock/ckinit.c +++ b/c/src/lib/libbsp/no_cpu/no_bsp/clock/ckinit.c @@ -105,7 +105,7 @@ void Install_clock( */ if ( BSP_Configuration.ticks_per_timeslice ) { - Old_ticker = ( rtems_isr_entry ) set_vector( clock_isr, CLOCK_VECTOR, 1 ); + Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 ); /* * Hardware specific initialize goes here */ @@ -120,30 +120,6 @@ void Install_clock( atexit( Clock_exit ); } -/* - * Reinstall_clock - * - * Install a clock tick handler without reprogramming the chip. This - * is used by the polling shared memory device driver. - */ - -void ReInstall_clock( - rtems_isr_entry clock_isr -) -{ - rtems_unsigned32 isrlevel = 0; - - /* - * Disable interrupts and install the clock ISR vector using the - * BSP dependent set_vector routine. In the below example, the clock - * ISR is on vector 4 and is an RTEMS interrupt. - */ - - rtems_interrupt_disable( isrlevel ); - (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); - rtems_interrupt_enable( isrlevel ); -} - /* * Clean up before the application exits */ @@ -188,6 +164,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -204,7 +181,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, CLOCK_VECTOR, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c b/c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c index e28e791503..7f08b779dd 100644 --- a/c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c +++ b/c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c @@ -131,18 +131,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int bsp_start( diff --git a/c/src/lib/libbsp/powerpc/papyrus/startup/bspstart.c b/c/src/lib/libbsp/powerpc/papyrus/startup/bspstart.c index 6c5133f7ed..b044367f43 100644 --- a/c/src/lib/libbsp/powerpc/papyrus/startup/bspstart.c +++ b/c/src/lib/libbsp/powerpc/papyrus/startup/bspstart.c @@ -149,18 +149,21 @@ void bsp_postdriver_hook(void) { int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); } int main( diff --git a/c/src/lib/libbsp/unix/posix/clock/clock.c b/c/src/lib/libbsp/unix/posix/clock/clock.c index da0dd46807..3e05b694a7 100644 --- a/c/src/lib/libbsp/unix/posix/clock/clock.c +++ b/c/src/lib/libbsp/unix/posix/clock/clock.c @@ -31,30 +31,18 @@ rtems_unsigned32 Clock_driver_vector; rtems_device_major_number rtems_clock_major = ~0; rtems_device_minor_number rtems_clock_minor; -void -Install_clock(rtems_isr_entry clock_isr) +void Install_clock(rtems_isr_entry clock_isr) { Clock_driver_ticks = 0; - (void)set_vector(clock_isr, Clock_driver_vector, 1); + (void) set_vector( clock_isr, Clock_driver_vector, 1 ); _CPU_Start_clock( BSP_Configuration.microseconds_per_tick ); atexit(Clock_exit); } -void -ReInstall_clock(rtems_isr_entry new_clock_isr) -{ - rtems_unsigned32 isrlevel = 0; - - rtems_interrupt_disable(isrlevel); - (void)set_vector(new_clock_isr, Clock_driver_vector, 1); - rtems_interrupt_enable(isrlevel); -} - -void -Clock_isr(int vector) +void Clock_isr(int vector) { Clock_driver_ticks++; rtems_clock_tick(); @@ -65,16 +53,14 @@ Clock_isr(int vector) * Remove the clock signal */ -void -Clock_exit(void) +void Clock_exit(void) { _CPU_Stop_clock(); - (void)set_vector(0, Clock_driver_vector, 1); + (void) set_vector( 0, Clock_driver_vector, 1 ); } -rtems_device_driver -Clock_initialize( +rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *pargp @@ -99,6 +85,7 @@ rtems_device_driver Clock_control( void *pargp ) { + rtems_unsigned32 isrlevel; rtems_libio_ioctl_args_t *args = pargp; if (args == 0) @@ -115,7 +102,9 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - ReInstall_clock(args->buffer); + rtems_interrupt_disable( isrlevel ); + (void) set_vector( args->buffer, Clock_driver_vector, 1 ); + rtems_interrupt_enable( isrlevel ); } done: diff --git a/c/src/lib/libbsp/unix/posix/startup/bspstart.c b/c/src/lib/libbsp/unix/posix/startup/bspstart.c index 8ce3e92ecb..cefa60032f 100644 --- a/c/src/lib/libbsp/unix/posix/startup/bspstart.c +++ b/c/src/lib/libbsp/unix/posix/startup/bspstart.c @@ -182,18 +182,21 @@ bsp_postdriver_hook(void) { #if 0 int stdin_fd, stdout_fd, stderr_fd; + int error_code; + + error_code = 'S' << 24 | 'T' << 16; if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1) - rtems_fatal_error_occurred('STD0'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' ); if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD1'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' ); if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1) - rtems_fatal_error_occurred('STD2'); + rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' ); if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2)) - rtems_fatal_error_occurred('STIO'); + rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' ); #endif #if defined(MALLOC_STATS) diff --git a/c/src/lib/libcpu/sparc/include/erc32.h b/c/src/lib/libcpu/sparc/include/erc32.h new file mode 100644 index 0000000000..9a8b875c49 --- /dev/null +++ b/c/src/lib/libcpu/sparc/include/erc32.h @@ -0,0 +1,503 @@ +/* erc32.h + * + * This include file contains information pertaining to the ERC32. + * The ERC32 is a custom SPARC V7 implementation based on the Cypress + * 601/602 chipset. This CPU has a number of on-board peripherals and + * was developed by the European Space Agency to target space applications. + * + * NOTE: Other than where absolutely required, this version currently + * supports only the peripherals and bits used by the basic board + * support package. This includes at least significant pieces of + * the following items: + * + * + UART Channels A and B + * + General Purpose Timer + * + Real Time Clock + * + Watchdog Timer (so it can be disabled) + * + Control Register (so powerdown mode can be enabled) + * + Memory Control Register + * + Interrupt Control + * + * $Id$ + */ + +#ifndef _INCLUDE_ERC32_h +#define _INCLUDE_ERC32_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interrupt Sources + * + * The interrupt source numbers directly map to the trap type and to + * the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + */ + +#define ERC32_INTERRUPT_MASKED_ERRORS 1 +#define ERC32_INTERRUPT_EXTERNAL_1 2 +#define ERC32_INTERRUPT_EXTERNAL_2 3 +#define ERC32_INTERRUPT_UART_A_RX_TX 4 +#define ERC32_INTERRUPT_UART_B_RX_TX 5 +#define ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR 6 +#define ERC32_INTERRUPT_UART_ERROR 7 +#define ERC32_INTERRUPT_DMA_ACCESS_ERROR 8 +#define ERC32_INTERRUPT_DMA_TIMEOUT 9 +#define ERC32_INTERRUPT_EXTERNAL_3 10 +#define ERC32_INTERRUPT_EXTERNAL_4 11 +#define ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER 12 +#define ERC32_INTERRUPT_REAL_TIME_CLOCK 13 +#define ERC32_INTERRUPT_EXTERNAL_5 14 +#define ERC32_INTERRUPT_WATCHDOG_TIMEOUT 15 + +#ifndef ASM + +/* + * Trap Types for on-chip peripherals + * + * Source: Table 8 - Interrupt Trap Type and Default Priority Assignments + * + * NOTE: The priority level for each source corresponds to the least + * significant nibble of the trap type. + */ + +#define ERC32_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10) + +#define ERC32_TRAP_SOURCE( _trap ) ((_trap) - 0x10) + +#define ERC32_Is_MEC_Trap( _trap ) \ + ( (_trap) >= ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ) && \ + (_trap) <= ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ) ) + +/* + * Structure for ERC32 memory mapped registers. + * + * Source: Section 3.25.2 - Register Address Map + * + * NOTE: There is only one of these structures per CPU, its base address + * is 0x01f80000, and the variable MEC is placed there by the + * linkcmds file. + */ + +typedef struct { + volatile unsigned32 Control; /* offset 0x00 */ + volatile unsigned32 Software_Reset; /* offset 0x04 */ + volatile unsigned32 Power_Down; /* offset 0x08 */ + volatile unsigned32 Unimplemented_0; /* offset 0x0c */ + volatile unsigned32 Memory_Configuration; /* offset 0x10 */ + volatile unsigned32 IO_Configuration; /* offset 0x14 */ + volatile unsigned32 Wait_State_Configuration; /* offset 0x18 */ + volatile unsigned32 Unimplemented_1; /* offset 0x1c */ + volatile unsigned32 Memory_Access_0; /* offset 0x20 */ + volatile unsigned32 Memory_Access_1; /* offset 0x24 */ + volatile unsigned32 Unimplemented_2[ 7 ]; /* offset 0x28 */ + volatile unsigned32 Interrupt_Shape; /* offset 0x44 */ + volatile unsigned32 Interrupt_Pending; /* offset 0x48 */ + volatile unsigned32 Interrupt_Mask; /* offset 0x4c */ + volatile unsigned32 Interrupt_Clear; /* offset 0x50 */ + volatile unsigned32 Interrupt_Force; /* offset 0x54 */ + volatile unsigned32 Unimplemented_3[ 2 ]; /* offset 0x58 */ + /* offset 0x60 */ + volatile unsigned32 Watchdog_Program_and_Timeout_Acknowledge; + volatile unsigned32 Watchdog_Trap_Door_Set; /* offset 0x64 */ + volatile unsigned32 Unimplemented_4[ 6 ]; /* offset 0x68 */ + volatile unsigned32 Real_Time_Clock_Counter; /* offset 0x80 */ + volatile unsigned32 Real_Time_Clock_Scalar; /* offset 0x84 */ + volatile unsigned32 General_Purpose_Timer_Counter; /* offset 0x88 */ + volatile unsigned32 General_Purpose_Timer_Scalar; /* offset 0x8c */ + volatile unsigned32 Unimplemented_5[ 2 ]; /* offset 0x90 */ + volatile unsigned32 Timer_Control; /* offset 0x98 */ + volatile unsigned32 Unimplemented_6; /* offset 0x9c */ + volatile unsigned32 System_Fault_Status; /* offset 0xa0 */ + volatile unsigned32 First_Failing_Address; /* offset 0xa4 */ + volatile unsigned32 First_Failing_Data; /* offset 0xa8 */ + volatile unsigned32 First_Failing_Syndrome_and_Check_Bits;/* offset 0xac */ + volatile unsigned32 Error_and_Reset_Status; /* offset 0xb0 */ + volatile unsigned32 Error_Mask; /* offset 0xb4 */ + volatile unsigned32 Unimplemented_7[ 2 ]; /* offset 0xb8 */ + volatile unsigned32 Debug_Control; /* offset 0xc0 */ + volatile unsigned32 Breakpoint; /* offset 0xc4 */ + volatile unsigned32 Watchpoint; /* offset 0xc8 */ + volatile unsigned32 Unimplemented_8; /* offset 0xcc */ + volatile unsigned32 Test_Control; /* offset 0xd0 */ + volatile unsigned32 Test_Data; /* offset 0xd4 */ + volatile unsigned32 Unimplemented_9[ 2 ]; /* offset 0xd8 */ + volatile unsigned32 UART_Channel_A; /* offset 0xe0 */ + volatile unsigned32 UART_Channel_B; /* offset 0xe4 */ + volatile unsigned32 UART_Status; /* offset 0xe8 */ +} ERC32_Register_Map; + +#endif + +/* + * The following constants are intended to be used ONLY in assembly + * language files. + * + * NOTE: The intended style of usage is to load the address of MEC + * into a register and then use these as displacements from + * that register. + */ + +#ifdef ASM + +#define ERC32_MEC_CONTROL_OFFSET 0x00 +#define ERC32_MEC_SOFTWARE_RESET_OFFSET 0x04 +#define ERC32_MEC_POWER_DOWN_OFFSET 0x08 +#define ERC32_MEC_UNIMPLEMENTED_0_OFFSET 0x0C +#define ERC32_MEC_MEMORY_CONFIGURATION_OFFSET 0x10 +#define ERC32_MEC_IO_CONFIGURATION_OFFSET 0x14 +#define ERC32_MEC_WAIT_STATE_CONFIGURATION_OFFSET 0x18 +#define ERC32_MEC_UNIMPLEMENTED_1_OFFSET 0x1C +#define ERC32_MEC_MEMORY_ACCESS_0_OFFSET 0x20 +#define ERC32_MEC_MEMORY_ACCESS_1_OFFSET 0x24 +#define ERC32_MEC_UNIMPLEMENTED_2_OFFSET 0x28 +#define ERC32_MEC_INTERRUPT_SHAPE_OFFSET 0x44 +#define ERC32_MEC_INTERRUPT_PENDING_OFFSET 0x48 +#define ERC32_MEC_INTERRUPT_MASK_OFFSET 0x4C +#define ERC32_MEC_INTERRUPT_CLEAR_OFFSET 0x50 +#define ERC32_MEC_INTERRUPT_FORCE_OFFSET 0x54 +#define ERC32_MEC_UNIMPLEMENTED_3_OFFSET 0x58 +#define ERC32_MEC_WATCHDOG_PROGRAM_AND_TIMEOUT_ACKNOWLEDGE_OFFSET 0x60 +#define ERC32_MEC_WATCHDOG_TRAP_DOOR_SET_OFFSET 0x64 +#define ERC32_MEC_UNIMPLEMENTED_4_OFFSET 0x6C +#define ERC32_MEC_REAL_TIME_CLOCK_COUNTER_OFFSET 0x80 +#define ERC32_MEC_REAL_TIME_CLOCK_SCALAR_OFFSET 0x84 +#define ERC32_MEC_GENERAL_PURPOSE_TIMER_COUNTER_OFFSET 0x88 +#define ERC32_MEC_GENERAL_PURPOSE_TIMER_SCALAR_OFFSET 0x8C +#define ERC32_MEC_UNIMPLEMENTED_5_OFFSET 0x90 +#define ERC32_MEC_TIMER_CONTROL_OFFSET 0x98 +#define ERC32_MEC_UNIMPLEMENTED_6_OFFSET 0x9C +#define ERC32_MEC_SYSTEM_FAULT_STATUS_OFFSET 0xA0 +#define ERC32_MEC_FIRST_FAILING_ADDRESS_OFFSET 0xA4 +#define ERC32_MEC_FIRST_FAILING_DATA_OFFSET 0xA8 +#define ERC32_MEC_FIRST_FAILING_SYNDROME_AND_CHECK_BITS_OFFSET 0xAC +#define ERC32_MEC_ERROR_AND_RESET_STATUS_OFFSET 0xB0 +#define ERC32_MEC_ERROR_MASK_OFFSET 0xB4 +#define ERC32_MEC_UNIMPLEMENTED_7_OFFSET 0xB8 +#define ERC32_MEC_DEBUG_CONTROL_OFFSET 0xC0 +#define ERC32_MEC_BREAKPOINT_OFFSET 0xC4 +#define ERC32_MEC_WATCHPOINT_OFFSET 0xC8 +#define ERC32_MEC_UNIMPLEMENTED_8_OFFSET 0xCC +#define ERC32_MEC_TEST_CONTROL_OFFSET 0xD0 +#define ERC32_MEC_TEST_DATA_OFFSET 0xD4 +#define ERC32_MEC_UNIMPLEMENTED_9_OFFSET 0xD8 +#define ERC32_MEC_UART_CHANNEL_A_OFFSET 0xE0 +#define ERC32_MEC_UART_CHANNEL_B_OFFSET 0xE4 +#define ERC32_MEC_UART_STATUS_OFFSET 0xE8 + +#endif + +/* + * The following defines the bits in the Configuration Register. + */ + +#define ERC32_CONFIGURATION_POWER_DOWN_MASK 0x00000001 +#define ERC32_CONFIGURATION_POWER_DOWN_ALLOWED 0x00000001 +#define ERC32_CONFIGURATION_POWER_DOWN_DISABLED 0x00000000 + +#define ERC32_CONFIGURATION_SOFTWARE_RESET_MASK 0x00000002 +#define ERC32_CONFIGURATION_SOFTWARE_RESET_ALLOWED 0x00000002 +#define ERC32_CONFIGURATION_SOFTWARE_RESET_DISABLED 0x00000000 + +#define ERC32_CONFIGURATION_BUS_TIMEOUT_MASK 0x00000004 +#define ERC32_CONFIGURATION_BUS_TIMEOUT_ENABLED 0x00000004 +#define ERC32_CONFIGURATION_BUS_TIMEOUT_DISABLED 0x00000000 + +#define ERC32_CONFIGURATION_ACCESS_PROTECTION_MASK 0x00000008 +#define ERC32_CONFIGURATION_ACCESS_PROTECTION_ENABLED 0x00000008 +#define ERC32_CONFIGURATION_ACCESS_PROTECTION_DISABLED 0x00000000 + + +/* + * The following defines the bits in the Memory Configuration Register. + */ + +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001C00 +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_256K ( 0 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_512K ( 1 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_1MB ( 2 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_2MB ( 3 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_4MB ( 4 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_8MB ( 5 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_16MB ( 6 << 10 ) +#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_32MB ( 7 << 10 ) + +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x001C0000 +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_4K ( 0 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_8K ( 1 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_16K ( 2 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_32K ( 3 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_64K ( 4 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_128K ( 5 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_256K ( 6 << 18 ) +#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_512K ( 7 << 18 ) + +/* + * The following defines the bits in the Timer Control Register. + */ + +#define ERC32_MEC_TIMER_CONTROL_GCR 0x00000001 /* 1 = reload at 0 */ + /* 0 = stop at 0 */ +#define ERC32_MEC_TIMER_CONTROL_GCL 0x00000002 /* 1 = load and start */ + /* 0 = no function */ +#define ERC32_MEC_TIMER_CONTROL_GSE 0x00000004 /* 1 = enable counting */ + /* 0 = hold scalar and counter */ +#define ERC32_MEC_TIMER_CONTROL_GSL 0x00000008 /* 1 = load scalar and start */ + /* 0 = no function */ + +#define ERC32_MEC_TIMER_CONTROL_RTCCR 0x00000100 /* 1 = reload at 0 */ + /* 0 = stop at 0 */ +#define ERC32_MEC_TIMER_CONTROL_RTCCL 0x00000200 /* 1 = load and start */ + /* 0 = no function */ +#define ERC32_MEC_TIMER_CONTROL_RTCSE 0x00000400 /* 1 = enable counting */ + /* 0 = hold scalar and counter */ +#define ERC32_MEC_TIMER_CONTROL_RTCSL 0x00000800 /* 1 = load scalar and start */ + /* 0 = no function */ + +/* + * The following defines the bits in the UART Control Registers. + * + * NOTE: Same bits in UART channels A and B. + */ + +#define ERC32_MEC_UART_CONTROL_RTD 0x000000FF /* RX/TX data */ +#define ERC32_MEC_UART_CONTROL_DR 0x00000100 /* RX Data Ready */ +#define ERC32_MEC_UART_CONTROL_TSE 0x00000200 /* TX Send Empty */ + /* (i.e. no data to send) */ +#define ERC32_MEC_UART_CONTROL_THE 0x00000400 /* TX Hold Empty */ + /* (i.e. ready to load) */ + +/* + * The following defines the bits in the MEC UART Control Registers. + */ + +#define ERC32_MEC_UART_STATUS_DR 0x00000001 /* Data Ready */ +#define ERC32_MEC_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */ +#define ERC32_MEC_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */ +#define ERC32_MEC_UART_STATUS_FE 0x00000010 /* RX Framing Error */ +#define ERC32_MEC_UART_STATUS_PE 0x00000020 /* RX Parity Error */ +#define ERC32_MEC_UART_STATUS_OE 0x00000040 /* RX Overrun Error */ +#define ERC32_MEC_UART_STATUS_CU 0x00000080 /* Clear Errors */ +#define ERC32_MEC_UART_STATUS_TXE 0x00000006 /* TX Empty */ + +#define ERC32_MEC_UART_STATUS_DRA (ERC32_MEC_UART_STATUS_DR << 0) +#define ERC32_MEC_UART_STATUS_TSEA (ERC32_MEC_UART_STATUS_TSE << 0) +#define ERC32_MEC_UART_STATUS_THEA (ERC32_MEC_UART_STATUS_THE << 0) +#define ERC32_MEC_UART_STATUS_FEA (ERC32_MEC_UART_STATUS_FE << 0) +#define ERC32_MEC_UART_STATUS_PEA (ERC32_MEC_UART_STATUS_PE << 0) +#define ERC32_MEC_UART_STATUS_OEA (ERC32_MEC_UART_STATUS_OE << 0) +#define ERC32_MEC_UART_STATUS_CUA (ERC32_MEC_UART_STATUS_CU << 0) +#define ERC32_MEC_UART_STATUS_TXEA (ERC32_MEC_UART_STATUS_TXE << 0) + +#define ERC32_MEC_UART_STATUS_DRB (ERC32_MEC_UART_STATUS_DR << 16) +#define ERC32_MEC_UART_STATUS_TSEB (ERC32_MEC_UART_STATUS_TSE << 16) +#define ERC32_MEC_UART_STATUS_THEB (ERC32_MEC_UART_STATUS_THE << 16) +#define ERC32_MEC_UART_STATUS_FEB (ERC32_MEC_UART_STATUS_FE << 16) +#define ERC32_MEC_UART_STATUS_PEB (ERC32_MEC_UART_STATUS_PE << 16) +#define ERC32_MEC_UART_STATUS_OEB (ERC32_MEC_UART_STATUS_OE << 16) +#define ERC32_MEC_UART_STATUS_CUB (ERC32_MEC_UART_STATUS_CU << 16) +#define ERC32_MEC_UART_STATUS_TXEB (ERC32_MEC_UART_STATUS_TXE << 16) + +#ifndef ASM + +/* + * This is used to manipulate the on-chip registers. + * + * The following symbol must be defined in the linkcmds file and point + * to the correct location. + */ + +extern ERC32_Register_Map ERC32_MEC; + +/* + * Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + * + * NOTE: For operations which are not atomic, this code disables interrupts + * to guarantee there are no intervening accesses to the same register. + * The operations which read the register, modify the value and then + * store the result back are vulnerable. + */ + +#define ERC32_Clear_interrupt( _source ) \ + do { \ + ERC32_MEC.Interrupt_Clear = (1 << (_source)); \ + } while (0) + +#define ERC32_Force_interrupt( _source ) \ + do { \ + ERC32_MEC.Interrupt_Force = (1 << (_source)); \ + } while (0) + +#define ERC32_Is_interrupt_pending( _source ) \ + (ERC32_MEC.Interrupt_Pending & (1 << (_source))) + +#define ERC32_Is_interrupt_masked( _source ) \ + (ERC32_MEC.Interrupt_Masked & (1 << (_source))) + +#define ERC32_Mask_interrupt( _source ) \ + do { \ + unsigned32 _level; \ + \ + sparc_disable_interrupts( _level ); \ + ERC32_MEC.Interrupt_Mask |= (1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define ERC32_Unmask_interrupt( _source ) \ + do { \ + unsigned32 _level; \ + \ + sparc_disable_interrupts( _level ); \ + ERC32_MEC.Interrupt_Mask &= ~(1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define ERC32_Disable_interrupt( _source, _previous ) \ + do { \ + unsigned32 _level; \ + unsigned32 _mask = 1 << (_source); \ + \ + sparc_disable_interrupts( _level ); \ + (_previous) = ERC32_MEC.Interrupt_Mask; \ + ERC32_MEC.Interrupt_Mask = _previous | _mask; \ + sparc_enable_interrupts( _level ); \ + (_previous) &= ~_mask; \ + } while (0) + +#define ERC32_Restore_interrupt( _source, _previous ) \ + do { \ + unsigned32 _level; \ + unsigned32 _mask = 1 << (_source); \ + \ + sparc_disable_interrupts( _level ); \ + ERC32_MEC.Interrupt_Mask = \ + (ERC32_MEC.Interrupt_Mask & ~_mask) | (_previous); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +/* + * The following macros attempt to hide the fact that the General Purpose + * Timer and Real Time Clock Timer share the Timer Control Register. Because + * the Timer Control Register is write only, we must mirror it in software + * and insure that writes to one timer do not alter the current settings + * and status of the other timer. + * + * This code promotes the view that the two timers are completely independent. + * By exclusively using the routines below to access the Timer Control + * Register, the application can view the system as having a General Purpose + * Timer Control Register and a Real Time Clock Timer Control Register + * rather than the single shared value. + * + * Each logical timer control register is organized as follows: + * + * D0 - Counter Reload + * 1 = reload counter at zero and restart + * 0 = stop counter at zero + * + * D1 - Counter Load + * 1 = load counter with preset value and restart + * 0 = no function + * + * D2 - Enable + * 1 = enable counting + * 0 = hold scaler and counter + * + * D2 - Scaler Load + * 1 = load scalar with preset value and restart + * 0 = no function + * + * To insure the management of the mirror is atomic, we disable interrupts + * around updates. + */ + +#define ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000001 +#define ERC32_MEC_TIMER_COUNTER_STOP_AT_ZERO 0x00000000 + +#define ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER 0x00000002 + +#define ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING 0x00000004 +#define ERC32_MEC_TIMER_COUNTER_DISABLE_COUNTING 0x00000000 + +#define ERC32_MEC_TIMER_COUNTER_LOAD_SCALER 0x00000008 + +#define ERC32_MEC_TIMER_COUNTER_RELOAD_MASK 0x00000001 +#define ERC32_MEC_TIMER_COUNTER_ENABLE_MASK 0x00000004 + +#define ERC32_MEC_TIMER_COUNTER_DEFINED_MASK 0x0000000F +#define ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000005 + +extern unsigned32 _ERC32_MEC_Timer_Control_Mirror; + +/* + * This macros manipulate the General Purpose Timer portion of the + * Timer Control register and promote the view that there are actually + * two independent Timer Control Registers. + */ + +#define ERC32_MEC_Set_General_Purpose_Timer_Control( _value ) \ + do { \ + unsigned32 _level; \ + unsigned32 _control; \ + unsigned32 __value; \ + \ + __value = ((_value) & 0x0f); \ + sparc_disable_interrupts( _level ); \ + _control = _ERC32_MEC_Timer_Control_Mirror; \ + _control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK << 8; \ + _ERC32_MEC_Timer_Control_Mirror = _control | _value; \ + _control &= (ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK << 8); \ + _control |= __value; \ + /* printf( "GPT 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \ + ERC32_MEC.Timer_Control = _control; \ + sparc_enable_interrupts( _level ); \ + } while ( 0 ) + +#define ERC32_MEC_Get_General_Purpose_Timer_Control( _value ) \ + do { \ + (_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \ + } while ( 0 ) + +/* + * This macros manipulate the Real Timer Clock Timer portion of the + * Timer Control register and promote the view that there are actually + * two independent Timer Control Registers. + */ + +#define ERC32_MEC_Set_Real_Time_Clock_Timer_Control( _value ) \ + do { \ + unsigned32 _level; \ + unsigned32 _control; \ + unsigned32 __value; \ + \ + __value = ((_value) & 0x0f) << 8; \ + sparc_disable_interrupts( _level ); \ + _control = _ERC32_MEC_Timer_Control_Mirror; \ + _control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK; \ + _ERC32_MEC_Timer_Control_Mirror = _control | _value; \ + _control &= ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK; \ + _control |= __value; \ + /* printf( "RTC 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \ + ERC32_MEC.Timer_Control = _control; \ + sparc_enable_interrupts( _level ); \ + } while ( 0 ) + +#define ERC32_MEC_Get_Real_Time_Clock_Timer_Control( _value ) \ + do { \ + (_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \ + } while ( 0 ) + + +#endif /* !ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_INCLUDE_ERC32_h */ +/* end of include file */ + diff --git a/c/src/tests/sptests/sp04/task1.c b/c/src/tests/sptests/sp04/task1.c index 117f5eaa80..671ae5483d 100644 --- a/c/src/tests/sptests/sp04/task1.c +++ b/c/src/tests/sptests/sp04/task1.c @@ -30,8 +30,8 @@ rtems_task Task_1( rtems_mode previous_mode; rtems_time_of_day time; rtems_status_code status; - rtems_unsigned32 start; - rtems_unsigned32 end; + rtems_unsigned32 start_time; + rtems_unsigned32 end_time; puts( "TA1 - rtems_task_suspend - on Task 2" ); status = rtems_task_suspend( Task_id[ 2 ] ); @@ -41,16 +41,16 @@ rtems_task Task_1( status = rtems_task_suspend( Task_id[ 3 ] ); directive_failed( status, "rtems_task_suspend of TA3" ); - status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &start ); + status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &start_time ); directive_failed( status, "rtems_clock_get" ); puts( "TA1 - killing time" ); for ( ; ; ) { - status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &end ); + status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &end_time ); directive_failed( status, "rtems_clock_get" ); - if ( end > (start + 2) ) + if ( end_time > (start_time + 2) ) break; } diff --git a/c/src/tests/sptests/sp09/screen09.c b/c/src/tests/sptests/sp09/screen09.c index 5c6eece679..c6fd1d3d72 100644 --- a/c/src/tests/sptests/sp09/screen09.c +++ b/c/src/tests/sptests/sp09/screen09.c @@ -25,7 +25,11 @@ void Screen9() rtems_status_code status; rtems_isr_entry old_service_routine; - status = rtems_interrupt_catch( Service_routine, 500, &old_service_routine ); + status = rtems_interrupt_catch( + Service_routine, + ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER + 10, + &old_service_routine + ); fatal_directive_status( status, RTEMS_INVALID_NUMBER, diff --git a/c/src/tests/sptests/sp11/sp11.scn b/c/src/tests/sptests/sp11/sp11.scn index 7abb8afe45..f34a9eac5f 100644 --- a/c/src/tests/sptests/sp11/sp11.scn +++ b/c/src/tests/sptests/sp11/sp11.scn @@ -11,7 +11,7 @@ TA1 - rtems_event_receive - waiting with 10 second timeout on RTEMS_EVENT_14 TA2 - RTEMS_EVENT_17 or RTEMS_EVENT_18 received - eventout => 00040000 TA2 - rtems_event_send - send RTEMS_EVENT_14 to TA1 TA2 - rtems_clock_set - 08:15:00 02/12/1988 -TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 5 seconds +TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 4 seconds TA2 - rtems_event_receive - waiting forever on RTEMS_EVENT_10 TA1 - RTEMS_EVENT_14 received - eventout => 00004000 TA1 - rtems_event_send - send RTEMS_EVENT_19 to TA2 diff --git a/c/src/tests/sptests/sp11/task2.c b/c/src/tests/sptests/sp11/task2.c index 176582bc36..d5ac476dac 100644 --- a/c/src/tests/sptests/sp11/task2.c +++ b/c/src/tests/sptests/sp11/task2.c @@ -73,9 +73,9 @@ rtems_task Task_2( status = rtems_clock_set( &time ); directive_failed( status, "TA2 rtems_clock_set" ); - time.second += 5; + time.second += 4; puts( - "TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 5 seconds" + "TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 4 seconds" ); status = rtems_timer_fire_when( Timer_id[ 5 ], @@ -83,7 +83,7 @@ rtems_task Task_2( TA2_send_10_to_self, NULL ); - directive_failed( status, "rtems_timer_fire_when after 5 seconds" ); + directive_failed( status, "rtems_timer_fire_when after 4 seconds" ); puts( "TA2 - rtems_event_receive - waiting forever on RTEMS_EVENT_10" ); status = rtems_event_receive( diff --git a/c/src/tests/sptests/sp12/system.h b/c/src/tests/sptests/sp12/system.h index 3c126963b6..81af1abbd9 100644 --- a/c/src/tests/sptests/sp12/system.h +++ b/c/src/tests/sptests/sp12/system.h @@ -57,6 +57,7 @@ rtems_task Task5( #define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER #define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER +#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2) #define CONFIGURE_MAXIMUM_SEMAPHORES 10 #define CONFIGURE_TICKS_PER_TIMESLICE 100 diff --git a/c/src/tests/sptests/sp19/system.h b/c/src/tests/sptests/sp19/system.h index 557299b9c2..6052075250 100644 --- a/c/src/tests/sptests/sp19/system.h +++ b/c/src/tests/sptests/sp19/system.h @@ -38,6 +38,8 @@ rtems_task Task_1( #define CONFIGURE_SPTEST +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + #define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER #define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER diff --git a/c/src/tests/sptests/sp20/init.c b/c/src/tests/sptests/sp20/init.c index 0e1b56ba3a..d2bc2ec00d 100644 --- a/c/src/tests/sptests/sp20/init.c +++ b/c/src/tests/sptests/sp20/init.c @@ -44,7 +44,7 @@ rtems_task Init( status = rtems_task_create( Task_name[ index ], Priorities[ index ], - RTEMS_MINIMUM_STACK_SIZE, + RTEMS_MINIMUM_STACK_SIZE * 4, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ index ] diff --git a/c/src/tests/sptests/sp24/init.c b/c/src/tests/sptests/sp24/init.c index 81abc0277a..74114ab82a 100644 --- a/c/src/tests/sptests/sp24/init.c +++ b/c/src/tests/sptests/sp24/init.c @@ -52,7 +52,7 @@ rtems_task Init( status = rtems_task_create( Task_name[ index ], 1, - RTEMS_MINIMUM_STACK_SIZE, + RTEMS_MINIMUM_STACK_SIZE * 2, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ index ] diff --git a/c/src/tests/sptests/spsize/init.c b/c/src/tests/sptests/spsize/init.c index 66e40cd0f1..d0d5490966 100644 --- a/c/src/tests/sptests/spsize/init.c +++ b/c/src/tests/sptests/spsize/init.c @@ -36,8 +36,12 @@ rtems_task Init( setvbuf(stdout, 0, _IONBF, 0); + puts( "\n*** RTEMS SIZE PROGRAM ***" ); + size_rtems( 1 ); + puts( "*** END OF RTEMS SIZE PROGRAM ***" ); + exit( 0 ); +#if 0 do { - puts( "\n*** RTEMS SIZE PROGRAM ***" ); printf( "\n\nPlease select program mode:\n" ); printf( " 1) Print Formulas\n" ); printf( " 2) Determine Workspace Size\n" ); @@ -52,4 +56,5 @@ rtems_task Init( default: continue; } } while ( FOREVER ); +#endif } diff --git a/c/src/tests/sptests/spsize/size.c b/c/src/tests/sptests/spsize/size.c index 474095972a..91ccbfb1a3 100644 --- a/c/src/tests/sptests/spsize/size.c +++ b/c/src/tests/sptests/spsize/size.c @@ -390,6 +390,22 @@ uninitialized += (sizeof _CPU_Interrupt_stack_low) + #endif +#ifdef sparc + +/* cpu.h */ +uninitialized += (sizeof _CPU_Interrupt_stack_low) + + (sizeof _CPU_Interrupt_stack_high) + + (sizeof _CPU_Null_fp_context) + + (sizeof _CPU_Trap_Table_area); + +#ifdef erc32 +uninitialized += (sizeof _ERC32_MEC_Timer_Control_Mirror); +#endif + + +#endif + + #ifdef no_cpu /* cpu.h */ @@ -421,13 +437,16 @@ initialized += (sizeof _TOD_Days_to_date) + (sizeof _TOD_Days_since_last_leap_year); +#ifdef sparc + +initialized += (sizeof _CPU_Trap_slot_template); + +#endif + puts( "" ); -#ifdef i960CA - print_formula(); -#else + if ( mode == 0 ) help_size(); else print_formula(); -#endif printf( "\n" ); printf( "RTEMS uninitialized data consumes %d bytes\n", uninitialized ); diff --git a/c/src/tests/tmtests/tm08/task1.c b/c/src/tests/tmtests/tm08/task1.c index 1a03329f26..b29d6c6206 100644 --- a/c/src/tests/tmtests/tm08/task1.c +++ b/c/src/tests/tmtests/tm08/task1.c @@ -198,7 +198,7 @@ rtems_task test_task( end_time = Read_timer(); put_time( - "rtems_task_set_note", + "rtems_task_get_note", end_time, OPERATION_COUNT, overhead, diff --git a/c/src/tests/tmtests/tm27/task1.c b/c/src/tests/tmtests/tm27/task1.c index c18ae2ab9b..a47e434200 100644 --- a/c/src/tests/tmtests/tm27/task1.c +++ b/c/src/tests/tmtests/tm27/task1.c @@ -11,6 +11,12 @@ * $Id$ */ +/* + * WARNING!!!!!!!!! + * + * THIS TEST USES INTERNAL RTEMS VARIABLES!!! + */ + #define TEST_INIT #include "system.h" @@ -33,15 +39,6 @@ rtems_isr Isr_handler( rtems_vector_number vector ); -/* - * INTERNAL RTEMS VARIABLES!!! - */ - -extern rtems_unsigned32 _Thread_Dispatch_disable_level; -extern rtems_unsigned32 _Context_Switch_necessary; -extern Chain_Control *_Thread_Ready_chain; -extern rtems_tcb *_Thread_Heir; - rtems_task Init( rtems_task_argument argument ) @@ -169,9 +166,23 @@ rtems_task Task_1( Interrupt_occurred = 0; Timer_initialize(); Cause_tm27_intr(); - /* goes to Isr_handler */ + + /* + * goes to Isr_handler and then returns + */ + + puts( "*** END OF TEST 27 ***" ); + exit( 0 ); } +/* + * NOTE: When this task is executing, some of the assumptions made + * regarding the placement of the currently executing task's TCB + * on the ready chains have been violated. At least the assumption + * that this task is at the head of the chain for its priority + * has been violated. + */ + rtems_task Task_2( rtems_task_argument argument ) @@ -197,8 +208,20 @@ rtems_task Task_2( 0 ); - puts( "*** END OF TEST 27 ***" ); - exit( 0 ); + fflush( stdout ); + + /* + * Switch back to the other task to exit the test. + */ + + _Thread_Dispatch_disable_level = 0; + + _Thread_Heir = (rtems_tcb *) _Thread_Ready_chain[254].first; + + _Context_Switch_necessary = 1; + + _Thread_Dispatch(); + } /* The Isr_handler() and Isr_handler_inner() routines are structured diff --git a/cpukit/libcsupport/include/ringbuf.h b/cpukit/libcsupport/include/ringbuf.h index b2494c1527..8c80aaf9c8 100644 --- a/cpukit/libcsupport/include/ringbuf.h +++ b/cpukit/libcsupport/include/ringbuf.h @@ -10,13 +10,13 @@ #define __RINGBUF_H__ #ifndef RINGBUF_QUEUE_LENGTH -#define RINGBUF_QUEUE_LENGTH 200 +#define RINGBUF_QUEUE_LENGTH 128 #endif typedef struct { char buffer[RINGBUF_QUEUE_LENGTH]; - int head; - int tail; + volatile int head; + volatile int tail; } Ring_buffer_t; #define Ring_buffer_Initialize( _buffer ) \ @@ -27,16 +27,27 @@ typedef struct { #define Ring_buffer_Is_empty( _buffer ) \ ( (_buffer)->head == (_buffer)->tail ) +#define Ring_buffer_Is_full( _buffer ) \ + ( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH ) + #define Ring_buffer_Add_character( _buffer, _ch ) \ do { \ - (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \ - (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \ + rtems_unsigned32 isrlevel; \ + \ + rtems_interrupt_disable( isrlevel ); \ + (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \ + (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \ + rtems_interrupt_enable( isrlevel ); \ } while ( 0 ) #define Ring_buffer_Remove_character( _buffer, _ch ) \ do { \ - (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \ - (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \ + rtems_unsigned32 isrlevel; \ + \ + rtems_interrupt_disable( isrlevel ); \ + (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \ + (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \ + rtems_interrupt_enable( isrlevel ); \ } while ( 0 ) #endif diff --git a/cpukit/posix/include/rtems/posix/intr.h b/cpukit/posix/include/rtems/posix/intr.h index b940148999..ae1690f676 100644 --- a/cpukit/posix/include/rtems/posix/intr.h +++ b/cpukit/posix/include/rtems/posix/intr.h @@ -60,8 +60,7 @@ EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information; * interrupt handlers installed on each vector. */ -EXTERN POSIX_Interrupt_Control - _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ]; +EXTERN POSIX_Interrupt_Control _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ]; /* * _POSIX_Interrupt_Manager_initialization diff --git a/cpukit/rtems/src/event.c b/cpukit/rtems/src/event.c index 2786d6b8dc..101162bec6 100644 --- a/cpukit/rtems/src/event.c +++ b/cpukit/rtems/src/event.c @@ -108,3 +108,205 @@ rtems_status_code rtems_event_receive( _Thread_Enable_dispatch(); return( _Thread_Executing->Wait.return_code ); } + + +/*PAGE + * + * _Event_Seize + * + * This routine attempts to satisfy the requested event condition + * for the running thread. + * + * Input parameters: + * event_in - the event condition to satisfy + * option_set - acquire event options + * ticks - interval to wait + * event_out - pointer to event set output area + * + * Output parameters: NONE + * *event_out - event set output area filled in + * + * INTERRUPT LATENCY: + * available + * wait + * check sync + */ + +void _Event_Seize( + rtems_event_set event_in, + rtems_option option_set, + rtems_interval ticks, + rtems_event_set *event_out +) +{ + Thread_Control *executing; + rtems_event_set seized_events; + rtems_event_set pending_events; + ISR_Level level; + RTEMS_API_Control *api; + + executing = _Thread_Executing; + executing->Wait.return_code = RTEMS_SUCCESSFUL; + + api = executing->API_Extensions[ THREAD_API_RTEMS ]; + + _ISR_Disable( level ); + pending_events = api->pending_events; + seized_events = _Event_sets_Get( pending_events, event_in ); + + if ( !_Event_sets_Is_empty( seized_events ) && + (seized_events == event_in || _Options_Is_any( option_set )) ) { + api->pending_events = + _Event_sets_Clear( pending_events, seized_events ); + _ISR_Enable( level ); + *event_out = seized_events; + return; + } + + if ( _Options_Is_no_wait( option_set ) ) { + _ISR_Enable( level ); + executing->Wait.return_code = RTEMS_UNSATISFIED; + *event_out = seized_events; + return; + } + + _Event_Sync = TRUE; + executing->Wait.option = (unsigned32) option_set; + executing->Wait.count = (unsigned32) event_in; + executing->Wait.return_argument = event_out; + + _ISR_Enable( level ); + _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT ); + + if ( ticks ) { + _Watchdog_Initialize( + &executing->Timer, + _Event_Timeout, + executing->Object.id, + NULL + ); + _Watchdog_Insert_ticks( + &executing->Timer, + ticks, + WATCHDOG_NO_ACTIVATE + ); + } + + _ISR_Disable( level ); + if ( _Event_Sync == TRUE ) { + _Event_Sync = FALSE; + if ( ticks ) + _Watchdog_Activate( &executing->Timer ); + _ISR_Enable( level ); + return; + } + _ISR_Enable( level ); + (void) _Watchdog_Remove( &executing->Timer ); + _Thread_Unblock( executing ); + return; +} + +/*PAGE + * + * _Event_Surrender + * + * This routines remove a thread from the specified threadq. + * + * Input parameters: + * the_thread - pointer to thread to be dequeued + * + * Output parameters: NONE + * + * INTERRUPT LATENCY: + * before flash + * after flash + * check sync + */ + +void _Event_Surrender( + Thread_Control *the_thread +) +{ + ISR_Level level; + rtems_event_set pending_events; + rtems_event_set event_condition; + rtems_event_set seized_events; + rtems_option option_set; + RTEMS_API_Control *api; + + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + + option_set = (rtems_option) the_thread->Wait.option; + + _ISR_Disable( level ); + pending_events = api->pending_events; + event_condition = (rtems_event_set) the_thread->Wait.count; + + seized_events = _Event_sets_Get( pending_events, event_condition ); + + if ( !_Event_sets_Is_empty( seized_events ) ) { + if ( _States_Is_waiting_for_event( the_thread->current_state ) ) { + if ( seized_events == event_condition || _Options_Is_any( option_set ) ) { + api->pending_events = + _Event_sets_Clear( pending_events, seized_events ); + *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; + + _ISR_Flash( level ); + + if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { + _ISR_Enable( level ); + _Thread_Unblock( the_thread ); + } + else { + _Watchdog_Deactivate( &the_thread->Timer ); + _ISR_Enable( level ); + (void) _Watchdog_Remove( &the_thread->Timer ); + _Thread_Unblock( the_thread ); + } + return; + } + } + else if ( _Thread_Is_executing( the_thread ) && _Event_Sync == TRUE ) { + if ( seized_events == event_condition || _Options_Is_any( option_set ) ) { + api->pending_events = _Event_sets_Clear( pending_events,seized_events ); + *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; + _Event_Sync = FALSE; + } + } + } + _ISR_Enable( level ); +} + +/*PAGE + * + * _Event_Timeout + * + * This routine processes a thread which timeouts while waiting to + * receive an event_set. It is called by the watchdog handler. + * + * Input parameters: + * id - thread id + * + * Output parameters: NONE + */ + +void _Event_Timeout( + Objects_Id id, + void *ignored +) +{ + Thread_Control *the_thread; + Objects_Locations location; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + case OBJECTS_ERROR: + case OBJECTS_REMOTE: /* impossible */ + break; + case OBJECTS_LOCAL: + the_thread->Wait.return_code = RTEMS_TIMEOUT; + _Thread_Unblock( the_thread ); + _Thread_Unnest_dispatch(); + break; + } +} diff --git a/cpukit/score/cpu/sparc/README b/cpukit/score/cpu/sparc/README new file mode 100644 index 0000000000..0c481d67c1 --- /dev/null +++ b/cpukit/score/cpu/sparc/README @@ -0,0 +1,118 @@ +# +# $Id$ +# + +This file discusses SPARC specific issues which are important to +this port. The primary topics in this file are: + + + Global Register Usage + + Stack Frame + + EF bit in the PSR + + +Global Register Usage +===================== + +This information on register usage is based heavily on a comment in the +file gcc-2.7.0/config/sparc/sparc.h in the the gcc 2.7.0 source. + + + g0 is hardwired to 0 + + On non-v9 systems: + - g1 is free to use as temporary. + - g2-g4 are reserved for applications. Gcc normally uses them as + temporaries, but this can be disabled via the -mno-app-regs option. + - g5 through g7 are reserved for the operating system. + + On v9 systems: + - g1 and g5 are free to use as temporaries. + - g2-g4 are reserved for applications (the compiler will not normally use + them, but they can be used as temporaries with -mapp-regs). + - g6-g7 are reserved for the operating system. + + NOTE: As of gcc 2.7.0 register g1 was used in the following scenarios: + + + as a temporary by the 64 bit sethi pattern + + when restoring call-preserved registers in large stack frames + +RTEMS places no constraints on the usage of the global registers. Although +gcc assumes that either g5-g7 (non-V9) or g6-g7 (V9) are reserved for the +operating system, RTEMS does not assume any special use for them. + + + +Stack Frame +=========== + +The stack grows downward (i.e. to lower addresses) on the SPARC architecture. + +The following is the organization of the stack frame: + + + + | ............... | + fp | | + +-------------------------------+ + | | + | Local registers, temporaries, | + | and saved floats | x bytes + | | + sp + x +-------------------------------+ + | | + | outgoing parameters past | + | the sixth one | x bytes + | | + sp + 92 +-------------------------------+ * + | | * + | area for callee to save | * + | register arguments | * 24 bytes + | | * + sp + 68 +-------------------------------+ * + | | * + | structure return pointer | * 4 bytes + | | * + sp + 64 +-------------------------------+ * + | | * + | local register set | * 32 bytes + | | * + sp + 32 +-------------------------------+ * + | | * + | input register set | * 32 bytes + | | * + sp +-------------------------------+ * + + +* = minimal stack frame + +x = optional components + +EF bit in the PSR +================= + +The EF (enable floating point unit) in the PSR is utilized in this port to +prevent non-floating point tasks from performing floating point +operations. This bit is maintained as part of the integer context. +However, the floating point context is switched BEFORE the integer +context. Thus the EF bit in place at the time of the FP switch may +indicate that FP operations are disabled. This occurs on certain task +switches, when the EF bit will be 0 for the outgoing task and thus a fault +will be generated on the first FP operation of the FP context save. + +The remedy for this is to enable FP access as the first step in both the +save and restore of the FP context area. This bit will be subsequently +reloaded by the integer context switch. + +Two of the scenarios which demonstrate this problem are outlined below: + +1. When the first FP task is switched to. The system tasks are not FP and +thus would be unable to restore the FP context of the incoming task. + +2. On a deferred FP context switch. In this case, the system might switch +from FP Task A to non-FP Task B and then to FP Task C. In this scenario, +the floating point state must technically be saved by a non-FP task. + + + + + + + + diff --git a/cpukit/score/cpu/sparc/asm.h b/cpukit/score/cpu/sparc/asm.h index 10157171c5..a3d62416b8 100644 --- a/cpukit/score/cpu/sparc/asm.h +++ b/cpukit/score/cpu/sparc/asm.h @@ -28,7 +28,9 @@ */ #define ASM + #include +#include /* * Recent versions of GNU cpp define variables which indicate the @@ -37,7 +39,9 @@ * have to define these as appropriate. */ -/* XXX This does not appear to work on gcc 2.7.0 on the sparc */ +/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */ +/* XXX The following ifdef magic fixes the problem but results in a warning */ +/* XXX when compiling assembly code. */ #undef __USER_LABEL_PREFIX__ #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ @@ -91,6 +95,16 @@ #define PUBLIC(sym) .globl SYM (sym) #define EXTERN(sym) .globl SYM (sym) +/* + * Entry for traps which jump to a programmer-specified trap handler. + */ + +#define TRAP(_vector, _handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + mov _vector, %l3 + #endif /* end of include file */ diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c index cf70913d5e..23d998cab5 100644 --- a/cpukit/score/cpu/sparc/cpu.c +++ b/cpukit/score/cpu/sparc/cpu.c @@ -7,52 +7,115 @@ #include #include -/* _CPU_Initialize +#if defined(erc32) +#include +#endif + +/* + * This initializes the set of opcodes placed in each trap + * table entry. The routine which installs a handler is responsible + * for filling in the fields for the _handler address and the _vector + * trap type. + * + * The constants following this structure are masks for the fields which + * must be filled in when the handler is installed. + */ + +const CPU_Trap_table_entry _CPU_Trap_slot_template = { + 0xa1480000, /* mov %psr, %l0 */ + 0x29000000, /* sethi %hi(_handler), %l4 */ + 0x81c52000, /* jmp %l4 + %lo(_handler) */ + 0xa6102000 /* mov _vector, %l3 */ +}; + +/*PAGE + * + * _CPU_Initialize * * This routine performs processor dependent initialization. * - * INPUT PARAMETERS: + * Input Parameters: * cpu_table - CPU table to initialize * thread_dispatch - address of disptaching routine + * + * Output Parameters: NONE + * + * NOTE: There is no need to save the pointer to the thread dispatch routine. + * The SPARC's assembly code can reference it directly with no problems. */ - void _CPU_Initialize( rtems_cpu_table *cpu_table, - void (*thread_dispatch) /* ignored on this CPU */ + void (*thread_dispatch) /* ignored on this CPU */ ) { - void *pointer; + void *pointer; + unsigned32 trap_table_start; + unsigned32 tbr_value; + CPU_Trap_table_entry *old_tbr; + CPU_Trap_table_entry *trap_table; /* - * The thread_dispatch argument is the address of the entry point - * for the routine called at the end of an ISR once it has been - * decided a context switch is necessary. On some compilation - * systems it is difficult to call a high-level language routine - * from assembly. This allows us to trick these systems. - * - * If you encounter this problem save the entry point in a CPU - * dependent variable. + * Install the executive's trap table. All entries from the original + * trap table are copied into the executive's trap table. This is essential + * since this preserves critical trap handlers such as the window underflow + * and overflow handlers. It is the responsibility of the BSP to provide + * install these in the initial trap table. */ + + trap_table_start = (unsigned32) &_CPU_Trap_Table_area; + if (trap_table_start & (SPARC_TRAP_TABLE_ALIGNMENT-1)) + trap_table_start = (trap_table_start + SPARC_TRAP_TABLE_ALIGNMENT) & + ~(SPARC_TRAP_TABLE_ALIGNMENT-1); + + trap_table = (CPU_Trap_table_entry *) trap_table_start; + + sparc_get_tbr( tbr_value ); - _CPU_Thread_dispatch_pointer = thread_dispatch; + old_tbr = (CPU_Trap_table_entry *) (tbr_value & 0xfffff000); + + memcpy( trap_table, (void *) old_tbr, 256 * sizeof( CPU_Trap_table_entry ) ); + + sparc_set_tbr( trap_table_start ); /* - * If there is not an easy way to initialize the FP context - * during Context_Initialize, then it is usually easier to - * save an "uninitialized" FP context here and copy it to - * the task's during Context_Initialize. + * This seems to be the most appropriate way to obtain an initial + * FP context on the SPARC. The NULL fp context is copied it to + * the task's FP context during Context_Initialize. */ pointer = &_CPU_Null_fp_context; _CPU_Context_save_fp( &pointer ); + /* + * Grab our own copy of the user's CPU table. + */ + _CPU_Table = *cpu_table; + +#if defined(erc32) + + /* + * ERC32 specific initialization + */ + + _ERC32_MEC_Timer_Control_Mirror = 0; + ERC32_MEC.Timer_Control = 0; + + ERC32_MEC.Control |= ERC32_CONFIGURATION_POWER_DOWN_ALLOWED; + +#endif + } /*PAGE * * _CPU_ISR_Get_level + * + * Input Parameters: NONE + * + * Output Parameters: + * returns the current interrupt level (PIL field of the PSR) */ unsigned32 _CPU_ISR_Get_level( void ) @@ -64,134 +127,263 @@ unsigned32 _CPU_ISR_Get_level( void ) return level; } -/* _CPU_ISR_install_vector +/*PAGE + * + * _CPU_ISR_install_raw_handler + * + * This routine installs the specified handler as a "raw" non-executive + * supported trap handler (a.k.a. interrupt service routine). + * + * Input Parameters: + * vector - trap table entry number plus synchronous + * vs. asynchronous information + * new_handler - address of the handler to be installed + * old_handler - pointer to an address of the handler previously installed + * + * Output Parameters: NONE + * *new_handler - address of the handler previously installed + * + * NOTE: + * + * On the SPARC, there are really only 256 vectors. However, the executive + * has no easy, fast, reliable way to determine which traps are synchronous + * and which are asynchronous. By default, synchronous traps return to the + * instruction which caused the interrupt. So if you install a software + * trap handler as an executive interrupt handler (which is desirable since + * RTEMS takes care of window and register issues), then the executive needs + * to know that the return address is to the trap rather than the instruction + * following the trap. + * + * So vectors 0 through 255 are treated as regular asynchronous traps which + * provide the "correct" return address. Vectors 256 through 512 are assumed + * by the executive to be synchronous and to require that the return address + * be fudged. + * + * If you use this mechanism to install a trap handler which must reexecute + * the instruction which caused the trap, then it should be installed as + * an asynchronous trap. This will avoid the executive changing the return + * address. + */ + +void _CPU_ISR_install_raw_handler( + unsigned32 vector, + proc_ptr new_handler, + proc_ptr *old_handler +) +{ + unsigned32 real_vector; + CPU_Trap_table_entry *tbr; + CPU_Trap_table_entry *slot; + unsigned32 u32_tbr; + unsigned32 u32_handler; + + /* + * Get the "real" trap number for this vector ignoring the synchronous + * versus asynchronous indicator included with our vector numbers. + */ + + real_vector = SPARC_REAL_TRAP_NUMBER( vector ); + + /* + * Get the current base address of the trap table and calculate a pointer + * to the slot we are interested in. + */ + + sparc_get_tbr( u32_tbr ); + + u32_tbr &= 0xfffff000; + + tbr = (CPU_Trap_table_entry *) u32_tbr; + + slot = &tbr[ real_vector ]; + + /* + * Get the address of the old_handler from the trap table. + * + * NOTE: The old_handler returned will be bogus if it does not follow + * the RTEMS model. + */ + +#define HIGH_BITS_MASK 0xFFFFFC00 +#define HIGH_BITS_SHIFT 10 +#define LOW_BITS_MASK 0x000003FF + + if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) { + u32_handler = + ((slot->sethi_of_handler_to_l4 & HIGH_BITS_MASK) << HIGH_BITS_SHIFT) | + (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK); + *old_handler = (proc_ptr) u32_handler; + } else + *old_handler = 0; + + /* + * Copy the template to the slot and then fix it. + */ + + *slot = _CPU_Trap_slot_template; + + u32_handler = (unsigned32) new_handler; + + slot->mov_vector_l3 |= vector; + slot->sethi_of_handler_to_l4 |= + (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT; + slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK); +} + +/*PAGE + * + * _CPU_ISR_install_vector * * This kernel routine installs the RTEMS handler for the * specified vector. * * Input parameters: - * vector - interrupt vector number - * old_handler - former ISR for this vector number - * new_handler - replacement ISR for this vector number + * vector - interrupt vector number + * new_handler - replacement ISR for this vector number + * old_handler - pointer to former ISR for this vector number * - * Output parameters: NONE + * Output parameters: + * *old_handler - former ISR for this vector number * */ - void _CPU_ISR_install_vector( unsigned32 vector, proc_ptr new_handler, proc_ptr *old_handler ) { - *old_handler = _ISR_Vector_table[ vector ]; + unsigned32 real_vector; + proc_ptr ignored; + + /* + * Get the "real" trap number for this vector ignoring the synchronous + * versus asynchronous indicator included with our vector numbers. + */ + + real_vector = SPARC_REAL_TRAP_NUMBER( vector ); /* - * If the interrupt vector table is a table of pointer to isr entry - * points, then we need to install the appropriate RTEMS interrupt - * handler for this vector number. + * Return the previous ISR handler. */ + *old_handler = _ISR_Vector_table[ real_vector ]; + /* - * We put the actual user ISR address in '_ISR_vector_table'. This will - * be used by the _ISR_Handler so the user gets control. + * Install the wrapper so this ISR can be invoked properly. */ - _ISR_Vector_table[ vector ] = new_handler; -} + _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored ); -/*PAGE - * - * _CPU_Install_interrupt_stack - */ + /* + * We put the actual user ISR address in '_ISR_vector_table'. This will + * be used by the _ISR_Handler so the user gets control. + */ -void _CPU_Install_interrupt_stack( void ) -{ + _ISR_Vector_table[ real_vector ] = new_handler; } /*PAGE * * _CPU_Context_Initialize + * + * This kernel routine initializes the basic non-FP context area associated + * with each thread. + * + * Input parameters: + * the_context - pointer to the context area + * stack_base - address of memory for the SPARC + * size - size in bytes of the stack area + * new_level - interrupt level for this context area + * entry_point - the starting execution point for this this context + * is_fp - TRUE if this context is associated with an FP thread + * + * Output parameters: NONE */ -/* - * The following constants assist in building a thread's initial context. - */ - -#define CPU_FRAME_SIZE (112) /* based on disassembled test code */ -#define ADDR_ADJ_OFFSET -8 - void _CPU_Context_Initialize( - Context_Control *_the_context, - unsigned32 *_stack_base, - unsigned32 _size, - unsigned32 _new_level, - void *_entry_point + Context_Control *the_context, + unsigned32 *stack_base, + unsigned32 size, + unsigned32 new_level, + void *entry_point, + boolean is_fp ) { - unsigned32 jmp_addr; - unsigned32 _stack_high; /* highest "stack aligned" address */ - unsigned32 _the_size; + unsigned32 stack_high; /* highest "stack aligned" address */ + unsigned32 the_size; unsigned32 tmp_psr; - jmp_addr = (unsigned32) _entry_point; - /* * On CPUs with stacks which grow down (i.e. SPARC), we build the stack - * based on the _stack_high address. + * based on the stack_high address. */ - _stack_high = ((unsigned32)(_stack_base) + _size); - _stack_high &= ~(CPU_STACK_ALIGNMENT - 1); + stack_high = ((unsigned32)(stack_base) + size); + stack_high &= ~(CPU_STACK_ALIGNMENT - 1); - _the_size = _size & ~(CPU_STACK_ALIGNMENT - 1); + the_size = size & ~(CPU_STACK_ALIGNMENT - 1); -/* XXX following code is based on unix port */ /* - * XXX SPARC port needs a diagram like this one... - * See /usr/include/sys/stack.h in Solaris 2.3 for a nice - * diagram of the stack. + * See the README in this directory for a diagram of the stack. */ - _the_context->o7 = jmp_addr + ADDR_ADJ_OFFSET; - _the_context->o6 = (unsigned32)(_stack_high - CPU_FRAME_SIZE); - _the_context->i6 = (unsigned32)(_stack_high); -#if 0 - _the_context->rp = jmp_addr + ADDR_ADJ_OFFSET; - _the_context->sp = (unsigned32)(_stack_high - CPU_FRAME_SIZE); - _the_context->fp = (unsigned32)(_stack_high); -#endif + the_context->o7 = ((unsigned32) entry_point) - 8; + the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE; + the_context->i6_fp = stack_high; - _the_context->wim = 0x01; + /* + * Build the PSR for the task. Most everything can be 0 and the + * CWP is corrected during the context switch. + * + * The EF bit determines if the floating point unit is available. + * The FPU is ONLY enabled if the context is associated with an FP task + * and this SPARC model has an FPU. + */ sparc_get_psr( tmp_psr ); - tmp_psr &= ~SPARC_PIL_MASK; - tmp_psr |= (((_new_level) << 8) & SPARC_PIL_MASK); - tmp_psr = (tmp_psr & ~0x07) | 0x07; /* XXX should use num windows */ - _the_context->psr = tmp_psr; + tmp_psr &= ~SPARC_PSR_PIL_MASK; + tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK; + tmp_psr &= ~SPARC_PSR_EF_MASK; /* disabled by default */ + +#if (SPARC_HAS_FPU == 1) + /* + * If this bit is not set, then a task gets a fault when it accesses + * a floating point register. This is a nice way to detect floating + * point tasks which are not currently declared as such. + */ + + if ( is_fp ) + tmp_psr |= SPARC_PSR_EF_MASK; +#endif + the_context->psr = tmp_psr; } /*PAGE * * _CPU_Internal_threads_Idle_thread_body * - * NOTES: - * - * 1. This is the same as the regular CPU independent algorithm. - * - * 2. If you implement this using a "halt", "idle", or "shutdown" - * instruction, then don't forget to put it in an infinite loop. + * Some SPARC implementations have low power, sleep, or idle modes. This + * tries to take advantage of those models. + */ + +#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE) + +/* + * This is the implementation for the erc32. * - * 3. Be warned. Some processors with onboard DMA have been known - * to stop the DMA if the CPU were put in IDLE mode. This might - * also be a problem with other on-chip peripherals. So use this - * hook with caution. + * NOTE: Low power mode was enabled at initialization time. */ +#if defined(erc32) + void _CPU_Internal_threads_Idle_thread_body( void ) { - - for( ; ; ) - /* insert your "halt" instruction here */ ; + while (1) { + ERC32_MEC.Power_Down = 0; /* value is irrelevant */ + } } + +#endif + +#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */ diff --git a/cpukit/score/cpu/sparc/rtems/asm.h b/cpukit/score/cpu/sparc/rtems/asm.h index 10157171c5..a3d62416b8 100644 --- a/cpukit/score/cpu/sparc/rtems/asm.h +++ b/cpukit/score/cpu/sparc/rtems/asm.h @@ -28,7 +28,9 @@ */ #define ASM + #include +#include /* * Recent versions of GNU cpp define variables which indicate the @@ -37,7 +39,9 @@ * have to define these as appropriate. */ -/* XXX This does not appear to work on gcc 2.7.0 on the sparc */ +/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */ +/* XXX The following ifdef magic fixes the problem but results in a warning */ +/* XXX when compiling assembly code. */ #undef __USER_LABEL_PREFIX__ #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ @@ -91,6 +95,16 @@ #define PUBLIC(sym) .globl SYM (sym) #define EXTERN(sym) .globl SYM (sym) +/* + * Entry for traps which jump to a programmer-specified trap handler. + */ + +#define TRAP(_vector, _handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + mov _vector, %l3 + #endif /* end of include file */ diff --git a/cpukit/score/cpu/unix/cpu.c b/cpukit/score/cpu/unix/cpu.c index 347882ddcc..c77276020b 100644 --- a/cpukit/score/cpu/unix/cpu.c +++ b/cpukit/score/cpu/unix/cpu.c @@ -341,17 +341,10 @@ void _CPU_Install_interrupt_stack( void ) * * _CPU_Internal_threads_Idle_thread_body * - * NOTES: - * - * 1. This is the same as the regular CPU independent algorithm. - * - * 2. If you implement this using a "halt", "idle", or "shutdown" - * instruction, then don't forget to put it in an infinite loop. - * - * 3. Be warned. Some processors with onboard DMA have been known - * to stop the DMA if the CPU were put in IDLE mode. This might - * also be a problem with other on-chip peripherals. So use this - * hook with caution. + * Stop until we get a signal which is the logically the same thing + * entering low-power or sleep mode on a real processor and waiting for + * an interrupt. This significantly reduces the consumption of host + * CPU cycles which is again similar to low power mode. */ void _CPU_Internal_threads_Idle_thread_body( void ) @@ -370,7 +363,8 @@ void _CPU_Context_Initialize( unsigned32 *_stack_base, unsigned32 _size, unsigned32 _new_level, - void *_entry_point + void *_entry_point, + boolean _is_fp ) { void *source; @@ -697,49 +691,15 @@ void _CPU_Fatal_error(unsigned32 error) _exit(error); } -/*PAGE - * - * _CPU_ffs - */ - -int _CPU_ffs(unsigned32 value) -{ - int output; - extern int ffs( int ); - - output = ffs(value); - output = output - 1; - - return output; -} - - /* * Special Purpose Routines to hide the use of UNIX system calls. */ -#if 0 -/* XXX clock had this set of #define's */ - -/* - * In order to get the types and prototypes used in this file under - * Solaris 2.3, it is necessary to pull the following magic. - */ - -#if defined(solaris) -#warning "Ignore the undefining __STDC__ warning" -#undef __STDC__ -#define __STDC__ 0 -#undef _POSIX_C_SOURCE -#endif -#endif - int _CPU_Get_clock_vector( void ) { return SIGALRM; } - void _CPU_Start_clock( int microseconds ) diff --git a/cpukit/score/include/rtems/score/bitfield.h b/cpukit/score/include/rtems/score/bitfield.h index a74ea97735..6dbf1e0ba0 100644 --- a/cpukit/score/include/rtems/score/bitfield.h +++ b/cpukit/score/include/rtems/score/bitfield.h @@ -38,9 +38,58 @@ extern "C" { * significant impact on the performance of the executive as a whole. */ +#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE ) + +#ifndef INIT + extern const unsigned char __log2table[256]; +#else +const unsigned char __log2table[256] = { + 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#endif + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE ) + #define _Bitfield_Find_first_bit( _value, _bit_number ) \ _CPU_Bitfield_Find_first_bit( _value, _bit_number ) +#else + +/* + * The following must be a macro because if a CPU specific version + * is used it will most likely use inline assembly. + */ + +#define _Bitfield_Find_first_bit( _value, _bit_number ) \ + { \ + register __value = (_value); \ + register const unsigned char *__p = __log2table; \ + \ + if ( __value < 0x100 ) \ + (_bit_number) = __p[ __value ] + 8; \ + else \ + (_bit_number) = __p[ __value >> 8 ]; \ + } + +#endif + #ifdef __cplusplus } #endif diff --git a/cpukit/score/include/rtems/score/context.h b/cpukit/score/include/rtems/score/context.h index b3a423bb47..4cd1f1e4c5 100644 --- a/cpukit/score/include/rtems/score/context.h +++ b/cpukit/score/include/rtems/score/context.h @@ -47,8 +47,9 @@ EXTERN boolean _Context_Switch_necessary; * thread's initial state. */ -#define _Context_Initialize( _the_context, _stack, _size, _isr, _entry ) \ - _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry ) +#define \ + _Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \ + _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) /* * _Context_Switch diff --git a/cpukit/score/include/rtems/score/isr.h b/cpukit/score/include/rtems/score/isr.h index 2409ed394a..bb80823cfb 100644 --- a/cpukit/score/include/rtems/score/isr.h +++ b/cpukit/score/include/rtems/score/isr.h @@ -50,11 +50,18 @@ typedef ISR_Handler ( *ISR_Handler_entry )( ISR_Vector_number ); /* - * This constant promotes out the number of vectors supported by - * the current CPU being used. + * This constant promotes out the number of vectors truly supported by + * the current CPU being used. This is usually the number of distinct vectors + * the cpu can vector. */ -#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS +#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS + +/* + * This constant promotes out the highest valid interrupt vector number. + */ + +#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER /* * The following is TRUE if signals have been sent to the currently @@ -75,7 +82,7 @@ EXTERN unsigned32 _ISR_Nest_level; * interrupt service routines are vectored by the ISR Handler via this table. */ -EXTERN ISR_Handler_entry _ISR_Vector_table[CPU_INTERRUPT_NUMBER_OF_VECTORS]; +EXTERN ISR_Handler_entry _ISR_Vector_table[ ISR_NUMBER_OF_VECTORS ]; /* * _ISR_Handler_initialization diff --git a/cpukit/score/include/rtems/score/priority.h b/cpukit/score/include/rtems/score/priority.h index 6639d56e0a..a4a96045d5 100644 --- a/cpukit/score/include/rtems/score/priority.h +++ b/cpukit/score/include/rtems/score/priority.h @@ -113,6 +113,51 @@ STATIC INLINE unsigned32 _Priority_Minor ( Priority_Control the_priority ); +/* + * _Priority_Mask + * + * DESCRIPTION: + * + * This function returns the mask associated with the major or minor + * number passed to it. + */ + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +STATIC INLINE unsigned32 _Priority_Mask ( + unsigned32 bit_number +); + +#else + +#define _Priority_Mask( _bit_number ) \ + _CPU_Priority_Mask( _bit_number ) + +#endif + +/* + * _Priority_Bits_index + * + * DESCRIPTION: + * + * This function translates the bit numbers returned by the bit scan + * of a priority bit field into something suitable for use as + * a major or minor component of a priority. + */ + +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +STATIC INLINE unsigned32 _Priority_Bits_index ( + unsigned32 bit_number +); + +#else + +#define _Priority_Bits_index( _priority ) \ + _CPU_Priority_bits_index( _priority ) + +#endif + /* * _Priority_Add_to_bit_map * diff --git a/cpukit/score/inline/rtems/score/isr.inl b/cpukit/score/inline/rtems/score/isr.inl index 222fcadb17..2b4969a5db 100644 --- a/cpukit/score/inline/rtems/score/isr.inl +++ b/cpukit/score/inline/rtems/score/isr.inl @@ -38,7 +38,7 @@ STATIC INLINE boolean _ISR_Is_vector_number_valid ( unsigned32 vector ) { - return ( vector < CPU_INTERRUPT_NUMBER_OF_VECTORS ); + return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER ); } /*PAGE diff --git a/cpukit/score/inline/rtems/score/priority.inl b/cpukit/score/inline/rtems/score/priority.inl index 64a6c1cf66..413e3b6724 100644 --- a/cpukit/score/inline/rtems/score/priority.inl +++ b/cpukit/score/inline/rtems/score/priority.inl @@ -78,6 +78,37 @@ STATIC INLINE unsigned32 _Priority_Minor ( return ( the_priority % 16 ); } +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +/*PAGE + * + * _Priority_Mask + * + */ + +STATIC INLINE unsigned32 _Priority_Mask ( + unsigned32 bit_number +) +{ + return (0x8000 >> bit_number); +} + + +/*PAGE + * + * _Priority_Bits_index + * + */ + +STATIC INLINE unsigned32 _Priority_Bits_index ( + unsigned32 bit_number +) +{ + return bit_number; +} + +#endif + /*PAGE * * _Priority_Add_to_bit_map @@ -121,8 +152,8 @@ STATIC INLINE Priority_Control _Priority_Get_highest( void ) _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); - return (_CPU_Priority_Bits_index( major ) << 4) + - _CPU_Priority_Bits_index( minor ); + return (_Priority_Bits_index( major ) << 4) + + _Priority_Bits_index( minor ); } /*PAGE @@ -144,13 +175,13 @@ STATIC INLINE void _Priority_Initialize_information( minor = _Priority_Minor( new_priority ); the_priority_map->minor = - &_Priority_Bit_map[ _CPU_Priority_Bits_index(major) ]; + &_Priority_Bit_map[ _Priority_Bits_index(major) ]; - mask = _CPU_Priority_Mask( major ); + mask = _Priority_Mask( major ); the_priority_map->ready_major = mask; the_priority_map->block_major = ~mask; - mask = _CPU_Priority_Mask( minor ); + mask = _Priority_Mask( minor ); the_priority_map->ready_minor = mask; the_priority_map->block_minor = ~mask; } diff --git a/cpukit/score/macros/rtems/score/isr.inl b/cpukit/score/macros/rtems/score/isr.inl index 975487c98b..95f0319396 100644 --- a/cpukit/score/macros/rtems/score/isr.inl +++ b/cpukit/score/macros/rtems/score/isr.inl @@ -33,7 +33,7 @@ */ #define _ISR_Is_vector_number_valid( _vector ) \ - ( (_vector) < CPU_INTERRUPT_NUMBER_OF_VECTORS ) + ( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER ) /*PAGE * diff --git a/cpukit/score/macros/rtems/score/priority.inl b/cpukit/score/macros/rtems/score/priority.inl index 3db8aee4fa..4c5d32b3b3 100644 --- a/cpukit/score/macros/rtems/score/priority.inl +++ b/cpukit/score/macros/rtems/score/priority.inl @@ -64,6 +64,28 @@ #define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 ) +#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE ) + +/*PAGE + * + * _Priority_Mask + * + */ + +#define _Priority_Mask( _bit_number ) \ + (0x8000 >> _bit_number) + +/*PAGE + * + * _Priority_Bits_index + * + */ + +#define _Priority_Bits_index( _bit_number ) \ + (_bit_number) + +#endif + /*PAGE * * _Priority_Add_to_bit_map @@ -103,8 +125,8 @@ _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \ _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \ \ - (_high_priority) = (_CPU_Priority_Bits_index( major ) * 16) + \ - _CPU_Priority_Bits_index( minor ); \ + (_high_priority) = (_Priority_Bits_index( major ) * 16) + \ + _Priority_Bits_index( minor ); \ } /*PAGE @@ -124,13 +146,13 @@ _minor = _Priority_Minor( (_new_priority) ); \ \ (_the_priority_map)->minor = \ - &_Priority_Bit_map[ _CPU_Priority_Bits_index(_major) ]; \ + &_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \ \ - _mask = _CPU_Priority_Mask( _major ); \ + _mask = _Priority_Mask( _major ); \ (_the_priority_map)->ready_major = _mask; \ (_the_priority_map)->block_major = ~_mask; \ \ - _mask = _CPU_Priority_Mask( _minor ); \ + _mask = _Priority_Mask( _minor ); \ (_the_priority_map)->ready_minor = _mask; \ (_the_priority_map)->block_minor = ~_mask; \ } diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c index d384b75788..b44da17c67 100644 --- a/cpukit/score/src/thread.c +++ b/cpukit/score/src/thread.c @@ -805,9 +805,12 @@ void _Thread_Load_environment( Thread_Control *the_thread ) { + boolean is_fp = FALSE; + if ( the_thread->Start.fp_context ) { the_thread->fp_context = the_thread->Start.fp_context; _Context_Initialize_fp( &the_thread->fp_context ); + is_fp = TRUE; } the_thread->is_preemptible = the_thread->Start.is_preemptible; @@ -818,7 +821,8 @@ void _Thread_Load_environment( the_thread->Start.Initial_stack.area, the_thread->Start.Initial_stack.size, the_thread->Start.isr_level, - _Thread_Handler + _Thread_Handler, + is_fp ); } diff --git a/testsuites/sptests/sp04/task1.c b/testsuites/sptests/sp04/task1.c index 117f5eaa80..671ae5483d 100644 --- a/testsuites/sptests/sp04/task1.c +++ b/testsuites/sptests/sp04/task1.c @@ -30,8 +30,8 @@ rtems_task Task_1( rtems_mode previous_mode; rtems_time_of_day time; rtems_status_code status; - rtems_unsigned32 start; - rtems_unsigned32 end; + rtems_unsigned32 start_time; + rtems_unsigned32 end_time; puts( "TA1 - rtems_task_suspend - on Task 2" ); status = rtems_task_suspend( Task_id[ 2 ] ); @@ -41,16 +41,16 @@ rtems_task Task_1( status = rtems_task_suspend( Task_id[ 3 ] ); directive_failed( status, "rtems_task_suspend of TA3" ); - status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &start ); + status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &start_time ); directive_failed( status, "rtems_clock_get" ); puts( "TA1 - killing time" ); for ( ; ; ) { - status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &end ); + status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &end_time ); directive_failed( status, "rtems_clock_get" ); - if ( end > (start + 2) ) + if ( end_time > (start_time + 2) ) break; } diff --git a/testsuites/sptests/sp09/screen09.c b/testsuites/sptests/sp09/screen09.c index 5c6eece679..c6fd1d3d72 100644 --- a/testsuites/sptests/sp09/screen09.c +++ b/testsuites/sptests/sp09/screen09.c @@ -25,7 +25,11 @@ void Screen9() rtems_status_code status; rtems_isr_entry old_service_routine; - status = rtems_interrupt_catch( Service_routine, 500, &old_service_routine ); + status = rtems_interrupt_catch( + Service_routine, + ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER + 10, + &old_service_routine + ); fatal_directive_status( status, RTEMS_INVALID_NUMBER, diff --git a/testsuites/sptests/sp11/sp11.scn b/testsuites/sptests/sp11/sp11.scn index 7abb8afe45..f34a9eac5f 100644 --- a/testsuites/sptests/sp11/sp11.scn +++ b/testsuites/sptests/sp11/sp11.scn @@ -11,7 +11,7 @@ TA1 - rtems_event_receive - waiting with 10 second timeout on RTEMS_EVENT_14 TA2 - RTEMS_EVENT_17 or RTEMS_EVENT_18 received - eventout => 00040000 TA2 - rtems_event_send - send RTEMS_EVENT_14 to TA1 TA2 - rtems_clock_set - 08:15:00 02/12/1988 -TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 5 seconds +TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 4 seconds TA2 - rtems_event_receive - waiting forever on RTEMS_EVENT_10 TA1 - RTEMS_EVENT_14 received - eventout => 00004000 TA1 - rtems_event_send - send RTEMS_EVENT_19 to TA2 diff --git a/testsuites/sptests/sp11/task2.c b/testsuites/sptests/sp11/task2.c index 176582bc36..d5ac476dac 100644 --- a/testsuites/sptests/sp11/task2.c +++ b/testsuites/sptests/sp11/task2.c @@ -73,9 +73,9 @@ rtems_task Task_2( status = rtems_clock_set( &time ); directive_failed( status, "TA2 rtems_clock_set" ); - time.second += 5; + time.second += 4; puts( - "TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 5 seconds" + "TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 4 seconds" ); status = rtems_timer_fire_when( Timer_id[ 5 ], @@ -83,7 +83,7 @@ rtems_task Task_2( TA2_send_10_to_self, NULL ); - directive_failed( status, "rtems_timer_fire_when after 5 seconds" ); + directive_failed( status, "rtems_timer_fire_when after 4 seconds" ); puts( "TA2 - rtems_event_receive - waiting forever on RTEMS_EVENT_10" ); status = rtems_event_receive( diff --git a/testsuites/sptests/sp12/system.h b/testsuites/sptests/sp12/system.h index 3c126963b6..81af1abbd9 100644 --- a/testsuites/sptests/sp12/system.h +++ b/testsuites/sptests/sp12/system.h @@ -57,6 +57,7 @@ rtems_task Task5( #define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER #define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER +#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2) #define CONFIGURE_MAXIMUM_SEMAPHORES 10 #define CONFIGURE_TICKS_PER_TIMESLICE 100 diff --git a/testsuites/sptests/sp19/system.h b/testsuites/sptests/sp19/system.h index 557299b9c2..6052075250 100644 --- a/testsuites/sptests/sp19/system.h +++ b/testsuites/sptests/sp19/system.h @@ -38,6 +38,8 @@ rtems_task Task_1( #define CONFIGURE_SPTEST +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + #define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER #define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER diff --git a/testsuites/sptests/sp20/init.c b/testsuites/sptests/sp20/init.c index 0e1b56ba3a..d2bc2ec00d 100644 --- a/testsuites/sptests/sp20/init.c +++ b/testsuites/sptests/sp20/init.c @@ -44,7 +44,7 @@ rtems_task Init( status = rtems_task_create( Task_name[ index ], Priorities[ index ], - RTEMS_MINIMUM_STACK_SIZE, + RTEMS_MINIMUM_STACK_SIZE * 4, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ index ] diff --git a/testsuites/sptests/sp24/init.c b/testsuites/sptests/sp24/init.c index 81abc0277a..74114ab82a 100644 --- a/testsuites/sptests/sp24/init.c +++ b/testsuites/sptests/sp24/init.c @@ -52,7 +52,7 @@ rtems_task Init( status = rtems_task_create( Task_name[ index ], 1, - RTEMS_MINIMUM_STACK_SIZE, + RTEMS_MINIMUM_STACK_SIZE * 2, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ index ] diff --git a/testsuites/sptests/spsize/init.c b/testsuites/sptests/spsize/init.c index 66e40cd0f1..d0d5490966 100644 --- a/testsuites/sptests/spsize/init.c +++ b/testsuites/sptests/spsize/init.c @@ -36,8 +36,12 @@ rtems_task Init( setvbuf(stdout, 0, _IONBF, 0); + puts( "\n*** RTEMS SIZE PROGRAM ***" ); + size_rtems( 1 ); + puts( "*** END OF RTEMS SIZE PROGRAM ***" ); + exit( 0 ); +#if 0 do { - puts( "\n*** RTEMS SIZE PROGRAM ***" ); printf( "\n\nPlease select program mode:\n" ); printf( " 1) Print Formulas\n" ); printf( " 2) Determine Workspace Size\n" ); @@ -52,4 +56,5 @@ rtems_task Init( default: continue; } } while ( FOREVER ); +#endif } diff --git a/testsuites/sptests/spsize/size.c b/testsuites/sptests/spsize/size.c index 474095972a..91ccbfb1a3 100644 --- a/testsuites/sptests/spsize/size.c +++ b/testsuites/sptests/spsize/size.c @@ -390,6 +390,22 @@ uninitialized += (sizeof _CPU_Interrupt_stack_low) + #endif +#ifdef sparc + +/* cpu.h */ +uninitialized += (sizeof _CPU_Interrupt_stack_low) + + (sizeof _CPU_Interrupt_stack_high) + + (sizeof _CPU_Null_fp_context) + + (sizeof _CPU_Trap_Table_area); + +#ifdef erc32 +uninitialized += (sizeof _ERC32_MEC_Timer_Control_Mirror); +#endif + + +#endif + + #ifdef no_cpu /* cpu.h */ @@ -421,13 +437,16 @@ initialized += (sizeof _TOD_Days_to_date) + (sizeof _TOD_Days_since_last_leap_year); +#ifdef sparc + +initialized += (sizeof _CPU_Trap_slot_template); + +#endif + puts( "" ); -#ifdef i960CA - print_formula(); -#else + if ( mode == 0 ) help_size(); else print_formula(); -#endif printf( "\n" ); printf( "RTEMS uninitialized data consumes %d bytes\n", uninitialized ); diff --git a/testsuites/tmtests/tm08/task1.c b/testsuites/tmtests/tm08/task1.c index 1a03329f26..b29d6c6206 100644 --- a/testsuites/tmtests/tm08/task1.c +++ b/testsuites/tmtests/tm08/task1.c @@ -198,7 +198,7 @@ rtems_task test_task( end_time = Read_timer(); put_time( - "rtems_task_set_note", + "rtems_task_get_note", end_time, OPERATION_COUNT, overhead, diff --git a/testsuites/tmtests/tm27/task1.c b/testsuites/tmtests/tm27/task1.c index c18ae2ab9b..a47e434200 100644 --- a/testsuites/tmtests/tm27/task1.c +++ b/testsuites/tmtests/tm27/task1.c @@ -11,6 +11,12 @@ * $Id$ */ +/* + * WARNING!!!!!!!!! + * + * THIS TEST USES INTERNAL RTEMS VARIABLES!!! + */ + #define TEST_INIT #include "system.h" @@ -33,15 +39,6 @@ rtems_isr Isr_handler( rtems_vector_number vector ); -/* - * INTERNAL RTEMS VARIABLES!!! - */ - -extern rtems_unsigned32 _Thread_Dispatch_disable_level; -extern rtems_unsigned32 _Context_Switch_necessary; -extern Chain_Control *_Thread_Ready_chain; -extern rtems_tcb *_Thread_Heir; - rtems_task Init( rtems_task_argument argument ) @@ -169,9 +166,23 @@ rtems_task Task_1( Interrupt_occurred = 0; Timer_initialize(); Cause_tm27_intr(); - /* goes to Isr_handler */ + + /* + * goes to Isr_handler and then returns + */ + + puts( "*** END OF TEST 27 ***" ); + exit( 0 ); } +/* + * NOTE: When this task is executing, some of the assumptions made + * regarding the placement of the currently executing task's TCB + * on the ready chains have been violated. At least the assumption + * that this task is at the head of the chain for its priority + * has been violated. + */ + rtems_task Task_2( rtems_task_argument argument ) @@ -197,8 +208,20 @@ rtems_task Task_2( 0 ); - puts( "*** END OF TEST 27 ***" ); - exit( 0 ); + fflush( stdout ); + + /* + * Switch back to the other task to exit the test. + */ + + _Thread_Dispatch_disable_level = 0; + + _Thread_Heir = (rtems_tcb *) _Thread_Ready_chain[254].first; + + _Context_Switch_necessary = 1; + + _Thread_Dispatch(); + } /* The Isr_handler() and Isr_handler_inner() routines are structured -- cgit v1.2.3