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