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