ppc403Timer.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:24k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* ppc403Timer.c - PowerPC 403 timer library */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01o,19sep01,pch  SPR 20698, 69142, 69143:  TSR is write-to-clear,
  8.  not read/modify/writeback
  9. 01n,25sep97,ms2  corrected sysAuxClkTicksPerSecond (spr 9348)
  10. 01m,16jul97,tam  add code to enable change of sysClk rate on the fly for GCX. 
  11. 01l,07may97,tam  added use of IS_CPU_403GCX macro. 
  12. 01k,17apr97,dat  rework on SYS_CLK_FREQ, fixed SPR 8372 - extra calls to
  13.  excIntConnect.
  14. 01j,09apr97,mkw  add support for 403GCX
  15. 01i,24mar97,tam  replace excCrtConnect by excIntCrtConnect in sysWdtConnect().
  16. 01h,08nov96,wlf  doc: cleanup.
  17. 01g,07oct96,tam  fixed spr 7242: declared sysBusClkFrequency as a LOCAL.
  18. 01f,02jul96,tam  added code to make system clock more accurate. Added
  19.  timestamp support.
  20. 01e,19mar96,tam  fixed sysAuxClkEnable() & sysWdtClkEnable().
  21. 01d,12mar96,tam  changed excIntConnect to excIntConnectTimer for FIT & PIT.
  22. 01c,11mar96,tam  added functions for the watchdog timer (WDT).
  23. 01b,07mar96,tam  added functions for the auxiliary clock (FIT).
  24. 01a,20feb96,tpr  written, inspired from ppcDecTimer.c version 01g.
  25. */
  26. /*
  27. DESCRIPTION
  28. This library provides PowerPC 403 Timer routines.  This library handles
  29. the system clock, the auxiliary clock and timestamp functions. To
  30. include the timestamp timer facility, the macro INCLUDE_TIMESTAMP must
  31. be defined.
  32. The macro SYS_CLK_FREQ should be defined before using
  33. this module.  This macro is the rate at which clock ticks occur.  For
  34. double clocked busses, this value should be half the actual clock speed.
  35. The macro PIT_CORRECTION is needed to adjust the reload value to account
  36. for the latency delay between generation of the interrupt and the time
  37. to actually enter the service routine.  If not defined, an approximate
  38. value is calculated from the SYS_CLK_FREQ value.  The calculated value
  39. for a 25Mhz clock is a 9 microsecond correction.
  40. The macros SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN,
  41. and AUX_CLK_RATE_MAX must be defined to provide
  42. parameter checking for sysClkRateSet().
  43. The BSP is responsible for connecting the interrupt handlers, sysClkInt(),
  44. and sysAuxClkInt(), to the appropriate vectors.
  45. INCLUDE FILES: ppc403Timer.h
  46. SEE ALSO:
  47. .pG "Configuration"
  48. */
  49. /* includes */
  50. #include "vxLib.h"
  51. #include "intLib.h"
  52. #include "drv/timer/ppc403Timer.h"
  53. #include "arch/ppc/ppc403.h"
  54. #include "drv/timer/timestampDev.h"
  55. /* local defines */
  56. /* System clock speed, default is 25 MHz */
  57. #ifndef SYS_CLK_FREQ
  58. #   define SYS_CLK_FREQ 25000000
  59. #endif
  60. /*
  61.  * The PIT_CORRECTION is expressed in nanoseconds.  It is used
  62.  * to correct the reload value for the 403GA and 403GC cpus
  63.  * which don't have an autoreload feature on the PIT clock.  It accounts
  64.  * for the latency time between when the interrupt was generated and when
  65.  * the interrupt handler was entered.
  66.  */
  67. #ifndef PIT_CORRECTION
  68. #   define PIT_CORRECTION (225000000 / (SYS_CLK_FREQ / 1000))
  69. #endif
  70. /* IS_CPU_403GCX returns TRUE if the CPU is a 403GCX, FALSE otherwise */
  71. #ifndef IS_CPU_403GCX
  72. #   define IS_CPU_403GCX      ((vxPvrGet() & (_PVR_CCF_MSK | _PVR_PCF_MSK)) 
  73.                               == (_PVR_CONF_403GCX << 8) ? 1:0)
  74. #endif
  75. /* Auxiliary clock default rate */
  76. #ifndef AUX_CLK_RATE_DEFAULT
  77. #   define AUX_CLK_RATE_DEFAULT 10
  78. #endif
  79. /* extern declarations */
  80. /* Locals */
  81. LOCAL FIT_PERIOD fitTable[] =                   /* available FIT periods */
  82.     {
  83.     {   (1 << 9),  0x00000000},
  84.     {   (1 << 13), 0x01000000},
  85.     {   (1 << 17), 0x02000000},
  86.     {   (1 << 21), 0x03000000},
  87.     };
  88. LOCAL WDT_PERIOD wdtTable[] =                   /* available WDT periods */
  89.     {
  90.     {   (1 << 17), 0x00000000},
  91.     {   (1 << 21), 0x40000000},
  92.     {   (1 << 25), 0x80000000},
  93.     {   (1 << 29), 0xC0000000},
  94.     };
  95. LOCAL int  sysClkTicksPerSecond  = 60; /* default 60 ticks/second */
  96. LOCAL FUNCPTR sysClkRoutine = NULL;
  97. LOCAL int sysClkArg = NULL;
  98. LOCAL BOOL sysClkConnectFirstTime = TRUE;
  99. LOCAL BOOL sysClkRunning  = FALSE;
  100. LOCAL BOOL sysClkReload = TRUE;
  101. LOCAL BOOL sysClkReloadOnce = FALSE;
  102. LOCAL int  sysAuxClkTicksPerSecond = AUX_CLK_RATE_DEFAULT;
  103. LOCAL FUNCPTR sysAuxClkRoutine = NULL;
  104. LOCAL int sysAuxClkArg = NULL;
  105. LOCAL BOOL sysAuxClkRunning  = FALSE;
  106. LOCAL int  sysWdtTicksPerSecond = 1;
  107. LOCAL FUNCPTR sysWdtRoutine = NULL;
  108. LOCAL int sysWdtArg = NULL;
  109. LOCAL BOOL sysWdtRunning  = FALSE;
  110. LOCAL UINT32 sysBusClkFrequency  = TIMER_CLK_FREQ;
  111. LOCAL UINT32 pitCountVal; /* PIT counter value */
  112. LOCAL UINT32  fitPeriodMask = 0x01000000; /* default FIT period: 2^21 */
  113. LOCAL UINT32 wdtPeriodMask = 0xC0000000; /* default WDT period: 2^29 */
  114. LOCAL UINT32 pitCorrection;
  115. #ifdef INCLUDE_TIMESTAMP
  116. LOCAL BOOL      sysTimestampRunning     = FALSE;   /* timestamp running flag */
  117. #endif  /* INCLUDE_TIMESTAMP */
  118. /*******************************************************************************
  119. *
  120. * sysClkInt - clock interrupt handler
  121. *
  122. * This routine handles the clock interrupt on the PowerPC 403 architecture. It
  123. * is attached to the Programmable Interval Timer vector by the routine
  124. * sysClkConnect().
  125. *
  126. * RETURNS : N/A
  127. */
  128. LOCAL void sysClkInt (void)
  129.     {
  130.     vxPitIntAck ();             /* acknowledge PIT interrupt */
  131.     /*
  132.      * Since the auto-reload feature of the PIT seems not to work properly
  133.      * for non-GCX it is necessary to reload the Programmable Interrupt Timer.
  134.      * The reload value should be adjusted each time because the time spent
  135.      * between the exception generation and the moment the register is reloaded
  136.      * changes.
  137.      * Since the PIT does not keep decrementing after it reaches 0 we cannot
  138.      * read it again and adjust pitCountVal. The current correction corresponds
  139.      * to the average time spend between the exception generation and the
  140.      * moment the register is reloaded. A better solution would be to use
  141.      * the time base to calculate that value dynamically but that requires
  142.      * adding code to the PPC interrupt stub routine.
  143.      */
  144.     if (sysClkReload)
  145. vxPitSet(pitCountVal - pitCorrection);
  146.     if (sysClkReloadOnce)
  147. {
  148. vxPitSet(pitCountVal); /* reload the PIT once after a call */
  149. sysClkReloadOnce = FALSE; /* to sysClkRateSet() for GCX cpu   */
  150. }
  151.     /* execute the system clock routine */
  152.     if (sysClkRoutine != NULL)
  153. (*(FUNCPTR) sysClkRoutine) (sysClkArg);
  154.     }
  155. /*******************************************************************************
  156. *
  157. * sysClkConnect - connect a routine to the system clock interrupt
  158. *
  159. * This routine specifies the interrupt service routine to be called at each
  160. * clock interrupt.  Normally, it is called from usrRoot() in usrConfig.c to
  161. * connect usrClock() to the system clock interrupt.  It also connects the
  162. * clock error interrupt service routine.
  163. *
  164. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  165. *
  166. * SEE ALSO: usrClock(), sysClkEnable()
  167. */
  168. STATUS sysClkConnect
  169.     (
  170.     FUNCPTR  routine, /* routine to connect */
  171.     int  arg /* argument with which to call the routine */
  172.     )
  173.     {
  174.     if (sysClkConnectFirstTime)
  175. {
  176. sysHwInit2();
  177. sysClkConnectFirstTime = FALSE;
  178. }
  179.     sysClkRoutine = routine;
  180.     sysClkArg = arg;
  181.     return (OK);
  182.     }
  183. /******************************************************************************
  184. *
  185. * sysClkEnable - turn on system clock interrupts
  186. *
  187. * This routine enables system clock interrupts.
  188. *
  189. * RETURNS: N/A
  190. *
  191. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  192. */
  193. void sysClkEnable (void)
  194.     {
  195.     if (!sysClkRunning)
  196. {
  197. /* clear the pending PIT interrupt */
  198. vxTsrSet (_PPC403_TSR_PIS);
  199. /* load the PIT counter and the hidden register with interval value */
  200. vxPitSet (pitCountVal);
  201. /* Enable the PIT interrupt & enable autoreload for 403GCX */
  202. if (IS_CPU_403GCX)
  203.     {
  204.     vxTcrSet (vxTcrGet() | _PPC403_TCR_PIE | _PPC403_TCR_ARE);
  205.     sysClkReload = FALSE;
  206.     }
  207. else
  208.     vxTcrSet (vxTcrGet() | _PPC403_TCR_PIE);
  209. /* set the running flag */
  210. sysClkRunning = TRUE;
  211. }
  212.     }
  213. /******************************************************************************
  214. *
  215. * sysClkDisable - turn off system clock interrupts
  216. *
  217. * This routine disables system clock interrupts.
  218. *
  219. * RETURNS: N/A
  220. *
  221. * SEE ALSO: sysClkEnable()
  222. */
  223. void sysClkDisable (void)
  224.     {
  225.     if (sysClkRunning)
  226. {
  227. /* disable the PIT interrupt and auto-reload capability */
  228. vxTcrSet (vxTcrGet() & ~ (_PPC403_TCR_PIE | _PPC403_TCR_ARE));
  229. /* clear the PIT counter */
  230. vxPitSet (0);
  231. /* clear the pending PIT interrupt */
  232. vxTsrSet (_PPC403_TSR_PIS);
  233. /* reset the running flag */
  234. sysClkRunning = FALSE;
  235. }
  236.     }
  237. /******************************************************************************
  238. *
  239. * sysClkRateGet - get the system clock rate
  240. *
  241. * This routine returns the system clock rate.
  242. *
  243. * RETURNS: The number of ticks per second of the system clock.
  244. *
  245. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  246. */
  247. int sysClkRateGet (void)
  248.     {
  249.     return (sysClkTicksPerSecond);
  250.     }
  251. /******************************************************************************
  252. *
  253. * sysClkRateSet - set the system clock rate
  254. *
  255. * This routine sets the interrupt rate of the system clock.  It does not
  256. * enable system clock interrupts.  It is called by usrRoot() in
  257. * usrConfig.c.
  258. *
  259. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  260. *
  261. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  262. */
  263. STATUS sysClkRateSet
  264.     (
  265.     int  ticksPerSecond  /* number of clock interrupts per second */
  266.     )
  267.     {
  268.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  269.         return (ERROR);
  270.     /* save the clock speed */
  271.     sysClkTicksPerSecond = ticksPerSecond;
  272.     /*
  273.      * compute the value to load in the decrementor. The new value will be
  274.      * load in the decrementor after the end of the current period
  275.      */
  276.     if (vxIocrGet () & _PPC403_IOCR_TCSM)
  277. sysBusClkFrequency = TIMER_CLK_FREQ;
  278.     else
  279. sysBusClkFrequency = SYS_CLK_FREQ;
  280.     pitCountVal = sysBusClkFrequency / ticksPerSecond;
  281.     pitCorrection = (((sysBusClkFrequency / 1000000) *
  282.     PIT_CORRECTION) / 1000);
  283.     if (IS_CPU_403GCX)
  284. sysClkReloadOnce = TRUE; /* reload the PIT with new value */
  285.     return (OK);
  286.     }
  287. /*******************************************************************************
  288. *
  289. * sysAuxClkInt - auxilary clock interrupt handler
  290. *
  291. * This routine handles the auxilary clock interrupt on the PowerPC 403
  292. * architecture. It is attached to the Fix Interval Timer vector by the routine
  293. * sysAuxClkConnect().
  294. *
  295. * RETURNS : N/A
  296. */
  297. LOCAL void sysAuxClkInt (void)
  298.     {
  299.     vxFitIntAck ();             /* acknowledge FIT interrupt */
  300.     /* program TCR with the FIT period */
  301.     vxTcrSet ((vxTcrGet() & ~_PPC403_TCR_FP) | fitPeriodMask);
  302.     /* execute the system clock routine */
  303.     if (sysAuxClkRoutine != NULL)
  304. (*(FUNCPTR) sysAuxClkRoutine) (sysAuxClkArg);
  305.     }
  306. /*******************************************************************************
  307. *
  308. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  309. *
  310. * This routine specifies the interrupt service routine to be called at each
  311. * auxiliary clock interrupt.  It does not enable auxiliary clock
  312. * interrupts.
  313. *
  314. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  315. *
  316. * SEE ALSO: excIntConnectTimer(), sysAuxClkEnable()
  317. */
  318. STATUS sysAuxClkConnect
  319.     (
  320.     FUNCPTR routine, /* routine called at each aux. clock interrupt */
  321.     int     arg /* argument to auxiliary clock interrupt */
  322.     )
  323.     {
  324.     sysAuxClkRoutine = routine;
  325.     sysAuxClkArg = arg;
  326.     return (OK);
  327.     }
  328. /*******************************************************************************
  329. *
  330. * sysAuxClkEnable - turn on auxiliary clock interrupts
  331. *
  332. * This routine enables auxiliary clock interrupts.
  333. *
  334. * RETURNS: N/A
  335. *
  336. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  337. */
  338. void sysAuxClkEnable (void)
  339.     {
  340.     if (!sysAuxClkRunning)
  341. {
  342. /* clear the pending FIT interrupt */
  343. vxTsrSet (_PPC403_TSR_FIS);
  344. /* program TCR with the FIT period */
  345. vxTcrSet ((vxTcrGet() & ~_PPC403_TCR_FP) | fitPeriodMask);
  346. /* Enable the FIT interrupt */
  347. vxTcrSet (vxTcrGet() | _PPC403_TCR_FIE);
  348. /* set the running flag */
  349. sysAuxClkRunning = TRUE;
  350. }
  351.     }
  352. /*******************************************************************************
  353. *
  354. * sysAuxClkDisable - turn off auxiliary clock interrupts
  355. *
  356. * This routine disables auxiliary clock interrupts.
  357. *
  358. *
  359. * RETURNS: N/A
  360. *
  361. * SEE ALSO: sysAuxClkEnable()
  362. */
  363. void sysAuxClkDisable (void)
  364.     {
  365.     if (sysAuxClkRunning)
  366. {
  367. /* disable the FIT interrupt */
  368. vxTcrSet (vxTcrGet() & ~ (_PPC403_TCR_FIE));
  369. /* clear the pending FIT interrupt */
  370. vxTsrSet (_PPC403_TSR_FIS);
  371. /* reset the running flag */
  372. sysAuxClkRunning = FALSE;
  373. }
  374.     }
  375. /*******************************************************************************
  376. *
  377. * sysAuxClkRateGet - get the auxiliary clock rate
  378. *
  379. * This routine returns the interrupt rate of the auxiliary clock.
  380. *
  381. * RETURNS: The number of ticks per second of the auxiliary clock.
  382. *
  383. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  384. */
  385. int sysAuxClkRateGet (void)
  386.     {
  387.     return (sysAuxClkTicksPerSecond);
  388.     }
  389. /*******************************************************************************
  390. *
  391. * sysAuxClkRateSet - set the auxiliary clock rate
  392. *
  393. * This routine sets the interrupt rate of the auxiliary clock.  It does not
  394. * enable auxiliary clock interrupts.
  395. *
  396. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  397. *
  398. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  399. */
  400. STATUS sysAuxClkRateSet
  401.     (
  402.     int ticksPerSecond     /* number of clock interrupts per second */
  403.     )
  404.     {
  405.     int ix;
  406.     int jx = 0;
  407.     UINT32 fitPeriod;
  408.     /*
  409.      * compute the FIT period.
  410.      * only 4 values are possible (cf fitTable[]). The closest value to
  411.      * <ticksPerSecond> is being used.
  412.      */
  413.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  414.         return (ERROR);
  415.     if (vxIocrGet () & _PPC403_IOCR_TCSM)
  416.         {       /* service clock */
  417.         sysBusClkFrequency = TIMER_CLK_FREQ;
  418.         }
  419.     else sysBusClkFrequency = SYS_CLK_FREQ;
  420.     fitPeriod = sysBusClkFrequency / ticksPerSecond;
  421.     /* get the closest value to ticksPerSecond supported by the FIT */
  422.     for (ix = 0; ix < NELEMENTS (fitTable); ix++)
  423.         {
  424.         if (fitPeriod <= fitTable [ix].fitPeriod)
  425.             {
  426.     if (ix != 0)
  427. if ( fitPeriod <
  428.      ((fitTable [ix].fitPeriod + fitTable [ix-1].fitPeriod)/2))
  429.     jx = ix-1;
  430.                 else
  431.     jx = ix;
  432.     else
  433. jx = ix;
  434.             break;
  435.             }
  436. if (ix == NELEMENTS (fitTable) - 1)
  437.     jx = ix;
  438.         }
  439.     fitPeriod = fitTable [jx].fitPeriod; /* actual period of the FIT */
  440.     fitPeriodMask = fitTable [jx].fpMask; /* Mask to program TCR with */
  441.     /* save the clock speed */
  442.     sysAuxClkTicksPerSecond = sysBusClkFrequency / fitPeriod;
  443.     return (OK);
  444.     }
  445. /*******************************************************************************
  446. *
  447. * sysWdtInt - watchdog interrupt handler.
  448. *
  449. * This routine handles the watchdog interrupt on the PowerPC 403
  450. * architecture. It is attached to the watchdog timer vector by the routine
  451. * sysWdtConnect().
  452. *
  453. * RETURNS : N/A
  454. */
  455. LOCAL void sysWdtInt (void)
  456.     {
  457.     /* acknowledge WDT interrupt */
  458.     vxTsrSet (_PPC403_TSR_WIS);
  459.     /* execute the watchdog  clock routine */
  460.     if (sysWdtRoutine != NULL)
  461.         (*(FUNCPTR) sysWdtRoutine) (sysWdtArg);
  462.     }
  463. /*******************************************************************************
  464. *
  465. * sysWdtConnect - connect a routine to the watchdog interrupt
  466. *
  467. * This routine specifies the interrupt service routine to be called at each
  468. * watchdog interrupt.  It does not enable watchdog interrupts.
  469. *
  470. * RETURNS: OK, or ERROR if the routine cannot be connected to the watchdog
  471. * interrupt.
  472. *
  473. * SEE ALSO: excIntCrtConnect(), sysWdtEnable()
  474. */
  475. STATUS sysWdtConnect
  476.     (
  477.     FUNCPTR routine,    /* routine called at each watchdog interrupt */
  478.     int     arg         /* argument with which to call routine         */
  479.     )
  480.     {
  481.     /* connect the routine to the WDT vector */
  482.     excIntCrtConnect ((VOIDFUNCPTR *) _EXC_OFF_WD, (VOIDFUNCPTR) sysWdtInt);
  483.     sysWdtRoutine    = routine;
  484.     sysWdtArg        = arg;
  485.     return (OK);
  486.     }
  487. /*******************************************************************************
  488. *
  489. * sysWdtEnable - turn on watchdog interrupts
  490. *
  491. * This routine enables watchdog interrupts.
  492. *
  493. * RETURNS: N/A
  494. *
  495. * SEE ALSO: sysWdtConnect(), sysWdtDisable(), sysWdtRateSet()
  496. */
  497. void sysWdtEnable (void)
  498.     {
  499.     if (!sysWdtRunning)
  500.         {
  501.         /* clear the pending WDT interrupt */
  502.         vxTsrSet (_PPC403_TSR_WIS);
  503.         /* program TCR with the WDT period */
  504.         vxTcrSet ((vxTcrGet() & ~_PPC403_TCR_WP) | wdtPeriodMask);
  505.         /* Enable the WDT interrupt */
  506.         vxTcrSet (vxTcrGet() | _PPC403_TCR_WIE);
  507. /* Enable critical interrupt */
  508. vxMsrSet (vxMsrGet() | _PPC_MSR_CE);
  509.         /* set the running flag */
  510.         sysWdtRunning = TRUE;
  511.         }
  512.     }
  513. /*******************************************************************************
  514. *
  515. * sysWdtDisable - turn off watchdog interrupts
  516. *
  517. * This routine disables watchdog interrupts.
  518. * This routine does not disable critical interrupts.
  519. *
  520. * RETURNS: N/A
  521. *
  522. * SEE ALSO: sysWdtEnable()
  523. */
  524. void sysWdtDisable (void)
  525.     {
  526.     if (sysWdtRunning)
  527.         {
  528.         /* disable the WDT interrupt */
  529.         vxTcrSet (vxTcrGet() & ~ (_PPC403_TCR_WIE));
  530.         /* clear the pending WDT interrupt */
  531.         vxTsrSet (_PPC403_TSR_WIS);
  532.         /* reset the running flag */
  533.         sysWdtRunning = FALSE;
  534.         }
  535.     }
  536. /*******************************************************************************
  537. *
  538. * sysWdtRateGet - get the watchdog timer rate
  539. *
  540. * This routine returns the interrupt rate of the watchdog timer.
  541. *
  542. * RETURNS: The number of watchdog interrupts per second.
  543. *
  544. * SEE ALSO: sysWdtEnable(), sysWdtRateSet()
  545. */
  546. int sysWdtRateGet (void)
  547.     {
  548.     return (sysWdtTicksPerSecond);
  549.     }
  550. /*******************************************************************************
  551. *
  552. * sysWdtRateSet - set the watchdog timer rate
  553. *
  554. * This routine sets the interrupt rate of the watchdog timer.  It does not
  555. * enable watchdog interrupts.
  556. *
  557. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  558. *
  559. * SEE ALSO: sysWdtEnable(), sysWdtRateGet()
  560. */
  561. STATUS sysWdtRateSet
  562.     (
  563.     int ticksPerSecond      /* number of clock interrupts per second */
  564.     )
  565.     {
  566.     int ix;
  567.     int jx = 0;
  568.     UINT32 wdtPeriod;
  569.     /*
  570.      * compute the WDT period.
  571.      * only 4 values are possible (cf wdtTable[]). The closest value to
  572.      * <ticksPerSecond> is being used.
  573.      */
  574.     if (ticksPerSecond < WDT_RATE_MIN || ticksPerSecond > WDT_RATE_MAX)
  575.         return (ERROR);
  576.     if (vxIocrGet () & _PPC403_IOCR_TCSM)
  577.         {       /* service clock */
  578.         sysBusClkFrequency = TIMER_CLK_FREQ;
  579.         }
  580.     else sysBusClkFrequency = SYS_CLK_FREQ;
  581.     wdtPeriod = sysBusClkFrequency / ticksPerSecond;
  582.     /* get the closest value to ticksPerSecond supported by the WDT */
  583.     for (ix = 0; ix < NELEMENTS (wdtTable); ix++)
  584.         {
  585.         if (wdtPeriod <= wdtTable [ix].wdtPeriod)
  586.             {
  587.             if (ix != 0)
  588.                 if ( wdtPeriod <
  589.                      ((wdtTable [ix].wdtPeriod + wdtTable [ix-1].wdtPeriod)/2))
  590.                     jx = ix-1;
  591.                 else
  592.                     jx = ix;
  593.             else
  594.                 jx = ix;
  595.             break;
  596.             }
  597.         if (ix == NELEMENTS (wdtTable) - 1)
  598.             jx = ix;
  599.         }
  600.     wdtPeriod = wdtTable [jx].wdtPeriod;        /* actual period of the WDT */
  601.     wdtPeriodMask = wdtTable [jx].fpMask; /* Mask to program TCR with */
  602.     /* save the clock speed */
  603.     sysWdtTicksPerSecond = sysBusClkFrequency / wdtPeriod;
  604.     return (OK);
  605.     }
  606. #ifdef  INCLUDE_TIMESTAMP
  607. /*******************************************************************************
  608. *
  609. * sysTimestampConnect - connect a user routine to a timestamp timer interrupt
  610. *
  611. * This routine specifies the user interrupt routine to be called at each
  612. * timestamp timer interrupt. In this case, however, the timestamp timer
  613. * interrupt is not used since the on-chip timer is also used by the system
  614. * clock.
  615. *
  616. * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used.
  617. */
  618. STATUS sysTimestampConnect
  619.     (
  620.     FUNCPTR routine,    /* routine called at each timestamp timer interrupt */
  621.     int arg             /* argument with which to call routine */
  622.     )
  623.     {
  624.     return (ERROR);
  625.     }
  626. /*******************************************************************************
  627. *
  628. * sysTimestampEnable - initialize and enable a timestamp timer
  629. *
  630. * This routine disables the timestamp timer interrupt and initializes the
  631. * counter registers.  If the timestamp timer is already running, this routine
  632. * merely resets the timer counter.
  633. *
  634. * This routine does not intialize the timer rate.  The rate of the timestamp
  635. * timer should be set explicitly in the BSP by sysHwInit().
  636. *
  637. * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled.
  638. */
  639. STATUS sysTimestampEnable (void)
  640.    {
  641.    if (sysTimestampRunning)
  642.       {
  643.       return (OK);
  644.       }
  645.    if (!sysClkRunning)
  646.       return (ERROR);
  647.    sysTimestampRunning = TRUE;
  648.    return (OK);
  649.    }
  650. /*******************************************************************************
  651. *
  652. * sysTimestampDisable - disable a timestamp timer
  653. *
  654. * This routine disables the timestamp timer.  Interrupts are not disabled;
  655. * however, because the tick counter does not increment after the timestamp
  656. * timer is disabled, interrupts no longer are generated.
  657. *
  658. * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled.
  659. */
  660. STATUS sysTimestampDisable (void)
  661.     {
  662.     if (sysTimestampRunning)
  663.         sysTimestampRunning = FALSE;
  664.     return (OK);
  665.     }
  666. /*******************************************************************************
  667. *
  668. * sysTimestampPeriod - get a timestamp timer period
  669. *
  670. * This routine specifies the period of the timestamp timer, in ticks.
  671. * The period, or terminal count, is the number of ticks to which the timestamp
  672. * timer counts before rolling over and restarting the counting process.
  673. *
  674. * RETURNS: The period of the timestamp timer in counter ticks.
  675. */
  676. UINT32 sysTimestampPeriod (void)
  677.     {
  678.     /*
  679.      * The period of the timestamp depends on the clock rate of the on-chip
  680.      * timer (ie the Decrementer reload value).
  681.      */
  682.     return (pitCountVal);
  683.     }
  684. /*******************************************************************************
  685. *
  686. * sysTimestampFreq - get a timestamp timer clock frequency
  687. *
  688. * This routine specifies the frequency of the timer clock, in ticks per second.
  689. * The rate of the timestamp timer should be set explicitly in the BSP
  690. * by sysHwInit().
  691. *
  692. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  693. */
  694. UINT32 sysTimestampFreq (void)
  695.     {
  696.     return (sysBusClkFrequency);
  697.     }
  698. /*******************************************************************************
  699. *
  700. * sysTimestamp - get a timestamp timer tick count
  701. *
  702. * This routine returns the current value of the timestamp timer tick counter.
  703. * The tick count can be converted to seconds by dividing by the return of
  704. * sysTimestampFreq().
  705. *
  706. * This routine should be called with interrupts locked.  If interrupts are
  707. * not locked, sysTimestampLock() should be used instead.
  708. *
  709. * RETURNS: The current timestamp timer tick count.
  710. *
  711. * SEE ALSO: sysTimestampFreq(), sysTimestampLock()
  712. */
  713. UINT32 sysTimestamp (void)
  714.     {
  715.     return (pitCountVal - (UINT32) vxPitGet());
  716.     }
  717. /*******************************************************************************
  718. *
  719. * sysTimestampLock - lock an interrupt and get a timestamp timer tick count
  720. *
  721. * This routine locks interrupts when stop the tick counter must be stopped
  722. * in order to read it or when two independent counters must be read.
  723. * It then returns the current value of the timestamp timer tick counter.
  724. *
  725. * The tick count can be converted to seconds by dividing by the return of
  726. * sysTimestampFreq().
  727. *
  728. * If interrupts are already locked, sysTimestamp() should be
  729. * used instead.
  730. *
  731. * RETURNS: The current timestamp timer tick count.
  732. *
  733. * SEE ALSO: sysTimestamp()
  734. */
  735. UINT32 sysTimestampLock (void)
  736.     {
  737.     UINT32 currentPitValue;
  738.     int oldLevel;
  739.     oldLevel = intLock ();                              /* LOCK INTERRUPT */
  740.     currentPitValue = vxPitGet();
  741.     intUnlock (oldLevel);                               /* UNLOCK INTERRUPT */
  742.     return (pitCountVal - currentPitValue);
  743.     }
  744. #endif  /* INCLUDE_TIMESTAMP */