Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

334 lines
7.7 KiB

4 years ago
  1. //#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/jxtime.c,v 1.1 1994/10/13 15:47:06 holli Exp $")
  2. /*++
  3. Copyright (c) 1993 SNI
  4. Module Name:
  5. SNItime.c
  6. Abstract:
  7. This module implements the HAL set/query realtime clock routines for
  8. a MIPS R4000 SNI system.
  9. Environment:
  10. Kernel mode
  11. --*/
  12. #include "halp.h"
  13. #define NVINDEX_STATE 0x6
  14. #define NVSTATE_TODVALID 0x1
  15. #define bcd_to_dec(x) ( ((((x) >> 4 ) & 0xf ) * 10 ) + ((x) & 0xf) )
  16. #define dec_to_bcd(x) ( (((x) / 10) << 4) | ((x) % 10) )
  17. #define RTC_NVRAM_SIZE 0x7ff // NVRAM size on this chip
  18. typedef struct _RealTimeClock {
  19. struct rtc_mem {
  20. UCHAR value;
  21. UCHAR FILL0[3]; // byte-wide device
  22. } Memory[RTC_NVRAM_SIZE]; // Non-volatile ram
  23. UCHAR ControlRegister; // control register
  24. UCHAR FILL1[3];
  25. } RealTimeClock, *PRealTimeClock;
  26. /* Smartwatch offset registers */
  27. #define REG_CENT_SECS 0
  28. #define REG_SECS 1
  29. #define REG_MINS 2
  30. #define REG_HOURS 3
  31. #define REG_DAY_W 4
  32. #define REG_DAY_M 5
  33. #define REG_MONTH 6
  34. #define REG_YEAR 7
  35. /* masks to get valid information */
  36. #define MASK_CENT_SECS 0xFF
  37. #define MASK_SECS 0x7F
  38. #define MASK_MINS 0x7F
  39. #define MASK_HOURS 0x3F
  40. #define MASK_DAY_W 0x07
  41. #define MASK_DAY_M 0x3F
  42. #define MASK_MONTH 0x1F
  43. #define MASK_YEAR 0xFF
  44. //
  45. // the reference year (we have only two digits for the year on the chip)
  46. //
  47. #define YRREF 1900
  48. //
  49. // Define forward referenced procedure prototypes.
  50. //
  51. BOOLEAN
  52. HalQueryRealTimeClock (
  53. OUT PTIME_FIELDS TimeFields
  54. );
  55. BOOLEAN
  56. HalSetRealTimeClock (
  57. IN PTIME_FIELDS TimeFields
  58. );
  59. VOID
  60. HalpWriteClockRegister(
  61. IN UCHAR number
  62. );
  63. UCHAR
  64. HalpReadClockRegister(
  65. VOID
  66. );
  67. VOID
  68. HalpWritePattern(
  69. VOID
  70. );
  71. BOOLEAN
  72. HalQueryRealTimeClock (
  73. OUT PTIME_FIELDS TimeFields
  74. )
  75. /*++
  76. Routine Description:
  77. This routine queries the realtime clock.
  78. N.B. this comment stand in jxtime.c:
  79. This routine is required to provide any synchronization necessary
  80. to query the realtime clock information.
  81. Arguments:
  82. TimeFields - Supplies a pointer to a time structure that receives
  83. the realtime clock information.
  84. Return Value:
  85. If the power to the realtime clock has not failed, then the time
  86. values are read from the realtime clock and a value of TRUE is
  87. returned. Otherwise, a value of FALSE is returned.
  88. --*/
  89. {
  90. register CSHORT month, dayweek, daymonth, year, hours, mins, secs, msecs;
  91. int i;
  92. UCHAR tmp[8];
  93. KIRQL oldIrql;
  94. KeRaiseIrql(HIGH_LEVEL, &oldIrql);
  95. // write the pattern to gain access to the smartwatch registers
  96. HalpWritePattern();
  97. // Read the 8 registers of smartwatch
  98. for (i = 0; i < 8; i++)
  99. tmp[i] = HalpReadClockRegister();
  100. KeLowerIrql(oldIrql);
  101. // Convert the contents of smartwatch registers into CSHORT
  102. msecs = ( (CSHORT) bcd_to_dec(tmp[REG_CENT_SECS] & MASK_CENT_SECS) ) * 10;
  103. secs = (CSHORT) bcd_to_dec(tmp[REG_SECS] & MASK_SECS);
  104. mins = (CSHORT) bcd_to_dec(tmp[REG_MINS] & MASK_MINS);
  105. hours = (CSHORT) bcd_to_dec(tmp[REG_HOURS] & MASK_HOURS);
  106. daymonth = (CSHORT) bcd_to_dec(tmp[REG_DAY_M] & MASK_DAY_M);
  107. dayweek = (CSHORT) bcd_to_dec(tmp[REG_DAY_W] & MASK_DAY_W);
  108. month = (CSHORT) bcd_to_dec(tmp[REG_MONTH] & MASK_MONTH);
  109. year = (CSHORT) bcd_to_dec(tmp[REG_YEAR] & MASK_YEAR);
  110. if (TimeFields)
  111. {
  112. TimeFields->Year = year+YRREF;
  113. TimeFields->Month = month;
  114. TimeFields->Day = daymonth;
  115. TimeFields->Weekday = dayweek;
  116. TimeFields->Hour = hours;
  117. TimeFields->Minute = mins;
  118. TimeFields->Second = secs;
  119. TimeFields->Milliseconds = msecs;
  120. }
  121. return TRUE;
  122. }
  123. BOOLEAN
  124. HalSetRealTimeClock (
  125. IN PTIME_FIELDS TimeFields
  126. )
  127. /*++
  128. Routine Description:
  129. This routine sets the realtime clock.
  130. N.B. this comment stand in jxtime.c:
  131. This routine is required to provide anq synchronization necessary
  132. to set the realtime clock information.
  133. Arguments:
  134. TimeFields - Supplies a pointer to a time structure that specifies the
  135. realtime clock information.
  136. Return Value:
  137. If the power to the realtime clock has not failed, then the time
  138. values are written to the realtime clock and a value of TRUE is
  139. returned. Otherwise, a value of FALSE is returned.
  140. --*/
  141. {
  142. UCHAR tmp[8];
  143. KIRQL oldIrql;
  144. UCHAR year, month, daymonth, dayweek, hours, mins, secs, msecs;
  145. int i;
  146. //
  147. // If the realtime clock battery is still functioning, then write
  148. // the realtime clock values, and return a function value of TRUE.
  149. // Otherwise, return a function value of FALSE.
  150. //
  151. // this part has to be written
  152. // if (...) return FALSE;
  153. year = (UCHAR) ( (TimeFields->Year - YRREF) % 100 );
  154. month = (UCHAR) TimeFields->Month;
  155. daymonth = (UCHAR) TimeFields->Day;
  156. dayweek = (UCHAR) TimeFields->Weekday;
  157. hours = (UCHAR) TimeFields->Hour;
  158. mins = (UCHAR) TimeFields->Minute;
  159. secs = (UCHAR) TimeFields->Second;
  160. msecs = (UCHAR) TimeFields->Milliseconds;
  161. tmp[REG_CENT_SECS] = (UCHAR) (dec_to_bcd(msecs/10) & MASK_CENT_SECS);
  162. tmp[REG_SECS] = (UCHAR) (dec_to_bcd(secs) & MASK_SECS);
  163. tmp[REG_MINS] = (UCHAR) (dec_to_bcd(mins) & MASK_MINS);
  164. tmp[REG_HOURS] = (UCHAR) (dec_to_bcd(hours) & MASK_HOURS);
  165. tmp[REG_DAY_W] = (UCHAR) (dec_to_bcd(dayweek) & MASK_DAY_W);
  166. tmp[REG_DAY_M] = (UCHAR) (dec_to_bcd(daymonth) & MASK_DAY_M);
  167. tmp[REG_MONTH] = (UCHAR) (dec_to_bcd(month) & MASK_MONTH);
  168. tmp[REG_YEAR] = (UCHAR) (dec_to_bcd(year) & MASK_YEAR);
  169. KeRaiseIrql(HIGH_LEVEL, &oldIrql);
  170. // write the pattern to gain access to the smartwatch registers
  171. HalpWritePattern();
  172. // Write the 8 registers of smartwatch
  173. for (i=0; i <8; i++)
  174. HalpWriteClockRegister(tmp[i]);
  175. KeLowerIrql(oldIrql);
  176. return TRUE;
  177. }
  178. //
  179. // Write a BCD 2-digits number in the smartwatch
  180. // This is done one bit at a time, LSB first
  181. //
  182. VOID
  183. HalpWriteClockRegister(
  184. IN UCHAR number
  185. )
  186. {
  187. PRealTimeClock rtc;
  188. UCHAR i;
  189. rtc = (HalpIsRM200) ? (PRealTimeClock )(RM200_REAL_TIME_CLOCK):
  190. (PRealTimeClock )(RM400_REAL_TIME_CLOCK);
  191. for (i = 1; i <= 8; i++) {
  192. WRITE_REGISTER_UCHAR(&rtc->ControlRegister, number);
  193. number = number >> 1; // next bit to write
  194. }
  195. }
  196. //
  197. // Read a BCD 2-digits number in the smartwatch
  198. // This is done one bit at a time, LSB first
  199. //
  200. UCHAR
  201. HalpReadClockRegister(
  202. VOID
  203. )
  204. {
  205. PRealTimeClock rtc;
  206. UCHAR i;
  207. UCHAR number;
  208. rtc = (HalpIsRM200) ? (PRealTimeClock )(RM200_REAL_TIME_CLOCK):
  209. (PRealTimeClock )(RM400_REAL_TIME_CLOCK);
  210. for (i = 0, number = 0; i < 8; i++) {
  211. number += (READ_REGISTER_UCHAR(&rtc->ControlRegister) & 0x01) << i; // Read a bit and shift it
  212. }
  213. return(number);
  214. }
  215. //
  216. // Write a pattern to gain access to the smartwatch registers
  217. // First we do 9 read's to reset the pointer
  218. //
  219. VOID
  220. HalpWritePattern(
  221. VOID
  222. )
  223. {
  224. // Pattern to use before reading or writing
  225. static UCHAR ClockPattern[4] = {0xc5,0x3a,0xa3,0x5c};
  226. register UCHAR *pt;
  227. register UCHAR i;
  228. for (i = 0; i <= 8; i++) (VOID) HalpReadClockRegister();
  229. for (i = 0, pt = ClockPattern; i < sizeof(ClockPattern); i++) HalpWriteClockRegister(*pt++);
  230. for (i = 0, pt = ClockPattern; i < sizeof(ClockPattern); i++) HalpWriteClockRegister(*pt++);
  231. }