PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/netbsd/src/sys/arch/vax/vax/clock.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 329 lines | 208 code | 49 blank | 72 comment | 45 complexity | 608ec7cbcc329729cd9be6494cae3327 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* $NetBSD: clock.c,v 1.55 2010/12/14 23:44:49 matt Exp $ */
  2. /*
  3. * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed at Ludd, University of Lule}.
  17. * 4. The name of the author may not be used to endorse or promote products
  18. * derived from this software without specific prior written permission
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  21. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  22. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  23. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include <sys/cdefs.h>
  32. __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.55 2010/12/14 23:44:49 matt Exp $");
  33. #include <sys/param.h>
  34. #include <sys/systm.h>
  35. #include <sys/cpu.h>
  36. #include <sys/device.h>
  37. #include <sys/timetc.h>
  38. #include <sys/kernel.h>
  39. #include <machine/sid.h>
  40. #include <machine/clock.h>
  41. #include "opt_cputype.h"
  42. struct evcnt clock_misscnt =
  43. EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "clock", "intr miss");
  44. EVCNT_ATTACH_STATIC(clock_misscnt);
  45. struct evcnt clock_intrcnt =
  46. EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "clock", "intr");
  47. EVCNT_ATTACH_STATIC(clock_intrcnt);
  48. static int vax_gettime(todr_chip_handle_t, struct timeval *);
  49. static int vax_settime(todr_chip_handle_t, struct timeval *);
  50. static struct todr_chip_handle todr_handle = {
  51. .todr_gettime = vax_gettime,
  52. .todr_settime = vax_settime,
  53. };
  54. #if VAX46 || VAXANY
  55. static u_int
  56. vax_diag_get_counter(struct timecounter *tc)
  57. {
  58. extern struct vs_cpu *ka46_cpu;
  59. int cur_hardclock;
  60. u_int counter;
  61. do {
  62. cur_hardclock = hardclock_ticks;
  63. counter = *(volatile u_int *)&ka46_cpu->vc_diagtimu;
  64. } while (cur_hardclock != hardclock_ticks);
  65. counter = (counter & 0x3ff) + (counter >> 16) * 1024;
  66. return counter + hardclock_ticks * tick;
  67. }
  68. #endif
  69. static u_int
  70. vax_mfpr_get_counter(struct timecounter *tc)
  71. {
  72. int cur_hardclock;
  73. u_int counter;
  74. static int prev_count, prev_hardclock;
  75. do {
  76. cur_hardclock = hardclock_ticks;
  77. counter = mfpr(PR_ICR) + tick;
  78. } while (cur_hardclock != hardclock_ticks);
  79. /*
  80. * Handle interval counter wrapping with interrupts blocked.
  81. * If the current hardclock_ticks is less than what we saw
  82. * previously, use the previous value.
  83. * If the interval counter is smaller, assume it has wrapped,
  84. * and if the [adjusted] current hardclock ticks is the same
  85. * as what we saw previously, increment the local copy of
  86. * the hardclock ticks.
  87. */
  88. if (cur_hardclock < prev_hardclock)
  89. cur_hardclock = prev_hardclock;
  90. if (counter < prev_count && cur_hardclock == prev_hardclock)
  91. cur_hardclock++;
  92. prev_count = counter;
  93. prev_hardclock=cur_hardclock;
  94. return counter + cur_hardclock * tick;
  95. }
  96. #if VAX46 || VAXANY
  97. static struct timecounter vax_diag_tc = {
  98. vax_diag_get_counter, /* get_timecount */
  99. 0, /* no poll_pps */
  100. ~0u, /* counter_mask */
  101. 1000000, /* frequency */
  102. "diagtimer", /* name */
  103. 100, /* quality */
  104. NULL, /* prev */
  105. NULL, /* next */
  106. };
  107. #endif
  108. static struct timecounter vax_mfpr_tc = {
  109. vax_mfpr_get_counter, /* get_timecount */
  110. 0, /* no poll_pps */
  111. ~0u, /* counter_mask */
  112. 1000000, /* frequency */
  113. "mfpr", /* name */
  114. 100, /* quality */
  115. NULL, /* prev */
  116. NULL, /* next */
  117. };
  118. /*
  119. * A delayloop that delays about the number of milliseconds that is
  120. * given as argument.
  121. */
  122. void
  123. delay(int i)
  124. {
  125. __asm ("1: sobgtr %0, 1b" : : "r" (dep_call->cpu_vups * i));
  126. }
  127. /*
  128. * On all VAXen there are a microsecond clock that should
  129. * be used for interval interrupts. Some CPUs don't use the ICR interval
  130. * register but it doesn't hurt to load it anyway.
  131. */
  132. void
  133. cpu_initclocks(void)
  134. {
  135. mtpr(-10000, PR_NICR); /* Load in count register */
  136. mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */
  137. todr_attach(&todr_handle);
  138. #if VAX46 || VAXANY
  139. if (vax_boardtype == VAX_BTYP_46)
  140. tc_init(&vax_diag_tc);
  141. #endif
  142. if (vax_boardtype != VAX_BTYP_46 && vax_boardtype != VAX_BTYP_48)
  143. tc_init(&vax_mfpr_tc);
  144. }
  145. int
  146. vax_gettime(todr_chip_handle_t handle, struct timeval *tvp)
  147. {
  148. tvp->tv_sec = handle->base_time;
  149. return (*dep_call->cpu_gettime)(tvp);
  150. }
  151. int
  152. vax_settime(todr_chip_handle_t handle, struct timeval *tvp)
  153. {
  154. (*dep_call->cpu_settime)(tvp);
  155. return 0;
  156. }
  157. /*
  158. * There are two types of real-time battery-backed up clocks on
  159. * VAX computers, one with a register that counts up every 1/100 second,
  160. * one with a clock chip that delivers time. For the register clock
  161. * we have a generic version, and for the chip clock there are
  162. * support routines for time conversion.
  163. */
  164. /*
  165. * Converts a year to corresponding number of ticks.
  166. */
  167. int
  168. yeartonum(int y)
  169. {
  170. int n;
  171. for (n = 0, y -= 1; y > 1969; y--)
  172. n += SECPERYEAR(y);
  173. return n;
  174. }
  175. /*
  176. * Converts tick number to a year 1970 ->
  177. */
  178. int
  179. numtoyear(int num)
  180. {
  181. int y = 1970, j;
  182. while(num >= (j = SECPERYEAR(y))) {
  183. y++;
  184. num -= j;
  185. }
  186. return y;
  187. }
  188. #if VAX750 || VAX780 || VAX8600 || VAX650 || \
  189. VAX660 || VAX670 || VAX680 || VAX53 || VAXANY
  190. /*
  191. * Reads the TODR register; returns a (probably) true tick value, and 0 is
  192. * success or EINVAL if failed. The year is based on the argument
  193. * year; the TODR doesn't hold years.
  194. */
  195. int
  196. generic_gettime(struct timeval *tvp)
  197. {
  198. unsigned klocka = mfpr(PR_TODR);
  199. /*
  200. * Sanity check.
  201. */
  202. if (klocka < TODRBASE) {
  203. if (klocka == 0)
  204. printf("TODR stopped");
  205. else
  206. printf("TODR too small");
  207. return EINVAL;
  208. }
  209. tvp->tv_sec = yeartonum(numtoyear(tvp->tv_sec)) + (klocka - TODRBASE) / 100;
  210. return 0;
  211. }
  212. /*
  213. * Takes the current system time and writes it to the TODR.
  214. */
  215. void
  216. generic_settime(struct timeval *tvp)
  217. {
  218. unsigned tid = tvp->tv_sec, bastid;
  219. bastid = tid - yeartonum(numtoyear(tid));
  220. mtpr((bastid * 100) + TODRBASE, PR_TODR);
  221. }
  222. #endif
  223. #if VAX630 || VAX410 || VAX43 || VAX8200 || VAX46 || VAX48 || VAX49 || VAXANY
  224. volatile short *clk_page; /* where the chip is mapped in virtual memory */
  225. int clk_adrshift; /* how much to multiply the in-page address with */
  226. int clk_tweak; /* Offset of time into word. */
  227. #define REGPEEK(off) (clk_page[off << clk_adrshift] >> clk_tweak)
  228. #define REGPOKE(off, v) (clk_page[off << clk_adrshift] = ((v) << clk_tweak))
  229. int
  230. chip_gettime(struct timeval *tvp)
  231. {
  232. struct clock_ymdhms c;
  233. int timeout = 1<<15, s;
  234. #ifdef DIAGNOSTIC
  235. if (clk_page == 0)
  236. panic("trying to use unset chip clock page");
  237. #endif
  238. if ((REGPEEK(CSRD_OFF) & CSRD_VRT) == 0) {
  239. printf("WARNING: TOY clock not marked valid");
  240. return EINVAL;
  241. }
  242. while (REGPEEK(CSRA_OFF) & CSRA_UIP) {
  243. if (--timeout == 0) {
  244. printf ("TOY clock timed out");
  245. return ETIMEDOUT;
  246. }
  247. }
  248. s = splhigh();
  249. c.dt_year = ((u_char)REGPEEK(YR_OFF)) + 1970;
  250. c.dt_mon = REGPEEK(MON_OFF);
  251. c.dt_day = REGPEEK(DAY_OFF);
  252. c.dt_wday = REGPEEK(WDAY_OFF);
  253. c.dt_hour = REGPEEK(HR_OFF);
  254. c.dt_min = REGPEEK(MIN_OFF);
  255. c.dt_sec = REGPEEK(SEC_OFF);
  256. splx(s);
  257. tvp->tv_sec = clock_ymdhms_to_secs(&c);
  258. tvp->tv_usec = 0;
  259. return 0;
  260. }
  261. void
  262. chip_settime(struct timeval *tvp)
  263. {
  264. struct clock_ymdhms c;
  265. #ifdef DIAGNOSTIC
  266. if (clk_page == 0)
  267. panic("trying to use unset chip clock page");
  268. #endif
  269. REGPOKE(CSRB_OFF, CSRB_SET);
  270. clock_secs_to_ymdhms(tvp->tv_sec, &c);
  271. REGPOKE(YR_OFF, ((u_char)(c.dt_year - 1970)));
  272. REGPOKE(MON_OFF, c.dt_mon);
  273. REGPOKE(DAY_OFF, c.dt_day);
  274. REGPOKE(WDAY_OFF, c.dt_wday);
  275. REGPOKE(HR_OFF, c.dt_hour);
  276. REGPOKE(MIN_OFF, c.dt_min);
  277. REGPOKE(SEC_OFF, c.dt_sec);
  278. REGPOKE(CSRB_OFF, CSRB_DM|CSRB_24);
  279. };
  280. #endif