4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
23 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
24 /* All Rights Reserved */
27 * Copyright (c) 1997, by Sun Microsystems, Inc.
28 * All rights reserved.
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
37 #include <sys/hrtcntl.h>
38 #include <sys/errno.h>
39 #include <sys/hrtsys.h>
41 #include <sys/timer.h>
42 #include <sys/cmn_err.h>
45 * This file contains the code that manages the hardware clocks and
46 * timers. We must provide UNIX with a HZ resolution clock and give
47 * the user an interface to the timers through system calls.
50 static int hrt_checkres(ulong res
);
51 static int hrt_bsd_cancel(int clock
);
52 static int hrt_checkclock(register int clock
);
55 * Argument vectors for the various flavors of hrtsys().
83 * Hrtcntl (time control) system call.
90 register struct hrtcntla
*uap
;
93 register int error
= 0;
98 case HRT_TOFD
: /* Get the time of day */
100 if (uap
->clk
!= CLK_STD
) {
105 if (copyin((caddr_t
)uap
->hrtp
,
106 (caddr_t
)&temptofd
, sizeof (hrtimes_t
))) {
111 if ((error
= hrt_checkres(temptofd
.hrt_res
)))
114 hrt_gettofd(&temptofd
);
116 if (copyout((caddr_t
)&temptofd
,
117 (caddr_t
)uap
->hrtp
, sizeof (hrtimes_t
)))
130 * Hrtalarm (start one or more alarms) system call.
135 register struct hrtalarma
*uap
;
138 register hrtcmd_t
*cp
;
149 * Return EINVAL for negative and zero counts.
159 /* Loop through and process each command. */
161 for (cnt
= 0; cnt
< uap
->cmds
; cnt
++, hrcmdp
++) {
163 if (copyin((caddr_t
)hrcmdp
, (caddr_t
)cp
, sizeof (hrtcmd_t
)))
169 * If we try to post a Berkley Timer remove
173 if (cmd
== HRT_BSD
|| cmd
== HRT_BSD_REP
)
174 (void) hrt_bsd_cancel(cp
->hrtc_clk
);
176 /* See what kind of command we have. */
179 case HRT_BSD
: /* one-shot timer */
181 struct itimerval itv
;
184 if (error
= hrt_checkclock(cp
->hrtc_clk
))
186 switch (cp
->hrtc_clk
) {
191 which
= ITIMER_VIRTUAL
;
200 itv
.it_value
.tv_sec
= cp
->hrtc_int
.hrt_secs
;
201 itv
.it_value
.tv_usec
= cp
->hrtc_int
.hrt_rem
;
202 itv
.it_interval
.tv_sec
= 0;
203 itv
.it_interval
.tv_usec
= 0;
204 (void) xsetitimer(which
, &itv
, 1);
211 struct itimerval itv
;
214 switch (cp
->hrtc_clk
) {
219 which
= ITIMER_VIRTUAL
;
228 itv
.it_value
.tv_sec
= cp
->hrtc_tod
.hrt_secs
;
229 itv
.it_value
.tv_usec
= cp
->hrtc_tod
.hrt_rem
;
230 itv
.it_interval
.tv_sec
= cp
->hrtc_int
.hrt_secs
;
231 itv
.it_interval
.tv_usec
= cp
->hrtc_int
.hrt_rem
;
232 (void) xsetitimer(which
, &itv
, 1);
239 struct itimerval itv
;
242 switch (cp
->hrtc_clk
) {
247 which
= ITIMER_VIRTUAL
;
256 (void) xgetitimer(which
, &itv
, 1);
257 delay_ht
.hrt_secs
= itv
.it_value
.tv_sec
;
258 delay_ht
.hrt_rem
= itv
.it_value
.tv_usec
;
261 if (copyout((caddr_t
)&delay_ht
,
262 (caddr_t
)&hrcmdp
->hrtc_int
, sizeof (hrtimes_t
)))
268 if (error
= hrt_checkclock(cp
->hrtc_clk
))
271 error
= hrt_bsd_cancel(cp
->hrtc_clk
);
281 cp
->hrtc_flags
|= HRTF_ERROR
;
282 cp
->hrtc_error
= error
;
284 cp
->hrtc_flags
|= HRTF_DONE
;
288 if (copyout((caddr_t
)&cp
->hrtc_flags
,
289 (caddr_t
)&hrcmdp
->hrtc_flags
,
290 sizeof (cp
->hrtc_flags
) + sizeof (cp
->hrtc_error
))) {
295 rvp
->r_val1
= alarm_cnt
;
305 hrt_bsd_cancel(int clock
)
307 struct itimerval itv
;
315 which
= ITIMER_VIRTUAL
;
323 itv
.it_value
.tv_sec
= 0;
324 itv
.it_value
.tv_usec
= 0;
325 (void) xsetitimer(which
, &itv
, 1);
331 * Return 0 if "res" is a legal resolution. Otherwise,
332 * return an error code, ERANGE.
336 hrt_checkres(ulong res
)
338 if (res
== 0 || res
> NANOSEC
)
344 * Return 0 if "clock" is a valid clock. Otherwise,
345 * return an error code, EINVAL.
349 hrt_checkclock(register int clock
)
362 * Set the current time of day in a specified resolution into
363 * a hrtimes_t structure.
366 hrt_gettofd(hrtimes_t
*td
)
368 ulong new_res
= td
->hrt_res
;
372 td
->hrt_secs
= ts
.tv_sec
;
373 td
->hrt_rem
= ts
.tv_nsec
;
374 td
->hrt_res
= NANOSEC
;
376 if (new_res
!= td
->hrt_res
) {
377 td
->hrt_rem
/= NANOSEC
/ new_res
;
378 td
->hrt_res
= new_res
;
384 * System entry point for hrtcntl, hrtalarm
390 register struct hrtsysa
*uap
;
395 switch (uap
->opcode
) {
397 error
= hrtcntl((struct hrtcntla
*)uap
, rvp
);
400 error
= hrtalarm((struct hrtalarma
*)uap
, rvp
);