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