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