ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
alarm.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Licenced under Academic Free License version 2.0
7 # Review ps2sdk README & LICENSE files for further details.
8 */
9 
10 #include "tamtypes.h"
11 #include "timer.h"
12 #include "ee_regs.h"
13 #include "kernel.h"
14 
15 #include "internal.h"
16 
17 #define USER_MODE_DISPATCHER 0x00082000 //Call the replacement dispatcher (the original dispatcher function is located at 0x00081fe0).
18 
19 #define INTC_TIM3 12
20 #define T3_COUNT_W ((vu32*)0xB0001800)
21 #define T3_MODE_W ((vu32*)0xB0001810)
22 #define T3_COMP_W ((vu32*)0xB0001820)
23 
24 static int AlarmCount = 0;
25 static u64 AlarmStatus = 0;
26 
27 struct alarm{
28  u16 target; //0x00
29  u16 time; //0x02
30  int id; //0x04
31  void *callback; //0x08
32  void *common; //0x0c
33  void *gp; //0x10
34 };
35 
36 static struct alarm alarms[MAX_ALARMS];
37 
38 //Function prototypes
39 static u32 CalculateTimeDiff(u32 t1, u32 t2);
40 static int InsertAlarm(u32 now, u32 target);
41 static s32 SetAlarmInternal(u16 time, void (*callback)(s32 dispatch_id, u16 time, void *common), void *common);
42 static void SetupTIM3(u16 ticks);
43 
44 static u32 CalculateTimeDiff(u32 t1, u32 t2)
45 {
46  return(t2 < t1 ? (0x10000 | t2) : t2);
47 }
48 
49 static int InsertAlarm(u32 now, u32 target)
50 {
51  int pos, i;
52 
53  pos = 0;
54  for(pos = 0; pos < AlarmCount; pos++)
55  {
57  { //Spot found. If it is not at the end of the list, move back the list.
58  for(i = AlarmCount - 1; i >= pos; i--)
59  alarms[i+1] = alarms[i];
60 
61  break;
62  }
63  }
64 
65  return pos;
66 }
67 
68 static s32 SetAlarmInternal(u16 time, void (*callback)(s32 dispatch_id, u16 time, void *common), void *common)
69 {
70  void *gp;
71  u32 target, now;
72  struct alarm *alarm;
73  int i, alarmID, pos;
74 
75  now = *T3_COUNT_W;
76  target = now + time;
77 
78  if(AlarmCount >= MAX_ALARMS)
79  return -1;
80 
81  alarmID = -1;
82  for(i = 0; i < MAX_ALARMS; i++)
83  {
84  if(((AlarmStatus >> i) & 1) == 0)
85  {
86  AlarmStatus |= (1 << i);
87  alarmID = i;
88  break;
89  }
90  }
91 
92  if(alarmID < 0)
93  return alarmID;
94 
95  gp = GetGP();
96  pos = InsertAlarm(now, target);
97  alarm = &alarms[pos];
98  alarm->time = time;
99  alarm->target = (u16)target;
100  alarm->id = alarmID;
101  alarm->gp = gp;
103  alarm->common = common;
104  AlarmCount++;
105  SetupTIM3(alarms[0].target);
106 
107  return alarm->id;
108 }
109 
111 {
112  u16 time;
113  s32 result;
114  int i, j;
115 
116  result = -1;
117  for(i = 0; i < AlarmCount; i++)
118  {
119  if(alarms[i].id == id)
120  {
121  if(alarms[i].target == *T3_COMP_W)
122  {
123  if(*R_EE_I_STAT & (1 << INTC_TIM3)) //Cannot release alarm that has already triggered.
124  return -1;
125  }
126 
127  time = alarms[i].time;
128  //Move forward list.
129  for(j = i; j < AlarmCount - 1; j++)
130  alarms[j] = alarms[j+1];
131 
132  --AlarmCount;
133  AlarmStatus &= ~(1 << id);
134 
135  if(i == 0) //If the first alarm was released, update timer comparator.
136  SetupTIM3(alarms[0].target);
137 
138  if(AlarmCount == 0) //Stop timer if there are no alarms left.
139  *T3_MODE_W = Tn_MODE(3,0,0,0,0,1,0,0,0,0);
140 
142  }
143  }
144 
145  EE_SYNC();
146  return result;
147 }
148 
149 s32 SetAlarm(u16 time, void (*callback)(s32 dispatch_id, u16 time, void *common), void *common)
150 {
151  s32 result;
152 
154  EE_SYNC();
155 
156  return result;
157 }
158 
159 static void SetupTIM3(u16 ticks)
160 {
161  *T3_COMP_W = ticks;
162  EE_SYNC();
163  *T3_MODE_W = Tn_MODE(3,0,0,0,0,1,1,0,1,0);
164 }
165 
166 //INTC 12 (TIM3) handler
167 void Intc12Handler(void)
168 {
169  struct alarm alarm;
170  void *gp;
171  int i;
172 
173  for(i = 0; i < AlarmCount; i++)
174  { //Attempt to find another alarm request that has a different target. Update TIM3's comparator.
175  if(alarms[i].target != alarms[0].target)
176  {
177  SetupTIM3(alarms[i].target);
178  break;
179  }
180  }
181 
182  do{
183  alarm = alarms[0];
184  AlarmCount--;
185  for(i = 0; i < AlarmCount; i++)
186  alarms[i] = alarms[i+1];
187 
188  gp = ChangeGP(alarm.gp);
189  AlarmStatus &= ~(1 << alarm.id);
191  SetGP(gp);
192 
193  if(AlarmCount <= 0)
194  break;
195  }while(alarms[0].target == alarm.target);
196 
197  if(AlarmCount <= 0) //If there are no further alarms, disable CMPE.
198  *T3_MODE_W = Tn_MODE(3,0,0,0,0,1,0,0,1,0);
199  else
200  SetupTIM3(alarms[0].target);
201 
202  ExitHandler();
203 }
#define gp
Definition: as_reg_compat.h:84
#define R_EE_I_STAT
Definition: ee_regs.h:461
void InvokeUserModeCallback(void *dispatcher, void *callback, int id, u32 target, void *common)
#define ExitHandler()
Definition: kernel.h:28
#define EE_SYNC()
Definition: kernel.h:31
void * ChangeGP(void *gp)
#define MAX_ALARMS
Definition: kernel.h:72
void SetGP(void *gp)
void * GetGP(void)
struct @29::@30 pos
u32 time
Definition: libmouse.c:37
s32 result
Definition: rpc_client.c:23
#define INTC_TIM3
Definition: alarm.c:19
#define T3_MODE_W
Definition: alarm.c:21
static int AlarmCount
Definition: alarm.c:24
#define USER_MODE_DISPATCHER
Definition: alarm.c:17
static u32 CalculateTimeDiff(u32 t1, u32 t2)
Definition: alarm.c:44
static s32 SetAlarmInternal(u16 time, void(*callback)(s32 dispatch_id, u16 time, void *common), void *common)
Definition: alarm.c:68
static struct alarm alarms[MAX_ALARMS]
Definition: alarm.c:36
static void SetupTIM3(u16 ticks)
Definition: alarm.c:159
void Intc12Handler(void)
Definition: alarm.c:167
#define T3_COMP_W
Definition: alarm.c:22
s32 SetAlarm(u16 time, void(*callback)(s32 dispatch_id, u16 time, void *common), void *common)
Definition: alarm.c:149
s32 ReleaseAlarm(s32 id)
Definition: alarm.c:110
static u64 AlarmStatus
Definition: alarm.c:25
#define T3_COUNT_W
Definition: alarm.c:20
static int InsertAlarm(u32 now, u32 target)
Definition: alarm.c:49
Definition: alarm.c:27
void * callback
Definition: alarm.c:31
int id
Definition: alarm.c:30
u16 time
Definition: alarm.c:29
u16 target
Definition: alarm.c:28
void * common
Definition: alarm.c:32
void * gp
Definition: alarm.c:33
signed int s32
Definition: tamtypes.h:58
unsigned int u32
Definition: tamtypes.h:30
unsigned short u16
Definition: tamtypes.h:24
unsigned long u64
Definition: tamtypes.h:34
#define Tn_MODE(CLKS, GATE, GATS, GATM, ZRET, CUE, CMPE, OVFE, EQUF, OVFF)
Definition: timer.h:42