xref: /illumos-gate/usr/src/uts/i86pc/io/hrtimers.c (revision 3df2e8b2)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
237c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
247c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Copyright (c) 1997, by Sun Microsystems, Inc.
287c478bd9Sstevel@tonic-gate  * All rights reserved.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/systm.h>
357c478bd9Sstevel@tonic-gate #include <sys/hrtcntl.h>
367c478bd9Sstevel@tonic-gate #include <sys/errno.h>
377c478bd9Sstevel@tonic-gate #include <sys/hrtsys.h>
387c478bd9Sstevel@tonic-gate #include <sys/time.h>
397c478bd9Sstevel@tonic-gate #include <sys/timer.h>
407c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * This file contains the code that manages the hardware clocks and
447c478bd9Sstevel@tonic-gate  * timers.  We must provide UNIX with a HZ resolution clock and give
457c478bd9Sstevel@tonic-gate  * the user an interface to the timers through system calls.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static int hrt_checkres(ulong res);
497c478bd9Sstevel@tonic-gate static int hrt_bsd_cancel(int clock);
507c478bd9Sstevel@tonic-gate static int hrt_checkclock(register int clock);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * Argument vectors for the various flavors of hrtsys().
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	HRTCNTL		0
577c478bd9Sstevel@tonic-gate #define	HRTALARM	1
587c478bd9Sstevel@tonic-gate #define	HRTSLEEP	2
597c478bd9Sstevel@tonic-gate #define	HRTCANCEL	3
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate struct 	hrtsysa {
627c478bd9Sstevel@tonic-gate 	int	opcode;
637c478bd9Sstevel@tonic-gate };
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate struct	hrtcntla {
667c478bd9Sstevel@tonic-gate 	int		opcode;
677c478bd9Sstevel@tonic-gate 	int		cmd;
687c478bd9Sstevel@tonic-gate 	int		clk;
697c478bd9Sstevel@tonic-gate 	interval_t	*intp;
707c478bd9Sstevel@tonic-gate 	hrtimes_t	*hrtp;
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate struct	hrtalarma {
747c478bd9Sstevel@tonic-gate 	int	opcode;
757c478bd9Sstevel@tonic-gate 	hrtcmd_t	*cmdp;
767c478bd9Sstevel@tonic-gate 	int		cmds;
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate  * Hrtcntl (time control) system call.
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
867c478bd9Sstevel@tonic-gate int
hrtcntl(uap,rvp)877c478bd9Sstevel@tonic-gate hrtcntl(uap, rvp)
887c478bd9Sstevel@tonic-gate 	register struct hrtcntla *uap;
897c478bd9Sstevel@tonic-gate 	rval_t	*rvp;
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	register int	error = 0;
927c478bd9Sstevel@tonic-gate 	hrtimes_t	temptofd;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	switch (uap->cmd) {
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	case HRT_TOFD:	/* Get the time of day */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 		if (uap->clk != CLK_STD) {
997c478bd9Sstevel@tonic-gate 			error = EINVAL;
1007c478bd9Sstevel@tonic-gate 			break;
1017c478bd9Sstevel@tonic-gate 		}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 		if (copyin((caddr_t)uap->hrtp,
1047c478bd9Sstevel@tonic-gate 		    (caddr_t)&temptofd, sizeof (hrtimes_t))) {
1057c478bd9Sstevel@tonic-gate 			error = EFAULT;
1067c478bd9Sstevel@tonic-gate 			break;
1077c478bd9Sstevel@tonic-gate 		}
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 		if ((error = hrt_checkres(temptofd.hrt_res)))
1107c478bd9Sstevel@tonic-gate 			break;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 		hrt_gettofd(&temptofd);
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 		if (copyout((caddr_t)&temptofd,
1157c478bd9Sstevel@tonic-gate 		    (caddr_t)uap->hrtp, sizeof (hrtimes_t)))
1167c478bd9Sstevel@tonic-gate 			error = EFAULT;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 		break;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	default:
1217c478bd9Sstevel@tonic-gate 		error = EINVAL;
1227c478bd9Sstevel@tonic-gate 		break;
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 	return (error);
1257c478bd9Sstevel@tonic-gate }
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate /*
1287c478bd9Sstevel@tonic-gate  * Hrtalarm (start one or more alarms) system call.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate int
hrtalarm(uap,rvp)1327c478bd9Sstevel@tonic-gate hrtalarm(uap, rvp)
1337c478bd9Sstevel@tonic-gate 	register struct hrtalarma *uap;
1347c478bd9Sstevel@tonic-gate 	rval_t	*rvp;
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	register hrtcmd_t	*cp;
1377c478bd9Sstevel@tonic-gate 	hrtcmd_t		*hrcmdp;
1387c478bd9Sstevel@tonic-gate 	uint			alarm_cnt;
1397c478bd9Sstevel@tonic-gate 	int			cnt;
1407c478bd9Sstevel@tonic-gate 	int			error = 0;
1417c478bd9Sstevel@tonic-gate 	int			cmd;
1427c478bd9Sstevel@tonic-gate 	hrtcmd_t		timecmd;
1437c478bd9Sstevel@tonic-gate 	hrtimes_t		delay_ht;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	/*
1477c478bd9Sstevel@tonic-gate 	 * Return EINVAL for negative and zero counts.
1487c478bd9Sstevel@tonic-gate 	 */
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if (uap->cmds <= 0)
1517c478bd9Sstevel@tonic-gate 		return (EINVAL);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	cp = &timecmd;
1547c478bd9Sstevel@tonic-gate 	hrcmdp = uap->cmdp;
1557c478bd9Sstevel@tonic-gate 	alarm_cnt = 0;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	/* Loop through and process each command. */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < uap->cmds; cnt++, hrcmdp++) {
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 		if (copyin((caddr_t)hrcmdp, (caddr_t)cp, sizeof (hrtcmd_t)))
1627c478bd9Sstevel@tonic-gate 			return (EFAULT);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 		cmd = cp->hrtc_cmd;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 		/*
1677c478bd9Sstevel@tonic-gate 		 * If we try to post a Berkley Timer remove
1687c478bd9Sstevel@tonic-gate 		 * previous timers.
1697c478bd9Sstevel@tonic-gate 		 */
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 		if (cmd == HRT_BSD || cmd == HRT_BSD_REP)
1727c478bd9Sstevel@tonic-gate 			(void) hrt_bsd_cancel(cp->hrtc_clk);
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 		/*	See what kind of command we have.  */
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 		switch (cmd) {
1777c478bd9Sstevel@tonic-gate 		case HRT_BSD:		/* one-shot timer */
1787c478bd9Sstevel@tonic-gate 		{
1797c478bd9Sstevel@tonic-gate 			struct itimerval itv;
1807c478bd9Sstevel@tonic-gate 			u_int which;
1817c478bd9Sstevel@tonic-gate 
182*3df2e8b2SRobert Mustacchi 			if ((error = hrt_checkclock(cp->hrtc_clk)) != 0)
1837c478bd9Sstevel@tonic-gate 				break;
1847c478bd9Sstevel@tonic-gate 			switch (cp->hrtc_clk) {
1857c478bd9Sstevel@tonic-gate 			case CLK_STD:
1867c478bd9Sstevel@tonic-gate 				which = ITIMER_REAL;
1877c478bd9Sstevel@tonic-gate 				break;
1887c478bd9Sstevel@tonic-gate 			case CLK_USERVIRT:
1897c478bd9Sstevel@tonic-gate 				which = ITIMER_VIRTUAL;
1907c478bd9Sstevel@tonic-gate 				break;
1917c478bd9Sstevel@tonic-gate 			case CLK_PROCVIRT:
1927c478bd9Sstevel@tonic-gate 				which = ITIMER_PROF;
1937c478bd9Sstevel@tonic-gate 				break;
1947c478bd9Sstevel@tonic-gate 			default:
1957c478bd9Sstevel@tonic-gate 				error = EINVAL;
1967c478bd9Sstevel@tonic-gate 				goto bad;
1977c478bd9Sstevel@tonic-gate 			}
1987c478bd9Sstevel@tonic-gate 			itv.it_value.tv_sec = cp->hrtc_int.hrt_secs;
1997c478bd9Sstevel@tonic-gate 			itv.it_value.tv_usec = cp->hrtc_int.hrt_rem;
2007c478bd9Sstevel@tonic-gate 			itv.it_interval.tv_sec = 0;
2017c478bd9Sstevel@tonic-gate 			itv.it_interval.tv_usec = 0;
2027c478bd9Sstevel@tonic-gate 			(void) xsetitimer(which, &itv, 1);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 			break;
2057c478bd9Sstevel@tonic-gate 		}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 		case HRT_BSD_REP:
2087c478bd9Sstevel@tonic-gate 		{
2097c478bd9Sstevel@tonic-gate 			struct itimerval itv;
2107c478bd9Sstevel@tonic-gate 			u_int which;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 			switch (cp->hrtc_clk) {
2137c478bd9Sstevel@tonic-gate 			case CLK_STD:
2147c478bd9Sstevel@tonic-gate 				which = ITIMER_REAL;
2157c478bd9Sstevel@tonic-gate 				break;
2167c478bd9Sstevel@tonic-gate 			case CLK_USERVIRT:
2177c478bd9Sstevel@tonic-gate 				which = ITIMER_VIRTUAL;
2187c478bd9Sstevel@tonic-gate 				break;
2197c478bd9Sstevel@tonic-gate 			case CLK_PROCVIRT:
2207c478bd9Sstevel@tonic-gate 				which = ITIMER_PROF;
2217c478bd9Sstevel@tonic-gate 				break;
2227c478bd9Sstevel@tonic-gate 			default:
2237c478bd9Sstevel@tonic-gate 				error = EINVAL;
2247c478bd9Sstevel@tonic-gate 				goto bad;
2257c478bd9Sstevel@tonic-gate 			}
2267c478bd9Sstevel@tonic-gate 			itv.it_value.tv_sec = cp->hrtc_tod.hrt_secs;
2277c478bd9Sstevel@tonic-gate 			itv.it_value.tv_usec = cp->hrtc_tod.hrt_rem;
2287c478bd9Sstevel@tonic-gate 			itv.it_interval.tv_sec = cp->hrtc_int.hrt_secs;
2297c478bd9Sstevel@tonic-gate 			itv.it_interval.tv_usec = cp->hrtc_int.hrt_rem;
2307c478bd9Sstevel@tonic-gate 			(void) xsetitimer(which, &itv, 1);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 			break;
2337c478bd9Sstevel@tonic-gate 		}
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 		case HRT_BSD_PEND:
2367c478bd9Sstevel@tonic-gate 			{
2377c478bd9Sstevel@tonic-gate 				struct itimerval itv;
2387c478bd9Sstevel@tonic-gate 				u_int which;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 				switch (cp->hrtc_clk) {
2417c478bd9Sstevel@tonic-gate 				case CLK_STD:
2427c478bd9Sstevel@tonic-gate 					which = ITIMER_REAL;
2437c478bd9Sstevel@tonic-gate 					break;
2447c478bd9Sstevel@tonic-gate 				case CLK_USERVIRT:
2457c478bd9Sstevel@tonic-gate 					which = ITIMER_VIRTUAL;
2467c478bd9Sstevel@tonic-gate 					break;
2477c478bd9Sstevel@tonic-gate 				case CLK_PROCVIRT:
2487c478bd9Sstevel@tonic-gate 					which = ITIMER_PROF;
2497c478bd9Sstevel@tonic-gate 					break;
2507c478bd9Sstevel@tonic-gate 				default:
2517c478bd9Sstevel@tonic-gate 					error = EINVAL;
2527c478bd9Sstevel@tonic-gate 					goto bad;
2537c478bd9Sstevel@tonic-gate 				}
2547c478bd9Sstevel@tonic-gate 				(void) xgetitimer(which, &itv, 1);
2557c478bd9Sstevel@tonic-gate 				delay_ht.hrt_secs = itv.it_value.tv_sec;
2567c478bd9Sstevel@tonic-gate 				delay_ht.hrt_rem = itv.it_value.tv_usec;
2577c478bd9Sstevel@tonic-gate 			}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 			if (copyout((caddr_t)&delay_ht,
2607c478bd9Sstevel@tonic-gate 			    (caddr_t)&hrcmdp->hrtc_int, sizeof (hrtimes_t)))
2617c478bd9Sstevel@tonic-gate 				error = EFAULT;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 			break;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		case HRT_BSD_CANCEL:
266*3df2e8b2SRobert Mustacchi 			if ((error = hrt_checkclock(cp->hrtc_clk)) != 0)
2677c478bd9Sstevel@tonic-gate 				break;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 			error = hrt_bsd_cancel(cp->hrtc_clk);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 			break;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		default :
2747c478bd9Sstevel@tonic-gate 			error = EINVAL;
2757c478bd9Sstevel@tonic-gate 			break;
2767c478bd9Sstevel@tonic-gate 		}
2777c478bd9Sstevel@tonic-gate bad:
2787c478bd9Sstevel@tonic-gate 		if (error) {
2797c478bd9Sstevel@tonic-gate 			cp->hrtc_flags |= HRTF_ERROR;
2807c478bd9Sstevel@tonic-gate 			cp->hrtc_error = error;
2817c478bd9Sstevel@tonic-gate 		} else {
2827c478bd9Sstevel@tonic-gate 			cp->hrtc_flags |= HRTF_DONE;
2837c478bd9Sstevel@tonic-gate 			cp->hrtc_error = 0;
2847c478bd9Sstevel@tonic-gate 			alarm_cnt++;
2857c478bd9Sstevel@tonic-gate 		}
2867c478bd9Sstevel@tonic-gate 		if (copyout((caddr_t)&cp->hrtc_flags,
2877c478bd9Sstevel@tonic-gate 		    (caddr_t)&hrcmdp->hrtc_flags,
2887c478bd9Sstevel@tonic-gate 		    sizeof (cp->hrtc_flags) + sizeof (cp->hrtc_error))) {
2897c478bd9Sstevel@tonic-gate 			error = EFAULT;
2907c478bd9Sstevel@tonic-gate 			return (error);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 	rvp->r_val1 = alarm_cnt;
2947c478bd9Sstevel@tonic-gate 	return (0);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  * Cancel BSD timers
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int
hrt_bsd_cancel(int clock)3037c478bd9Sstevel@tonic-gate hrt_bsd_cancel(int clock)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	struct itimerval itv;
3067c478bd9Sstevel@tonic-gate 	u_int which;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	switch (clock) {
3097c478bd9Sstevel@tonic-gate 	case CLK_STD:
3107c478bd9Sstevel@tonic-gate 		which = ITIMER_REAL;
3117c478bd9Sstevel@tonic-gate 		break;
3127c478bd9Sstevel@tonic-gate 	case CLK_USERVIRT:
3137c478bd9Sstevel@tonic-gate 		which = ITIMER_VIRTUAL;
3147c478bd9Sstevel@tonic-gate 		break;
3157c478bd9Sstevel@tonic-gate 	case CLK_PROCVIRT:
3167c478bd9Sstevel@tonic-gate 		which = ITIMER_PROF;
3177c478bd9Sstevel@tonic-gate 		break;
3187c478bd9Sstevel@tonic-gate 	default:
3197c478bd9Sstevel@tonic-gate 		return (EINVAL);
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 	itv.it_value.tv_sec = 0;
3227c478bd9Sstevel@tonic-gate 	itv.it_value.tv_usec = 0;
3237c478bd9Sstevel@tonic-gate 	(void) xsetitimer(which, &itv, 1);
3247c478bd9Sstevel@tonic-gate 	return (0);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate /*
3297c478bd9Sstevel@tonic-gate  * Return 0 if "res" is a legal resolution. Otherwise,
3307c478bd9Sstevel@tonic-gate  * return an error code, ERANGE.
3317c478bd9Sstevel@tonic-gate  */
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate static int
hrt_checkres(ulong res)3347c478bd9Sstevel@tonic-gate hrt_checkres(ulong res)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate 	if (res == 0 || res > NANOSEC)
3377c478bd9Sstevel@tonic-gate 		return (ERANGE);
3387c478bd9Sstevel@tonic-gate 	return (0);
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate /*
3427c478bd9Sstevel@tonic-gate  * Return 0 if "clock" is a valid clock. Otherwise,
3437c478bd9Sstevel@tonic-gate  * return an error code, EINVAL.
3447c478bd9Sstevel@tonic-gate  */
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate static int
hrt_checkclock(register int clock)3477c478bd9Sstevel@tonic-gate hrt_checkclock(register int clock)
3487c478bd9Sstevel@tonic-gate {
3497c478bd9Sstevel@tonic-gate 	switch (clock)
3507c478bd9Sstevel@tonic-gate 	case CLK_STD:
3517c478bd9Sstevel@tonic-gate 	case CLK_USERVIRT:
3527c478bd9Sstevel@tonic-gate 	case CLK_PROCVIRT:
3537c478bd9Sstevel@tonic-gate 		return (0);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	return (EINVAL);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * Set the current time of day in a specified resolution into
3617c478bd9Sstevel@tonic-gate  * a hrtimes_t structure.
3627c478bd9Sstevel@tonic-gate  */
3637c478bd9Sstevel@tonic-gate void
hrt_gettofd(hrtimes_t * td)3647c478bd9Sstevel@tonic-gate hrt_gettofd(hrtimes_t *td)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	ulong new_res = td->hrt_res;
3677c478bd9Sstevel@tonic-gate 	timestruc_t ts;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	gethrestime(&ts);
3707c478bd9Sstevel@tonic-gate 	td->hrt_secs = ts.tv_sec;
3717c478bd9Sstevel@tonic-gate 	td->hrt_rem = ts.tv_nsec;
3727c478bd9Sstevel@tonic-gate 	td->hrt_res = NANOSEC;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if (new_res != td->hrt_res) {
3757c478bd9Sstevel@tonic-gate 		td->hrt_rem /= NANOSEC / new_res;
3767c478bd9Sstevel@tonic-gate 		td->hrt_res = new_res;
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate  * System entry point for hrtcntl, hrtalarm
3837c478bd9Sstevel@tonic-gate  * system calls.
3847c478bd9Sstevel@tonic-gate  */
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate int
hrtsys(uap,rvp)3877c478bd9Sstevel@tonic-gate hrtsys(uap, rvp)
3887c478bd9Sstevel@tonic-gate 	register struct	hrtsysa *uap;
3897c478bd9Sstevel@tonic-gate 	rval_t *rvp;
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	register int	error;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	switch (uap->opcode) {
3947c478bd9Sstevel@tonic-gate 	case	HRTCNTL:
3957c478bd9Sstevel@tonic-gate 		error = hrtcntl((struct hrtcntla *)uap, rvp);
3967c478bd9Sstevel@tonic-gate 		break;
3977c478bd9Sstevel@tonic-gate 	case	HRTALARM:
3987c478bd9Sstevel@tonic-gate 		error = hrtalarm((struct hrtalarma *)uap, rvp);
3997c478bd9Sstevel@tonic-gate 		break;
4007c478bd9Sstevel@tonic-gate 	default:
4017c478bd9Sstevel@tonic-gate 		error = EINVAL;
4027c478bd9Sstevel@tonic-gate 		break;
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	return (error);
4067c478bd9Sstevel@tonic-gate }
407