summaryrefslogtreecommitdiffstats
path: root/c/src
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1995-10-30 21:54:45 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1995-10-30 21:54:45 +0000
commit97005786d89fd7a57b5fe82f713cea739916f3da (patch)
treecfff15a6bc93114480ecd20f6afddde3dcd74470 /c/src
parentreordered test cases from simple to complex (diff)
downloadrtems-97005786d89fd7a57b5fe82f713cea739916f3da.tar.bz2
SPARC port passes all tests
Diffstat (limited to 'c/src')
-rw-r--r--c/src/exec/libcsupport/include/ringbuf.h25
-rw-r--r--c/src/exec/posix/headers/intr.h3
-rw-r--r--c/src/exec/posix/include/rtems/posix/intr.h3
-rw-r--r--c/src/exec/rtems/src/event.c202
-rw-r--r--c/src/exec/score/cpu/hppa1.1/cpu.h10
-rw-r--r--c/src/exec/score/cpu/i386/cpu.h10
-rw-r--r--c/src/exec/score/cpu/i960/cpu.h10
-rw-r--r--c/src/exec/score/cpu/m68k/cpu.h12
-rw-r--r--c/src/exec/score/cpu/m68k/cpu_asm.s3
-rw-r--r--c/src/exec/score/cpu/no_cpu/cpu.h26
-rw-r--r--c/src/exec/score/cpu/powerpc/cpu.h14
-rw-r--r--c/src/exec/score/cpu/sparc/README118
-rw-r--r--c/src/exec/score/cpu/sparc/asm.h16
-rw-r--r--c/src/exec/score/cpu/sparc/cpu.c370
-rw-r--r--c/src/exec/score/cpu/sparc/cpu.h674
-rw-r--r--c/src/exec/score/cpu/sparc/cpu_asm.s881
-rw-r--r--c/src/exec/score/cpu/sparc/erc32.h503
-rw-r--r--c/src/exec/score/cpu/sparc/rtems.s16
-rw-r--r--c/src/exec/score/cpu/sparc/sparc.h150
-rw-r--r--c/src/exec/score/cpu/sparc/sparctypes.h26
-rw-r--r--c/src/exec/score/cpu/unix/cpu.c52
-rw-r--r--c/src/exec/score/cpu/unix/cpu.h49
-rw-r--r--c/src/exec/score/headers/bitfield.h49
-rw-r--r--c/src/exec/score/headers/context.h5
-rw-r--r--c/src/exec/score/headers/isr.h15
-rw-r--r--c/src/exec/score/headers/priority.h45
-rw-r--r--c/src/exec/score/include/rtems/score/bitfield.h49
-rw-r--r--c/src/exec/score/include/rtems/score/context.h5
-rw-r--r--c/src/exec/score/include/rtems/score/isr.h15
-rw-r--r--c/src/exec/score/include/rtems/score/priority.h45
-rw-r--r--c/src/exec/score/inline/isr.inl2
-rw-r--r--c/src/exec/score/inline/priority.inl41
-rw-r--r--c/src/exec/score/inline/rtems/score/isr.inl2
-rw-r--r--c/src/exec/score/inline/rtems/score/priority.inl41
-rw-r--r--c/src/exec/score/macros/isr.inl2
-rw-r--r--c/src/exec/score/macros/priority.inl32
-rw-r--r--c/src/exec/score/macros/rtems/score/isr.inl2
-rw-r--r--c/src/exec/score/macros/rtems/score/priority.inl32
-rw-r--r--c/src/exec/score/src/thread.c6
-rw-r--r--c/src/lib/include/ringbuf.h25
-rw-r--r--c/src/lib/libbsp/hppa1.1/simhppa/startup/bspstart.c31
-rw-r--r--c/src/lib/libbsp/i386/force386/clock/ckinit.c16
-rw-r--r--c/src/lib/libbsp/i386/force386/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/i386/go32/clock/ckinit.c16
-rw-r--r--c/src/lib/libbsp/i386/go32/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/i960/cvme961/clock/ckinit.c12
-rw-r--r--c/src/lib/libbsp/i960/cvme961/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/m68k/dmv152/clock/ckinit.c16
-rw-r--r--c/src/lib/libbsp/m68k/dmv152/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/m68k/efi332/clock/ckinit.c16
-rw-r--r--c/src/lib/libbsp/m68k/efi332/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/m68k/efi68k/clock/ckinit.c16
-rw-r--r--c/src/lib/libbsp/m68k/efi68k/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/m68k/gen68302/clock/ckinit.c18
-rw-r--r--c/src/lib/libbsp/m68k/gen68302/start/start302.s9
-rw-r--r--c/src/lib/libbsp/m68k/gen68302/start302/start302.s9
-rw-r--r--c/src/lib/libbsp/m68k/gen68302/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/m68k/idp/clock/ckinit.c15
-rw-r--r--c/src/lib/libbsp/m68k/idp/console/duart.c6
-rw-r--r--c/src/lib/libbsp/m68k/idp/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/m68k/mvme136/clock/ckinit.c16
-rw-r--r--c/src/lib/libbsp/m68k/mvme136/startup/bspstart.c13
-rw-r--r--c/src/lib/libbsp/m68k/mvme162/clock/ckinit.c14
-rw-r--r--c/src/lib/libbsp/m68k/mvme162/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/no_cpu/no_bsp/clock/ckinit.c31
-rw-r--r--c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/powerpc/papyrus/startup/bspstart.c11
-rw-r--r--c/src/lib/libbsp/unix/posix/clock/clock.c31
-rw-r--r--c/src/lib/libbsp/unix/posix/startup/bspstart.c11
-rw-r--r--c/src/lib/libcpu/sparc/include/erc32.h503
-rw-r--r--c/src/tests/sptests/sp04/task1.c10
-rw-r--r--c/src/tests/sptests/sp09/screen09.c6
-rw-r--r--c/src/tests/sptests/sp11/sp11.scn2
-rw-r--r--c/src/tests/sptests/sp11/task2.c6
-rw-r--r--c/src/tests/sptests/sp12/system.h1
-rw-r--r--c/src/tests/sptests/sp19/system.h2
-rw-r--r--c/src/tests/sptests/sp20/init.c2
-rw-r--r--c/src/tests/sptests/sp24/init.c2
-rw-r--r--c/src/tests/sptests/spsize/init.c7
-rw-r--r--c/src/tests/sptests/spsize/size.c27
-rw-r--r--c/src/tests/tmtests/tm08/task1.c2
-rw-r--r--c/src/tests/tmtests/tm27/task1.c47
82 files changed, 3446 insertions, 1174 deletions
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 <rtems/score/sparc.h>
+#include <rtems/score/cpu.h>
/*
* 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 <rtems/system.h>
#include <rtems/score/isr.h>
-/* _CPU_Initialize
+#if defined(erc32)
+#include <erc32.h>
+#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 <asm.h>
#include <rtems/score/cpu.h>
+#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 <rtems/score/sparc.h>
+
+#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
@@ -74,6 +83,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
@@ -114,6 +114,51 @@ STATIC INLINE unsigned32 _Priority_Minor (
);
/*
+ * _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
*
* DESCRIPTION:
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
@@ -114,6 +114,51 @@ STATIC INLINE unsigned32 _Priority_Minor (
);
/*
+ * _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
*
* DESCRIPTION:
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 <rtems.h>
#include <bsp.h>
#include <rtems/libio.h>
-#include <rtems/score/intthrd.h>
+#include <rtems/intthrd.h>
#include <libcsupport.h>
@@ -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
*/
@@ -121,30 +121,6 @@ void Install_clock(
}
/*
- * 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 <rtems/score/sparc.h>
+
+#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