mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-21 00:07:36 +08:00
2008-06-09 Ken Werner <ken.werner@de.ibm.com>
* libc/machine/spu/Makefile.am: Add new files. * libc/machine/spu/Makefile.in: Likewise. * libc/machine/spu/include/spu_timer.h: New file to add timer support using interrupts. * libc/machine/spu/spu_clock_stop.c: Likewise. * libc/machine/spu/spu_clock_svcs.c: Likewise. * libc/machine/spu/spu_timer_flih.S: Likewise. * libc/machine/spu/spu_timer_free.c: Likewise. * libc/machine/spu/spu_timer_internal.h: Likewise. * libc/machine/spu/spu_timer_slih.c: Likewise. * libc/machine/spu/spu_timer_slih_reg.c: Likewise. * libc/machine/spu/spu_timer_stop.c: Likewise. * libc/machine/spu/spu_timer_svcs.c: Likewise.
This commit is contained in:
parent
27a07c4596
commit
a0496b5e4f
@ -1,3 +1,19 @@
|
||||
2008-06-09 Ken Werner <ken.werner@de.ibm.com>
|
||||
|
||||
* libc/machine/spu/Makefile.am: Add new files.
|
||||
* libc/machine/spu/Makefile.in: Likewise.
|
||||
* libc/machine/spu/include/spu_timer.h: New file to add timer support
|
||||
using interrupts.
|
||||
* libc/machine/spu/spu_clock_stop.c: Likewise.
|
||||
* libc/machine/spu/spu_clock_svcs.c: Likewise.
|
||||
* libc/machine/spu/spu_timer_flih.S: Likewise.
|
||||
* libc/machine/spu/spu_timer_free.c: Likewise.
|
||||
* libc/machine/spu/spu_timer_internal.h: Likewise.
|
||||
* libc/machine/spu/spu_timer_slih.c: Likewise.
|
||||
* libc/machine/spu/spu_timer_slih_reg.c: Likewise.
|
||||
* libc/machine/spu/spu_timer_stop.c: Likewise.
|
||||
* libc/machine/spu/spu_timer_svcs.c: Likewise.
|
||||
|
||||
2008-06-09 Ken Werner <ken.werner@de.ibm.com>
|
||||
|
||||
* libc/machine/spu/strcat.c: Return value fixed.
|
||||
|
@ -21,7 +21,9 @@ lib_a_SOURCES = setjmp.S assert.c clearerr.c creat.c fclose.c feof.c \
|
||||
tmpnam.c ungetc.c usleep.c vfiprintf.c vfiscanf.c vfprintf.c \
|
||||
vfscanf.c viprintf.c viscanf.c vprintf.c vscanf.c vsiprintf.c \
|
||||
vsiscanf.c vsniprintf.c vsnprintf.c vsprintf.c vsscanf.c \
|
||||
stack_reg_va.S
|
||||
stack_reg_va.S spu_clock_svcs.c spu_clock_stop.c spu_timer_flih.S \
|
||||
spu_timer_slih.c spu_timer_slih_reg.c spu_timer_svcs.c \
|
||||
spu_timer_stop.c spu_timer_free.c
|
||||
|
||||
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
|
||||
lib_a_CFLAGS = $(AM_CFLAGS)
|
||||
|
@ -74,7 +74,11 @@ DIST_COMMON = $(srcdir)/../../../../config.guess \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
|
||||
$(srcdir)/../../../../compile
|
||||
subdir = .
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../../../acinclude.m4 \
|
||||
@ -131,7 +135,12 @@ am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-assert.$(OBJEXT) \
|
||||
lib_a-vscanf.$(OBJEXT) lib_a-vsiprintf.$(OBJEXT) \
|
||||
lib_a-vsiscanf.$(OBJEXT) lib_a-vsniprintf.$(OBJEXT) \
|
||||
lib_a-vsnprintf.$(OBJEXT) lib_a-vsprintf.$(OBJEXT) \
|
||||
lib_a-vsscanf.$(OBJEXT) lib_a-stack_reg_va.$(OBJEXT)
|
||||
lib_a-vsscanf.$(OBJEXT) lib_a-stack_reg_va.$(OBJEXT) \
|
||||
lib_a-spu_clock_svcs.$(OBJEXT) lib_a-spu_clock_stop.$(OBJEXT) \
|
||||
lib_a-spu_timer_flih.$(OBJEXT) lib_a-spu_timer_slih.$(OBJEXT) \
|
||||
lib_a-spu_timer_slih_reg.$(OBJEXT) \
|
||||
lib_a-spu_timer_svcs.$(OBJEXT) lib_a-spu_timer_stop.$(OBJEXT) \
|
||||
lib_a-spu_timer_free.$(OBJEXT)
|
||||
lib_a_OBJECTS = $(am_lib_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir)
|
||||
depcomp =
|
||||
@ -205,6 +214,11 @@ STRIP = @STRIP@
|
||||
USE_LIBTOOL_FALSE = @USE_LIBTOOL_FALSE@
|
||||
USE_LIBTOOL_TRUE = @USE_LIBTOOL_TRUE@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_AS = @ac_ct_AS@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_READELF = @ac_ct_READELF@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
aext = @aext@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
@ -220,23 +234,18 @@ build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
libm_machine_dir = @libm_machine_dir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lpfx = @lpfx@
|
||||
machine_dir = @machine_dir@
|
||||
@ -245,10 +254,8 @@ mkdir_p = @mkdir_p@
|
||||
newlib_basedir = @newlib_basedir@
|
||||
oext = @oext@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sys_dir = @sys_dir@
|
||||
@ -271,7 +278,9 @@ lib_a_SOURCES = setjmp.S assert.c clearerr.c creat.c fclose.c feof.c \
|
||||
tmpnam.c ungetc.c usleep.c vfiprintf.c vfiscanf.c vfprintf.c \
|
||||
vfscanf.c viprintf.c viscanf.c vprintf.c vscanf.c vsiprintf.c \
|
||||
vsiscanf.c vsniprintf.c vsnprintf.c vsprintf.c vsscanf.c \
|
||||
stack_reg_va.S
|
||||
stack_reg_va.S spu_clock_svcs.c spu_clock_stop.c spu_timer_flih.S \
|
||||
spu_timer_slih.c spu_timer_slih_reg.c spu_timer_svcs.c \
|
||||
spu_timer_stop.c spu_timer_free.c
|
||||
|
||||
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
|
||||
lib_a_CFLAGS = $(AM_CFLAGS)
|
||||
@ -430,6 +439,12 @@ lib_a-stack_reg_va.o: stack_reg_va.S
|
||||
lib_a-stack_reg_va.obj: stack_reg_va.S
|
||||
$(CCAS) $(lib_a_CCASFLAGS) $(CCASFLAGS) -c -o lib_a-stack_reg_va.obj `if test -f 'stack_reg_va.S'; then $(CYGPATH_W) 'stack_reg_va.S'; else $(CYGPATH_W) '$(srcdir)/stack_reg_va.S'; fi`
|
||||
|
||||
lib_a-spu_timer_flih.o: spu_timer_flih.S
|
||||
$(CCAS) $(lib_a_CCASFLAGS) $(CCASFLAGS) -c -o lib_a-spu_timer_flih.o `test -f 'spu_timer_flih.S' || echo '$(srcdir)/'`spu_timer_flih.S
|
||||
|
||||
lib_a-spu_timer_flih.obj: spu_timer_flih.S
|
||||
$(CCAS) $(lib_a_CCASFLAGS) $(CCASFLAGS) -c -o lib_a-spu_timer_flih.obj `if test -f 'spu_timer_flih.S'; then $(CYGPATH_W) 'spu_timer_flih.S'; else $(CYGPATH_W) '$(srcdir)/spu_timer_flih.S'; fi`
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
@ -855,6 +870,48 @@ lib_a-vsscanf.o: vsscanf.c
|
||||
|
||||
lib_a-vsscanf.obj: vsscanf.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vsscanf.obj `if test -f 'vsscanf.c'; then $(CYGPATH_W) 'vsscanf.c'; else $(CYGPATH_W) '$(srcdir)/vsscanf.c'; fi`
|
||||
|
||||
lib_a-spu_clock_svcs.o: spu_clock_svcs.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_clock_svcs.o `test -f 'spu_clock_svcs.c' || echo '$(srcdir)/'`spu_clock_svcs.c
|
||||
|
||||
lib_a-spu_clock_svcs.obj: spu_clock_svcs.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_clock_svcs.obj `if test -f 'spu_clock_svcs.c'; then $(CYGPATH_W) 'spu_clock_svcs.c'; else $(CYGPATH_W) '$(srcdir)/spu_clock_svcs.c'; fi`
|
||||
|
||||
lib_a-spu_clock_stop.o: spu_clock_stop.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_clock_stop.o `test -f 'spu_clock_stop.c' || echo '$(srcdir)/'`spu_clock_stop.c
|
||||
|
||||
lib_a-spu_clock_stop.obj: spu_clock_stop.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_clock_stop.obj `if test -f 'spu_clock_stop.c'; then $(CYGPATH_W) 'spu_clock_stop.c'; else $(CYGPATH_W) '$(srcdir)/spu_clock_stop.c'; fi`
|
||||
|
||||
lib_a-spu_timer_slih.o: spu_timer_slih.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_slih.o `test -f 'spu_timer_slih.c' || echo '$(srcdir)/'`spu_timer_slih.c
|
||||
|
||||
lib_a-spu_timer_slih.obj: spu_timer_slih.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_slih.obj `if test -f 'spu_timer_slih.c'; then $(CYGPATH_W) 'spu_timer_slih.c'; else $(CYGPATH_W) '$(srcdir)/spu_timer_slih.c'; fi`
|
||||
|
||||
lib_a-spu_timer_slih_reg.o: spu_timer_slih_reg.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_slih_reg.o `test -f 'spu_timer_slih_reg.c' || echo '$(srcdir)/'`spu_timer_slih_reg.c
|
||||
|
||||
lib_a-spu_timer_slih_reg.obj: spu_timer_slih_reg.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_slih_reg.obj `if test -f 'spu_timer_slih_reg.c'; then $(CYGPATH_W) 'spu_timer_slih_reg.c'; else $(CYGPATH_W) '$(srcdir)/spu_timer_slih_reg.c'; fi`
|
||||
|
||||
lib_a-spu_timer_svcs.o: spu_timer_svcs.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_svcs.o `test -f 'spu_timer_svcs.c' || echo '$(srcdir)/'`spu_timer_svcs.c
|
||||
|
||||
lib_a-spu_timer_svcs.obj: spu_timer_svcs.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_svcs.obj `if test -f 'spu_timer_svcs.c'; then $(CYGPATH_W) 'spu_timer_svcs.c'; else $(CYGPATH_W) '$(srcdir)/spu_timer_svcs.c'; fi`
|
||||
|
||||
lib_a-spu_timer_stop.o: spu_timer_stop.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_stop.o `test -f 'spu_timer_stop.c' || echo '$(srcdir)/'`spu_timer_stop.c
|
||||
|
||||
lib_a-spu_timer_stop.obj: spu_timer_stop.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_stop.obj `if test -f 'spu_timer_stop.c'; then $(CYGPATH_W) 'spu_timer_stop.c'; else $(CYGPATH_W) '$(srcdir)/spu_timer_stop.c'; fi`
|
||||
|
||||
lib_a-spu_timer_free.o: spu_timer_free.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_free.o `test -f 'spu_timer_free.c' || echo '$(srcdir)/'`spu_timer_free.c
|
||||
|
||||
lib_a-spu_timer_free.obj: spu_timer_free.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-spu_timer_free.obj `if test -f 'spu_timer_free.c'; then $(CYGPATH_W) 'spu_timer_free.c'; else $(CYGPATH_W) '$(srcdir)/spu_timer_free.c'; fi`
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
|
84
newlib/libc/machine/spu/include/spu_timer.h
Normal file
84
newlib/libc/machine/spu/include/spu_timer.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SPU_TIMER_H_
|
||||
#define _SPU_TIMER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Clock services. */
|
||||
extern void spu_clock_start (void);
|
||||
extern int spu_clock_stop (void);
|
||||
extern uint64_t spu_clock_read (void);
|
||||
|
||||
/* Timer services. */
|
||||
extern int spu_timer_alloc (int interval, void (*func) (int));
|
||||
extern int spu_timer_free (int id);
|
||||
extern int spu_timer_start (int id);
|
||||
extern int spu_timer_stop (int id);
|
||||
|
||||
/* Interrupt services. */
|
||||
extern void spu_slih_register (unsigned event_mask,
|
||||
unsigned (*slih) (unsigned));
|
||||
extern unsigned spu_clock_slih (unsigned event_mask);
|
||||
|
||||
/* Number of supported timers. */
|
||||
#define SPU_TIMER_NTIMERS 4
|
||||
|
||||
/* Recommended minimun spu timer interval time from (cat /proc/cpuinfo)
|
||||
* QS20 100/14318000 = 6.98 usec
|
||||
* QS21/QS22 100/26666666 = 3.75 usec
|
||||
* PS3 100/79800000 = 1.25 usec */
|
||||
#define SPU_TIMER_MIN_INTERVAL 100
|
||||
|
||||
/* Clock error codes. */
|
||||
#define SPU_CLOCK_ERR_NOT_RUNNING -2
|
||||
#define SPU_CLOCK_ERR_STILL_RUNNING -3
|
||||
#define SPU_CLOCK_ERR_TIMERS_ACTIVE -4
|
||||
|
||||
/* Timer error codes. */
|
||||
#define SPU_TIMER_ERR_INVALID_PARM -10
|
||||
#define SPU_TIMER_ERR_NONE_FREE -11
|
||||
#define SPU_TIMER_ERR_INVALID_ID -12
|
||||
#define SPU_TIMER_ERR_ACTIVE -13
|
||||
#define SPU_TIMER_ERR_NOT_ACTIVE -14
|
||||
#define SPU_TIMER_ERR_NOCLOCK -15
|
||||
#define SPU_TIMER_ERR_FREE -16
|
||||
#define SPU_TIMER_ERR_NOT_STOPPED -17
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
67
newlib/libc/machine/spu/spu_clock_stop.c
Normal file
67
newlib/libc/machine/spu/spu_clock_stop.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SPU clock stop library service. */
|
||||
#include <spu_timer.h>
|
||||
#include "spu_timer_internal.h"
|
||||
|
||||
/* Stops the SPU clock:
|
||||
* decrements clock start count
|
||||
* when count is zero, disables the decrementer event and stops the
|
||||
decrementer
|
||||
Returns 0 on success and <0 on failure:
|
||||
* SPU_CLOCK_ERR_NOT_RUNNING - clock was already off
|
||||
* SPU_CLOCK_ERR_TIMERS_ACTIVE - active timers exist
|
||||
* SPU_CLOCK_ERR_STILL_RUNNING - start count was decremented but clock was
|
||||
not stopped */
|
||||
int
|
||||
spu_clock_stop (void)
|
||||
{
|
||||
if (__spu_clock_startcnt == 0)
|
||||
return SPU_CLOCK_ERR_NOT_RUNNING;
|
||||
|
||||
if (__spu_clock_startcnt == 1 && (__spu_timers_active || __spu_timers_handled))
|
||||
return SPU_CLOCK_ERR_TIMERS_ACTIVE;
|
||||
|
||||
/* Don't stop clock if the clock is still in use. */
|
||||
if (--__spu_clock_startcnt != 0)
|
||||
return SPU_CLOCK_ERR_STILL_RUNNING;
|
||||
|
||||
/* Clock stopped, stop decrementer. */
|
||||
__disable_spu_decr ();
|
||||
|
||||
/* Clock is enabled on clock start - restore to original state (saved at start). */
|
||||
if (__likely (!__spu_clock_state_was_enabled))
|
||||
{
|
||||
spu_idisable ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
93
newlib/libc/machine/spu/spu_clock_svcs.c
Normal file
93
newlib/libc/machine/spu/spu_clock_svcs.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SPU clock start and read library services. */
|
||||
#include <spu_timer.h>
|
||||
#include "spu_timer_internal.h"
|
||||
|
||||
/* The software managed timebase value. */
|
||||
volatile uint64_t __spu_tb_val __attribute__ ((aligned (16)));
|
||||
|
||||
/* Timeout value of the current interval. */
|
||||
volatile int __spu_tb_timeout __attribute__ ((aligned (16)));
|
||||
|
||||
/* Clock start count (clock is running if >0). */
|
||||
volatile unsigned __spu_clock_startcnt __attribute__ ((aligned (16)));
|
||||
|
||||
/* Saved interrupt state from clock_start. */
|
||||
volatile unsigned __spu_clock_state_was_enabled;
|
||||
|
||||
/* Initializes the software managed timebase, enables the decrementer event,
|
||||
starts the decrementer and enables interrupts. Must be called before
|
||||
clock or timer services can be used. Should only be called by base app/lib
|
||||
code (not from an interrupt/timer handler).
|
||||
Returns with interrupts ENABLED. */
|
||||
void
|
||||
spu_clock_start (void)
|
||||
{
|
||||
/* Increment clock start and return if it was already running. */
|
||||
if (++__spu_clock_startcnt > 1)
|
||||
return;
|
||||
|
||||
__spu_clock_state_was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
|
||||
spu_idisable ();
|
||||
__spu_tb_timeout = CLOCK_START_VALUE;
|
||||
__spu_tb_val = 0;
|
||||
|
||||
/* Disable, write, enable the decrementer. */
|
||||
__enable_spu_decr (__spu_tb_timeout, __disable_spu_decr ());
|
||||
|
||||
spu_ienable ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns a monotonically increasing, 64-bit counter, in timebase units,
|
||||
relative to the last call to spu_clock_start(). */
|
||||
uint64_t
|
||||
spu_clock_read (void)
|
||||
{
|
||||
int64_t time;
|
||||
unsigned was_enabled;
|
||||
|
||||
/* Return 0 if clock is off. */
|
||||
if (__spu_clock_startcnt == 0)
|
||||
return 0LL;
|
||||
|
||||
was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
spu_idisable ();
|
||||
|
||||
time = __spu_tb_val + (__spu_tb_timeout - spu_readch (SPU_RdDec));
|
||||
|
||||
if (__likely (was_enabled))
|
||||
spu_ienable ();
|
||||
return time;
|
||||
}
|
152
newlib/libc/machine/spu/spu_timer_flih.S
Normal file
152
newlib/libc/machine/spu/spu_timer_flih.S
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* First-level interrupt handler. */
|
||||
|
||||
/* The following two convenience macros assist in the coding of the
|
||||
saving and restoring the volatile register starting from register
|
||||
2 up to register 79.
|
||||
|
||||
saveregs first, last Saves registers from first to the last.
|
||||
restoreregs first, last Restores registers from last down to first.
|
||||
|
||||
Note: first must be less than or equal to last. */
|
||||
|
||||
.macro saveregs first, last
|
||||
stqd $\first, -(STACK_SKIP+\first)*16($SP)
|
||||
.if \last-\first
|
||||
saveregs "(\first+1)",\last
|
||||
.endif
|
||||
.endm
|
||||
|
||||
|
||||
.macro restoreregs first, last
|
||||
lqd $\last, (82-\last)*16($SP)
|
||||
.if \last-\first
|
||||
restoreregs \first,"(\last-1)"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.section .interrupt,"ax"
|
||||
.align 3
|
||||
.type spu_flih, @function
|
||||
spu_flih:
|
||||
/* Adjust the stack pointer to skip the maximum register save area
|
||||
(STACK_SKIP quadword registers) in case an interrupt occurred while
|
||||
executing a leaf function that used the stack area without actually
|
||||
allocating its own stack frame. */
|
||||
.set STACK_SKIP, 125
|
||||
|
||||
/* Save the current link register on a new stack frame for the
|
||||
normal spu_flih() version of this file. */
|
||||
stqd $0, -(STACK_SKIP+80)*16($SP)
|
||||
stqd $SP, -(STACK_SKIP+82)*16($SP) /* Save back chain pointer. */
|
||||
|
||||
saveregs 2, 39
|
||||
|
||||
il $2, -(STACK_SKIP+82)*16 /* Stack frame size. */
|
||||
rdch $3, $SPU_RdEventStat /* Read event status. */
|
||||
|
||||
rdch $6, $SPU_RdEventMask /* Read event mask. */
|
||||
hbrp /* Open a slot for instruction prefetch. */
|
||||
|
||||
saveregs 40,59
|
||||
|
||||
clz $4, $3 /* Get first slih index. */
|
||||
stqd $6, -(STACK_SKIP+1)*16($SP) /* Save event mask on stack. */
|
||||
|
||||
saveregs 60, 67
|
||||
|
||||
/* Do not disable/ack the decrementer event here.
|
||||
The timer library manages this and expects it
|
||||
to be enabled upon entry to the SLIH. */
|
||||
il $7, 0x20
|
||||
andc $5, $3, $7
|
||||
andc $7, $6, $5 /* Clear event bits. */
|
||||
saveregs 68, 69
|
||||
|
||||
wrch $SPU_WrEventAck, $3 /* Ack events(s) - include decrementer event. */
|
||||
wrch $SPU_WrEventMask, $7 /* Disable event(s) - exclude decrementer event. */
|
||||
|
||||
saveregs 70, 79
|
||||
|
||||
a $SP, $SP, $2 /* Instantiate flih stack frame. */
|
||||
next_event:
|
||||
/* Fetch and dispatch the event handler for the first non-zero event. The
|
||||
dispatch handler is indexed into the __spu_slih_handlers array using the
|
||||
count of zero off the event status as an index. */
|
||||
ila $5, __spu_slih_handlers /* Slih array offset. */
|
||||
|
||||
shli $4, $4, 2 /* Slih entry offset. */
|
||||
lqx $5, $4, $5 /* Load slih address. */
|
||||
rotqby $5, $5, $4 /* Rotate to word 0. */
|
||||
bisl $0, $5 /* Branch to slih. */
|
||||
|
||||
clz $4, $3 /* Get next slih index. */
|
||||
brnz $3, next_event
|
||||
|
||||
|
||||
lqd $2, 81*16($SP) /* Read event mask from stack. */
|
||||
|
||||
restoreregs 40, 79
|
||||
|
||||
wrch $SPU_WrEventMask, $2 /* Restore event mask. */
|
||||
hbrp /* Open a slot for instruction pre-fetch. */
|
||||
|
||||
restoreregs 2, 39
|
||||
|
||||
/* Restore the link register from the new stack frame for the
|
||||
normal spu_flih() version of this file. */
|
||||
lqd $0, 2*16($SP)
|
||||
|
||||
lqd $SP, 0*16($SP) /* restore stack pointer from back chain ptr. */
|
||||
|
||||
irete /* Return from interrupt and re-enable interrupts. */
|
||||
.size spu_flih, .-spu_flih
|
||||
/* spu_slih_handlers[]
|
||||
Here we initialize 33 default event handlers. The first entry in this array
|
||||
corresponds to the event handler for the event associated with bit 0 of
|
||||
Channel 0 (External Event Status). The 32nd entry in this array corresponds
|
||||
to bit 31 of Channel 0 (DMA Tag Status Update Event). The 33rd entry in
|
||||
this array is a special case entry to handle "phantom events" which occur
|
||||
when the channel count for Channel 0 is 1, causing an asynchronous SPU
|
||||
interrupt, but the value returned for a read of Channel 0 is 0. The index
|
||||
calculated into this array by spu_flih() for this case is 32, hence the
|
||||
33rd entry. */
|
||||
.data
|
||||
.align 4
|
||||
.extern __spu_default_slih
|
||||
.global __spu_slih_handlers
|
||||
.type __spu_slih_handlers, @object
|
||||
__spu_slih_handlers:
|
||||
.rept 33
|
||||
.long __spu_default_slih
|
||||
.endr
|
||||
.size __spu_slih_handlers, .-__spu_slih_handlers
|
86
newlib/libc/machine/spu/spu_timer_free.c
Normal file
86
newlib/libc/machine/spu/spu_timer_free.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SPU timer free library service. */
|
||||
#include <spu_timer.h>
|
||||
#include "spu_timer_internal.h"
|
||||
|
||||
|
||||
/* Frees an allocated timer. The timer must be in the stopped state for this
|
||||
to succeed. Maybe be called:
|
||||
* after allocated, before it's started
|
||||
* after it's been explicitly stopped
|
||||
Returns 0 on success, timer sucessfully deallocated. Returns <0 on failure
|
||||
* SPU_TIMER_INVALID_ID - id out of range
|
||||
* SPU_TIMER_ERR_FREE - id in free state
|
||||
* SPU_TIMER_ERR_ACTIVE - id in handled or active state */
|
||||
int
|
||||
spu_timer_free (int id)
|
||||
{
|
||||
spu_timer_t *t, **pn;
|
||||
unsigned was_enabled;
|
||||
|
||||
if (id < 0 || id >= SPU_TIMER_NTIMERS)
|
||||
return SPU_TIMER_ERR_INVALID_ID;
|
||||
|
||||
if (__spu_timers[id].state == SPU_TIMER_STOPPED)
|
||||
{
|
||||
|
||||
was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
spu_idisable ();
|
||||
|
||||
t = __spu_timers_stopped;
|
||||
pn = &__spu_timers_stopped;
|
||||
|
||||
while (t && (t->id != id))
|
||||
{
|
||||
pn = &t->next;
|
||||
t = t->next;
|
||||
}
|
||||
#ifdef SPU_TIMER_DEBUG
|
||||
if (!t)
|
||||
ABORT ();
|
||||
#endif
|
||||
*pn = t->next;
|
||||
|
||||
/* Add timer back to free list (mask). */
|
||||
__spu_timers_avail |= (1 << (id));
|
||||
__spu_timers[id].state = SPU_TIMER_FREE;
|
||||
|
||||
if (__likely (was_enabled))
|
||||
spu_ienable ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle invalid states. */
|
||||
return (__spu_timers[id].state == SPU_TIMER_FREE) ?
|
||||
SPU_TIMER_ERR_FREE : SPU_TIMER_ERR_ACTIVE;
|
||||
}
|
140
newlib/libc/machine/spu/spu_timer_internal.h
Normal file
140
newlib/libc/machine/spu/spu_timer_internal.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Internal definitions for SPU timer library. */
|
||||
#ifndef _SPU_TIMER_INTERNAL_H_
|
||||
#define _SPU_TIMER_INTERNAL_H_
|
||||
|
||||
#include <spu_intrinsics.h>
|
||||
#include <spu_mfcio.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef SPU_TIMER_DEBUG
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* The timer state tells which list its on. */
|
||||
typedef enum spu_timer_state
|
||||
{
|
||||
SPU_TIMER_FREE = 0,
|
||||
SPU_TIMER_ACTIVE = 1,
|
||||
SPU_TIMER_HANDLED = 2,
|
||||
SPU_TIMER_STOPPED = 3
|
||||
} spu_timer_state_t;
|
||||
|
||||
typedef struct spu_timer
|
||||
{
|
||||
int tmout __attribute__ ((aligned (16))); /* Time until expiration (tb). */
|
||||
int intvl __attribute__ ((aligned (16))); /* Interval. */
|
||||
int id __attribute__ ((aligned (16)));
|
||||
spu_timer_state_t state __attribute__ ((aligned (16)));
|
||||
void (*func) (int) __attribute__ ((aligned (16))); /* Handler. */
|
||||
struct spu_timer *next __attribute__ ((aligned (16)));
|
||||
} spu_timer_t;
|
||||
|
||||
|
||||
/* Max decrementer value. */
|
||||
#define DECR_MAX 0xFFFFFFFFU
|
||||
|
||||
/* Arbitrary non-triggering value. */
|
||||
#define CLOCK_START_VALUE 0x7FFFFFFF
|
||||
|
||||
#define MIN_INTVL 1
|
||||
#define MAX_INTVL INT_MAX
|
||||
|
||||
/* Timers within 15 tics will expire together. */
|
||||
#define TIMER_INTERVAL_WINDOW 15
|
||||
|
||||
/* Disables the decrementer and returns the saved event mask for a subsequent
|
||||
call to __enable_spu_decr. The decrementer interrupt is acknowledged in the
|
||||
flih when the event is received, but is required also as part of the
|
||||
procedure to stop the decrementer. */
|
||||
static inline unsigned
|
||||
__disable_spu_decr (void)
|
||||
{
|
||||
unsigned mask = spu_readch (SPU_RdEventMask);
|
||||
spu_writech (SPU_WrEventMask, mask & ~MFC_DECREMENTER_EVENT);
|
||||
spu_writech (SPU_WrEventAck, MFC_DECREMENTER_EVENT);
|
||||
spu_sync_c ();
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* Writes and enables the decrementer, along with the given event mask. */
|
||||
static inline void
|
||||
__enable_spu_decr (int val, unsigned mask)
|
||||
{
|
||||
spu_writech (SPU_WrDec, (val));
|
||||
spu_writech (SPU_WrEventMask, mask | MFC_DECREMENTER_EVENT);
|
||||
spu_sync_c ();
|
||||
}
|
||||
|
||||
/* These are shared between modules but are not inlined, to save space. */
|
||||
extern void __spu_timer_start (int id, int reset);
|
||||
extern void __reset_spu_decr (int val);
|
||||
|
||||
/* The timers. */
|
||||
extern spu_timer_t __spu_timers[];
|
||||
|
||||
/* Active timer list. */
|
||||
extern spu_timer_t *__spu_timers_active;
|
||||
|
||||
/* Stopped (allocated) timer list. */
|
||||
extern spu_timer_t *__spu_timers_stopped;
|
||||
|
||||
/* List of timers being handled. */
|
||||
extern spu_timer_t *__spu_timers_handled;
|
||||
|
||||
/* Bitmask of available timers. */
|
||||
extern unsigned __spu_timers_avail;
|
||||
|
||||
/* The software managed timebase value. */
|
||||
extern volatile uint64_t __spu_tb_val;
|
||||
|
||||
/* Timeout value of the current interval. */
|
||||
extern volatile int __spu_tb_timeout;
|
||||
|
||||
/* Clock start count (clock is running if >0). */
|
||||
extern volatile unsigned __spu_clock_startcnt;
|
||||
|
||||
/* Saved interrupt state from clock_start. */
|
||||
extern volatile unsigned __spu_clock_state_was_enabled;
|
||||
|
||||
#define __likely(_c) __builtin_expect((_c), 1)
|
||||
#define __unlikely(_c) __builtin_expect((_c), 0)
|
||||
|
||||
#define ABORT() \
|
||||
{\
|
||||
fprintf(stderr, "Internal error, aborting: %s:%d\n", __FILE__, __LINE__);\
|
||||
assert(0);\
|
||||
}
|
||||
|
||||
#endif
|
221
newlib/libc/machine/spu/spu_timer_slih.c
Normal file
221
newlib/libc/machine/spu/spu_timer_slih.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Second Level Interrupt handler and related services for SPU timers. */
|
||||
#include "spu_timer_internal.h"
|
||||
/* Resets decrementer to the specified value. Also updates software timebase
|
||||
to account for the time between the last decrementer reset and now. There
|
||||
are two cases:
|
||||
* Called by application to start a new timer.
|
||||
* Called by spu_clock to active the next timer.
|
||||
In both cases, the amount of time is the current interval timeout minus the
|
||||
current decrementer value. */
|
||||
void
|
||||
__reset_spu_decr (int val)
|
||||
{
|
||||
|
||||
/* The interrupt occurs when the msb goes from 0 to 1 or when the decrementer
|
||||
goes from 0 to -1. To be precisely accurate we should set the timer to
|
||||
the intverval -1, unless the interval passed in is 0 in which case it
|
||||
should be left at 0. */
|
||||
int enable_val = (__likely (val)) ? val - 1 : 0;
|
||||
|
||||
/* Decrementer must be stopped before writing it - minimize the time
|
||||
stopped. */
|
||||
unsigned mask = __disable_spu_decr ();
|
||||
|
||||
/* Perform tb correction before resettting the decrementer. the corrected
|
||||
value is the current timeout value minus the current decrementer value.
|
||||
Occasionally the read returns 0 - a second read will clear this
|
||||
condition. */
|
||||
int decval0 = spu_readch (SPU_RdDec);
|
||||
int decval = spu_readch (SPU_RdDec);
|
||||
/* Restart decrementer with next timeout val. */
|
||||
__enable_spu_decr (enable_val, mask);
|
||||
|
||||
/* Update the timebase values before enabling for interrupts. */
|
||||
__spu_tb_val += __spu_tb_timeout - decval;
|
||||
__spu_tb_timeout = enable_val;
|
||||
}
|
||||
|
||||
/* Update software timebase and timeout value for the 'next to expire' timer.
|
||||
Called when starting a new timer so the timer list will have timeouts
|
||||
relative to the current time. */
|
||||
static inline void
|
||||
__update_spu_tb_val (void)
|
||||
{
|
||||
int elapsed = __spu_tb_timeout - spu_readch (SPU_RdDec);
|
||||
#ifdef SPU_TIMER_DEBUG
|
||||
if (elapsed < 0)
|
||||
ABORT ();
|
||||
#endif
|
||||
__spu_tb_val += elapsed;
|
||||
|
||||
/* Adjust the timeout for the timer next to expire. Note this could cause
|
||||
the timeout to go negative, if it was just about to expire when we called
|
||||
spu_timer_start. This is OK, since this can happen any time interrupts
|
||||
are disabled. We just schedule an immediate timeout in this case. */
|
||||
if (__spu_timers_active)
|
||||
{
|
||||
__spu_timers_active->tmout -= elapsed;
|
||||
if (__spu_timers_active->tmout < 0)
|
||||
__spu_timers_active->tmout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add an allocated timer to the active list. The active list is sorted by
|
||||
timeout value. The timer at the head of the list is the timer that will
|
||||
expire next. The rest of the timers have a timeout value that is relative
|
||||
to the timer ahead of it on the list. This relative value is determined
|
||||
here, when the timer is added to the active list. When its position in the
|
||||
list is found, the timer's timeout value is set to its interval minus the
|
||||
sum of all the timeout values ahead of it. The timeout value for the timer
|
||||
following the newly added timer is then adjusted to a new relative value. If
|
||||
the newly added timer is at the head of the list, the decrementer is reset.
|
||||
This function is called by SLIH to restart multiple timers (reset == 0) or
|
||||
by spu_timer_start() to start a single timer (reset == 1). */
|
||||
void
|
||||
__spu_timer_start (int id, int reset)
|
||||
{
|
||||
spu_timer_t *t;
|
||||
spu_timer_t **pn;
|
||||
spu_timer_t *start = &__spu_timers[id];
|
||||
unsigned tmout_time = 0;
|
||||
unsigned my_intvl = start->intvl;
|
||||
unsigned was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
|
||||
spu_idisable ();
|
||||
|
||||
t = __spu_timers_active;
|
||||
pn = &__spu_timers_active;
|
||||
|
||||
/* If the active list is empty, just add the timer with the timeout set to
|
||||
the interval. Otherwise find the place in the list for the timer, setting
|
||||
its timeout to its interval minus the sum of timeouts ahead of it. */
|
||||
start->state = SPU_TIMER_ACTIVE;
|
||||
if (__likely (!t))
|
||||
{
|
||||
__spu_timers_active = start;
|
||||
start->next = NULL;
|
||||
start->tmout = my_intvl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Update swtb and timeout val of the next timer, so all times are
|
||||
relative to now. */
|
||||
if (reset)
|
||||
__update_spu_tb_val ();
|
||||
|
||||
while (t && (my_intvl >= (tmout_time + t->tmout)))
|
||||
{
|
||||
tmout_time += t->tmout;
|
||||
pn = &t->next;;
|
||||
t = t->next;
|
||||
}
|
||||
start->next = t;
|
||||
start->tmout = my_intvl - tmout_time;
|
||||
*pn = start;
|
||||
|
||||
/* Adjust timeout for timer after us. */
|
||||
if (t)
|
||||
t->tmout -= start->tmout;
|
||||
}
|
||||
|
||||
if (reset && (__spu_timers_active == start))
|
||||
__reset_spu_decr (__spu_timers_active->tmout);
|
||||
|
||||
if (__unlikely (was_enabled))
|
||||
spu_ienable ();
|
||||
}
|
||||
|
||||
/* SLIH for decrementer. Manages software timebase and timers.
|
||||
Called by SPU FLIH. Assumes decrementer is still running
|
||||
(event not yet acknowledeged). */
|
||||
unsigned int
|
||||
spu_clock_slih (unsigned status)
|
||||
{
|
||||
int decr_reset_val;
|
||||
spu_timer_t *active, *handled;
|
||||
unsigned was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
|
||||
status &= ~MFC_DECREMENTER_EVENT;
|
||||
|
||||
spu_idisable ();
|
||||
|
||||
/* The decrementer has now expired. The decrementer event was acknowledged
|
||||
in the FLIH but not disabled. The decrementer will continue to run while
|
||||
we're running the clock/timer handler. The software clock keeps running,
|
||||
and accounts for all the time spent running handlers. Add the current
|
||||
timeout to the software timebase and set the timeout to DECR_MAX. This
|
||||
allows the "clock read" code to continue to work while we're in here, and
|
||||
gives us the most possible time to finish before another underflow. */
|
||||
__spu_tb_val += __spu_tb_timeout;
|
||||
__spu_tb_timeout = DECR_MAX;
|
||||
|
||||
/* For all timers that have the current timeout value, move them from the
|
||||
active list to the handled list and call their handlers. Note that the
|
||||
handled/stopped lists may be manipulated by the handlers if they wish to
|
||||
stop/free the timers. Note that only the first expired timer will reflect
|
||||
the real timeout value; the rest of the timers that had the same timeout
|
||||
value will have a relative value of zero. */
|
||||
if (__spu_timers_active)
|
||||
{
|
||||
__spu_timers_active->tmout = 0;
|
||||
while ((active = __spu_timers_active)
|
||||
&& (active->tmout <= TIMER_INTERVAL_WINDOW))
|
||||
{
|
||||
__spu_timers_active = active->next;
|
||||
active->next = __spu_timers_handled;
|
||||
__spu_timers_handled = active;
|
||||
active->state = SPU_TIMER_HANDLED;
|
||||
(*active->func) (active->id);
|
||||
}
|
||||
}
|
||||
|
||||
/* put the handled timers back on the list and restart decrementer. */
|
||||
while ((handled = __spu_timers_handled) != NULL)
|
||||
{
|
||||
__spu_timers_handled = handled->next;
|
||||
__spu_timer_start (handled->id, 0);
|
||||
}
|
||||
|
||||
/* Reset the decrementer before returning. If we have any active timers, we
|
||||
set it to the timeout value for the timer at the head of the list, else
|
||||
the default clock value. */
|
||||
decr_reset_val = __spu_timers_active ? __spu_timers_active->tmout : CLOCK_START_VALUE;
|
||||
|
||||
__reset_spu_decr (decr_reset_val);
|
||||
|
||||
if (__likely (was_enabled))
|
||||
spu_ienable ();
|
||||
|
||||
return status;
|
||||
}
|
72
newlib/libc/machine/spu/spu_timer_slih_reg.c
Normal file
72
newlib/libc/machine/spu/spu_timer_slih_reg.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/* Services for SLIH registration. */
|
||||
#include <spu_intrinsics.h>
|
||||
#include <spu_timer.h>
|
||||
|
||||
#define SPU_EVENT_ID(_mask) \
|
||||
(spu_extract(spu_cntlz(spu_promote(_mask, 0)), 0))
|
||||
typedef unsigned (*spu_slih_t) (unsigned);
|
||||
|
||||
extern spu_slih_t __spu_slih_handlers[];
|
||||
|
||||
/* This function is called whenever an event occurs for which no second level
|
||||
event handler was registered. The default event handler does nothing and
|
||||
zeros the most significant event bit indicating that the event was processed
|
||||
(when in reality, it was discarded). */
|
||||
unsigned
|
||||
__spu_default_slih (unsigned events)
|
||||
{
|
||||
unsigned int mse;
|
||||
|
||||
mse = 0x80000000 >> SPU_EVENT_ID (events);
|
||||
events &= ~mse;
|
||||
|
||||
return (events);
|
||||
}
|
||||
|
||||
/* Registers a SPU second level interrupt handler for the events specified by
|
||||
mask. The event mask consists of a set of bits corresponding to the event
|
||||
status bits (see channel 0 description). A mask containing multiple 1 bits
|
||||
will set the second level event handler for each of the events. */
|
||||
void
|
||||
spu_slih_register (unsigned mask, spu_slih_t func)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
while (mask)
|
||||
{
|
||||
id = SPU_EVENT_ID (mask);
|
||||
__spu_slih_handlers[id] = (func) ? func : __spu_default_slih;
|
||||
mask &= ~(0x80000000 >> id);
|
||||
}
|
||||
}
|
101
newlib/libc/machine/spu/spu_timer_stop.c
Normal file
101
newlib/libc/machine/spu/spu_timer_stop.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SPU timer stop library service. */
|
||||
#include <spu_timer.h>
|
||||
#include "spu_timer_internal.h"
|
||||
|
||||
/* Stop a timer. Moves it from either the active or handled list to the
|
||||
stopped list. Returns 0 on sucess, timer was successfully stopped.
|
||||
Returns <0 - Failure:
|
||||
* SPU_TIMER_ERR_NOT_ACTIVE - timer was not active
|
||||
* SPU_TIMER_ERR_INVALID_ID - invalid timer id
|
||||
* SPU_TIMER_ERR_NOCLOCK - spu clock is not running */
|
||||
int
|
||||
spu_timer_stop (int id)
|
||||
{
|
||||
spu_timer_t *t, **pn;
|
||||
unsigned was_enabled;
|
||||
|
||||
if (id < 0 || id >= SPU_TIMER_NTIMERS)
|
||||
return SPU_TIMER_ERR_INVALID_ID;
|
||||
|
||||
if (__spu_clock_startcnt == 0)
|
||||
return SPU_TIMER_ERR_NOCLOCK;
|
||||
|
||||
|
||||
/* Free or stopped states. */
|
||||
if (__spu_timers[id].state == SPU_TIMER_ACTIVE ||
|
||||
__spu_timers[id].state == SPU_TIMER_HANDLED)
|
||||
{
|
||||
was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
spu_idisable ();
|
||||
|
||||
/* Timer is on either active list or handled list. */
|
||||
t = (__spu_timers[id].state == SPU_TIMER_ACTIVE)
|
||||
? __spu_timers_active : __spu_timers_handled;
|
||||
|
||||
pn = (__spu_timers[id].state == SPU_TIMER_ACTIVE)
|
||||
? &__spu_timers_active : &__spu_timers_handled;
|
||||
|
||||
while (t && t->id != id)
|
||||
{
|
||||
pn = &t->next;
|
||||
t = t->next;
|
||||
}
|
||||
#ifdef SPU_TIMER_DEBUG
|
||||
if (!t)
|
||||
ABORT (); /* Internal error. */
|
||||
#endif
|
||||
/* Fix timeout of next timer and decrementer if we were at the head of
|
||||
the active list. */
|
||||
if (t->next)
|
||||
{
|
||||
t->next->tmout += t->tmout;
|
||||
if (__spu_timers_active == t)
|
||||
__reset_spu_decr (t->next->tmout);
|
||||
}
|
||||
else
|
||||
__reset_spu_decr (CLOCK_START_VALUE);
|
||||
|
||||
*pn = t->next; /* Update this elements to pointer. */
|
||||
t->next = __spu_timers_stopped;
|
||||
__spu_timers_stopped = t;
|
||||
|
||||
__spu_timers[id].state = SPU_TIMER_STOPPED;
|
||||
|
||||
if (__likely (was_enabled))
|
||||
spu_ienable ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SPU_TIMER_ERR_NOT_ACTIVE;
|
||||
}
|
115
newlib/libc/machine/spu/spu_timer_svcs.c
Normal file
115
newlib/libc/machine/spu/spu_timer_svcs.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
(C) Copyright IBM Corp. 2008
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of IBM nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* SPU timer start and alloc library services. */
|
||||
#include <spu_timer.h>
|
||||
#include "spu_timer_internal.h"
|
||||
|
||||
/* The timers. */
|
||||
spu_timer_t __spu_timers[SPU_TIMER_NTIMERS] __attribute__ ((aligned (16)));
|
||||
|
||||
/* Active timer list. */
|
||||
spu_timer_t *__spu_timers_active;
|
||||
|
||||
/* Stopped (allocated) timer list. */
|
||||
spu_timer_t *__spu_timers_stopped;
|
||||
|
||||
/* List of timers being handled. */
|
||||
spu_timer_t *__spu_timers_handled;
|
||||
|
||||
/* Bitmask of available timers. */
|
||||
unsigned __spu_timers_avail =
|
||||
((1 << (SPU_TIMER_NTIMERS - 1)) + ((1 << (SPU_TIMER_NTIMERS - 1)) - 1));
|
||||
|
||||
/* Allocates an SPU interval timer and returns the timer ID. Must be called
|
||||
before starting a timer. interval specifies the expiration interval in
|
||||
timebase units. func specifies the function pointer to expiration handler.
|
||||
Returns the timer ID on success or <0 on Failure:
|
||||
* SPU_TIMER_ERR_NONE_FREE - no free timers to allocate
|
||||
* SPU_TIMER_ERR_INVALID_PARM - invalid parm */
|
||||
int
|
||||
spu_timer_alloc (int interval, void (*func) (int))
|
||||
{
|
||||
unsigned was_enabled;
|
||||
int id;
|
||||
if (interval < MIN_INTVL || interval > MAX_INTVL || func == NULL)
|
||||
return SPU_TIMER_ERR_INVALID_PARM;
|
||||
|
||||
was_enabled = spu_readch (SPU_RdMachStat) & 0x1;
|
||||
|
||||
/* Get id of next available timer. */
|
||||
id = spu_extract ((spu_sub ((unsigned) 31,
|
||||
spu_cntlz (spu_promote
|
||||
(__spu_timers_avail, 0)))), 0);
|
||||
|
||||
/* No timers avail. */
|
||||
if (id == -1)
|
||||
return SPU_TIMER_ERR_NONE_FREE;
|
||||
|
||||
/* Higher order bits represent lower timer ids. */
|
||||
__spu_timers_avail &= ~(1 << (id));
|
||||
id = (SPU_TIMER_NTIMERS - 1) - id;
|
||||
|
||||
/* Initialize timer and put it on stopped list. */
|
||||
(__spu_timers + id)->func = func;
|
||||
(__spu_timers + id)->intvl = interval;
|
||||
(__spu_timers + id)->id = id;
|
||||
(__spu_timers + id)->state = SPU_TIMER_STOPPED;
|
||||
|
||||
spu_idisable ();
|
||||
(__spu_timers + id)->next = __spu_timers_stopped;
|
||||
__spu_timers_stopped = &__spu_timers[id];
|
||||
|
||||
if (__likely (was_enabled))
|
||||
spu_ienable ();
|
||||
return id;
|
||||
}
|
||||
|
||||
/* External interface for starting a timer. See description of
|
||||
__spu_timer_start(). Returns 0 on success and <0 on failure:
|
||||
* SPU_TIMER_ERR_INVALID_ID - invalid id
|
||||
* SPU_TIMER_ERR_NOCLOCK - clock is off
|
||||
* SPU_TIMER_ERR_NOT_STOPPED - timer not in stopped state */
|
||||
int
|
||||
spu_timer_start (int id)
|
||||
{
|
||||
if (id < 0 || id >= SPU_TIMER_NTIMERS)
|
||||
return SPU_TIMER_ERR_INVALID_ID;
|
||||
|
||||
if (__spu_clock_startcnt == 0)
|
||||
return SPU_TIMER_ERR_NOCLOCK;
|
||||
|
||||
if (__spu_timers[id].state != SPU_TIMER_STOPPED)
|
||||
return SPU_TIMER_ERR_NOT_STOPPED;
|
||||
|
||||
__spu_timer_start (id, 1);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user