5#include "irx_imports.h"
9IRX_ID(
"Timer_Manager", 2, 2);
17 __asm__ volatile("mfc0 %0, " #reg \
22#define mfc0(reg) _mfc0(reg)
24#ifdef BUILDING_TIMRMANP
31 TMR0_COUNT = 0xBF801100,
32 TMR1_COUNT = 0xBF801110,
33 TMR2_COUNT = 0xBF801120,
35 TMR3_COUNT = 0xBF801480,
36 TMR4_COUNT = 0xBF801490,
37 TMR5_COUNT = 0xBF8014A0,
43 TMR_IN_PS1_MODE = 0xBF801450,
45 TMR_HOLD_REG = 0xBF8014B0,
46 TMR_HOLD_MODE = 0xBF8014C0,
49 TMR_CTRL_ZERO_RETURN = 1 << 3,
52 TMR_CTRL_CMP_IRQ_ENABLE = 1 << 4,
53 TMR_CTRL_OVFL_IRQ_ENABLE = 1 << 5,
54 TMR_CTRL_IRQ_ENABLE = 1 << 11,
55 TMR_CTRL_IRQ_REPEAT = 1 << 6,
57 TMR_CTRL_EXT_SIGNAL = 1 << 8,
60 TMR_CTRL_CMP_IRQ = 1 << 11,
61 TMR_CTRL_OVFL_IRQ = 1 << 12,
78 unsigned int (*timeup_handler)(
void *);
80 unsigned int (*overflow_handler)(
void *);
81 void *overflow_common;
84static struct Timer sTimerTable[NUM_TIMERS] = {
131static int sIndexMap[NUM_TIMERS] = {
142u32 timer0() {
return _lh(TMR0_COUNT); }
143u32 timer1() {
return _lh(TMR1_COUNT); }
144u32 timer2() {
return _lh(TMR2_COUNT); }
146u32 timer3() {
return _lw(TMR3_COUNT); }
147u32 timer4() {
return _lw(TMR4_COUNT); }
148u32 timer5() {
return _lw(TMR5_COUNT); }
151static u32 (*sTimerCountFun[NUM_TIMERS])() = {
162int _start(
int argc,
char **argv)
167#ifdef BUILDING_TIMRMANP
169 if ((_lw(TMR_IN_PS1_MODE) & 8) == 0) {
170 return MODULE_NO_RESIDENT_END;
175 return MODULE_NO_RESIDENT_END;
178 if ((_lw(TMR_IN_PS1_MODE) & 8) != 0) {
179 return MODULE_NO_RESIDENT_END;
183 for (
int i = 0; i < NUM_TIMERS; i++) {
184 sTimerTable[i].users = 0;
187 ret = RegisterLibraryEntries(&_exp_timrman);
189 return MODULE_NO_RESIDENT_END;
192 return MODULE_RESIDENT_END;
195void *GetTimersTable()
200int AllocHardTimer(
int source,
int size,
int prescale)
206 return KE_ILLEGAL_CONTEXT;
211 for (
int i = 0; i < NUM_TIMERS; i++) {
212 timer = &sTimerTable[sIndexMap[i]];
213 if (timer->users != 0) {
217 if ((timer->sources & source) == 0) {
221 if (timer->size != size || timer->max_prescale < prescale) {
225 timid = ((sIndexMap[i] + 1) << 28) | (timer->addr >> 4);
226 SetTimerMode(timid, 0);
230 timer->ctrl_config = 0;
231 timer->timeup_flags = 0;
232 timer->overflow_flags = 0;
233 timer->timeup_handler = 0;
234 timer->overflow_handler = 0;
244int ReferHardTimer(
int source,
int size,
int mode,
int modemask)
250 return KE_ILLEGAL_CONTEXT;
256 for (
int i = 0; i < NUM_TIMERS; i++) {
257 timer = &sTimerTable[i];
258 if (timer->users == 0) {
262 if (timer->mode == 0) {
266 if ((timer->sources & source) == 0) {
270 if (timer->size != size || (timer->mode & modemask) != mode) {
278 return ((i << 28) + 1) | (timer->addr >> 4);
285int FreeHardTimer(
int timid)
288 u32 timer_idx = (timid >> 28) - 1;
292 return KE_ILLEGAL_CONTEXT;
295 timer = &sTimerTable[timer_idx];
300 return KE_ILLEGAL_TIMERID;
305 if ((timer->users << 24) != 0) {
306 SetTimerMode(timid, 0);
308 timer->ctrl_config = 0;
309 timer->timeup_flags = 0;
310 timer->overflow_flags = 0;
311 timer->timeup_handler = 0;
312 timer->overflow_handler = 0;
314 if (timer->has_irq_handler) {
318 timer->has_irq_handler = 0;
325void SetTimerMode(
int timid,
int mode)
327 u32 timer = (timid >> 28) - 1;
328 if (timer >= NUM_TIMERS) {
332 sTimerTable[timer].mode = mode;
333 _sh(mode, (timid << 4) + 4);
336u32 GetTimerMode(
int timid)
338 u32 timer = (timid >> 28) - 1;
339 if (timer >= NUM_TIMERS) {
340 return KE_ILLEGAL_TIMERID;
343 return sTimerTable[timer].mode;
346u32 GetTimerStatus(
int timid)
348 return _lh((timid << 4) + 4);
351void SetTimerCounter(
int timid, u32
count)
353 u32 addr = timid << 4;
362u32 GetTimerCounter(
int timid)
364 u32 addr = timid << 4;
373void SetTimerCompare(
int timid, u32 compare)
375 u32 addr = timid << 4;
378 _sw(compare, addr + 8);
380 _sh(compare, addr + 8);
384u32 GetTimerCompare(
int timid)
386 u32 addr = timid << 4;
389 return _lw(addr + 8);
391 return _lh(addr + 8);
395void SetHoldMode(
int holdnum,
int mode)
397#ifndef BUILDING_TIMRMANP
398 u32 hold = _lw(TMR_HOLD_MODE);
399 hold &= ~(0xF << (4 * holdnum));
400 hold |= (mode & 0xF) << (4 * holdnum);
401 _sw(TMR_HOLD_MODE, hold);
405u32 GetHoldMode(
int holdnum)
407#ifdef BUILDING_TIMRMANP
410 return _lw(TMR_HOLD_MODE >> (holdnum * 4)) & 0xF;
414u32 GetHoldReg(
int holdnum)
416#ifdef BUILDING_TIMRMANP
419 return _lw(TMR_HOLD_REG + (holdnum * 4));
423int GetHardTimerIntrCode(
int timid)
425 u32 timer = (timid >> 28) - 1;
426 if (timer >= NUM_TIMERS) {
427 return KE_ILLEGAL_TIMERID;
430 return sTimerTable[timer].irq;
434u32 (*GetTimerReadFunc(
int timid))()
436 u32 timer = (timid >> 28) - 1;
437 if (timer >= NUM_TIMERS) {
438 return (
void *)KE_ILLEGAL_TIMERID;
441 return sTimerCountFun[timer];
445int SetTimerHandler(
int timid,
unsigned long comparevalue,
unsigned int (*timeuphandler)(
void *),
void *common)
449 u32 timer_idx = (timid >> 28) - 1;
450 if (timer_idx >= NUM_TIMERS) {
451 return KE_ILLEGAL_TIMERID;
455 timer = &sTimerTable[timer_idx];
457 if (timer->mode != 0) {
462 timer->compare_value = comparevalue;
463 timer->timeup_handler = timeuphandler;
464 timer->timeup_common = common;
466 timer->timeup_flags = TMR_CTRL_ZERO_RETURN | TMR_CTRL_CMP_IRQ_ENABLE | TMR_CTRL_IRQ_REPEAT;
468 timer->timeup_flags = 0;
475int SetOverflowHandler(
int timid,
unsigned int (*handler)(
void *),
void *common)
480 u32 timer_idx = (timid >> 28) - 1;
481 if (timer_idx >= NUM_TIMERS) {
482 return KE_ILLEGAL_TIMERID;
486 timer = &sTimerTable[timer_idx];
488 if (timer->mode != 0) {
493 timer->overflow_handler = handler;
494 timer->overflow_common = common;
495 if (handler != NULL) {
496 timer->overflow_flags = TMR_CTRL_OVFL_IRQ_ENABLE | TMR_CTRL_IRQ_REPEAT;
498 timer->overflow_flags = 0;
504static int irqHandler(
void *arg)
506 struct Timer *timer = arg;
510 u32 ctrl = _lh(timer->addr + TMR_CTRL_OFFSET);
511 if (ctrl & TMR_CTRL_OVFL_IRQ) {
512 cb_ret = timer->overflow_handler(timer->overflow_common);
518 if (ctrl & TMR_CTRL_CMP_IRQ) {
519 cb_ret = timer->timeup_handler(timer->timeup_common);
523 if (timer->size == 16) {
524 _sh(cb_ret, timer->addr + TMR_CMP_OFFSET);
526 _sw(cb_ret, timer->addr + TMR_CMP_OFFSET);
531 if (stop || timer->mode == 0) {
533 _sh(0, timer->addr + TMR_CTRL_OFFSET);
540int SetupHardTimer(
int timid,
int source,
int mode,
int prescale)
542 u32 timer_idx = (timid >> 28) - 1;
548 return KE_ILLEGAL_CONTEXT;
551 if (timer_idx >= NUM_TIMERS) {
552 return KE_ILLEGAL_TIMERID;
556 timer = &sTimerTable[timer_idx];
558 if (timer->mode != 0) {
563 timer->ctrl_config = 0;
564 if (!timer->has_irq_handler) {
573 timer->has_irq_handler = 1;
585 return KE_ILLEGAL_MODE;
588 new_mode = mode | 0x80000000;
595 new_mode |= TMR_CTRL_EXT_SIGNAL;
626 timer->ctrl_config = new_mode;
631int StartHardTimer(
int timid)
635 u32 timer_idx = (timid >> 28) - 1;
636 if (timer_idx >= NUM_TIMERS) {
637 return KE_ILLEGAL_TIMERID;
641 timer = &sTimerTable[timer_idx];
642 if (timer->mode != 0) {
647 if (timer->ctrl_config != 0) {
652 _sh(0, timer->addr + TMR_CTRL_OFFSET);
654 if (timer->timeup_flags) {
658 _sw(timer->compare_value, timer->addr + TMR_CMP_OFFSET);
663 _sh(timer->compare_value, timer->addr + TMR_CMP_OFFSET);
667 timer->mode = timer->ctrl_config | timer->timeup_flags | timer->overflow_flags;
669 _sh(timer->mode, timer->addr + TMR_CTRL_OFFSET);
671 if (timer->mode & 0x30) {
678int StopHardTimer(
int timid)
682 u32 timer_idx = (timid >> 28) - 1;
683 if (timer_idx >= NUM_TIMERS) {
684 return KE_ILLEGAL_TIMERID;
688 timer = &sTimerTable[timer_idx];
689 if (timer->mode == 0) {
694 if (timer->mode & 0x30) {
699 _sh(0, timer->addr + 4);
int CpuResumeIntr(int state)
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
int ReleaseIntrHandler(int irq)
int QueryIntrContext(void)
int DisableIntr(int irq, int *res)
int CpuSuspendIntr(int *state)
u32 count
start sector of fragmented bd/file