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:
		| @@ -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; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user