Initial revision

This commit is contained in:
Joel Sherrill
1995-05-11 17:39:37 +00:00
commit ac7d5ef06a
1683 changed files with 189788 additions and 0 deletions

14
c/src/lib/libcpu/README Normal file
View File

@@ -0,0 +1,14 @@
#
# $Id$
#
This is the README file for libcpu.
This directory contains reusable libraries which are CPU dependent but not
target board dependent. For example, the HPPA has an on chip interval timer
which may be used by all HPPA bsp's.
Another example might be the Intel i960CA has on-chip DMA which could be
supported in a library and placed in lib/libcpu/i960. This level of support
will make it easier for others developing embedded applications on a given
CPU.

View File

@@ -0,0 +1,220 @@
/* Clock
*
* This routine initializes the interval timer on the
* PA-RISC CPU. The tick frequency is specified by the bsp.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
* All rights assigned to U.S. Government, 1994.
*
* This material may be reproduced by or for the U.S. Government pursuant
* to the copyright license under the clause at DFARS 252.227-7013. This
* notice must appear in all copies of this file and its derivatives.
*
* $Id$
*/
#include <bsp.h>
#include <clockdrv.h>
#include <stdlib.h> /* for atexit() */
extern rtems_cpu_table Cpu_table; /* owned by BSP */
typedef unsigned long long hppa_click_count_t;
/*
* CPU_HPPA_CLICKS_PER_TICK is either a #define or an rtems_unsigned32
* allocated and set by bsp_start()
*/
#ifndef CPU_HPPA_CLICKS_PER_TICK
extern rtems_unsigned32 CPU_HPPA_CLICKS_PER_TICK;
#endif
volatile rtems_unsigned32 Clock_driver_ticks;
rtems_unsigned32 Clock_isrs; /* ISRs until next tick */
rtems_unsigned32 most_recent_itimer_value;
rtems_unsigned64 Clock_clicks; /* running total of cycles */
rtems_unsigned32 Clock_clicks_interrupt;
rtems_device_driver Clock_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp,
rtems_id tid,
rtems_unsigned32 *rval
)
{
Install_clock(Clock_isr);
}
void
ReInstall_clock(rtems_isr_entry new_clock_isr)
{
rtems_unsigned32 isrlevel = 0;
rtems_interrupt_disable(isrlevel);
(void) set_vector(
new_clock_isr,
HPPA_INTERRUPT_EXTERNAL_INTERVAL_TIMER,
1
);
rtems_interrupt_enable(isrlevel);
}
/*
* read itimer and update Clock_clicks as appropriate
*/
rtems_unsigned32
Clock_read_itimer()
{
rtems_unsigned32 isrlevel;
rtems_unsigned32 itimer_value;
rtems_unsigned32 wrap_count;
rtems_unsigned32 recent_count;
rtems_interrupt_disable(isrlevel);
wrap_count = (Clock_clicks & 0xFFFFFFFF00000000ULL) >> 32;
recent_count = (rtems_unsigned32) Clock_clicks;
itimer_value = get_itimer();
if (itimer_value < recent_count)
wrap_count++;
Clock_clicks = (((rtems_unsigned64) wrap_count) << 32) + itimer_value;
rtems_interrupt_enable(isrlevel);
return itimer_value;
}
void Install_clock(rtems_isr_entry clock_isr)
{
Clock_driver_ticks = 0;
Clock_clicks_interrupt = 0;
Clock_clicks = 0;
Clock_isrs = BSP_Configuration.microseconds_per_tick / 1000;
if (BSP_Configuration.ticks_per_timeslice)
{
/*
* initialize the interval here
* First tick is set to right amount of time in the future
* Future ticks will be incremented over last value set
* in order to provide consistent clicks in the face of
* interrupt overhead
*/
Clock_clicks_interrupt = Clock_read_itimer() + CPU_HPPA_CLICKS_PER_TICK;
set_itimer((rtems_unsigned32) Clock_clicks_interrupt);
(void) set_vector(clock_isr, HPPA_INTERRUPT_EXTERNAL_INTERVAL_TIMER, 1);
}
atexit(Clock_exit);
}
rtems_isr
Clock_isr(rtems_vector_number vector)
{
rtems_unsigned32 clicks_til_next_interrupt;
rtems_unsigned32 itimer_value;
/*
* setup for next interrupt; making sure the new value is reasonably
* in the future.... in case we lost out on an interrupt somehow
*/
itimer_value = Clock_read_itimer();
Clock_clicks_interrupt += CPU_HPPA_CLICKS_PER_TICK;
/*
* how far away is next interrupt *really*
* It may be a long time; this subtraction works even if
* Clock_clicks_interrupt < Clock_clicks_low_order via
* the miracle of unsigned math.
*/
clicks_til_next_interrupt = Clock_clicks_interrupt - itimer_value;
/*
* If it is too soon then bump it up.
* This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small.
* But setting it low is useful for debug, so...
*/
if (clicks_til_next_interrupt < 400)
{
Clock_clicks_interrupt = itimer_value + 1000;
/* XXX: count these! this should be rare */
}
/*
* If it is too late, that means we missed the interrupt somehow.
* Rather than wait 35-50s for a wrap, we just fudge it here.
*/
if (clicks_til_next_interrupt > CPU_HPPA_CLICKS_PER_TICK)
{
Clock_clicks_interrupt = itimer_value + 1000;
/* XXX: count these! this should never happen :-) */
}
set_itimer((rtems_unsigned32) Clock_clicks_interrupt);
Clock_driver_ticks++;
if (Clock_isrs == 1)
{
rtems_clock_tick();
Clock_isrs = BSP_Configuration.microseconds_per_tick / 10000;
if (Clock_isrs == 0)
Clock_isrs = 1;
}
else
Clock_isrs--;
}
/*
* Called via atexit()
* Remove the clock interrupt handler by setting handler to NULL
*/
void
Clock_exit(void)
{
if ( BSP_Configuration.ticks_per_timeslice )
{
(void) set_vector(0, HPPA_INTERRUPT_EXTERNAL_INTERVAL_TIMER, 1);
}
}
/*
* spin delay for specified number of microseconds
* used by RTEMS delay macro
*/
void
Clock_delay(rtems_unsigned32 microseconds)
{
rtems_unsigned64 future_time;
(void) Clock_read_itimer();
future_time = Clock_clicks +
((rtems_unsigned64) microseconds) *
Cpu_table.itimer_clicks_per_microsecond;
for (;;)
{
(void) Clock_read_itimer();
if (future_time <= Clock_clicks)
break;
}
}

