saturntimer.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #include "msaturn.h"
  9. enum {
  10. Timer_ctrl = Saturn + 0x0106,
  11. Timer0_load = Saturn + 0x0200,
  12. Timer0_cnt = Saturn + 0x0204,
  13. Timer1_load = Saturn + 0x0300,
  14. Timer1_cnt = Saturn + 0x0304,
  15. T0_event = RBIT(13, ushort),
  16. T0_ie = RBIT(14, ushort),
  17. T0_cen = RBIT(15, ushort),
  18. T1_event = RBIT(5, ushort),
  19. T1_ie = RBIT(6, ushort),
  20. T1_cen = RBIT(7, ushort),
  21. };
  22. static ulong ticks;
  23. static Lock tlock;
  24. static ushort timer_ctl;
  25. void
  26. saturntimerintr(Ureg *u, void*)
  27. {
  28. ushort ctl = *(ushort*)Timer_ctrl, v = 0;
  29. if(ctl&T1_event){
  30. v = T1_event;
  31. ticks++;
  32. }
  33. *(ushort*)Timer_ctrl = timer_ctl|T0_event|v;
  34. intack();
  35. timerintr(u, 0);
  36. }
  37. void
  38. timerinit(void)
  39. {
  40. *(ushort*)Timer_ctrl = 0;
  41. *(ulong*)Timer0_load = m->bushz / HZ;
  42. *(ulong*)Timer0_cnt = m->bushz / HZ;
  43. *(ulong*)Timer1_load = m->bushz;
  44. *(ulong*)Timer1_cnt = m->bushz;
  45. intrenable(Vectimer0, saturntimerintr, nil, "timer");
  46. timer_ctl = T0_cen|T0_ie|T1_cen;
  47. *(ushort*)Timer_ctrl = timer_ctl;
  48. }
  49. uvlong
  50. fastticks(uvlong *hz)
  51. {
  52. assert(*(ushort*)Timer_ctrl&T1_cen);
  53. if(*(ushort*)Timer_ctrl&T1_event){
  54. *(ushort*)Timer_ctrl = timer_ctl|T1_event;
  55. ticks++;
  56. }
  57. if (hz)
  58. *hz = m->bushz;
  59. return (uvlong)ticks*m->bushz+(uvlong)(m->bushz-*(ulong*)Timer1_cnt);
  60. }
  61. void
  62. timerset(uvlong next)
  63. {
  64. ulong offset;
  65. uvlong now;
  66. ilock(&tlock);
  67. *(ushort*)Timer_ctrl = T1_cen;
  68. now = fastticks(nil);
  69. offset = next - now;
  70. if((long)offset < 10000)
  71. offset = 10000;
  72. else if(offset > m->bushz)
  73. offset = m->bushz;
  74. *(ulong*)Timer0_cnt = offset;
  75. *(ushort*)Timer_ctrl = timer_ctl;
  76. assert(*(ushort*)Timer_ctrl & T1_cen);
  77. iunlock(&tlock);
  78. }