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