View File

@@ -0,0 +1,37 @@
/*
* File: $RCSfile$
* Project: PixelFlow
* Created: 94/11/29
* RespEngr: tony bennett
* Revision: $Revision$
* Last Mod: $Date$
*
* Description:
* definitions specific to the runway bus
*
* TODO:
* Add lots more.
*
* $Id$
*/
#ifndef _INCLUDE_RUNWAY_H
#define _INCLUDE_RUNWAY_H
#ifdef __cplusplus
extern "C" {
#endif
#define HPPA_RUNWAY_PROC_HPA_BASE ((void *) 0xFFFA0000)
/* given a processor number, where is its HPA? */
#define HPPA_RUNWAY_HPA(cpu) \
((rtems_unsigned32) (HPPA_RUNWAY_PROC_HPA_BASE + ((cpu) * 0x2000)))
#define HPPA_RUNWAY_REG_IO_EIR_OFFSET 0x000
#ifdef __cplusplus
}
#endif
#endif /* ! _INCLUDE_RUNWAY_H */

View File

@@ -0,0 +1,308 @@
/*
* File: $RCSfile$
* Project: PixelFlow
* Created: 94/11/29
* RespEngr: tony bennett
* Revision: $Revision$
* Last Mod: $Date$
*
* COPYRIGHT (c) 1994 by Division Incorporated
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of Division Incorporated not be
* used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission.
* Division Incorporated makes no representations about the
* suitability of this software for any purpose.
*
* Description:
* HPPA fast spinlock semaphores based on LDCWX instruction.
* These semaphores are not known to RTEMS.
*
* TODO:
* Put node number in high 16 bits of flag??
* XXX: Need h_s_deallocate
*
* $Id$
*/
#include <bsp.h>
#include "semaphore.h"
/*
* Report fatal semaphore error
*/
#define SEM_FATAL_ERROR(sp) rtems_fatal_error_occurred((rtems_unsigned32) sp)
#define SEM_CHECK(sp) do { \
if (((sp) == 0) || (int) (sp) & 0xf) \
{ \
SEM_FATAL_ERROR(sp); \
} \
} while (0)
/*
* Init a semaphore to be free
*/
#define SEM_FREE_INIT(sp) \
do { \
(sp)->lock = 1; \
(sp)->flags = 0; \
(sp)->owner_tcb = 0; \
} while (0)
/*
* Grab a semaphore recording its owner.
*/
#define SEM_MARK_GRABBED(sp) \
do { \
(sp)->owner_tcb = _Thread_Executing; \
} while (0)
/*
* Mark the semaphore busy
*/
#define SEM_MARK_BUSY(sp) ((sp)->flags |= HPPA_SEM_IN_USE)
/*
* Is a semaphore available?
*/
#define SEM_IS_AVAILABLE(sp) ((sp)->owner_tcb == 0)
/*
* The pool control semaphore is the first in the pool
*/
#define SEM_CONTROL (&hppa_semaphore_pool[0])
#define SEM_FIRST (&hppa_semaphore_pool[1])
#define SEM_PRIVATE(cookie) rtems_interrupt_disable(cookie)
#define SEM_PUBLIC(cookie) rtems_interrupt_enable(cookie)
/*
* Control variables for the pool
*/
hppa_semaphore_t *hppa_semaphore_pool; /* ptr to first */
int hppa_semaphores;
int hppa_semaphores_available;
void
hppa_semaphore_pool_initialize(void *pool_base,
int pool_size)
{
hppa_semaphore_t *sp;
int align_factor;
rtems_unsigned32 isr_level;
/*
* round pool_base up to be a multiple of SEM_ALIGN
*/
align_factor = SEM_ALIGN - (((int) pool_base) & (SEM_ALIGN-1));
if (align_factor != SEM_ALIGN)
{
pool_base += align_factor;
pool_size -= align_factor;
}
/*
* How many can the pool hold?
* Assumes the semaphores are SEM_ALIGN bytes each
*/
if (sizeof(hppa_semaphore_t) != SEM_ALIGN)
rtems_fatal_error_occurred(RTEMS_INVALID_SIZE);
pool_size &= ~(SEM_ALIGN - 1);
SEM_PRIVATE(isr_level);
hppa_semaphore_pool = pool_base;
hppa_semaphores = pool_size / SEM_ALIGN;
/*
* If we are node0, then init all in the pool
*/
if (cpu_number == 0)
{
/*
* Tell other cpus we are not done, jic
*/
SEM_CONTROL->user = rtems_build_name('!', 'D', 'N', 'E');
for (sp=SEM_FIRST; sp < &hppa_semaphore_pool[hppa_semaphores]; sp++)
SEM_FREE_INIT(sp);
SEM_FREE_INIT(SEM_CONTROL);
}
/*
* Tell other cpus we are done, or wait for it to be done if on another cpu
*/
if (cpu_number == 0)
SEM_CONTROL->user = rtems_build_name('D', 'O', 'N', 'E');
else
while (SEM_CONTROL->user != rtems_build_name('D', 'O', 'N', 'E'))
;
hppa_semaphores_available = hppa_semaphores;
SEM_PUBLIC(isr_level);
}
/*
* Function: hppa_semaphore_acquire
* Created: 94/11/29
* RespEngr: tony bennett
*
* Description:
* Acquire a semaphore. Will spin on the semaphore unless
* 'flag' says not to.
*
* Parameters:
*
*
* Returns:
* 0 -- if did not acquire
* non-zero -- if acquired semaphore
* (actually this is the spin count)
*
* Notes:
* There is no requirement that the semaphore be within the pool
*
* Deficiencies/ToDo:
*
*/
rtems_unsigned32
hppa_semaphore_acquire(hppa_semaphore_t *sp,
int flag)
{
rtems_unsigned32 lock_value;
rtems_unsigned32 spin_count = 1;
SEM_CHECK(sp);
for (;;)
{
HPPA_ASM_LDCWS(0, 0, sp, lock_value);
if (lock_value) /* we now own the lock */
{
SEM_MARK_GRABBED(sp);
return spin_count ? spin_count : ~0; /* jic */
}
if (flag & HPPA_SEM_NO_SPIN)
return 0;
spin_count++;
}
}
void
hppa_semaphore_release(hppa_semaphore_t *sp)
{
SEM_CHECK(sp);
if (sp->owner_tcb != _Thread_Executing)
SEM_FATAL_ERROR("owner mismatch");
sp->lock = 1;
}
/*
* Function: hppa_semaphore_allocate
* Created: 94/11/29
* RespEngr: tony bennett
*
* Description:
* Get a pointer to a semaphore.
*
* Parameters:
* which -- if 0, then allocate a free semaphore from the pool
* if non-zero, then return pointer to that one, even
* if it is already busy.
*
* Returns:
* successful -- pointer to semaphore
* NULL otherwise
*
* Notes:
*
*
* Deficiencies/ToDo:
*
*
*/
hppa_semaphore_t *
hppa_semaphore_allocate(rtems_unsigned32 which,
int flag)
{
hppa_semaphore_t *sp = 0;
/*
* grab the control semaphore
*/
if (hppa_semaphore_acquire(SEM_CONTROL, 0) == 0)
SEM_FATAL_ERROR("could not grab control semaphore");
/*
* Find a free one and init it
*/
if (which)
{
if (which >= hppa_semaphores)
SEM_FATAL_ERROR("requested non-existent semaphore");
sp = &hppa_semaphore_pool[which];
/*
* if it is "free", then mark it claimed now.
* If it is not free then we are done.
*/
if (SEM_IS_AVAILABLE(sp))
goto allmine;
}
else for (sp = SEM_FIRST;
sp < &hppa_semaphore_pool[hppa_semaphores];
sp++)
{
if (SEM_IS_AVAILABLE(sp))
{
allmine: SEM_FREE_INIT(sp);
SEM_MARK_BUSY(sp);
if ( ! (flag & HPPA_SEM_INITIALLY_FREE))
SEM_MARK_GRABBED(sp);
break;
}
}
/*
* Free up the control semaphore
*/
hppa_semaphore_release(SEM_CONTROL);
return sp;
}

