mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-01 08:33:24 +00:00
This is a prototype implementation of the draft-mogul-pps-api-##.txt
paper. It will be updated along with the draft and possible subsequent standard. The ppbus based pps driver is updated to implement this API.
This commit is contained in:
parent
498b291e26
commit
8afeddf0a8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=36739
@ -1,5 +1,5 @@
|
||||
# From: @(#)Makefile 8.2 (Berkeley) 1/4/94
|
||||
# $Id: Makefile,v 1.76 1998/03/28 11:48:14 dufault Exp $
|
||||
# $Id: Makefile,v 1.77 1998/05/21 19:21:43 eivind Exp $
|
||||
#
|
||||
# Doing a make install builds /usr/include
|
||||
#
|
||||
@ -18,8 +18,8 @@ FILES= a.out.h ar.h assert.h bitstring.h ctype.h db.h dirent.h disktab.h \
|
||||
paths.h pthread.h pthread_np.h pwd.h \
|
||||
ranlib.h regex.h regexp.h resolv.h rune.h runetype.h setjmp.h sgtty.h \
|
||||
signal.h stab.h stddef.h stdio.h stdlib.h string.h stringlist.h \
|
||||
strings.h struct.h sysexits.h tar.h time.h timers.h ttyent.h unistd.h \
|
||||
utime.h utmp.h vis.h
|
||||
strings.h struct.h sysexits.h tar.h time.h timepps.h timers.h \
|
||||
ttyent.h unistd.h utime.h utmp.h vis.h
|
||||
.if defined(WANT_CSRG_LIBM)
|
||||
FILES+= math.h
|
||||
.endif
|
||||
|
86
include/timepps.h
Normal file
86
include/timepps.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* The is a FreeBSD protype version of the "draft-mogul-pps-api-02.txt"
|
||||
* specification for Pulse Per Second timing interfaces.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TIME_PPS_H_
|
||||
#define _TIME_PPS_H_
|
||||
|
||||
#include <sys/timepps.h>
|
||||
|
||||
int time_pps_create(int filedes, pps_handle_t *handle);
|
||||
int time_pps_destroy(pps_handle_t handle);
|
||||
int time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams);
|
||||
int time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams);
|
||||
int time_pps_getcap(pps_handle_t handle, int *mode);
|
||||
int time_pps_fetch(pps_handle_t handle, pps_info_t *ppsinfobuf);
|
||||
int time_pps_wait(pps_handle_t handle, const struct timespec *timeout,
|
||||
pps_info_t *ppsinfobuf);
|
||||
|
||||
__inline int
|
||||
time_pps_create(int filedes, pps_handle_t *handle)
|
||||
{
|
||||
int error;
|
||||
|
||||
*handle = -1;
|
||||
error = ioctl(filedes, PPS_IOC_CREATE, 0);
|
||||
if (error < 0)
|
||||
return (-1);
|
||||
*handle = filedes;
|
||||
return (0);
|
||||
}
|
||||
|
||||
__inline int
|
||||
time_pps_destroy(pps_handle_t handle)
|
||||
{
|
||||
return (ioctl(handle, PPS_IOC_DESTROY, 0));
|
||||
}
|
||||
|
||||
__inline int
|
||||
time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams)
|
||||
{
|
||||
return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams));
|
||||
}
|
||||
|
||||
__inline int
|
||||
time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams)
|
||||
{
|
||||
return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams));
|
||||
}
|
||||
|
||||
__inline int
|
||||
time_pps_getcap(pps_handle_t handle, int *mode)
|
||||
{
|
||||
return (ioctl(handle, PPS_IOC_GETCAP, mode));
|
||||
}
|
||||
|
||||
__inline int
|
||||
time_pps_fetch(pps_handle_t handle, pps_info_t *ppsinfobuf)
|
||||
{
|
||||
return (ioctl(handle, PPS_IOC_FETCH, ppsinfobuf));
|
||||
}
|
||||
|
||||
__inline int
|
||||
time_pps_wait(pps_handle_t handle, const struct timespec *timeout,
|
||||
pps_info_t *ppsinfobuf)
|
||||
{
|
||||
int error;
|
||||
struct pps_wait_args arg;
|
||||
|
||||
arg.timeout = *timeout;
|
||||
error = ioctl(handle, PPS_IOC_WAIT, &arg);
|
||||
*ppsinfobuf = arg.pps_info_buf;
|
||||
return (error);
|
||||
}
|
||||
|
||||
#endif /* !_TIME_PPS_H_ */
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ppbconf.h,v 1.4 1997/09/01 00:51:48 bde Exp $
|
||||
* $Id: ppbconf.h,v 1.5 1997/09/01 18:39:37 bde Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __PPBCONF_H
|
||||
@ -59,6 +59,7 @@
|
||||
#define AUTOFEED 0x02
|
||||
#define nINIT 0x04
|
||||
#define SELECTIN 0x08
|
||||
#define IRQENABLE 0x10
|
||||
#define PCD 0x20
|
||||
|
||||
/*
|
||||
|
@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: pps.c,v 1.3 1998/02/15 14:54:09 phk Exp $
|
||||
* $Id: pps.c,v 1.4 1998/02/16 23:51:00 eivind Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/timepps.h>
|
||||
#ifdef DEVFS
|
||||
#include <sys/devfsext.h>
|
||||
#endif
|
||||
@ -25,18 +26,21 @@
|
||||
#include <dev/ppbus/ppbconf.h>
|
||||
#include "pps.h"
|
||||
|
||||
#define PPS_NAME "pps" /* our official name */
|
||||
#define PPS_NAME "lppps" /* our official name */
|
||||
|
||||
static struct pps_data {
|
||||
int pps_unit;
|
||||
struct ppb_device pps_dev;
|
||||
struct ppsclockev {
|
||||
struct timespec timestamp;
|
||||
u_int serial;
|
||||
} ev;
|
||||
int sawtooth;
|
||||
pps_params_t ppsparam;
|
||||
pps_info_t ppsinfo;
|
||||
} *softc[NPPS];
|
||||
|
||||
static int ppscap =
|
||||
PPS_CAPTUREASSERT |
|
||||
PPS_HARDPPSONASSERT |
|
||||
PPS_OFFSETASSERT |
|
||||
PPS_ECHOASSERT;
|
||||
|
||||
static int npps;
|
||||
|
||||
/*
|
||||
@ -56,13 +60,12 @@ DATA_SET(ppbdriver_set, ppsdriver);
|
||||
|
||||
static d_open_t ppsopen;
|
||||
static d_close_t ppsclose;
|
||||
static d_read_t ppsread;
|
||||
static d_write_t ppswrite;
|
||||
static d_ioctl_t ppsioctl;
|
||||
|
||||
#define CDEV_MAJOR 89
|
||||
static struct cdevsw pps_cdevsw =
|
||||
{ ppsopen, ppsclose, ppsread, ppswrite,
|
||||
noioctl, nullstop, nullreset, nodevtotty,
|
||||
{ ppsopen, ppsclose, noread, nowrite,
|
||||
ppsioctl, nullstop, nullreset, nodevtotty,
|
||||
seltrue, nommap, nostrat, PPS_NAME,
|
||||
NULL, -1 };
|
||||
|
||||
@ -122,7 +125,7 @@ ppsopen(dev_t dev, int flags, int fmt, struct proc *p)
|
||||
if (ppb_request_bus(&sc->pps_dev, PPB_WAIT|PPB_INTR))
|
||||
return (EINTR);
|
||||
|
||||
ppb_wctr(&sc->pps_dev, 0x10);
|
||||
ppb_wctr(&sc->pps_dev, IRQENABLE);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -132,6 +135,7 @@ ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
|
||||
{
|
||||
struct pps_data *sc = softc[minor(dev)];
|
||||
|
||||
sc->ppsparam.mode = 0;
|
||||
ppb_release_bus(&sc->pps_dev);
|
||||
return(0);
|
||||
}
|
||||
@ -139,60 +143,67 @@ ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
|
||||
static void
|
||||
ppsintr(int unit)
|
||||
{
|
||||
/*
|
||||
* XXX: You want to thing carefully about what you actually want to do
|
||||
* here.
|
||||
*/
|
||||
#if 1
|
||||
struct pps_data *sc = softc[unit];
|
||||
struct timespec tc;
|
||||
#if 1
|
||||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
nanotime(&tc);
|
||||
if (!(ppb_rstr(&sc->pps_dev) & nACK))
|
||||
return;
|
||||
tc.tv_nsec -= sc->sawtooth;
|
||||
sc->sawtooth = 0;
|
||||
if (tc.tv_nsec > 1000000000) {
|
||||
tc.tv_sec++;
|
||||
tc.tv_nsec -= 1000000000;
|
||||
} else if (tc.tv_nsec < 0) {
|
||||
if (sc->ppsparam.mode & PPS_ECHOASSERT)
|
||||
ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED);
|
||||
timespecadd(&tc, &sc->ppsparam.assert_offset);
|
||||
if (tc.tv_nsec < 0) {
|
||||
tc.tv_sec--;
|
||||
tc.tv_nsec += 1000000000;
|
||||
}
|
||||
sc->ev.timestamp = tc;
|
||||
sc->ev.serial++;
|
||||
#if 1
|
||||
tv.tv_sec = tc.tv_sec;
|
||||
tv.tv_usec = tc.tv_nsec / 1000;
|
||||
hardpps(&tv, tv.tv_usec);
|
||||
#endif
|
||||
#endif
|
||||
sc->ppsinfo.assert_timestamp = tc;
|
||||
sc->ppsinfo.assert_sequence++;
|
||||
if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) {
|
||||
tv.tv_sec = tc.tv_sec;
|
||||
tv.tv_usec = tc.tv_nsec / 1000;
|
||||
hardpps(&tv, tv.tv_usec);
|
||||
}
|
||||
if (sc->ppsparam.mode & PPS_ECHOASSERT)
|
||||
ppb_wctr(&sc->pps_dev, IRQENABLE);
|
||||
}
|
||||
|
||||
static int
|
||||
ppsread(dev_t dev, struct uio *uio, int ioflag)
|
||||
static int
|
||||
ppsioctl(dev_t dev, int cmd, caddr_t data, int flags, struct proc *p)
|
||||
{
|
||||
struct pps_data *sc = softc[minor(dev)];
|
||||
int err, c;
|
||||
pps_params_t *pp;
|
||||
pps_info_t *pi;
|
||||
|
||||
c = imin(uio->uio_resid, (int)sizeof sc->ev);
|
||||
err = uiomove((caddr_t)&sc->ev, c, uio);
|
||||
return(err);
|
||||
switch (cmd) {
|
||||
case PPS_IOC_CREATE:
|
||||
return (0);
|
||||
case PPS_IOC_DESTROY:
|
||||
return (0);
|
||||
case PPS_IOC_SETPARAMS:
|
||||
pp = (pps_params_t *)data;
|
||||
if (pp->mode & ~ppscap)
|
||||
return (EINVAL);
|
||||
sc->ppsparam = *pp;
|
||||
return (0);
|
||||
case PPS_IOC_GETPARAMS:
|
||||
pp = (pps_params_t *)data;
|
||||
*pp = sc->ppsparam;
|
||||
return (0);
|
||||
case PPS_IOC_GETCAP:
|
||||
*(int*)data = ppscap;
|
||||
return (0);
|
||||
case PPS_IOC_FETCH:
|
||||
pi = (pps_info_t *)data;
|
||||
*pi = sc->ppsinfo;
|
||||
return (0);
|
||||
case PPS_IOC_WAIT:
|
||||
return (EOPNOTSUPP);
|
||||
default:
|
||||
return (ENODEV);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ppswrite(dev_t dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct pps_data *sc = softc[minor(dev)];
|
||||
int err, c;
|
||||
|
||||
c = imin(uio->uio_resid, (int)sizeof sc->sawtooth);
|
||||
err = uiomove((caddr_t)&sc->sawtooth, c, uio);
|
||||
return(err);
|
||||
}
|
||||
|
||||
static pps_devsw_installed = 0;
|
||||
|
||||
|
67
sys/sys/timepps.h
Normal file
67
sys/sys/timepps.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* The is a FreeBSD protype version of the "draft-mogul-pps-api-02.txt"
|
||||
* specification for Pulse Per Second timing interfaces.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TIMEPPS_H_
|
||||
#define _SYS_TIMEPPS_H_
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
|
||||
typedef int pps_handle_t;
|
||||
|
||||
typedef unsigned pps_seq_t;
|
||||
|
||||
typedef struct {
|
||||
pps_seq_t assert_sequence;
|
||||
pps_seq_t clear_sequence;
|
||||
struct timespec assert_timestamp;
|
||||
struct timespec clear_timestamp;
|
||||
int current_mode;
|
||||
} pps_info_t;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
struct timespec assert_offset;
|
||||
struct timespec clear_offset;
|
||||
} pps_params_t;
|
||||
|
||||
#define PPS_CAPTUREASSERT 0x01
|
||||
#define PPS_CAPTURECLEAR 0x01
|
||||
#define PPS_CAPTUREBOTH 0x03
|
||||
|
||||
#define PPS_HARDPPSONASSERT 0x04
|
||||
#define PPS_HARDPPSONCLEAR 0x08
|
||||
|
||||
#define PPS_OFFSETASSERT 0x10
|
||||
#define PPS_OFFSETCLEAR 0x20
|
||||
|
||||
#define PPS_ECHOASSERT 0x40
|
||||
#define PPS_ECHOCLEAR 0x80
|
||||
|
||||
#define PPS_CANWAIT 0x100
|
||||
|
||||
struct pps_wait_args {
|
||||
struct timespec timeout;
|
||||
pps_info_t pps_info_buf;
|
||||
};
|
||||
|
||||
#define PPS_IOC_CREATE _IO('1', 1)
|
||||
#define PPS_IOC_DESTROY _IO('1', 2)
|
||||
#define PPS_IOC_SETPARAMS _IOW('1', 3, pps_params_t)
|
||||
#define PPS_IOC_GETPARAMS _IOR('1', 4, pps_params_t)
|
||||
#define PPS_IOC_GETCAP _IOR('1', 5, int)
|
||||
#define PPS_IOC_FETCH _IOWR('1', 6, pps_info_t)
|
||||
#define PPS_IOC_WAIT _IOWR('1', 6, struct pps_wait_args)
|
||||
|
||||
#endif /* _SYS_TIMEPPS_H_ */
|
Loading…
Reference in New Issue
Block a user