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:
Poul-Henning Kamp 1998-06-07 19:44:22 +00:00
parent 498b291e26
commit 8afeddf0a8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=36739
5 changed files with 218 additions and 53 deletions

View File

@ -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
View 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_ */

View File

@ -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
/*

View File

@ -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
View 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_ */