View File

@@ -0,0 +1,84 @@
/*
* File: $RCSfile$
* Project: PixelFlow
* Created: 94/11/29
* RespEngr: tony e bennett
* Revision: $Revision$
* Last Mod: $Date$
*
* COPYRIGHT (c) 1994 by Division Incorporated
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of Division Incorporated not be
* used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission.
* Division Incorporated makes no representations about the
* suitability of this software for any purpose.
*
* Description:
* HPPA fast spinlock semaphores based on LDCWX instruction.
* These semaphores are not known to RTEMS.
*
* TODO:
*
* $Id$
*/
#ifndef _INCLUDE_SEMAPHORE_H
#define _INCLUDE_SEMAPHORE_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* This structure has hardware requirements.
* LDCWX opcode requires 16byte alignment for the lock
* 'lock' must be first member of structure.
*/
#define SEM_ALIGN 16
typedef volatile struct {
rtems_unsigned32 lock __attribute__ ((aligned (SEM_ALIGN)));
rtems_unsigned32 flags;
void *owner_tcb; /* for debug/commentary only */
rtems_unsigned32 user; /* for use by user */
} hppa_semaphore_t;
/*
* Values for flags
*/
#define HPPA_SEM_IN_USE 0x0001 /* semaphore owned by somebody */
#define HPPA_SEM_NO_SPIN 0x0002 /* don't spin if unavailable */
#define HPPA_SEM_INITIALLY_FREE 0x0004 /* init it to be free */
/*
* Caller specifiable flags
*/
#define HPPA_SEM_CALLER_FLAGS (HPPA_SEM_NO_SPIN | HPPA_SEM_INITIALLY_FREE)
void hppa_semaphore_pool_initialize(void *pool_base, int pool_size);
rtems_unsigned32 hppa_semaphore_acquire(hppa_semaphore_t *sp, int flag);
void hppa_semaphore_release(hppa_semaphore_t *sp);
hppa_semaphore_t *hppa_semaphore_allocate(rtems_unsigned32 which, int flag);
#ifdef __cplusplus
}
#endif
#endif /* ! _INCLUDE_SEMAPHORE_H */

