1 /*
2 (C) Copyright IBM Corp. 2008
3 
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 
9 * Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 * Neither the name of IBM nor the names of its contributors may be
15 used to endorse or promote products derived from this software without
16 specific prior written permission.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 /* Internal definitions for SPU timer library.  */
32 #ifndef _SPU_TIMER_INTERNAL_H_
33 #define _SPU_TIMER_INTERNAL_H_
34 
35 #include <spu_intrinsics.h>
36 #include <spu_mfcio.h>
37 #include <limits.h>
38 #include <stdlib.h>
39 
40 #ifdef SPU_TIMER_DEBUG
41 #include <stdio.h>
42 #include <assert.h>
43 #endif
44 
45 /* The timer state tells which list its on.  */
46 typedef enum spu_timer_state
47 {
48   SPU_TIMER_FREE = 0,
49   SPU_TIMER_ACTIVE = 1,
50   SPU_TIMER_HANDLED = 2,
51   SPU_TIMER_STOPPED = 3
52 } spu_timer_state_t;
53 
54 typedef struct spu_timer
55 {
56   int tmout __attribute__ ((__aligned__ (16)));	/* Time until expiration (tb).  */
57   int intvl __attribute__ ((__aligned__ (16)));	/* Interval.  */
58   int id __attribute__ ((__aligned__ (16)));
59   spu_timer_state_t state __attribute__ ((__aligned__ (16)));
60   void (*func) (int) __attribute__ ((__aligned__ (16)));	/* Handler.  */
61   struct spu_timer *next __attribute__ ((__aligned__ (16)));
62 } spu_timer_t;
63 
64 
65 /* Max decrementer value.  */
66 #define DECR_MAX        0xFFFFFFFFU
67 
68  /* Arbitrary non-triggering value.  */
69 #define CLOCK_START_VALUE 0x7FFFFFFF
70 
71 #define MIN_INTVL       1
72 #define MAX_INTVL       INT_MAX
73 
74 /* Timers within 15 tics will expire together.  */
75 #define TIMER_INTERVAL_WINDOW  15
76 
77 /* Disables the decrementer and returns the saved event mask for a subsequent
78    call to __enable_spu_decr. The decrementer interrupt is acknowledged in the
79    flih when the event is received, but is required also as part of the
80    procedure to stop the decrementer.  */
81 static inline unsigned
__disable_spu_decr(void)82 __disable_spu_decr (void)
83 {
84   unsigned mask = spu_readch (SPU_RdEventMask);
85   spu_writech (SPU_WrEventMask, mask & ~MFC_DECREMENTER_EVENT);
86   spu_writech (SPU_WrEventAck, MFC_DECREMENTER_EVENT);
87   spu_sync_c ();
88   return mask;
89 }
90 
91 /* Writes and enables the decrementer, along with the given event mask.  */
92 static inline void
__enable_spu_decr(int val,unsigned mask)93 __enable_spu_decr (int val, unsigned mask)
94 {
95   spu_writech (SPU_WrDec, (val));
96   spu_writech (SPU_WrEventMask, mask | MFC_DECREMENTER_EVENT);
97   spu_sync_c ();
98 }
99 
100 /* These are shared between modules but are not inlined, to save space.  */
101 extern void __spu_timer_start (int id, int reset);
102 extern void __reset_spu_decr (int val);
103 
104 /* The timers.  */
105 extern spu_timer_t __spu_timers[];
106 
107 /* Active timer list.  */
108 extern spu_timer_t *__spu_timers_active;
109 
110 /* Stopped (allocated) timer list.  */
111 extern spu_timer_t *__spu_timers_stopped;
112 
113 /* List of timers being handled.  */
114 extern spu_timer_t *__spu_timers_handled;
115 
116 /* Bitmask of available timers.  */
117 extern unsigned __spu_timers_avail;
118 
119 /* The software managed timebase value.  */
120 extern volatile uint64_t __spu_tb_val;
121 
122 /* Timeout value of the current interval.  */
123 extern volatile int __spu_tb_timeout;
124 
125 /* Clock start count (clock is running if >0).  */
126 extern volatile unsigned __spu_clock_startcnt;
127 
128 /* Saved interrupt state from clock_start.  */
129 extern volatile unsigned __spu_clock_state_was_enabled;
130 
131 #define __likely(_c)        __builtin_expect((_c), 1)
132 #define __unlikely(_c)      __builtin_expect((_c), 0)
133 
134 #define ABORT() \
135 {\
136     fprintf(stderr, "Internal error, aborting: %s:%d\n", __FILE__, __LINE__);\
137     assert(0);\
138 }
139 
140 #endif
141