PS2SDK
PS2 Homebrew Libraries
timer.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
16 #include <kernel.h>
17 #include <timer.h>
18 #include <string.h>
19 #include <mipscopaccess.h>
20 
21 #define TIMER_MODE_START 0x00000001
22 #define TIMER_MODE_HANDLER 0x00000002
23 
24 typedef struct counter_struct_
25 {
26  struct counter_struct_ *timer_next;
27  struct counter_struct_ *timer_previous;
28  vu32 timer_key;
29  u32 timer_mode;
30  u64 timer_base_time;
31  u64 timer_base_count;
32  u64 timer_schedule;
33  timer_alarm_handler_t callback_handler;
34  void *gp_value;
35  void *callback_handler_arg;
36  u32 padding[3];
37 } counter_struct_t __attribute__((aligned(64)));
38 
40 {
41  vu64 timer_handled_count;
42  s32 intc_handler;
43  vu32 timer_counter_total;
44  vu32 timer_counter_used;
45  counter_struct_t *timer_counter_buf_free;
46  counter_struct_t *timer_counter_buf_alarm;
47  vs32 current_handling_timer_id;
49 
50 #define PTR_TO_TIMER_ID(ptr_) ((s32)((((uiptr)(ptr_)) << 4) | ((ptr_)->timer_key)))
51 #define TIMER_ID_TO_PTR(id_) ((counter_struct_t *)((((uiptr)(id_)) >> 10) << 6))
52 #define TIMER_ID_IS_VALID(id_) ((TIMER_ID_TO_PTR(id_) != NULL) && ((siptr)(id_) >= 0) && (((uiptr)(id_) & 0x3FF) == ((TIMER_ID_TO_PTR(id_))->timer_key)))
53 
54 // The following is defined in timer_alarm.h
55 extern void ForTimer_InitAlarm(void);
56 
57 extern void SetT2(volatile void *ptr, u32 val);
58 extern void SetT2_COUNT(u32 val);
59 extern void SetT2_MODE(u32 val);
60 extern void SetT2_COMP(u32 val);
61 extern void InsertAlarm_ForTimer(counter_struct_t *timer_link);
62 extern counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink);
63 extern s32 TimerHandler_callback(s32 cause, void *arg, void *addr);
64 
65 #define COUNTER_COUNT 128
66 
67 #ifdef F_timer_data
69 counter_struct_t g_CounterBuf[COUNTER_COUNT] __attribute__((aligned(64)));
70 #else
71 extern timer_ee_global_struct g_Timer;
72 extern counter_struct_t g_CounterBuf[COUNTER_COUNT] __attribute__((aligned(64)));
73 #endif
74 
75 #ifdef F__ps2sdk_init_timer
76 void __attribute__((weak)) _ps2sdk_init_timer_impl(void);
77 __attribute__((weak)) void _ps2sdk_init_timer(void)
78 {
79  // cppcheck-suppress knownConditionTrueFalse
80  if (&_ps2sdk_init_timer_impl)
81  {
82  _ps2sdk_init_timer_impl();
83  }
84 }
85 #endif
86 
87 #ifdef F__ps2sdk_deinit_timer
88 void __attribute__((weak)) _ps2sdk_deinit_timer_impl(void);
89 __attribute__((weak)) void _ps2sdk_deinit_timer(void)
90 {
91  // cppcheck-suppress knownConditionTrueFalse
92  if (&_ps2sdk_deinit_timer_impl)
93  {
94  _ps2sdk_deinit_timer_impl();
95  }
96 }
97 #endif
98 
99 #ifdef F_SetT2
100 void SetT2(volatile void *ptr, u32 val)
101 {
102  ee_kmode_enter();
103  *((volatile u32 *)ptr) = val;
104  ee_kmode_exit();
105 }
106 #endif
107 
108 #ifdef F_SetT2_COUNT
109 void SetT2_COUNT(u32 val)
110 {
111  SetT2((volatile void *)K_T2_COUNT, val);
112 }
113 #endif
114 
115 #ifdef F_SetT2_MODE
116 void SetT2_MODE(u32 val)
117 {
118  SetT2((volatile void *)K_T2_MODE, val);
119 }
120 #endif
121 
122 #ifdef F_SetT2_COMP
123 void SetT2_COMP(u32 val)
124 {
125  SetT2((volatile void *)K_T2_COMP, val);
126 }
127 #endif
128 
129 #ifdef F_InitTimer
130 __attribute__((weak)) s32 InitTimer(s32 in_mode)
131 {
132  s32 handler;
133  u32 oldintr;
134  u32 mode;
135 
136  if (g_Timer.intc_handler > 0)
137  {
138  return 0x80008001; // EINIT
139  }
140  g_Timer.timer_handled_count = 0;
141  g_Timer.timer_counter_used = 0;
142  g_Timer.timer_counter_total = 1;
143  g_Timer.current_handling_timer_id = -1;
144  memset(g_CounterBuf, 0, sizeof(g_CounterBuf));
145  g_Timer.timer_counter_buf_free = &g_CounterBuf[0];
146  for (u32 i = 0; i < ((sizeof(g_CounterBuf) / sizeof(g_CounterBuf[0])) - 1); i += 1)
147  {
148  g_CounterBuf[i].timer_next = &g_CounterBuf[i + 1];
149  }
150  g_CounterBuf[(sizeof(g_CounterBuf) / sizeof(g_CounterBuf[0])) - 1].timer_next = NULL;
151  g_Timer.timer_counter_buf_alarm = NULL;
152  ForTimer_InitAlarm();
153  handler = AddIntcHandler2(INTC_TIM2, TimerHandler_callback, 0, NULL);
154  if (handler < 0)
155  {
156  return 0x80009021; // EINT_HANDLER
157  }
158  g_Timer.intc_handler = handler;
159  oldintr = DIntr();
160  mode = ((*T2_MODE) & (~0x3)) | in_mode;
161  mode |= (1 << 9) | (1 << 8);
162  if ((mode & (1 << 7)) == 0)
163  {
164  mode |= (1 << 7);
165  mode |= (1 << 11) | (1 << 10);
166  SetT2_COUNT(0);
167  SetT2_COMP(0xFFFF);
168  }
169  SetT2_MODE(mode);
170  EnableIntc(INTC_TIM2);
171  if (oldintr != 0)
172  {
173  EIntr();
174  }
175  return 0;
176 }
177 #endif
178 
179 #ifdef F_EndTimer
180 __attribute__((weak)) s32 EndTimer(void)
181 {
182  u32 oldintr;
183 
184  if (g_Timer.intc_handler < 0)
185  {
186  return 0x80008001; // EINIT
187  }
188  if (g_Timer.timer_counter_used != 0)
189  {
190  return 0x80000010; // EBUSY
191  }
192  oldintr = DIntr();
193  if (RemoveIntcHandler(INTC_TIM2, g_Timer.intc_handler) == 0)
194  {
195  DisableIntc(INTC_TIM2);
196  SetT2_MODE((1 << 11) | (1 << 10));
197  SetT2_COUNT(0);
198  }
199  g_Timer.timer_handled_count = 0;
200  g_Timer.intc_handler = -1;
201  if (oldintr != 0)
202  {
203  EIntr();
204  }
205  return 0;
206 }
207 #endif
208 
209 #ifdef F_GetTimerPreScaleFactor
210 s32 GetTimerPreScaleFactor(void)
211 {
212  if (g_Timer.intc_handler < 0)
213  {
214  return 0x80008001; // EINIT
215  }
216  return (*T2_MODE) & 3;
217 }
218 #endif
219 
220 #ifdef F_StartTimerSystemTime
221 
227 __attribute__((weak)) s32 StartTimerSystemTime(void)
228 {
229  u32 oldintr;
230 
231  oldintr = DIntr();
232  if (((*T2_MODE) & (1 << 7)) != 0)
233  {
234  if (oldintr != 0)
235  {
236  EIntr();
237  }
238  return 1;
239  }
240  else
241  {
242  SetT2_MODE(((*T2_MODE) & (~((1 << 11) | (1 << 10)))) | (1 << 7));
243  SetNextComp(iGetTimerSystemTime());
244  if (oldintr != 0)
245  {
246  EIntr();
247  }
248  return 0;
249  }
250 }
251 #endif
252 
253 #ifdef F_StopTimerSystemTime
254 
260 __attribute__((weak)) s32 StopTimerSystemTime(void)
261 {
262  u32 oldintr;
263 
264  oldintr = DIntr();
265  if (((*T2_MODE) & (1 << 7)) != 0)
266  {
267  SetT2_MODE((*T2_MODE) & (~((1 << 11) | (1 << 10))));
268  if (oldintr != 0)
269  {
270  EIntr();
271  }
272  return 1;
273  }
274  else
275  {
276  if (oldintr != 0)
277  {
278  EIntr();
279  }
280  return 0;
281  }
282 }
283 #endif
284 
285 #ifdef F_SetNextComp
286 #define CLOCKS_GAP 0x200 // For assuring the timer interrupt is triggered
287 void SetNextComp(u64 time_now)
288 {
289  u64 current_schedule, next_schedule;
290  counter_struct_t *timer_current;
291 
292  if (g_Timer.current_handling_timer_id >= 0)
293  {
294  return;
295  }
296  timer_current = g_Timer.timer_counter_buf_alarm;
297  if (timer_current == NULL)
298  {
299  SetT2_COMP(0);
300  SetT2_MODE((*T2_MODE) & (~(1 << 11)));
301  return;
302  }
303  current_schedule = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
304  timer_current = timer_current->timer_next;
305 
306  // Grouping the timers that are so close to each other, to reduce the number of interrupts
307  while (timer_current != NULL)
308  {
309  next_schedule = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
310  if (next_schedule < (current_schedule + CLOCKS_GAP))
311  {
312  current_schedule = next_schedule;
313  }
314  else
315  {
316  break;
317  }
318  timer_current = timer_current->timer_next;
319  }
320  if (current_schedule < (time_now + CLOCKS_GAP))
321  {
322  SetT2_COMP((*T2_COUNT) + (CLOCKS_GAP >> (((*T2_MODE) & 3) << 2)));
323  SetT2_MODE((*T2_MODE) & (~(1 << 11)));
324  }
325  else
326  {
327  SetT2_MODE((*T2_MODE) & (~(1 << 11)));
328  SetT2_COMP(current_schedule >> (((*T2_MODE) & 3) << 2));
329  }
330 }
331 #endif
332 
333 #ifdef F_InsertAlarm_ForTimer
334 void InsertAlarm_ForTimer(counter_struct_t *timer_link)
335 {
336  counter_struct_t *timer_current;
337  counter_struct_t *timer_next;
338  u64 abs_cmp;
339 
340  abs_cmp = timer_link->timer_schedule + timer_link->timer_base_time - timer_link->timer_base_count;
341  timer_current = NULL;
342  timer_next = g_Timer.timer_counter_buf_alarm;
343  while (timer_next != NULL)
344  {
345  u64 target_cmp = timer_next->timer_schedule + timer_next->timer_base_time - timer_next->timer_base_count;
346  if (abs_cmp < target_cmp)
347  {
348  break;
349  }
350  timer_current = timer_next;
351  timer_next = timer_next->timer_next;
352  }
353  timer_link->timer_previous = timer_current;
354  timer_link->timer_next = timer_next;
355  if (timer_next != NULL)
356  {
357  timer_next->timer_previous = timer_link;
358  }
359  if (timer_current != NULL)
360  {
361  timer_current->timer_next = timer_link;
362  }
363  else
364  {
365  g_Timer.timer_counter_buf_alarm = timer_link;
366  }
367 }
368 #endif
369 
370 #ifdef F_UnlinkAlarm_ForTimer
371 counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink)
372 {
373  counter_struct_t *timer_next;
374 
375  timer_next = timer_unlink->timer_next;
376  if (timer_unlink->timer_previous)
377  {
378  timer_unlink->timer_previous->timer_next = timer_next;
379  }
380  else
381  {
382  g_Timer.timer_counter_buf_alarm = timer_unlink->timer_next;
383  }
384  if (timer_next != NULL)
385  {
386  timer_next->timer_previous = timer_unlink->timer_previous;
387  }
388  timer_unlink->timer_previous = NULL;
389  return timer_next;
390 }
391 #endif
392 
393 #ifdef F_TimerHandler_callback
394 static inline u64 ApplyOverflow(void)
395 {
396  u64 timer_system_time_now;
397  u32 mode;
398  u32 low;
399 
400  low = *T2_COUNT;
401  mode = *T2_MODE;
402  if ((mode & (1 << 11)) != 0)
403  {
404  g_Timer.timer_handled_count += 1;
405  SetT2_MODE(mode & (~(1 << 10)));
406  low = *T2_COUNT;
407  }
408  timer_system_time_now = (g_Timer.timer_handled_count << 16) | low;
409  timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
410  return timer_system_time_now;
411 }
412 
413 s32 TimerHandler_callback(s32 cause, void *arg, void *addr)
414 {
415  counter_struct_t *timer_current;
416  counter_struct_t *timer_next;
417  u64 target_cmp;
418  u64 abs_cmp;
419  u32 timer_id;
420  u64 timer_schedule_next;
421 
422  if (((*T2_MODE) & (1 << 10)) != 0)
423  {
424  timer_current = g_Timer.timer_counter_buf_alarm;
425  while (timer_current != NULL)
426  {
427  target_cmp = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
428  abs_cmp = ApplyOverflow();
429  if (abs_cmp < target_cmp)
430  {
431  break;
432  }
433  timer_next = UnlinkAlarm_ForTimer(timer_current);
434  timer_id = PTR_TO_TIMER_ID(timer_current);
435  g_Timer.current_handling_timer_id = timer_id;
436  SetGP(timer_current->gp_value);
437  timer_schedule_next = timer_current->callback_handler(
438  timer_id,
439  timer_current->timer_schedule,
440  (abs_cmp + timer_current->timer_base_count) - timer_current->timer_base_time,
441  timer_current->callback_handler_arg,
442  addr);
443  if (timer_schedule_next == 0)
444  {
445  timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
446  }
447  else if (timer_schedule_next == (u64)-1)
448  {
449  timer_current->timer_next = g_Timer.timer_counter_buf_free;
450  g_Timer.timer_counter_buf_free = timer_current;
451  timer_current->timer_key = 0;
452  timer_current->timer_mode = 0;
453  g_Timer.timer_counter_used -= 1;
454  }
455  else
456  {
457  if (timer_schedule_next < 0x3999)
458  {
459  timer_schedule_next = 0x3999;
460  }
461  timer_current->timer_schedule += timer_schedule_next;
462  InsertAlarm_ForTimer(timer_current);
463  }
464  timer_current = timer_next;
465  }
466  }
467  g_Timer.current_handling_timer_id = -1;
468  SetNextComp(ApplyOverflow());
469  ApplyOverflow();
470  ExitHandler();
471  return 0;
472 }
473 #endif
474 
475 #ifdef F_iGetTimerSystemTime
476 
484 u64 iGetTimerSystemTime(void)
485 {
486  u64 timer_handled_count, timer_system_time_now;
487  u32 low, mode;
488 
489  low = *T2_COUNT;
490  mode = *T2_MODE;
491  timer_handled_count = g_Timer.timer_handled_count;
492  if ((mode & (1 << 11)) != 0)
493  {
494  timer_handled_count += 1;
495  low = *T2_COUNT;
496  }
497  timer_system_time_now = (timer_handled_count << 16) | low;
498  timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
499  return timer_system_time_now;
500 }
501 
502 void _ps2sdk_init_timer_impl(void)
503 {
504  InitTimer(2);
505  StartTimerSystemTime();
506 }
507 
508 void _ps2sdk_deinit_timer_impl(void)
509 {
510  StopTimerSystemTime();
511  EndTimer();
512 }
513 #endif
514 
515 #ifdef F_GetTimerSystemTime
516 
525 u64 GetTimerSystemTime(void)
526 {
527  u32 oldintr;
528  u64 ret;
529 
530  oldintr = DIntr();
531  ret = iGetTimerSystemTime();
532  if (oldintr != 0)
533  {
534  EIntr();
535  }
536  return ret;
537 }
538 #endif
539 
540 #ifdef F_iAllocTimerCounter
541 s32 iAllocTimerCounter(void)
542 {
543  counter_struct_t *timer_current;
544 
545  timer_current = g_Timer.timer_counter_buf_free;
546  if (timer_current == NULL)
547  {
548  return 0x80008005; // ETIMER
549  }
550  g_Timer.timer_counter_buf_free = timer_current->timer_next;
551  g_Timer.timer_counter_used += 1;
552  timer_current->timer_mode = 0;
553  timer_current->callback_handler = NULL;
554  timer_current->timer_base_count = 0;
555  g_Timer.timer_counter_total += 1;
556  timer_current->timer_key = ((g_Timer.timer_counter_total << 1) & 0x3FE) | 1;
557  return PTR_TO_TIMER_ID(timer_current);
558 }
559 #endif
560 
561 #ifdef F_AllocTimerCounter
562 s32 AllocTimerCounter(void)
563 {
564  u32 oldintr;
565  s32 ret;
566 
567  oldintr = DIntr();
568  ret = iAllocTimerCounter();
569  if (oldintr != 0)
570  {
571  EIntr();
572  }
573  return ret;
574 }
575 #endif
576 
577 #ifdef F_iFreeTimerCounter
578 s32 iFreeTimerCounter(s32 id)
579 {
580  counter_struct_t *timer_current;
581 
582  timer_current = TIMER_ID_TO_PTR(id);
583  if (!TIMER_ID_IS_VALID(id))
584  {
585  return 0x80008002; // EID
586  }
587  if (g_Timer.current_handling_timer_id == id)
588  {
589  return 0x80000010; // EBUSY
590  }
591  if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
592  {
593  UnlinkAlarm_ForTimer(timer_current);
594  }
595  timer_current->timer_key = 0;
596  timer_current->timer_mode = 0;
597  timer_current->timer_next = g_Timer.timer_counter_buf_free;
598  g_Timer.timer_counter_buf_free = timer_current;
599  g_Timer.timer_counter_used -= 1;
600  return 0;
601 }
602 #endif
603 
604 #ifdef F_FreeTimerCounter
605 s32 FreeTimerCounter(s32 id)
606 {
607  u32 oldintr;
608  s32 ret;
609 
610  oldintr = DIntr();
611  ret = iFreeTimerCounter(id);
612  if (oldintr != 0)
613  {
614  EIntr();
615  }
616  return ret;
617 }
618 #endif
619 
620 #ifdef F_iGetTimerUsedUnusedCounters
621 s32 iGetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
622 {
623  if (g_Timer.intc_handler < 0)
624  {
625  return 0x80008001; // EINIT
626  }
627  if (used_counters != NULL)
628  {
629  *used_counters = g_Timer.timer_counter_used;
630  }
631  if (unused_counters != NULL)
632  {
633  *unused_counters = (sizeof(g_CounterBuf) / sizeof(g_CounterBuf[0])) - g_Timer.timer_counter_used;
634  }
635  return 0;
636 }
637 #endif
638 
639 #ifdef F_GetTimerUsedUnusedCounters
640 s32 GetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
641 {
642  u32 oldintr;
643  s32 ret;
644 
645  oldintr = DIntr();
646  ret = iGetTimerUsedUnusedCounters(used_counters, unused_counters);
647  if (oldintr != 0)
648  {
649  EIntr();
650  }
651  return ret;
652 }
653 #endif
654 
655 #ifdef F_iStartTimerCounter
656 s32 iStartTimerCounter(s32 id)
657 {
658  counter_struct_t *timer_current;
659  u64 timer_system_time_now;
660 
661  timer_current = TIMER_ID_TO_PTR(id);
662  if (!TIMER_ID_IS_VALID(id))
663  {
664  return 0x80008002; // EID
665  }
666  if (g_Timer.current_handling_timer_id == id)
667  {
668  return 0x80000010; // EBUSY
669  }
670  if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
671  {
672  return 1;
673  }
674  timer_system_time_now = iGetTimerSystemTime();
675  timer_current->timer_base_time = timer_system_time_now;
676  timer_current->timer_mode |= TIMER_MODE_START;
677  if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
678  {
679  InsertAlarm_ForTimer(timer_current);
680  SetNextComp(timer_system_time_now);
681  }
682  return 0;
683 }
684 #endif
685 
686 #ifdef F_StartTimerCounter
687 s32 StartTimerCounter(s32 id)
688 {
689  u32 oldintr;
690  s32 ret;
691 
692  oldintr = DIntr();
693  ret = iStartTimerCounter(id);
694  if (oldintr != 0)
695  {
696  EIntr();
697  }
698  return ret;
699 }
700 #endif
701 
702 #ifdef F_iStopTimerCounter
703 s32 iStopTimerCounter(s32 id)
704 {
705  counter_struct_t *timer_current;
706  u64 timer_system_time_now;
707 
708  timer_current = TIMER_ID_TO_PTR(id);
709  if (!TIMER_ID_IS_VALID(id))
710  {
711  return 0x80008002; // EID
712  }
713  if (g_Timer.current_handling_timer_id == id)
714  {
715  return 0x80000010; // EBUSY
716  }
717  if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
718  {
719  return 0;
720  }
721  timer_system_time_now = iGetTimerSystemTime();
722  timer_current->timer_base_count += timer_system_time_now - timer_current->timer_base_time;
723  timer_current->timer_mode &= ~TIMER_MODE_START;
724  if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
725  {
726  UnlinkAlarm_ForTimer(timer_current);
727  SetNextComp(timer_system_time_now);
728  }
729  return 1;
730 }
731 #endif
732 
733 #ifdef F_StopTimerCounter
734 s32 StopTimerCounter(s32 id)
735 {
736  u32 oldintr;
737  s32 ret;
738 
739  oldintr = DIntr();
740  ret = iStopTimerCounter(id);
741  if (oldintr != 0)
742  {
743  EIntr();
744  }
745  return ret;
746 }
747 #endif
748 
749 #ifdef F_SetTimerCount
750 u64 SetTimerCount(s32 id, u64 timer_count)
751 {
752  counter_struct_t *timer_current;
753  u32 oldintr;
754  u64 ret;
755  u64 timer_system_time_now;
756 
757  timer_current = TIMER_ID_TO_PTR(id);
758  oldintr = DIntr();
759  if ((!TIMER_ID_IS_VALID(id)) || g_Timer.current_handling_timer_id == id)
760  {
761  if (oldintr != 0)
762  {
763  EIntr();
764  }
765  return -1;
766  }
767  ret = timer_current->timer_base_count;
768  if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
769  {
770  timer_system_time_now = iGetTimerSystemTime();
771  ret += timer_system_time_now - timer_current->timer_base_time;
772  timer_current->timer_base_count = timer_count;
773  timer_current->timer_base_time = timer_system_time_now;
774  }
775  else
776  {
777  timer_current->timer_base_count = timer_count;
778  }
779  if (oldintr != 0)
780  {
781  EIntr();
782  }
783  return ret;
784 }
785 #endif
786 
787 #ifdef F_iGetTimerBaseTime
788 u64 iGetTimerBaseTime(s32 id)
789 {
790  counter_struct_t *timer_current;
791 
792  timer_current = TIMER_ID_TO_PTR(id);
793  if (!TIMER_ID_IS_VALID(id))
794  {
795  return -1;
796  }
797  if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
798  {
799  return 0;
800  }
801  return timer_current->timer_base_time - timer_current->timer_base_count;
802 }
803 #endif
804 
805 #ifdef F_GetTimerBaseTime
806 u64 GetTimerBaseTime(s32 id)
807 {
808  u32 oldintr;
809  u64 ret;
810 
811  oldintr = DIntr();
812  ret = iGetTimerBaseTime(id);
813  if (oldintr != 0)
814  {
815  EIntr();
816  }
817  return ret;
818 }
819 #endif
820 
821 #ifdef F_iGetTimerCount
822 u64 iGetTimerCount(s32 id)
823 {
824  u64 ret;
825  counter_struct_t *timer_current;
826 
827  timer_current = TIMER_ID_TO_PTR(id);
828  if (!TIMER_ID_IS_VALID(id))
829  {
830  return -1;
831  }
832  ret = timer_current->timer_base_count;
833  if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
834  {
835  ret += iGetTimerSystemTime() - timer_current->timer_base_time;
836  }
837  return ret;
838 }
839 #endif
840 
841 #ifdef F_GetTimerCount
842 u64 GetTimerCount(s32 id)
843 {
844  u32 oldintr;
845  u64 ret;
846 
847  oldintr = DIntr();
848  ret = iGetTimerCount(id);
849  if (oldintr != 0)
850  {
851  EIntr();
852  }
853  return ret;
854 }
855 #endif
856 
857 #ifdef F_iSetTimerHandler
858 s32 iSetTimerHandler(s32 id, u64 scheduled_time, timer_alarm_handler_t callback_handler, void *arg)
859 {
860  counter_struct_t *timer_current;
861 
862  timer_current = TIMER_ID_TO_PTR(id);
863  if (!TIMER_ID_IS_VALID(id))
864  {
865  return 0x80008002; // EID
866  }
867  if (g_Timer.current_handling_timer_id == id)
868  {
869  return 0x80000010; // EBUSY
870  }
871  if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
872  {
873  UnlinkAlarm_ForTimer(timer_current);
874  }
875  timer_current->callback_handler = callback_handler;
876  if (callback_handler == NULL)
877  {
878  timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
879  }
880  else
881  {
882  timer_current->timer_schedule = scheduled_time;
883  timer_current->timer_mode |= TIMER_MODE_HANDLER;
884  timer_current->gp_value = GetGP();
885  timer_current->callback_handler_arg = arg;
886  if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
887  {
888  InsertAlarm_ForTimer(timer_current);
889  }
890  }
891  SetNextComp(iGetTimerSystemTime());
892  return 0;
893 }
894 #endif
895 
896 #ifdef F_SetTimerHandler
897 s32 SetTimerHandler(s32 id, u64 scheduled_time, timer_alarm_handler_t callback_handler, void *arg)
898 {
899  u32 oldintr;
900  s32 ret;
901 
902  oldintr = DIntr();
903  ret = iSetTimerHandler(id, scheduled_time, callback_handler, arg);
904  if (oldintr != 0)
905  {
906  EIntr();
907  }
908  return ret;
909 }
910 #endif
911 
912 #ifdef F_TimerBusClock2USec
913 void TimerBusClock2USec(u64 clocks, u32 *seconds_result, u32 *microseconds_result)
914 {
915  u32 seconds;
916 
917  seconds = (u32)(clocks / kBUSCLK);
918  if (seconds_result != NULL)
919  {
920  *seconds_result = seconds;
921  }
922  if (microseconds_result != NULL)
923  {
924  *microseconds_result = (u32)(1000 * 1000 * (clocks - (((s64)(s32)((kBUSCLK * (u64)seconds) >> 32) << 32) | (u32)(kBUSCLK * seconds))) / kBUSCLK);
925  }
926 }
927 #endif
928 
929 #ifdef F_TimerUSec2BusClock
930 u64 TimerUSec2BusClock(u32 seconds, u32 microseconds)
931 {
932  return (seconds * kBUSCLK) + (microseconds * (u64)kBUSCLK / (1000 * 1000));
933 }
934 #endif
935 
936 #ifdef F_TimerBusClock2Freq
937 float TimerBusClock2Freq(s64 clocks)
938 {
939  return (float)kBUSCLK / (float)clocks;
940 }
941 #endif
942 
943 #ifdef F_TimerFreq2BusClock
944 u64 TimerFreq2BusClock(float timer_frequency)
945 {
946  return (u64)((float)kBUSCLK / timer_frequency);
947 }
948 #endif
949 
950 #ifdef F_cpu_ticks
951 u32 cpu_ticks(void)
952 {
953  u32 out;
954 
955  out = get_mips_cop_reg(0, COP0_REG_Count);
956  return out;
957 }
958 #endif
kernel.h
counter_struct_
Definition: timer.c:24
COP0_REG_Count
@ COP0_REG_Count
Definition: mipscopaccess.h:30
mipscopaccess.h
timer.h
__attribute__
Definition: gif_registers.h:38
timer_ee_global_struct_
Definition: timer.c:39