View File

@@ -0,0 +1,62 @@
/* timer.c
*
* This file manages the interval timer on the PA-RISC.
*
* NOTE: It is important that the timer start/stop overhead be
* determined when porting or modifying this code.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
* All rights assigned to U.S. Government, 1994.
*
* This material may be reproduced by or for the U.S. Government pursuant
* to the copyright license under the clause at DFARS 252.227-7013. This
* notice must appear in all copies of this file and its derivatives.
*
* $Id$
*/
#include <rtems.h>
volatile rtems_unsigned32 Timer_starting;
rtems_boolean Timer_driver_Find_average_overhead;
void Timer_initialize()
{
Timer_starting = get_itimer();
}
#define AVG_OVERHEAD 0 /* It typically takes 3.0 microseconds */
/* (6 countdowns) to start/stop the timer. */
#define LEAST_VALID 1 /* Don't trust a value lower than this */
int Read_timer()
{
rtems_unsigned32 clicks;
rtems_unsigned32 total;
clicks = get_itimer();
total = clicks - Timer_starting;
if ( Timer_driver_Find_average_overhead == 1 )
return total; /* in XXX microsecond units */
else {
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
return (total - AVG_OVERHEAD);
}
}
rtems_status_code Empty_function( void )
{
return RTEMS_SUCCESSFUL;
}
void Set_find_average_overhead(
rtems_boolean find_flag
)
{
Timer_driver_Find_average_overhead = find_flag;
}