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

VxWorks

开发平台:

C/C++

  1. /* i8253Timer.c - Intel 8253 timer library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01z,18apr02,hdn  added docs for the PIC IRQ0 interrupt options (spr 76411)
  8. 01y,14oct01,dat  merged with VxAE 1.1
  9. 01x,13apr01,hdn  cleared int-request-flag in sysAuxClkEnable() (spr 34212)
  10.  replaced the magic numbers with macros in mc146818.h
  11. 01w,05apr01,hdn  changed NULL to 0 in line 86 to shut off warning (spr 65562)
  12. 01v,15dec00,dat  added #includes to define CLK_RATE
  13. 01u,20nov00,mks  renamed INCLUDE_TIMESTAMP to INCLUDE_TIMESTAMP_PIT2, and
  14.  cleaned up last checkin. (SPR 62085).
  15. 01t,14nov00,rcs  changed references to SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX,
  16.                  AUX_CLK_RATE_MIN, and AUX_CLK_RATE_MAX to parameters SPR 62266
  17. 01s,08nov00,mks  calling sysTimestampRoutine before sysClkRoutine in sysClkInt,
  18.                  modified sysTimestampConnect to allow external agents to hook
  19.                  callback function call which will be called at timer interrupt,
  20.                  and modified init sequence of i8253 CH2 in mode 3. (SPR 62085).
  21. 01r,09apr00,stv  made sysClkInt, sysAuxClkInt functions global
  22. 01q,29mar00,dat  removed sysHwInit2() (vxAE)
  23. 01p,28jan00,jkf  corrected build warnings.
  24. 01o,08may98,hdn  fixed typo.  sysTsc..() to pentiumTsc..().
  25. 01n,20apr98,hdn  added documentation for INCLUDE_TIMESTAMP_TSC.
  26. 01m,09apr98,hdn  added support for Pentium, PentiumPro.
  27. 01l,22jul96,dat  merged timestamp driver into normal driver.
  28. 01k,23may96,wlf  doc: cleanup.
  29. 01j,12feb96,hdn  added support for a channel-1 as Aux timer with PIT1_FOR_AUX.
  30. 01i,25apr94,hdn  changed sysAuxClkTicksPerSecond from 60 to 64.
  31. 01h,09nov93,vin  added SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN,
  32.                  AUX_CLK_RATE_MAX macros, moved intConnect of auxiliary clock
  33.  sysLib.c; made sysAuxClkRateSet return error if any value
  34.  other than the one in the auxTable is set. Added sysClkDisable
  35.  and sysClkEnable in sysClkRateSet.
  36. 01g,27oct93,hdn  deleted memAddToPool stuff from sysClkConnect().
  37. 01f,12oct93,hdn  added sysIntEnablePIC(), sysIntDisablePIC().
  38. 01e,16aug93,hdn  added aux clock functions.
  39. 01d,16jun93,hdn  updated to 5.1.
  40. 01c,08apr93,jdi  doc cleanup.
  41. 01d,07apr93,hdn  renamed compaq to pc.
  42. 01c,26mar93,hdn  added the global descriptor table, memAddToPool.
  43.  moved enabling A20 to romInit.s. added cacheClear for 486.
  44. 01b,18nov92,hdn  supported nested interrupt.
  45. 01a,15may92,hdn  written based on frc386 version.
  46. */
  47. /*
  48. DESCRIPTION
  49. This library contains routines to manipulate the timer functions on the
  50. Intel 8253 chip with a board-independent interface.  This library handles
  51. both the system clock and the auxiliary clock functions.
  52. The parameters SYS_CLK_RATE_MIN, SYS_CLK_RATE_MAX, AUX_CLK_RATE_MIN, and
  53. AUX_CLK_RATE_MAX must be defined to provide parameter checking for the
  54. sys[Aux]ClkRateSet() routines.
  55. The macro PIT_CLOCK must also be defined to indicate the clock frequency
  56. of the i8253.
  57. The macro INCLUDE_TIMESTAMP_TSC lets the timestamp driver use the on-chip
  58. TSC (Timestamp Counter) in P5 (Pentium), P6 (PentiumPro, II, III), and
  59. P7 (Pentium4) family processors.  P5, P6, and P7 family processors provide
  60. a 64-bit timestamp counter that is incremented every processor clock cycle.
  61. The counter is incremented even when the processor is halted by the HLT
  62. instruction or the external STPCLK# pin.  The timestamp counter is set to
  63. 0 following a hardware reset of the processor.  The RDTSC instruction reads
  64. the timestamp counter and is guaranteed to return a monotonically
  65. increasing unique value whenever executed, except for 64-bit counter
  66. wraparound.  Intel guarantees, architecturally, that the timestamp counter
  67. frequency and configuration will be such that it will not wraparound within
  68. 10 years after being reset to 0.  The period for counter wrap is several
  69. thousands of years in P5, P6, and P7 family processors.
  70. The system clock is the programmable interrupt timer (PIT) channel 0.  The
  71. default auxiliary clock is the real-time clock (RTC).
  72. The PIC(8259A) IRQ0 is hard wired to the PIT(8253) channel 0 in a PC
  73. motherboard.  The IRQ0 is the highest priority in the 8259A interrupt
  74. controller.  Thus, the system clock interrupt handler blocks all lower
  75. level interrupts.  This may cause a delay of the lower level interrupts in
  76. some situations even though the system clock interrupt handler finishes
  77. its job in the clock period.  This is quite natural from the hardware point
  78. of view, but may not be ideal from the application software standpoint.
  79. To mitigate this situation, the PIC(8259A) driver provides several
  80. configurations in the BSP.
  81. SEE ALSO: intrCtl/i8259Intr.c
  82. */
  83. #include "vxWorks.h"
  84. #include "sysLib.h"
  85. #include "intLib.h"
  86. #include "taskLib.h"
  87. #include "arch/i86/pentiumLib.h"
  88. #include "drv/timer/i8253.h"
  89. #include "drv/timer/mc146818.h"
  90. #if defined(INCLUDE_TIMESTAMP_PIT2) || defined(INCLUDE_TIMESTAMP_TSC)
  91. /* Locals */ 
  92. LOCAL BOOL sysTimestampRunning = FALSE; /* running flag */
  93. LOCAL int  sysTimestampPeriodValue = 0; /* Max counter value */
  94. union uc
  95.     {
  96.     USHORT count16;
  97.     UCHAR  count08[2];
  98.     };
  99. #endif /* INCLUDE_TIMESTAMP_PIT2 || INCLUDE_TIMESTAMP_TSC */
  100. #ifdef INCLUDE_TIMESTAMP_TSC
  101. LOCAL FUNCPTR sysTimestampRoutine   = NULL; /* user rollover routine */
  102. LOCAL int    sysTimestampTickCount = 0; /* system ticks counter */
  103. LOCAL UINT32 sysTimestampFreqValue = PENTIUMPRO_TSC_FREQ; /* TSC freq */
  104. #endif /* INCLUDE_TIMESTAMP_TSC */
  105. /* locals */
  106. LOCAL FUNCPTR sysClkRoutine = NULL; /* routine to call on clock interrupt */
  107. LOCAL int sysClkArg = 0; /* its argument */
  108. LOCAL int sysClkRunning = FALSE;
  109. LOCAL int sysClkConnected = FALSE;
  110. LOCAL int sysClkTicksPerSecond = 60;
  111. LOCAL FUNCPTR sysAuxClkRoutine = NULL;
  112. LOCAL int sysAuxClkArg = 0;
  113. LOCAL int sysAuxClkRunning = FALSE;
  114. #ifdef PIT1_FOR_AUX
  115. LOCAL int sysAuxClkTicksPerSecond = 60;
  116. #else
  117. LOCAL int sysAuxClkTicksPerSecond = 64;
  118. LOCAL CLK_RATE auxTable[] =
  119.     {
  120.     {   2, 0x0f}, 
  121.     {   4, 0x0e}, 
  122.     {   8, 0x0d}, 
  123.     {  16, 0x0c}, 
  124.     {  32, 0x0b}, 
  125.     {  64, 0x0a}, 
  126.     { 128, 0x09}, 
  127.     { 256, 0x08}, 
  128.     { 512, 0x07}, 
  129.     {1024, 0x06}, 
  130.     {2048, 0x05}, 
  131.     {4096, 0x04}, 
  132.     {8192, 0x03} 
  133.     };
  134. #endif /* PIT1_FOR_AUX */
  135. /* forward declarations */
  136. #if defined (INCLUDE_TIMESTAMP_TSC)
  137. LOCAL void sysTimestampFreqGet (void);
  138. #endif /* defined (INCLUDE_TIMESTAMP_TSC) */
  139. /*******************************************************************************
  140. *
  141. * sysClkInt - interrupt level processing for system clock
  142. *
  143. * This routine handles the system clock interrupt.  It is attached to the
  144. * clock interrupt vector by the routine sysClkConnect().
  145. */
  146. void sysClkInt (void)
  147.     {
  148.     /* reset TSC */
  149. #if defined (INCLUDE_TIMESTAMP_TSC)
  150.     if (sysTimestampRoutine != NULL)  
  151.         (* sysTimestampRoutine) ();
  152. #endif /* defined (INCLUDE_TIMESTAMP_TSC) */
  153.     /* acknowledge interrupt */
  154.     if (sysClkRoutine != NULL)
  155. (* sysClkRoutine) (sysClkArg);
  156.     
  157.     }
  158. /*******************************************************************************
  159. *
  160. * sysClkConnect - connect a routine to the system clock interrupt
  161. *
  162. * This routine specifies the interrupt service routine to be called at each
  163. * clock interrupt.  Normally, it is called from usrRoot() in usrConfig.c to 
  164. * connect usrClock() to the system clock interrupt.
  165. *
  166. * RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.
  167. *
  168. * SEE ALSO: intConnect(), usrClock(), sysClkEnable()
  169. */
  170. STATUS sysClkConnect
  171.     (
  172.     FUNCPTR routine, /* routine to be called at each clock interrupt */
  173.     int arg /* argument with which to call routine */
  174.     )
  175.     {
  176. #ifdef _WRS_VXWORKS_5_X
  177.     if (sysClkConnected == FALSE)
  178. sysHwInit2 (); /* VxAE does this in the prjConfig */
  179. #endif
  180.     sysClkRoutine   = routine;
  181.     sysClkArg     = arg;
  182.     sysClkConnected = TRUE;
  183.     return (OK);
  184.     }
  185. /*******************************************************************************
  186. *
  187. * sysClkDisable - turn off system clock interrupts
  188. *
  189. * This routine disables system clock interrupts.
  190. *
  191. * RETURNS: N/A
  192. *
  193. * SEE ALSO: sysClkEnable()
  194. */
  195. void sysClkDisable (void)
  196.     {
  197.     int oldLevel;
  198.     if (sysClkRunning)
  199. {
  200.         oldLevel = intLock (); /* LOCK INTERRUPT */
  201. sysOutByte (PIT_CMD (PIT_BASE_ADR), 0x38);
  202. sysOutByte (PIT_CNT0 (PIT_BASE_ADR), LSB(0));
  203. sysOutByte (PIT_CNT0 (PIT_BASE_ADR), MSB(0));
  204.         intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  205. sysIntDisablePIC (PIT0_INT_LVL);
  206. #ifdef INCLUDE_TIMESTAMP_PIT2
  207.         sysOutByte (0x61, sysInByte (0x61) & 0xfe); /* disable counter 2 */
  208. #endif /* INCLUDE_TIMESTAMP_PIT2 */
  209. sysClkRunning = FALSE;
  210. }
  211.     }
  212. /*******************************************************************************
  213. *
  214. * sysClkEnable - turn on system clock interrupts
  215. *
  216. * This routine enables system clock interrupts.
  217. *
  218. * RETURNS: N/A
  219. *
  220. * SEE ALSO: sysClkConnect(), sysClkDisable(), sysClkRateSet()
  221. */
  222. void sysClkEnable (void)
  223.     {
  224.     UINT tc0;
  225.     UINT tc2;
  226.     int oldLevel;
  227.     if (!sysClkRunning)
  228. {
  229. tc0 = PIT_CLOCK / sysClkTicksPerSecond;
  230.         tc2 = PIT_CLOCK / sysClkTicksPerSecond * 2;
  231.         oldLevel = intLock (); /* LOCK INTERRUPT */
  232. sysOutByte (PIT_CMD (PIT_BASE_ADR), 0x36);
  233. sysOutByte (PIT_CNT0 (PIT_BASE_ADR), LSB(tc0));
  234. sysOutByte (PIT_CNT0 (PIT_BASE_ADR), MSB(tc0));
  235. #ifdef INCLUDE_TIMESTAMP_PIT2
  236.         sysOutByte (PIT_CMD (PIT_BASE_ADR), 0xb6);
  237.         sysOutByte (PIT_CNT2 (PIT_BASE_ADR), LSB(tc2));
  238.         sysOutByte (PIT_CNT2 (PIT_BASE_ADR), MSB(tc2));        
  239.         sysOutByte (0x61, sysInByte (0x61) | 1); /* enable counter 2 */
  240. #endif /* INCLUDE_TIMESTAMP_PIT2 */        
  241. #ifdef INCLUDE_TIMESTAMP_TSC
  242. sysTimestampRoutine = (FUNCPTR)pentiumTscReset;
  243. #endif /* INCLUDE_TIMESTAMP_TSC */
  244.         
  245.         intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  246. /* enable clock interrupt */
  247. sysIntEnablePIC (PIT0_INT_LVL);
  248. sysClkRunning = TRUE;
  249. #if defined (INCLUDE_TIMESTAMP_TSC)
  250. if (sysTimestampFreqValue == 0) /* get TSC freq */
  251.     {
  252.     FUNCPTR oldFunc = sysTimestampRoutine;
  253.     sysTimestampRoutine = (FUNCPTR)sysTimestampFreqGet;
  254.     taskDelay (sysClkTicksPerSecond + 5); /* wait 1 sec */
  255.     sysTimestampRoutine = oldFunc;
  256.     }
  257. #endif /* defined (INCLUDE_TIMESTAMP_TSC) */
  258. }
  259.     }
  260. /*******************************************************************************
  261. *
  262. * sysClkRateGet - get the system clock rate
  263. *
  264. * This routine returns the system clock rate.
  265. *
  266. * RETURNS: The number of ticks per second of the system clock.
  267. *
  268. * SEE ALSO: sysClkEnable(), sysClkRateSet()
  269. */
  270. int sysClkRateGet (void)
  271.     {
  272.     return (sysClkTicksPerSecond);
  273.     }
  274. /*******************************************************************************
  275. *
  276. * sysClkRateSet - set the system clock rate
  277. *
  278. * This routine sets the interrupt rate of the system clock.
  279. * It is called by usrRoot() in usrConfig.c.
  280. *
  281. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  282. *
  283. * SEE ALSO: sysClkEnable(), sysClkRateGet()
  284. */
  285. STATUS sysClkRateSet
  286.     (
  287.     int ticksPerSecond     /* number of clock interrupts per second */
  288.     )
  289.     {
  290.     if (ticksPerSecond < SYS_CLK_RATE_MIN || ticksPerSecond > SYS_CLK_RATE_MAX)
  291. return (ERROR);
  292.     sysClkTicksPerSecond = ticksPerSecond;
  293.     if (sysClkRunning)
  294. {
  295. sysClkDisable ();
  296. sysClkEnable ();
  297. }
  298.     return (OK);
  299.     }
  300. #ifdef PIT1_FOR_AUX
  301. /*******************************************************************************
  302. *
  303. * sysAuxClkInt - handle an auxiliary clock interrupt
  304. *
  305. * This routine handles an auxiliary clock interrupt.  It acknowledges the
  306. * interrupt and calls the routine installed by sysAuxClkConnect().
  307. *
  308. * RETURNS: N/A
  309. */
  310. void sysAuxClkInt (void)
  311.     {
  312.     /* call auxiliary clock service routine */
  313.     if (sysAuxClkRoutine != NULL)
  314. (*sysAuxClkRoutine) (sysAuxClkArg);
  315.     }
  316. /*******************************************************************************
  317. *
  318. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  319. *
  320. * This routine specifies the interrupt service routine to be called at each
  321. * auxiliary clock interrupt.  It does not enable auxiliary clock interrupts.
  322. *
  323. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  324. *
  325. * SEE ALSO: intConnect(), sysAuxClkEnable()
  326. */
  327. STATUS sysAuxClkConnect
  328.     (
  329.     FUNCPTR routine,    /* routine called at each aux clock interrupt    */
  330.     int arg             /* argument to auxiliary clock interrupt routine */
  331.     )
  332.     {
  333.     sysAuxClkRoutine = routine;
  334.     sysAuxClkArg = arg;
  335.     return (OK);
  336.     }
  337. /*******************************************************************************
  338. *
  339. * sysAuxClkDisable - turn off auxiliary clock interrupts
  340. *
  341. * This routine disables auxiliary clock interrupts.
  342. *
  343. * RETURNS: N/A
  344. *
  345. * SEE ALSO: sysAuxClkEnable()
  346. */
  347. void sysAuxClkDisable (void)
  348.     {
  349.     if (sysAuxClkRunning)
  350.         {
  351. sysOutByte (PIT_CMD (PIT_BASE_ADR), 0x78);
  352. sysOutByte (PIT_CNT1 (PIT_BASE_ADR), LSB(0));
  353. sysOutByte (PIT_CNT1 (PIT_BASE_ADR), MSB(0));
  354. sysIntDisablePIC (PIT1_INT_LVL);
  355. sysAuxClkRunning = FALSE;
  356.         }
  357.     }
  358. /*******************************************************************************
  359. *
  360. * sysAuxClkEnable - turn on auxiliary clock interrupts
  361. *
  362. * This routine enables auxiliary clock interrupts.
  363. *
  364. * RETURNS: N/A
  365. *
  366. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  367. */
  368. void sysAuxClkEnable (void)
  369.     {
  370.     UINT tc;
  371.     if (!sysAuxClkRunning)
  372. {
  373. tc = PIT_CLOCK / sysAuxClkTicksPerSecond;
  374. sysOutByte (PIT_CMD (PIT_BASE_ADR), 0x76);
  375. sysOutByte (PIT_CNT1 (PIT_BASE_ADR), LSB(tc));
  376. sysOutByte (PIT_CNT1 (PIT_BASE_ADR), MSB(tc));
  377. /* enable clock interrupt */
  378. sysIntEnablePIC (PIT1_INT_LVL);
  379. sysAuxClkRunning = TRUE;
  380. }
  381.     }
  382. /*******************************************************************************
  383. *
  384. * sysAuxClkRateGet - get the auxiliary clock rate
  385. *
  386. * This routine returns the interrupt rate of the auxiliary clock.
  387. *
  388. * RETURNS: The number of ticks per second of the auxiliary clock.
  389. *
  390. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  391. */
  392. int sysAuxClkRateGet (void)
  393.     {
  394.     return (sysAuxClkTicksPerSecond);
  395.     }
  396. /*******************************************************************************
  397. *
  398. * sysAuxClkRateSet - set the auxiliary clock rate
  399. *
  400. * This routine sets the interrupt rate of the auxiliary clock.  It does not
  401. * enable auxiliary clock interrupts.
  402. *
  403. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  404. *
  405. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  406. */
  407. STATUS sysAuxClkRateSet
  408.     (
  409.     int ticksPerSecond  /* number of clock interrupts per second */
  410.     )
  411.     {
  412.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  413.         return (ERROR);
  414.     sysAuxClkTicksPerSecond = ticksPerSecond;
  415.     if (sysAuxClkRunning)
  416. {
  417. sysAuxClkDisable ();
  418. sysAuxClkEnable ();
  419. }
  420.     return (OK);
  421.     }
  422. #else /*PIT1_FOR_AUX*/
  423. /*******************************************************************************
  424. *
  425. * sysAuxClkInt - handle an auxiliary clock interrupt
  426. *
  427. * This routine handles an auxiliary clock interrupt.  It acknowledges the
  428. * interrupt and calls the routine installed by sysAuxClkConnect().
  429. *
  430. * RETURNS: N/A
  431. */
  432. void sysAuxClkInt (void)
  433.     {
  434.     int oldLevel;
  435.     /* acknowledge the interrupt */
  436.     oldLevel = intLock (); /* LOCK INTERRUPT */
  437.     sysOutByte (RTC_INDEX, MC146818_STATUS_C);
  438.     sysInByte (RTC_DATA);
  439.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  440.     /* call auxiliary clock service routine */
  441.     if (sysAuxClkRoutine != NULL)
  442. (*sysAuxClkRoutine) (sysAuxClkArg);
  443.     }
  444. /*******************************************************************************
  445. *
  446. * sysAuxClkConnect - connect a routine to the auxiliary clock interrupt
  447. *
  448. * This routine specifies the interrupt service routine to be called at each
  449. * auxiliary clock interrupt.  It does not enable auxiliary clock interrupts.
  450. *
  451. * RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.
  452. *
  453. * SEE ALSO: intConnect(), sysAuxClkEnable()
  454. */
  455. STATUS sysAuxClkConnect
  456.     (
  457.     FUNCPTR routine,    /* routine called at each aux clock interrupt */
  458.     int arg             /* argument to auxiliary clock interrupt routine */
  459.     )
  460.     {
  461.     sysAuxClkRoutine = routine;
  462.     sysAuxClkArg = arg;
  463.     return (OK);
  464.     }
  465. /*******************************************************************************
  466. *
  467. * sysAuxClkDisable - turn off auxiliary clock interrupts
  468. *
  469. * This routine disables auxiliary clock interrupts.
  470. *
  471. * RETURNS: N/A
  472. *
  473. * SEE ALSO: sysAuxClkEnable()
  474. */
  475. void sysAuxClkDisable (void)
  476.     {
  477.     if (sysAuxClkRunning)
  478.         {
  479. /* disable interrupts */
  480. sysOutByte (RTC_INDEX, MC146818_STATUS_B);
  481. sysOutByte (RTC_DATA, MC146818_24);
  482. sysIntDisablePIC (RTC_INT_LVL);
  483. sysAuxClkRunning = FALSE;
  484.         }
  485.     }
  486. /*******************************************************************************
  487. *
  488. * sysAuxClkEnable - turn on auxiliary clock interrupts
  489. *
  490. * This routine enables auxiliary clock interrupts.
  491. *
  492. * RETURNS: N/A
  493. *
  494. * SEE ALSO: sysAuxClkConnect(), sysAuxClkDisable(), sysAuxClkRateSet()
  495. */
  496. void sysAuxClkEnable (void)
  497.     {
  498.     int ix;
  499.     char statusA;
  500.     int oldLevel;
  501.     if (!sysAuxClkRunning)
  502.         {
  503. /* set an interrupt rate */
  504. for (ix = 0; ix < NELEMENTS (auxTable); ix++)
  505.     {
  506.     if (auxTable [ix].rate == sysAuxClkTicksPerSecond)
  507. {
  508.         sysOutByte (RTC_INDEX, MC146818_STATUS_A);
  509.         statusA = sysInByte (RTC_DATA) & ~MC146818_RS_BITS;
  510.         sysOutByte (RTC_INDEX, MC146818_STATUS_A);
  511.         sysOutByte (RTC_DATA, statusA | auxTable [ix].bits);
  512. break;
  513. }
  514.     }
  515. /* start the timer */
  516.         oldLevel = intLock (); /* LOCK INTERRUPT */
  517.         sysOutByte (RTC_INDEX, MC146818_STATUS_C); /* clear Int Flags */
  518.         sysInByte (RTC_DATA);
  519. sysOutByte (RTC_INDEX, MC146818_STATUS_B); /* set PIE */
  520. sysOutByte (RTC_DATA, MC146818_PIE | MC146818_24);
  521. sysIntEnablePIC (RTC_INT_LVL);
  522. sysAuxClkRunning = TRUE;
  523.         intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  524. }
  525.     }
  526. /*******************************************************************************
  527. *
  528. * sysAuxClkRateGet - get the auxiliary clock rate
  529. *
  530. * This routine returns the interrupt rate of the auxiliary clock.
  531. *
  532. * RETURNS: The number of ticks per second of the auxiliary clock.
  533. *
  534. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateSet()
  535. */
  536. int sysAuxClkRateGet (void)
  537.     {
  538.     return (sysAuxClkTicksPerSecond);
  539.     }
  540. /*******************************************************************************
  541. *
  542. * sysAuxClkRateSet - set the auxiliary clock rate
  543. *
  544. * This routine sets the interrupt rate of the auxiliary clock.  It does not
  545. * enable auxiliary clock interrupts.
  546. *
  547. * RETURNS: OK, or ERROR if the tick rate is invalid or the timer cannot be set.
  548. *
  549. * SEE ALSO: sysAuxClkEnable(), sysAuxClkRateGet()
  550. */
  551. STATUS sysAuxClkRateSet
  552.     (
  553.     int ticksPerSecond  /* number of clock interrupts per second */
  554.     )
  555.     {
  556.     int ix; /* hold temporary variable */
  557.     BOOL match; /* hold the match status */
  558.     match = FALSE;  /* initialize to false */
  559.     if (ticksPerSecond < AUX_CLK_RATE_MIN || ticksPerSecond > AUX_CLK_RATE_MAX)
  560.         return (ERROR);
  561.     for (ix = 0; ix < NELEMENTS (auxTable); ix++)
  562. {
  563. if (auxTable [ix].rate == ticksPerSecond)
  564.     {
  565.     sysAuxClkTicksPerSecond = ticksPerSecond;
  566.     match = TRUE;
  567.     break;
  568.     }
  569. }
  570.     if (!match) /* ticksPerSecond not matching the values in table */
  571.        return (ERROR);
  572.     if (sysAuxClkRunning)
  573. {
  574. sysAuxClkDisable ();
  575. sysAuxClkEnable ();
  576. }
  577.     return (OK);
  578.     }
  579. #endif /* PIT1_FOR_AUX */
  580. #if defined(INCLUDE_TIMESTAMP_PIT2) || defined (INCLUDE_TIMESTAMP_TSC)
  581. /*******************************************************************************
  582. *
  583. * sysTimestampConnect - connect a user routine to the timestamp timer interrupt
  584. *
  585. * This routine specifies the user interrupt routine to be called at each
  586. * timestamp timer interrupt.  It does not enable the timestamp timer itself.
  587. *
  588. * RETURNS: OK, or ERROR if sysTimestampInt() interrupt handler is not used.
  589. */
  590.  
  591. STATUS sysTimestampConnect
  592.     (
  593.     FUNCPTR routine, /* routine called at each timestamp timer interrupt */
  594.     int arg /* argument with which to call routine */
  595.     )
  596.     {
  597.     return (ERROR);
  598.     }
  599. /*******************************************************************************
  600. *
  601. * sysTimestampEnable - initialize and enable the timestamp timer
  602. *
  603. * This routine connects the timestamp timer interrupt and initializes the
  604. * counter registers.  If the timestamp timer is already running, this routine
  605. * merely resets the timer counter.
  606. *
  607. * The rate of the timestamp timer should be set explicitly within the BSP,
  608. * in the sysHwInit() routine.  This routine does not intialize the timer
  609. * rate.  
  610. *
  611. * RETURNS: OK, or ERROR if the timestamp timer cannot be enabled.
  612. */
  613.  
  614. STATUS sysTimestampEnable (void)
  615.     {
  616.     if (sysTimestampRunning)
  617. return (OK);
  618.     
  619.     sysTimestampRunning = TRUE;
  620.     return (OK);
  621.     }
  622. /********************************************************************************
  623. * sysTimestampDisable - disable the timestamp timer
  624. *
  625. * This routine disables the timestamp timer.  Interrupts are not disabled,
  626. * although the tick counter will not increment after the timestamp timer
  627. * is disabled, thus interrupts will no longer be generated.
  628. *
  629. * RETURNS: OK, or ERROR if the timestamp timer cannot be disabled.
  630. */
  631.  
  632. STATUS sysTimestampDisable (void)
  633.     {
  634.     if (sysTimestampRunning)
  635. {
  636.         sysTimestampRunning = FALSE;
  637. }
  638.     return (ERROR);
  639.     }
  640. /*******************************************************************************
  641. *
  642. * sysTimestampPeriod - get the timestamp timer period
  643. *
  644. * This routine returns the period of the timestamp timer in ticks.
  645. * The period, or terminal count, is the number of ticks to which the timestamp
  646. * timer will count before rolling over and restarting the counting process.
  647. *
  648. * RETURNS: The period of the timestamp timer in counter ticks.
  649. */
  650.  
  651. UINT32 sysTimestampPeriod (void)
  652.     {
  653.     sysTimestampPeriodValue = sysTimestampFreq () / sysClkTicksPerSecond;
  654.     return (sysTimestampPeriodValue);
  655.     }
  656. /*******************************************************************************
  657. *
  658. * sysTimestampFreq - get the timestamp timer clock frequency
  659. *
  660. * This routine returns the frequency of the timer clock, in ticks per second.
  661. * The rate of the timestamp timer should be set explicitly within the BSP,
  662. * in the sysHwInit() routine.
  663. *
  664. * RETURNS: The timestamp timer clock frequency, in ticks per second.
  665. */
  666.  
  667. UINT32 sysTimestampFreq (void)
  668.     {
  669. #ifdef INCLUDE_TIMESTAMP_TSC
  670.     return (sysTimestampFreqValue);
  671. #else
  672.     return (PIT_CLOCK * 2);
  673. #endif /* INCLUDE_TIMESTAMP_TSC */
  674.     }
  675.  
  676. #ifdef INCLUDE_TIMESTAMP_TSC
  677. LOCAL void sysTimestampFreqGet (void)
  678.     {
  679.     if (sysTimestampTickCount == sysClkTicksPerSecond)
  680. {
  681. sysTimestampFreqValue = pentiumTscGet32 ();
  682. sysTimestampTickCount = 0;
  683. }
  684.     if (sysTimestampTickCount == 0)
  685. pentiumTscReset ();
  686.     sysTimestampTickCount++;
  687.     }
  688. #endif /* INCLUDE_TIMESTAMP_TSC */
  689. /*******************************************************************************
  690. *
  691. * sysTimestamp - get the timestamp timer tick count
  692. *
  693. * This routine returns the current value of the timestamp timer tick counter.
  694. * The tick count can be converted to seconds by dividing by the return of
  695. * sysTimestampFreq().
  696. *
  697. * This routine should be called with interrupts locked.  If interrupts are
  698. * not already locked, sysTimestampLock() should be used instead.
  699. *
  700. * RETURNS: The current timestamp timer tick count.
  701. *
  702. * SEE ALSO: sysTimestampLock()
  703. */
  704.  
  705. UINT32 sysTimestamp (void)
  706.     {
  707. #ifdef INCLUDE_TIMESTAMP_TSC
  708.     return (pentiumTscGet32 ());
  709. #else
  710.     union uc uc;
  711.     sysOutByte (PIT_CMD (PIT_BASE_ADR), 0x80);
  712.     uc.count08[0] = sysInByte (PIT_CNT2 (PIT_BASE_ADR));
  713.     uc.count08[1] = sysInByte (PIT_CNT2 (PIT_BASE_ADR));
  714.     return (sysTimestampPeriodValue - uc.count16);
  715. #endif /* INCLUDE_TIMESTAMP_TSC */
  716.     }
  717. /*******************************************************************************
  718. *
  719. * sysTimestampLock - get the timestamp timer tick count
  720. *
  721. * This routine returns the current value of the timestamp timer tick counter.
  722. * The tick count can be converted to seconds by dividing by the return of
  723. * sysTimestampFreq().
  724. *
  725. * This routine locks interrupts for cases where it is necessary to stop the
  726. * tick counter in order to read it, or when two independent counters must
  727. * be read.  If interrupts are already locked, sysTimestamp() should be
  728. * used instead.
  729. *
  730. * RETURNS: The current timestamp timer tick count.
  731. *
  732. * SEE ALSO: sysTimestamp()
  733. */
  734.  
  735. UINT32 sysTimestampLock (void)
  736.     {
  737. #ifdef INCLUDE_TIMESTAMP_TSC
  738.     /* pentiumTscGet32() has just one instruction "rdtsc", so locking
  739.      * the interrupt is not necessary.
  740.      */
  741.     return (pentiumTscGet32 ());
  742. #else
  743.     int oldLevel;
  744.     union uc uc;
  745.     oldLevel = intLock ();
  746.     sysOutByte (PIT_CMD (PIT_BASE_ADR), 0x80);
  747.     uc.count08[0] = sysInByte (PIT_CNT2 (PIT_BASE_ADR));
  748.     uc.count08[1] = sysInByte (PIT_CNT2 (PIT_BASE_ADR));
  749.     intUnlock (oldLevel);
  750.     return (sysTimestampPeriodValue - uc.count16);
  751. #endif /* INCLUDE_TIMESTAMP_TSC */
  752.     }
  753. #endif /* INCLUDE_TIMESTAMP_PIT2 || INCLUDE_TIMESTAMP_TSC */