summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Burnicki <martin.burnicki@meinberg.de>2011-03-17 12:01:00 +0100
committerMartin Burnicki <martin.burnicki@meinberg.de>2011-03-17 12:01:00 +0100
commit64b3c157d3b8b693a995e32e9ab76fe6f92be7ad (patch)
tree60057f03b59a28089e7685271af331f81a4dc554
parent8d63063059cb0b4fee631d788d75d1b739dbac91 (diff)
downloadmbgtools-nbsd-64b3c157d3b8b693a995e32e9ab76fe6f92be7ad.tar.gz
mbgtools-nbsd-64b3c157d3b8b693a995e32e9ab76fe6f92be7ad.zip
Initial source code provided by Frank Kardelmbgtools-nbsd-20110317
Based on mbgtools-fbsd-dev-2011-03-25.
-rw-r--r--src/external/bsd/meinberg/Makefile6
-rw-r--r--src/external/bsd/meinberg/Makefile.inc22
-rwxr-xr-xsrc/external/bsd/meinberg/dist/Makefile458
-rwxr-xr-xsrc/external/bsd/meinberg/dist/README259
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgclock/Makefile48
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgclock/Makefile.nbsd48
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgclock/mbgdrvr.c725
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgctrl/Makefile45
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c2350
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgfasttstamp/Makefile29
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c271
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbggpscap/Makefile39
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c391
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbghrtime/Makefile39
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c287
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgirigcfg/Makefile36
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c728
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h49
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h64
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c82
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h70
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/amccdefs.h111
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h100
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/ctry.c177
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/ctry.h233
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c184
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h74
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h4554
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/gpsutils.c194
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/gpsutils.h80
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/identdec.c164
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/identdec.h67
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/macioctl.h1882
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h165
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h443
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h152
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c6164
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h3157
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgerror.h156
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbggenio.h176
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbggeo.h297
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h459
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c117
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h57
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgtime.h322
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgutil.c615
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/mbgutil.h183
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/myutil.h221
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/parmgps.c242
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/parmgps.h138
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/parmpcps.c115
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/parmpcps.h157
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pci.h162
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pci_asic.h333
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcidefs.h251
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h1276
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h1732
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c3459
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h1445
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h212
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c502
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h1038
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c53
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h62
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c160
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h183
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/plxdefs.h76
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/qsdefs.h46
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/rsrc.h89
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/toolutil.c401
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/toolutil.h83
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/usbdefs.h110
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/use_pack.h39
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbglib/common/words.h340
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgsetsystime/Makefile43
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c173
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgshowsignal/Makefile39
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c182
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgstatus/Makefile50
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c817
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgsvcd/Makefile31
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c472
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgxhrtime/Makefile33
-rwxr-xr-xsrc/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c334
-rw-r--r--src/external/bsd/meinberg/mbgclock/Makefile1
-rw-r--r--src/external/bsd/meinberg/mbgclock/Makefile.kmod15
-rw-r--r--src/external/bsd/meinberg/mbgclock/files.mbgclock13
-rw-r--r--src/external/bsd/meinberg/mbgclock/mbgclock.c558
-rw-r--r--src/sys/dev/pci/files.pci.diff16
-rw-r--r--src/sys/dev/pci/pcidevs.diff47
l---------src/sys/external/bsd/meinberg1
91 files changed, 42079 insertions, 0 deletions
diff --git a/src/external/bsd/meinberg/Makefile b/src/external/bsd/meinberg/Makefile
new file mode 100644
index 0000000..346d99a
--- /dev/null
+++ b/src/external/bsd/meinberg/Makefile
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.2 2010/08/28 15:42:46 kardel Exp $
+
+SUBDIR+= mbgclock
+SUBDIR+= dist
+
+.include <bsd.subdir.mk>
diff --git a/src/external/bsd/meinberg/Makefile.inc b/src/external/bsd/meinberg/Makefile.inc
new file mode 100644
index 0000000..23fe19c
--- /dev/null
+++ b/src/external/bsd/meinberg/Makefile.inc
@@ -0,0 +1,22 @@
+# $NetBSD: Makefile.inc,v 1.5 2010/12/04 23:08:32 christos Exp $
+
+.if !defined(MEINBERG_MAKEFILE_INC)
+MEINBERG_MAKEFILE_INC=yes
+
+USE_FORT?= yes # network client/server
+
+# WARNS?= 5
+
+.include <bsd.own.mk>
+
+IDIST= ${NETBSDSRCDIR}/external/bsd/meinberg/dist
+MBG_LIB_COMMON= ${IDIST}/mbglib/common
+MBG_LIB_BSD= ${IDIST}/mbglib/bsd
+
+CPPFLAGS+=-DDEBUG -I${MBG_LIB_COMMON} -I${MBG_LIB_BSD}
+
+.if exists(${.CURDIR}/../../Makefile.inc)
+.include "${.CURDIR}/../../Makefile.inc"
+.endif
+
+.endif
diff --git a/src/external/bsd/meinberg/dist/Makefile b/src/external/bsd/meinberg/dist/Makefile
new file mode 100755
index 0000000..70b8148
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/Makefile
@@ -0,0 +1,458 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.1.1.6 2011/03/25 11:05:55 martin TRASH $
+#
+# Description:
+# Makefile for mbgtools which recurses into the subdirectories.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.1.1.6 2011/03/25 11:05:55 martin
+# Optional parameter USE_TIMESPEC.
+# Revision 1.1.1.5 2011/03/21 16:24:12 martin
+# Workaround for recursive make under NetBSD.
+# Revision 1.1.1.4 2011/02/04 10:09:45 martin
+# Revision 1.1.1.3 2011/02/02 12:33:29 martin
+# Revision 1.1.1.2 2011/01/28 09:29:47 martin
+# Revision 1.1.1.1 2011/01/27 16:16:40 martin
+# Revision 1.1 2011/01/27 15:41:01 martin
+# Initial revision
+#
+#########################################################################
+
+.ifndef prefix
+ prefix := /usr/local
+.endif
+
+.ifndef bindir
+ bindir := $(prefix)/bin
+.endif
+
+.ifndef sbindir
+ sbindir := $(prefix)/sbin
+.endif
+
+.ifndef sysconfdir
+ sysconfdir := /etc
+.endif
+
+.ifndef includedir
+ includedir := $(prefix)/include
+.endif
+
+.ifndef libdir
+ CUR_ARCH = $(shell uname -m)
+ find_libdirname := $(shell \
+ if [ $(CUR_ARCH) = "ia64" -o $(CUR_ARCH) = "x86_64" ]; then \
+ if test -d $(prefix)/lib64; \
+ then echo "lib64"; \
+ else echo "lib"; \
+ fi \
+ else \
+ if test -d $(prefix)/lib32; \
+ then echo "lib32"; \
+ else echo "lib"; \
+ fi \
+ fi \
+ )
+ libdir := $(prefix)/$(call find_libdirname)
+##$(warning $(INFO) libdir set to $(libdir))
+.endif
+
+INSTALL_PATHS = DESTDIR=$(DESTDIR) prefix=$(prefix) bindir=$(bindir) sbindir=$(sbindir) includedir=$(includedir) libdir=$(libdir) sysconfdir=$(sysconfdir)
+
+.ifndef SO_BASENAMES
+ SO_BASENAMES += devio
+ SO_BASENAMES += util
+ SO_BASENAMES += serio
+ SO_BASENAMES += extio
+.endif
+
+.ifndef SO_SUBDIRS
+# SO_SUBDIRS += $(foreach dir,$(SO_BASENAMES), libmbg_so/mbg$(dir) )
+## $(warning $(INFO) **************** SO_SUBDIRS set to $(SO_SUBDIRS))
+.endif
+
+##$(warning $(INFO) SO_SUBDIRS set to $(SO_SUBDIRS))
+
+.ifndef BASEDIR
+
+.DEFAULT_GOAL := all
+MAKECMDGOALS ?= $(.DEFAULT_GOAL)
+
+# This section is used only if this makefile is called by the top-level
+# make. It specifies some common targets and some subdirs in which a
+# recursive make will be executed, which may include this make file again
+# and evaluate the second part.
+
+INFO=top 1st:
+## $(warning $(INFO) reading top level part)
+
+## export COMMON_MAKEFILE := $(CURDIR)/Makefile
+## $(warning $(INFO) COMMON_MAKEFILE set to $(COMMON_MAKEFILE))
+
+# The macro function below prints an info string whether a target
+# is supported by the kernel Makefile
+
+.ifndef SUBDIRS
+
+chk_subdir = $(shell test -f $(strip $(1))/Makefile && echo "$(1)" )
+
+.ifndef DONT_BUILD_LIBS
+ SUBDIRS += $(SO_SUBDIRS)
+## $(foreach dir,$(SO_SUBDIRS),$(eval SUBDIRS += $(call chk_subdir, $(dir))))
+ SUBDIRS += $(call chk_subdir, "libmbg_so/devel" )
+.endif
+
+.ifndef DONT_BUILD_TOOLS
+ SUBDIRS += $(call chk_subdir, "mbgstatus" )
+ SUBDIRS += $(call chk_subdir, "mbgsetsystime" )
+ SUBDIRS += $(call chk_subdir, "mbgctrl" )
+ SUBDIRS += $(call chk_subdir, "mbgirigcfg" )
+ SUBDIRS += $(call chk_subdir, "mbgshowsignal" )
+ SUBDIRS += $(call chk_subdir, "mbggpscap" )
+ SUBDIRS += $(call chk_subdir, "mbghrtime" )
+ SUBDIRS += $(call chk_subdir, "mbgfasttstamp" )
+ SUBDIRS += $(call chk_subdir, "mbgsvcd" )
+ SUBDIRS += $(call chk_subdir, "mbgxhrtime" )
+ SUBDIRS += $(call chk_subdir, "test/mbgtestio" )
+ SUBDIRS += $(call chk_subdir, "test/mbgtestmmio" )
+ SUBDIRS += $(call chk_subdir, "test/mbgtestxhrt" )
+ SUBDIRS += $(call chk_subdir, "test/mbgchksystime" )
+ SUBDIRS += $(call chk_subdir, "test/mbgtestsettime" )
+.endif
+
+.ifndef DONT_BUILD_GUI
+.ifndef DONT_BUILD_MBGMON
+ SUBDIRS += $(call chk_subdir, "wxwidgets/mbgmon" )
+.endif
+.ifndef DONT_BUILD_MBGSTATSVIEWER
+ SUBDIRS += $(call chk_subdir, "wxwidgets/mbgstatsviewer" )
+.endif
+.endif
+
+.ifndef DONT_BUILD_DRIVER
+ SUBDIRS += $(call chk_subdir, "mbgclock" )
+ ##SUBDIRS += $(call chk_subdir, "test/mbgclock-test" )
+.endif
+
+## $(warning $(INFO) SUBDIRS = $(SUBDIRS))
+## $(warning $(INFO) MAKECMDGOALS = $(MAKECMDGOALS))
+
+.endif
+
+
+SUBDIRS += mbgstatus
+SUBDIRS += mbgsvcd
+SUBDIRS += mbgsetsystime
+SUBDIRS += mbgctrl
+SUBDIRS += mbgirigcfg
+SUBDIRS += mbgshowsignal
+SUBDIRS += mbggpscap
+SUBDIRS += mbghrtime
+SUBDIRS += mbgfasttstamp
+# SUBDIRS += mbgxhrtime ## not yet tested
+SUBDIRS += test/mbgtestio
+SUBDIRS += test/mbgtestmmio
+SUBDIRS += test/mbgtestxhrt
+SUBDIRS += test/mbgchksystime
+# SUBDIRS += mbgclock
+
+.PHONY: all clean distclean install uninstall
+all clean distclean install uninstall:
+ @for dir in $(SUBDIRS); do \
+ if test -f $$dir/Makefile; then \
+ /bin/sh -c "cd $$dir; $(MAKE) $@"; \
+ fi \
+ done
+
+.PHONY: dev dev-nodes dev-clean suse_symvers probe ins rm test reload check \
+ refclocks kernel_config
+dev dev-nodes dev-clean suse_symvers probe ins rm test reload check \
+ refclocks kernel_config:
+ @cd mbgclock && make $@
+
+.PHONY: cleanreload
+cleanreload: clean all install reload
+
+.else # ================================================================
+
+# This section is evaluated only if this makefile is included from
+# a subproject's makefile.
+
+
+.ifndef MBGLIB
+ MBGLIB := $(BASEDIR)/mbglib
+.endif
+
+MBGLIB_DIRS += common linux
+
+# Macros useful to run individual commands as root:
+.ifndef CALLED_FROM_SPEC
+.ifndef SUDO
+ SUDO := $(shell which sudo)
+.endif
+
+.ifndef SU
+ SU := $(shell which su)
+.endif
+
+ UID = $(shell id -u)
+.else
+ #fake running as root
+ UID = 0
+.endif
+
+run_as_root = $(shell echo "$(SUDO) $(1) || $(SU) -c \"$(1)\"" )
+make_as_root = $(call run_as_root, make $(1))
+
+.ifndef MODULE_OBJS #===========================================================
+
+# not building a kernel module
+
+CFLAGS += -Wall
+## CFLAGS += -W
+
+.ifdef DEBUG
+ CFLAGS += -DDEBUG=$(DEBUG)
+ CFLAGS += -g
+.else
+ CFLAGS += -O2
+.endif
+
+.ifdef USE_TIMESPEC
+ CFLAGS += -DUSE_TIMESPEC=$(USE_TIMESPEC)
+.endif
+
+CFLAGS += -I.
+CFLAGS += $(foreach dir,$(MBGLIB_DIRS),-I$(MBGLIB)/$(dir))
+#########
+CFLAGS += -I$(BASEDIR)/mbglib/common
+CFLAGS += -I$(BASEDIR)/mbglib/bsd
+
+
+# Use all CFLAGS defined above also for C++ files.
+CXXFLAGS += $(CFLAGS)
+
+# Additional C++-only compiler flags.
+## CXXFLAGS += -Wno-deprecated
+
+
+LDFLAGS += $(foreach dir,$(SO_SUBDIRS),-L $(BASEDIR)/$(dir) )
+
+
+SO_MAJOR_VERSION = 1
+SO_MINOR_VERSION = 0
+
+.ifdef SO_TARGET_BASENAME
+.ifndef SO_POINT_RELEASE
+ SO_POINT_RELEASE = 0
+.endif
+
+ SO_TARGET_NAME = libmbg$(SO_TARGET_BASENAME)
+ SO_TARGET_LIBNAME = $(SO_TARGET_NAME).so
+ SO_TARGET_SONAME = $(SO_TARGET_LIBNAME).$(SO_MAJOR_VERSION)
+ TARGET = $(SO_TARGET_SONAME).$(SO_MINOR_VERSION).$(SO_POINT_RELEASE)
+
+ OBJS += mbg$(SO_TARGET_BASENAME).o
+
+ CLEAN_FILES += $(SO_TARGET_LIBNAME)
+
+ CFLAGS += -fPIC
+ CFLAGS += -c
+
+ LDFLAGS += -shared
+ LDFLAGS += -lc
+ LDFLAGS += -Wl,-soname,$(SO_TARGET_SONAME)
+
+.ifndef LIBDIR
+ LIBDIR := $(shell if [ -d /usr/lib64 ]; then echo /usr/lib64; else echo /usr/lib; fi )
+.endif
+.endif
+
+
+
+.PHONY: all
+all: $(TARGET)
+
+#### VPATH += $(foreach dir,$(MBGLIB_DIRS),$(MBGLIB)/$(dir))
+VPATH = $(BASEDIR)/mbglib/common:$(BASEDIR)/mbglib/bsd
+
+.ifndef MBGDEVIO_SIMPLE
+ MBGDEVIO_SIMPLE = 1
+.endif
+
+.ifdef MBGDEVIO_SIMPLE
+ CFLAGS += -DMBGDEVIO_SIMPLE=$(MBGDEVIO_SIMPLE)
+.endif
+
+
+.ifdef USE_THREAD_API
+
+ # Check whether thread affinity is supported by the installed pthread library.
+ # Newer versions of glibc/pthread (at least glibc 2.5) supports this natively.
+ # Older versions of glibc/pthread (e.g. glibc 2.3) may not support this natively
+ # but may provide a NPTL (New Posix Thread Library) library located under separate
+ # include and lib paths. We try to detect NPTL and add those paths to the search
+ # paths only if USE_NTPL has been defined e.g. on the make command line.
+
+ # Check whether pthread_getaffinity is supported by the standard pthread.h
+ USE_THREAD_AFFINITY := $(shell grep -q pthread_getaffinity /usr/include/pthread.h && echo 1)
+
+ # If it is not, check nptl/pthread.h
+.ifndef USE_THREAD_AFFINITY
+.ifdef USE_NPTL
+ USE_THREAD_AFFINITY := $(shell grep -q pthread_getaffinity /usr/include/nptl/pthread.h && echo 1)
+.endif
+
+.ifndef USE_THREAD_AFFINITY
+ ##++++ If not found either, don't support thread affinity
+ USE_THREAD_AFFINITY=0
+.else
+ #if supported via nptl add the associated search paths
+ CFLAGS += -I /usr/include/nptl -L /usr/lib/nptl
+.endif
+.endif
+
+ # May want to use the result for our program
+ ## CFLAGS += -DUSE_THREAD_AFFINITY=$(USE_THREAD_AFFINITY)
+
+ CFLAGS += -DMBGDEVIO_USE_THREAD_API=1
+
+ #LDFLAGS += -lpthread
+ LDFLAGS += -pthread
+.endif
+
+.ifdef INST_TO_BIN
+ INST_DIR = $(DESTDIR)$(bindir)
+.else
+.ifdef INST_TO_SBIN
+ INST_DIR = $(DESTDIR)$(sbindir)
+.else
+.ifdef INST_TO_LIB
+ INST_DIR = $(DESTDIR)$(libdir)
+.else
+.ifdef INST_TO_INCLUDE
+ INST_DIR = $(DESTDIR)$(includedir)/mbglib
+.endif
+.endif
+.endif
+.endif
+
+.ifdef DO_GUI_INSTALLATION
+ EXT_INSTALL += gui_install
+ EXT_UNINSTALL += gui_uninstall
+.endif
+
+
+## $(warning $(INFO) CFLAGS=$(CFLAGS))
+## $(warning $(INFO) EXTRA_CFLAGS=$(EXTRA_CFLAGS))
+## $(warning $(INFO) MAKECMDGOALS = $(MAKECMDGOALS))
+
+$(TARGET): $(OBJS)
+ $(CC) -o $@ $(OBJS) $(LDFLAGS)
+.ifdef SO_TARGET_LIBNAME
+ ln -sf $(TARGET) $(SO_TARGET_LIBNAME)
+.endif
+
+.PHONY: install
+install: $(EXT_INSTALL)
+.ifdef XXX #.ifneq ($(UID),0)
+ $(call make_as_root, $@)
+.else
+.ifdef INCLUDE_FILES #include files
+ mkdir -p $(INST_DIR)
+ for incfile in $(INCLUDE_FILES); do \
+ install -m 644 $(BASEDIR)/mbglib/common/$$incfile $(INST_DIR)/; \
+ done;
+ for basename in $(SO_BASENAMES); do \
+ pushd $(DESTDIR)$(libdir); \
+ ln -sf libmbg$$basename.so.$(SO_MAJOR_VERSION) libmbg$$basename.so; \
+ popd; \
+ done;
+.else #usual installation
+.ifdef CALLED_FROM_SPEC
+ mkdir -p $(INST_DIR)
+.endif
+ install -s $(TARGET) $(INST_DIR)
+
+.ifndef CALLED_FROM_SPEC
+.ifdef INST_TO_LIB
+ /sbin/ldconfig
+.endif
+.endif
+.endif
+.endif
+
+
+.PHONY: uninstall
+uninstall: $(EXT_UNINSTALL)
+.ifdef INCLUDE_FILES #remove include files and
+ rm -rf $(INST_DIR)
+.ifndef CALLED_FROM_SPEC #remove symbolic links
+ for basename in $(SO_BASENAMES); do \
+ rm -f $(libdir)/libmbg$$basename.so; \
+ done;
+.endif
+.else
+.ifdef XXX #.ifneq ($(UID),0)
+ $(call make_as_root, $@)
+.else
+ rm -f $(INST_DIR)/$(TARGET)
+.ifndef CALLED_FROM_SPEC
+.ifdef INST_TO_LIB
+ /sbin/ldconfig
+.endif
+.endif
+.endif
+.endif
+
+.PHONY: gui_install
+gui_install:
+.ifdef XXX #.ifneq ($(UID),0)
+ $(call make_as_root, $@)
+.else
+ mkdir -p $(DESTDIR)$(prefix)/share/$(TARGET)
+ cp $(TARGET).png $(DESTDIR)$(prefix)/share/$(TARGET)/$(TARGET).png
+ mkdir -p $(DESTDIR)$(prefix)/share/applications
+ cp $(TARGET).desktop $(DESTDIR)$(prefix)/share/applications/$(TARGET).desktop
+.endif
+
+.PHONY: gui_uninstall
+gui_uninstall:
+.ifdef XXX #.ifneq ($(UID),0)
+ $(call make_as_root, $@)
+.else
+ rm -rf $(DESTDIR)$(prefix)/share/$(TARGET)
+ rm -f $(DESTDIR)$(prefix)/share/applications/$(TARGET).desktop
+.endif
+
+CLEAN_FILES += *.o
+CLEAN_FILES += *~
+CLEAN_FILES += core
+CLEAN_FILES += $(TARGET)
+
+.PHONY: clean
+clean:
+.ifdef CLEAN_FILES
+ rm -f $(CLEAN_FILES)
+.endif
+.ifdef CLEAN_DIRS
+ rm -rf $(CLEAN_DIRS)
+.endif
+
+
+.else
+# ===== Building module for kernel 2.6 =============================================
+
+.endif # building kernel module
+#==================================================================================
+
+
+# common targets:
+
+.PHONY: distclean
+distclean: clean
+
+.endif
diff --git a/src/external/bsd/meinberg/dist/README b/src/external/bsd/meinberg/dist/README
new file mode 100755
index 0000000..9067192
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/README
@@ -0,0 +1,259 @@
+$Id: README 1.1.1.1 2011/02/09 11:47:11 martin TRASH martin $
+
+This is the README file for mbgtools-fbsd-dev-2011-02-04
+--------------------------------------------------------
+
+
+Please send comments and required modifications to
+Meinberg support <support@meinberg.de>
+
+
+Contents
+--------
+ 1. Notes and description
+ 2. Driver files and programs
+ 3. Installation
+ 3.1 Unpacking the sources
+ 3.2 Compiling the driver
+ 3.3 Installing the driver
+ 3.4 Loading the kernel module
+ 4. Using the driver with NTP
+
+
+1. Notes and description
+------------------------
+This driver package has been implemented for FreeBSD 8.1
+on standard PCs (i386 architecture) and on Intel/AMD 64 bit
+systems (amd64 architecture).
+
+Unless the BSD kernel API calls have changed the driver should
+also work properly under earlier versions of FreeBSD. However,
+other target platforms than i386 and amd64 are not yet supported.
+
+The driver supports all PCI cards manufactured by Meinberg which
+have been shipped up to the release date of this driver version.
+
+This version of the driver package should compile fine
+under FreeBSD 8.1 for kernels 2.6.x, .
+
+
+
+2. Driver files and programs
+----------------------------
+mbgtools for Linux is based on Meinberg's common driver library mbglib
+and implements the following programs each of which can be found in
+its own subdirectory:
+
+mbgclock.ko
+ A kernel module which implements the device driver.
+
+mbgstatus
+ This program prints some status information for a device. The
+ kind of information to be printed depends on the specific type
+ of the card.
+
+mbgsvcd
+ This program periodically calls the kernel driver to retrieve
+ time stamps of both the system time and the PCI card as close
+ as possible after each other, and feeds the time stamp pairs
+ into a shared memory segment compatible with the NTP daemon ntpd.
+ This enables ntpd to use up to 4 PCI card(s) as refererence time
+ source, if configured accordingly.
+
+ Usually the program runs as daemon, but using the -f parameter
+ it can also run in the foreground where it also prints the time
+ stamps and the time differences between the system time and the
+ PCI card's time on the console.
+
+ This mode can be used to monitor how accurately the system time
+ is actually disciplined, even if the system time is disciplined
+ by some other means.
+
+mbgctrl
+ This program can be used to do some basic configuration of a card.
+ Run mbgctrl -? to get a list of valid options.
+
+mbgirigcfg
+ This program can be used to check and configure IRIG settings of
+ cards which provide an IRIG input or output.
+ Type "mbgirigcfg -h" for help.
+
+mbgsetsystime
+ This program reads the time from a device and sets the system time.
+ If NTP is used on a system which has an unreliable clock, this
+ program can be used to set the system time initially (before the
+ NTP daemon starts). The program should not be run if NTP is active
+ and controls the system time since NTP achieves a higher accuracy.
+
+mbgdcfmod
+ This program displays the modulation (i.e. the second marks) of a
+ received longwave signal, e.g. from DCF77.
+
+mbggpscap
+ This example program reads time capture events from a card's time
+ capture buffer. This works only with cards which provide time capture
+ inputs, and the DIP switches on those cards must be set up properly
+ to enable time capturing.
+
+mbghrtime
+ This example program checks whether a card supports high-resolution
+ time and reads those time stamps from the device, if supported.
+
+mbgfasttstamp
+ This examle program demonstrates how to read high resolution time stamps
+ from a card very much faster than mbghrtime. However, this works only
+ with cards which support memory mapped I/O.
+ As of this writing this applies to the GPS170PEX only.
+
+mbgxhrtime
+ This example program also shows how to get time stamps faster than
+ shown in mbghrtime. This is not as easy as mbgfasttstamp but can be
+ used with every card which can be used with mbghrtime, even if the
+ card does not support memory mapped I/O.
+ The program starts a polling thread which reads a high resolution
+ time stamp from the card once per second, and then uses the CPU's
+ time stamp counter to extrapolate the time.
+ A limitation of this approach is that the CPU's time stamp counters
+ may return different values on different CPUs. So the program
+ takes care to have the code executed always on the same CPU. Also,
+ power saving mechanisms (Intel Speedstep, or AMD Cool'n'Quiet)
+ should be disabled to prevent the extrapolated times from being
+ messed up.
+
+
+
+3. Installation
+---------------
+
+3.1 Unpacking the sources
+-------------------------
+Unpack the archive file using the command
+
+ tar xvzf mbgtools-fbsd*.tar.gz
+
+After the archive file has been unpacked cd to the base directory
+that has been created corresponding to the name and version of
+the package.
+
+
+
+3.2 Compiling the driver
+------------------------
+If the driver package has already been built before then
+
+ make clean
+
+should be run first to remove old object files and binaries.
+
+Make sure your working directory is the driver base directory and
+simply type
+
+ make
+
+to compile the utility programs first, then the kernel module.
+If *any* error or warning messages are displayed then please
+report to Meinberg.
+
+
+
+3.3 Installing the driver
+-------------------------
+Installation must be done as user root. Type
+
+ make install
+
+to copy the compiled binaries to their target directories. Programs
+which only read the clock to display some information are copied to
+/usr/local/bin, whereas programs which may change the device
+configuration, or set the system time, are copied to /usr/local/sbin.
+
+
+
+3.4 Loading the kernel module
+-----------------------------
+After the binaries have been installed the module can be loaded
+for the first time. The command syntax is:
+
+ kldload mbgclock
+
+When the module is loaded some some startup messages are generated which
+can be checked in the syslog, or using the dmesg command. If the module
+was loaded successfully it should be listed if you type
+
+ kldstat
+
+You may try to display the device status by entering
+
+ mbgstatus
+
+The output shows some information on the device status,
+depending on the type of the clock.
+
+Once the module has been loaded, the other utility programs can be
+used accordingly.
+
+
+
+4. Using the driver with NTP
+----------------------------
+The NTP daemon can be configured to use up to 4 Meinberg PCI cards
+as reference time source to discipline the system time. In order to
+achieve this, ntpd needs to be configured to use its shared memory
+driver (SHM, type 28).
+
+The following entries needd to be made in the ntp.conf file
+to enable support for 4 PCI cards:
+
+ server 127.127.28.0 minpoll 4 maxpoll 4 iburst
+ fudge 127.127.28.0 refid SHM0
+
+ server 127.127.28.1 minpoll 4 maxpoll 4 iburst
+ fudge 127.127.28.1 refid SHM1
+
+ server 127.127.28.2 minpoll 4 maxpoll 4 iburst
+ fudge 127.127.28.2 refid SHM2
+
+ server 127.127.28.3 minpoll 4 maxpoll 4 iburst
+ fudge 127.127.28.3 refid SHM3
+
+Of course, only the first entry is required if only a single PCI card
+is installed.
+
+Please keep in mind the mbgsvcd program also needs to be running to feed
+time stamp pairs of the system time and the PCI card's time into the
+shared memory segment(s).
+
+If the NTP daemon is already running restart it and check the syslog file
+for messages generated by the daemon.
+
+The NTP daemon shipped with a FreeBSD may have been compiled without
+support for the SHM driver. If this is the case you will find a message
+in the syslog saying the daemon is unable to handle 127.127.28.<n>.
+In this case you need to recompile the NTP package with support
+for the SHM driver.
+
+Simply download the NTP source packge of your choice from
+http://support.ntp.org
+
+Then unpack the sources and compile the package with the usual instructions:
+
+./configure
+make
+make install
+
+By default this installs the NTP binaries under /usr/local rather than /usr/sbin,
+so be sure the right instance of ntpd is started on reboot or when you run the
+"service ntpd start" command.
+
+-----------------------------------------------------------------------------------
+Recompile ntpd with modified configuration (FreeBSD 5.3):
+
+root# cd /usr/ports/net/ntp/
+root# vi Makefile
+
+Add line:
+ CONFIGURE_ARGS+= --enable-MEINBERG
+
+root# make install clean
+
+
diff --git a/src/external/bsd/meinberg/dist/mbgclock/Makefile b/src/external/bsd/meinberg/dist/mbgclock/Makefile
new file mode 100755
index 0000000..7dd2450
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgclock/Makefile
@@ -0,0 +1,48 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.1.1.4 2011/02/03 14:10:39 martin TEST martin $
+#
+# Description:
+# Makefile for mbgclock driver to support Meinberg bus level
+# devices under FreeBSD.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.1.1.4 2011/02/03 14:10:39 martin
+# Revision 1.1.1.3 2011/01/26 17:38:58 martin
+# Add support for DEBUG build.
+# Revision 1.1.1.2 2011/01/26 16:36:37 martin
+# Enabled all required source files.
+# Revision 1.1.1.1 2011/01/26 14:12:02 martin
+# Started modifications to build mbgclock.
+# Revision 1.1 2011/01/26 13:56:32 martin
+# Initial skeleton based on FreeBSD's mypci.c sample program by Murray Stokely.
+#
+#########################################################################
+
+KMOD= mbgclock
+
+MBGLIB= ../mbglib
+MBGLIB_COMMON= $(MBGLIB)/common
+MBGLIB_BSD= $(MBGLIB)/bsd
+
+.PATH: $(MBGLIB_COMMON) $(MBGLIB_BSD)
+
+CFLAGS= -I$(MBGLIB_COMMON) -I$(MBGLIB_BSD)
+
+.ifdef DEBUG
+CFLAGS+= -D DEBUG=$(DEBUG)
+.endif
+
+SRCS= mbgdrvr.c
+SRCS+= pcpsdrvr.c
+SRCS+= identdec.c
+SRCS+= rsrc_bsd.c
+SRCS+= device_if.h bus_if.h pci_if.h
+
+CLEANFILES= *~
+CLEANFILES+= machine
+CLEANFILES+= @
+
+.include <bsd.kmod.mk>
diff --git a/src/external/bsd/meinberg/dist/mbgclock/Makefile.nbsd b/src/external/bsd/meinberg/dist/mbgclock/Makefile.nbsd
new file mode 100755
index 0000000..7dd2450
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgclock/Makefile.nbsd
@@ -0,0 +1,48 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.1.1.4 2011/02/03 14:10:39 martin TEST martin $
+#
+# Description:
+# Makefile for mbgclock driver to support Meinberg bus level
+# devices under FreeBSD.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.1.1.4 2011/02/03 14:10:39 martin
+# Revision 1.1.1.3 2011/01/26 17:38:58 martin
+# Add support for DEBUG build.
+# Revision 1.1.1.2 2011/01/26 16:36:37 martin
+# Enabled all required source files.
+# Revision 1.1.1.1 2011/01/26 14:12:02 martin
+# Started modifications to build mbgclock.
+# Revision 1.1 2011/01/26 13:56:32 martin
+# Initial skeleton based on FreeBSD's mypci.c sample program by Murray Stokely.
+#
+#########################################################################
+
+KMOD= mbgclock
+
+MBGLIB= ../mbglib
+MBGLIB_COMMON= $(MBGLIB)/common
+MBGLIB_BSD= $(MBGLIB)/bsd
+
+.PATH: $(MBGLIB_COMMON) $(MBGLIB_BSD)
+
+CFLAGS= -I$(MBGLIB_COMMON) -I$(MBGLIB_BSD)
+
+.ifdef DEBUG
+CFLAGS+= -D DEBUG=$(DEBUG)
+.endif
+
+SRCS= mbgdrvr.c
+SRCS+= pcpsdrvr.c
+SRCS+= identdec.c
+SRCS+= rsrc_bsd.c
+SRCS+= device_if.h bus_if.h pci_if.h
+
+CLEANFILES= *~
+CLEANFILES+= machine
+CLEANFILES+= @
+
+.include <bsd.kmod.mk>
diff --git a/src/external/bsd/meinberg/dist/mbgclock/mbgdrvr.c b/src/external/bsd/meinberg/dist/mbgclock/mbgdrvr.c
new file mode 100755
index 0000000..e2f968c
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgclock/mbgdrvr.c
@@ -0,0 +1,725 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgdrvr.c 1.1.1.11.1.3 2011/03/25 11:06:27 martin TRASH martin $
+ *
+ * Description:
+ * Main file for for mbgclock driver to support Meinberg bus level
+ * devices under FreeBSD.
+ *
+ * The binary is a loadable module called mbgclock which implements
+ * /dev/mbgclock* devices.
+ *
+ * Based on FreeBSD's mypci.c sample program by Murray Stokely.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgdrvr.c $
+ * Revision 1.1.1.11.1.3 2011/03/25 11:06:27 martin
+ * Fixed typo.
+ * Revision 1.1.1.11.1.2 2011/03/23 16:49:53 martin
+ * Syntax fix.
+ * Revision 1.1.1.11.1.1 2011/03/22 12:09:16 martin
+ * Started to support NetBSD.
+ * Revision 1.1.1.11 2011/02/04 14:44:19 martin
+ * Revision 1.1.1.10 2011/02/02 12:33:52 martin
+ * Revision 1.1.1.9 2011/02/01 17:11:38 martin
+ * Revision 1.1.1.8 2011/02/01 14:49:42 martin
+ * Revision 1.1.1.7 2011/02/01 12:12:17 martin
+ * Revision 1.1.1.6 2011/01/31 17:28:56 martin
+ * Modified resource handling.
+ * Revision 1.1.1.5 2011/01/28 09:31:21 martin
+ * Fixed debug/non-debug build.
+ * Revision 1.1.1.4 2011/01/27 15:15:23 martin
+ * Loads and unloads properly. Calls pcps_start_device() which
+ * properly reads some data from a card.
+ * Revision 1.1.1.3 2011/01/26 16:37:18 martin
+ * Ioctl support compiled in.
+ * Revision 1.1.1.2 2011/01/26 15:05:53 martin
+ * Revision 1.1.1.1 2011/01/26 14:34:33 martin
+ * Started modifications to build mbgclock.
+ * Revision 1.1 2011/01/26 13:56:32 martin
+ * Initial skeleton based on FreeBSD's mypci.c sample program by Murray Stokely.
+ *
+ **************************************************************************/
+
+#include <pcpsdrvr.h>
+#include <mbgddmsg.h>
+
+#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
+#include <sys/malloc.h>
+#include <sys/bus.h> /* structs, prototypes for pci bus stuff */
+
+#if defined( MBG_TGT_FREEBSD )
+ #include <sys/rman.h>
+#endif
+
+#include <dev/pci/pcivar.h> /* For pci_get macros! */
+#include <dev/pci/pcireg.h>
+
+
+
+#if 1 //##++ move this elsewhere!
+
+#define REV_NUM 0x100
+#define REV_NUM_STR "1.00"
+
+#define MBG_COPYRIGHT "(c) Meinberg 2011"
+
+#define MBG_DRVR_NAME "mbgclock"
+#define MBGCLK_NAME "mbgclk"
+#define MBGNTP_NAME "mbgntp"
+
+const char pcps_driver_name[] = MBG_DRVR_NAME;
+
+static MBG_DBG_DATA mbg_dbg_data;
+static MBG_DBG_PORT mbg_dbg_port = 0x378 + 0; //##++
+static PCPS_IO_ADDR_MAPPED mbg_dbg_port_mapped; //##++
+
+static PCPS_DRVR_INFO drvr_info = { REV_NUM, 0, MBG_DRVR_NAME " radio clock driver" };
+
+#if defined( DEBUG )
+int debug = DEBUG;
+#endif
+
+MALLOC_DEFINE( M_MBGCLOCK, "short desc", "long desc" );
+
+#include <macioctl.h>
+
+#endif
+
+
+
+/* The softc holds our per-instance data. */
+struct mbgclock_softc
+{
+ device_t device;
+ struct cdev *cdev;
+ PCPS_DDEV *pddev;
+};
+
+
+/* Function prototypes */
+#if defined( MBG_TGT_NETBSD )
+ static int mbgclock_open( dev_t, int, int, struct proc * );
+ static int mbgclock_close( dev_t, int, int, struct proc * );
+ static int mbgclock_read( dev_t dev, struct uio *, int );
+#else // FreeBSD
+ static d_open_t mbgclock_open;
+ static d_close_t mbgclock_close;
+ static d_read_t mbgclock_read;
+ static d_write_t mbgclock_write;
+ static d_ioctl_t mbgclock_ioctl;
+#endif
+
+
+/* Character device entry points */
+
+static struct cdevsw mbgclock_cdevsw =
+{
+#if defined( MBG_TGT_NETBSD )
+
+#if 0 //##+++++++
+ .d_open = mbgclock_open,
+ .d_close = mbgclock_close,
+ .d_read = mbgclock_read,
+ .d_write = mbgclock_write,
+ .d_ioctl = mbgclock_ioctl,
+ .d_name = "mbgclock"
+#endif
+
+#else // FreeBSD
+ .d_version = D_VERSION,
+ .d_open = mbgclock_open,
+ .d_close = mbgclock_close,
+ .d_read = mbgclock_read,
+ .d_write = mbgclock_write,
+ .d_ioctl = mbgclock_ioctl,
+ .d_name = "mbgclock"
+#endif
+};
+
+
+
+static __mbg_inline
+void set_dev_connected( PCPS_DDEV *pddev, int state )
+{
+ _mbgddmsg_4( MBG_DBG_DETAIL, "%s: setting dev %s_%s connected state to %i",
+ pcps_driver_name, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ),
+ state );
+ atomic_store_rel_int( &pddev->connected, state );
+
+} // set_dev_connected
+
+
+
+/*
+ * In the cdevsw routines, we find our softc by using the si_drv1 member
+ * of struct cdev. We set this variable to point to our softc in our
+ * attach routine when we create the /dev entry.
+ */
+#if defined( MBG_TGT_NETBSD )
+
+#if 0 //##++++
+int
+mbgclock_open( dev_t, int, int, struct proc * )
+{
+} // mbgclock_open
+#endif
+
+#else // FreeBSD
+
+int
+mbgclock_open( struct cdev *dev, int oflags, int devtype, d_thread_t *td )
+{
+ struct mbgclock_softc *psc = dev->si_drv1;
+ PCPS_DDEV *pddev = psc->pddev;
+
+ _mbgddmsg_3( MBG_DBG_INFO, "%s: dev %s_%s opened successfully.", pcps_driver_name,
+ _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+
+ atomic_add_int( &pddev->open_count, 1 );
+
+ return 0;
+
+} // mbgclock_open
+
+#endif
+
+
+#if defined( MBG_TGT_NETBSD )
+
+#else // FreeBSD
+
+int
+mbgclock_close( struct cdev *dev, int fflag, int devtype, d_thread_t *td )
+{
+ struct mbgclock_softc *psc = dev->si_drv1;
+ PCPS_DDEV *pddev = psc->pddev;
+
+ atomic_subtract_int( &pddev->open_count, 1 );
+
+ _mbgddmsg_3( MBG_DBG_INFO, "%s: dev %s_%s closed.", pcps_driver_name,
+ _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+
+ return 0;
+
+} // mbgclock_close
+
+#endif
+
+
+#if defined( MBG_TGT_NETBSD )
+
+#else // FreeBSD
+
+int
+mbgclock_read( struct cdev *dev, struct uio *uio, int ioflag )
+{
+ #if defined( DEBUG )
+ struct mbgclock_softc *psc = dev->si_drv1;
+ PCPS_DDEV *pddev = psc->pddev;
+
+ _mbgddmsg_4( MBG_DBG_INFO, "%s: dev %s_%s asked to read %li bytes",
+ pcps_driver_name, _pcps_ddev_type_name( pddev ),
+ _pcps_ddev_sernum( pddev ), (long) uio->uio_resid );
+ #endif
+
+ return 0;
+
+} // mbgclock_read
+
+#endif
+
+
+#if defined( MBG_TGT_NETBSD )
+
+#else // FreeBSD
+
+int
+mbgclock_write( struct cdev *dev, struct uio *uio, int ioflag )
+{
+ #if defined( DEBUG )
+ struct mbgclock_softc *psc = dev->si_drv1;
+ PCPS_DDEV *pddev = psc->pddev;
+
+ _mbgddmsg_4( MBG_DBG_INFO, "%s: dev %s_%s asked to write %li bytes",
+ pcps_driver_name, _pcps_ddev_type_name( pddev ),
+ _pcps_ddev_sernum( pddev ), (long) uio->uio_resid );
+ #endif
+
+ return 0;
+
+} // mbgclock_write
+
+#endif
+
+
+
+#if defined( MBG_TGT_NETBSD ) //##++++++++++++
+
+// Below there are some dummy declarations to make the IOCTL handler
+// for FreeBSD *compile* without errors under NetBSD.
+// This is mainly to see if ioctl_switch() compiles without errors.
+
+#define caddr_t void *
+
+struct thread
+{
+ int dummy;
+};
+
+#endif
+
+int
+mbgclock_ioctl( struct cdev *dev, u_long cmd, caddr_t data,
+ int32_t flag, struct thread *td )
+{
+#if defined( MBG_TGT_NETBSD )
+ struct mbgclock_softc *psc = NULL; //##++++ dummy, just to avoid build error
+#else // FreeBSD
+ struct mbgclock_softc *psc = dev->si_drv1;
+#endif
+ PCPS_DDEV *pddev = psc->pddev;
+ int rc;
+
+ rc = ioctl_switch( pddev, cmd, (void *) data, (void *) data );
+
+ // On success we return quickly.
+
+ if ( rc == MBG_SUCCESS )
+ {
+ _mbgddmsg_5( MBG_DBG_INFO, "%s: %p IOCTL 0x%02lX: success, dev %s_%s",
+ pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ goto out;
+ }
+
+
+ // An error has occurred.
+ // Generate an appropriate debug/error message
+ // and return an error status.
+
+ switch ( rc )
+ {
+ case MBG_ERR_INV_DEV_REQUEST:
+ _mbgddmsg_6( MBG_DBG_WARN, "%s: %p ioctl 0x%02lX: invalid cmd %04lX, dev %s_%s",
+ pcps_driver_name, dev, cmd, IOCBASECMD( cmd ),
+ _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EINVAL;
+ break;
+
+
+ case MBG_ERR_NOT_SUPP_BY_DEV:
+ _mbgddmsg_5( MBG_DBG_WARN, "%s: %p ioctl 0x%02lX: not supported by dev %s_%s",
+ pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EIO;
+ break;
+
+
+ case MBG_ERR_NO_MEM:
+ _mbgddmsg_5( MBG_DBG_WARN, "%s: %p ioctl 0x%02lX: unable to allocate buffer for dev %s_%s",
+ pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EFAULT;
+ break;
+
+
+ case MBG_ERR_IRQ_UNSAFE:
+ _mbgddmsg_5( MBG_DBG_DETAIL, "%s: %p ioctl 0x%02lX: busy since unsafe IRQ enabled, dev %s_%s",
+ pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EBUSY;
+ break;
+
+
+ default: // any access error code returned by the low level routine
+ // or copying from or to user space
+ _mbgddmsg_6( MBG_DBG_WARN, "%s: %p ioctl 0x%02lX: error %i accessing dev %s_%s",
+ pcps_driver_name, dev, cmd, rc, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EFAULT;
+
+ } // switch error rc
+
+
+out:
+ return rc;
+
+} // mbgclock_ioctl
+
+
+
+/* PCI Support Functions */
+
+static void
+mbg_deallocate_resource( device_t device, BSD_RSRC_INFO *p_ri, int type )
+{
+ if ( p_ri->res )
+ {
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ bus_deactivate_resource( device, type,
+ p_ri->rid, p_ri->res );
+ bus_release_resource( device, type,
+ p_ri->rid, p_ri->res );
+#endif
+ p_ri->res = NULL;
+ }
+
+} // mbg_deallocate_resource
+
+
+
+/*
+ * deallocate resources
+ */
+static void
+mbg_dealloc_rsrcs( device_t device )
+{
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ struct mbgclock_softc *psc = device_get_softc( device );
+ PCPS_DDEV *pddev = psc->pddev;
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+ int i;
+
+// mbg_deallocate_resource( device, &prsrci->irq.bsd, SYS_RES_IRQ );
+
+ for ( i = 0; i < N_PCPS_MEM_RSRC; i++ )
+ mbg_deallocate_resource( device, &prsrci->mem[i].bsd, SYS_RES_MEMORY );
+
+ for ( i = 0; i < N_PCPS_PORT_RSRC; i++ )
+ mbg_deallocate_resource( device, &prsrci->port[i].bsd, SYS_RES_IOPORT );
+#endif
+
+} // mbg_dealloc_rsrcs
+
+
+
+static void
+mbg_alloc_rsrc( device_t device, int rid, BSD_RSRC_INFO *p_ri, int type, int flags )
+{
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ p_ri->rid = rid;
+
+ p_ri->res = bus_alloc_resource_any( device, type, &p_ri->rid, flags );
+
+ if ( p_ri->res )
+ {
+ p_ri->bst = rman_get_bustag( p_ri->res );
+ p_ri->bsh = rman_get_bushandle( p_ri->res );
+ }
+#endif
+
+} // mbg_alloc_rsrc
+
+
+
+static void
+mbg_alloc_rsrcs( device_t device )
+{
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ struct mbgclock_softc *psc = device_get_softc( device );
+ PCPS_DDEV *pddev = psc->pddev;
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+ BSD_RSRC_INFO ri;
+ int bar;
+
+// _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: alloc I/O range %i: PCI device 0x%04X:0x%04X supported",
+// pcps_driver_name, vend_id, dev_id );
+
+ for ( bar = 0; bar < 5; bar ++ )
+ {
+ int rid = PCIR_BAR( bar );
+
+ if ( prsrci->num_rsrc_io < N_PCPS_PORT_RSRC )
+ {
+ mbg_alloc_rsrc( device, rid, &ri, SYS_RES_IOPORT, RF_ACTIVE );
+
+ if ( ri.res )
+ {
+ prsrci->port[prsrci->num_rsrc_io].bsd = ri;
+ pcps_add_rsrc_io( pddev, rman_get_start( ri.res ), rman_get_size( ri.res ) );
+ continue;
+ }
+ }
+
+ if ( prsrci->num_rsrc_mem < N_PCPS_MEM_RSRC )
+ {
+ mbg_alloc_rsrc( device, rid, &ri, SYS_RES_MEMORY, RF_ACTIVE );
+
+ if ( ri.res )
+ {
+ prsrci->mem[prsrci->num_rsrc_mem].bsd = ri;
+ pcps_add_rsrc_mem( pddev, rman_get_start( ri.res ), rman_get_size( ri.res ) );
+ continue;
+ }
+ }
+ }
+
+
+ // single IRQ resource
+#if 0 // currently not used / required
+ mbg_alloc_rsrc( device, 0, &ri, SYS_RES_IRQ, RF_SHAREABLE | RF_ACTIVE );
+
+ if ( ri.res )
+ {
+ prsrci->port[prsrci->num_rsrc_irq].bsd = ri;
+ pcps_add_rsrc_irq( pddev, rman_get_start( ri.res ) );
+ }
+#endif
+
+#endif
+
+} // mbg_alloc_rsrcs
+
+
+
+/*
+ * Probe: compare the device ID of this device against the IDs that this driver
+ * supports. If there is a match, set the description and return success.
+ */
+static int
+mbgclock_probe( device_t device )
+{
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ uint16_t vend_id = pci_get_vendor( device );
+ uint16_t dev_id = pci_get_device( device );
+ PCPS_DEV_TYPE *pdt;
+
+
+ if ( vend_id != PCI_VENDOR_MEINBERG )
+ goto fail;
+
+ pdt = pcps_get_dev_type( PCPS_BUS_PCI, dev_id );
+
+ if ( pdt == NULL )
+ goto fail;
+
+ device_set_desc( device, pdt->name );
+
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: probe: PCI device 0x%04X:0x%04X supported",
+ pcps_driver_name, vend_id, dev_id );
+
+ return BUS_PROBE_DEFAULT;
+
+
+fail:
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: probe: PCI device 0x%04X:0x%04X not supported",
+ pcps_driver_name, vend_id, dev_id );
+ return ENXIO;
+
+#endif
+
+} // mbgclock_probe
+
+
+
+/*
+ * Attach function is only called if the probe is successful.
+ */
+static int
+mbgclock_attach( device_t device )
+{
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ uint16_t dev_id = pci_get_device( device );
+ struct mbgclock_softc *psc = device_get_softc( device );
+ int rc;
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: attach for device 0x%04X",
+ pcps_driver_name, dev_id );
+
+ psc->pddev = pcps_alloc_ddev();
+
+ if ( psc->pddev == NULL )
+ {
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_alloc_ddev() failed",
+ pcps_driver_name, dev_id );
+ rc = ENOMEM;
+ goto fail;
+ }
+
+
+ rc = pcps_init_ddev( psc->pddev, PCPS_BUS_PCI, dev_id );
+
+ if ( rc != PCPS_SUCCESS )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_init_ddev() failed, rc: %i",
+ pcps_driver_name, dev_id, rc );
+ rc = ENXIO;
+ goto fail;
+ }
+
+
+ //##++++++ rc = pci_enable_device( dev );
+
+
+ mbg_alloc_rsrcs( device );
+
+ //##++++++ rc = pcps_start_device( pddev, device->bus->number, device->devfn );
+ rc = pcps_start_device( psc->pddev, 0, 0 );
+
+ if ( rc != PCPS_SUCCESS )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_start_device() failed, rc: %i",
+ pcps_driver_name, dev_id, rc );
+ rc = ENXIO;
+ goto fail;
+ }
+
+
+ set_dev_connected( psc->pddev, 1 );
+
+ /* Initialize our softc. */
+ psc->device = device;
+ /*
+ * Create a /dev entry for this device. The kernel will assign us
+ * a major number automatically. We use the unit number of this
+ * device as the minor number and name the character device
+ * "mbgclock<unit>".
+ */
+ psc->cdev = make_dev( &mbgclock_cdevsw, device_get_unit( device ),
+ UID_ROOT, GID_WHEEL, 0600, "mbgclock%u", device_get_unit( device ) );
+
+ psc->cdev->si_drv1 = psc;
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: device 0x%04X attached successfully",
+ pcps_driver_name, dev_id );
+
+ return 0;
+
+
+fail:
+ mbg_dealloc_rsrcs( device );
+
+ if ( psc->pddev )
+ pcps_free_ddev( psc->pddev );
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: failed to attach device 0x%04X",
+ pcps_driver_name, dev_id );
+ return rc;
+#endif
+
+} // mbgclock_attach
+
+
+
+/*
+ * Detach device.
+ */
+static int
+mbgclock_detach( device_t device )
+{
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+ #if defined( DEBUG )
+ uint16_t dev_id = pci_get_device( device );
+ #endif
+ struct mbgclock_softc *psc;
+ PCPS_DDEV *pddev;
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: detach for device 0x%04X",
+ pcps_driver_name, dev_id );
+
+ /* Teardown the state in our softc created in our attach routine. */
+ psc = device_get_softc( device );
+ pddev = psc->pddev;
+
+ set_dev_connected( pddev, 0 );
+
+// pcps_free_ddev( pddev ); //##++++++ should wait for outstanding requests
+
+ mbg_dealloc_rsrcs( device );
+
+ destroy_dev( psc->cdev );
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: device 0x%04X detached",
+ pcps_driver_name, dev_id );
+#endif
+
+ return 0;
+
+} // mbgclock_detach
+
+
+
+/*
+ * Called during system shutdown after sync.
+ */
+static int
+mbgclock_shutdown( device_t device )
+{
+ printf( "mbgclock shutdown!\n" );
+
+ return 0;
+
+} // mbgclock_shutdown
+
+
+
+/*
+ * Device suspend routine.
+ */
+static int
+mbgclock_suspend( device_t device )
+{
+ printf( "mbgclock suspend!\n" );
+
+ return 0;
+
+} // mbgclock_suspend
+
+
+
+/*
+ * Device resume routine.
+ */
+static int
+mbgclock_resume( device_t device )
+{
+ printf( "mbgclock resume!\n" );
+
+ return 0;
+
+} // mbgclock_resume
+
+
+
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+static device_method_t mbgclock_methods[] =
+{
+ /* Device interface */
+ DEVMETHOD( device_probe, mbgclock_probe ),
+ DEVMETHOD( device_attach, mbgclock_attach ),
+ DEVMETHOD( device_detach, mbgclock_detach ),
+ DEVMETHOD( device_shutdown, mbgclock_shutdown ),
+ DEVMETHOD( device_suspend, mbgclock_suspend ),
+ DEVMETHOD( device_resume, mbgclock_resume ),
+ { 0, 0 }
+};
+#endif
+
+
+#if defined( MBG_TGT_NETBSD )
+ //##++++++
+#else // FreeBSD
+static devclass_t mbgclock_devclass;
+
+DEFINE_CLASS_0( mbgclock, mbgclock_driver, mbgclock_methods, sizeof( struct mbgclock_softc ) );
+DRIVER_MODULE( mbgclock, pci, mbgclock_driver, mbgclock_devclass, 0, 0 );
+#endif
diff --git a/src/external/bsd/meinberg/dist/mbgctrl/Makefile b/src/external/bsd/meinberg/dist/mbgctrl/Makefile
new file mode 100755
index 0000000..e485fc0
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgctrl/Makefile
@@ -0,0 +1,45 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.7.1.2 2010/08/30 09:05:22 martin TEST $
+#
+# Description:
+# Makefile for mbgctrl.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.7.1.2 2010/08/30 09:05:22 martin
+# Revision 1.7.1.1 2010/08/30 08:20:54 martin
+# Revision 1.7 2009/07/24 10:31:16 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.6 2008/12/22 11:54:31 martin
+# Changed enumeration of source files.
+# Revision 1.5 2007/03/02 11:45:09 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.4 2003/04/25 10:21:05 martin
+# Updated source module list.
+# Revision 1.3 2002/11/21 14:56:31 martin
+# New targets install and uninstall.
+# Revision 1.2 2001/11/30 10:21:54 martin
+# Added pcpsutil.o to the list of source files.
+# Revision 1.1 2001/09/17 15:07:55 martin
+#
+#########################################################################
+
+TARGET = mbgctrl
+INST_DIR = /usr/local/sbin
+
+# By default these tools only need a simple set of mbgdevio API
+# functions, but here we use all API calls.
+MBGDEVIO_SIMPLE = 0
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+OBJS += pcpsutil.o
+OBJS += parmgps.o
+OBJS += parmpcps.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c b/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c
new file mode 100755
index 0000000..d7c6d9f
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c
@@ -0,0 +1,2350 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgctrl.c 1.22.1.5 2011/03/21 08:32:18 martin TRASH $
+ *
+ * Description:
+ * Main file for mbgctrl program which sends commands and
+ * configuration parameters to a Meinberg device via IOCTL calls.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgctrl.c $
+ * Revision 1.22.1.5 2011/03/21 08:32:18 martin
+ * Fixed compiler warning.
+ * Revision 1.22.1.4 2011/03/03 10:01:00 daniel
+ * Support configuring PTP roles.
+ * Revision 1.22.1.3 2011/02/18 13:35:59 daniel
+ * Revision 1.22.1.2 2011/02/18 13:35:11 daniel
+ * Revision 1.22.1.1 2011/02/18 11:27:29 daniel
+ * Preliminary support for configuring PTP parameters incl. Unicast
+ * Bugfix: accept parameter keyword only when substring is found at the
+ * start of the parameter string.
+ * Revision 1.22 2009/09/29 14:58:18 martin
+ * Unified and simplified parameter evaluation.
+ * Updated version number to 3.4.0.
+ * Revision 1.21 2009/09/28 09:36:43 martin
+ * Support configuration of antenna cable length.
+ * Removed duplicate usage message for event time.
+ * Revision 1.20 2009/09/28 07:19:03 martin
+ * Made parameter syntax for enable_flags and LAN configuration more flexible.
+ * Revision 1.19 2009/08/20 14:19:29 martin
+ * Updated version number to 3.3.1.
+ * Support configuration of board's LAN interface.
+ * Revision 1.18 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.17 2009/06/19 12:38:51 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.16 2009/06/18 15:14:53 martin
+ * Added command TZOFFS which can be used to set TZDL to UTC, and then
+ * configure the standard TZDL offset to a dedicated number of seconds, to the
+ * output time has a configurable UTC offset against the time derived from the
+ * input signal.
+ * Revision 1.15 2009/03/20 11:53:19 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Support programmable time scales.
+ * Revision 1.14 2008/12/22 12:39:00 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.13 2008/11/07 10:25:49 martin
+ * Support modification of a card's ENABLE_FLAGS.
+ * Changes due to renamed library function.
+ * Changes due to renamed library function.
+ * Revision 1.12 2008/09/15 14:20:21 martin
+ * Support generic serial settings including string type and mode.
+ * Reworked evaluation of command line parameters.
+ * New parameter COM0= to configure an individual port.
+ * Account for renamed library symbols.
+ * Revision 1.11 2007/07/24 09:31:39 martin
+ * Changes due to renamed library symbols.
+ * Revision 1.10 2007/03/01 16:09:16 martin
+ * Be able to set the board date and/or time.
+ * Revision 1.9 2007/02/22 16:38:50 martin
+ * Added function to set on-board date.
+ * Revision 1.8 2006/08/28 10:45:50 martin
+ * Picked up Heiko's patch to set the GPS receiver position.
+ * Revision 1.7 2004/11/08 15:47:40 martin
+ * Using type cast to avoid compiler warning.
+ * Revision 1.6 2003/08/26 14:37:35 martin
+ * Support configuration of some standard time zones,
+ * also for GPS devices.
+ * Revision 1.5 2003/07/31 13:48:54 martin
+ * Added function to set COM port parms for GPS clocks.
+ * Usage shows which parameters are supported by a device.
+ * Revision 1.4 2003/04/25 10:27:58 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.3 2002/08/22 14:52:49 martin
+ * Added function to set clock's COM port parameters.
+ * Revision 1.2 2001/12/03 16:04:46 martin
+ * New program version 1.2.
+ * Added new function set_event_time().
+ * Fixed a bug in eval of cmd line parameters.
+ * Revision 1.1 2001/09/17 15:07:56 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsmktm.h>
+#include <pcpsutil.h>
+#include <parmpcps.h>
+#include <parmgps.h>
+#include <myutil.h>
+#include <gpsutils.h>
+#include <cnv_wday.h>
+#include <toolutil.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+
+static const char *pname = "mbgctrl";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2001-2009";
+
+static char *dev_name;
+
+static TZDL tzdl_utc = DEFAULT_TZDL_UTC;
+static TZDL tzdl_cet_cest = DEFAULT_TZDL_CET_CEST_EN;
+static TZDL tzdl_eet_eest = DEFAULT_TZDL_EET_EEST_EN;
+static long max_tzdl_offs = 0x7FFFFFFFL; // max val for int32_t
+
+static const char *tz_info_utc = TZ_INFO_UTC;
+static const char *tz_info_cet_cest = TZ_INFO_CET_CEST_EN;
+static const char *tz_info_eet_eest = TZ_INFO_EET_EEST_EN;
+
+static const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES;
+static const char *time_scale_name[N_MBG_TIME_SCALE] = MBG_TIME_SCALE_STRS;
+
+#define _get_time_scale_name( _i ) \
+ ( ( (_i) < N_MBG_TIME_SCALE ) ? time_scale_name[_i] : "(unknown)" )
+
+
+static const char *no_gps_cmd = "does not support GPS commands";
+static const char *no_tzdl = "does not support configurable time zone";
+static const char *no_tz = "does not support time zones";
+static const char *no_event_time = "does not support event times";
+static const char *no_enable_flags = "does not support enable flags";
+static const char *no_time_scale = "does not support a configurable time scale";
+static const char *no_lan_intf = "does not provide a LAN interface";
+static const char *no_ptp = "does not provide PTP";
+static const char *no_cab_len = "does not support antenna signal delay compensation";
+
+typedef struct
+{
+ const char *name;
+ uint16_t *flags;
+ uint16_t on_flags;
+} EF_INFO;
+
+#define N_EF_INFO 3
+
+static const char *ef_name_serial = "SERIAL";
+static const char *ef_name_pulses = "PULSES";
+static const char *ef_name_synth = "SYNTH";
+
+
+typedef struct
+{
+ const char *name;
+ IP4_ADDR *addr;
+} IP4_INFO;
+
+#define N_IP4_INFO 4
+
+static const char *ip4_name_ip = "IP";
+static const char *ip4_name_nm = "NM";
+static const char *ip4_name_ba = "BA";
+static const char *ip4_name_gw = "GW";
+
+static const char *ptp_name_net = "NP";
+static const char *ptp_name_del = "DM";
+static const char *ptp_name_dom = "DO";
+static const char *ptp_name_v1 = "HW";
+
+static const char *ptp_name_gm_ip = "GMIP";
+static const char *ptp_name_gm_id = "GMID";
+static const char *ptp_name_tp_id = "PID";
+static const char *ptp_name_dur = "DUR";
+static const char *ptp_name_sr = "SR";
+static const char *ptp_name_ar = "AR";
+static const char *ptp_name_dr = "DR";
+
+
+static /*HDR*/
+void err_msg( const PCPS_DEV *p_dev, const char *msg )
+{
+ printf( "This device %s.\n", msg );
+
+} // err_msg
+
+
+
+static /*HDR*/
+int set_tz_code( MBG_DEV_HANDLE dh, PCPS_TZCODE tzcode, const char *s )
+{
+ int rc = mbg_set_tzcode( dh, &tzcode );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_tzcode" ) )
+ return rc;
+
+ printf( "The clock's time zone setting has been set to %s.\n", s );
+
+ return MBG_SUCCESS;
+
+} // set_tz_code
+
+
+
+static /*HDR*/
+int set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *tzdl, const char *info )
+{
+ int rc = mbg_set_gps_tzdl( dh, tzdl );
+
+ if ( mbg_ioctl_err( rc, "set_gps_tzdl" ) )
+ return rc;
+
+ if ( info )
+ printf( "The clock's time zone setting has been set to %s.\n", info );
+
+ return MBG_SUCCESS;
+
+} // set_gps_tzdl
+
+
+
+static /*HDR*/
+int set_timezone( MBG_DEV_HANDLE dh, const char *tz_name, const PCPS_DEV *p_dev )
+{
+ const char *tz_info = NULL;
+ TZDL *tz_tzdl = NULL;
+ PCPS_TZCODE tz_code = 0;
+ int rc = MBG_SUCCESS;
+
+ if ( strcmp( tz_name, "UTC" ) == 0 )
+ {
+ tz_info = tz_info_utc;
+ tz_tzdl = &tzdl_utc;
+ tz_code = PCPS_TZCODE_UTC;
+ }
+ else if ( strcmp( tz_name, "CET" ) == 0 )
+ {
+ tz_info = tz_info_cet_cest;
+ tz_tzdl = &tzdl_cet_cest;
+ tz_code = PCPS_TZCODE_MEZMESZ;
+ }
+ else if ( strcmp( tz_name, "EET" ) == 0 )
+ {
+ tz_info = tz_info_eet_eest;
+ tz_tzdl = &tzdl_eet_eest;
+ tz_code = PCPS_TZCODE_OEZ;
+ }
+ else
+ {
+ printf( "** Unknown timezone name %s\n", tz_name );
+ rc = 1;
+ }
+
+ if ( tz_info )
+ {
+ if ( _pcps_has_tzcode( p_dev ) )
+ rc = set_tz_code( dh, tz_code, tz_info );
+ else
+ if ( _pcps_has_tzdl( p_dev ) )
+ rc = set_gps_tzdl( dh, tz_tzdl, tz_info );
+ else
+ err_msg( p_dev, no_tz );
+ }
+
+ return rc;
+
+} // set_timezone
+
+
+
+static /*HDR*/
+int show_tzdl_offs( MBG_DEV_HANDLE dh, const char *info )
+{
+ TZDL tzdl;
+ int rc = mbg_get_gps_tzdl( dh, &tzdl );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_tzdl" ) )
+ return rc;
+
+ printf( "%s timezone offset: UTC%+lis", info, (long) tzdl.offs );
+
+ return MBG_SUCCESS;
+
+} // show_tzdl_offs
+
+
+
+static /*HDR*/
+int set_tzdl_offs( MBG_DEV_HANDLE dh, const char *s )
+{
+ TZDL tzdl = tzdl_utc;
+ long tzdl_offs = atol( s );
+
+ if ( labs( tzdl_offs ) > max_tzdl_offs ) // max val for int32_t
+ {
+ fprintf( stderr, "** Time zone offset %li exceeds range (%li..%li)\n",
+ tzdl_offs, -max_tzdl_offs, max_tzdl_offs );
+ return MBG_ERR_CFG;
+ }
+
+ tzdl.offs = (int32_t) tzdl_offs;
+
+ return set_gps_tzdl( dh, &tzdl, NULL );
+
+} // set_tzdl_offs
+
+
+
+static /*HDR*/
+int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *addr )
+{
+ int n;
+
+ n = snprintf( s, max_len, "%i.%i.%i.%i",
+ BYTE_OF( *addr, 3 ),
+ BYTE_OF( *addr, 2 ),
+ BYTE_OF( *addr, 1 ),
+ BYTE_OF( *addr, 0 )
+ );
+
+ return n;
+
+} // snprint_ip4_addr
+
+
+
+/*HDR*/
+const char *str_to_ip4_addr( IP4_ADDR *p, const char *s )
+{
+ IP4_ADDR tmp_ip4_addr = 0;
+ char *cp;
+ int i;
+
+ for ( i = 0, cp = (char *) s; ; )
+ {
+ unsigned long ul = strtoul( cp, &cp, 10 );
+
+ if ( ul > 255 ) // invalid number
+ return NULL;
+
+ tmp_ip4_addr |= ul << ( 8 * (3 - i) );
+
+ if ( ++i >= 4 )
+ break; // done
+
+ if ( *cp != '.' )
+ return NULL; // invalid string format, dot expected
+
+ cp++; // skip dot
+ }
+
+ if ( p )
+ *p = tmp_ip4_addr;
+
+ return cp; // success
+
+} // str_to_ip4_addr
+
+
+
+static /*HDR*/
+int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ IP4_SETTINGS ip4_settings;
+ char ws[256];
+
+ int rc = mbg_get_ip4_settings( dh, &ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) )
+ return rc;
+
+ printf( "On-board LAN interface settings:" );
+
+ if ( ip4_settings.flags & IP4_MSK_DHCP )
+ printf( " (DHCP client)\n" );
+ else
+ {
+ printf( "\n" );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr );
+ printf( " IP Address: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask );
+ printf( " Net Mask: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr );
+ printf( " Broadcast Addr: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway );
+ printf( " Gateway: %s\n", ws );
+ }
+
+ return MBG_SUCCESS;
+
+} // show_lan_intf
+
+
+
+static /*HDR*/
+int show_ptp_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ PTP_CFG_INFO ptp_settings;
+ PTP_UNICAST_CFG_INFO ptp_unicast_settings;
+
+ const char* delay_mech[] = PTP_DELAY_MECH_NAMES;
+ const char* network_prot[] = PTP_NW_PROT_STRS;
+ const char* network_prot_short[] = PTP_NW_PROT_STRS_SHORT;
+ const char* ptp_roles[] = PTP_ROLE_STRS;
+
+ int supports_unicast = 0;
+
+ int rc = mbg_get_ptp_cfg_info( dh, &ptp_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_cfg_info" ) )
+ return rc;
+
+ supports_unicast = ptp_settings.supported_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST;
+
+ printf( "\nPTP configuration:\n");
+
+ supports_unicast ? printf( " PTP Role : %s\n", ptp_roles[ptp_settings.settings.ptp_role] ) :
+ printf( " PTP Role : %s\n", ptp_roles[0] );
+
+ printf( " Network Protocol: %s (%s)\n", network_prot_short[ptp_settings.settings.network_protocol], network_prot[ptp_settings.settings.network_protocol] );
+ printf( " Delay Mechanism : %s\n", delay_mech[ptp_settings.settings.delay_mechanism] );
+ printf( " Domain Number : %d\n", ptp_settings.settings.domain_number );
+ printf( " V1 HW Compat. : %d\n", ( ptp_settings.settings.flags & PTP_CFG_MSK_V1_HW_COMPAT ) ? 1:0 );
+
+ if ( supports_unicast )
+ {
+ int i;
+
+ int rc = mbg_get_ptp_unicast_cfg_info( dh, &ptp_unicast_settings);
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_unicast_cfg_info" ) )
+ return rc;
+
+ printf( "\nPTP Unicast configuration:\n");
+ printf( " GM Host: %s\n", ptp_unicast_settings.settings.gm_host);
+
+ printf( " GM Clock ID: ");
+ for ( i = 0; i < 8; i++ )
+ {
+ printf( "%02X", ptp_unicast_settings.settings.gm_clock_id.b[i] );
+ if ( i < 7 )
+ printf(":");
+ }
+
+ printf("\n");
+
+ printf( " GM Port ID: %d\n\n", ptp_unicast_settings.settings.gm_port_id );
+ printf( " Sync Msg Interval [2^x s]: %i\n", ptp_unicast_settings.settings.sync_interval );
+ printf( " Ann. Msg Interval [2^x s]: %i\n", ptp_unicast_settings.settings.announce_interval );
+ printf( " DelReq Msg Interval [2^x s]: %i\n", ptp_unicast_settings.settings.delay_request_interval );
+ printf( " Message Duration: %i s\n", ptp_unicast_settings.settings.message_duration );
+ }
+
+ return MBG_SUCCESS;
+
+} // show_ptp_cfg
+
+
+
+
+static /*HDR*/
+int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ PTP_CFG_INFO prv_ptp_settings;
+ PTP_CFG_SETTINGS ptp_settings;
+ PTP_UNICAST_CFG_INFO prv_ptp_unicast_settings;
+ PTP_UNICAST_CFG_SETTINGS ptp_unicast_settings;
+
+ char *cp;
+ int l;
+
+ int supports_unicast = 0;
+
+ int rc = mbg_get_ptp_cfg_info( dh, &prv_ptp_settings);
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_cfg_info" ) )
+ return rc;
+
+ supports_unicast = prv_ptp_settings.supported_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST;
+
+ if ( supports_unicast )
+ {
+ int rc = mbg_get_ptp_unicast_cfg_info( dh, &prv_ptp_unicast_settings);
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_unicast_cfg_info" ) )
+ return rc;
+
+ memcpy( &ptp_unicast_settings, &prv_ptp_unicast_settings.settings, sizeof(ptp_unicast_settings) );
+ }
+
+ memcpy( &ptp_settings, &prv_ptp_settings.settings, sizeof(ptp_settings) );
+
+
+ // Network protocol
+ cp = strstr( arg, ptp_name_net );
+
+ if ( cp != NULL )
+ {
+ l = strlen(ptp_name_net);
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if ( strstr( (cp+l) , "IP4" ) != 0 )
+ ptp_settings.network_protocol = PTP_NW_PROT_BIT_UDP_IPV4;
+ else if ( strstr( (cp+l) , "ETH" ) != 0 )
+ ptp_settings.network_protocol = PTP_NW_PROT_BIT_IEEE_802_3;
+ else
+ {
+ printf("error: Invalid or unsupported network protocol type!\n");
+ goto fail;
+ }
+ }
+
+ // Delay Mechanism
+ cp = strstr( arg, ptp_name_del );
+
+ if ( cp != NULL )
+ {
+ l = strlen(ptp_name_del);
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if ( strstr( (cp+l) , "E2E" ) != 0 )
+ ptp_settings.delay_mechanism = PTP_DELAY_MECH_BIT_E2E;
+ else if ( strstr( (cp+l) , "P2P" ) != 0 )
+ ptp_settings.delay_mechanism = PTP_DELAY_MECH_BIT_P2P;
+ else
+ {
+ printf("error: Invalid delay mechanism\n");
+ goto fail;
+ }
+ }
+
+ // Domain Number
+ cp = strstr( arg, ptp_name_dom );
+
+ if ( cp != NULL )
+ {
+ l = strlen(ptp_name_dom);
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_settings.domain_number = atoi( cp+l );
+ }
+
+ // V1 Hardware compatibility flag
+ cp = strstr( arg, ptp_name_v1 );
+
+ if ( cp != NULL )
+ {
+ l = strlen(ptp_name_v1);
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if( atoi( cp+l) == 1 )
+ ptp_settings.flags |= PTP_CFG_MSK_V1_HW_COMPAT;
+ else if( atoi( cp+l) == 0 )
+ ptp_settings.flags &= ~PTP_CFG_MSK_V1_HW_COMPAT;
+ else
+ {
+ printf("error: No valid V1 HWC settings!\n");
+ goto fail;
+ }
+ }
+
+ if ( supports_unicast )
+ {
+
+ // PTP role
+ cp = strstr( arg, "ROLE" );
+
+ if ( cp != NULL )
+ {
+ l = strlen("ROLE");
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if ( strstr( (cp+l) , "UCS" ) != 0 )
+ ptp_settings.ptp_role = PTP_ROLE_UNICAST_SLAVE;
+ else
+ ptp_settings.ptp_role = PTP_ROLE_MULTICAST_SLAVE;
+ }
+
+
+ // GM Host
+ // (currently IP addresses accepted only) ##++
+ cp = strstr( arg, ptp_name_gm_ip );
+
+ if ( cp != NULL )
+ {
+ IP4_ADDR ip4addr;
+
+ l = strlen(ptp_name_gm_ip);
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if ( str_to_ip4_addr( &ip4addr, cp+l ) != NULL )
+ {
+ char ws[50];
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4addr );
+ printf( " GM IP Address: %s\n", ws );
+
+ strcpy( ptp_unicast_settings.gm_host, ws );
+ }
+ }
+
+
+ // GM Clock ID
+ cp = strstr( arg, ptp_name_gm_id );
+
+ if ( cp != NULL )
+ {
+ int i = 0;
+ char* p_tail;
+
+ l = strlen(ptp_name_gm_id);
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ for ( i= 0; i < sizeof( ptp_unicast_settings.gm_clock_id ); i++ )
+ {
+ if ( (*(cp+l+i) == 0) || (*(cp+l+i) == ',') )
+ break;
+
+ if ( *(cp+l+i) == ':' )
+ {
+ l++;
+ continue;
+ }
+
+ ptp_unicast_settings.gm_clock_id.b[i] = strtoul( (cp+l+i), &p_tail, 16 );
+
+ if ( p_tail == cp ) // no number found
+ goto fail;
+
+ l+=2;
+ }
+
+
+ if ( i != sizeof( ptp_unicast_settings.gm_clock_id ) )
+ {
+ printf("Syntax error in specifying GM Clock ID\n");
+ goto fail;
+ }
+ else
+ {
+ printf( " setting GM Clock ID: ");
+
+ for ( i = 0; i < sizeof( ptp_unicast_settings.gm_clock_id ); i++ )
+ {
+ printf( "%02X", ptp_unicast_settings.gm_clock_id.b[i] );
+
+ if ( i < ( sizeof( ptp_unicast_settings.gm_clock_id ) - 1 ) )
+ printf(":");
+ }
+
+ printf("\n");
+ }
+ }
+
+
+ // GM Target Port ID
+ cp = strstr( arg, ptp_name_tp_id );
+
+ if ( cp != NULL )
+ {
+ char* p_tail;
+
+ l = strlen( ptp_name_tp_id );
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_unicast_settings.gm_port_id = strtoul( cp+l, &p_tail, 10 );
+ printf( " setting GM port id: %d\n", ptp_unicast_settings.gm_port_id );
+ }
+
+
+ // Sync Message Rate
+ cp = strstr( arg, ptp_name_sr );
+
+ if ( cp != NULL )
+ {
+ l = strlen( ptp_name_sr );
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_unicast_settings.sync_interval = atoi( cp+l );
+ printf( " setting Sync Int: %i\n", ptp_unicast_settings.sync_interval );
+ }
+
+
+ // Announce Message Rate
+ cp = strstr( arg, ptp_name_ar );
+
+ if ( cp != NULL )
+ {
+ l = strlen( ptp_name_ar );
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_unicast_settings.announce_interval = atoi( cp+l );
+ printf( " setting Ann Int: %i\n", ptp_unicast_settings.announce_interval );
+ }
+
+
+ // Delay Message Rate
+ cp = strstr( arg, ptp_name_dr );
+
+ if ( cp != NULL )
+ {
+ l = strlen( ptp_name_dr );
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_unicast_settings.delay_request_interval = atoi( cp+l );
+ printf( " setting DelayReq Int: %i\n", ptp_unicast_settings.delay_request_interval );
+ }
+
+
+ // Message Duration
+ cp = strstr( arg, ptp_name_dur );
+
+ if ( cp != NULL )
+ {
+ l = strlen( ptp_name_dur );
+
+ if ( *(cp+l) != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ ptp_unicast_settings.message_duration = atoi( cp+l );
+ printf( " setting message duration: %i seconds\n", ptp_unicast_settings.message_duration );
+ }
+ }
+
+ rc = mbg_set_ptp_cfg_settings( dh, &ptp_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_ptp_cfg_settings" ) )
+ return rc;
+
+
+ if ( supports_unicast )
+ {
+ rc = mbg_set_ptp_unicast_cfg_settings( dh, &ptp_unicast_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_ptp_unicast_cfg_settings" ) )
+ return rc;
+ }
+
+ return MBG_SUCCESS;
+
+fail:
+
+ printf("Syntax error in argument!\n");
+
+ return MBG_ERR_CFG;
+
+} // set_ptp_cfg
+
+
+
+static /*HDR*/
+int ip4_check_parm( const char *s, IP4_INFO *p )
+{
+ int l = strlen( p->name );
+ const char *cp;
+
+ if ( strncmp( s, p->name, l ) != 0 )
+ return 0; // parameter does not match
+
+ if ( s[l] != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ cp = str_to_ip4_addr( p->addr, &s[l] );
+
+ if ( cp == NULL )
+ goto fail; // parameter syntax error: failed to convert numeric address
+
+ return cp - s;
+
+fail:
+ return MBG_ERR_CFG;
+
+} // ip4_check_parm
+
+
+
+static /*HDR*/
+int set_lan_intf( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ IP4_SETTINGS prv_ip4_settings;
+ IP4_SETTINGS ip4_settings = { 0 };
+ IP4_ADDR default_broad_addr;
+
+ IP4_INFO ip4_info[N_IP4_INFO] =
+ {
+ { ip4_name_ip, &ip4_settings.ip_addr },
+ { ip4_name_nm, &ip4_settings.netmask },
+ { ip4_name_ba, &ip4_settings.broad_addr },
+ { ip4_name_gw, &ip4_settings.gateway }
+ };
+
+ int rc = mbg_get_ip4_settings( dh, &prv_ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) )
+ return rc;
+
+ if ( strcmp( arg, "DHCP" ) == 0 )
+ {
+ ip4_settings = prv_ip4_settings;
+ ip4_settings.flags |= IP4_MSK_DHCP;
+ goto save;
+ }
+
+ for (;;)
+ {
+ int i;
+
+ for ( i = 0; i < N_IP4_INFO; i++ )
+ {
+ rc = ip4_check_parm( arg, &ip4_info[i] );
+
+ if ( rc == 0 ) // check next
+ continue;
+
+ if ( rc < 0 ) // error
+ goto invalid_msg;
+
+ arg += rc;
+
+ if ( *arg == 0 ) // end of parameter string
+ goto done;
+
+ if ( *arg != ',' )
+ goto invalid_msg;
+
+ arg++;
+ }
+ }
+
+
+done: // now check static configuration
+ if ( ip4_settings.ip_addr == 0 ) // no IP address specified on the command line
+ ip4_settings.ip_addr = prv_ip4_settings.ip_addr; // use previous IP address
+
+ if ( ip4_settings.ip_addr == 0 ) // no IP address specified at all
+ {
+ printf( "*** Aborting: No IP address specified\n" );
+ goto invalid;
+ }
+
+ if ( ip4_settings.netmask == 0 ) // no network mask specified on the command line
+ ip4_settings.netmask = prv_ip4_settings.netmask; // use previous network mask
+
+ if ( ip4_settings.netmask == 0 ) // no network mask specified at all
+ {
+ printf( "*** Aborting: No network mask specified\n" );
+ goto invalid;
+ }
+
+ // the default broadcast address is computed from the IP address and the network mask
+ default_broad_addr = ip4_settings.ip_addr | ~ip4_settings.netmask;
+
+ if ( ip4_settings.broad_addr == 0 ) // no broadcast address specified on the command line
+ ip4_settings.broad_addr = default_broad_addr;
+ else
+ if ( ip4_settings.broad_addr != default_broad_addr )
+ {
+ char ws1[40];
+ char ws2[40];
+ snprint_ip4_addr( ws1, sizeof( ws1 ), &ip4_settings.broad_addr );
+ snprint_ip4_addr( ws2, sizeof( ws2 ), &default_broad_addr );
+ printf( "*** Warning: Broadcast address %s does not match the default broadcast address %s\n",
+ ws1, ws2 );
+ }
+
+ if ( ip4_settings.gateway == 0 )
+ ip4_settings.gateway = prv_ip4_settings.gateway;
+
+ ip4_settings.flags = prv_ip4_settings.flags & ~IP4_MSK_DHCP;
+ // fall through to save:
+
+save:
+ rc = mbg_set_ip4_settings( dh, &ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_ip4_settings" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+
+invalid_msg:
+ printf( "*** Warning: invalid LAN interface parameter syntax\n" );
+ // fall through to invalid:
+
+invalid:
+ return MBG_ERR_CFG; // invalid parameter or parameter syntax error
+
+} // set_lan_intf
+
+
+
+static /*HDR*/
+int set_gps_pos( MBG_DEV_HANDLE dh, const char *gp )
+{
+ LLA new_pos_lla;
+ char *cp;
+ int rc;
+ double r2d = 180 / PI;
+
+ new_pos_lla[LAT] = strtod( gp, &cp ) / r2d;
+
+ if ( *cp++ != ',' )
+ goto invalid;
+
+ new_pos_lla[LON] = strtod( cp, &cp ) / r2d;
+
+ if ( *cp++ != ',' )
+ goto invalid;
+
+ new_pos_lla[ALT] = strtod( cp, &cp );
+
+ if (
+ ( ( new_pos_lla[LAT] * r2d ) < -90 ) ||
+ ( ( new_pos_lla[LAT] * r2d ) > +90 ) ||
+ ( ( new_pos_lla[LON] * r2d ) < -180 ) ||
+ ( ( new_pos_lla[LON] * r2d ) > +180 ) ||
+ ( new_pos_lla[ALT] < -50 ) ||
+ ( new_pos_lla[ALT] > 20000 )
+ )
+ goto invalid;
+
+
+ rc = mbg_set_gps_pos_lla ( dh, new_pos_lla );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_pos_lla" ) )
+ return rc;
+
+ printf( "The clock's receiver position has been set to lat=%+.4f, lon=%+.4f, alt=%.0fm\n",
+ new_pos_lla[LAT] * r2d, new_pos_lla[LON] * r2d, new_pos_lla[ALT] );
+
+ return rc;
+
+
+invalid:
+ fprintf( stderr, "** Invalid GPS position parameters: %s\n", gp );
+
+ return MBG_ERR_CFG;
+
+} // set_gps_pos
+
+
+
+static /*HDR*/
+int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
+ const char *sdate, const char *stime )
+{
+ PCPS_TIME_UNION u = { { 0 } };
+ TTM ttm = { 0 };
+ unsigned int year = 0;
+ unsigned int month = 0;
+ unsigned int mday = 0;
+ unsigned int hour = 0;
+ unsigned int min = 0;
+ unsigned int sec = 0;
+ unsigned int sec100 = 0;
+ int rc;
+
+ // Either a date string, a time string, or both
+ // may have been passed to this function.
+ // If either of them is NULL read the current date/time
+ // as default values.
+ if ( sdate == NULL || stime == NULL )
+ {
+ rc = mbg_get_time( dh, &u.t );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time" ) )
+ return rc;
+ }
+
+
+ if ( sdate )
+ {
+ rc = sscanf( sdate, "%u-%u-%u", &year, &month, &mday );
+
+ if ( ( rc < 3 )
+ || ( month < 1 ) || ( month > 12 )
+ || ( mday < 1 ) || ( mday > 31 ) )
+ {
+ printf( "** Invalid date: %04u-%02u-%02u\n", year, month, mday );
+ return MBG_ERR_CFG;
+ }
+ }
+
+
+ if ( stime )
+ {
+ rc = sscanf( stime, "%u:%u:%u.%u", &hour, &min, &sec, &sec100 );
+
+ if ( ( rc < 2 ) // at least hours and minutes are required
+ || ( hour > 23 )
+ || ( min > 59 )
+ || ( sec > 60 )
+ || ( sec100 > 99 ) )
+ {
+ printf( "** Invalid time: %02u:%02u:%02u.%02u\n", hour, min, sec, sec100 );
+ return MBG_ERR_CFG;
+ }
+ }
+
+ // GPS and non-GPS cards require different API calls which use
+ // different structures to set the on-board date and time,
+ // so we have to distinguish.
+
+ if ( _pcps_is_gps( p_dev ) ) // is a GPS card
+ {
+ ttm.channel = -1;
+
+ if ( sdate ) // new date
+ {
+ ttm.tm.year = year;
+ ttm.tm.month = month;
+ ttm.tm.mday = mday;
+ }
+ else // copy current date as default
+ {
+ ttm.tm.year = u.t.year + 2000;
+ ttm.tm.month = u.t.month;
+ ttm.tm.mday = u.t.mday;
+ }
+
+ if ( stime ) // new time
+ {
+ ttm.tm.hour = hour;
+ ttm.tm.min = min;
+ ttm.tm.sec = sec;
+ ttm.tm.frac = sec100;
+ }
+ else // copy current time as default
+ {
+ ttm.tm.hour = u.t.hour;
+ ttm.tm.min = u.t.min;
+ ttm.tm.sec = u.t.sec;
+ ttm.tm.frac = u.t.sec100;
+ }
+
+ ttm.tm.frac *= 100000; // fracs are in 100 ns units
+
+ #if 0
+ // Existing versions of the GPS cards just take
+ // TTM.tm as local time without accounting for
+ // the status flags, or UTC offset.
+ // Instead, the TTM.tm time is converted on-board
+ // to UTC depending on the local TZDL configuration.
+ // This works if the system time and the
+ ttm.tm.offs_from_utc = 7200;
+ ttm.tm.status |= TM_UTC | TM_LOCAL;
+ ttm.tm.status |= TM_DL_ENB;
+ #endif
+
+ rc = mbg_set_gps_time( dh, &ttm );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_time" ) )
+ return rc;
+ }
+ else // is not a GPS card
+ {
+ if ( sdate ) // new date
+ {
+ // determine the day-of-week for the given date
+ struct tm tm = { 0 };
+
+ tm.tm_year = year - 1900;
+ tm.tm_mon = month - 1;
+ tm.tm_mday = mday;
+ tm.tm_hour = 12;
+ tm.tm_isdst = -1;
+ mktime( &tm );
+
+ u.stime.year = year % 100;
+ u.stime.month = month;
+ u.stime.mday = mday;
+ u.stime.wday = _wday_sun06_to_mon17( tm.tm_wday );
+ }
+
+ if ( stime ) // new time
+ {
+ u.stime.hour = hour;
+ u.stime.min = min;
+ u.stime.sec = sec;
+ u.stime.sec100 = sec100;
+ }
+
+ if ( u.stime.wday == 0 )
+ u.stime.wday = 1; // dummy
+
+ rc = mbg_set_time( dh, &u.stime );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_time" ) )
+ return rc;
+ }
+
+ printf( "Device date/time have been set.\n" );
+
+ return MBG_SUCCESS;
+
+} // set_date_time
+
+
+
+static /*HDR*/
+void check_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
+ RECEIVER_INFO *p_ri )
+{
+ // Set up the RECEIVER_INFO structure only if this has not been done
+ // before. Check the ticks_per_sec field to see if the structure
+ // has already been set up or not.
+ if ( p_ri->ticks_per_sec == 0 )
+ mbg_setup_receiver_info( dh, p_dev, p_ri );
+
+} // check_setup_receiver_info
+
+
+
+static /*HDR*/
+int check_get_receiver_port_cfg( MBG_DEV_HANDLE dh, RECEIVER_PORT_CFG *p_rpcfg,
+ const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri )
+{
+ int rc = MBG_SUCCESS;
+
+ check_setup_receiver_info( dh, p_dev, p_ri );
+
+ // Set up the RECEIVER_PORT_CFG structure only if this has not been done
+ // before. Check whether the number of ports is > 0 and the first port's
+ // baud rate is still 0 to see if the structure has already been set up.
+ if ( ( p_ri->n_com_ports > 0 ) &&
+ ( p_rpcfg->pii[0].port_info.port_settings.parm.baud_rate == 0 ) )
+ {
+ rc = mbg_get_serial_settings( dh, p_dev, p_rpcfg, p_ri );
+
+ mbg_ioctl_err( rc, "mbg_get_serial_settings" );
+ }
+
+ return rc;
+
+} // check_get_receiver_port_cfg
+
+
+
+static /*HDR*/
+int snprint_port_cfg( char *s, int sz, unsigned int port_num,
+ const RECEIVER_PORT_CFG *p_rpcfg )
+{
+ const PORT_SETTINGS *p_ps = &p_rpcfg->pii[port_num].port_info.port_settings;
+
+ int n = snprintf( s, sz, "\"%s\" %s at %lu/%s",
+ p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
+ mode_names[p_ps->mode],
+ (unsigned long) p_ps->parm.baud_rate,
+ p_ps->parm.framing
+ );
+
+ return n;
+
+} // snprint_port_cfg
+
+
+
+static /*HDR*/
+void show_serial_settings( MBG_DEV_HANDLE dh, const RECEIVER_PORT_CFG *p_rpcfg,
+ const RECEIVER_INFO *p_ri )
+{
+ char ws[256];
+ unsigned int i;
+
+ for ( i = 0; i < p_ri->n_com_ports; i ++ )
+ {
+ snprint_port_cfg( ws, sizeof( ws ), i, p_rpcfg );
+ printf( "Serial port COM%u: %s.\n", i, ws );
+ }
+
+} // show_serial_settings
+
+
+
+static /*HDR*/
+void print_port_info_errors( const char *port_name, unsigned int port_num,
+ int flags, const RECEIVER_PORT_CFG *p_rpcfg )
+{
+ const char *msg_nsupp_drvr = "is not supported by the driver software";
+
+ const PORT_INFO *p_pi = &p_rpcfg->pii[port_num].port_info;
+ const PORT_SETTINGS *p_ps = &p_pi->port_settings;
+
+
+ if ( flags & MBG_PS_MSK_BAUD_RATE_OVR_SW )
+ printf( "** Baud rate %lu %s.\n", (ulong) p_ps->parm.baud_rate, msg_nsupp_drvr );
+ else
+ if ( flags & MBG_PS_MSK_BAUD_RATE )
+ printf( "** Baud rate %lu is not supported by %s%u.\n",
+ (ulong) p_ps->parm.baud_rate, port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_FRAMING_OVR_SW )
+ printf( "** Framing %s %s.\n", p_ps->parm.framing, msg_nsupp_drvr );
+ else
+ if ( flags & MBG_PS_MSK_FRAMING )
+ printf( "** Framing %s is not supported by %s%u.\n",
+ p_ps->parm.framing, port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_HS_OVR_SW )
+ printf( "** Handshake mode %u %s.\n", p_ps->parm.handshake, msg_nsupp_drvr );
+ else
+ if ( flags & MBG_PS_MSK_HS )
+ printf( "** Handshake mode %u is not supported by %s%u.\n",
+ (unsigned int) p_ps->parm.handshake, port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_STR_TYPE_OVR_DEV )
+ printf( "** String type index %u exceeds number of string types supp. by device.\n",
+ p_ps->str_type );
+ else
+ if ( flags & MBG_PS_MSK_STR_TYPE )
+ printf( "** String type \"%s\" is not supported by %s%u.\n",
+ p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
+ port_name, port_num );
+
+
+ if ( flags & MBG_PS_MSK_STR_MODE_OVR_SW )
+ printf( "** String mode index %u exceeds number of string modes supported by driver software (%u).\n",
+ p_ps->mode, N_STR_MODE );
+ else
+ if ( flags & MBG_PS_MSK_STR_MODE )
+ printf( "** String mode \"%s\" is not supported by string type \"%s\" via %s%u .\n",
+ mode_names[p_ps->mode],
+ p_rpcfg->stii[p_ps->str_type].str_type_info.long_name,
+ port_name, port_num );
+
+} // print_port_info_errors
+
+
+
+static /*HDR*/
+int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char *parm_str,
+ const PCPS_DEV *p_dev, const RECEIVER_INFO *p_ri )
+{
+ char ws[256];
+ RECEIVER_PORT_CFG rpcfg = { { { 0 } } };
+ PORT_INFO *p_pi = &rpcfg.pii[port_num].port_info;
+ PORT_SETTINGS *p_ps = &p_pi->port_settings;
+ ulong ul;
+ const char *cp;
+ char *p_tail;
+ int rc;
+ int flags;
+ int i;
+
+ // load current settings and supported settings
+ rc = mbg_get_serial_settings( dh, p_dev, &rpcfg, p_ri );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_serial_settings" ) )
+ return rc;
+
+
+ cp = parm_str;
+ p_ps->parm.baud_rate = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail == cp ) // no number found
+ goto invalid;
+
+ cp = p_tail;
+
+ if ( *cp++ != ',' ) // separator before framing missing
+ goto invalid;
+
+ for ( i = 0; i < sizeof( p_ps->parm.framing ); i++ )
+ {
+ int c = *cp;
+
+ if ( !isalnum( c ) ) // stop copying if non-alpha and non-digit
+ break;
+
+ p_ps->parm.framing[i] = *cp++;
+ }
+
+ p_ps->parm.framing[i] = 0; // force terminating 0
+
+ p_ps->parm.handshake = HS_NONE; // this is the only supported setting
+
+
+ // get optional string type index
+
+ if ( *cp++ != ',' )
+ goto done_parm_str;
+
+ ul = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail != cp )
+ p_ps->str_type = ul;
+
+ cp = p_tail;
+
+
+ // get optional string mode index
+
+ if ( *cp++ != ',' )
+ goto done_parm_str;
+
+ ul = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail != cp )
+ p_ps->mode = ul;
+
+
+done_parm_str:
+
+ // check if the new parameter set is valid
+ flags = check_valid_port_info( p_pi, rpcfg.stii, p_ri->n_str_type );
+
+ if ( flags ) // parameters not valid
+ {
+ print_port_info_errors( "COM", port_num, flags, &rpcfg );
+ goto invalid;
+ }
+
+ // save new parameters
+ rc = mbg_save_serial_settings( dh, p_dev, &rpcfg, port_num );
+
+ if ( mbg_ioctl_err( rc, "mbg_save_serial_settings" ) )
+ return rc;
+
+
+ snprint_port_cfg( ws, sizeof( ws ), port_num, &rpcfg );
+ printf( "The clock's COM%u port has been set to %s.\n", port_num, ws );
+
+ return MBG_SUCCESS;
+
+
+invalid:
+ fprintf( stderr, "** Invalid COM port parameters: %s\n", parm_str );
+ return MBG_ERR_CFG;
+
+} // save_serial_settings
+
+
+
+static /*HDR*/
+void printf_ef( uint16_t flag, const char *info )
+{
+ printf( "%s:%u", info, ( flag == EF_OFF ) ? 0 : 1 );
+
+} // printf_ef
+
+
+
+static /*HDR*/
+int show_enable_flags( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ ENABLE_FLAGS ef;
+ int rc;
+
+ rc = mbg_get_gps_enable_flags( dh, &ef );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) )
+ return rc;
+
+ printf( "%s enable flags: ", info );
+ printf_ef( ef.serial, ef_name_serial );
+ printf( "," );
+ printf_ef( ef.pulses, ef_name_pulses );
+
+ if ( _pcps_has_synth( p_dev ) )
+ {
+ printf( "," );
+ printf_ef( ef.synth, ef_name_synth );
+ }
+
+ printf( "\n" );
+
+ return MBG_SUCCESS;
+
+} // show_enable_flags
+
+
+
+static /*HDR*/
+int ef_check_parm( const char *s, EF_INFO *p )
+{
+ int l = strlen( p->name );
+
+ if ( strncmp( s, p->name, l ) != 0 )
+ return 0; // parameter does not match
+
+ if ( s[l] != ':' )
+ goto fail; // parameter syntax error: name not followed by colon
+
+ l++;
+
+ if ( s[l] != '0' && s[l] != '1' )
+ goto fail; // parameter syntax error: colon not followed by '0' or '1'
+
+ *p->flags = ( s[l] == '0' ) ? EF_OFF : p->on_flags;
+
+ l++;
+
+ return l;
+
+
+fail:
+ return MBG_ERR_CFG;
+
+} // ef_check_parm
+
+
+
+static /*HDR*/
+int set_enable_flags( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ ENABLE_FLAGS ef;
+
+ EF_INFO ef_parms[N_EF_INFO] =
+ {
+ { ef_name_serial, &ef.serial, EF_SERIAL_BOTH },
+ { ef_name_pulses, &ef.pulses, EF_PULSES_BOTH },
+ { ef_name_synth, &ef.synth, EF_SYNTH }
+ };
+
+ int rc;
+
+ rc = mbg_get_gps_enable_flags( dh, &ef );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) )
+ return rc;
+
+ // Scan input parameters
+ for (;;)
+ {
+ int i;
+
+ for ( i = 0; i < N_EF_INFO; i++ )
+ {
+ rc = ef_check_parm( arg, &ef_parms[i] );
+
+ if ( rc == 0 ) // check next
+ continue;
+
+ if ( rc < 0 ) // error
+ return rc;
+
+ arg += rc;
+
+ if ( *arg == 0 ) // done
+ goto save;
+
+ if ( *arg != ',' )
+ return MBG_ERR_CFG; // invalid parameter or parameter syntax error
+
+ arg++;
+ }
+ }
+
+save:
+ rc = mbg_set_gps_enable_flags( dh, &ef );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_enable_flags" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+} // set_enable_flags
+
+
+
+static /*HDR*/
+int send_gps_cmd( MBG_DEV_HANDLE dh, ushort cmd )
+{
+ int rc = mbg_set_gps_cmd( dh, &cmd );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_cmd" ) )
+ return rc;
+
+ printf( "NOTE: the command code %u has been sent to the GPS clock.\n", cmd );
+
+ return MBG_SUCCESS;
+
+} // send_gps_cmd
+
+
+
+static /*HDR*/
+int show_ant_cable_len( MBG_DEV_HANDLE dh, const char *info )
+{
+ ANT_CABLE_LEN len;
+ int rc = mbg_get_gps_ant_cable_len( dh, &len );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_ant_cable_len" ) )
+ return rc;
+
+ printf( "%s antenna cable length: %u meter(s)", info, len );
+
+ return MBG_SUCCESS;
+
+} // show_ant_cable_len
+
+
+
+static /*HDR*/
+int set_ant_cable_len( MBG_DEV_HANDLE dh, const char *s )
+{
+ ANT_CABLE_LEN len = atol( s );
+ int rc = mbg_set_gps_ant_cable_len( dh, &len );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_ant_cable_len" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+} // set_ant_cable_len
+
+
+
+static /*HDR*/
+int set_event_time( MBG_DEV_HANDLE dh, const char *s )
+{
+ char ws[80];
+ time_t event_time;
+ PCPS_TIME_STAMP event_ts;
+ int rc;
+
+ // set event at current system time + number of seconds
+ event_time = time( NULL ) + strtol( s, NULL, 10 );
+ event_ts.sec = event_time; // Unix UTC seconds
+ event_ts.frac = 0; // fraction of second, 0xFFFFFFFF == 0.99.. sec
+
+ rc = mbg_set_event_time( dh, &event_ts );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_event_time" ) )
+ return rc;
+
+ mbg_snprint_hr_tstamp( ws, sizeof( ws ), &event_ts );
+ printf( "Event time set to UTC %s\n", ws );
+
+ return MBG_SUCCESS;
+
+} // set_event_time
+
+
+
+static /*HDR*/
+int get_n_time_scale( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p_tsci )
+{
+ MBG_TIME_SCALE_INFO tsci = { { 0 } };
+ int rc;
+ int i;
+
+ rc = mbg_dev_has_time_scale( dh, &i );
+
+ if ( ( rc != MBG_SUCCESS ) || ( i == 0 ) )
+ goto done; // failed or not supported
+
+ rc = mbg_get_time_scale_info( dh, &tsci );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+ if ( p_tsci )
+ *p_tsci = tsci;
+
+done:
+ return tsci.max_settings.scale;
+
+} // get_n_time_scale
+
+
+
+static /*HDR*/
+int show_time_scale( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info )
+{
+ MBG_TIME_SCALE_INFO tsci = { { 0 } };
+ int rc;
+
+ rc = mbg_get_time_scale_info( dh, &tsci );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) )
+ return rc;
+
+ printf( "%s time scale index: %u (%s)", info, tsci.settings.scale,
+ _get_time_scale_name( tsci.settings.scale ) );
+
+ printf( "\n" );
+
+ return MBG_SUCCESS;
+
+} // show_time_scale
+
+
+
+static /*HDR*/
+int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev )
+{
+ MBG_TIME_SCALE_INFO tsci = { { 0 } };
+ int rc;
+
+ rc = mbg_get_time_scale_info( dh, &tsci );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) )
+ return rc;
+
+
+ tsci.settings.scale = atoi( arg );
+
+ if ( tsci.settings.scale >= tsci.max_settings.scale )
+ {
+ printf( "*** Error: new time scale index (%u) out of range (0..%u)\n",
+ tsci.settings.scale, tsci.max_settings.scale - 1 );
+ return MBG_ERR_CFG;
+ }
+
+ if ( !( tsci.supp_scales & ( 1UL << tsci.settings.scale ) ) )
+ {
+ printf( "*** Warning: new time scale index (%u) not supported by device\n",
+ tsci.settings.scale );
+ return MBG_ERR_CFG;
+ }
+
+ rc = mbg_set_time_scale_settings( dh, &tsci.settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_time_scale_settings" ) )
+ return rc;
+
+ return MBG_SUCCESS;
+
+} // set_time_scale
+
+
+
+static /*HDR*/
+void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri,
+ RECEIVER_PORT_CFG *p_rpcfg )
+{
+ int i;
+ int n_time_scale;
+
+ if ( p_dev )
+ {
+ check_setup_receiver_info( dh, p_dev, p_ri );
+ check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
+ }
+
+ printf( "Usage: %s cmd [dev]\n"
+ "\n"
+ "where cmd can be one of the following:\n"
+ " BOOT set GPS clock to boot mode\n"
+ " GPSPOS=x.x,y.y,z set GPS position to (lat,lon,alt)\n",
+ pname
+ );
+
+
+ printf( " DATE=yyyy-mm-dd set on-board date to year, month, day-of-month\n"
+ " TIME=hh:mm:ss.hh set on-board time to hours, mins, secs, hundredths\n"
+ );
+
+
+ printf( " TIMESCALE show clock's time scale setting, if supported\n"
+ " TIMESCALE=<n> set clock's time scale to scale with index <n>\n"
+ );
+
+ n_time_scale = p_dev ? get_n_time_scale( dh, NULL ) : N_MBG_TIME_SCALE;
+
+ if ( n_time_scale )
+ {
+ printf( " Known time scales:\n" );
+ for ( i = 0; i < n_time_scale; i++ )
+ {
+ printf( " %u: %s", i, _get_time_scale_name( i ) );
+
+ if ( i == 0 )
+ printf( " (default)" );
+
+ printf( "\n" );
+ }
+ }
+ else
+ printf( " (Configurable time scales not supported by this device)\n" );
+
+
+ printf( " TZOFFS show clock's time zone offset, if supported\n"
+ " TZOFFS=<n> set clock's basic time zone to UTC with additional offset, in seconds\n"
+ );
+
+ printf( " TZ=UTC set time zone code to %s\n"
+ " TZ=CET set time zone code to %s\n"
+ " TZ=EET set time zone code to %s\n",
+ tz_info_utc,
+ tz_info_cet_cest,
+ tz_info_eet_eest
+ );
+
+
+ printf( " COMPARM show clock's COM port parameters\n"
+ " COM<n>=<bd>,<f>[,<t>[,<m>]] set parameters of clock's port COM<n>"
+ );
+
+ printf( ", where\n"
+ " <bd> is one of:" );
+ for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
+ printf( " %s", mbg_baud_str[i] );
+
+ printf( "\n"
+ " <f> is one of:" );
+ for ( i = 0; i < N_MBG_FRAMINGS; i++ )
+ printf( " %s", mbg_framing_str[i] );
+
+ printf( "\n <t> optional time string format index" );
+
+ if ( p_dev )
+ {
+ printf( ":" );
+
+ for ( i = 0; i < p_ri->n_str_type; i ++ )
+ {
+ const STR_TYPE_INFO *p_sti = &p_rpcfg->stii[i].str_type_info;
+
+ printf( "\n %u: %s", i, p_sti->long_name );
+ }
+ }
+
+ printf( "\n <m> optional time string mode index" );
+
+ if ( p_dev )
+ {
+ printf( ":" );
+
+ for ( i = 0; i < N_STR_MODE; i ++ )
+ printf( "\n %u: %s", i, mode_names[i] );
+
+ printf( "\n"
+ " Please note not each baud rate, framing, string format and mode\n"
+ " must necessarily be supported by every individual serial port.\n" );
+ }
+
+ printf( "\n" );
+
+ printf( " EF show clock's enable flags\n"
+ " EF=SERIAL:0,PULSES:1,SYNTH:0 modify clock's enable flags\n"
+ "\n"
+ " SERIAL controls the serial port output\n"
+ " PULSES controls pulse outputs and IRIG timecode output, if available\n"
+ " SYNTH controls a programmable synthesizer output, if available\n"
+ "\n"
+ " 0 or 1 controls when the corresponding output signals are enabled:\n"
+ " 0: only after the card has synchronized to its incoming signal\n"
+ " 1: immediately after power-up\n"
+ "\n"
+ " Please note enable flags may not be supported by any device\n"
+ "\n"
+ );
+
+ printf( " LAN show board's LAN interface settings\n"
+ " LAN=DHCP set LAN interface to be configured via DHCP\n"
+ " LAN=IP:<ip>[,NM:<nm>][,BA:<ba>][,GW:<gw>] set LAN interface to given static settings\n"
+ "\n"
+ " where each of <ip>,<nm>,<ba>,<gw> is an IPv4 address of the form aaa.bbb.ccc.ddd, e.g.:\n"
+ " IP:192.168.1.115 specifies the IP address\n"
+ " NM:255.255.255.0 specifies the net mask\n"
+ " BA:192.168.1.255 specifies the broadcast address\n"
+ " GW:192.168.1.1 specifies the default gateway\n"
+ "\n"
+ " If no broadcast address is specified then the default broadcast address\n"
+ " is computed from the IP address and the network mask.\n"
+ "\n"
+ " Please note a LAN interface may not be provided by any board type.\n"
+ " Also, the IP values above are examples only. The real values to be used\n"
+ " depend on the settings of the network to which the card is attached.\n"
+ "\n"
+ );
+
+ printf( " PTP show board's PTP settings\n"
+ " PTP=NP:<np>[,DM:<dm>][,DO:<do>][,HW:<hw>] set general PTP protocol parameters\n"
+ "\n"
+ " where, e.g. :\n"
+ " NP:IP4 specifies UDP/IPv4 (Layer 3) as network protocol\n"
+ " NP:ETH specifies IEEE 802.3 (Layer 2) as network protocol\n"
+ " DM:E2E specifies end-to-end delay mechanism\n"
+ " DM:P2P specifies peer-to-peer delay mechanism\n"
+ " DO:0 specifies PTP domain number [0..255]\n"
+ " HW:1 specifies if the \"v1 hardware compatibility flag\" shall be set ('1') or disabled ('0')\n"
+ "\n"
+ );
+
+printf( " If the PTP device supports unicast mode then the following\n"
+ " additional parameters can be set:\n"
+ " PTP=ROLE:<rl>[,GMIP:<ip>][,GMID:<id>][,PID:<po>][,SR:<sr>][,AR:<ar>][,DR:<dr>][,DUR:<du>] set PTP unicast parameters\n"
+ "\n"
+ " where, e.g. :\n"
+ " ROLE:MCS specifies \"Multicast Slave\" PTP role\n"
+ " ROLE:UCS specifies \"Unicast Slave\" PTP role\n"
+ " GMIP:192.168.1.115 specifies the IP address of the grandmaster\n"
+ " GMID:FF:FF:FF:FF:FF:FF:FF:FF specifies the Clock ID of the grandmaster or FF:FF:... as wildcard\n"
+ " PID:1 specifies the target port id of the grandmaster port that shall be used or 65535 as wildcard\n"
+ " SR:0 specifies the Sync message rate requested from the grandmaster in 2^x seconds [-6..6]\n"
+ " AR:1 specifies the Announce message rate requested from the grandmaster in 2^x seconds [-6..6]\n"
+ " DR:1 specifies the DelayRequest message rate requested from the grandmaster in 2^x seconds [-6..6]\n"
+ " DUR:300 specifies the duration in seconds how long the master shall send messages to the slave until a timeout or renewal occurs\n"
+ "\n"
+ );
+
+printf( " ANT_CABLE_LEN show the configured antenna cable length\n"
+ " ANT_CABLE_LEN=<len> set the antenna cable length to be compensated to <len>, in meters.\n"
+ "\n"
+ " Please note note this parameter is only supported with cards which provide\n"
+ " compensation of the antenna cable signal propagation delay, i.e. GPS cards.\n"
+ "\n"
+ );
+
+ if ( p_dev )
+ {
+ if ( _pcps_has_event_time( p_dev ) )
+ printf( " EVENT=<n> set event time to system time + <n> seconds\n" );
+ }
+
+} // usage
+
+
+
+static /*HDR*/
+const char *str_parm_p(const char *s, const char *keyword )
+{
+ char *match = strstr( s, keyword );
+
+ if ( match && ( match == s ) )
+ return &s[strlen( keyword )];
+ else
+ return NULL;
+
+} // str_parm_p
+
+
+
+static /*HDR*/
+int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev,
+ RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg )
+{
+ const char *sdate = NULL;
+ const char *stime = NULL;
+ const char *cp;
+ int i;
+ int rc = 0;
+ int error_occurred = 0;
+
+ must_print_usage = 0;
+
+ for ( i = 1; i < argc; i++ )
+ {
+ if ( rc < 0 )
+ error_occurred = 1;
+
+ if ( rc > 0 )
+ must_print_usage = 1;
+
+ rc = 0;
+
+ if ( ( strcmp( argv[i], "-?" ) == 0 ) ||
+ ( strcmp( argv[i], "-h" ) == 0 ) ||
+ ( strcmp( argv[i], "--help" ) == 0 ) )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( strcmp( argv[i], "BOOT" ) == 0 )
+ {
+ if ( p_dev )
+ {
+ if ( _pcps_is_gps( p_dev ) )
+ rc = send_gps_cmd( dh, PC_GPS_CMD_BOOT );
+ else
+ err_msg( p_dev, no_gps_cmd );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TZ=" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ rc = set_timezone( dh, cp, p_dev );
+
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "GPSPOS=" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ if ( _pcps_is_gps( p_dev ) )
+ rc = set_gps_pos( dh, cp );
+ else
+ err_msg( p_dev, no_gps_cmd );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "DATE=" );
+
+ if ( cp )
+ {
+ sdate = cp;
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TIME=" );
+
+ if ( cp )
+ {
+ stime = cp;
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "COMPARM" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ check_setup_receiver_info( dh, p_dev, p_ri );
+ check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
+
+ if ( *cp != 0 )
+ {
+ printf( "** Invalid parameter: %s\n", argv[i] );
+ must_print_usage = 1;
+ continue;
+ }
+
+ show_serial_settings( dh, p_rpcfg, p_ri );
+ }
+
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "COM" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *p_tail;
+ ulong port_num;
+
+ check_setup_receiver_info( dh, p_dev, p_ri );
+ check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri );
+
+ port_num = strtoul( cp, &p_tail, 10 );
+
+ if ( p_tail == cp ) // no COM port number specified
+ {
+ printf( "** Invalid COM port specification: %s\n", argv[i] );
+ must_print_usage = 1;
+ continue;
+ }
+
+ cp = p_tail;
+
+ if ( port_num >= (ulong) p_ri->n_com_ports )
+ {
+ printf( "** COM port number %lu exceeds maximum %u\n",
+ port_num, p_ri->n_com_ports );
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( *cp != '=' )
+ {
+ printf( "** Invalid COM port specification: %s\n", argv[i] );
+ must_print_usage = 1;
+ continue;
+ }
+
+ rc = save_serial_settings( dh, (unsigned) port_num, ++cp, p_dev, p_ri );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "EF" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_gps_data( p_dev ) )
+ {
+ err_msg( p_dev, no_enable_flags );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_enable_flags( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ printf( "*** Warning: invalid enable flag parameter syntax\n" );
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_enable_flags( dh, p_dev, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TIMESCALE" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_time_scale( p_dev ) )
+ {
+ err_msg( p_dev, no_time_scale );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_time_scale( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_time_scale( dh, p_dev, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "TZOFFS" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_tzdl( p_dev ) )
+ {
+ err_msg( p_dev, no_tzdl );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_tzdl_offs( dh, ++cp );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_tzdl_offs( dh, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "LAN" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_lan_intf( p_dev ) )
+ {
+ err_msg( p_dev, no_lan_intf );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_lan_intf( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_lan_intf( dh, p_dev, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "PTP" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_ptp( p_dev ) )
+ {
+ err_msg( p_dev, no_ptp );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+
+ rc = set_ptp_cfg( dh, ++cp, p_dev );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+
+ }
+
+ show_ptp_cfg( dh, p_dev, info );
+ }
+ continue;
+ }
+
+ cp = str_parm_p( argv[i], "ANT_CABLE_LEN" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ char *info = "Current";
+
+ if ( !_pcps_has_cab_len( p_dev ) )
+ {
+ err_msg( p_dev, no_cab_len );
+ continue;
+ }
+
+ if ( *cp == '=' )
+ {
+ rc = set_ant_cable_len( dh, ++cp );
+
+ if ( rc < 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ info = "New";
+ }
+
+ show_ant_cable_len( dh, info );
+ }
+ continue;
+ }
+
+
+ cp = str_parm_p( argv[i], "EVENT" );
+
+ if ( cp )
+ {
+ if ( p_dev )
+ {
+ if ( _pcps_has_event_time( p_dev ) )
+ {
+ if ( *cp == '=' )
+ rc = set_event_time( dh, ++cp );
+ else
+ rc = -1;
+
+ if ( rc < 0 )
+ printf( "*** Warning: invalid event time parameter\n" );
+ }
+ else
+ err_msg( p_dev, no_event_time );
+ }
+ continue;
+ }
+
+ if ( dev_name == NULL )
+ dev_name = argv[i];
+
+#if 0 //##++
+ else
+ {
+ printf( "** Unknown command: %s\n", argv[i] );
+ must_print_usage = 1;
+ }
+#endif
+
+ }
+
+ if ( p_dev )
+ if ( sdate || stime )
+ rc = set_date_time( dh, p_dev, sdate, stime );
+
+ if ( error_occurred )
+ return -1;
+
+ if ( must_print_usage )
+ return 1;
+
+ return MBG_SUCCESS;
+
+} // check_cmd_line
+
+
+
+int main( int argc, char *argv[] )
+{
+ RECEIVER_PORT_CFG rpcfg = { { { 0 } } };
+ RECEIVER_INFO ri = { 0 };
+ PCPS_DEV dev = { { 0 } };
+ PCPS_DEV *pdev = NULL;
+ MBG_DEV_HANDLE dh = MBG_INVALID_DEV_HANDLE;
+ int rc;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // If no arguments have been given, just print usage.
+ if ( argc < 2 )
+ goto show_usage;
+
+ // Check the command line for a device name, but don't
+ // pass a device handle, so commands are not evaluated.
+ check_cmd_line( argc, argv, dh, NULL, &ri, &rpcfg );
+
+ if ( dev_name )
+ dh = open( dev_name, 0 ); // open specific device
+ else
+ dh = mbg_open_device( 0 ); // open first device found
+
+ if ( dh == MBG_INVALID_DEV_HANDLE )
+ {
+ perror( "Unable to open device" );
+ goto fail;
+ }
+
+ // get information about the device
+ rc = mbg_get_show_dev_info( dh, dev_name, &dev );
+
+ if ( rc < 0 )
+ goto fail;
+
+
+ pdev = &dev;
+
+ rc = check_cmd_line( argc, argv, dh, pdev, &ri, &rpcfg );
+
+ if ( rc < 0 )
+ goto fail;
+
+ if ( rc > 0 )
+ goto show_usage;
+
+ printf( "\n" );
+
+ mbg_close_device( &dh );
+
+ return 0;
+
+
+show_usage:
+ usage( dh, pdev, &ri, &rpcfg );
+ return 1;
+
+fail:
+ return 2;
+}
diff --git a/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile b/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile
new file mode 100755
index 0000000..92cfa46
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile
@@ -0,0 +1,29 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.2.1.2 2010/08/30 09:05:23 martin TEST $
+#
+# Description:
+# Makefile for mbgfasttstamp.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.2.1.2 2010/08/30 09:05:23 martin
+# Revision 1.2.1.1 2010/08/30 08:21:01 martin
+# Revision 1.2 2009/07/24 10:31:16 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.1 2008/12/22 11:45:01 martin
+# Initial revision.
+#
+#########################################################################
+
+TARGET = mbgfasttstamp
+INST_DIR = /usr/local/bin
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c b/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c
new file mode 100755
index 0000000..35bad13
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c
@@ -0,0 +1,271 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgfasttstamp.c 1.6.1.3 2011/01/28 12:04:07 martin TEST $
+ *
+ * Description:
+ * Main file for mbgfasttstamp program which demonstrates how to access
+ * a Meinberg device via memory mapped I/O, if supported by the device.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgfasttstamp.c $
+ * Revision 1.6.1.3 2011/01/28 12:04:07 martin
+ * Revision 1.6.1.2 2011/01/28 11:51:13 martin
+ * Revision 1.6.1.1 2011/01/28 11:17:00 martin
+ * Abort if MM access not supported on the target OS.
+ * Revision 1.6 2010/05/21 12:54:33 martin
+ * Print warning if no cycles supported on the target platform
+ * and thus latencies can not be computed.
+ * Revision 1.5 2009/09/29 15:02:14 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.4 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.3 2009/06/19 14:01:32 martin
+ * Made print_hr_timestamp() to toolutil.c as mbg_print_hr_timestamp().
+ * Updated version number to 3.2.0.
+ * Revision 1.2 2009/03/20 11:48:19 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * New parameter -r lets the program read raw timestamps
+ * using the new API call mbg_get_fast_hr_timestamp().
+ * Revision 1.1 2008/12/22 11:45:01 martin
+ * Initial revision.
+ * Revision 1.1 2008/12/22 11:05:24 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static const char *pname = "mbgfasttstamp";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2007-2009";
+
+
+#define MAX_TS_BURST 1000
+
+static int loops;
+static int burst_read;
+static int read_raw;
+
+
+
+// The function below reads a number of time stamps and prints
+// each timestamp immediately. This is not as fast as possible
+// since printing the time stamp takes some time to execute.
+// However, this can run continuously forever.
+
+static /*HDR*/
+int show_fast_hr_timestamp( MBG_DEV_HANDLE dh )
+{
+ int this_loops = loops;
+ PCPS_TIME_STAMP ts;
+ int32_t hns_latency = 0;
+
+ for (;;)
+ {
+ int rc = read_raw ? mbg_get_fast_hr_timestamp( dh, &ts ) :
+ mbg_get_fast_hr_timestamp_comp( dh, &ts, &hns_latency );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp..." ) )
+ goto fail;
+
+ mbg_print_hr_timestamp( &ts, hns_latency, NULL, read_raw );
+
+ if ( this_loops > 0 )
+ this_loops--;
+
+ if ( this_loops == 0 )
+ break;
+
+ // if this_loops is < 0 then loop forever
+ }
+
+ return 0;
+
+fail:
+ return -1;
+
+} // show_fast_hr_timestamp
+
+
+
+// The function below takes a number of time stamps and saves
+// them to a buffer. After the time stamps have been read
+// a second loop prints the time stamps from the buffer.
+// This way the time stamps are read in shorter intervals.
+// However, this can not run continuously forever since
+// the buffer size is somewhat limited.
+
+static /*HDR*/
+int show_fast_hr_timestamp_burst( MBG_DEV_HANDLE dh )
+{
+ PCPS_TIME_STAMP ts[MAX_TS_BURST];
+ int32_t hns_latency[MAX_TS_BURST];
+ int this_loops;
+ int i;
+
+ this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST;
+
+
+ if ( read_raw )
+ {
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_fast_hr_timestamp( dh, &ts[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp" ) )
+ goto fail;
+ }
+ }
+ else
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_fast_hr_timestamp_comp( dh, &ts[i], &hns_latency[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_comp" ) )
+ goto fail;
+ }
+
+ for ( i = 0; i < this_loops; i++ )
+ {
+ PCPS_TIME_STAMP *p_prv_ts = i ? &ts[i - 1] : NULL;
+ mbg_print_hr_timestamp( &ts[i], hns_latency[i], p_prv_ts, read_raw );
+ }
+
+ return 0;
+
+
+fail:
+ return -1;
+
+} // show_fast_hr_timestamp_burst
+
+
+
+static /*HDR*/
+int do_mbgfasttstamp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int supported = 0;
+ int rc = mbg_dev_has_fast_hr_timestamp( dh, &supported );
+
+ if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) )
+ goto done;
+
+ if ( !supported )
+ {
+ printf( "This device does not support fast (memory mapped) time stamps.\n" );
+ goto done;
+ }
+
+ if ( burst_read )
+ show_fast_hr_timestamp_burst( dh );
+ else
+ show_fast_hr_timestamp( dh );
+
+done:
+ mbg_close_device( &dh );
+
+ return rc;
+
+} // do_mbgfasttstamp
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads fast high resolution time stamps.\n"
+ "\n"
+ "This is done using memory mapped I/O in the kernel driver, so\n"
+ "this works only with cards which support memory mapped I/O."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-n num", "run num loops" );
+ mbg_print_opt_info( "-b", "burst read" );
+ mbg_print_opt_info( "-r", "read raw time stamps, no cycles" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "bcn:rh?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'b':
+ burst_read = 1;
+ break;
+
+ case 'c':
+ loops = -1;
+ break;
+
+ case 'n':
+ loops = atoi( optarg );
+ break;
+
+ case 'r':
+ read_raw = 1;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ #if !MBG_TGT_SUPP_MEM_ACC
+ printf( "** Memory mapped access not supported on this target platform.\n\n" );
+ return 1;
+ #endif
+
+ #if !defined( MBG_PC_CYCLES_SUPPORTED )
+ printf( "** Warning: No cycles support to compute real latencies on this platform!\n" );
+
+ if ( !read_raw )
+ {
+ read_raw = 1;
+ printf( "** Falling back to raw mode.\n" );
+ }
+
+ printf( "\n" );
+ #endif
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgfasttstamp );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbggpscap/Makefile b/src/external/bsd/meinberg/dist/mbggpscap/Makefile
new file mode 100755
index 0000000..6564761
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbggpscap/Makefile
@@ -0,0 +1,39 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.7.1.2 2010/08/30 09:05:23 martin TEST $
+#
+# Description:
+# Makefile for mbggpscap.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.7.1.2 2010/08/30 09:05:23 martin
+# Revision 1.7.1.1 2010/08/30 08:21:32 martin
+# Revision 1.7 2009/07/24 10:31:16 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.6 2008/12/22 11:56:58 martin
+# Changed enumeration of source files.
+# Define MBGDEVIO_SIMPLE to avoid inclusion of unnecessary modules.
+# Revision 1.5 2007/03/02 11:45:10 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.4 2003/07/08 15:33:46 martin
+# Added gpsutils.c to the module list.
+# Revision 1.3 2003/04/25 10:21:06 martin
+# Updated source module list.
+# Revision 1.2 2002/11/21 14:56:31 martin
+# New targets install and uninstall.
+# Revision 1.1 2001/09/17 15:08:22 martin
+#
+#########################################################################
+
+TARGET = mbggpscap
+INST_DIR = /usr/local/bin
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += gpsutils.o
+OBJS += toolutil.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c b/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c
new file mode 100755
index 0000000..bfa8804
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c
@@ -0,0 +1,391 @@
+
+/**************************************************************************
+ *
+ * $Id: mbggpscap.c 1.10.1.2 2010/11/12 12:27:17 martin TEST $
+ *
+ * Description:
+ * Main file for mbggpscap program which demonstrates how to access
+ * a Meinberg device via IOCTL calls and read entries from the time
+ * capture FIFO buffer.
+ *
+ * Please note that this may only work with devices which provide
+ * time capture input(s).
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbggpscap.c $
+ * Revision 1.10.1.2 2010/11/12 12:27:17 martin
+ * Improved reading capture events arriving at a high rate.
+ * Support validation of capture signals arriving at a constant rate.
+ * Revision 1.10.1.1 2010/03/10 16:42:33 martin
+ * Improved code execution paths.
+ * Revision 1.10 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.9 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.8 2009/06/19 12:38:51 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.7 2009/03/19 17:04:26 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Revision 1.6 2008/12/22 12:00:55 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.5 2007/07/24 09:32:26 martin
+ * Updated copyright to include 2007.
+ * Revision 1.4 2006/02/22 15:29:17 martin
+ * Support new ucap API.
+ * Print an error message if device can't be opened.
+ * Revision 1.3 2004/11/08 15:47:10 martin
+ * Using type cast to avoid compiler warning.
+ * Revision 1.2 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.1 2001/09/17 15:08:22 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+
+
+#define USLEEP_INTV 10000 // [microseconds]
+
+static const char *pname = "mbggpscap";
+static const char *pversion = "v3.4.1";
+static const char *pcopyright = "(c) Meinberg 2001-2010";
+
+
+static int continuous;
+static double nom_cap_intv; // nominal capture interval to check [s]
+static double max_cap_jitter; // max allowed jitter [s]
+
+static int has_been_called;
+static int must_check_intv;
+static ulong err_cnt;
+static PCPS_HR_TIME prv_ucap;
+
+
+static /*HDR*/
+void show_ucap_status( ulong status )
+{
+ // status bit definitions can be found in pcpsdefs.h.
+
+ if ( status & PCPS_UCAP_OVERRUN ) // capture events have occurred too fast
+ printf( " << CAP OVR" );
+
+ if ( status & PCPS_UCAP_BUFFER_FULL ) // capture buffer has been full, events lost
+ printf( " << BUF OVR" );
+
+} // show_ucap_status
+
+
+
+static /*HDR*/
+void show_ucap_event( const PCPS_HR_TIME *ucap )
+{
+ char ws[80];
+
+ // Print converted date and time to a string:
+ mbg_snprint_hr_time( ws, sizeof( ws ), ucap );
+
+ // Print the time stamp, ucap->signal contains the channel number:
+ printf( "New capture: CH%i: %s", ucap->signal, ws );
+
+ if ( must_check_intv && has_been_called )
+ {
+ double abs_delta;
+ double d = ucap->tstamp.sec - prv_ucap.tstamp.sec;
+ d += ( (double) ucap->tstamp.frac - prv_ucap.tstamp.frac ) / PCPS_HRT_BIN_FRAC_SCALE;
+
+ printf( " %+.6f", d );
+
+ abs_delta = d - nom_cap_intv;
+
+ if ( abs_delta < 0.0 )
+ abs_delta = -abs_delta;
+
+ if ( abs_delta > max_cap_jitter )
+ err_cnt++;
+
+ if ( err_cnt )
+ printf( " ** %lu", err_cnt );
+ }
+
+ show_ucap_status( ucap->status );
+
+ prv_ucap = *ucap;
+ has_been_called = 1;
+
+ printf( "\n" );
+
+} // show_ucap_event
+
+
+
+// The function below is normally outdated, and show_ucap_event()
+// above should be used if possible, together with the associated
+// API calls.
+
+static /*HDR*/
+void show_gps_ucap( const TTM *ucap )
+{
+ printf( "New capture: CH%i: %04i-%02i-%02i %2i:%02i:%02i.%07li",
+ ucap->channel,
+ ucap->tm.year,
+ ucap->tm.month,
+ ucap->tm.mday,
+ ucap->tm.hour,
+ ucap->tm.min,
+ ucap->tm.sec,
+ (ulong) ucap->tm.frac
+ );
+
+ show_ucap_status( ucap->tm.status );
+
+ printf( "\n" );
+
+} // show_gps_ucap
+
+
+
+static /*HDR*/
+void check_serial_mode( MBG_DEV_HANDLE dh )
+{
+ PORT_PARM port_parm;
+ int i;
+ int must_modify = 0;
+
+ // read the clock's current port settings
+ int rc = mbg_get_gps_port_parm( dh, &port_parm );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_port_parm" ) )
+ return;
+
+
+ // If one of the ports has been set to send user captures
+ // then the user capture buffer will most often be empty
+ // if we check for captures, so modify the port mode.
+ for ( i = 0; i < N_COM; i++ )
+ {
+ if ( port_parm.mode[i] == STR_UCAP )
+ {
+ port_parm.mode[i] = STR_UCAP_REQ;
+ must_modify = 1;
+ }
+ }
+
+ if ( !must_modify )
+ return;
+
+
+ rc = mbg_set_gps_port_parm( dh, &port_parm );
+
+ if ( mbg_ioctl_err( rc, "mbg_set_gps_port_parm" ) )
+ return;
+
+ printf( "NOTE: the clock's serial port mode has been changed.\n" );
+
+} // check_serial_mode
+
+
+
+static /*HDR*/
+int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int rc;
+
+ must_check_intv = continuous && ( nom_cap_intv != 0 );
+ has_been_called = 0;
+ err_cnt = 0;
+
+ if ( !_pcps_has_ucap( p_dev ) && !_pcps_is_gps( p_dev ) )
+ {
+ printf( "This device type does not provide time capture inputs.\n" );
+ return 0;
+ }
+
+ check_serial_mode( dh );
+
+ printf( "Be sure the card has been properly configured to enable capture inputs.\n" );
+
+ // There's an older API which has been introduced with the first GPS boards
+ // and uses the TTM structure to return the capture events. However, that
+ // API call is slow and not very flexible, so a new set of API calls has been
+ // introduced to handle capture events.
+ // The new API calls are supported by all supported by all newer boards which
+ // provide user capture inputs, and also for older boards with a firmware update.
+
+ if ( _pcps_has_ucap( p_dev ) ) // check if the new API is supported
+ {
+ // The new API provides the following functions:
+ // mbg_clr_ucap_buff() clear the on-board FIFO buffer
+ // mbg_get_ucap_entries() get the max number of FIFO entries, and the current number of entries
+ // mbg_get_ucap_event() read one entry from the FIFO
+
+ PCPS_UCAP_ENTRIES ucap_entries;
+
+ // retrieve and print information of the maximum number of events that can
+ // be stored in the on-board FIFO, and the number of events that are currently
+ // stored
+ rc = mbg_get_ucap_entries( dh, &ucap_entries );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ // Cards report they could save one more capture event
+ // than they actually do save, so adjust the reported value
+ // for a proper display.
+ if ( ucap_entries.max )
+ ucap_entries.max--;
+
+ printf( "\nOn-board FIFO: %u of %u entries used\n\n",
+ ucap_entries.used, ucap_entries.max );
+ }
+
+ // If the program is not to run continuously and no
+ // capture events are available then we're through.
+ if ( !continuous && ucap_entries.used == 0 )
+ return 0;
+
+
+ printf( ( ucap_entries.used == 0 ) ?
+ "Waiting for capture events:\n" :
+ "Reading capture events:\n"
+ );
+
+ // Now read out all events from the FIFO and wait
+ // for new events if the FIFO is empty.
+ for (;;)
+ {
+ PCPS_HR_TIME ucap_event;
+
+ rc = mbg_get_ucap_event( dh, &ucap_event );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ucap_event" ) )
+ break; // an error has occurred
+
+ // If a user capture event has been read then it
+ // has been removed from the card's FIFO buffer.
+
+ // If the time stamp is not 0 then a new capture event has been retrieved.
+ if ( ucap_event.tstamp.sec || ucap_event.tstamp.frac )
+ {
+ show_ucap_event( &ucap_event );
+ continue;
+ }
+
+ usleep( USLEEP_INTV ); // sleep, then try again
+ }
+ }
+ else // use the old API
+ {
+ printf( "Checking for capture events:\n" );
+
+ for (;;)
+ {
+ TTM ucap_ttm;
+
+ rc = mbg_get_gps_ucap( dh, &ucap_ttm );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_ucap" ) )
+ break; // an error has occurred
+
+
+ // If a user capture event has been read then it
+ // has been removed from the card's FIFO buffer.
+
+ // If a new capture event has been available then
+ // the ucap.tm contains a time stamp.
+ if ( _pcps_time_is_read( &ucap_ttm.tm ) )
+ show_gps_ucap( &ucap_ttm );
+
+ if ( !continuous )
+ {
+ printf( "No capture event available!\n" );
+ break;
+ }
+
+ usleep( USLEEP_INTV ); // sleep, then try again
+ }
+ }
+
+ return 0;
+
+} // do_mbggpscap
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads time capture events from a card.\n"
+ "This works only with cards which provide time capture inputs."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-i val", "check interval between captures events [s]" );
+ mbg_print_opt_info( "-j val", "max allowed jitter of capture interval [s]" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "ci:j:h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'c':
+ continuous = 1;
+ break;
+
+ case 'i':
+ nom_cap_intv = atof( optarg );
+ break;
+
+ case 'j':
+ max_cap_jitter = atof( optarg );
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbggpscap );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbghrtime/Makefile b/src/external/bsd/meinberg/dist/mbghrtime/Makefile
new file mode 100755
index 0000000..e332204
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbghrtime/Makefile
@@ -0,0 +1,39 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.7.1.2 2010/08/30 09:05:23 martin TEST $
+#
+# Description:
+# Makefile for mbghrtime.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.7.1.2 2010/08/30 09:05:23 martin
+# Revision 1.7.1.1 2010/08/30 08:21:39 martin
+# Revision 1.7 2009/07/24 10:31:16 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.6 2008/12/22 11:56:59 martin
+# Changed enumeration of source files.
+# Define MBGDEVIO_SIMPLE to avoid inclusion of unnecessary modules.
+# Revision 1.5 2007/03/02 11:45:10 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.4 2003/07/08 15:33:46 martin
+# Added gpsutils.c to the module list.
+# Revision 1.3 2003/04/25 10:21:06 martin
+# Updated source module list.
+# Revision 1.2 2002/11/21 14:56:31 martin
+# New targets install and uninstall.
+# Revision 1.1 2001/09/17 15:08:31 martin
+#
+#########################################################################
+
+TARGET = mbghrtime
+INST_DIR = /usr/local/bin
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c b/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c
new file mode 100755
index 0000000..86214a2
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c
@@ -0,0 +1,287 @@
+
+/**************************************************************************
+ *
+ * $Id: mbghrtime.c 1.11.1.4 2011/01/28 12:04:08 martin TEST $
+ *
+ * Description:
+ * Main file for mbghrtime program which demonstrates how to access
+ * a Meinberg device via IOCTL calls to read high resolution
+ * time stamps, if supported by the device.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbghrtime.c $
+ * Revision 1.11.1.4 2011/01/28 12:04:08 martin
+ * Revision 1.11.1.3 2011/01/28 11:52:51 martin
+ * Revision 1.11.1.2 2011/01/28 11:51:13 martin
+ * Revision 1.11.1.1 2011/01/28 11:17:33 martin
+ * Starrted to support raw and burst.
+ * Revision 1.11 2010/05/21 12:54:33 martin
+ * Print warning if no cycles supported on the target platform
+ * and thus latencies can not be computed.
+ * Revision 1.10 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.9 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.8 2009/06/19 14:03:53 martin
+ * Use common mbg_print_hr_timestamp() for unified output format.
+ * Updated version number to 3.2.0.
+ * Revision 1.7 2009/03/20 11:45:16 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Call mbg_get_hr_time_comp() instead of mbg_get_hr_time_cycles().
+ * Revision 1.6 2008/12/22 12:02:00 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Revision 1.5 2007/07/24 09:32:41 martin
+ * Updated copyright to include 2007.
+ * Revision 1.4 2004/11/08 15:45:22 martin
+ * Modifications to support 64 bit systems in a clean way.
+ * Revision 1.3 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.2 2001/11/30 10:01:49 martin
+ * Account for the modified definition of PCPS_HR_TIME which
+ * uses the new structure PCPS_TIME_STAMP now.
+ * Revision 1.1 2001/09/17 15:08:31 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h> // gettimeofday()
+
+
+
+static const char *pname = "mbghrtime";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2001-2009";
+
+
+#define MAX_TS_BURST 1000
+
+static int loops;
+static int burst_read;
+static int read_raw;
+
+
+
+// The function below reads a number of time stamps and prints
+// each timestamp immediately. This is not as fast as possible
+// since printing the time stamp takes some time to execute.
+// However, this can run continuously forever.
+
+static /*HDR*/
+int show_hr_timestamp( MBG_DEV_HANDLE dh )
+{
+ PCPS_HR_TIME ht = { { 0 } };
+ PCPS_HR_TIME prv_ht = { { 0 } };
+ PCPS_TIME_STAMP *p = NULL;
+ int32_t hns_latency = 0;
+ int this_loops = loops;
+
+ for (;;)
+ {
+ int rc = read_raw ? mbg_get_hr_time( dh, &ht ) :
+ mbg_get_hr_time_comp( dh, &ht, &hns_latency );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time_..." ) )
+ goto fail;
+
+ mbg_print_hr_timestamp( &ht.tstamp, hns_latency, p, read_raw );
+
+ prv_ht = ht;
+ p = &prv_ht.tstamp;
+
+ if ( this_loops > 0 )
+ this_loops--;
+
+ if ( this_loops == 0 )
+ break;
+
+ // if this_loops is < 0 then loop forever
+ }
+
+ return 0;
+
+fail:
+ return -1;
+
+} // show_hr_timestamp
+
+
+
+// The function below takes a number of time stamps and saves
+// them to a buffer. After the time stamps have been read
+// a second loop prints the time stamps from the buffer.
+// This way the time stamps are read in shorter intervals.
+// However, this can not run continuously forever since
+// the buffer size is somewhat limited.
+
+static /*HDR*/
+int show_hr_timestamp_burst( MBG_DEV_HANDLE dh )
+{
+ PCPS_HR_TIME ht[MAX_TS_BURST] = { { { 0 } } };
+ int32_t hns_latency[MAX_TS_BURST];
+ int this_loops;
+ int i;
+
+ this_loops = ( loops && ( loops < MAX_TS_BURST ) ) ? loops : MAX_TS_BURST;
+
+
+ if ( read_raw )
+ {
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_hr_time( dh, &ht[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) )
+ goto fail;
+ }
+ }
+ else
+ for ( i = 0; i < this_loops; i++ )
+ {
+ int rc = mbg_get_hr_time_comp( dh, &ht[i], &hns_latency[i] );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time_comp" ) )
+ goto fail;
+ }
+
+ for ( i = 0; i < this_loops; i++ )
+ {
+ PCPS_HR_TIME *p_prv_ht = i ? &ht[i - 1] : NULL;
+ mbg_print_hr_timestamp( &ht[i].tstamp, hns_latency[i], &p_prv_ht->tstamp, read_raw );
+ }
+
+ return 0;
+
+
+fail:
+ return -1;
+
+} // show_hr_timestamp_burst
+
+
+
+static /*HDR*/
+int do_mbghrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int supported = 0;
+ int rc = mbg_dev_has_hr_time( dh, &supported );
+
+ if ( mbg_ioctl_err( rc, "mbg_dev_has_hr_time" ) )
+ goto done;
+
+ if ( !supported )
+ {
+ printf( "High resolution time not supported by this device.\n" );
+ goto done;
+ }
+
+ if ( burst_read )
+ show_hr_timestamp_burst( dh );
+ else
+ show_hr_timestamp( dh );
+
+done:
+ mbg_close_device( &dh );
+
+ return rc;
+
+} // do_mbghrtime
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads high resolution time stamps (HR time)\n"
+ "from a device.\n"
+ "This works only for devices which support high resolution time (HR time)."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-n num", "run num loops" );
+ mbg_print_opt_info( "-b", "burst read" );
+ mbg_print_opt_info( "-r", "read raw time stamps, no cycles" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "bcn:rh?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'b':
+ burst_read = 1;
+ break;
+
+ case 'c':
+ loops = -1;
+ break;
+
+ case 'n':
+ loops = atoi( optarg );
+ break;
+
+ case 'r':
+ read_raw = 1;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+
+ #if !defined( MBG_PC_CYCLES_SUPPORTED )
+ printf( "** Warning: No cycles support to compute real latencies on this platform!\n" );
+
+ if ( !read_raw )
+ {
+ read_raw = 1;
+ printf( "** Falling back to raw mode.\n" );
+ }
+
+ printf( "\n" );
+ #endif
+
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbghrtime );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile b/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile
new file mode 100755
index 0000000..fbeb4b5
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile
@@ -0,0 +1,36 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.5.1.2 2010/08/30 09:05:23 martin TEST $
+#
+# Description:
+# Makefile for mbgirigcfg.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.5.1.2 2010/08/30 09:05:23 martin
+# Revision 1.5.1.1 2010/08/30 08:21:45 martin
+# Revision 1.5 2009/07/24 10:31:17 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.4 2008/12/22 11:56:59 martin
+# Changed enumeration of source files.
+# Define MBGDEVIO_SIMPLE to avoid inclusion of unnecessary modules.
+# Revision 1.3 2007/03/02 11:45:10 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.2 2003/07/08 15:33:47 martin
+# Added gpsutils.c to the module list.
+# Revision 1.1 2003/04/25 10:42:10 martin
+#
+#########################################################################
+
+TARGET = mbgirigcfg
+INST_DIR = /usr/local/sbin
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
+
diff --git a/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c b/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c
new file mode 100755
index 0000000..95f6238
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c
@@ -0,0 +1,728 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgirigcfg.c 1.10.1.4 2011/02/02 12:28:44 martin TEST $
+ *
+ * Description:
+ * Main file for the mbgirigcfg program which can be used to configure
+ * the IRIG code frame and the UTC offset of the time contained in the
+ * IRIG code.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgirigcfg.c $
+ * Revision 1.10.1.4 2011/02/02 12:28:44 martin
+ * Revision 1.10.1.3 2010/08/30 08:22:24 martin
+ * Revision 1.10.1.2 2010/08/19 13:57:42 martin
+ * Revision 1.10.1.1 2010/08/19 11:26:12 martin
+ * Accept parameter -? to print usage.
+ * New parameter -i to let incoming TFOM flag be ignored.
+ * Revision 1.10 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.9 2009/07/24 09:50:08 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.8 2009/06/19 12:38:51 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.7 2009/03/19 17:07:16 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Include mbgtime.h for some symbolic constants.
+ * Revision 1.6 2008/12/22 12:42:58 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.5 2007/07/24 09:34:46 martin
+ * Changes due to renamed library symbols.
+ * Updated copyright to include 2007.
+ * Revision 1.4 2006/08/28 10:08:17 martin
+ * Display TFOM settings only it the selected IRIG code format supports TFOM.
+ * Revision 1.3 2006/07/03 13:27:31 martin
+ * Source code cleanup and fixed a typo.
+ * Revision 1.2 2004/11/08 15:59:10 martin
+ * Support separate config of IRIG RX and TX.
+ * Changes due to renamed symbols.
+ * Revision 1.1 2003/04/25 10:42:10 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <mbgtime.h>
+#include <pcpsmktm.h>
+#include <pcpsutil.h>
+#include <pcpslstr.h>
+#include <myutil.h>
+#include <toolutil.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+static const char pname[] = "mbgirigcfg";
+static const char pversion[] = "v3.4.0";
+static const char pcopyright[] = "(c) Meinberg 2003-2009";
+
+static const char str_yes[] = "YES";
+static const char str_no[] = "NO";
+static const char str_not_supp[] = " (not supp. by this frame type)";
+
+static const char info_curr[] = "Current";
+static const char info_new[] = "New";
+static const char msg_rx[] = DEFAULT_OPT_NAME_IRIG_RX_EN;
+static const char msg_tx[] = DEFAULT_OPT_NAME_IRIG_TX_EN;
+
+static IRIG_INFO irig_rx_info;
+static IRIG_INFO irig_tx_info;
+static MBG_REF_OFFS ref_offs;
+static MBG_OPT_INFO opt_info;
+
+static int cfg_err;
+static int changed_cfg_rx;
+static int changed_cfg_tx;
+
+static const char *icode_rx_names[N_ICODE_RX] = DEFAULT_ICODE_RX_NAMES;
+static const char *icode_rx_descr[N_ICODE_RX] = DEFAULT_ICODE_RX_DESCRIPTIONS_ENG;
+
+static const char *icode_tx_names[N_ICODE_TX] = DEFAULT_ICODE_TX_NAMES;
+static const char *icode_tx_descr[N_ICODE_TX] = DEFAULT_ICODE_TX_DESCRIPTIONS_ENG;
+
+static int max_ref_offs_h = MBG_REF_OFFS_MAX / MINS_PER_HOUR;
+
+
+static /*HDR*/
+int get_cfg( MBG_DEV_HANDLE dh, PCPS_DEV *pdev )
+{
+ int rc_rx = MBG_SUCCESS;
+ int rc_tx = MBG_SUCCESS;
+
+ if ( _pcps_is_irig_rx( pdev ) )
+ {
+ rc_rx = mbg_get_irig_rx_info( dh, &irig_rx_info );
+
+ if ( rc_rx == MBG_SUCCESS && _pcps_has_ref_offs( pdev ) )
+ rc_rx = mbg_get_ref_offs( dh, &ref_offs );
+
+ if ( rc_rx == MBG_SUCCESS && _pcps_has_opt_flags( pdev ) )
+ rc_rx = mbg_get_opt_info( dh, &opt_info );
+ }
+
+ if ( _pcps_has_irig_tx( pdev ) )
+ {
+ rc_tx = mbg_get_irig_tx_info( dh, &irig_tx_info );
+ }
+
+
+ if ( rc_rx != MBG_SUCCESS )
+ printf( "** Error reading current IRIG RX configuration.\n" );
+
+ if ( rc_tx != MBG_SUCCESS )
+ printf( "** Error reading current IRIG TX configuration.\n" );
+
+ if ( rc_rx != MBG_SUCCESS || rc_tx != MBG_SUCCESS )
+ return -1; //##++
+
+ return MBG_SUCCESS;
+
+} // get_cfg
+
+
+
+static /*HDR*/
+int save_cfg( MBG_DEV_HANDLE dh, PCPS_DEV *pdev )
+{
+ int rc_rx = MBG_SUCCESS;
+ int rc_tx = MBG_SUCCESS;
+
+ if ( _pcps_is_irig_rx( pdev ) )
+ {
+ rc_rx = mbg_set_irig_rx_settings( dh, &irig_rx_info.settings );
+
+ if ( rc_rx == MBG_SUCCESS && _pcps_has_ref_offs( pdev ) )
+ rc_rx = mbg_set_ref_offs( dh, &ref_offs );
+
+ if ( rc_rx == MBG_SUCCESS && _pcps_has_opt_flags( pdev ) )
+ rc_rx = mbg_set_opt_settings( dh, &opt_info.settings );
+ }
+
+ if ( rc_rx == MBG_SUCCESS && _pcps_has_irig_tx( pdev ) )
+ {
+ rc_tx = mbg_set_irig_tx_settings( dh, &irig_tx_info.settings );
+ }
+
+ if ( rc_rx != MBG_SUCCESS )
+ printf( "** Error writing IRIG RX configuration.\n" );
+
+ if ( rc_tx != MBG_SUCCESS )
+ printf( "** Error writing IRIG TX configuration.\n" );
+
+ if ( rc_rx != MBG_SUCCESS || rc_tx != MBG_SUCCESS )
+ return -1;
+
+ return MBG_SUCCESS;
+
+} // save_cfg
+
+
+
+static /*HDR*/
+void print_cfg_rx( const char *info, const char *msg )
+{
+ int idx = irig_rx_info.settings.icode;
+ int ref_offs_h = ref_offs / MINS_PER_HOUR;
+
+ printf( "%s %s:\n", info, msg );
+
+ printf( " " DEFAULT_STR_IRIG_FMT_EN ": %s, %s\n",
+ icode_rx_names[idx],
+ icode_rx_descr[idx]
+ );
+
+ printf( " " DEFAULT_IGNORE_RX_TFOM_EN ": %s%s\n",
+ ( irig_rx_info.settings.flags & IFLAGS_DISABLE_TFOM ) ? str_yes : str_no,
+ ( _idx_bit( idx ) & MSK_ICODE_RX_HAS_TFOM ) ? "" : str_not_supp );
+
+ printf( " " DEFAULT_STR_IRIG_OFFS_EN ": " );
+
+ if ( abs( ref_offs_h ) > max_ref_offs_h )
+ printf( "** not configured **\n" );
+ else
+ printf( "%+i h\n", ref_offs_h );
+
+ if ( opt_info.supp_flags & MBG_OPT_FLAG_STR_UTC )
+ printf( " " DEFAULT_STR_IRIG_TIMESTR_UTC_EN ": %s\n",
+ ( opt_info.settings.flags & MBG_OPT_FLAG_STR_UTC ) ?
+ str_yes : str_no );
+
+} // print_cfg_rx
+
+
+
+static /*HDR*/
+void print_cfg_tx( const char *info, const char *msg )
+{
+ int idx = irig_tx_info.settings.icode;
+
+ printf( "%s %s:\n", info, msg );
+
+ printf( " " DEFAULT_STR_IRIG_FMT_EN ": %s, %s\n",
+ icode_tx_names[idx],
+ icode_tx_descr[idx]
+ );
+
+ printf( " " DEFAULT_STR_TFOM_ALWAYS_SYNC_EN ": %s%s\n",
+ ( irig_tx_info.settings.flags & IFLAGS_DISABLE_TFOM ) ? str_yes : str_no,
+ ( _idx_bit( idx ) & MSK_ICODE_TX_HAS_TFOM ) ? "" : str_not_supp );
+
+ printf( " " DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN ": %s\n",
+ ( irig_tx_info.settings.flags & IFLAGS_TX_GEN_LOCAL_TIME ) ?
+ str_yes : str_no
+ );
+
+} // print_cfg_tx
+
+
+
+static /*HDR*/
+void err_msg( PCPS_DEV *pdev, const char *msg )
+{
+ printf( "The clock device %s %s.\n", _pcps_type_name( pdev ), msg );
+
+} // err_msg
+
+
+
+static /*HDR*/
+void set_new_icode_rx( char *s )
+{
+ int idx = atoi( s );
+
+ if ( idx >= N_ICODE_RX )
+ {
+ printf( "** IRIG RX code index %i is out of range (0..%i).\n",
+ idx, N_ICODE_RX - 1 );
+ cfg_err = 1;
+ return;
+ }
+
+ if ( _is_supported( idx, irig_rx_info.supp_codes ) )
+ {
+ irig_rx_info.settings.icode = idx;
+ changed_cfg_rx = 1;
+ }
+ else
+ {
+ printf( "** IRIG RX code \"%s\" not supported by this device.\n",
+ icode_rx_names[idx] );
+ cfg_err = 1;
+ }
+
+} // set_new_icode_rx
+
+
+
+static /*HDR*/
+void set_new_ref_offs( char *s )
+{
+ int new_ref_offs_h;
+
+ new_ref_offs_h = atoi( s );
+
+ if ( abs( new_ref_offs_h ) > max_ref_offs_h )
+ {
+ printf( "** New IRIG time offset %ih exceeds range (%+ih..%+ih).\n",
+ new_ref_offs_h, -max_ref_offs_h, max_ref_offs_h );
+ cfg_err = 1;
+ }
+ else
+ {
+ ref_offs = new_ref_offs_h * MINS_PER_HOUR;
+ changed_cfg_rx = 1;
+ }
+
+} // set_new_ref_offs
+
+
+
+static /*HDR*/
+void set_new_str_utc( char *s )
+{
+ int this_cfg_err;
+
+ if ( !( opt_info.supp_flags & MBG_OPT_FLAG_STR_UTC ) )
+ return; // not supported
+
+
+ this_cfg_err = 0;
+
+ if ( strcmp( s, "1" ) == 0 )
+ opt_info.settings.flags |= MBG_OPT_FLAG_STR_UTC;
+ else
+ if ( strcmp( s, "0" ) == 0 )
+ opt_info.settings.flags &= ~MBG_OPT_FLAG_STR_UTC;
+ else
+ this_cfg_err = 1;
+
+ if ( this_cfg_err )
+ cfg_err = 1;
+ else
+ changed_cfg_rx = 1;
+
+} // set_new_str_utc
+
+
+
+static /*HDR*/
+void set_new_icode_tx( char *s )
+{
+ int idx = atoi( s );
+
+ if ( idx >= N_ICODE_TX )
+ {
+ printf( "** IRIG TX code index %i is out of range (0..%i).\n",
+ idx, N_ICODE_TX - 1 );
+ cfg_err = 1;
+ return;
+ }
+
+ if ( _is_supported( idx, irig_tx_info.supp_codes ) )
+ {
+ irig_tx_info.settings.icode = idx;
+ changed_cfg_tx = 1;
+ }
+ else
+ {
+ printf( "** IRIG TX code \"%s\" not supported by this device.\n",
+ icode_tx_names[idx] );
+ cfg_err = 1;
+ }
+
+} // set_new_icode_tx
+
+
+
+static /*HDR*/
+void set_new_irig_tx_local( char *s )
+{
+ int this_cfg_err = 0;
+
+ if ( strcmp( s, "1" ) == 0 )
+ irig_tx_info.settings.flags |= IFLAGS_TX_GEN_LOCAL_TIME;
+ else
+ if ( strcmp( s, "0" ) == 0 )
+ irig_tx_info.settings.flags &= ~IFLAGS_TX_GEN_LOCAL_TIME;
+ else
+ this_cfg_err = 1;
+
+ if ( this_cfg_err )
+ cfg_err = 1;
+ else
+ changed_cfg_tx = 1;
+
+} // set_new_irig_tx_local
+
+
+
+static /*HDR*/
+void set_new_tfom_flag( char *s, IRIG_SETTINGS *p, int *changed_flag )
+{
+ if ( !(_idx_bit( p->icode ) & MSK_ICODE_TX_HAS_TFOM ) )
+ return; // not supported
+
+
+ if ( strcmp( s, "1" ) == 0 )
+ p->flags |= IFLAGS_DISABLE_TFOM;
+ else
+ if ( strcmp( s, "0" ) == 0 )
+ p->flags &= ~IFLAGS_DISABLE_TFOM;
+ else
+ cfg_err = 1;
+
+ *changed_flag = 1;
+
+} // set_new_tfom_flag
+
+
+
+static /*HDR*/
+int chk_dev_rx( const PCPS_DEV *pdev )
+{
+ if ( !_pcps_is_irig_rx( pdev ) )
+ {
+ printf( "** This device is no IRIG receiver.\n" );
+ cfg_err = 1;
+ return 0;
+ }
+
+ return 1;
+
+} // chk_dev_rx
+
+
+
+static /*HDR*/
+int chk_dev_tx( const PCPS_DEV *pdev )
+{
+ if ( !_pcps_has_irig_tx( pdev ) )
+ {
+ printf( "** This device has no IRIG transmitter.\n" );
+ cfg_err = 1;
+ return 0;
+ }
+
+ return 1;
+
+} // chk_dev_tx
+
+
+
+static /*HDR*/
+void check_cmd_line( int argc, char *argv[], const PCPS_DEV *pdev )
+{
+ int i;
+
+ for ( i = 1; i < argc; i++ )
+ {
+ if ( strcmp( argv[i], "-?" ) == 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-h" ) == 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( strcmp( argv[i], "--help" ) == 0 )
+ {
+ must_print_usage = 1;
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-r" ) == 0 ) // IRIG RX code frame
+ {
+ if ( ++i < argc )
+ if ( chk_dev_rx( pdev ) )
+ set_new_icode_rx( argv[i] );
+
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-o" ) == 0 ) // IRIG time offset from UTC
+ {
+ if ( ++i < argc )
+ if ( chk_dev_rx( pdev ) )
+ set_new_ref_offs( argv[i] );
+
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-u" ) == 0 ) // Option flag: serial output always UTC
+ {
+ if ( ++i < argc )
+ if ( chk_dev_rx( pdev ) )
+ set_new_str_utc( argv[i] );
+
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-t" ) == 0 ) // IRIG TX code frame
+ {
+ if ( ++i < argc )
+ if ( chk_dev_tx( pdev ) )
+ set_new_icode_tx( argv[i] );
+
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-l" ) == 0 ) // Option flag: transmit local time, not UTC
+ {
+ if ( ++i < argc )
+ if ( chk_dev_tx( pdev ) )
+ set_new_irig_tx_local( argv[i] );
+
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-s" ) == 0 ) // Option flag: send TFOM as always "sync"
+ {
+ if ( ++i < argc )
+ if ( chk_dev_tx( pdev ) )
+ set_new_tfom_flag( argv[i], &irig_tx_info.settings, &changed_cfg_tx );
+
+ continue;
+ }
+
+ if ( strcmp( argv[i], "-i" ) == 0 ) // Option flag: ignore incoming TFOM flag, alway sync
+ {
+ if ( ++i < argc )
+ if ( chk_dev_rx( pdev ) )
+ set_new_tfom_flag( argv[i], &irig_rx_info.settings, &changed_cfg_rx );
+
+ continue;
+ }
+
+ }
+
+} // check_cmd_line
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ const char *frame_fmt = " %4i %s, %s\n";
+ int i;
+
+ printf(
+ "Usage: %s [-h]|[option] [option] ...\n"
+ "\n",
+ pname
+ );
+
+ printf(
+ " -h or --help prints this info\n"
+ "\n"
+ );
+
+
+ printf(
+ "Options supported by IRIG receivers:\n"
+ "\n"
+ );
+
+ printf(
+ " -r code specifies the IRIG receiver code format, where \"code\" \n"
+ " can be one a number according to the table below:\n"
+ );
+
+ for ( i = 0; i < N_ICODE_RX; i++ )
+ printf( frame_fmt, i, icode_rx_names[i], icode_rx_descr[i] );
+
+ printf( "\n" );
+
+ printf(
+ " -o offs specifies the IRIG input time offset from UTC, in hours,\n"
+ " where \"offs\" can be a value in the range %+i..%+i\n"
+ "\n",
+ -max_ref_offs_h, max_ref_offs_h
+ );
+
+ printf(
+ " -u flag determines whether the time string sent via the\n"
+ " board's serial output contains always UTC time\n"
+ " or the same time as received from the IRIG input\n"
+ " signal. \"flag\" can be \"1\" for always UTC,\n"
+ " or \"0\" for IRIG time.\n"
+ "\n"
+ );
+
+
+ printf(
+ "Options supported by IRIG transmitters:\n"
+ "\n"
+ );
+
+ printf(
+ " -t code specifies the IRIG transmitter code format, where \"code\" \n"
+ " can be one a number according to the table below:\n"
+ );
+
+ for ( i = 0; i < N_ICODE_TX; i++ )
+ printf( frame_fmt, i, icode_tx_names[i], icode_tx_descr[i] );
+
+ printf( "\n" );
+
+ printf(
+ " -l flag determines whether IRIG output shall contain local\n"
+ " time, or UTC. \"flag\" must be \"1\" for local time,\n"
+ " or \"0\" for UTC.\n"
+ "\n"
+ );
+
+ printf(
+ " -s flag If \"flag\" is set to \"1\" then the TFOM qualifier in the\n"
+ " IRIG output is always set to \"synchronized\". If it is \"0\" \n"
+ " then the qualifier reflects the current status of the input signal.\n"
+ " Please note that most IRIG codes do not support a TFOM qualifier.\n"
+ "\n"
+ );
+
+
+ printf(
+ "If no parameters are given the program reports the current settings.\n"
+ "Please note that not all IRIG codes must be supported by all devices.\n"
+ );
+
+} // usage
+
+
+
+static /*HDR*/
+void help_info( void )
+{
+ printf( "\nFor help type \"%s -h\"\n", pname );
+
+} // help_info
+
+
+
+static /*HDR*/
+int do_mbgirigcfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ const char *no_irig = "is not an IRIG code receiver";
+ PCPS_DEV dev = { { 0 } };
+ int exit_code = 0;
+ int rc = 0;
+
+ {
+ // if success, read the current IRIG configuration
+ if ( rc == MBG_SUCCESS )
+ rc = get_cfg( dh, &dev );
+ }
+
+
+// check_cmd_line( argc, argv, &dev );
+
+
+ if ( cfg_err )
+ {
+ help_info();
+ exit_code = 1;
+ goto done;
+ }
+
+
+ // At this point we shall either report or modify the current
+ // configuration. If there has been an error accessing the
+ // device, or the device is not an IRIG receiver, then we must
+ // print a message.
+
+ if ( dh == MBG_INVALID_DEV_HANDLE )
+ {
+ printf( "** Error opening the device.\n" );
+ exit_code = 3;
+ goto done;
+ }
+
+ if ( rc != MBG_SUCCESS )
+ {
+ exit_code = 3;
+ goto done;
+ }
+
+ if ( !_pcps_has_irig( &dev ) )
+ {
+ err_msg( &dev, no_irig );
+ exit_code = 2;
+ goto done;
+ }
+
+
+ if ( changed_cfg_rx || changed_cfg_tx )
+ {
+
+ if ( changed_cfg_rx )
+ print_cfg_rx( info_new, msg_rx );
+
+ if ( changed_cfg_tx )
+ print_cfg_tx( info_new, msg_tx );
+
+ rc = save_cfg( dh, &dev );
+
+ if ( mbg_ioctl_err( rc, "save IRIG configuration" ) )
+ exit_code = 3;
+ }
+ else
+ {
+ if ( _pcps_is_irig_rx( &dev ) )
+ print_cfg_rx( info_curr, msg_rx );
+
+ if ( _pcps_has_irig_tx( &dev ) )
+ print_cfg_tx( info_curr, msg_tx );
+
+ help_info();
+ }
+
+done:
+ printf( "\n" );
+
+ if ( dh != MBG_INVALID_DEV_HANDLE )
+ mbg_close_device( &dh );
+
+ return exit_code;
+
+} // do_mbgirigcfg
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ check_cmd_line( argc, argv, NULL );
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ //##+++++++++++ rc = mbg_check_devices( argc, argv, optind, do_mbgirigcfg );
+ rc = mbg_check_devices( argc, argv, 0, do_mbgirigcfg );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h b/src/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h
new file mode 100755
index 0000000..9efef59
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h
@@ -0,0 +1,49 @@
+
+/**************************************************************************
+ *
+ * $Id: mbg_bsd.h 1.1.1.1 2011/02/04 14:44:33 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * OS dependend definitions/redefinitions for *BSD.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbg_bsd.h $
+ * Revision 1.1.1.1 2011/02/04 14:44:33 martin
+ * Revision 1.1 2011/01/26 16:09:33 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBG_BSD_H
+#define _MBG_BSD_H
+
+
+/* Other headers to be included */
+
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+
+
+#ifdef _MBG_BSD
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+// definitions for clock() support in kernel drivers
+// extern unsigned long volatile jiffies; //##++ this is just a workaround to build without errors
+// #define clock() jiffies
+
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _MBG_BSD_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h b/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h
new file mode 100755
index 0000000..f032234
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h
@@ -0,0 +1,64 @@
+
+/**************************************************************************
+ *
+ * $Id: pci_bsd.h 1.1 2011/01/26 16:09:33 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions to enable usage of Meinberg PCI function calls
+ * with *BSD.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pci_bsd.h $
+ * Revision 1.1 2011/01/26 16:09:33 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _PCI_BSD_H
+#define _PCI_BSD_H
+
+
+/* Other headers to be included */
+
+#include <pcidefs.h>
+
+#include <mbg_bsd.h>
+//##++ #include <linux/pci.h>
+
+
+#ifdef _PCI_BSD
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+//##++ update comment
+// The pcibios_..() calls use below are not supported by
+// recent 2.6.x kernels. However, those kernels should use
+// the PNP PCI interface anyway, whereas the functions below
+// are only used by non-PNP environments.
+
+#define _mbg_pci_find_bios( _p1, _p2, _p3 ) \
+ ( pcibios_present() ? PCI_SUCCESS : PCI_NO_SUCCESS )
+
+#define _mbg_pci_find_device( _did, _vid, _ix, _pbn, _pdfn ) \
+ pcibios_find_device( (_vid), (_did), (_ix), (_pbn), (_pdfn) )
+
+#define _mbg_pci_read_cfg_byte pcibios_read_config_byte
+#define _mbg_pci_read_cfg_word pcibios_read_config_word
+#define _mbg_pci_read_cfg_dword pcibios_read_config_dword
+
+#define _mbg_pci_write_cfg_byte pcibios_write_config_byte
+#define _mbg_pci_write_cfg_word pcibios_write_config_word
+#define _mbg_pci_write_cfg_dword pcibios_write_config_dword
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _PCI_BSD_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c
new file mode 100755
index 0000000..a1b14d1
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c
@@ -0,0 +1,82 @@
+
+/**************************************************************************
+ *
+ * $Id: rsrc_bsd.c 1.1.1.1 2011/02/07 15:28:32 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Interface functions for the Linux resource manager.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: rsrc_bsd.c $
+ * Revision 1.1.1.1 2011/02/07 15:28:32 martin
+ * Removed obsolete code; more cleanup required.
+ * Revision 1.1 2011/01/26 16:09:33 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#define _RSRC_BSD
+ #include <rsrc_bsd.h>
+#undef _RSRC_BSD
+
+
+// extern const char *pcps_driver_name;
+
+
+#if 1 //##++ ||defined( KERNEL_VERSION ) && ( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 0 ) )
+
+ // check_region(), request_region(), and release_region() used in 2.2.x and
+ // maybe early 2.4.x kernels have been replaced by more versatile functions.
+ // Additionally, there have been defined some macros with the names
+ // of the old functions, but calling the new functions. Those macros are still
+ // supported by early 2.6.x kernels, but may not be supported anymore in the future.
+ // So if those macros don't exist then only the old functions can be used and we
+ // use some macros with the new names and call the old functions.
+
+ #if !defined( request_region )
+ #define __check_region( _rsrc, _start, _n ) \
+ check_region( (_start), (_n) )
+
+ #define __request_region( _rsrc, _start, _n, _name ) \
+ request_region( (_start), (_n), (_name) )
+
+ #define __release_region( _rsrc, _start, _n ) \
+ release_region( (_start), (_n) )
+ #endif
+
+#endif
+
+
+
+/*HDR*/
+int rsrc_alloc_ports( ushort port, ushort n, ushort decode_width )
+{
+#if 0 //##++
+ int rc = __check_region( &ioport_resource, port, n );
+
+ if ( rc < 0 )
+ return( rc );
+
+
+ __request_region( &ioport_resource, port, n, pcps_driver_name );
+#endif
+
+ return 0;
+
+} // rsrc_alloc_ports
+
+
+
+/*HDR*/
+void rsrc_dealloc_ports( ushort port, ushort n )
+{
+#if 0 //##++
+ __release_region( &ioport_resource, port, n );
+#endif
+
+} // rsrc_dealloc_ports
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h
new file mode 100755
index 0000000..ba1af48
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h
@@ -0,0 +1,70 @@
+
+/**************************************************************************
+ *
+ * $Id: rsrc_bsd.h 1.1 2011/01/26 16:09:34 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for rsrc_bsd.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: rsrc_bsd.h $
+ * Revision 1.1 2011/01/26 16:09:34 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _RSRC_BSD_H
+#define _RSRC_BSD_H
+
+
+/* Other headers to be included */
+
+#include <mbg_bsd.h>
+#include <rsrc.h>
+#include <words.h>
+
+#ifdef _RSRC_BSD
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#define _rsrc_alloc_ports( _ph, _pb, _n, _w ) \
+ rsrc_alloc_ports( _pb, _n, _w )
+
+#define _rsrc_dealloc_ports( _ph, _pb, _n ) \
+ rsrc_dealloc_ports( _pb, _n )
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int rsrc_alloc_ports( ushort port, ushort n, ushort decode_width ) ;
+ void rsrc_dealloc_ports( ushort port, ushort n ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _RSRC_BSD_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h
new file mode 100755
index 0000000..1d68cbe
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h
@@ -0,0 +1,111 @@
+
+/**************************************************************************
+ *
+ * $Id: amccdefs.h 1.2 2007/06/06 10:16:53 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions to be used with AMCC PCI interface chips.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: amccdefs.h $
+ * Revision 1.2 2007/06/06 10:16:53 martin
+ * Moved some IRQ bit masks here.
+ * Revision 1.1 2000/07/20 09:19:39Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _AMCCDEFS_H
+#define _AMCCDEFS_H
+
+
+/* Other headers to be included */
+
+
+#ifdef _AMCCDEFS
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+// The following operation registers are implemented
+// in the S5933. The registers can be accessed via port
+// I/O to base_addr_0 + offset as defined below:
+
+#define AMCC_OP_REG_OMB1 0x00 // Outgoing Mail Box 1
+#define AMCC_OP_REG_OMB2 0x04 // Outgoing Mail Box 2
+#define AMCC_OP_REG_OMB3 0x08 // Outgoing Mail Box 3
+#define AMCC_OP_REG_OMB4 0x0C // Outgoing Mail Box 4
+#define AMCC_OP_REG_IMB1 0x10 // Incoming Mail Box 1
+#define AMCC_OP_REG_IMB2 0x14 // Incoming Mail Box 2
+#define AMCC_OP_REG_IMB3 0x18 // Incoming Mail Box 3
+#define AMCC_OP_REG_IMB4 0x1C // Incoming Mail Box 4
+#define AMCC_OP_REG_FIFO 0x20 // FIFO Register
+#define AMCC_OP_REG_MWAR 0x24 // Master Write Address Register
+#define AMCC_OP_REG_MWTC 0x28 // Master Write Transfer Count Register
+#define AMCC_OP_REG_MRAR 0x2C // Master Read Address Register
+#define AMCC_OP_REG_MRTC 0x30 // Master Read Transfer Count Register
+#define AMCC_OP_REG_MBEF 0x34 // Mailbox Empty/Full Status
+#define AMCC_OP_REG_INTCSR 0x38 // Interrupt Control/Status Register
+#define AMCC_OP_REG_MCSR 0x3C // Bus Master Control/Status Register
+
+#define AMCC_OP_REG_RANGE_S5933 0x40 // number of operation registers
+
+
+
+// The following operation registers are implemented
+// in the S5920. The registers can be accessed via port
+// I/O to base_addr_0 + offset as defined below:
+
+#define AMCC_OP_REG_OMB 0x0C // Outgoing Mail Box
+#define AMCC_OP_REG_IMB 0x1C // Incoming Mail Box
+#define AMCC_OP_REG_MBEF 0x34 // Mailbox Empty/Full Status
+#define AMCC_OP_REG_INTCSR 0x38 // Interrupt Control/Status Register
+#define AMCC_OP_REG_RCR 0x3C // Reset Control Register
+#define AMCC_OP_REG_PTCR 0x60 // Pass-Thru Configuration Register
+
+#define AMCC_OP_REG_RANGE_S5920 0x64 // number of operation registers
+
+
+
+// The following bit masks are used by the drivers in order to
+// control interrupts on the PCI bus:
+
+#define AMCC_INT_MASK 0x0000FFFFL
+#define AMCC_INT_ENB ( 1L << 12 )
+#define AMCC_INT_FLAG ( 1L << 17 )
+#define AMCC_INT_ACK ( AMCC_INT_ENB | AMCC_INT_FLAG )
+
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _AMCCDEFS_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h b/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h
new file mode 100755
index 0000000..7736135
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h
@@ -0,0 +1,100 @@
+
+/***************************************************************************/
+/* */
+/* File: CNV_WDAY.H $Revision: 1.1 $ */
+/* */
+/* Project: Common C Library */
+/* */
+/* Compiler: Borland C++ and others */
+/* */
+/* Author: M. Burnicki, Meinberg Funkuhren */
+/* */
+/* */
+/* Description: */
+/* This header provides macros which can be used to convert */
+/* day-of-week codes from one convention to another. */
+/* */
+/* The conventions supported yet have been named as describrd below: */
+/* */
+/* name range assignment used with ... */
+/* ---------------------------------------------------------------- */
+/* sun06 0..6 0 = Sunday RTC72421, DOS1.10+, Novell */
+/* sun17 1..7 1 = Sunday RTC146818 */
+/* mon17 1..7 1 = Monday DCF77 */
+/* */
+/***************************************************************************/
+
+
+#ifndef _CNV_WDAY_H
+
+
+/* Other headers to be included */
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _CNV_WDAY
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+/* use the following macros if sure that the source value is in range */
+
+#define _wday_mon17_to_mon06( d ) ( ( d ) - 1 )
+#define _wday_mon06_to_mon17( d ) ( ( d ) + 1 )
+
+#define _wday_mon17_to_sun17( d ) ( ( (d) >= 7 ) ? 1 : ( (d) + 1 ) )
+#define _wday_sun17_to_mon17( d ) ( ( (d) < 2 ) ? 7 : ( (d) - 1 ) )
+
+#define _wday_mon17_to_sun06( d ) ( ( (d) >= 7 ) ? 0 : (d) )
+#define _wday_sun06_to_mon17( d ) ( ( (d) < 1 ) ? 7 : (d) )
+
+#define _wday_sun17_to_sun06( d ) ( (d) - 1 )
+#define _wday_sun06_to_sun17( d ) ( (d) + 1 )
+
+
+/* use the macros below to check for valid ranges */
+
+#define _inrng( d, what, min, lt, max, gt ) ( ( (d) < (min) ) ? (lt) : ( ( (d) > (max) ) ? (gt) : (what) ) )
+ /* _inrng is a local macro which does the boundary check */
+ /* d the day code to be converted */
+ /* what the conversion algorithm if in range */
+ /* min, lt if (d) is below (min), the macro returns (lt) */
+ /* max, gt if (d) is above (max), the macro returns (gt) */
+
+#define _wday_chk_mon17_to_sun17( d ) _inrng( (d), _wday_mon17_to_sun17( (d) ), 1, 7, 7, 6 )
+#define _wday_chk_sun17_to_mon17( d ) _inrng( (d), _wday_sun17_to_mon17( (d) ), 1, 7, 7, 6 )
+
+
+#define _wday_chk_mon17_to_sun06( d ) _inrng( (d), _wday_mon17_to_sun06( (d) ), 1, 1, 7, 0 )
+#define _wday_chk_sun06_to_mon17( d ) _inrng( (d), _wday_sun06_to_mon17( (d) ), 0, 1, 6, 6 )
+
+#define _wday_chk_sun17_to_sun06( d ) _inrng( (d), _wday_sun17_to_sun06( (d) ), 1, 0, 7, 6 )
+#define _wday_chk_sun06_to_sun17( d ) _inrng( (d), _wday_sun06_to_sun17( (d) ), 0, 1, 6, 7 )
+
+
+/* function prototypes: */
+
+/* #include <CNV_WDAY.hdr> not needed yet */
+
+/* End of header body */
+
+
+#undef _ext
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _CNV_WDAY_H
+
+#endif /* _CNV_WDAY_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctry.c b/src/external/bsd/meinberg/dist/mbglib/common/ctry.c
new file mode 100755
index 0000000..ef647d0
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/ctry.c
@@ -0,0 +1,177 @@
+
+/**************************************************************************
+ *
+ * $Id: ctry.c 1.7 2010/07/15 08:26:57 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions providing support for different country settings
+ * and languages.
+ *
+ * Some OS dependent functions may be required which can be found
+ * in the OS dependent modules ctry_xxx.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctry.c $
+ * Revision 1.7 2010/07/15 08:26:57 martin
+ * Added clstr_lng() implemented by stefan returning a translated string
+ * by giving the different strings as function arguments.
+ * Revision 1.6 2007/03/29 12:21:51 martin
+ * New functions lstr_idx() and lstr_array_idx().
+ * Revision 1.1 2010/06/01 07:57:03 philipp
+ * Revision 1.5 2004/10/26 07:39:37Z martin
+ * Use C99 fixed-size definitions where appropriate.
+ * Revision 1.4 2001/09/14 12:02:12 MARTIN
+ * Modified parameters for lstr_lng().
+ * Revision 1.3 2000/11/27 14:09:24 MARTIN
+ * Replaced lstr() by lstr_lng() with takes a language paramter to allow
+ * retrieval of strings for another than the current language.
+ * A new macro _lstr() has been added to ctry.h which calls lstr_lng()
+ * passing the current language.
+ * The functions ctry_fmt_dt() and ctry_fmt_times() and associated
+ * definitions have been moved to a new module ctry_fmt.c/ctry_fmt.h.
+ * Revision 1.2 2000/07/21 10:00:08 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _CTRY
+ #include <ctry.h>
+#undef _CTRY
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+// Return the index of a CLSTR component for a
+// certain language lng
+
+/*HDR*/
+int lstr_idx( CLSTR s, int lng )
+{
+ if ( lng >= N_LNG ) // if lng out of range
+ return 0; // use default index
+
+ // If there are duplicate strings for several languages
+ // then the duplicate strings may be NULL, in which case
+ // the string at index 0 must be used.
+ return s[lng] ? lng : 0;
+
+} // lstr_idx
+
+
+
+// Return the index of a CLSTR component for a
+// certain language lng out of an array of CLSTRs.
+// CLSTR s: the array of CLSTRs
+// int idx: the index of the array element
+// int n_lng: the number of supported languages
+// int lng: the language for which the inex shall be retrieved
+
+/*HDR*/
+int lstr_array_idx( CLSTR s, int idx, int n_lng, int lng )
+{
+ int str_idx = n_lng * idx;
+ return str_idx + lstr_idx( &s[str_idx], lng );
+
+} // lstr_array_idx
+
+
+
+/*HDR*/
+const char *lstr_lng( CLSTR s, int lng )
+{
+ return s[lstr_idx( s, lng)];
+
+} // lstr_lng
+
+
+
+/*HDR*/
+void ctry_setup( CTRY_CODE code )
+{
+ language = LNG_ENGLISH;
+ ctry.code = code;
+
+ switch ( code )
+ {
+ case CTRY_US:
+ ctry.dt_fmt = DT_FMT_MMDDYYYY;
+ ctry.dt_sep = DT_SEP_MINUS;
+ ctry.tm_fmt = TM_FMT_24H;
+ ctry.tm_sep = TM_SEP_COLON;
+ break;
+
+
+ case CTRY_UK:
+ ctry.dt_fmt = DT_FMT_DDMMYYYY;
+ ctry.dt_sep = DT_SEP_SLASH;
+ ctry.tm_fmt = TM_FMT_24H;
+ ctry.tm_sep = TM_SEP_COLON;
+ break;
+
+
+ default:
+ language = LNG_GERMAN;
+ ctry.code = CTRY_GERMANY;
+
+ ctry.dt_fmt = DT_FMT_DDMMYYYY;
+ ctry.dt_sep = DT_SEP_DOT;
+ ctry.tm_fmt = TM_FMT_24H;
+ ctry.tm_sep = TM_SEP_COLON;
+
+ } /* switch */
+
+
+} /* ctry_setup */
+
+
+
+/*HDR*/
+void ctry_next( void )
+{
+ switch ( ctry.code )
+ {
+ case CTRY_GERMANY:
+ ctry_setup( CTRY_US );
+ break;
+
+ case CTRY_US:
+ ctry_setup( CTRY_UK );
+ break;
+
+ default:
+ ctry_setup( CTRY_GERMANY );
+ break;
+
+ } // switch
+
+} // ctry_next
+
+
+
+/*HDR*/
+const char *clstr_lng( int index, ... )
+{
+ const char *ret;
+ const char *default_ret;
+ int i;
+ typedef char *MY_LSTR;
+
+ va_list ap;
+ va_start( ap, index );
+
+ ret = va_arg( ap, MY_LSTR );
+ default_ret = ret;
+
+ for ( i = 1; ( i <= index ) && ( ret != NULL ); i++ )
+ ret = va_arg( ap, MY_LSTR );
+
+ va_end( ap );
+
+ return ret ? ret : default_ret;
+
+} // clstr_lng
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctry.h b/src/external/bsd/meinberg/dist/mbglib/common/ctry.h
new file mode 100755
index 0000000..9c39a28
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/ctry.h
@@ -0,0 +1,233 @@
+
+/**************************************************************************
+ *
+ * $Id: ctry.h 1.11 2010/07/15 08:33:41 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for ctry.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctry.h $
+ * Revision 1.11 2010/07/15 08:33:41 martin
+ * Added some macros implemented by Stefan.
+ * Updated function prototypes.
+ * Revision 1.10 2007/03/29 12:21:10 martin
+ * Updated function prototypes.
+ * Revision 1.1 2010/06/01 07:57:04 philipp
+ * Revision 1.9 2004/10/26 07:38:50Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Updated function prototypes.
+ * Revision 1.8 2004/04/14 08:47:28 martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.7 2002/02/19 09:28:00Z MARTIN
+ * Use new header mbg_tgt.h to check the target environment.
+ * Revision 1.6 2001/09/14 12:04:40 MARTIN
+ * Modified definition for CLSTR.
+ * Updated function prototypes.
+ * Revision 1.5 2001/02/28 15:07:06 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.4 2000/11/27 14:13:27 MARTIN
+ * New types CLSTR, PLSTR, and PCLSTR.
+ * New macro _lstr() calls lstr_lng() for the current language.
+ * Definitions associated with ctry_fmt_dt() and ctry_fmt_times()
+ * have been moved to a new file ctry_fmt.h.
+ * Updated function prototypes.
+ * Revision 1.3 2000/08/17 15:35:02 MARTIN
+ * No init function by default (previously DOS),
+ * Revision 1.2 2000/07/21 09:48:34 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _CTRY_H
+#define _CTRY_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <words.h>
+
+#if defined( MBG_TGT_NETWARE )
+ #include <ctry_nw.h>
+#elif defined( MBG_TGT_OS2 )
+ #include <ctry_os2.h>
+#elif defined( MBG_TGT_WIN32 )
+ // #include <ctry_w32.h>
+#elif defined( MBG_TGT_LINUX )
+ // #include <ctry_lx.h>
+#elif defined( MBG_TGT_DOS )
+ #include <ctry_dos.h>
+#else
+ // nothing to include for C166 etc.
+#endif
+
+#include <use_pack.h>
+
+
+#ifdef _CTRY
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// the definitions below are used to support different languages:
+typedef uint8_t LANGUAGE;
+typedef uint16_t CTRY_CODE;
+
+// codes used with LANGUAGE:
+#if !defined LNG_DEFINED
+ enum
+ {
+ LNG_ENGLISH,
+ LNG_GERMAN,
+ N_LNG
+ };
+
+ #define LNG_DEFINED
+#endif
+
+// the type below is used to declare string variables
+// for several languages
+typedef char *LSTR[N_LNG]; // array of strings
+typedef char **PLSTR; // pointer to array
+
+// same as above, but const
+typedef const char * const CLSTR[N_LNG]; // array of strings
+typedef const char * const *PCLSTR; // pointer to array
+
+
+// the definitions below are used to handle date and time
+// formats used by different countries:
+typedef struct
+{
+ CTRY_CODE code;
+
+ uint8_t dt_fmt; // (codes defined below)
+ uint8_t tm_fmt; // (codes defined below)
+ char dt_sep; // (valid chars defined below)
+ char tm_sep; // (valid chars defined below)
+} CTRY;
+
+
+// codes used with CTRY.code:
+#define CTRY_US 1
+#define CTRY_UK 44
+#define CTRY_GERMANY 49
+
+
+#ifndef CTRY_DEFINED
+
+ #define CTRY_DEFINED
+
+ // codes used with CTRY.dt_fmt:
+ enum
+ {
+ DT_FMT_DDMMYYYY,
+ DT_FMT_MMDDYYYY,
+ DT_FMT_YYYYMMDD,
+ N_DT_FMT
+ };
+
+ // codes used with CTRY.tm_fmt:
+ enum
+ {
+ TM_FMT_24H,
+ // TM_FMT_12H, // not yet supported
+ N_TM_FMT
+ };
+
+
+ // codes used with CTRY.dt_sep:
+ #define DT_SEP_DOT '.'
+ #define DT_SEP_MINUS '-'
+ #define DT_SEP_SLASH '/'
+
+ // a zero-terminated list of valid dt_sep characters
+ #define DT_SEP_LIST { DT_SEP_DOT, DT_SEP_MINUS, DT_SEP_SLASH, 0 }
+
+
+ // codes used with CTRY.tm_sep:
+ #define TM_SEP_COLON ':'
+ #define TM_SEP_DOT '.'
+
+ // a zero-terminated list of valid tm_sep characters
+ #define TM_SEP_LIST { TM_SEP_COLON, TM_SEP_DOT, 0 }
+
+#endif // CTRY_DEFINED
+
+
+extern LANGUAGE language;
+extern CTRY ctry;
+
+
+#define _ctry_init() \
+ ctry_setup( ctry_get_code() )
+
+
+#define _next_language() \
+{ \
+ if ( ++language >= N_LNG ) \
+ language = 0; \
+ \
+} // next_language
+
+
+// macro to call lstr_lng with the current language
+#define _lstr( _s ) lstr_lng( (_s), language )
+
+// macro to call clstr_lng with the current language, and a set of strings
+#define _clstr( _s ) clstr_lng( language, _s )
+
+// macros used in wxWidgets projects
+#if defined( __WXWINDOWS__ )
+ #define _wx_lstr( _s ) wxString::From8BitData( lstr_lng( (_s), language ) )
+ #define _wx_clstr( _s ) wxString::From8BitData( clstr_lng( language, _s ) )
+#endif
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int lstr_idx( CLSTR s, int lng ) ;
+ int lstr_array_idx( CLSTR s, int idx, int n_lng, int lng ) ;
+ const char *lstr_lng( CLSTR s, int lng ) ;
+ void ctry_setup( CTRY_CODE code ) ;
+ void ctry_next( void ) ;
+ const char *clstr_lng( int index, ... ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+
+#endif /* _CTRY_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c
new file mode 100755
index 0000000..4d35644
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c
@@ -0,0 +1,184 @@
+
+/**************************************************************************
+ *
+ * $Id: ctrydttm.c 1.5 2008/11/24 16:15:46 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions converting dates and time into strings depending on
+ * language/country settings.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctrydttm.c $
+ * Revision 1.5 2008/11/24 16:15:46 martin
+ * Don't use sprintf() without format string.
+ * Revision 1.4 2000/11/27 10:06:27 MARTIN
+ * Renamed local variable wday_str to lstrs_wday.
+ * If macro USER_LSTR_WDAY is defined, lstrs_wday can be declared
+ * externally to override the defaults.
+ * Revision 1.3 2000/09/14 15:13:25 MARTIN
+ * Renamed sprint_short_ctry_dt() to sprint_ctry_dt_short() to match
+ * other naming conventions.
+ * Revision 1.2 2000/07/21 11:53:42 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _CTRYDTTM
+ #include <ctrydttm.h>
+#undef _CTRYDTTM
+
+#include <ctry.h>
+
+#include <stdio.h>
+
+
+#ifndef DAYS_PER_WEEK
+ #define DAYS_PER_WEEK 7
+#endif
+
+#ifdef USER_LSTRS_WDAY
+ extern const char *lstrs_wday[N_LNG][DAYS_PER_WEEK];
+#else
+ static const char *lstrs_wday[N_LNG][DAYS_PER_WEEK] =
+ {
+ { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" },
+ { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" }
+ };
+#endif
+
+extern CTRY ctry;
+extern LANGUAGE language;
+
+
+/*HDR*/
+ushort sprint_02u( char *s, uchar uc )
+{
+ return( sprintf( s, "%02u", uc ) );
+
+} // sprint_02u
+
+
+
+/*HDR*/
+ushort sprint_04u( char *s, ushort us )
+{
+ return( sprintf( s, "%04u", us ) );
+
+} // sprint_04u
+
+
+
+/*HDR*/
+ushort sprint_ctry_wday( char *s, uchar wday, ushort language )
+{
+ if ( language >= N_LNG )
+ language = LNG_ENGLISH;
+
+ return( sprintf( s, "%s", ( wday < DAYS_PER_WEEK ) ?
+ lstrs_wday[language][wday] : "--" ) );
+
+} // sprint_ctry_wday
+
+
+
+/*HDR*/
+ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month )
+{
+ uchar tmp_1;
+ uchar tmp_2;
+ ushort n = 0;
+
+
+ switch( ctry.dt_fmt )
+ {
+ case DT_FMT_YYYYMMDD:
+ case DT_FMT_MMDDYYYY:
+ tmp_1 = month;
+ tmp_2 = mday;
+ break;
+
+ default:
+ tmp_1 = mday;
+ tmp_2 = month;
+ break;
+
+ } // switch
+
+ n = sprint_02u( s, tmp_1 );
+ s[n++] = ctry.dt_sep;
+ n += sprint_02u( &s[n], tmp_2 );
+ s[n++] = ctry.dt_sep;
+ s[n] = 0;
+
+ return( n );
+
+} // sprint_ctry_dt_short
+
+
+
+/*HDR*/
+ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year )
+{
+ ushort n = 0;
+
+
+ if ( ctry.dt_fmt == DT_FMT_YYYYMMDD )
+ {
+ n = sprint_04u( s, year );
+ s[n++] = ctry.dt_sep;
+ }
+
+ n += sprint_ctry_dt_short( &s[n], mday, month );
+
+ if ( ctry.dt_fmt == DT_FMT_YYYYMMDD )
+ s[--n] = 0;
+ else
+ n += sprint_04u( &s[n], year );
+
+ return( n );
+
+} // sprint_ctry_dt
+
+
+
+/*HDR*/
+ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute )
+{
+ ushort n = sprint_02u( s, hour );
+ s[n++] = ctry.tm_sep;
+ n += sprint_02u( &s[n], minute );
+
+ return( n );
+
+} // sprint_ctry_tm_short
+
+
+
+/*HDR*/
+ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second )
+{
+ ushort n = sprint_ctry_tm_short( s, hour, minute );
+ s[n++] = ctry.tm_sep;
+ n += sprint_02u( &s[n], second );
+
+ return( n );
+
+} // sprint_ctry_tm
+
+
+
+/*HDR*/
+ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second,
+ long frac, ushort frac_digits )
+{
+ ushort n = sprint_ctry_tm( s, hour, minute, second );
+ s[n++] = '.';
+ n += sprintf( &s[n], "%0*lu", frac_digits, frac );
+
+ return( n );
+
+} // sprint_ctry_tm_long
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h
new file mode 100755
index 0000000..ce613d7
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h
@@ -0,0 +1,74 @@
+
+/**************************************************************************
+ *
+ * $Id: ctrydttm.h 1.3 2000/09/14 15:13:45 MARTIN REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for ctrydttm.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: ctrydttm.h $
+ * Revision 1.3 2000/09/14 15:13:45 MARTIN
+ * Updated function prototypes.
+ * Revision 1.2 2000/07/21 11:50:43 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _CTRYDTTM_H
+#define _CTRYDTTM_H
+
+
+/* Other headers to be included */
+
+#include <ctry.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _CTRYDTTM
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+
+
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ ushort sprint_02u( char *s, uchar uc ) ;
+ ushort sprint_04u( char *s, ushort us ) ;
+ ushort sprint_ctry_wday( char *s, uchar wday, ushort language ) ;
+ ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) ;
+ ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year ) ;
+ ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute ) ;
+ ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second ) ;
+ ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second, long frac, ushort frac_digits ) ;
+
+/* ----- function prototypes end ----- */
+
+/* End of header body */
+
+
+#undef _ext
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _CTRYDTTM_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h
new file mode 100755
index 0000000..80a4e1d
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h
@@ -0,0 +1,4554 @@
+
+/**************************************************************************
+ *
+ * $Id: gpsdefs.h 1.91.1.8 2011/02/23 15:11:23 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * General definitions to be used with Meinberg clocks.
+ * These definitions have initially be used with GPS devices only.
+ * However, more and more Meinberg non-GPS devices also use some of
+ * these definitions.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: gpsdefs.h $
+ * Revision 1.91.1.8 2011/02/23 15:11:23 martin
+ * New PTP_STATE flags bit PTP_FLAG_MSK_IS_UNICAST.
+ * Revision 1.91.1.7 2011/02/23 15:05:54 martin
+ * Made unused PTP_STATE fields num_clients and num_masters reserved.
+ * Revision 1.91.1.6 2011/02/23 14:47:22 martin
+ * Removed trailing whitespace and hard tabs.
+ * Revision 1.91.1.5 2011/02/23 13:17:06 daniel
+ * Revision 1.91.1.4 2011/02/17 14:39:13Z daniel
+ * Account for different PTP roles.
+ * Revision 1.91.1.3 2011/02/15 14:24:53 martin
+ * Revision 1.91.1.2 2011/02/15 11:30:56 martin
+ * New feature GPS_FEAT_PTP_UNICAST.
+ * Revision 1.91.1.1 2011/02/15 10:54:28 daniel
+ * Started to support configuration for PTP unicast.
+ * Revision 1.91 2011/01/31 11:23:56Z martin
+ * Added model type name definitions for GPS180PEX and TCR180PEX.
+ * Introduced synthesizer mode for programmable outputs.
+ * Added IRIG-RX code TXC-101 DTR-6.
+ * Fixed missing comma bugs in DEFAULT_GPS_MODEL_NAMES.
+ * Fixed missing comma bugs in some IRIG string initializers.
+ * Fixed AFNOR notation.
+ * Modified some comments for doxygen.
+ * Revision 1.90 2010/10/15 11:47:53 martin
+ * Added definitions POUT_TIMEBASE_UTC and POUT_SUPP_DCF77_UTC.
+ * Added receiver info feature GPS_FEAT_RAW_IRIG_TIME.
+ * Support IRIG format C37.118.
+ * Added initializers for short IRIG code names.
+ * Cleaned up IRIG definitions and comments.
+ * Revision 1.89 2010/09/06 07:40:02Z martin
+ * Picked up Daniel's definitions for multi GNSS support.
+ * Moved MBG_IRIG_CTRL_BITS, MBG_RAW_IRIG_DATA and related definitions
+ * from pcpsdefs.h here.
+ * Added macros _pcps_tfom_from_irig_ctrl_bits()
+ * and _pcps_tfom_from_raw_irig_data().
+ * Added RI_FEATURES type.
+ * Revision 1.88 2010/04/21 13:47:54 daniel
+ * Added support for new model GLN170.
+ * Revision 1.87 2010/03/10 11:29:37Z martin
+ * Added definitions for GPS180.
+ * Added multiref source 1 PPS plus associated string.
+ * Revision 1.86 2010/02/17 14:16:42 martin
+ * Added definitions for PZF600 and TCR600.
+ * Revision 1.85 2010/02/15 11:34:36 martin
+ * Changed definition of PTP_TABLE::name to const char *.
+ * Added definitions to support new model JJY511.
+ * Revision 1.84 2010/02/01 13:20:50 martin
+ * Support programmable outputs being disabled when sync. is lost.
+ * Revision 1.83 2010/01/28 09:15:50 martin
+ * Added new POUT mode DCF77_M59 and associated definitions.
+ * Revision 1.82 2010/01/07 09:04:55 martin
+ * Added XMR status bit XMRS_BIT_NOT_PHASE_LOCKED.
+ * Revision 1.81 2009/11/09 09:08:24 martin
+ * New TM_GPS status bit TM_INVT.
+ * Added definitions to support VLAN.
+ * Changed DEFAULT_PTP_DELAY_MECH_MASK to include also
+ * PTP_DELAY_MECH_MSK_P2P.
+ * There is now only one type of TCXO supported which matches the former
+ * TCXO HQ, so the default name for TCXO HQ has been changed to TCXO.
+ * TCXO LQ and MQ names are still supported for backward compatibility.
+ * Revision 1.80 2009/09/28 14:55:53 martin
+ * Support IRIG formats G002/G142 and G006/G146.
+ * Modified IRIG format description strings.
+ * Revision 1.79 2009/08/12 14:12:38 daniel
+ * Added definitions to support new model MGR170.
+ * Added definitions and commands to support configuration
+ * of navigation engine (currently supported by u-blox
+ * receivers only).
+ * Renamed simulation values in PTP_SETTINGS to reserved.
+ * Added "UNINITIALIZED" to PTP port state.
+ * Removed obsolete braces in initializer.
+ * Revision 1.78 2009/06/25 15:49:05Z martin
+ * Added macro _nano_time_negative().
+ * Revision 1.77 2009/06/08 19:22:32Z daniel
+ * Added feature GPS_HAS_PTP.
+ * Added preliminary structures and definitions for PTP
+ * configuration and state.
+ * Added IP4_ADDR type.
+ * Added Bitmask IP4_MSK_DHCP.
+ * Added byte swapper macros for LAN and PTP structures.
+ * Moved LAN interface configuration definitions here.
+ * Moved DAC_VAL definition here.
+ * Changed type iof FPGA_INFO::start_addr for non-firmware applications.
+ * Revision 1.76 2009/04/08 08:26:56 daniel
+ * Added feature GPS_FEAT_IRIG_CTRL_BITS.
+ * Revision 1.75 2009/03/19 14:06:39Z martin
+ * Modified string initializer for unknown oscillator type.
+ * Revision 1.74 2009/03/18 13:45:53 daniel
+ * Added missing commas in
+ * MBG_DEBUG_STATUS_STRS initializer.
+ * Adjusted some comments for doxygen parser.
+ * Revision 1.73 2009/03/10 16:55:33Z martin
+ * Support configurable time scales GPS and TAI.
+ * Defined extended TM status type and associated flags.
+ * Added definition TM_MSK_TIME_VALID.
+ * Added some macros to swap endianess of structures.
+ * Revision 1.72 2008/11/28 09:26:21Z daniel
+ * Added definitions to support WWVB511
+ * Revision 1.71 2008/10/31 14:31:44Z martin
+ * Added definitions for TCR170PEX.
+ * Revision 1.70 2008/09/18 11:14:39 martin
+ * Added definitions to support GEN170.
+ * Revision 1.69 2008/09/15 14:16:17 martin
+ * Added more macros to convert the endianess of structures.
+ * Added N_COM_HS to the enumeration of handshake modes.
+ * Added MBG_PS_... codes.
+ * Revision 1.68 2008/08/25 10:51:13 martin
+ * Added definitions for PTP270PEX and FRC511PEX.
+ * Revision 1.67 2008/07/17 08:54:52Z martin
+ * Added macros to convert the endianess of structures.
+ * Added multiref fixed frequency source.
+ * Revision 1.66 2008/05/19 14:49:07 daniel
+ * Renamed s_addr to start_addr in FPGA_INFO.
+ * Revision 1.65 2008/05/19 09:00:01Z martin
+ * Added definitions for GPS162.
+ * Added FPGA_INFO and GPS_HAS_FPGA.
+ * Added FPGA_START_INFO and associated definitions.
+ * Added new XMRS status XMRS_..._NOT_SETTLED.
+ * Added initializer XMULTI_REF_STATUS_INVALID.
+ * Revision 1.64 2008/01/17 11:50:33Z daniel
+ * Made IGNORE_LOCK bit maskable.
+ * Revision 1.63 2008/01/17 11:42:09Z daniel
+ * Made comments compatible for Doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.62 2007/11/15 13:23:33Z martin
+ * Decide whether other Meinberg headers are to be included depending on whether
+ * CLOCK_MEINBERG is defined (as with NTP) or not. Previous versions checked
+ * for "PACKAGE" which is also defined by the Borland C++ build environment, though.
+ * Revision 1.61 2007/11/13 13:28:54 daniel
+ * Added definitions to support GPS170PEX.
+ * Revision 1.60 2007/09/13 12:37:35Z martin
+ * Modified and added initializers for TZDL.
+ * Added multiref source PTP over E1.
+ * Added codes for MSF511 and GRC170 devices.
+ * Modified XMULTI_REF_SETTINGS and XMULTI_REF_STATUS structures.
+ * Avoid inclusion of other Meinberg headers in non-Meinberg projects.
+ * Added device classification macros _mbg_rcvr_is_...().
+ * Modified feature name string initializer for non-GPS devices.
+ * Updated some comments.
+ * Removed some obsolete comments.
+ * Revision 1.59 2007/07/19 07:41:56Z martin
+ * Added symbol MBG_REF_OFFS_NOT_CFGD.
+ * Revision 1.58 2007/05/21 15:46:44Z martin
+ * Fixed a typo.
+ * Revision 1.57 2007/03/29 12:20:43 martin
+ * Fixed some TZDL initializers.
+ * Revision 1.56 2007/02/14 14:17:10Z andre
+ * bug fixed in mask XMRS_MSK_NO_CONN
+ * Revision 1.55 2007/02/06 16:23:18Z martin
+ * Added definitions for AM511.
+ * Made SVNO unsigned.
+ * Added support for OPT_SETTINGS.
+ * Added XMULTI_REF_... definitions.
+ * Added string initializer DEFAULT_FREQ_RANGES.
+ * Revision 1.54 2007/01/04 11:39:39Z martin
+ * Added definitions for TCR511.
+ * Added definition GPS_FEAT_5_MHZ.
+ * Updated some comments related to duplicate features/options
+ * IGNORE_LOCK and EMU_SYNC.
+ * Revision 1.53 2006/12/13 09:31:49 martin
+ * Added feature flag for ignore_lock.
+ * Revision 1.52 2006/12/12 15:47:18 martin
+ * Added MBG_DEBUG_STATUS type and associated definitions.
+ * Added definition GPS_HAS_REF_OFFS.
+ * Moved PCPS_REF_OFFS and associated definitions from pcpsdefs.h here
+ * and renamed them to MBG_REF_OFFS, etc.
+ * Revision 1.51 2006/10/23 15:31:27 martin
+ * Added definitions for GPS170.
+ * Added definitions for new multi_ref sources IRIG, NTP, and PTP.
+ * Added some definitions useful when editing synth frequency.
+ * Revision 1.50 2006/08/25 09:29:28Z martin
+ * Added structure NANO_TIME.
+ * Revision 1.49 2006/08/09 07:06:42Z martin
+ * New TM_GPS status flag TM_EXT_SYNC.
+ * Revision 1.48 2006/08/08 12:51:20Z martin
+ * Added definitions for IRIG codes B006/B126 and B007/B127.
+ * Revision 1.47 2006/07/06 08:41:45Z martin
+ * Added definition of MEINBERG_MAGIC.
+ * Revision 1.46 2006/06/21 14:08:53Z martin
+ * Added masks of IRIG codes which contain time zone information.
+ * Revision 1.45 2006/06/15 12:13:32Z martin
+ * Added MULTI_REF_STATUS and associated flags.
+ * Added ROM_CSUM, RCV_TIMEOUT, and IGNORE_LOCK types.
+ * Revision 1.44 2006/05/18 09:34:41Z martin
+ * Added definitions for POUT max. pulse_len and max timeout.
+ * Changed comment for POUT_SETTINGS::timeout:
+ * Units are minutes, not seconds.
+ * Added definition for MAX_POUT_TIME_STR_PORTS.
+ * Added definitions for POUT mode 10MHz.
+ * Added hint strings for POUT modes.
+ * Added definitions for PZF511.
+ * Revision 1.43 2006/01/24 07:53:29Z martin
+ * New TM_GPS status flag TM_HOLDOVER.
+ * Revision 1.42 2005/11/24 14:53:22Z martin
+ * Added definitions for manchester encoded DC IRIG frames.
+ * Added POUT_TIMESTR and related definitions.
+ * Revision 1.41 2005/11/03 15:06:59Z martin
+ * Added definitions to support GPS170PCI.
+ * Revision 1.40 2005/10/28 08:58:29Z martin
+ * Added definitions for OCXO_DHQ.
+ * Revision 1.39 2005/09/08 14:06:00Z martin
+ * Added definition SYNTH_PHASE_SYNC_LIMIT.
+ * Revision 1.38 2005/08/18 10:27:35 andre
+ * added definitions for GPS164,
+ * added POUT_TIMECODE,
+ * struct SCU_STAT changed,
+ * ulong flags changed into two byte clk_info and ushort flags
+ * Revision 1.37 2005/05/02 14:44:55Z martin
+ * Added structure SYNTH_STATE and associated definitions.
+ * Revision 1.36 2005/03/29 12:44:07Z martin
+ * New RECEIVER_INFO::flags code: GPS_IRIG_FO_IN
+ * Revision 1.35 2004/12/09 14:04:38Z martin
+ * Changed max synth freq from 12 MHz to 10 MHz.
+ * Revision 1.34 2004/11/23 16:20:09Z martin
+ * Added bit definitions for the existing TTM status bit masks.
+ * Revision 1.33 2004/11/09 12:39:59Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Added model code and name for TCR167PCI.
+ * New type GPS_CMD.
+ * Defined type BVAR_STAT and associated flags.
+ * Revision 1.32 2004/09/20 12:46:25 andre
+ * Added structures and definitions for SCU board.
+ * Revision 1.31 2004/07/08 08:30:36Z martin
+ * Added feature GPS_FEAT_RCV_TIMEOUT.
+ * Revision 1.30 2004/06/21 13:38:42 martin
+ * New flag MBG_OPT_BIT_EMU_SYNC/MBG_OPT_FLAG_EMU_SYNC
+ * lets the receicer emulate/pretend to be always synchronized.
+ * Revision 1.30 2004/06/21 13:35:46Z martin
+ * Revision 1.29 2004/06/16 12:47:53Z martin
+ * Moved OPT_SETTINGS related definitions from pcpsdefs.h
+ * here and renamed symbols from PCPS_.. to to MBG_...
+ * Revision 1.28 2004/03/26 10:37:00Z martin
+ * Added definitions to support multiple ref sources.
+ * Added definitions OSC_DAC_RANGE, OSC_DAC_BIAS.
+ * Revision 1.27 2004/03/08 14:06:45Z martin
+ * New model code and name for GPS169PCI.
+ * Existing feature GPS_FEAT_IRIG has been
+ * renamed to GPS_FEAT_IRIG_TX.
+ * Added feature GPS_FEAT_IRIG_RX.
+ * Added IPv4 LAN interface feature flags.
+ * Renamed IFLAGS_IGNORE_TFOM to IFLAGS_DISABLE_TFOM.
+ * Revision 1.26 2003/12/05 12:28:20Z martin
+ * Added some codes used with IRIG cfg.
+ * Revision 1.25 2003/10/29 16:18:14Z martin
+ * Added 7N2 to DEFAULT_GPS_FRAMINGS_GP2021.
+ * Revision 1.24 2003/09/30 08:49:48Z martin
+ * New flag TM_LS_ANN_NEG which is set in addition to
+ * TM_LS_ANN if next leap second is negative.
+ * Revision 1.23 2003/08/26 14:32:33Z martin
+ * Added some initializers for commonly used
+ * TZDL configurations.
+ * Revision 1.22 2003/04/25 10:18:11 martin
+ * Fixed typo inside an IRIG name string initializer.
+ * Revision 1.21 2003/04/15 09:18:48 martin
+ * New typedef ANT_CABLE_LEN.
+ * Revision 1.20 2003/04/03 11:03:44Z martin
+ * Extended definitions for IRIG support.
+ * Revision 1.19 2003/01/31 13:38:20 MARTIN
+ * Modified type of RECEIVER_INFO.fixed_freq field.
+ * Revision 1.18 2002/10/28 09:24:07 MARTIN
+ * Added/renamed some POUT related symbols.
+ * Revision 1.17 2002/09/05 10:58:39 MARTIN
+ * Renamed some symbols related to programmable outputs.
+ * Revision 1.16 2002/08/29 08:04:47 martin
+ * Renamed structure POUT_PROG to POUT_SETTINGS.
+ * New structures POUT_SETTINGS_IDX, POUT_INFO,
+ * POUT_INFO_IDX and associated definitions.
+ * Updated some comments.
+ * Revision 1.15 2002/07/17 07:39:39Z Andre
+ * comma added in definition DEFAULT_GPS_OSC_NAMES
+ * Revision 1.14 2002/06/27 12:17:29Z MARTIN
+ * Added new oscillator code TCXO_MQ.
+ * Added initializer for oscillator names.
+ * Added initializer for oscillator list ordered by quality.
+ * Revision 1.13 2002/05/08 08:16:03 MARTIN
+ * Added GPS_OSC_CFG_SUPP for RECEIVER_INFO::flags.
+ * Fixed some comments.
+ * Revision 1.12 2002/03/14 13:45:56 MARTIN
+ * Changed type CSUM from short to ushort.
+ * Revision 1.11 2002/03/01 12:29:30 Andre
+ * Added GPS_MODEL_GPS161 and GPS_MODEL_NAME_GPS161.
+ * Revision 1.10 2002/02/25 08:02:33Z MARTIN
+ * Added array of chars to union IDENT.
+ * Revision 1.9 2002/01/29 15:21:46 MARTIN
+ * Added new field "reserved" to struct SW_REV to fix C166 data
+ * alignment/structure size. Converted structure IDENT to a union.
+ * The changes above should not affect existing monitoring programs.
+ * New status flag TM_ANT_SHORT.
+ * New structure RECEIVER_INFO and associated definitions to
+ * enhance control from monitoring programs.
+ * New structures PORT_INFO, STR_TYPE_INFO, and associated
+ * definitions to simplify and unify configuration from external programs.
+ * New structures IRIG_INFO and POUT_PROG_IDX to configure an
+ * optional IRIG interface and programmable pulse outputs.
+ * Modified some comments.
+ * Revision 1.8 2001/03/30 11:44:11 MARTIN
+ * Control alignment of structures from new file use_pack.h.
+ * Defined initializers with valid baud rate and framing parameters.
+ * Modified some comments.
+ * Revision 1.7 2001/03/01 08:09:22 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.6 2000/07/21 14:04:33 MARTIN
+ * Added som #if directives to protect structures against being multiply
+ * defined.
+ * Modified some comments.
+ * Comments using characters for +/- and degree now include ASCII
+ * characters only.
+ *
+ **************************************************************************/
+
+#ifndef _GPSDEFS_H
+#define _GPSDEFS_H
+
+
+/* Other headers to be included */
+
+#if defined( HAVE_CONFIG_H )
+ // this is mainly to simplify usage in non-Meinberg projects
+ #include <config.h>
+#endif
+
+// CLOCK_MEINBERG is defined in NTP's config.h if configured
+// to support Meinberg clocks.
+#if !defined( CLOCK_MEINBERG )
+ // avoid having to use these headers in non-Meinberg projects
+ #include <words.h>
+ #include <use_pack.h>
+#endif
+
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+/* Start of header body */
+
+/* "magic" number */
+#define MEINBERG_MAGIC 0x6AAC
+
+#define MIN_SVNO 1 /* min. SV number */
+#define MAX_SVNO 32 /* max. SV number */
+#define N_SVNO ( MAX_SVNO - MIN_SVNO + 1) /* number of possibly active SVs */
+
+
+#define GPS_ID_STR_LEN 16
+#define GPS_ID_STR_SIZE ( GPS_ID_STR_LEN + 1 )
+
+#define GPS_EPLD_STR_LEN 8
+#define GPS_EPLD_STR_SIZE ( GPS_EPLD_STR_LEN + 1 )
+
+
+#define DEFAULT_GPS_TICKS_PER_SEC 10000000L /* system time base */
+
+#if !defined( GPS_TICKS_PER_SEC )
+ /*
+ * The actual ticks per seconds may vary for different
+ * GPS receiver models. If this is the case, the receiver
+ * model support the RECEIVER_INFO structure which contains
+ * the actual value.
+ */
+ #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC
+#endif
+
+
+typedef uint16_t SVNO; /* the number of a SV */
+typedef uint16_t HEALTH; /* a SV's health code */
+typedef uint16_t CFG; /* a SV's configuration code */
+typedef uint16_t IOD; /* Issue-Of-Data code */
+
+
+/* the type of various checksums */
+
+#ifndef _CSUM_DEFINED
+ typedef uint16_t CSUM;
+ #define _CSUM_DEFINED
+
+ #define _mbg_swab_csum( _p ) _mbg_swab16( _p )
+#endif
+
+
+/**
+ * @brief The type of a GPS command code
+ *
+ * These command codes can be passed via
+ * @ref gps_cmds_serial "serial port" (see @file gpsserio.h), or
+ * @ref gps_cmds_bus "system bus" (see @file pcpsdefs.h).
+ */
+typedef uint16_t GPS_CMD;
+
+#define _mbg_swab_gps_cmd( _p ) _mbg_swab16( _p )
+
+
+/**
+ * @brief Software revision information
+ *
+ * Contains a software revision code, plus an optional
+ * identifier for a customized version.
+ */
+typedef struct
+{
+ uint16_t code; /**< Version number, e.g. 0x0120 means v1.20 */
+ char name[GPS_ID_STR_SIZE]; /**< Optional string identifying a customized version */
+ uint8_t reserved; /**< Reserved field to yield even structure size */
+} SW_REV;
+
+#define _mbg_swab_sw_rev( _p ) \
+{ \
+ _mbg_swab16( &(_p)->code ); \
+}
+
+
+
+/**
+ * @defgroup bvar_stat BVAR_STAT status of buffered GPS data
+ *
+ * Status word, associated bit numbers and bit masks indicating
+ * whether certain data from the GPS satellites are
+ * available and valid.
+ *
+ * These bits defined are set in ::BVAR_STAT if the corresponding
+ * parameters are NOT valid and complete.
+ *
+ * @{ */
+
+/**
+ * @brief Status flags of battery buffered data received
+ * from GPS satellites.
+ *
+ * All '0' means OK, single bits set to '1' indicate
+ * the associated type of GPS data is not available.
+ */
+typedef uint16_t BVAR_STAT;
+
+#define _mbg_swab_bvar_stat( _p ) _mbg_swab16( (_p) )
+
+
+/** @brief Enumeration of bits used with BVAR_STAT */
+enum
+{
+ BVAR_BIT_CFGH_INVALID,
+ BVAR_BIT_ALM_NOT_COMPLETE,
+ BVAR_BIT_UTC_INVALID,
+ BVAR_BIT_IONO_INVALID,
+ BVAR_BIT_RCVR_POS_INVALID,
+ N_BVAR_BIT /**< @brief number of defined ::BVAR_STAT bits */
+};
+
+#define BVAR_CFGH_INVALID ( 1UL << BVAR_BIT_CFGH_INVALID ) /**< @brief ::CFGH not valid*/
+#define BVAR_ALM_NOT_COMPLETE ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ) /**< @brief ::ALM not complete */
+#define BVAR_UTC_INVALID ( 1UL << BVAR_BIT_UTC_INVALID ) /**< @brief UTC data not valid */
+#define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) /**< @brief IONO data not valid */
+#define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) /**< @brief ::POS not valid */
+
+#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) /**< @brief Bit mask for all defined bits */
+
+/** @} */
+
+
+
+/**
+ A structure used to hold a fixed frequency value.
+ frequ[kHz] = khz_val * 10^range
+*/
+
+typedef struct
+{
+ uint16_t khz_val; /* the base frequency in [kHz] */
+ int16_t range; /* an optional base 10 exponent */
+} FIXED_FREQ_INFO;
+
+#define _mbg_swab_fixed_freq_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->khz_val ); \
+ _mbg_swab16( &(_p)->range ); \
+}
+
+
+typedef uint32_t RI_FEATURES; // type of RECEIVER_INFO::features field
+
+
+/*
+ * The following code defines features and properties
+ * of the various GPS receivers. Older GPS receivers
+ * may require a recent firmvare version to support
+ * this, or may not support this at all.
+ */
+
+/**
+ * The structure is ordered in a way that all fields
+ * except chars or arrays of chars are word-aligned.
+ */
+typedef struct
+{
+ uint16_t model_code; /**< identifier for receiver model */
+ SW_REV sw_rev; /**< software revision and ID */
+ char model_name[GPS_ID_STR_SIZE]; /**< ASCIIZ, name of receiver model */
+ char sernum[GPS_ID_STR_SIZE]; /**< ASCIIZ, serial number */
+ char epld_name[GPS_EPLD_STR_SIZE]; /**< ASCIIZ, file name of EPLD image */
+ uint8_t n_channels; /**< number of sats to be tracked simultaneously */
+ uint32_t ticks_per_sec; /**< resolution of fractions of seconds */
+ RI_FEATURES features; /**< optional features, see below */
+ FIXED_FREQ_INFO fixed_freq; /**< optional non-standard fixed frequency */
+ uint8_t osc_type; /**< type of installed oscillator, see below */
+ uint8_t osc_flags; /**< oscillator flags, see below */
+ uint8_t n_ucaps; /**< number of user time capture inputs */
+ uint8_t n_com_ports; /**< number of on-board serial ports */
+ uint8_t n_str_type; /**< max num of string types supported by any port */
+ uint8_t n_prg_out; /**< number of programmable pulse outputs */
+ uint16_t flags; /**< additional information, see below */
+} RECEIVER_INFO;
+
+#define _mbg_swab_receiver_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->model_code ); \
+ _mbg_swab_sw_rev( &(_p)->sw_rev ); \
+ _mbg_swab16( &(_p)->ticks_per_sec ); \
+ _mbg_swab32( &(_p)->features ); \
+ _mbg_swab_fixed_freq_info( &(_p)->fixed_freq ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+/**
+ * Valid codes for RECEIVER_INFO.model_code:
+ */
+enum
+{
+ GPS_MODEL_UNKNOWN,
+ GPS_MODEL_GPS166,
+ GPS_MODEL_GPS167,
+ GPS_MODEL_GPS167SV,
+ GPS_MODEL_GPS167PC,
+ GPS_MODEL_GPS167PCI,
+ GPS_MODEL_GPS163,
+ GPS_MODEL_GPS168PCI,
+ GPS_MODEL_GPS161,
+ GPS_MODEL_GPS169PCI,
+ GPS_MODEL_TCR167PCI,
+ GPS_MODEL_GPS164,
+ GPS_MODEL_GPS170PCI,
+ GPS_MODEL_PZF511,
+ GPS_MODEL_GPS170,
+ GPS_MODEL_TCR511,
+ GPS_MODEL_AM511,
+ GPS_MODEL_MSF511,
+ GPS_MODEL_GRC170,
+ GPS_MODEL_GPS170PEX,
+ GPS_MODEL_GPS162,
+ GPS_MODEL_PTP270PEX,
+ GPS_MODEL_FRC511PEX,
+ GPS_MODEL_GEN170,
+ GPS_MODEL_TCR170PEX,
+ GPS_MODEL_WWVB511,
+ GPS_MODEL_MGR170,
+ GPS_MODEL_JJY511,
+ GPS_MODEL_PZF600,
+ GPS_MODEL_TCR600,
+ GPS_MODEL_GPS180,
+ GPS_MODEL_GLN170,
+ GPS_MODEL_GPS180PEX,
+ GPS_MODEL_TCR180PEX,
+ N_GPS_MODEL
+ /* If new model codes are added then care must be taken
+ * to update the associated string initializers below
+ * accordingly, and to check whether the classification macros
+ * also cover the new model names. */
+};
+
+
+
+
+/*
+ * String initializers for each of the GPS
+ * receiver models enum'ed above:
+ */
+#define GPS_MODEL_NAME_UNKNOWN "(unknown)"
+#define GPS_MODEL_NAME_GPS166 "GPS166"
+#define GPS_MODEL_NAME_GPS167 "GPS167"
+#define GPS_MODEL_NAME_GPS167SV "GPS167SV"
+#define GPS_MODEL_NAME_GPS167PC "GPS167PC"
+#define GPS_MODEL_NAME_GPS167PCI "GPS167PCI"
+#define GPS_MODEL_NAME_GPS163 "GPS163"
+#define GPS_MODEL_NAME_GPS168PCI "GPS168PCI"
+#define GPS_MODEL_NAME_GPS161 "GPS161"
+#define GPS_MODEL_NAME_GPS169PCI "GPS169PCI"
+#define GPS_MODEL_NAME_TCR167PCI "TCR167PCI"
+#define GPS_MODEL_NAME_GPS164 "GPS164"
+#define GPS_MODEL_NAME_GPS170PCI "GPS170PCI"
+#define GPS_MODEL_NAME_PZF511 "PZF511"
+#define GPS_MODEL_NAME_GPS170 "GPS170"
+#define GPS_MODEL_NAME_TCR511 "TCR511"
+#define GPS_MODEL_NAME_AM511 "AM511"
+#define GPS_MODEL_NAME_MSF511 "MSF511"
+#define GPS_MODEL_NAME_GRC170 "GRC170"
+#define GPS_MODEL_NAME_GPS170PEX "GPS170PEX"
+#define GPS_MODEL_NAME_GPS162 "GPS162"
+#define GPS_MODEL_NAME_PTP270PEX "PTP270PEX"
+#define GPS_MODEL_NAME_FRC511PEX "FRC511PEX"
+#define GPS_MODEL_NAME_GEN170 "GEN170"
+#define GPS_MODEL_NAME_TCR170PEX "TCR170PEX"
+#define GPS_MODEL_NAME_WWVB511 "WWVB511"
+#define GPS_MODEL_NAME_MGR170 "MGR170"
+#define GPS_MODEL_NAME_JJY511 "JJY511"
+#define GPS_MODEL_NAME_PZF600 "PZF600"
+#define GPS_MODEL_NAME_TCR600 "TCR600"
+#define GPS_MODEL_NAME_GPS180 "GPS180"
+#define GPS_MODEL_NAME_GLN170 "GLN170"
+#define GPS_MODEL_NAME_GPS180PEX "GPS180PEX"
+#define GPS_MODEL_NAME_TCR180PEX "TCR180PEX"
+
+
+/*
+ * The definition below can be used to initialize
+ * an array of N_GPS_MODEL type name strings.
+ * Including the trailing 0, each name must not
+ * exceed GPS_ID_STR_SIZE chars.
+ */
+#define DEFAULT_GPS_MODEL_NAMES \
+{ \
+ GPS_MODEL_NAME_UNKNOWN, \
+ GPS_MODEL_NAME_GPS166, \
+ GPS_MODEL_NAME_GPS167, \
+ GPS_MODEL_NAME_GPS167SV, \
+ GPS_MODEL_NAME_GPS167PC, \
+ GPS_MODEL_NAME_GPS167PCI, \
+ GPS_MODEL_NAME_GPS163, \
+ GPS_MODEL_NAME_GPS168PCI, \
+ GPS_MODEL_NAME_GPS161, \
+ GPS_MODEL_NAME_GPS169PCI, \
+ GPS_MODEL_NAME_TCR167PCI, \
+ GPS_MODEL_NAME_GPS164, \
+ GPS_MODEL_NAME_GPS170PCI, \
+ GPS_MODEL_NAME_PZF511, \
+ GPS_MODEL_NAME_GPS170, \
+ GPS_MODEL_NAME_TCR511, \
+ GPS_MODEL_NAME_AM511, \
+ GPS_MODEL_NAME_MSF511, \
+ GPS_MODEL_NAME_GRC170, \
+ GPS_MODEL_NAME_GPS170PEX, \
+ GPS_MODEL_NAME_GPS162, \
+ GPS_MODEL_NAME_PTP270PEX, \
+ GPS_MODEL_NAME_FRC511PEX, \
+ GPS_MODEL_NAME_GEN170, \
+ GPS_MODEL_NAME_TCR170PEX, \
+ GPS_MODEL_NAME_WWVB511, \
+ GPS_MODEL_NAME_MGR170, \
+ GPS_MODEL_NAME_JJY511, \
+ GPS_MODEL_NAME_PZF600, \
+ GPS_MODEL_NAME_TCR600, \
+ GPS_MODEL_NAME_GPS180, \
+ GPS_MODEL_NAME_GLN170, \
+ GPS_MODEL_NAME_GPS180PEX, \
+ GPS_MODEL_NAME_TCR180PEX \
+}
+
+
+/*
+ * The macros below can be used to classify a receiver,
+ * e.g. depending on the time source and/or depending on
+ * whether it's a plug-in card or an external device.
+ */
+
+#define _mbg_rcvr_is_plug_in( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "PC" ) || \
+ ( strstr( (_p_ri)->model_name, "PEX" ) )
+
+#define _mbg_rcvr_is_gps( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "GPS" ) || \
+ ( strstr( (_p_ri)->model_name, "MGR" ) )
+
+#define _mbg_rcvr_is_mobile_gps( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "MGR" ) )
+
+#define _mbg_rcvr_is_gps_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_gps( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_irig( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "TCR" ) )
+
+#define _mbg_rcvr_is_irig_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_irig( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_dcf77_am( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "AM" ) )
+
+#define _mbg_rcvr_is_dcf77_am_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_dcf77_am( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_dcf77_pzf( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "PZF" ) )
+
+#define _mbg_rcvr_is_dcf77_pzf_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_dcf77_pzf( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_any_dcf77( _p_ri ) \
+ ( _mbg_rcvr_is_dcf77_am( _p_ri ) || \
+ _mbg_rcvr_is_dcf77_pzf( _p_ri ) )
+
+#define _mbg_rcvr_is_any_dcf77_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_any_dcf77( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_msf( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "MSF" ) )
+
+#define _mbg_rcvr_is_jjy( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "JJY" ) )
+
+#define _mbg_rcvr_is_msf_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_msf( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_glonass( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "GRC" ) || \
+ ( strstr( (_p_ri)->model_name, "GLN" ) )
+
+#define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_glonass( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+#define _mbg_rcvr_is_wwvb( _p_ri ) \
+ ( strstr( (_p_ri)->model_name, "WWVB" ) )
+
+#define _mbg_rcvr_is_wwvb_plug_in( _p_ri ) \
+ ( _mbg_rcvr_is_wwvb( _p_ri ) && \
+ _mbg_rcvr_is_plug_in( _p_ri ) )
+
+
+/**
+ * The classification codes for oscillators below
+ * are used with RECEIVER_INFO.osc_type. New codes
+ * must be appended to the enumeration, so the sequence
+ * of codes does NOT reflect the order of quality:
+ */
+enum
+{
+ GPS_OSC_UNKNOWN,
+ GPS_OSC_TCXO_LQ,
+ GPS_OSC_TCXO_HQ,
+ GPS_OSC_OCXO_LQ,
+ GPS_OSC_OCXO_MQ,
+ GPS_OSC_OCXO_HQ,
+ GPS_OSC_OCXO_XHQ,
+ GPS_OSC_RUBIDIUM,
+ GPS_OSC_TCXO_MQ,
+ GPS_OSC_OCXO_DHQ,
+ N_GPS_OSC
+};
+
+
+/*
+ * The sequence and number of oscillator names
+ * listed below must correspond to the enumeration
+ * above:
+ */
+#define DEFAULT_GPS_OSC_NAMES \
+{ \
+ "[unknown]", \
+ "TCXO LQ", \
+ "TCXO", \
+ "OCXO LQ", \
+ "OCXO MQ", \
+ "OCXO HQ", \
+ "OCXO XHQ", \
+ "RUBIDIUM", \
+ "TCXO MQ", \
+ "OCXO DHQ" \
+}
+
+
+/*
+ * The initializer below can be used to initialize
+ * an array (e.g. "int osc_quality_idx[N_GPS_OSC]")
+ * which allows to display the oscillator types
+ * ordered by quality:
+ */
+#define DEFAULT_GPS_OSC_QUALITY_IDX \
+{ \
+ GPS_OSC_UNKNOWN, \
+ GPS_OSC_TCXO_LQ, \
+ GPS_OSC_TCXO_MQ, \
+ GPS_OSC_TCXO_HQ, \
+ GPS_OSC_OCXO_LQ, \
+ GPS_OSC_OCXO_MQ, \
+ GPS_OSC_OCXO_HQ, \
+ GPS_OSC_OCXO_DHQ, \
+ GPS_OSC_OCXO_XHQ, \
+ GPS_OSC_RUBIDIUM \
+}
+
+
+
+/*
+ * Codes to be used with RECEIVER_INFO.osc_flags
+ * are not yet used/required, so they are reserved
+ * for future use.
+ */
+
+
+/**
+ * The codes below enumerate some features which may be
+ * supported by a given clock, or not.
+ */
+enum
+{
+ GPS_FEAT_PPS, /**< has pulse per second output */
+ GPS_FEAT_PPM, /**< has pulse per minute output */
+ GPS_FEAT_SYNTH, /**< has programmable synthesizer output */
+ GPS_FEAT_DCFMARKS, /**< has DCF77 compatible time mark output */
+ GPS_FEAT_IRIG_TX, /**< has on-board IRIG output */
+ GPS_FEAT_IRIG_RX, /**< has on-board IRIG input */
+ GPS_FEAT_LAN_IP4, /**< has LAN IPv4 interface */
+ GPS_FEAT_MULTI_REF, /**< has multiple input sources with priorities */
+ GPS_FEAT_RCV_TIMEOUT, /**< timeout after GPS reception has stopped */
+ GPS_FEAT_IGNORE_LOCK, /**< supports "ignore lock", alternatively */
+ /**< MBG_OPT_BIT_EMU_SYNC may be supported */
+ GPS_FEAT_5_MHZ, /**< output 5 MHz rather than 100 kHz */
+ GPS_FEAT_XMULTI_REF, /**< has extended multiple input source configuration */
+ GPS_FEAT_OPT_SETTINGS, /**< supports MBG_OPT_SETTINGS */
+ GPS_FEAT_TIME_SCALE, /**< supports configurable time scale (UTC, TAI, GPS, ...) */
+ GPS_FEAT_IRIG_CTRL_BITS, /**< supports IRIG control bits */
+ GPS_FEAT_PTP, /**< has PTP support */
+ GPS_FEAT_NAV_ENGINE_SETTINGS, /**< supports navigation engine configuration */
+ GPS_FEAT_RAW_IRIG_DATA, /**< supports reading raw IRIG input data */
+ GPS_FEAT_RAW_IRIG_TIME, /**< supports reading decoded IRIG time */
+ GPS_FEAT_PTP_UNICAST, /**< has PTP Unicast support */
+ N_GPS_FEATURE /**< the number of valid features */
+};
+
+
+#define DEFAULT_GPS_FEATURE_NAMES \
+{ \
+ "Pulse Per Second", \
+ "Pulse Per Minute", \
+ "Programmable Synth.", \
+ "DCF77 Time Marks", \
+ "IRIG Out", \
+ "IRIG In", \
+ "IPv4 LAN Interface", \
+ "Multiple Ref. Sources", \
+ "Receive Timeout", \
+ "Ignore Lock", \
+ "5 MHz Output", \
+ "Ext. Multiple Ref. Src. Cfg.", \
+ "Optional Settings", \
+ "Configurable Time Scale", \
+ "IRIG Control Bits", \
+ "PTP/IEEE1588", \
+ "Nav. Engine Settings", \
+ "Raw IRIG Data", \
+ "Raw IRIG Time", \
+ "PTP/IEEE1588 Unicast" \
+}
+
+
+/*
+ * Bit masks used with RECEIVER_INFO.features
+ * (others are reserved):
+ */
+#define GPS_HAS_PPS ( 1UL << GPS_FEAT_PPS )
+#define GPS_HAS_PPM ( 1UL << GPS_FEAT_PPM )
+#define GPS_HAS_SYNTH ( 1UL << GPS_FEAT_SYNTH )
+#define GPS_HAS_DCFMARKS ( 1UL << GPS_FEAT_DCFMARKS )
+#define GPS_HAS_IRIG_TX ( 1UL << GPS_FEAT_IRIG_TX )
+#define GPS_HAS_IRIG_RX ( 1UL << GPS_FEAT_IRIG_RX )
+#define GPS_HAS_LAN_IP4 ( 1UL << GPS_FEAT_LAN_IP4 )
+#define GPS_HAS_MULTI_REF ( 1UL << GPS_FEAT_MULTI_REF )
+#define GPS_HAS_RCV_TIMEOUT ( 1UL << GPS_FEAT_RCV_TIMEOUT )
+#define GPS_HAS_IGNORE_LOCK ( 1UL << GPS_FEAT_IGNORE_LOCK )
+#define GPS_HAS_5_MHZ ( 1UL << GPS_FEAT_5_MHZ )
+#define GPS_HAS_XMULTI_REF ( 1UL << GPS_FEAT_XMULTI_REF )
+#define GPS_HAS_OPT_SETTINGS ( 1UL << GPS_FEAT_OPT_SETTINGS )
+#define GPS_HAS_TIME_SCALE ( 1UL << GPS_FEAT_TIME_SCALE )
+#define GPS_HAS_IRIG_CTRL_BITS ( 1UL << GPS_FEAT_IRIG_CTRL_BITS )
+#define GPS_HAS_PTP ( 1UL << GPS_FEAT_PTP )
+#define GPS_HAS_NAV_ENGINE_SETTINGS ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS )
+#define GPS_HAS_RAW_IRIG_DATA ( 1UL << GPS_FEAT_RAW_IRIG_DATA )
+#define GPS_HAS_RAW_IRIG_TIME ( 1UL << GPS_FEAT_RAW_IRIG_TIME )
+#define GPS_HAS_PTP_UNICAST ( 1UL << GPS_FEAT_PTP_UNICAST )
+
+#define GPS_HAS_REF_OFFS GPS_HAS_IRIG_RX
+
+
+/*
+ * The features below are supported by default by older
+ * C166 based GPS receivers:
+ */
+#define DEFAULT_GPS_FEATURES_C166 \
+{ \
+ GPS_HAS_PPS | \
+ GPS_HAS_PPM | \
+ GPS_HAS_SYNTH | \
+ GPS_HAS_DCFMARKS \
+}
+
+
+/*
+ * Codes to be used with RECEIVER_INFO::flags:
+ */
+#define GPS_OSC_CFG_SUPP 0x0001 // GPS_OSC_CFG supported
+#define GPS_IRIG_FO_IN 0x0002 // IRIG input via fiber optics
+#define GPS_HAS_FPGA 0x0004 // device provides on-board FPGA
+
+
+/*
+ * If the GPS_HAS_FPGA flag is set in RECEIVER_INFO::flags then the card
+ * provides an FPGA and the following information about the FPGA is available:
+ */
+#define FPGA_NAME_LEN 31 // max name length
+#define FPGA_NAME_SIZE ( FPGA_NAME_LEN + 1 ) // size including trailing 0
+
+#define FPGA_INFO_SIZE 128
+
+typedef union
+{
+ struct
+ {
+ CSUM csum;
+ uint32_t fsize;
+ #if _IS_MBG_FIRMWARE
+ uint32_t start_addr;
+ #else
+ uint8_t *start_addr;
+ #endif
+ char name[FPGA_NAME_SIZE];
+ } hdr;
+
+ char b[FPGA_INFO_SIZE];
+
+} FPGA_INFO;
+
+
+
+/*
+ * The definitions below are used to specify where a FPGA image is located
+ * in the flash memory:
+ */
+typedef struct
+{
+ CSUM csum;
+ uint16_t fpga_start_seg; // Number of the 4k block where an FPGA image is located
+} FPGA_START_INFO;
+
+#define DEFAULT_FPGA_START_SEG 0x60
+
+#define DEFAULT_FPGA_START_INFO \
+{ \
+ 0x1234 + DEFAULT_FPGA_START_SEG, \
+ DEFAULT_FPGA_START_SEG \
+}
+
+
+
+/**
+ Date and time referred to the linear time scale defined by GPS.
+ GPS time is defined by the number of weeks since midnight from
+ January 5, 1980 to January 6, 1980 plus the number of seconds of
+ the current week plus fractions of a second. GPS time differs from
+ UTC because UTC is corrected with leap seconds while GPS time scale
+ is continuous.
+*/
+typedef struct
+{
+ uint16_t wn; /**< the week number since GPS has been installed */
+ uint32_t sec; /**< the second of that week */
+ uint32_t tick; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */
+} T_GPS;
+
+#define _mbg_swab_t_gps( _p ) \
+{ \
+ _mbg_swab16( &(_p)->wn ); \
+ _mbg_swab32( &(_p)->sec ); \
+ _mbg_swab32( &(_p)->tick ); \
+}
+
+
+/**
+ Local date and time computed from GPS time. The current number
+ of leap seconds have to be added to get UTC from GPS time.
+ Additional corrections could have been made according to the
+ time zone/daylight saving parameters (TZDL, see below) defined
+ by the user. The status field can be checked to see which corrections
+ have been applied.
+*/
+typedef struct
+{
+ int16_t year; /**< year number, 0..9999 */
+ int8_t month; /**< month, 1..12 */
+ int8_t mday; /**< day of month, 1..31 */
+ int16_t yday; /**< day of year, 1..366 */
+ int8_t wday; /**< day of week, 0..6 == Sun..Sat */
+ int8_t hour; /**< hours, 0..23 */
+ int8_t min; /**< minutes, 0..59 */
+ int8_t sec; /**< seconds, 0..59 */
+ int32_t frac; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */
+ int32_t offs_from_utc; /**< local time's offset from UTC */
+ uint16_t status; /**< status flags */
+} TM_GPS;
+
+#define _mbg_swab_tm_gps( _p ) \
+{ \
+ _mbg_swab16( &(_p)->year ); \
+ _mbg_swab16( &(_p)->yday ); \
+ _mbg_swab32( &(_p)->frac ); \
+ _mbg_swab32( &(_p)->offs_from_utc ); \
+ _mbg_swab16( &(_p)->status ); \
+}
+
+
+/* status flag bits used with conversion from GPS time to local time */
+
+enum
+{
+ TM_BIT_UTC, /* UTC correction has been made */
+ TM_BIT_LOCAL, /* UTC has been converted to local time */
+ TM_BIT_DL_ANN, /* state of daylight saving is going to change */
+ TM_BIT_DL_ENB, /* daylight saving is enabled */
+ TM_BIT_LS_ANN, /* leap second will be inserted */
+ TM_BIT_LS_ENB, /* current second is leap second */
+ TM_BIT_LS_ANN_NEG, /* set in addition to TM_LS_ANN if leap sec negative */
+ TM_BIT_INVT, /* invalid time, e.g. if RTC battery empty */
+
+ TM_BIT_EXT_SYNC, /* sync'd externally */
+ TM_BIT_HOLDOVER, /* holdover mode after previous sync. */
+ TM_BIT_ANT_SHORT, /* antenna cable short circuited */
+ TM_BIT_NO_WARM, /* OCXO has not warmed up */
+ TM_BIT_ANT_DISCONN, /* antenna currently disconnected */
+ TM_BIT_SYN_FLAG, /* TIME_SYN output is low */
+ TM_BIT_NO_SYNC, /* time sync actually not verified */
+ TM_BIT_NO_POS /* position actually not verified, LOCK LED off */
+};
+
+// Type of an extended TM status which is mainly used by the firmware.
+typedef uint32_t TM_STATUS_EXT; // extended status, mainly used by the firmware
+
+// The lower 16 bits of the TM_STATUS_X type correspond to those defined above,
+// and the upper bits are defined below:
+enum
+{
+ TM_BIT_SCALE_GPS = 16,
+ TM_BIT_SCALE_TAI
+ // the remaining bits are reserved
+};
+
+
+/* bit masks corresponding to the flag bits above */
+
+#define TM_UTC ( 1UL << TM_BIT_UTC )
+#define TM_LOCAL ( 1UL << TM_BIT_LOCAL )
+#define TM_DL_ANN ( 1UL << TM_BIT_DL_ANN )
+#define TM_DL_ENB ( 1UL << TM_BIT_DL_ENB )
+#define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN )
+#define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB )
+#define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG )
+#define TM_INVT ( 1UL << TM_BIT_INVT )
+
+#define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC )
+#define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER )
+#define TM_ANT_SHORT ( 1UL << TM_BIT_ANT_SHORT )
+#define TM_NO_WARM ( 1UL << TM_BIT_NO_WARM )
+#define TM_ANT_DISCONN ( 1UL << TM_BIT_ANT_DISCONN )
+#define TM_SYN_FLAG ( 1UL << TM_BIT_SYN_FLAG )
+#define TM_NO_SYNC ( 1UL << TM_BIT_NO_SYNC )
+#define TM_NO_POS ( 1UL << TM_BIT_NO_POS )
+
+// The following bits are only used with the TM_STATUS_X type:
+#define TM_SCALE_GPS ( 1UL << TM_BIT_SCALE_GPS )
+#define TM_SCALE_TAI ( 1UL << TM_BIT_SCALE_TAI )
+
+#define TM_MSK_TIME_VALID ( TM_UTC | TM_SCALE_GPS | TM_SCALE_TAI )
+
+/**
+ This structure is used to transmit information on date and time
+ */
+typedef struct
+{
+ int16_t channel; /**< -1: the current time; 0, 1: capture 0, 1 */
+ T_GPS t; /**< time in GPS format */
+ TM_GPS tm; /**< that time converted to local time */
+} TTM;
+
+#define _mbg_swab_ttm( _p ) \
+{ \
+ _mbg_swab16( &(_p)->channel ); \
+ _mbg_swab_t_gps( &(_p)->t ); \
+ _mbg_swab_tm_gps( &(_p)->tm ); \
+}
+
+
+
+typedef struct
+{
+ int32_t nano_secs; // [nanoseconds]
+ int32_t secs; // [seconds]
+} NANO_TIME;
+
+#define _mbg_swab_nano_time( _p ) \
+{ \
+ _mbg_swab32( &(_p)->nano_secs ); \
+ _mbg_swab32( &(_p)->secs ); \
+}
+
+// The macro below checks if a NANO_TIME value is negative.
+#define _nano_time_negative( _nt ) \
+ ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) )
+
+
+
+/* Two types of variables used to store a position. Type XYZ is */
+/* used with a position in earth centered, earth fixed (ECEF) */
+/* coordinates whereas type LLA holds such a position converted */
+/* to geographic coordinates as defined by WGS84 (World Geodetic */
+/* System from 1984). */
+
+#ifndef _XYZ_DEFINED
+ /* sequence and number of components of a cartesian position */
+ enum { XP, YP, ZP, N_XYZ };
+
+ /** a type of array holding a cartesian position */
+ typedef double XYZ[N_XYZ]; /**< values are in [m] */
+
+ #define _XYZ_DEFINED
+#endif
+
+#define _mbg_swab_xyz( _p ) _mbg_swab_doubles( _p, N_XYZ )
+
+
+#ifndef _LLA_DEFINED
+ /* sequence and number of components of a geographic position */
+ enum { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */
+
+ /** a type of array holding a geographic position */
+ typedef double LLA[N_LLA]; /**< lon, lat in [rad], alt in [m] */
+
+ #define _LLA_DEFINED
+#endif
+
+#define _mbg_swab_lla( _p ) _mbg_swab_doubles( _p, N_LLA )
+
+
+/**
+ @defgroup group_synth Synthesizer parameters
+
+ Synthesizer frequency is expressed as a
+ four digit decimal number (freq) to be multiplied by 0.1 Hz and an
+ base 10 exponent (range). If the effective frequency is less than
+ 10 kHz its phase is synchronized corresponding to the variable phase.
+ Phase may be in a range from -360 deg to +360 deg with a resolution
+ of 0.1 deg, so the resulting numbers to be stored are in a range of
+ -3600 to +3600.
+
+ Example:<br>
+ Assume the value of freq is 2345 (decimal) and the value of phase is 900.
+ If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg.
+ If range == 1 the synthesizer will generate a 2345 Hz output frequency
+ and so on.
+
+ Limitations:<br>
+ If freq == 0 the synthesizer is disabled. If range == 0 the least
+ significant digit of freq is limited to 0, 3, 5 or 6. The resulting
+ frequency is shown in the examples below:
+ - freq == 1230 --> 123.0 Hz
+ - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz)
+ - freq == 1235 --> 123.5 Hz
+ - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz)
+
+ If range == MAX_RANGE the value of freq must not exceed 1000, so the
+ output frequency is limited to 10 MHz.
+ @{
+*/
+
+#define N_SYNTH_FREQ_DIGIT 4 /**< number of digits to edit */
+#define MAX_SYNTH_FREQ 1000 /**< if range == MAX_SYNTH_RANGE */
+
+#define MIN_SYNTH_RANGE 0
+#define MAX_SYNTH_RANGE 5
+#define N_SYNTH_RANGE ( MAX_SYNTH_RANGE - MIN_SYNTH_RANGE + 1 )
+
+#define N_SYNTH_PHASE_DIGIT 4
+#define MAX_SYNTH_PHASE 3600
+
+
+#define MAX_SYNTH_FREQ_EDIT 9999 /**< max sequence of digits when editing */
+
+/** The maximum frequency that can be configured for the synthesizer */
+#define MAX_SYNTH_FREQ_VAL 10000000UL /**< 10 MHz */
+/* == MAX_SYNTH_FREQ * 10^(MAX_SYNTH_RANGE-1) */
+
+/**
+ The synthesizer phase will only be synchronized if the frequency
+ is below this limit: */
+#define SYNTH_PHASE_SYNC_LIMIT 10000UL /**< 10 kHz */
+
+/**
+ the position of the decimal point if the frequency is
+ printed as 4 digit value */
+#define _synth_dp_pos_from_range( _r ) \
+ ( ( ( N_SYNTH_RANGE - (_r) ) % ( N_SYNTH_FREQ_DIGIT - 1 ) ) + 1 )
+
+/**
+ An initializer for commonly displayed synthesizer frequency units
+ (N_SYNTH_RANGE strings) */
+#define DEFAULT_FREQ_RANGES \
+{ \
+ "Hz", \
+ "kHz", \
+ "kHz", \
+ "kHz", \
+ "MHz", \
+ "MHz", \
+}
+
+
+
+typedef struct
+{
+ int16_t freq; /**< four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz */
+ int16_t range; /**< scale factor for freq; 0..MAX_SYNTH_RANGE */
+ int16_t phase; /**< -MAX_SYNTH_PHASE..+MAX_SYNTH_PHASE; >0 -> pulses later */
+} SYNTH;
+
+#define _mbg_swab_synth( _p ) \
+{ \
+ _mbg_swab16( &(_p)->freq ); \
+ _mbg_swab16( &(_p)->range ); \
+ _mbg_swab16( &(_p)->phase ); \
+}
+
+
+/**
+ The definitions below can be used to query the
+ current synthesizer state.
+ */
+enum
+{
+ SYNTH_DISABLED, /**< disbled by cfg, i.e. freq == 0.0 */
+ SYNTH_OFF, /**< not enabled after power-up */
+ SYNTH_FREE, /**< enabled, but not synchronized */
+ SYNTH_DRIFTING, /**< has initially been sync'd, but now running free */
+ SYNTH_SYNC, /**< fully synchronized */
+ N_SYNTH_STATE /**< the number of known states */
+};
+
+typedef struct
+{
+ uint8_t state; /**< state code as enumerated above */
+ uint8_t flags; /**< reserved, currently always 0 */
+} SYNTH_STATE;
+
+#define _mbg_swab_synth_state( _p ) _nop_macro_fnc()
+
+#define SYNTH_FLAG_PHASE_IGNORED 0x01
+
+/** @} */ // endgroup
+
+/**
+ @defgroup group_tzdl Time zone/daylight saving parameters
+
+ Example: <br>
+ For automatic daylight saving enable/disable in Central Europe,
+ the variables are to be set as shown below: <br>
+ - offs = 3600L one hour from UTC
+ - offs_dl = 3600L one additional hour if daylight saving enabled
+ - tm_on = first Sunday from March 25, 02:00:00h ( year |= DL_AUTO_FLAG )
+ - tm_off = first Sunday from October 25, 03:00:00h ( year |= DL_AUTO_FLAG )
+ - name[0] == "CET " name if daylight saving not enabled
+ - name[1] == "CEST " name if daylight saving is enabled
+ @{
+*/
+
+/** the name of a time zone, 5 characters plus trailing zero */
+typedef char TZ_NAME[6];
+
+typedef struct
+{
+ int32_t offs; /**< offset from UTC to local time [sec] */
+ int32_t offs_dl; /**< additional offset if daylight saving enabled [sec] */
+ TM_GPS tm_on; /**< date/time when daylight saving starts */
+ TM_GPS tm_off; /**< date/time when daylight saving ends */
+ TZ_NAME name[2]; /**< names without and with daylight saving enabled */
+} TZDL;
+
+#define _mbg_swab_tzdl( _p ) \
+{ \
+ _mbg_swab32( &(_p)->offs ); \
+ _mbg_swab32( &(_p)->offs_dl ); \
+ _mbg_swab_tm_gps( &(_p)->tm_on ); \
+ _mbg_swab_tm_gps( &(_p)->tm_off ); \
+}
+
+
+/**
+ If the year in tzdl.tm_on and tzdl.tm_off is or'ed with that constant,
+ the receiver automatically generates daylight saving year by year.
+ */
+#define DL_AUTO_FLAG 0x8000
+
+
+
+// Below there are some initializers for commonly used TZDL configurations:
+
+#define DEFAULT_TZDL_AUTO_YEAR ( 2007 | DL_AUTO_FLAG )
+
+#define DEFAULt_TZDL_OFFS_DL 3600L /**< usually DST is +1 hour */
+
+
+/**
+ The symbol below can be used to initialize both the tm_on
+ and tm_off fields for time zones which do not switch to DST:
+ */
+#define DEFAULT_TZDL_TM_ON_OFF_NO_DST \
+ { DEFAULT_TZDL_AUTO_YEAR, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+
+// Settings used with UTC:
+
+#define TZ_INFO_UTC "UTC (Universal Time, Coordinated)"
+
+#define DEFAULT_TZDL_NAMES_UTC { "UTC ", "UTC " }
+
+#define DEFAULT_TZDL_UTC \
+{ \
+ 0L, /**< offs */ \
+ 0L, /**< offs_dl */ \
+ DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_on */ \
+ DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_off */ \
+ DEFAULT_TZDL_NAMES_UTC /**< name[] */ \
+}
+
+
+/**
+ The symbols below specify beginning and end of DST for
+ Central Europe, as constituted by the European Parliament:
+ */
+
+#define DEFAULT_TZDL_TM_ON_CET_CEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 2, 0, 0, 0L, 0L, 0 }
+
+#define DEFAULT_TZDL_TM_OFF_CET_CEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 }
+
+
+// Settings used with Central European Time:
+
+#define TZ_INFO_CET_CEST_EN "CET/CEST (Central Europe)"
+#define TZ_INFO_CET_CEST_DE "MEZ/MESZ (Mitteleuropa)"
+
+#define DEFAULT_TZDL_NAMES_CET_CEST_EN { "CET ", "CEST " }
+#define DEFAULT_TZDL_NAMES_CET_CEST_DE { "MEZ ", "MESZ " }
+
+#define DEFAULT_TZDL_OFFS_CET 3600L
+
+#define DEFAULT_TZDL_CET_CEST_EN \
+{ \
+ DEFAULT_TZDL_OFFS_CET, /**< offs */ \
+ DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \
+ DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \
+ DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \
+ DEFAULT_TZDL_NAMES_CET_CEST_EN /**< name[] */ \
+}
+
+#define DEFAULT_TZDL_CET_CEST_DE \
+{ \
+ DEFAULT_TZDL_OFFS_CET, /**< offs */ \
+ DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \
+ DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \
+ DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \
+ DEFAULT_TZDL_NAMES_CET_CEST_DE /**< name[] */ \
+}
+
+
+// The symbols below specify beginning and end of DST for
+// Easter Europe, as constituted by the European Parliament:
+
+#define DEFAULT_TZDL_TM_ON_EET_EEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 }
+
+#define DEFAULT_TZDL_TM_OFF_EET_EEST \
+ { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 4, 0, 0, 0L, 0L, 0 }
+
+
+// Settings used with Eastern European Time:
+
+#define TZ_INFO_EET_EEST_EN "EET/EEST (East Europe)"
+#define TZ_INFO_EET_EEST_DE "OEZ/OEST (Osteuropa)"
+
+#define DEFAULT_TZDL_NAMES_EET_EEST_EN { "EET ", "EEST " }
+#define DEFAULT_TZDL_NAMES_EET_EEST_DE { "OEZ ", "OESZ " }
+
+#define DEFAULT_TZDL_OFFS_EET 7200L
+
+#define DEFAULT_TZDL_EET_EEST_EN \
+{ \
+ DEFAULT_TZDL_OFFS_EET, /* offs */ \
+ DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \
+ DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \
+ DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \
+ DEFAULT_TZDL_NAMES_EET_EEST_EN /* name[] */ \
+}
+
+#define DEFAULT_TZDL_EET_EEST_DE \
+{ \
+ DEFAULT_TZDL_OFFS_EET, /* offs */ \
+ DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \
+ DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \
+ DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \
+ DEFAULT_TZDL_NAMES_EET_EEST_DE /* name[] */ \
+}
+
+/** @} */ // endgroup
+
+/**
+ * The structure below reflects the status of the antenna,
+ * the times of last disconnect/reconnect, and the board's
+ * clock offset after the disconnection interval.
+ */
+typedef struct
+{
+ int16_t status; /**< current status of antenna */
+ TM_GPS tm_disconn; /**< time of antenna disconnect */
+ TM_GPS tm_reconn; /**< time of antenna reconnect */
+ int32_t delta_t; /**< clock offs. at reconn. time in #GPS_TICKS_PER_SEC */
+} ANT_INFO;
+
+#define _mbg_swab_ant_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->status ); \
+ _mbg_swab_tm_gps( &(_p)->tm_disconn ); \
+ _mbg_swab_tm_gps( &(_p)->tm_reconn ); \
+ _mbg_swab32( &(_p)->delta_t ); \
+}
+
+
+/**
+ The status field may be set to one of the values below:
+*/
+enum
+{
+ ANT_INVALID, /**< struct not set yet because ant. has not been disconn. */
+ ANT_DISCONN, /**< ant. now disconn., tm_reconn and delta_t not set */
+ ANT_RECONN /**< ant. has been disconn. and reconn., all fields valid */
+};
+
+/* Defines used with ENABLE_FLAGS */
+
+#define EF_OFF 0x00 /**< outputs off until sync'd */
+
+#define EF_SERIAL_BOTH 0x03 /**< both serial ports on */
+#define EF_PULSES_BOTH 0x03 /**< both pulses P_SEC and P_MIN on */
+#define EF_FREQ_ALL 0x07 /**< all fixed freq. outputs on */
+#define EF_SYNTH 0x01 /**< synth. on */
+
+/**
+ The structure holds some flags which let
+ the corresponding outputs be disabled after power-up until
+ the receiver has synchronized (flag == 0x00, the default) or force
+ the outputs to be enabled immediately after power-up. The fixed
+ frequency output is hard-wired to be enabled immediately after
+ power-up, so the code for freq must always be 0x03.
+*/
+typedef struct
+{
+ uint16_t serial; /**< #EF_OFF or #EF_SERIAL_BOTH */
+ uint16_t pulses; /**< #EF_OFF or #EF_PULSES_BOTH */
+ uint16_t freq; /**< always #EF_FREQ_ALL */
+ uint16_t synth; /**< #EF_OFF or #EF_SYNTH */
+} ENABLE_FLAGS;
+
+#define _mbg_swab_enable_flags( _p ) \
+{ \
+ _mbg_swab16( &(_p)->serial ); \
+ _mbg_swab16( &(_p)->pulses ); \
+ _mbg_swab16( &(_p)->freq ); \
+ _mbg_swab16( &(_p)->synth ); \
+}
+
+
+/* A struct used to hold the settings of a serial port: */
+
+#ifndef _COM_HS_DEFINED
+ /* types of handshake */
+ enum { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS };
+ #define _COM_HS_DEFINED
+#endif
+
+#ifndef _COM_PARM_DEFINED
+ typedef int32_t BAUD_RATE;
+
+ /* indices used to identify a parameter in the framing string */
+ enum { F_DBITS, F_PRTY, F_STBITS };
+
+ typedef struct
+ {
+ BAUD_RATE baud_rate; /* e.g. 19200L */
+ char framing[4]; /* e.g. "8N1" */
+ int16_t handshake; /* a numeric value, only HS_NONE supported yet */
+ } COM_PARM;
+
+ #define _COM_PARM_DEFINED
+#endif
+
+#define _mbg_swab_baud_rate( _p ) _mbg_swab32( _p )
+
+#define _mbg_swab_com_parm( _p ) \
+{ \
+ _mbg_swab_baud_rate( &(_p)->baud_rate ); \
+ _mbg_swab16( &(_p)->handshake ); \
+}
+
+
+/*
+ * Indices of any supported baud rates.
+ * Note that not each baud rate must be supported by
+ * any clock model and/or port:
+ */
+enum
+{
+ MBG_BAUD_RATE_300,
+ MBG_BAUD_RATE_600,
+ MBG_BAUD_RATE_1200,
+ MBG_BAUD_RATE_2400,
+ MBG_BAUD_RATE_4800,
+ MBG_BAUD_RATE_9600,
+ MBG_BAUD_RATE_19200,
+ MBG_BAUD_RATE_38400,
+ N_MBG_BAUD_RATES /* the number of supported baud rates */
+};
+
+/*
+ * An initializer for a table of baud rate values.
+ * The values must correspond to the enumeration above.
+ */
+#define MBG_BAUD_RATES \
+{ \
+ 300L, \
+ 600L, \
+ 1200L, \
+ 2400L, \
+ 4800L, \
+ 9600L, \
+ 19200L, \
+ 38400L \
+}
+
+/*
+ * An initializer for a table of baud rate strings.
+ * The values must correspond to the enumeration above.
+ */
+#define MBG_BAUD_STRS \
+{ \
+ "300", \
+ "600", \
+ "1200", \
+ "2400", \
+ "4800", \
+ "9600", \
+ "19200", \
+ "38400" \
+}
+
+/*
+ * The bit masks below can be used to determine which baud rates
+ * are supported by a serial port. This may vary between
+ * different ports of the same radio clock since different
+ * types of UART are used which must not necessarily support
+ * each baud rate:
+ */
+#define MBG_PORT_HAS_300 ( 1UL << MBG_BAUD_RATE_300 )
+#define MBG_PORT_HAS_600 ( 1UL << MBG_BAUD_RATE_600 )
+#define MBG_PORT_HAS_1200 ( 1UL << MBG_BAUD_RATE_1200 )
+#define MBG_PORT_HAS_2400 ( 1UL << MBG_BAUD_RATE_2400 )
+#define MBG_PORT_HAS_4800 ( 1UL << MBG_BAUD_RATE_4800 )
+#define MBG_PORT_HAS_9600 ( 1UL << MBG_BAUD_RATE_9600 )
+#define MBG_PORT_HAS_19200 ( 1UL << MBG_BAUD_RATE_19200 )
+#define MBG_PORT_HAS_38400 ( 1UL << MBG_BAUD_RATE_38400 )
+
+
+/*
+ * Indices of any supported framings.
+ * Note that not each framing must be supported by
+ * any clock model and/or port:
+ */
+enum
+{
+ MBG_FRAMING_7N2,
+ MBG_FRAMING_7E1,
+ MBG_FRAMING_7E2,
+ MBG_FRAMING_8N1,
+ MBG_FRAMING_8N2,
+ MBG_FRAMING_8E1,
+ MBG_FRAMING_7O1,
+ MBG_FRAMING_7O2,
+ MBG_FRAMING_8O1,
+ N_MBG_FRAMINGS /* the number of supported framings */
+};
+
+/*
+ * An initializer for a table of framing strings.
+ * The values must correspond to the enumeration above.
+ */
+#define MBG_FRAMING_STRS \
+{ \
+ "7N2", \
+ "7E1", \
+ "7E2", \
+ "8N1", \
+ "8N2", \
+ "8E1", \
+ "7O1", \
+ "7O2", \
+ "8O1" \
+}
+
+/*
+ * The bit masks below can be used to determine which framings
+ * are supported by a serial port. This may vary between
+ * different ports of the same radio clock since different
+ * types of UART are used which must not necessarily support
+ * each framing type:
+ */
+#define MBG_PORT_HAS_7N2 ( 1UL << MBG_FRAMING_7N2 )
+#define MBG_PORT_HAS_7E1 ( 1UL << MBG_FRAMING_7E1 )
+#define MBG_PORT_HAS_7E2 ( 1UL << MBG_FRAMING_7E2 )
+#define MBG_PORT_HAS_8N1 ( 1UL << MBG_FRAMING_8N1 )
+#define MBG_PORT_HAS_8N2 ( 1UL << MBG_FRAMING_8N2 )
+#define MBG_PORT_HAS_8E1 ( 1UL << MBG_FRAMING_8E1 )
+#define MBG_PORT_HAS_7O1 ( 1UL << MBG_FRAMING_7O1 )
+#define MBG_PORT_HAS_7O2 ( 1UL << MBG_FRAMING_7O2 )
+#define MBG_PORT_HAS_8O1 ( 1UL << MBG_FRAMING_8O1 )
+
+
+
+/*
+ * By default, the baud rates and framings below
+ * are supported by the UARTs integrated into
+ * the C166 microcontroller:
+ */
+#define DEFAULT_GPS_BAUD_RATES_C166 \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 | \
+ MBG_PORT_HAS_19200 \
+)
+
+#define DEFAULT_GPS_FRAMINGS_C166 \
+( \
+ MBG_PORT_HAS_7N2 | \
+ MBG_PORT_HAS_7E1 | \
+ MBG_PORT_HAS_7E2 | \
+ MBG_PORT_HAS_8N1 | \
+ MBG_PORT_HAS_8N2 | \
+ MBG_PORT_HAS_8E1 \
+)
+
+
+/*
+ * By default, the baud rates and framings below
+ * are supported by the UARTs integrated into
+ * the GP2021 chipset:
+ */
+#define DEFAULT_GPS_BAUD_RATES_GP2021 \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 | \
+ MBG_PORT_HAS_19200 \
+)
+
+#define DEFAULT_GPS_FRAMINGS_GP2021 \
+( \
+ MBG_PORT_HAS_7N2 | \
+ MBG_PORT_HAS_7E2 | \
+ MBG_PORT_HAS_8N1 | \
+ MBG_PORT_HAS_8E1 | \
+ MBG_PORT_HAS_8O1 \
+)
+
+
+/*
+ * The structure below is more flexible if different receiver
+ * models have different numbers of serial ports, so the old
+ * structure PORT_PARM will become obsolete.
+ */
+typedef struct
+{
+ COM_PARM parm; /* speed, framing, etc. */
+ uint8_t mode; /* per second, per minute, etc. */
+ uint8_t str_type; /* type of the output string */
+ uint32_t flags; /* reserved for future use, currently 0 */
+} PORT_SETTINGS;
+
+#define _mbg_swab_port_settings( _p ) \
+{ \
+ _mbg_swab_com_parm( &(_p)->parm ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/*
+ * The definitions below can be used to mark specific fields of a
+ * PORT_SETTINGS structure, e.g. when editing build a mask indicating
+ * which of the fields have changed or which are not valid.
+ */
+enum
+{
+ MBG_PS_BIT_BAUD_RATE_OVR_SW, /* Baud rate index exceeds num supp by driver SW */
+ MBG_PS_BIT_BAUD_RATE_OVR_DEV, /* Baud rate index exceeds num supp by device */
+ MBG_PS_BIT_BAUD_RATE, /* Baud rate not supp by given port */
+ MBG_PS_BIT_FRAMING_OVR_SW, /* Framing index exceeds num supp by driver SW */
+ MBG_PS_BIT_FRAMING_OVR_DEV, /* Framing index exceeds num supp by device */
+ MBG_PS_BIT_FRAMING, /* Framing not supp by given port */
+ MBG_PS_BIT_HS_OVR_SW, /* Handshake index exceeds num supp by driver SW */
+ MBG_PS_BIT_HS, /* Handshake mode not supp by given port */
+ MBG_PS_BIT_STR_TYPE_OVR_SW, /* String type index exceeds num supp by driver SW */
+ MBG_PS_BIT_STR_TYPE_OVR_DEV, /* String type index exceeds num supp by device */
+ MBG_PS_BIT_STR_TYPE, /* String type not supp by given port */
+ MBG_PS_BIT_STR_MODE_OVR_SW, /* String mode index exceeds num supp by driver SW */
+ MBG_PS_BIT_STR_MODE_OVR_DEV, /* String mode index exceeds num supp by device */
+ MBG_PS_BIT_STR_MODE, /* String mode not supp by given port and string type */
+ MBG_PS_BIT_FLAGS_OVR_SW, /* Flags not supp by driver SW */
+ MBG_PS_BIT_FLAGS, /* Flags not supp by device */
+ N_MBG_PS_BIT
+};
+
+#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW )
+#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV )
+#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE )
+#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW )
+#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV )
+#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING )
+#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW )
+#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS )
+#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW )
+#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV )
+#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE )
+#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW )
+#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV )
+#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE )
+#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW )
+#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS )
+
+
+
+/*
+ * The structure below adds an index number to the structure
+ * above to allow addressing of several instances:
+ */
+typedef struct
+{
+ uint16_t idx; /* 0..RECEIVER_INFO.n_com_port-1 */
+ PORT_SETTINGS port_settings;
+} PORT_SETTINGS_IDX;
+
+#define _mbg_swab_port_settings_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_port_settings( &(_p)->port_settings ); \
+}
+
+
+/*
+ * The structure below holds the current settings
+ * for a port, plus additional informaton on the
+ * port's capabilities. This can be read by setup
+ * programs to allow setup of supported features
+ * only.
+ */
+typedef struct
+{
+ PORT_SETTINGS port_settings; /* COM port settings as defined above */
+ uint32_t supp_baud_rates; /* bit mask of baud rates supp. by this port */
+ uint32_t supp_framings; /* bit mask of framings supp. by this port */
+ uint32_t supp_str_types; /* bit mask, bit 0 set if str_type[0] supp. */
+ uint32_t reserved; /* reserved for future use, currently 0 */
+ uint32_t flags; /* reserved for future use, currently 0 */
+} PORT_INFO;
+
+#define _mbg_swab_port_info( _p ) \
+{ \
+ _mbg_swab_port_settings( &(_p)->port_settings ); \
+ _mbg_swab32( &(_p)->supp_baud_rates ); \
+ _mbg_swab32( &(_p)->supp_framings ); \
+ _mbg_swab32( &(_p)->supp_str_types ); \
+ _mbg_swab32( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/*
+ * The structure below adds an index number to the structure
+ * above to allow addressing of several instances:
+ */
+typedef struct
+{
+ uint16_t idx; /* 0..RECEIVER_INFO.n_com_port-1 */
+ PORT_INFO port_info;
+} PORT_INFO_IDX;
+
+#define _mbg_swab_port_info_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_port_info( &(_p)->port_info ); \
+}
+
+
+/*
+ * The structure below keeps information for a given
+ * string type, e.g. which modes can be used with that
+ * string type:
+ */
+typedef struct
+{
+ uint32_t supp_modes; /* bit mask of modes supp. with this string type */
+ char long_name[23]; /* long name of the string format */
+ char short_name[11]; /* short name of the string format */
+ uint16_t flags; /* reserved, currently always 0 */
+} STR_TYPE_INFO;
+
+#define _mbg_swab_str_type_info( _p ) \
+{ \
+ _mbg_swab32( &(_p)->supp_modes ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+
+/*
+ * The structure below adds an index number to the structure
+ * above to allow addressing of several instances:
+ */
+typedef struct
+{
+ uint16_t idx; /* 0..RECEIVER_INFO.n_str_type-1 */
+ STR_TYPE_INFO str_type_info;
+} STR_TYPE_INFO_IDX;
+
+#define _mbg_swab_str_type_info_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_str_type_info( &(_p)->str_type_info ); \
+}
+
+
+/*
+ * The codes below define valid modes for time strings,
+ * i.e. the condition when a string is being sent
+ * via the serial port:
+ */
+enum
+{
+ STR_ON_REQ, /* on request only */
+ STR_PER_SEC, /* automatically if second changes */
+ STR_PER_MIN, /* automatically if minute changes */
+ STR_AUTO, /* automatically if required, e.g. on capture event */
+ STR_ON_REQ_SEC, /* if second changes and a request has been received */
+ N_STR_MODE /* the number of valid modes */
+};
+
+
+#define DEFAULT_SHORT_MODE_NAMES \
+{ \
+ "'?'", \
+ "1 sec", \
+ "1 min", \
+ "auto", \
+ "'?' sec" \
+}
+
+
+/*
+ * Default initializers for English mode string names. Initializers
+ * for multi-language strings can be found in pcpslstr.h.
+ */
+#define ENG_MODE_NAME_STR_ON_REQ "on request '?' only"
+#define ENG_MODE_NAME_STR_PER_SEC "per second"
+#define ENG_MODE_NAME_STR_PER_MIN "per minute"
+#define ENG_MODE_NAME_STR_AUTO "automatically"
+#define ENG_MODE_NAME_STR_ON_REQ_SEC "sec after request"
+
+#define DEFAULT_ENG_MODE_NAMES \
+{ \
+ ENG_MODE_NAME_STR_ON_REQ, \
+ ENG_MODE_NAME_STR_PER_SEC, \
+ ENG_MODE_NAME_STR_PER_MIN, \
+ ENG_MODE_NAME_STR_AUTO, \
+ ENG_MODE_NAME_STR_ON_REQ_SEC \
+}
+
+/*
+ * The definitions below are used to set up bit masks
+ * which restrict the modes which can be used with
+ * a given string type:
+ */
+#define MSK_STR_ON_REQ ( 1UL << STR_ON_REQ )
+#define MSK_STR_PER_SEC ( 1UL << STR_PER_SEC )
+#define MSK_STR_PER_MIN ( 1UL << STR_PER_MIN )
+#define MSK_STR_AUTO ( 1UL << STR_AUTO )
+#define MSK_STR_ON_REQ_SEC ( 1UL << STR_ON_REQ_SEC )
+
+
+/*
+ * The modes below are supported by most string types:
+ */
+#define DEFAULT_STR_MODES \
+( \
+ MSK_STR_ON_REQ | \
+ MSK_STR_PER_SEC | \
+ MSK_STR_PER_MIN \
+)
+
+
+/*
+ * The modes below can be used with the capture string:
+ */
+#define DEFAULT_STR_MODES_UCAP \
+( \
+ MSK_STR_ON_REQ | \
+ MSK_STR_AUTO \
+)
+
+
+
+/**
+ * The number of serial ports which were available
+ * with all GPS receiver models:
+ */
+#define DEFAULT_N_COM 2
+
+/*
+ * By default that's also the number of ports
+ * currently available:
+ */
+#ifndef N_COM
+ #define N_COM DEFAULT_N_COM
+#endif
+
+/**
+ * The structure used to store the modes of both serial ports:<br>
+ * <b>(now obsolete)</b>
+ */
+typedef struct
+{
+ COM_PARM com[DEFAULT_N_COM]; /**< COM0 and COM1 settings */
+ uint8_t mode[DEFAULT_N_COM]; /**< COM0 and COM1 output mode */
+} PORT_PARM;
+
+#define _mbg_swab_port_parm( _p ) \
+{ \
+ int i; \
+ for ( i = 0; i < DEFAULT_N_COM; i++ ) \
+ { \
+ _mbg_swab_com_parm( &(_p)->com[i] ); \
+ /* no need to swap mode byte */ \
+ } \
+}
+
+
+/*
+ * The codes below were used with the obsolete
+ * PORT_PARM.mode above. They are defined for
+ * compatibility with older devices only:
+ */
+enum
+{
+ /* STR_ON_REQ, defined above */
+ /* STR_PER_SEC, defined above */
+ /* STR_PER_MIN, defined above */
+ N_STR_MODE_0 = STR_AUTO, /* COM0 and COM1 */
+ STR_UCAP = N_STR_MODE_0,
+ STR_UCAP_REQ,
+ N_STR_MODE_1 /* COM1 only */
+};
+
+
+
+/**
+ @defgroup group_icode IRIG Codes
+
+ The following definitions are used to configure an optional
+ on-board IRIG input or output. Which frame types are supported
+ by a device depends on the device type, and may eventually
+ depend on the device's firmware version.
+
+ All IRIG frames transport the day-of-year number plus the time-of-day,
+ and include a control field segment which can transport user defined
+ information.
+
+ Some newer IRIG frames are compatible with older frame types but support
+ well defined extensions like the year number, local time offset, DST status,
+ etc., in the control fields:
+
+ - Supported IRIG signal code types:
+ - \b A002: 1000 bps, DCLS, time-of-year
+ - \b A003: 1000 bps, DCLS, time-of-year, SBS
+ - \b A132: 1000 bps, 10 kHz carrier, time-of-year
+ - \b A133: 1000 bps, 10 kHz carrier, time-of-year, SBS
+ - \b B002: 100 bps, DCLS, time-of-year
+ - \b B003: 100 bps, DCLS, time-of-year, SBS
+ - \b B122: 100 bps, 1 kHz carrier, time-of-year
+ - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS
+ - \b B006: 100 bps, DCLS, complete date
+ - \b B007: 100 bps, DCLS, complete date, SBS
+ - \b B126: 100 bps, 1 kHz carrier, complete date
+ - \b B127: 100 bps, 1 kHz carrier, complete date, SBS
+ - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions
+ - \b B222: 100 bps, DCLS, manchester encoded, time-of-year
+ - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS
+ - \b G002: 10 kbps, DCLS, time-of-year
+ - \b G142: 10 kbps, 100 kHz carrier, time-of-year
+ - \b G006: 10 kbps, DCLS, complete date
+ - \b G146: 10 kbps, 100 kHz carrier, complete date
+ - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date
+ - <b> AFNOR DC:</b> 100 bps, DCLS, SBS, complete date
+ - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120)
+ - <b> IEEE1344 DC:</b> 100 bps, DCLS, time-of-year, SBS, IEEE1344 extensions (B000)
+ - \b C37.118: like IEEE1344, but UTC offset with reversed sign
+ - \b C37.118 DC: like IEEE1344 DC, but UTC offset with reversed sign
+
+ - time-of-year: day-of-year, hours, minutes, seconds
+ - complete date: time-of-year plus year number
+ - SBS: straight binary seconds, second-of-day
+
+ AFNOR codes are based on the french standard AFNOR NF S87-500
+
+ IEEE1344 codes are defined in IEEE standard 1344-1995. The code frame is compatible
+ with B002/B122 but provides some welldefined extensions in the control field which
+ include a quality indicator (time figure of merit, TFOM), year number, DST and leap
+ second status, and local time offset from UTC.
+
+ C37.118 codes are defined in IEEE standard C37.118-2005 which includes a revised version
+ of the IEEE1344 standard from 1995. These codes provide the same extensions as IEEE1344
+ but unfortunately define the UTC offset with reversed sign.
+
+ <b>ATTENTION:</b> There are 3rd party IRIG devices out there which apply the UTC offset
+ as specified in C37.118, but claim to be compatible with IEEE1344. So if local time is
+ transmitted in the IRIG signal then care must be taken that the UTC offset is evaluated
+ by the IRIG receiver in the same way as output by the IRIG generator. Otherwise the UTC
+ time computed by the receiver may be wrong.
+ @{
+ */
+
+/**
+ * Definitions used with IRIG transmitters which usually output both
+ * the unmodulated and the modulated IRIG signals at the same time: */
+enum
+{
+ ICODE_TX_B002_B122,
+ ICODE_TX_B003_B123,
+ ICODE_TX_A002_A132,
+ ICODE_TX_A003_A133,
+ ICODE_TX_AFNOR,
+ ICODE_TX_IEEE1344,
+ ICODE_TX_B2201344, // DCLS only
+ ICODE_TX_B222, // DCLS only
+ ICODE_TX_B223, // DCLS only
+ ICODE_TX_B006_B126,
+ ICODE_TX_B007_B127,
+ ICODE_TX_G002_G142,
+ ICODE_TX_G006_G146,
+ ICODE_TX_C37118,
+ N_ICODE_TX /**< number of code types */
+};
+
+
+/**
+ * Initializers for format name strings.
+ */
+#define DEFAULT_ICODE_TX_NAMES \
+{ \
+ "B002+B122", \
+ "B003+B123", \
+ "A002+A132", \
+ "A003+A133", \
+ "AFNOR NF S87-500", \
+ "IEEE1344", \
+ "B220(1344) DCLS", \
+ "B222 DCLS", \
+ "B223 DCLS", \
+ "B006+B126", \
+ "B007+B127", \
+ "G002+G142", \
+ "G006+G146", \
+ "C37.118" \
+}
+
+/**
+ * Initializers for short name strings which must not
+ * be longer than 10 printable characters.
+ */
+#define DEFAULT_ICODE_TX_NAMES_SHORT \
+{ \
+ "B002+B122", \
+ "B003+B123", \
+ "A002+A132", \
+ "A003+A133", \
+ "AFNOR NF-S", \
+ "IEEE1344", \
+ "B220/1344", \
+ "B222 DC", \
+ "B223 DC", \
+ "B006+B126", \
+ "B007+B127", \
+ "G002+G142", \
+ "G006+G146", \
+ "C37.118" \
+}
+
+
+/**
+ * Initializers for English format description strings.
+ */
+#define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \
+{ \
+ "100 bps, DCLS or 1 kHz carrier", \
+ "100 bps, DCLS or 1 kHz carrier, SBS", \
+ "1000 bps, DCLS or 10 kHz carrier", \
+ "1000 bps, DCLS or 10 kHz carrier, SBS", \
+ "100 bps, DCLS or 1 kHz carrier, SBS, complete date", \
+ "100 bps, DCLS or 1 kHz carrier, SBS, complete date, time zone info", \
+ "100 bps, Manchester enc., DCLS only, SBS, complete date, time zone info", \
+ "100 bps, Manchester enc., DCLS only", \
+ "100 bps, Manchester enc., DCLS only, SBS", \
+ "100 bps, DCLS or 1 kHz carrier, complete date", \
+ "100 bps, DCLS or 1 kHz carrier, complete date, SBS", \
+ "10 kbps, DCLS or 100 kHz carrier", \
+ "10 kbps, DCLS or 100 kHz carrier, complete date", \
+ "like IEEE1344, but UTC offset with reversed sign" \
+}
+
+/*
+ * The definitions below are used to set up bit masks
+ * which restrict the IRIG formats which are supported
+ * by a given IRIG transmitter device:
+ */
+#define MSK_ICODE_TX_B002_B122 ( 1UL << ICODE_TX_B002_B122 )
+#define MSK_ICODE_TX_B003_B123 ( 1UL << ICODE_TX_B003_B123 )
+#define MSK_ICODE_TX_A002_A132 ( 1UL << ICODE_TX_A002_A132 )
+#define MSK_ICODE_TX_A003_A133 ( 1UL << ICODE_TX_A003_A133 )
+#define MSK_ICODE_TX_AFNOR ( 1UL << ICODE_TX_AFNOR )
+#define MSK_ICODE_TX_IEEE1344 ( 1UL << ICODE_TX_IEEE1344 )
+#define MSK_ICODE_TX_B2201344 ( 1UL << ICODE_TX_B2201344 )
+#define MSK_ICODE_TX_B222 ( 1UL << ICODE_TX_B222 )
+#define MSK_ICODE_TX_B223 ( 1UL << ICODE_TX_B223 )
+#define MSK_ICODE_TX_B006_B126 ( 1UL << ICODE_TX_B006_B126 )
+#define MSK_ICODE_TX_B007_B127 ( 1UL << ICODE_TX_B007_B127 )
+#define MSK_ICODE_TX_G002_G142 ( 1UL << ICODE_TX_G002_G142 )
+#define MSK_ICODE_TX_G006_G146 ( 1UL << ICODE_TX_G006_G146 )
+#define MSK_ICODE_TX_C37118 ( 1UL << ICODE_TX_C37118 )
+
+/**
+ * A mask of IRIG formats with manchester encoded DC output:
+ */
+#define MSK_ICODE_TX_DC_MANCH \
+( \
+ MSK_ICODE_TX_B2201344 | \
+ MSK_ICODE_TX_B222 | \
+ MSK_ICODE_TX_B223 \
+)
+
+/**
+ * A mask of IRIG formats with 1 kHz carrier:
+ */
+#define MSK_ICODE_TX_1KHZ \
+( \
+ MSK_ICODE_TX_B002_B122 | \
+ MSK_ICODE_TX_B003_B123 | \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_B2201344 | \
+ MSK_ICODE_TX_B222 | \
+ MSK_ICODE_TX_B223 | \
+ MSK_ICODE_TX_B006_B126 | \
+ MSK_ICODE_TX_B007_B127 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kHz carrier:
+ */
+#define MSK_ICODE_TX_10KHZ \
+( \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 \
+)
+
+/**
+ * A mask of IRIG formats with 100 kHz carrier:
+ */
+#define MSK_ICODE_TX_100KHZ \
+( \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * A mask of IRIG formats with 100 bps data rate:
+ */
+#define MSK_ICODE_TX_100BPS \
+( \
+ MSK_ICODE_TX_B002_B122 | \
+ MSK_ICODE_TX_B003_B123 | \
+ MSK_ICODE_TX_AFNOR | \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_B006_B126 | \
+ MSK_ICODE_TX_B007_B127 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * A mask of IRIG formats with 1000 bps data rate:
+ */
+#define MSK_ICODE_TX_1000BPS \
+( \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kbps data rate:
+ */
+#define MSK_ICODE_TX_10000BPS \
+( \
+ MSK_ICODE_TX_G002_G142 | \
+ MSK_ICODE_TX_G006_G146 \
+)
+
+/**
+ * A mask of IRIG formats which support TFOM:
+ */
+#define MSK_ICODE_TX_HAS_TFOM \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * A mask of IRIG formats which support time zone information:
+ */
+#define MSK_ICODE_TX_HAS_TZI \
+( \
+ MSK_ICODE_TX_IEEE1344 | \
+ MSK_ICODE_TX_C37118 \
+)
+
+/**
+ * The default mask of IRIG formats supported by
+ * IRIG transmitters:
+ */
+#if !defined( SUPP_MSK_ICODE_TX )
+ #define SUPP_MSK_ICODE_TX \
+ ( \
+ MSK_ICODE_TX_B002_B122 | \
+ MSK_ICODE_TX_B003_B123 | \
+ MSK_ICODE_TX_A002_A132 | \
+ MSK_ICODE_TX_A003_A133 | \
+ MSK_ICODE_TX_AFNOR \
+ )
+#endif
+
+
+
+/**
+ * Definitions used with IRIG receivers which decode
+ * two similar IRIG codes (with or without SBS)
+ * at the same time.
+ */
+enum
+{
+ ICODE_RX_B122_B123, // modulated
+ ICODE_RX_A132_A133, // modulated
+ ICODE_RX_B002_B003, // DCLS
+ ICODE_RX_A002_A003, // DCLS
+ ICODE_RX_AFNOR, // modulated
+ ICODE_RX_AFNOR_DC, // DCLS
+ ICODE_RX_IEEE1344, // modulated
+ ICODE_RX_IEEE1344_DC, // DCLS
+ ICODE_RX_B126_B127, // modulated
+ ICODE_RX_B006_B007, // DCLS
+ ICODE_RX_G142_G146, // modulated
+ ICODE_RX_G002_G006, // DCLS
+ ICODE_RX_C37118, // modulated
+ ICODE_RX_C37118_DC, // DCLS
+ ICODE_RX_TXC_101, // modulated
+ ICODE_RX_TXC_101_DC, // DCLS
+ N_ICODE_RX /* the number of valid signal code types */
+};
+
+/**
+ * Initializers for format name strings.
+ */
+#define DEFAULT_ICODE_RX_NAMES \
+{ \
+ "B122/B123", \
+ "A132/A133", \
+ "B002/B003 (DCLS)", \
+ "A002/A003 (DCLS)", \
+ "AFNOR NF S87-500", \
+ "AFNOR NF S87-500 (DCLS)", \
+ "IEEE1344", \
+ "IEEE1344 (DCLS)", \
+ "B126/B127", \
+ "B006/B007 (DCLS)", \
+ "G142/G146", \
+ "G002/G006 (DCLS)", \
+ "C37.118", \
+ "C37.118 (DCLS)", \
+ "TXC-101 DTR-6", \
+ "TXC-101 DTR-6 (DCLS)" \
+}
+
+/**
+ * Initializers for short name strings which must not
+ * be longer than 11 printable characters.
+ */
+#define DEFAULT_ICODE_RX_NAMES_SHORT \
+{ \
+ "B122/B123", \
+ "A132/A133", \
+ "B002/B003", \
+ "A002/A003", \
+ "AFNOR NF-S", \
+ "AFNOR DC", \
+ "IEEE1344", \
+ "IEEE1344 DC", \
+ "B126/B127", \
+ "B006/B007", \
+ "G142/G146", \
+ "G002/G006", \
+ "C37.118", \
+ "C37.118 DC", \
+ "TXC-101", \
+ "TXC-101 DC" \
+}
+
+
+/**
+ * Initializers for English format description strings.
+ */
+#define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \
+{ \
+ "100 bps, 1 kHz carrier, SBS optionally", \
+ "1000 bps, 10 kHz carrier, SBS optionally", \
+ "100 bps, DCLS, SBS optionally", \
+ "1000 bps, DCLS, SBS optionally", \
+ "100 bps, 1 kHz carrier, SBS, complete date", \
+ "100 bps, DCLS, SBS, complete date", \
+ "100 bps, 1 kHz carrier, SBS, time zone info", \
+ "100 bps, DCLS, SBS, time zone info", \
+ "100 bps, 1 kHz carrier, complete date, SBS optionally", \
+ "100 bps, DCLS, complete date, SBS optionally", \
+ "10 kbps, 100 kHz carrier, complete date optionally", \
+ "10 kbps, DCLS, complete date optionally", \
+ "like IEEE1344, but UTC offset with reversed sign", \
+ "like IEEE1344 DC, but UTC offset with reversed sign", \
+ "code from TV time sync device TXC-101 DTR-6", \
+ "DC code from TV time sync device TXC-101 DTR-6" \
+}
+
+/*
+ * Bit masks corresponding to the enumeration above:
+ */
+#define MSK_ICODE_RX_B122_B123 ( 1UL << ICODE_RX_B122_B123 )
+#define MSK_ICODE_RX_A132_A133 ( 1UL << ICODE_RX_A132_A133 )
+#define MSK_ICODE_RX_B002_B003 ( 1UL << ICODE_RX_B002_B003 )
+#define MSK_ICODE_RX_A002_A003 ( 1UL << ICODE_RX_A002_A003 )
+#define MSK_ICODE_RX_AFNOR ( 1UL << ICODE_RX_AFNOR )
+#define MSK_ICODE_RX_AFNOR_DC ( 1UL << ICODE_RX_AFNOR_DC )
+#define MSK_ICODE_RX_IEEE1344 ( 1UL << ICODE_RX_IEEE1344 )
+#define MSK_ICODE_RX_IEEE1344_DC ( 1UL << ICODE_RX_IEEE1344_DC )
+#define MSK_ICODE_RX_B126_B127 ( 1UL << ICODE_RX_B126_B127 )
+#define MSK_ICODE_RX_B006_B007 ( 1UL << ICODE_RX_B006_B007 )
+#define MSK_ICODE_RX_G142_G146 ( 1UL << ICODE_RX_G142_G146 )
+#define MSK_ICODE_RX_G002_G006 ( 1UL << ICODE_RX_G002_G006 )
+#define MSK_ICODE_RX_C37118 ( 1UL << ICODE_RX_C37118 )
+#define MSK_ICODE_RX_C37118_DC ( 1UL << ICODE_RX_C37118_DC )
+#define MSK_ICODE_RX_TXC_101 ( 1UL << ICODE_RX_TXC_101 )
+#define MSK_ICODE_RX_TXC_101_DC ( 1UL << ICODE_RX_TXC_101_DC )
+
+/**
+ * A mask of IRIG DCLS formats:
+ */
+#define MSK_ICODE_RX_DC \
+( \
+ MSK_ICODE_RX_B002_B003 | \
+ MSK_ICODE_RX_A002_A003 | \
+ MSK_ICODE_RX_AFNOR_DC | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_B006_B007 | \
+ MSK_ICODE_RX_G002_G006 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * A mask of IRIG formats with 1 kHz carrier:
+ */
+#define MSK_ICODE_RX_1KHZ \
+( \
+ MSK_ICODE_RX_B122_B123 | \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_B126_B127 | \
+ MSK_ICODE_RX_C37118 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kHz carrier:
+ */
+#define MSK_ICODE_RX_10KHZ \
+( \
+ MSK_ICODE_RX_A132_A133 \
+)
+
+/**
+ * A mask of IRIG formats with 100 kHz carrier:
+ */
+#define MSK_ICODE_RX_100KHZ \
+( \
+ MSK_ICODE_RX_G142_G146 \
+)
+
+/**
+ * A mask of IRIG formats with 100 bps data rate:
+ */
+#define MSK_ICODE_RX_100BPS \
+( \
+ MSK_ICODE_RX_B122_B123 | \
+ MSK_ICODE_RX_B002_B003 | \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_AFNOR_DC | \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_B126_B127 | \
+ MSK_ICODE_RX_B006_B007 | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * A mask of IRIG formats with 1000 bps data rate:
+ */
+#define MSK_ICODE_RX_1000BPS \
+( \
+ MSK_ICODE_RX_A132_A133 | \
+ MSK_ICODE_RX_A002_A003 \
+)
+
+/**
+ * A mask of IRIG formats with 10 kbps data rate:
+ */
+#define MSK_ICODE_RX_10000BPS \
+( \
+ MSK_ICODE_RX_G142_G146 \
+)
+
+/**
+ * A mask of IRIG formats which support TFOM:
+ */
+#define MSK_ICODE_RX_HAS_TFOM \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * A mask of IRIG formats which support time zone information:
+ */
+#define MSK_ICODE_RX_HAS_TZI \
+( \
+ MSK_ICODE_RX_IEEE1344 | \
+ MSK_ICODE_RX_IEEE1344_DC | \
+ MSK_ICODE_RX_C37118 | \
+ MSK_ICODE_RX_C37118_DC \
+)
+
+/**
+ * The default mask of IRIG formats supported by
+ * IRIG receivers:
+ */
+#if !defined( SUPP_MSK_ICODE_RX )
+ #define SUPP_MSK_ICODE_RX \
+ ( \
+ MSK_ICODE_RX_B122_B123 | \
+ MSK_ICODE_RX_A132_A133 | \
+ MSK_ICODE_RX_B002_B003 | \
+ MSK_ICODE_RX_A002_A003 | \
+ MSK_ICODE_RX_AFNOR | \
+ MSK_ICODE_RX_AFNOR_DC \
+ )
+#endif
+/** @} */
+
+
+
+/**
+ * The structure below is used to configure an optional
+ * on-board IRIG output:
+ */
+typedef struct
+{
+ uint16_t icode; /**< IRIG signal code, see \ref group_icode */
+ uint16_t flags; /**< see \ref group_irig_flags */
+} IRIG_SETTINGS;
+
+#define _mbg_swab_irig_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->icode ); \
+ _mbg_swab16( &(_p)->flags ); \
+}
+
+
+/**
+ @defgroup group_irig_flags Bit Masks used with IRIG_SETTINGS::flags
+
+ (others are reserved)
+* @{
+ */
+#define IFLAGS_DISABLE_TFOM 0x0001 /**< RX ignore/TX don't gen TFOM */
+#define IFLAGS_TX_GEN_LOCAL_TIME 0x0002 /**< gen local time, not UTC */
+
+#define IFLAGS_MASK 0x0003 /**< flags above or'ed */
+
+// Note: the presence or absence of the IFLAGS_DISABLE_TFOM flag for the IRIG RX
+// settings of some PCI cards may not be evaluated correctly by some firmware
+// versions for those cards, even if an IRIG code has been configured which supports
+// this flag. See the comments near the declaration of the _pcps_incoming_tfom_ignored()
+// macro in pcpsdev.h for details.
+
+/** @} */
+
+/**
+ * @brief Current IRIG settings and supported codes
+ *
+ * Used to query the IRIG current IRIG settings
+ * plus a mask of supported codes.
+ */
+typedef struct
+{
+ IRIG_SETTINGS settings;
+ uint32_t supp_codes; /**< bit mask of supported codes */
+} IRIG_INFO;
+
+#define _mbg_swab_irig_info( _p ) \
+{ \
+ _mbg_swab_irig_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_codes ); \
+}
+
+
+// The type below is used to read the board's debug status
+// which also include IRIG decoder status:
+typedef uint32_t MBG_DEBUG_STATUS;
+
+// The debug status is bit coded as defined below:
+enum
+{
+ MBG_IRIG_BIT_WARMED_UP, /**< Osc has warmed up */
+ MBG_IRIG_BIT_PPS_ACTIVE, /**< PPS output is active */
+ MBG_IRIG_BIT_INV_CONFIG, /**< Invalid config, e.g. data csum error */
+ MBG_IRIG_BIT_MSG_DECODED, /**< IRIG msg could be decoded */
+ MBG_IRIG_BIT_MSG_INCONSISTENT, /**< IRIG msg contains inconsistent data */
+ MBG_IRIG_BIT_LOOP_LOCKED, /**< Decoder control loop is locked */
+ MBG_IRIG_BIT_JITTER_TOO_LARGE, /**< Phase jitter too large */
+ MBG_IRIG_BIT_INV_REF_OFFS, /**< UTC ref offset not configured */
+
+ MBG_SYS_BIT_INV_TIME, /**< Internal time not valid/set */
+ MBG_SYS_BIT_TIME_SET_VIA_API, /**< On board time set externally */
+ MBG_SYS_BIT_INV_RTC, /**< On board RTC invalid */
+ MBG_SYS_BIT_CPU_PLL_FAILED, /**< The CPU's PLL watchdog */
+
+ N_MBG_DEBUG_BIT
+};
+
+/*
+ * Initializers for IRIG status bit strings.
+ */
+#define MBG_DEBUG_STATUS_STRS \
+{ \
+ "Osc has warmed up", \
+ "PPS output is active", \
+ "Config set to default", \
+ "IRIG msg decoded", \
+ "IRIG msg not consistent", \
+ "Decoder control loop locked", \
+ "Phase jitter too large", \
+ "Invalid ref offset", \
+ \
+ "Internal time not valid", \
+ "On board time set via API", \
+ "On board RTC invalid", \
+ "CPU PLL failure, needs restart" \
+}
+
+
+
+#define MBG_IRIG_MSK_WARMED_UP ( 1UL << MBG_IRIG_BIT_WARMED_UP )
+#define MBG_IRIG_MSK_PPS_ACTIVE ( 1UL << MBG_IRIG_BIT_PPS_ACTIVE )
+#define MBG_IRIG_MSK_INV_CONFIG ( 1UL << MBG_IRIG_BIT_INV_CONFIG )
+#define MBG_IRIG_MSK_MSG_DECODED ( 1UL << MBG_IRIG_BIT_MSG_DECODED )
+#define MBG_IRIG_MSK_MSG_INCONSISTENT ( 1UL << MBG_IRIG_BIT_MSG_INCONSISTENT )
+#define MBG_IRIG_MSK_LOOP_LOCKED ( 1UL << MBG_IRIG_BIT_LOOP_LOCKED )
+#define MBG_IRIG_MSK_JITTER_TOO_LARGE ( 1UL << MBG_IRIG_BIT_JITTER_TOO_LARGE )
+#define MBG_IRIG_MSK_INV_REF_OFFS ( 1UL << MBG_IRIG_BIT_INV_REF_OFFS )
+
+#define MBG_SYS_MSK_INV_TIME ( 1UL << MBG_SYS_BIT_INV_TIME )
+#define MBG_SYS_MSK_TIME_SET_VIA_API ( 1UL << MBG_SYS_BIT_TIME_SET_VIA_API )
+#define MBG_SYS_MSK_INV_RTC ( 1UL << MBG_SYS_BIT_INV_RTC )
+#define MBG_SYS_MSK_CPU_PLL_FAILED ( 1UL << MBG_SYS_BIT_CPU_PLL_FAILED )
+
+
+
+typedef int16_t MBG_REF_OFFS; /**< -MBG_REF_OFFS_MAX..MBG_REF_OFFS_MAX */
+
+#define _mbg_swab_mbg_ref_offs( _p ) _mbg_swab16( (_p) )
+
+
+/** the maximum allowed positive / negative offset */
+#define MBG_REF_OFFS_MAX ( ( 12L * 60 ) + 30 ) // [minutes]
+
+/**
+ * the following value is used to indicate that the ref offset
+ * value has not yet been configured
+ */
+#define MBG_REF_OFFS_NOT_CFGD 0x8000
+
+
+typedef struct
+{
+ uint32_t flags;
+} MBG_OPT_SETTINGS;
+
+#define _mbg_swab_mbg_opt_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+typedef struct
+{
+ MBG_OPT_SETTINGS settings;
+ uint32_t supp_flags;
+} MBG_OPT_INFO;
+
+#define _mbg_swab_mbg_opt_info( _p ) \
+{ \
+ _mbg_swab_mbg_opt_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_flags ); \
+}
+
+
+enum
+{
+ MBG_OPT_BIT_STR_UTC, /**< serial string contains UTC time */
+ MBG_OPT_BIT_EMU_SYNC, /**< emulate/pretend to be synchronized, */
+ /**< alternatively GPS_FEAT_IGNORE_LOCK may be supported */
+ N_MBG_OPT_BIT
+};
+
+/*
+ * Bit masks corresponding to the enumeration above:
+ */
+#define MBG_OPT_FLAG_STR_UTC ( 1UL << MBG_OPT_BIT_STR_UTC )
+#define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC )
+
+
+
+// bit coded return type for PCPS_GET_IRIG_CTRL_BITS
+typedef uint32_t MBG_IRIG_CTRL_BITS;
+
+#define _mbg_swab_irig_ctrl_bits( _p ) _mbg_swab32( _p )
+
+
+// The following macro extracts the 4 bit TFOM code from the
+// IRIG control bits read from a card. This only works if the received
+// IRIG code is a code which supports TFOM, this is currently
+// only IEEE1344.
+#define _pcps_tfom_from_irig_ctrl_bits( _p ) \
+ ( ( ( *(_p) ) >> 24 ) & 0x0F )
+
+
+
+#define RAW_IRIG_SIZE 16
+
+/**
+ The buffer below can be used to get the raw data bits
+ from the IRIG decoder. A maximum number of RAW_IRIG_SIZE
+ bytes can be filled. If less bytes are used then the rest
+ of the bytes are filled with zeros.
+
+ The first IRIG bit received from the transmitter is saved
+ in the MSB (bit 7) of data_bytes[0], etc.
+*/
+typedef struct
+{
+ uint8_t data_bytes[RAW_IRIG_SIZE];
+} MBG_RAW_IRIG_DATA;
+
+// The following macro extracts the 4 bit TFOM code from the raw
+// data bits read from a card. This only works if the received
+// IRIG code is a code which supports TFOM, this is currently
+// only IEEE1344.
+#define _pcps_tfom_from_raw_irig_data( _p ) \
+ ( ( ( (_p)->data_bytes[9] >> 2 ) & 0x08 ) \
+ | ( ( (_p)->data_bytes[9] >> 4 ) & 0x04 ) \
+ | ( ( (_p)->data_bytes[9] >> 6 ) & 0x02 ) \
+ | ( ( (_p)->data_bytes[8] & 0x01 ) ) )
+
+
+
+/**
+ @defgroup group_scale Time Scale Configuration
+
+ The structures and defines can be used to configure the GPS receiver's
+ basic time scale. By default this is UTC which can optionally
+ be converted to some local time. However, some applications
+ prefer TAI or pure GPS time. This can be configured using the
+ structures below if the GPS_HAS_TIME_SCALE flag is set in
+ RECEIVER_INFO::features.
+ @{
+*/
+
+enum
+{
+ MBG_TIME_SCALE_DEFAULT, /**< UTC or local time, t_gps - deltat_ls */
+ MBG_TIME_SCALE_GPS, /**< GPS time, monotonical */
+ MBG_TIME_SCALE_TAI, /**< TAI, t_gps + GPS_TAI_OFFSET seconds */
+ N_MBG_TIME_SCALE
+};
+
+#define MBG_TIME_SCALE_MSK_DEFAULT ( 1UL << MBG_TIME_SCALE_DEFAULT )
+#define MBG_TIME_SCALE_MSK_GPS ( 1UL << MBG_TIME_SCALE_GPS )
+#define MBG_TIME_SCALE_MSK_TAI ( 1UL << MBG_TIME_SCALE_TAI )
+
+// See also the extended status bits TM_SCALE_GPS and TM_SCALE_TAI
+// indicating the active time scale setting.
+
+
+#define MBG_TIME_SCALE_STRS \
+{ \
+ "UTC/local", \
+ "GPS", \
+ "TAI" \
+}
+
+
+
+/**
+ The fixed time offset between the GPS and TAI time scales, in seconds
+*/
+#define GPS_TAI_OFFSET 19 /**< [s], TAI = GPS + GPS_TAI_OFFSET */
+
+
+typedef struct
+{
+ uint8_t scale; /**< current time scale code from the enum above */
+ uint8_t flags; /**< reserved, currently always 0 */
+} MBG_TIME_SCALE_SETTINGS;
+
+#define _mbg_swab_mbg_time_scale_settings( _p ) \
+ _nop_macro_fnc()
+
+
+typedef struct
+{
+ MBG_TIME_SCALE_SETTINGS settings; /**< current settings */
+ MBG_TIME_SCALE_SETTINGS max_settings; /**< numb. of scales, all supported flags */
+ uint32_t supp_scales; /**< bit masks of supported scales */
+} MBG_TIME_SCALE_INFO;
+
+#define _mbg_swab_mbg_time_scale_info( _p ) \
+{ \
+ _mbg_swab_mbg_time_scale_settings( &(_p)->settings ); \
+ _mbg_swab_mbg_time_scale_settings( &(_p)->max_settings ); \
+ _mbg_swab32( &(_p)->supp_scales ); \
+}
+
+/** @} */ // endgroup
+
+
+/*
+ * The structures below are required to setup the programmable
+ * pulse outputs which are provided by some GPS receivers.
+ * The number of programmable pulse outputs supported by a GPS
+ * receiver is reported in the RECEIVER_INFO.n_str_type field.
+ */
+
+/**
+ * The structure is used to define a date of year:
+ */
+typedef struct
+{
+ uint8_t mday; /* 1..28,29,30,31 */
+ uint8_t month; /* 1..12 */
+ uint16_t year; /* including century */
+} MBG_DATE;
+
+#define _mbg_swab_mbg_date( _p ) \
+{ \
+ _mbg_swab16( &(_p)->year ); \
+}
+
+
+/**
+ * The structure is used to define a time of day:
+ */
+typedef struct
+{
+ uint8_t hour; /* 0..23 */
+ uint8_t min; /* 0..59 */
+ uint8_t sec; /* 0..59,60 */
+ uint8_t sec100; /* reserved, currently always 0 */
+} MBG_TIME;
+
+#define _mbg_swab_mbg_time( _p ) \
+ _nop_macro_fnc() // nothing to swap
+
+
+/**
+ * The structure defines a single date and time
+ * for switching operations:
+ */
+typedef struct
+{
+ MBG_DATE d; /* date to switch */
+ MBG_TIME t; /* time to switch */
+ uint8_t wday; /* reserved, currently always 0 */
+ uint8_t flags; /* reserved, currently 0 */
+} MBG_DATE_TIME;
+
+#define _mbg_swab_mbg_date_time( _p ) \
+{ \
+ _mbg_swab_mbg_date( &(_p)->d ); \
+ _mbg_swab_mbg_time( &(_p)->t ); \
+}
+
+
+/**
+ * The structure defines times and dates
+ * for an on/off cycle:
+ */
+typedef struct
+{
+ MBG_DATE_TIME on; /* time and date to switch on */
+ MBG_DATE_TIME off; /* time and date to switch off */
+} POUT_TIME;
+
+#define _mbg_swab_pout_time( _p ) \
+{ \
+ _mbg_swab_mbg_date_time( &(_p)->on ); \
+ _mbg_swab_mbg_date_time( &(_p)->off ); \
+}
+
+
+/**
+ * The number of POUT_TIMEs for each programmable pulse output
+ */
+#define N_POUT_TIMES 3
+
+/**
+ * The structure is used to configure a single programmable
+ * pulse output.
+ */
+typedef struct
+{
+ uint16_t mode; /**< mode of operation, codes defined below */
+ uint16_t pulse_len; /**< 10 msec units, or COM port number */
+ uint16_t timeout; /**< [min], for dcf_mode */
+ uint16_t flags; /**< see below */
+ POUT_TIME tm[N_POUT_TIMES]; /**< switching times */
+} POUT_SETTINGS;
+
+#define _mbg_swab_pout_settings( _p ) \
+{ \
+ int i; \
+ _mbg_swab16( &(_p)->mode ); \
+ _mbg_swab16( &(_p)->pulse_len ); \
+ _mbg_swab32( &(_p)->timeout ); \
+ _mbg_swab16( &(_p)->flags ); \
+ \
+ for ( i = 0; i < N_POUT_TIMES; i++ ) \
+ _mbg_swab_pout_time( &(_p)->tm[i] ); \
+}
+
+
+#define MAX_POUT_PULSE_LEN 1000 /**< 10 secs, in 10 msec units */
+#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) /**< 48 hours, in minutes */
+
+
+/**
+ * These codes are defined for POUT_SETTINGS.mode to setup
+ * the basic mode of operation for a single programmable pulse
+ * output:
+ */
+enum
+{
+ POUT_IDLE, /**< always off, or on if POUT_INVERTED */
+ POUT_TIMER, /**< switch on/off at configured times */
+ POUT_SINGLE_SHOT, /**< pulse at time POUT_SETTINGS.tm[0].on */
+ POUT_CYCLIC_PULSE, /**< pulse every POUT_SETTINGS.tm[0].on.t interval */
+ POUT_PER_SEC, /**< pulse if second changes */
+ POUT_PER_MIN, /**< pulse if minute changes */
+ POUT_PER_HOUR, /**< pulse if hour changes */
+ POUT_DCF77, /**< emulate DCF77 signal */
+ POUT_POS_OK, /**< on if pos. OK (nav_solved) */
+ POUT_TIME_SYNC, /**< on if time sync (time_syn) */
+ POUT_ALL_SYNC, /**< on if pos. OK and time sync */
+ POUT_TIMECODE, /**< IRIG/AFNOR DCLS output */
+ POUT_TIMESTR, /**< COM port number in pulse_len field */
+ POUT_10MHZ, /**< 10 MHz fixed frequency */
+ POUT_DCF77_M59, /**< DCF77-like signal with 500 ms pulse in 59th second */
+ POUT_SYNTH, /**< programmable synthesizer frequency */
+ N_POUT_MODES
+};
+
+
+/*
+ * Default initializers for English pulse mode names. Initializers
+ * for multi-language strings can be found in pcpslstr.h.
+ */
+#define ENG_POUT_NAME_IDLE "Idle"
+#define ENG_POUT_NAME_TIMER "Timer"
+#define ENG_POUT_NAME_SINGLE_SHOT "Single Shot"
+#define ENG_POUT_NAME_CYCLIC_PULSE "Cyclic Pulse"
+#define ENG_POUT_NAME_PER_SEC "Pulse Per Second"
+#define ENG_POUT_NAME_PER_MIN "Pulse Per Min"
+#define ENG_POUT_NAME_PER_HOUR "Pulse Per Hour"
+#define ENG_POUT_NAME_DCF77 "DCF77 Marks"
+#define ENG_POUT_NAME_POS_OK "Position OK"
+#define ENG_POUT_NAME_TIME_SYNC "Time Sync"
+#define ENG_POUT_NAME_ALL_SYNC "All Sync"
+#define ENG_POUT_NAME_TIMECODE "DCLS Time Code"
+#define ENG_POUT_NAME_TIMESTR "COM Time String"
+#define ENG_POUT_NAME_10MHZ "10 MHz Frequency"
+#define ENG_POUT_NAME_DCF77_M59 "DCF77-like M59"
+#define ENG_POUT_NAME_SYNTH "Synthesizer Frequency"
+
+#define DEFAULT_ENG_POUT_NAMES \
+{ \
+ ENG_POUT_NAME_IDLE, \
+ ENG_POUT_NAME_TIMER, \
+ ENG_POUT_NAME_SINGLE_SHOT, \
+ ENG_POUT_NAME_CYCLIC_PULSE, \
+ ENG_POUT_NAME_PER_SEC, \
+ ENG_POUT_NAME_PER_MIN, \
+ ENG_POUT_NAME_PER_HOUR, \
+ ENG_POUT_NAME_DCF77, \
+ ENG_POUT_NAME_POS_OK, \
+ ENG_POUT_NAME_TIME_SYNC, \
+ ENG_POUT_NAME_ALL_SYNC, \
+ ENG_POUT_NAME_TIMECODE, \
+ ENG_POUT_NAME_TIMESTR, \
+ ENG_POUT_NAME_10MHZ, \
+ ENG_POUT_NAME_DCF77_M59, \
+ ENG_POUT_NAME_SYNTH \
+}
+
+
+#define ENG_POUT_HINT_IDLE "Constant output level"
+#define ENG_POUT_HINT_TIMER "Switch based on configured on/off times"
+#define ENG_POUT_HINT_SINGLE_SHOT "Generate a single pulse of determined length"
+#define ENG_POUT_HINT_CYCLIC_PULSE "Generate cyclic pulses of determined length"
+#define ENG_POUT_HINT_PER_SEC "Generate pulse at beginning of new second"
+#define ENG_POUT_HINT_PER_MIN "Generate pulse at beginning of new minute"
+#define ENG_POUT_HINT_PER_HOUR "Generate pulse at beginning of new hour"
+#define ENG_POUT_HINT_DCF77 "DCF77 compatible time marks"
+#define ENG_POUT_HINT_POS_OK "Switch if receiver position has been verified"
+#define ENG_POUT_HINT_TIME_SYNC "Switch if time is synchronized"
+#define ENG_POUT_HINT_ALL_SYNC "Switch if full sync"
+#define ENG_POUT_HINT_TIMECODE "Duplicate IRIG time code signal"
+#define ENG_POUT_HINT_TIMESTR "Duplicate serial time string of specified port"
+#define ENG_POUT_HINT_10MHZ "10 MHz fixed output frequency"
+#define ENG_POUT_HINT_DCF77_M59 "DCF77 time marks with 500 ms pulse in 59th second"
+#define ENG_POUT_HINT_SYNTH "Frequency generated by programmable synthesizer"
+
+#define DEFAULT_ENG_POUT_HINTS \
+{ \
+ ENG_POUT_HINT_IDLE, \
+ ENG_POUT_HINT_TIMER, \
+ ENG_POUT_HINT_SINGLE_SHOT, \
+ ENG_POUT_HINT_CYCLIC_PULSE, \
+ ENG_POUT_HINT_PER_SEC, \
+ ENG_POUT_HINT_PER_MIN, \
+ ENG_POUT_HINT_PER_HOUR, \
+ ENG_POUT_HINT_DCF77, \
+ ENG_POUT_HINT_POS_OK, \
+ ENG_POUT_HINT_TIME_SYNC, \
+ ENG_POUT_HINT_ALL_SYNC, \
+ ENG_POUT_HINT_TIMECODE, \
+ ENG_POUT_HINT_TIMESTR, \
+ ENG_POUT_HINT_10MHZ, \
+ ENG_POUT_HINT_DCF77_M59, \
+ ENG_POUT_HINT_SYNTH \
+}
+
+
+/*
+ * The definitions below are used to set up bit masks
+ * which restrict the modes which can be used with
+ * a given programmable output:
+ */
+#define MSK_POUT_IDLE ( 1UL << POUT_IDLE )
+#define MSK_POUT_TIMER ( 1UL << POUT_TIMER )
+#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT )
+#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE )
+#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC )
+#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN )
+#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR )
+#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 )
+#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK )
+#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC )
+#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC )
+#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE )
+#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR )
+#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ )
+#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 )
+#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH )
+
+
+/*
+ * The codes below are used with POUT_SETTINGS::flags:
+ */
+#define POUT_INVERTED 0x0001 // invert output level
+#define POUT_IF_SYNC_ONLY 0x0002 // disable in holdover mode
+#define POUT_TIMEBASE_UTC 0x0004 // use UTC, only applicable for DCF77 output
+
+
+/**
+ Since a clock may support more than one programmable
+ pulse output, setup tools must use the structure below
+ to read/set pulse output configuration.
+ The number of outputs supported by a receiver model
+ can be queried using the RECEIVER_INFO structure.
+ */
+typedef struct
+{
+ uint16_t idx; /**< 0..RECEIVER_INFO.n_prg_out-1 */
+ POUT_SETTINGS pout_settings;
+} POUT_SETTINGS_IDX;
+
+#define _mbg_swab_pout_settings_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_pout_settings( &(_p)->pout_settings ); \
+}
+
+
+/**
+ The structure below holds the current settings
+ for a programmable pulse output, plus additional
+ informaton on the output's capabilities.
+ This can be read by setup programs to allow setup
+ of supported features only.
+ */
+typedef struct
+{
+ POUT_SETTINGS pout_settings;
+ uint32_t supp_modes; /**< bit mask of modes supp. by this output */
+ uint8_t timestr_ports; /**< bit mask of COM ports supported for POUT_TIMESTR */
+ uint8_t reserved_0; /**< reserved for future use, currently 0 */
+ uint16_t reserved_1; /**< reserved for future use, currently 0 */
+ uint32_t flags; /**< see below */
+} POUT_INFO;
+
+#define _mbg_swab_pout_info( _p ) \
+{ \
+ _mbg_swab_pout_settings( &(_p)->pout_settings ); \
+ _mbg_swab32( &(_p)->supp_modes ); \
+ _mbg_swab16( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/** The max number of COM ports that can be handled by POUT_INFO::timestr_ports */
+#define MAX_POUT_TIMESTR_PORTS 8
+
+
+/*
+ * The codes below are used with POUT_INFO::flags:
+ */
+#define POUT_SUPP_IF_SYNC_ONLY 0x0001 // supports disabling outputs in holdover mode
+#define POUT_SUPP_DCF77_UTC 0x0002 // supports UTC output in DCF77 mode
+
+
+/**
+ The structure below adds an index number to the structure
+ above to allow addressing of several instances:
+ */
+typedef struct
+{
+ uint16_t idx; /**< 0..RECEIVER_INFO.n_prg_out-1 */
+ POUT_INFO pout_info;
+} POUT_INFO_IDX;
+
+#define _mbg_swab_pout_info_idx( _p ) \
+{ \
+ _mbg_swab16( &(_p)->idx ); \
+ _mbg_swab_pout_info( &(_p)->pout_info ); \
+}
+
+
+/*
+ * The codes below are used with devices which support multiple
+ * ref time sources at the same time. The priorities of the
+ * supported ref time sources is configurable.
+ */
+
+
+/*
+ * All possibly supported ref time sources
+ */
+enum
+{
+ MULTI_REF_NONE = -1, // nothing, undefined
+ MULTI_REF_GPS = 0, // standard GPS
+ MULTI_REF_10MHZ, // 10 MHz input frequency
+ MULTI_REF_PPS, // 1 PPS input signal
+ MULTI_REF_10MHZ_PPS, // combined 10 MHz plus PPS
+ MULTI_REF_IRIG, // IRIG input
+ MULTI_REF_NTP, // Network Time Protocol (NTP)
+ MULTI_REF_PTP, // Precision Time Protocol (PTP, IEEE1588)
+ MULTI_REF_PTP_E1, // PTP over E1
+ MULTI_REF_FREQ, // fixed frequency
+ MULTI_REF_PPS_STRING, // 1 PPS in addition to string
+ N_MULTI_REF // the number of defined sources
+};
+
+
+/*
+ * Names of supported ref time sources
+ */
+#define DEFAULT_MULTI_REF_NAMES \
+{ \
+ "GPS", \
+ "10 MHz freq in", \
+ "PPS in", \
+ "10 MHz + PPS in", \
+ "IRIG", \
+ "NTP", \
+ "PTP (IEEE1588)", \
+ "PTP over E1", \
+ "Fixed Freq. in", \
+ "PPS plus string" \
+}
+
+
+/*
+ * Bit masks used to indicate supported reference sources
+ */
+#define HAS_MULTI_REF_GPS ( 1UL << MULTI_REF_GPS )
+#define HAS_MULTI_REF_10MHZ ( 1UL << MULTI_REF_10MHZ )
+#define HAS_MULTI_REF_PPS ( 1UL << MULTI_REF_PPS )
+#define HAS_MULTI_REF_10MHZ_PPS ( 1UL << MULTI_REF_10MHZ_PPS )
+#define HAS_MULTI_REF_IRIG ( 1UL << MULTI_REF_IRIG )
+#define HAS_MULTI_REF_NTP ( 1UL << MULTI_REF_NTP )
+#define HAS_MULTI_REF_PTP ( 1UL << MULTI_REF_PTP )
+#define HAS_MULTI_REF_PTP_E1 ( 1UL << MULTI_REF_PTP_E1 )
+#define HAS_MULTI_REF_FREQ ( 1UL << MULTI_REF_FREQ )
+#define HAS_MULTI_REF_PPS_STRING ( 1UL << MULTI_REF_PPS_STRING )
+
+
+/*
+ * There are 2 different ways to configure multi ref support
+ * provided by some devices.
+ *
+ * Newer devices which have the GPS_FEAT_XMULTI_REF flag set
+ * in RECEIVER_INFO::features support the newer XMULTI_REF_...
+ * structures which provide a more flexible interface.
+ *
+ * Older devices which have the GPS_FEAT_MULTI_REF flag set
+ * support these MULTI_REF_... structures below where
+ * the number of supported input sources and priorities
+ * is limited to N_MULTI_REF_PRIO.
+ */
+
+#define N_MULTI_REF_PRIO 4
+
+
+/**
+ The structure below is used to configure the priority of
+ the supported ref sources.
+
+ The number stored in prio[0] of the array indicates the ref time
+ source with highest priority. If that source fails, the device
+ falls back to the source indicated by prio[1]. Each field of
+ the prio[] array must be set to one of the values 0..N_MULTI_REF-1,
+ or to -1 (0xFF) if the value is not assigned.
+ */
+typedef struct
+{
+ uint8_t prio[N_MULTI_REF_PRIO];
+} MULTI_REF_SETTINGS;
+
+
+/**
+ The structure below is used to query the MULTI_REF configuration,
+ plus the supported ref sources.
+ */
+typedef struct
+{
+ MULTI_REF_SETTINGS settings; /* current settings */
+ uint32_t supp_ref; /* supp. HAS_MULTI_REF_... codes or'ed */
+ uint16_t n_levels; /* supp. levels, 0..N_MULTI_REF_PRIO */
+ uint16_t flags; /* reserved, currently 0 */
+} MULTI_REF_INFO;
+
+
+/*
+ * The type below is used to query the MULTI_REF status information,
+ */
+typedef uint16_t MULTI_REF_STATUS; /* flag bits as defined below */
+
+
+/*
+ * The bits and associated bit masks below are used with the
+ * MULTI_REF_STATUS type. Each bit is set if the associated
+ * condition is true and is reset if the condition is not true:
+ */
+enum
+{
+ WRN_MODULE_MODE, /* selected input mode was invalid, set to default */
+ WRN_COLD_BOOT, /* GPS is in cold boot mode */
+ WRN_WARM_BOOT, /* GPS is in warm boot mode */
+ WRN_ANT_DISCONN, /* antenna is disconnected */
+ WRN_10MHZ_UNLOCK, /* impossible to lock to external 10MHz reference */
+ WRN_1PPS_UNLOCK, /* impossible to lock to external 1PPS reference */
+ WRN_GPS_UNLOCK, /* impossible to lock to GPS */
+ WRN_10MHZ_MISSING, /* external 10MHz signal not available */
+ WRN_1PPS_MISSING, /* external 1PPS signal not available */
+ N_MULTI_REF_STATUS_BITS
+};
+
+#define MSK_WRN_COLD_BOOT ( 1UL << WRN_COLD_BOOT )
+#define MSK_WRN_WARM_BOOT ( 1UL << WRN_WARM_BOOT )
+#define MSK_WRN_ANT_DISCONN ( 1UL << WRN_ANT_DISCONN )
+#define MSK_WRN_10MHZ_UNLOCK ( 1UL << WRN_10MHZ_UNLOCK )
+#define MSK_WRN_1PPS_UNLOCK ( 1UL << WRN_1PPS_UNLOCK )
+#define MSK_WRN_GPS_UNLOCK ( 1UL << WRN_GPS_UNLOCK )
+#define MSK_WRN_10MHZ_MISSING ( 1UL << WRN_10MHZ_MISSING )
+#define MSK_WRN_1PPS_MISSING ( 1UL << WRN_1PPS_MISSING )
+#define MSK_WRN_MODULE_MODE ( 1UL << WRN_MODULE_MODE )
+
+
+
+/*
+ * If the RECEIVER_INFO::features flag GPS_FEAT_XMULTI_REF is set
+ * then the following XMULTI_REF_... data structures must be used
+ * instead of the older MULTI_REF_... structures above.
+ *
+ * Those devices support a number of priority levels addressed by
+ * the priority index, starting at 0 for highest priority. A single
+ * reference time source from the set of supported sources can be
+ * assigned to each priority level.
+ *
+ * The structures below are used to configure the individual
+ * time source for each priority level, and retrieve the status
+ * of the time source at each priority level.
+ */
+
+typedef struct
+{
+ uint8_t type; /* 0..N_MULTI_REF-1 from the enum above */
+ uint8_t instance; /* reserved, currently always 0 */
+} XMULTI_REF_ID;
+
+typedef struct
+{
+ XMULTI_REF_ID id; /* time source identifier */
+ uint16_t flags; /* reserved, currently always 0 */
+ NANO_TIME bias; /* time bias, e.g. path delay */
+ NANO_TIME precision; /* precision of the time source */
+ uint32_t fine_limit; /* smooth control if below this limit */
+} XMULTI_REF_SETTINGS;
+
+
+/*
+ * The structure below is used to retrieve or configure the time source
+ * for a specific priority level.
+ * After configuring, a structure with idx == 0xFFFF (-1) must be sent
+ * to let the changes become effective.
+ */
+typedef struct
+{
+ uint16_t idx; /* the priority level index, highest == 0 */
+ XMULTI_REF_SETTINGS settings; /* the settings configured for this level */
+
+} XMULTI_REF_SETTINGS_IDX;
+
+
+/*
+ * The structure below contains the XMULTI_REF configuration
+ * for a single priority level, plus information on supported
+ * ref time sources, and the number of supported priority levels.
+ */
+typedef struct
+{
+ XMULTI_REF_SETTINGS settings; /* current settings */
+ uint32_t supp_ref; /* supp. HAS_MULTI_REF_... codes or'ed */
+ uint8_t n_supp_ref; /* number of supported ref time sources */
+ uint8_t n_prio; /* number of supported priority levels */
+ uint16_t flags; /* reserved, currently 0, e.g. multiple instance support */
+
+} XMULTI_REF_INFO;
+
+
+/*
+ * The structure below is used to retrieve the XMULTI_REF configuration
+ * information for a specific priority level.
+ */
+typedef struct
+{
+ uint16_t idx; /* the priority level index, highest == 0 */
+ XMULTI_REF_INFO info;
+
+} XMULTI_REF_INFO_IDX;
+
+
+/*
+ * The structure below contains status information on a single
+ * ref time source.
+ */
+typedef struct
+{
+ XMULTI_REF_ID id; /* time source identifier */
+ uint16_t status; /* flag bits as defined below */
+ NANO_TIME offset; /* time offset from main time base */
+ uint32_t reserved; /* reserved, currently always 0 */
+
+} XMULTI_REF_STATUS;
+
+
+/*
+ * The structure below is used to retrieve the the status information
+ * of the time source at a specific priority level.
+ */
+typedef struct
+{
+ uint16_t idx; /* the priority level index, highest == 0 */
+ XMULTI_REF_STATUS status;
+
+} XMULTI_REF_STATUS_IDX;
+
+
+/*
+ * Bits used with XMULTI_REF_STATUS.
+ */
+enum
+{
+ XMRS_BIT_NOT_SUPP, /* ref type cfg'd for this level is not supported */
+ XMRS_BIT_NO_CONN, /* input signal is disconnected */
+ XMRS_BIT_NO_SIGNAL, /* no input signal */
+ XMRS_BIT_IS_MASTER, /* reference is master source */
+ XMRS_BIT_IS_LOCKED, /* locked to input signal */
+ XMRS_BIT_IS_ACCURATE, /* oscillator control has reached full accuracy */
+ XMRS_BIT_NOT_SETTLED, /* reference time signal not settled */
+ XMRS_BIT_NOT_PHASE_LOCKED, /* oscillator not phase locked to PPS */
+ N_XMRS_BITS
+};
+
+
+/* bit masks corresponding to the flag bits above */
+
+#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP )
+#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN )
+#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL )
+#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER )
+#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED )
+#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE )
+#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED )
+#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED )
+
+
+
+/*
+ * An initializer for a XMULTI_REF_STATUS variable
+ * with status invalid / not used
+ */
+#define XMULTI_REF_STATUS_INVALID \
+{ \
+ { (uint8_t) MULTI_REF_NONE, 0 }, /* id; instance 0 ? */ \
+ XMRS_MSK_NO_CONN | XMRS_MSK_NO_SIGNAL, /* status */ \
+ { 0 }, /* offset */ \
+ 0 /* reserved */ \
+}
+
+
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * The types below are not used with all devices:
+ */
+
+typedef uint16_t ROM_CSUM; /* The ROM checksum */
+typedef uint16_t RCV_TIMEOUT; /* [min] (only if HAS_RCV_TIMEOUT) */
+typedef uint16_t IGNORE_LOCK; /* (only if GPS_HAS_IGNORE_LOCK) */
+
+/*
+ * Originally IGNORE_LOG above has been a boolean value (equal or
+ * not equal 0) which was evaluated the same way for all ports.
+ *
+ * Due to special firmware requirements it has been changed to a
+ * bit maskable property in order to be able to specify the behaviour
+ * for individual ports.
+ *
+ * In order to keep compatibility with older versions the LSB is used
+ * to specify ignore_lock for all ports. The next higher bits are used
+ * to specify ignore_lock for an individual port, where the bit position
+ * depends on the port number, e.g. 0x02 for COM0, 0x04 for COM1, etc.
+ * The macros below can be used to simplify the code:
+ */
+
+/* return a bit mask depending on the port number */
+#define IGNORE_LOCK_FOR_ALL_PORTS 0x01
+
+#define _ignore_lock_for_all_ports() ( IGNORE_LOCK_FOR_ALL_PORTS )
+
+#define _ignore_lock_for_port( _n ) ( 0x02 << (_n) )
+
+/* check if all ports are ignore_lock'ed */
+#define _is_ignore_lock_all_ports( _il ) ( (_il) & IGNORE_LOCK_FOR_ALL_PORTS )
+
+/* check if a specific port is ignore_lock'ed */
+#define _is_ignore_lock_for_port( _il, _n ) \
+ ( (_il) & ( _ignore_lock_for_port(_n) | IGNORE_LOCK_FOR_ALL_PORTS ) )
+
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * The structures below are used with the SCU multiplexer board
+ * in a redundant system:
+ */
+
+typedef struct
+{
+ uint32_t hw_id; // hardware identification
+ uint32_t fw_id; // firmware identification
+ uint16_t flags; // reserved currently 0
+ uint8_t clk0_info; // reference clock 0 type
+ uint8_t clk1_info; // reference clock 1 type
+ uint16_t epld_status; // epld status word, see defintions below
+ uint16_t epld_control; // epld control word, see defintions below
+} SCU_STAT_INFO;
+
+typedef struct
+{
+ uint16_t epld_control_mask; // control mask, determines which bit is to be changed
+ uint16_t epld_control_value; // control value, determines value of bits to be changed
+ uint32_t flags; // reserved, currently 0
+} SCU_STAT_SETTINGS;
+
+// definitions for status word bit masks
+#define MSK_EPLD_STAT_TS1 0x0001 // state of time sync signal clk_1
+#define MSK_EPLD_STAT_TS2 0x0002 // state of time sync signal clk_2
+#define MSK_EPLD_STAT_TL_ERROR 0x0004 // state of time limit error input
+#define MSK_EPLD_STAT_PSU1_OK 0x0008 // state of power supply 1 monitoring input
+#define MSK_EPLD_STAT_PSU2_OK 0x0010 // state of power supply 2 monitoring input
+#define MSK_EPLD_STAT_AUTO 0x0020 // AUTOMATIC/REMOTE or MANUAL Mode
+#define MSK_EPLD_STAT_SEL 0x0040 // select bit for output MUX, ( clk_1 = 0 )
+#define MSK_EPLD_STAT_ENA 0x0080 // enable Bit for output MUX, set if enabled
+#define MSK_EPLD_STAT_ACO 0x4000 // Access control override bit
+#define MSK_EPLD_STAT_WDOG_OK 0x8000 // WDT_OK set to zero if watchdog expired
+
+
+#define MSK_EPLD_CNTL_SEL_REM 0x0800 // remote select for output MUX ( clk_1 = 0 )
+#define MSK_EPLD_CNTL_DIS_REM 0x1000 // remote disable for output MUX
+#define MSK_EPLD_CNTL_REMOTE 0x2000 // must be set to enable remote operation
+#define MSK_EPLD_CNTL_SEL_SNMP 0x4000 // connect COM0 channels to XPORT
+#define MSK_EPLD_CNTL_ENA_SNMP 0x8000 // select clk for comm. ( clk1 = 0 )
+
+
+/*
+ * Definitions for clk0_info and clk1_info, can be used to determine
+ * the reference clock type connected to SCU input channel 0 and 1:
+ */
+enum
+{
+ SCU_CLK_INFO_GPS, // ref. clock is GPS receiver
+ SCU_CLK_INFO_DCF_PZF, // ref. clock is DCF77 PZF receiver
+ SCU_CLK_INFO_DCF_AM, // ref. clock is DCF77 AM receiver
+ SCU_CLK_INFO_TCR // ref. clock is IRIG time code receiver
+};
+
+
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * GPS receiver modes of operation. Some of the codes combinations
+ * are obsolete with recent GPS receivers. However, that doesn't
+ * matter since the mode is just read from the receiver:
+ */
+#define REMOTE 0x10
+#define BOOT 0x20
+
+#define TRACK ( 0x01 )
+#define AUTO_166 ( 0x02 )
+#define WARM_166 ( 0x03 | BOOT )
+#define COLD_166 ( 0x04 | BOOT )
+#define AUTO_BC ( 0x05 | REMOTE )
+#define WARM_BC ( 0x06 | REMOTE | BOOT )
+#define COLD_BC ( 0x07 | REMOTE | BOOT )
+#define UPDA_166 ( 0x08 | BOOT )
+#define UPDA_BC ( 0x09 | REMOTE | BOOT )
+
+
+
+typedef int16_t DAC_VAL;
+
+#define _mbg_swab_dac_val( _p ) \
+ _mbg_swab16( _p );
+
+
+
+typedef struct
+{
+ uint16_t mode; /**< Mode of operation */
+ uint16_t good_svs; /**< Numb. of satellites that can currently be received and used */
+ uint16_t svs_in_view; /**< Numb. of satellites that should be in view according to the almanac data */
+ DAC_VAL dac_val; /**< Oscillator fine DAC value */
+ DAC_VAL dac_cal; /**< Oscillator calibration DAC value ( see #OSC_DAC_RANGE, #OSC_DAC_BIAS ) */
+} STAT_INFO;
+
+#define _mbg_swab_stat_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->mode ); \
+ _mbg_swab16( &(_p)->good_svs ); \
+ _mbg_swab16( &(_p)->svs_in_view ); \
+ _mbg_swab_dac_val( &(_p)->dac_val ); \
+ _mbg_swab_dac_val( &(_p)->dac_cal ); \
+}
+
+
+#define OSC_DAC_RANGE 4096UL
+#define OSC_DAC_BIAS ( OSC_DAC_RANGE / 2 )
+
+
+
+/*
+ The enumeration below lists all
+ known satellite navigation systems
+*/
+enum
+{
+ GNSS_TYPE_GPS,
+ GNSS_TYPE_GLONASS,
+ GNSS_TYPE_BEIDOU,
+ GNSS_TYPE_GALILEO,
+ N_GNSS_TYPES
+};
+
+
+
+#define GNSS_TYPE_STRS \
+{ \
+ "GPS", \
+ "GLONASS", \
+ "BEIDOU" , \
+ "GALILEO" \
+}
+
+
+
+#define MBG_GNSS_TYPE_MSK_GPS ( 1UL << GNSS_TYPE_GPS )
+#define MBG_GNSS_TYPE_MSK_GLONASS ( 1UL << GNSS_TYPE_GLONASS )
+#define MBG_GNSS_TYPE_MSK_BEIDOU ( 1UL << GNSS_TYPE_BEIDOU )
+#define MBG_GNSS_TYPE_MSK_GALILEO ( 1UL << GNSS_TYPE_GALILEO )
+
+
+#define N_GNSS_MODE_PRIO 8
+
+typedef struct
+{
+ uint32_t gnss_set; /**< current set of GNSS types */
+ uint8_t prio[N_GNSS_MODE_PRIO]; /**< index 0 for highest priority, use GNSS enumeration above, init with 0xFF if not supported */
+ uint32_t flags; /**< see below */
+} MBG_GNSS_MODE_SETTINGS;
+
+#define _mbg_swab_mbg_gnss_mode_settings( _p ) \
+{ \
+ _mbg_swab32( &(_p)->gnss_set ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+typedef struct
+{
+ MBG_GNSS_MODE_SETTINGS settings; /**< current GNSS mode settings */
+ uint32_t supp_gnss_types; /**< bit masks of supported GNSS types */
+ uint32_t flags; /**< indicates which of the defined flags are supported by the device */
+} MBG_GNSS_MODE_INFO;
+
+#define _mbg_swab_mbg_gnss_mode_info( _p ) \
+{ \
+ _mbg_swab_mbg_gnss_mode_settings( &(_p)->settings ); \
+ _mbg_swab32( &(_p)->supp_gnss_types ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+/* Flags used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags: */
+
+enum
+{
+ MBG_GNSS_FLAG_EXCLUSIVE, /**< (read only) only one of the supported GNSS systems can be used at the same time */
+ MBG_GNSS_FLAG_HAS_PRIORITY, /**< (read only) priority can be configured using the MBG_GNSS_MODE_SETTINGS::prio field */
+ N_MBG_GNSS_FLAGS
+};
+
+#define MBG_GNSS_FLAG_MSK_EXCLUSIVE ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE )
+#define MBG_GNSS_FLAG_MSK_HAS_PRIORITY ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY )
+
+
+
+#define MAX_USED_SATS 32
+
+/*
+ The structure below allos to transfer
+ SV information from a certain GNSS type.
+*/
+typedef struct
+{
+ uint8_t gnss_type; /**< GNSS type from the enumeration above */
+ uint8_t reserved;
+ uint16_t good_svs;
+ uint16_t svs_in_view;
+ uint8_t svs[MAX_USED_SATS];
+} GNSS_SAT_INFO;
+
+#define _mbg_swab_gnss_sat_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->good_svs ); \
+ _mbg_swab16( &(_p)->svs_in_view ); \
+}
+
+
+#ifndef _IDENT_DEFINED
+
+ typedef union
+ {
+ char c[16]; // as string which may NOT be terminated
+ int16_t wrd[8];
+ uint32_t lw[4];
+ } IDENT;
+
+ #define _IDENT_DEFINED
+#endif
+
+#define _mbg_swab_ident( _p ) \
+{ \
+ int i; \
+ for ( i = 0; i < 4; i++ ) \
+ _mbg_swab32( &(_p)->lw[i] ); \
+}
+
+/**
+ * The type below is used to configure the length of the
+ * antenna cable in [m]:
+ */
+typedef uint16_t ANT_CABLE_LEN;
+
+#define _mbg_swab_ant_cable_len( _p ) _mbg_swab16( _p )
+
+
+
+/* Configuration data for an optional LAN interface.
+ *
+ * This is only supported if the flag GPS_HAS_LAN_IP4
+ * is set in RECEIVER_INFO::features.
+ */
+
+
+/* Basic network settings */
+
+typedef uint32_t IP4_ADDR;
+
+#define _mbg_swab_ip4_addr( _p ) \
+ _mbg_swab32( _p );
+
+
+typedef struct
+{
+ IP4_ADDR ip_addr;
+ IP4_ADDR netmask;
+ IP4_ADDR broad_addr;
+ IP4_ADDR gateway;
+ uint16_t flags; /* see below */
+ uint16_t vlan_cfg; /* see below */
+
+} IP4_SETTINGS;
+
+#define _mbg_swab_ip4_settings( _p ) \
+{ \
+ _mbg_swab_ip4_addr( &(_p)->ip_addr ); \
+ _mbg_swab_ip4_addr( &(_p)->netmask ); \
+ _mbg_swab_ip4_addr( &(_p)->broad_addr ); \
+ _mbg_swab_ip4_addr( &(_p)->gateway ); \
+ _mbg_swab16( &(_p)->flags ); \
+ _mbg_swab16( &(_p)->vlan_cfg ); \
+}
+
+
+// IP4_SETTINGS::vlan_cfg contains a combination of
+// a VLAN ID number plus a VLAN priiority code.
+// Definitions used with IP4_SETTINGS::vlan_cfg:
+
+#define VLAN_ID_BITS 12 // number of bits to hold the ID
+#define N_VLAN_ID ( 1 << VLAN_ID_BITS ) // number of ID values
+#define MIN_VLAN_ID 0 // minimum ID value
+#define MAX_VLAN_ID ( N_VLAN_ID - 1 ) // maximum ID value
+
+// vlan_id = ( vlan_cfg >> VLAN_ID_SHIFT ) & VLAN_ID_MSK
+#define VLAN_ID_SHIFT 0
+#define VLAN_ID_MSK ( ( 1 << VLAN_ID_BITS ) - 1 )
+
+
+#define VLAN_PRIORITY_BITS 3 // number of bits to hold priority
+#define N_VLAN_PRIORITY ( 1 << VLAN_PRIORITY_BITS ) // number of priority values
+#define MIN_VLAN_PRIORITY 0 // minimum priority
+#define MAX_VLAN_PRIORITY ( N_VLAN_PRIORITY - 1 ) // maximum priority
+
+// vlan_priority = ( vlan_cfg >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK
+#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( uint16_t ) ) - VLAN_PRIORITY_BITS )
+#define VLAN_PRIORITY_MSK ( ( 1 << VLAN_PRIORITY_BITS ) - 1 )
+
+// The macros below can be used to encode/decode packed vlan_cfg variables:
+#define _decode_vlan_id( _cfg ) ( ( (_cfg) >> VLAN_ID_SHIFT ) & VLAN_ID_MSK )
+#define _decode_vlan_priority( _cfg ) ( ( (_cfg) >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK )
+#define _encode_vlan_cfg( _id, _prty ) ( ( (_id) << VLAN_ID_SHIFT ) | ( (_prty) << VLAN_PRIORITY_SHIFT ) )
+
+
+#if 0 //##++ currently not used
+
+/* Misc configuration */
+
+typedef struct
+{
+ uint16_t id; /* service ID, see below */
+ uint16_t index; /* used if several same svcs must be cfg'd, e.g. DNS */
+ char host[50]; /* see below */
+
+} IP_CFG;
+
+
+
+/* Description of a service running on a device */
+
+typedef struct
+{
+ uint16_t id; /* service ID, see below */
+ uint16_t socket; /* the socket on which the service is listening */
+ uint32_t flags; /* see below */
+
+} IP_SERVICE;
+
+#endif // 0
+
+
+
+/* LAN interface information */
+
+typedef struct
+{
+ uint16_t type; /* codes see below */
+ uint8_t mac_addr[6]; /* MAC address */
+ uint16_t ver_code; /* high byte.low byte, in hex */
+ char ver_str[GPS_ID_STR_SIZE];
+ char sernum[GPS_ID_STR_SIZE];
+ uint32_t rsvd_0; /* reserved, currently always 0 */
+ uint16_t flags; /* see below */
+ uint16_t rsvd_1; /* reserved, currently always 0 */
+} LAN_IF_INFO;
+
+#define _mbg_swab_lan_if_info( _p ) \
+{ \
+ _mbg_swab16( &(_p)->type ); \
+ _mbg_swab16( &(_p)->ver_code ); \
+ _mbg_swab32( &(_p)->rsvd_0 ); \
+ _mbg_swab16( &(_p)->flags ); \
+ _mbg_swab16( &(_p)->rsvd_1 ); \
+}
+
+
+
+/* codes used with LAN_IF_INFO::type: */
+
+enum
+{
+ LAN_IF_TYPE_XPORT,
+ LAN_IF_TYPE_PTP,
+ N_LAN_IF_TYPE
+};
+
+
+/* Flags used with IP4_SETTINGS::flags and LAN_IF_INFO::flags: */
+
+enum
+{
+ IP4_BIT_DHCP, // DHCP supported (LAN_IF_INFO) / enabled (IP4_SETTINGS)
+ IP4_BIT_LINK, // used only in IP4_SETTINGS to report link state
+ IP4_BIT_VLAN, // VLAN supported (LAN_IF_INFO) / enabled (IP4_SETTINGS)
+ N_IP4_BIT
+};
+
+#define IP4_MSK_DHCP ( 1UL << IP4_BIT_DHCP )
+#define IP4_MSK_LINK ( 1UL << IP4_BIT_LINK )
+#define IP4_MSK_VLAN ( 1UL << IP4_BIT_VLAN )
+
+
+enum
+{
+ PTP_NW_PROT_BIT_RESERVED,
+ PTP_NW_PROT_BIT_UDP_IPV4,
+ PTP_NW_PROT_BIT_UDP_IPV6,
+ PTP_NW_PROT_BIT_IEEE_802_3,
+ PTP_NW_PROT_BIT_DEVICE_NET,
+ PTP_NW_PROT_BIT_CONTROL_NET,
+ PTP_NW_PROT_BIT_PROFINET,
+ N_PTP_NW_PROT
+};
+
+#define PTP_NW_PROT_MSK_RESERVED ( 1UL << PTP_NW_PROT_BIT_RESERVED )
+#define PTP_NW_PROT_MSK_UDP_IPV4 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV4 )
+#define PTP_NW_PROT_MSK_UDP_IPV6 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV6 )
+#define PTP_NW_PROT_MSK_IEEE_802_3 ( 1UL << PTP_NW_PROT_BIT_IEEE_802_3 )
+#define PTP_NW_PROT_MSK_DEVICE_NET ( 1UL << PTP_NW_PROT_BIT_DEVICE_NET )
+#define PTP_NW_PROT_MSK_CONTROL_NET ( 1UL << PTP_NW_PROT_BIT_CONTROL_NET )
+#define PTP_NW_PROT_MSK_PROFINET ( 1UL << PTP_NW_PROT_BIT_PROFINET )
+
+#if !defined( DEFAULT_PTP_NW_PROT_MASK )
+ #define DEFAULT_PTP_NW_PROT_MASK ( PTP_NW_PROT_MSK_UDP_IPV4 | PTP_NW_PROT_MSK_IEEE_802_3 )
+#endif
+
+#define PTP_NW_PROT_STRS \
+{ \
+ "Reserved", \
+ "UDP/IPv4", \
+ "UDP/IPv6", \
+ "IEEE 802.3", \
+ "DeviceNet", \
+ "ControlNet", \
+ "PROFINET" \
+}
+
+
+#define PTP_NW_PROT_STRS_SHORT \
+{ \
+ "RES", \
+ "IP4", \
+ "IP6", \
+ "ETH", \
+ "DN", \
+ "CN", \
+ "PN" \
+}
+
+enum
+{
+ PTP_PORT_STATE_UNINITIALIZED,
+ PTP_PORT_STATE_INITIALIZING,
+ PTP_PORT_STATE_FAULTY,
+ PTP_PORT_STATE_DISABLED,
+ PTP_PORT_STATE_LISTENING,
+ PTP_PORT_STATE_PRE_MASTER,
+ PTP_PORT_STATE_MASTER,
+ PTP_PORT_STATE_PASSIVE,
+ PTP_PORT_STATE_UNCALIBRATED,
+ PTP_PORT_STATE_SLAVE,
+ N_PTP_PORT_STATE
+};
+
+#define PTP_PORT_STATE_STRS \
+{ \
+ "UNINITIALIZED", \
+ "INITIALIZING", \
+ "FAULTY", \
+ "DISABLED", \
+ "LISTENING", \
+ "PRE_MASTER", \
+ "MASTER", \
+ "PASSIVE", \
+ "UNCALIBRATED", \
+ "SLAVE" \
+}
+
+
+typedef struct
+{
+ uint8_t value;
+ const char *name;
+} PTP_TABLE;
+
+
+enum
+{
+ PTP_DELAY_MECH_BIT_E2E, // in PTP2 specs: 0x01
+ PTP_DELAY_MECH_BIT_P2P, // in PTP2 specs: 0x02
+ N_PTP_DELAY_MECH // additionally the specs define 0xFE for disabled
+};
+
+#define PTP_DELAY_MECH_MSK_E2E ( 1UL << PTP_DELAY_MECH_BIT_E2E )
+#define PTP_DELAY_MECH_MSK_P2P ( 1UL << PTP_DELAY_MECH_BIT_P2P )
+
+#if !defined( DEFAULT_PTP_DELAY_MECH_MASK )
+ #define DEFAULT_PTP_DELAY_MECH_MASK ( PTP_DELAY_MECH_MSK_E2E | PTP_DELAY_MECH_MSK_P2P )
+#endif
+
+#define PTP_DELAY_MECH_NAMES \
+{ \
+ "E2E", \
+ "P2P" \
+}
+
+
+
+#define PTP_CLOCK_ACCURACY_RESERVED_OFFSET 0x20
+
+enum
+{
+ PTP_CLOCK_ACCURACY_25ns = PTP_CLOCK_ACCURACY_RESERVED_OFFSET,
+ PTP_CLOCK_ACCURACY_100ns,
+ PTP_CLOCK_ACCURACY_250ns,
+ PTP_CLOCK_ACCURACY_1us,
+ PTP_CLOCK_ACCURACY_2_5us,
+ PTP_CLOCK_ACCURACY_10us,
+ PTP_CLOCK_ACCURACY_25us,
+ PTP_CLOCK_ACCURACY_100us,
+ PTP_CLOCK_ACCURACY_250us,
+ PTP_CLOCK_ACCURACY_1ms,
+ PTP_CLOCK_ACCURACY_2_5ms,
+ PTP_CLOCK_ACCURACY_10ms,
+ PTP_CLOCK_ACCURACY_25ms,
+ PTP_CLOCK_ACCURACY_100ms,
+ PTP_CLOCK_ACCURACY_250ms,
+ PTP_CLOCK_ACCURACY_1s,
+ PTP_CLOCK_ACCURACY_10s,
+ PTP_CLOCK_ACCURACY_MORE_10s,
+ PTP_CLOCK_ACCURACY_RESERVED_1,
+ PTP_CLOCK_ACCURACY_RESERVED_2,
+ PTP_CLOCK_ACCURACY_RESERVED_3,
+ PTP_CLOCK_ACCURACY_RESERVED_4,
+ N_PTP_CLOCK_ACCURACY
+};
+
+
+// Attention: Substract offset of PTP_CLOCK_ACCURACY_RESERVED_OFFSET when
+// using the enum above as index for the initializer below!
+#define PTP_CLOCK_ACCURACY_STRS \
+{ \
+ "< 25 ns", \
+ "< 100 ns", \
+ "< 250 ns", \
+ "< 1 us", \
+ "< 2.5 us", \
+ "< 10 us", \
+ "< 25 us", \
+ "< 100 us", \
+ "< 250 us", \
+ "< 1 ms", \
+ "< 2.5 ms", \
+ "< 10 ms", \
+ "< 25 ms", \
+ "< 100 ms", \
+ "< 250 ms", \
+ "< 1 s", \
+ "< 10 s", \
+ "more than 10 s", \
+ "reserved_1", \
+ "reserved_2", \
+ "reserved_3", \
+ "reserved_4" \
+}
+
+
+
+#define PTP_TIME_SOURCE_ATOMIC_CLOCK 0x10
+#define PTP_TIME_SOURCE_GPS 0x20
+#define PTP_TIME_SOURCE_TERRESTRIAL_RADIO 0x30
+#define PTP_TIME_SOURCE_PTP 0x40
+#define PTP_TIME_SOURCE_NTP 0x50
+#define PTP_TIME_SOURCE_HAND_SET 0x60
+#define PTP_TIME_SOURCE_OTHER 0x90
+#define PTP_TIME_SOURCE_INTERNAL_OSCILLATOR 0xA0
+
+
+
+#define PTP_TIME_SOURCE_TABLE \
+{ \
+ { PTP_TIME_SOURCE_ATOMIC_CLOCK, "Atomic Clock" }, \
+ { PTP_TIME_SOURCE_GPS, "GPS" }, \
+ { PTP_TIME_SOURCE_TERRESTRIAL_RADIO, "Terrestrial Radio" }, \
+ { PTP_TIME_SOURCE_PTP, "PTP" }, \
+ { PTP_TIME_SOURCE_NTP, "NTP" }, \
+ { PTP_TIME_SOURCE_HAND_SET, "HAND SET" }, \
+ { PTP_TIME_SOURCE_OTHER, "OTHER" }, \
+ { PTP_TIME_SOURCE_INTERNAL_OSCILLATOR, "Internal Oscillator" }, \
+ { 0, NULL } \
+}
+
+
+
+enum
+{
+ PTP_ROLE_MULTICAST_SLAVE,
+ PTP_ROLE_UNICAST_SLAVE,
+ PTP_ROLE_MULTICAST_MASTER,
+ PTP_ROLE_UNICAST_MASTER,
+ N_PTP_ROLES
+};
+
+
+#define PTP_ROLE_STRS \
+{ \
+ "Multicast Slave", \
+ "Unicast Slave", \
+ "Multicast Master", \
+ "Unicast Master" \
+}
+
+
+
+/* PTP configuration stuff */
+
+typedef struct
+{
+ uint8_t b[8];
+} PTP_CLOCK_IDENTITY;
+
+#define _mbg_swab_ptp_clock_identity( _p ) _nop_macro_fnc() // nothing to swap
+
+
+
+typedef struct
+{
+ uint16_t network_protocol; // enum
+ uint8_t ptp_proto_version; // PTP v1 or v2
+ uint8_t port_state; // enum
+ uint32_t flags;
+ NANO_TIME offset;
+ NANO_TIME path_delay;
+ NANO_TIME mean_path_delay;
+ NANO_TIME delay_asymmetry;
+
+ PTP_CLOCK_IDENTITY gm_identity;
+
+ uint16_t clock_offset_scaled_log_variance;
+ uint8_t clock_class;
+ uint8_t clock_accuracy; // enum
+
+ uint32_t reserved_1;
+ uint32_t reserved_2;
+
+ uint8_t domain_number;
+ uint8_t time_source; // enum
+ uint8_t delay_mech;
+ int8_t log_delay_req_intv;
+
+ int16_t utc_offset;
+ DAC_VAL osc_dac_cal;
+
+ uint32_t reserved_3;
+} PTP_STATE;
+
+#define _mbg_swab_ptp_state( _p ) \
+{ \
+ _mbg_swab16( &(_p)->network_protocol ); \
+ _mbg_swab32( &(_p)->flags ); \
+ _mbg_swab_nano_time( &(_p)->offset ); \
+ _mbg_swab_nano_time( &(_p)->path_delay ); \
+ _mbg_swab_nano_time( &(_p)->mean_path_delay ); \
+ _mbg_swab_nano_time( &(_p)->delay_asymmetry ); \
+ _mbg_swab_ptp_clock_identity( &(_p)->gm_identity ); \
+ _mbg_swab16( &(_p)->clock_offset_scaled_log_variance ); \
+ _mbg_swab32( &(_p)->num_clients ); \
+ _mbg_swab32( &(_p)->num_masters ); \
+ _mbg_swab32( &(_p)->utc_offset ); \
+ _mbg_swab_dac_val( &(_p)->osc_dac_cal ); \
+}
+
+
+enum
+{
+ PTP_FLAG_BIT_SLAVE_ONLY,
+ PTP_FLAG_BIT_IS_SLAVE,
+ PTP_FLAG_BIT_TIMESCALE_IS_PTP,
+ PTP_FLAG_BIT_LS_ANN,
+ PTP_FLAG_BIT_LS_ANN_NEG,
+ PTP_FLAG_BIT_IS_UNICAST,
+ N_PTP_FLAG_BIT
+};
+
+#define PTP_FLAG_MSK_SLAVE_ONLY ( 1UL << PTP_FLAG_BIT_SLAVE_ONLY )
+#define PTP_FLAG_MSK_IS_SLAVE ( 1UL << PTP_FLAG_BIT_IS_SLAVE )
+#define PTP_FLAG_MSK_TIMESCALE_IS_PTP ( 1UL << PTP_FLAG_BIT_TIMESCALE_IS_PTP )
+#define PTP_FLAG_MSK_LS_ANN ( 1UL << PTP_FLAG_BIT_LS_ANN )
+#define PTP_FLAG_MSK_LS_ANN_NEG ( 1UL << PTP_FLAG_BIT_LS_ANN_NEG )
+#define PTP_FLAG_MSK_IS_UNICAST ( 1UL << PTP_FLAG_BIT_IS_UNICAST )
+
+
+#define PTP_SYNC_INTERVAL_MIN -6
+#define PTP_SYNC_INTERVAL_MAX 6
+
+#define PTP_DELAY_REQ_INTERVAL_MIN -6
+#define PTP_DELAY_REQ_INTERVAL_MAX 6
+
+#define PTP_DEFAULT_UNICAST_SYNC_INTERVAL_MIN -4
+#define PTP_DEFAULT_UNICAST_SYNC_INTERVAL_MAX 4
+
+#define PTP_DEFAULT_UNICAST_DELAY_REQ_INTERVAL_MIN -4
+#define PTP_DEFAULT_UNICAST_DELAY_REQ_INTERVAL_MAX 4
+
+#define PTP_DEFAULT_UNICAST_ANNOUNCE_INTERVAL_MIN -4
+#define PTP_DEFAULT_UNICAST_ANNOUNCE_INTERVAL_MAX 4
+
+
+typedef struct
+{
+ uint16_t network_protocol; // enum, only 1 or 3
+ uint8_t profile; // currently only 0 = default
+ uint8_t domain_number; // 0:3
+
+ uint8_t delay_mechanism; // 0 (E2E) or 1 (P2P), unless disabled
+ uint8_t ptp_role; // MC_SLAVE/UC_SLAVE/MC_Master/UC_MASTER as defined in enum above
+ uint8_t priority_1;
+ uint8_t priority_2;
+
+ uint8_t dflt_clk_class_unsync_cold; // 6:255
+ uint8_t dflt_clk_class_unsync_warm; // 6:255
+ uint8_t dflt_clk_class_sync_cold; // 6:255
+ uint8_t dflt_clk_class_sync_warm; // 6:255
+
+ uint8_t reserved_1; // currently always 0
+ uint8_t reserved_2; // currently always 0
+ int16_t sync_interval; // log 2
+
+ int16_t announce_interval; // log 2
+ int16_t delay_request_interval; // log 2
+
+ uint32_t upper_bound; // [ns] sync state set to false if above this limit
+ uint32_t lower_bound; // [ns] sync state set to true if below this limit
+
+ uint32_t reserved_3; // currently always 0
+ uint32_t flags; // (see below)
+
+} PTP_CFG_SETTINGS;
+
+#define _mbg_swab_ptp_cfg_settings( _p ) \
+{ \
+ _mbg_swab16( &(_p)->network_protocol ); \
+ _mbg_swab16( &(_p)->sync_interval ); \
+ _mbg_swab16( &(_p)->announce_interval ); \
+ _mbg_swab16( &(_p)->delay_request_interval ); \
+ _mbg_swab32( &(_p)->upper_bound ); \
+ _mbg_swab32( &(_p)->lower_bound ); \
+ _mbg_swab32( &(_p)->reserved_1 ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+typedef struct
+{
+ PTP_CFG_SETTINGS settings;
+
+ uint8_t ptp_proto_version; // PTP v1 or v2
+ uint8_t reserved_1; // currently always 0
+ uint16_t reserved_2; // currently always 0
+
+ int16_t sync_interval_min; // log 2
+ int16_t sync_interval_max; // log 2
+ int16_t announce_interval_min; // log 2
+ int16_t announce_interval_max; // log 2
+ int16_t delay_request_interval_min; // log 2
+ int16_t delay_request_interval_max; // log 2
+
+ uint32_t supported_flags; // (see below)
+ uint32_t supported_network_protocols;
+ uint32_t supported_profiles;
+ uint32_t supported_delay_mechanisms;
+
+} PTP_CFG_INFO;
+
+#define _mbg_swab_ptp_cfg_info( _p ) \
+{ \
+ _mbg_swab_ptp_cfg_settings( &(_p)->settings ); \
+ _mbg_swab16( &(_p)->sync_interval_min ); \
+ _mbg_swab16( &(_p)->sync_interval_max ); \
+ _mbg_swab16( &(_p)->announce_interval_min ); \
+ _mbg_swab16( &(_p)->announce_interval_max ); \
+ _mbg_swab16( &(_p)->delay_request_interval_min ); \
+ _mbg_swab16( &(_p)->delay_request_interval_max ); \
+ _mbg_swab32( &(_p)->supported_flags ); \
+ _mbg_swab32( &(_p)->supported_profiles ); \
+ _mbg_swab32( &(_p)->supported_delay_mechanisms ); \
+}
+
+
+
+// flags used with PTP_CFG_SETTINGS::flags and PTP_CFG_INFO::supported_flags:
+// possibly also: can be master (i.e not slave only), v1 hw compat, ...
+enum
+{
+ PTP_CFG_BIT_TIME_SCALE_IS_PTP, // time scale is PTP/TAI, else arbitrary
+ PTP_CFG_BIT_V1_HW_COMPAT,
+ PTP_CFG_BIT_CAN_BE_UNICAST_SLAVE,
+ PTP_CFG_BIT_CAN_BE_MULTICAST_MASTER,
+ PTP_CFG_BIT_CAN_BE_UNICAST_MASTER
+};
+
+#define PTP_CFG_MSK_TIME_SCALE_IS_PTP ( 1UL << PTP_CFG_BIT_TIME_SCALE_IS_PTP )
+#define PTP_CFG_MSK_V1_HW_COMPAT ( 1UL << PTP_CFG_BIT_V1_HW_COMPAT )
+#define PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE ( 1UL << PTP_CFG_BIT_CAN_BE_UNICAST_SLAVE )
+#define PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER ( 1UL << PTP_CFG_BIT_CAN_BE_MULTICAST_MASTER )
+#define PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ( 1UL << PTP_CFG_BIT_CAN_BE_UNICAST_MASTER )
+
+
+#define PTP_CFG_MSK_SUPPORT_PTP_ROLES ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \
+ PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER | \
+ PTP_CFG_MSK_CAN_BE_UNICAST_MASTER )
+
+#define PTP_CFG_MSK_SUPPORT_PTP_UNICAST ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \
+ PTP_CFG_MSK_CAN_BE_UNICAST_MASTER )
+
+
+// Set Multicast as default
+#define _get_supp_ptp_roles( _r ) ((((_r) & ~3UL) >> PTP_CFG_BIT_V1_HW_COMPAT ) | 1UL)
+
+// The MBG_HOSTNAME type can hold a host's fully qualified domain name (FQDN),
+// or the ASCII string of a numeric IP address.
+// In theory each single component (host name, domain name, top level domain name)
+// of a FQDN can have up to 63 characters, but the overall length is limited to
+// 255 characters. We specify one more character for the trailing 0.
+typedef char MBG_HOSTNAME[256];
+
+typedef struct
+{
+ MBG_HOSTNAME gm_host; /**< grandmaster's hostname or IP address */
+ PTP_CLOCK_IDENTITY gm_clock_id; /**< use clock ID of master port, or FF:FF:FF:FF:FF:FF:FF:FF as wildcard */
+ uint16_t gm_port_id; /**< use target port ID of master port (e.g. '1') or 0xFFFF as wildcard */
+ int16_t sync_interval; /**< log 2 */
+ int16_t announce_interval; /**< log 2 */
+ int16_t delay_request_interval; /**< log 2 */
+ uint16_t message_duration; /**< time period until master stops sending the messages */
+ uint16_t reserved;
+ uint32_t flags;
+
+} PTP_UNICAST_CFG_SETTINGS;
+
+#define _mbg_swab_ptp_unicast_cfg_settings( _p ) \
+{ \
+ _mbg_swab_ptp_clock_identity( &(_p)->gm_clock_id ); \
+ _mbg_swab16( &(_p)->gm_port_id ); \
+ _mbg_swab16( &(_p)->sync_interval ); \
+ _mbg_swab16( &(_p)->announce_interval ); \
+ _mbg_swab16( &(_p)->delay_request_interval ); \
+ _mbg_swab16( &(_p)->message_duration ); \
+ _mbg_swab16( &(_p)->reserved ); \
+ _mbg_swab32( &(_p)->flags ); \
+}
+
+
+
+typedef struct
+{
+ PTP_UNICAST_CFG_SETTINGS settings;
+
+ int16_t sync_interval_min; // log 2
+ int16_t sync_interval_max; // log 2
+ int16_t announce_interval_min; // log 2
+ int16_t announce_interval_max; // log 2
+ int16_t delay_request_interval_min; // log 2
+ int16_t delay_request_interval_max; // log 2
+
+ uint32_t supported_flags;
+ uint32_t reserved;
+
+} PTP_UNICAST_CFG_INFO;
+
+#define _mbg_swab_ptp_unicast_cfg_info( _p ) \
+{ \
+ _mbg_swab_ptp_unicast_cfg_settings( &(_p)->settings ); \
+ _mbg_swab16( &(_p)->sync_interval_min ); \
+ _mbg_swab16( &(_p)->sync_interval_max ); \
+ _mbg_swab16( &(_p)->announce_interval_min ); \
+ _mbg_swab16( &(_p)->announce_interval_max ); \
+ _mbg_swab16( &(_p)->delay_request_interval_min ); \
+ _mbg_swab16( &(_p)->delay_request_interval_max ); \
+ _mbg_swab32( &(_p)->supported_flags ); \
+ _mbg_swab32( &(_p)->reserved ); \
+}
+
+
+
+/*------------------------------------------------------------------------*/
+
+/* Ephemeris parameters of one specific SV. Needed to compute the position */
+/* of a satellite at a given time with high precision. Valid for an */
+/* interval of 4 to 6 hours from start of transmission. */
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ HEALTH health; /* health indication of transmitting SV [---] */
+ IOD IODC; /* Issue Of Data, Clock */
+ IOD IODE2; /* Issue of Data, Ephemeris (Subframe 2) */
+ IOD IODE3; /* Issue of Data, Ephemeris (Subframe 3) */
+ T_GPS tt; /* time of transmission */
+ T_GPS t0c; /* Reference Time Clock [---] */
+ T_GPS t0e; /* Reference Time Ephemeris [---] */
+
+ double sqrt_A; /* Square Root of semi-major Axis [sqrt(m)] */
+ double e; /* Eccentricity [---] */
+ double M0; /* +- Mean Anomaly at Ref. Time [rad] */
+ double omega; /* +- Argument of Perigee [rad] */
+ double OMEGA0; /* +- Longit. of Asc. Node of orbit plane [rad] */
+ double OMEGADOT; /* +- Rate of Right Ascension [rad/sec] */
+ double deltan; /* +- Mean Motion Diff. from computed value [rad/sec] */
+ double i0; /* +- Inclination Angle [rad] */
+ double idot; /* +- Rate of Inclination Angle [rad/sec] */
+ double crc; /* +- Cosine Corr. Term to Orbit Radius [m] */
+ double crs; /* +- Sine Corr. Term to Orbit Radius [m] */
+ double cuc; /* +- Cosine Corr. Term to Arg. of Latitude [rad] */
+ double cus; /* +- Sine Corr. Term to Arg. of Latitude [rad] */
+ double cic; /* +- Cosine Corr. Term to Inclination Angle [rad] */
+ double cis; /* +- Sine Corr. Term to Inclination Angle [rad] */
+
+ double af0; /* +- Clock Correction Coefficient 0 [sec] */
+ double af1; /* +- Clock Correction Coefficient 1 [sec/sec] */
+ double af2; /* +- Clock Correction Coefficient 2 [sec/sec^2] */
+ double tgd; /* +- estimated group delay differential [sec] */
+
+ uint16_t URA; /* predicted User Range Accuracy */
+
+ uint8_t L2code; /* code on L2 channel [---] */
+ uint8_t L2flag; /* L2 P data flag [---] */
+} EPH;
+
+
+
+/* Almanac parameters of one specific SV. A reduced precision set of */
+/* parameters used to check if a satellite is in view at a given time. */
+/* Valid for an interval of more than 7 days from start of transmission. */
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ HEALTH health; /* [---] */
+ T_GPS t0a; /* Reference Time Almanac [sec] */
+
+ double sqrt_A; /* Square Root of semi-major Axis [sqrt(m)] */
+ double e; /* Eccentricity [---] */
+
+ double M0; /* +- Mean Anomaly at Ref. Time [rad] */
+ double omega; /* +- Argument of Perigee [rad] */
+ double OMEGA0; /* +- Longit. of Asc. Node of orbit plane [rad] */
+ double OMEGADOT; /* +- Rate of Right Ascension [rad/sec] */
+ double deltai; /* +- [rad] */
+ double af0; /* +- Clock Correction Coefficient 0 [sec] */
+ double af1; /* +- Clock Correction Coefficient 1 [sec/sec] */
+} ALM;
+
+
+
+/* Summary of configuration and health data of all SVs. */
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ T_GPS tot_51; /* time of transmission, page 51 */
+ T_GPS tot_63; /* time of transmission, page 63 */
+ T_GPS t0a; /* complete reference time almanac */
+
+ CFG cfg[N_SVNO]; /* SV configuration from page 63 */
+ HEALTH health[N_SVNO]; /* SV health from pages 51, 63 */
+} CFGH;
+
+
+
+/**
+ @brief GPS UTC correction parameters
+*/
+typedef struct
+{
+ CSUM csum; /**< Checksum of the remaining bytes */
+ int16_t valid; /**< Flag indicating UTC parameters are valid */
+
+ T_GPS t0t; /**< Reference Time UTC Parameters [wn|sec] */
+ double A0; /**< +- Clock Correction Coefficient 0 [sec] */
+ double A1; /**< +- Clock Correction Coefficient 1 [sec/sec] */
+
+ uint16_t WNlsf; /**< Week number of nearest leap second */
+ int16_t DNt; /**< The day number at the end of which a leap second occurs */
+ int8_t delta_tls; /**< Current UTC offset to GPS system time [sec] */
+ int8_t delta_tlsf; /**< Future UTC offset to GPS system time after next leap second transition [sec] */
+} UTC;
+
+#define _mbg_swab_utc_parm( _p ) \
+{ \
+ _mbg_swab_csum( &(_p)->csum ); \
+ _mbg_swab16( &(_p)->valid ); \
+ _mbg_swab_t_gps( &(_p)->t0t ); \
+ _mbg_swab_double( &(_p)->A0 ); \
+ _mbg_swab_double( &(_p)->A1 ); \
+ _mbg_swab16( &(_p)->WNlsf ); \
+ _mbg_swab16( &(_p)->DNt ); \
+}
+
+
+
+/* Ionospheric correction parameters */
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ double alpha_0; /* Ionosph. Corr. Coeff. Alpha 0 [sec] */
+ double alpha_1; /* Ionosph. Corr. Coeff. Alpha 1 [sec/deg] */
+ double alpha_2; /* Ionosph. Corr. Coeff. Alpha 2 [sec/deg^2] */
+ double alpha_3; /* Ionosph. Corr. Coeff. Alpha 3 [sec/deg^3] */
+
+ double beta_0; /* Ionosph. Corr. Coeff. Beta 0 [sec] */
+ double beta_1; /* Ionosph. Corr. Coeff. Beta 1 [sec/deg] */
+ double beta_2; /* Ionosph. Corr. Coeff. Beta 2 [sec/deg^2] */
+ double beta_3; /* Ionosph. Corr. Coeff. Beta 3 [sec/deg^3] */
+} IONO;
+
+
+
+/* GPS ASCII message */
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+ char s[23]; /* 22 chars GPS ASCII message plus trailing zero */
+} ASCII_MSG;
+
+
+
+enum
+{
+ GPS_PLATFORM_PORTABLE,
+ GPS_PLATFORM_FIXED,
+ GPS_PLATFORM_STATIONARY,
+ GPS_PLATFORM_PEDESTRIAN,
+ GPS_PLATFORM_AUTOMOTIVE,
+ GPS_PLATFORM_SEA,
+ GPS_PLATFORM_AIRBORNE_1G,
+ GPS_PLATFORM_AIRBORNE_2G,
+ GPS_PLATFORM_AIRBORNE_4G,
+ N_GPS_PLATFORMS
+};
+
+
+#define GPS_PLATFORM_STRS \
+{ \
+ "Portable ", \
+ "Fixed ", \
+ "Stationary ", \
+ "Pedestrian ", \
+ "Automotive ", \
+ "Sea ", \
+ "Airborne <1G", \
+ "Airborne <2G", \
+ "Airborne <4G" \
+}
+
+
+
+enum
+{
+ TIME_MODE_DISABLED,
+ TIME_MODE_SURVEY_IN,
+ TIME_MODE_FIXED
+};
+
+
+
+typedef struct
+{
+ uint32_t time_mode;
+ uint32_t survey_in_duration;
+ uint32_t survey_in_pos_var;
+ int32_t fixedPosX; // cm
+ int32_t fixedPosY; // cm
+ int32_t fixedPosZ; // cm
+ uint32_t fixedPosVar; // cm
+ uint32_t flags; // currently 0
+ uint32_t reserved; // currently 0
+} NAV_TIME_MODE_SETTINGS;
+
+
+/**
+ Navigation Engine settings to set configuration
+ parameters of a dynamic platform model.
+*/
+typedef struct
+{
+ uint8_t dynamic_platform;
+ uint8_t fix_mode;
+ int8_t min_elevation;
+ uint8_t static_hold_threshold;
+ int32_t fixed_altitude;
+ uint32_t fixed_altitude_variance;
+ uint32_t flags; // currently 0
+ uint32_t reserved; // currently 0
+ NAV_TIME_MODE_SETTINGS nav_time_mode_settings;
+} NAV_ENGINE_SETTINGS;
+
+
+/* End of header body */
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+
+#endif /* _GPSDEFS_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c
new file mode 100755
index 0000000..f493af9
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c
@@ -0,0 +1,194 @@
+
+/**************************************************************************
+ *
+ * $Id: gpsutils.c 1.4.1.3 2010/07/15 13:33:43 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Utility functions useful with GPS data.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: gpsutils.c $
+ * Revision 1.4.1.3 2010/07/15 13:33:43 martin
+ * Use DEG character definition from pcpslstr.h.
+ * Revision 1.4.1.2 2004/11/09 14:42:36Z martin
+ * Use C99 fixed-size types in swap_double().
+ * Revision 1.4.1.1 2003/05/16 08:36:27 MARTIN
+ * Fixed sprint_dms() to work correctly under QNX.
+ * Revision 1.4 2003/01/31 13:45:19 MARTIN
+ * sprint_pos_geo() returns N/A if position not valid.
+ * Revision 1.3 2002/12/12 16:07:04 martin
+ * New functions swap_pos_doubles(), sprint_dms(),
+ * and sprint_pos_geo().
+ * Revision 1.2 2001/02/05 09:39:12Z MARTIN
+ * New file header.
+ * Change include file name to lower case.
+ * Source code cleanup.
+ *
+ **************************************************************************/
+
+#define _GPSUTILS
+ #include <gpsutils.h>
+#undef _GPSUTILS
+
+#include <pcpslstr.h>
+
+#include <stdio.h>
+#include <string.h>
+
+
+
+#define _eos( _s ) ( &(_s)[strlen( _s )] )
+
+
+/*HDR*/
+void swap_double( double *d )
+{
+ uint16_t *wp1;
+ uint16_t *wp2;
+ uint16_t w;
+ int i;
+
+ wp1 = (uint16_t *) d;
+ wp2 = ( (uint16_t *) d ) + 3;
+
+ for ( i = 0; i < 2; i++ )
+ {
+ w = *wp1;
+ *wp1 = *wp2;
+ *wp2 = w;
+ wp1++;
+ wp2--;
+ }
+
+} /* swap_double */
+
+
+
+/*HDR*/
+void swap_eph_doubles( EPH *ephp )
+{
+ swap_double( &ephp->sqrt_A );
+ swap_double( &ephp->e );
+ swap_double( &ephp->M0 );
+ swap_double( &ephp->omega );
+ swap_double( &ephp->i0 );
+ swap_double( &ephp->OMEGA0 );
+ swap_double( &ephp->OMEGADOT );
+
+ swap_double( &ephp->deltan );
+ swap_double( &ephp->idot );
+
+ swap_double( &ephp->crc );
+ swap_double( &ephp->crs );
+ swap_double( &ephp->cuc );
+ swap_double( &ephp->cus );
+ swap_double( &ephp->cic );
+ swap_double( &ephp->cis );
+
+ swap_double( &ephp->af0 );
+ swap_double( &ephp->af1 );
+ swap_double( &ephp->af2 );
+
+ swap_double( &ephp->tgd );
+
+} /* swap_eph_doubles */
+
+
+
+/*HDR*/
+void swap_alm_doubles( ALM *almp )
+{
+ swap_double( &almp->sqrt_A );
+ swap_double( &almp->e );
+ swap_double( &almp->deltai );
+ swap_double( &almp->OMEGA0 );
+ swap_double( &almp->OMEGADOT );
+ swap_double( &almp->omega );
+ swap_double( &almp->M0 );
+ swap_double( &almp->af0 );
+ swap_double( &almp->af1 );
+
+} /* swap_alm_doubles */
+
+
+
+/*HDR*/
+void swap_utc_doubles( UTC *utcp )
+{
+ swap_double( &utcp->A0 );
+ swap_double( &utcp->A1 );
+
+} /* swap_utc_doubles */
+
+
+
+/*HDR*/
+void swap_iono_doubles( IONO *ionop )
+{
+ swap_double( &ionop->alpha_0 );
+ swap_double( &ionop->alpha_1 );
+ swap_double( &ionop->alpha_2 );
+ swap_double( &ionop->alpha_3 );
+
+ swap_double( &ionop->beta_0 );
+ swap_double( &ionop->beta_1 );
+ swap_double( &ionop->beta_2 );
+ swap_double( &ionop->beta_3 );
+
+} /* swap_iono_doubles */
+
+
+
+/*HDR*/
+void swap_pos_doubles( POS *posp )
+{
+ int i;
+
+ for ( i = 0; i < N_XYZ; i++ )
+ swap_double( &posp->xyz[i] );
+
+ for ( i = 0; i < N_LLA; i++ )
+ swap_double( &posp->lla[i] );
+
+ swap_double( &posp->longitude.sec );
+ swap_double( &posp->latitude.sec );
+
+} /* swap_pos_doubles */
+
+
+
+/*HDR*/
+void sprint_dms( char *s, DMS *pdms, int prec )
+{
+ sprintf( s, "%c %i" DEG "%02i'%02.*f\"",
+ pdms->prefix,
+ pdms->deg,
+ pdms->min,
+ prec,
+ pdms->sec
+ );
+
+} /* sprint_dms */
+
+
+
+/*HDR*/
+void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec )
+{
+ if ( ppos->lla[LON] && ppos->lla[LAT] && ppos->lla[ALT] )
+ {
+ sprint_dms( s, &ppos->latitude, prec );
+ strcat( s, sep );
+ sprint_dms( _eos( s ), &ppos->longitude, prec );
+ strcat( s, sep );
+ sprintf( _eos( s ), "%.0fm", ppos->lla[ALT] );
+ }
+ else
+ strcpy( s, "N/A" );
+
+} /* sprint_pos_geo */
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h
new file mode 100755
index 0000000..8716adf
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h
@@ -0,0 +1,80 @@
+
+/**************************************************************************
+ *
+ * $Id: gpsutils.h 1.4.1.2 2010/07/15 09:19:04 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for gpsutils.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: gpsutils.h $
+ * Revision 1.4.1.2 2010/07/15 09:19:04 martin
+ * Use DEG character definition from pcpslstr.h.
+ * Revision 1.4.1.1 2003/05/15 09:40:25Z martin
+ * Changed degree string/char for QNX.
+ * Revision 1.4 2002/12/12 16:08:11 martin
+ * Definitions for degree character.
+ * Requires mbggeo.h.
+ * Updated function prototypes.
+ * Revision 1.3 2001/02/05 09:40:42Z MARTIN
+ * New file header.
+ * Source code cleanup.
+ *
+ **************************************************************************/
+
+#ifndef _GPSUTILS_H
+#define _GPSUTILS_H
+
+
+/* Other headers to be included */
+
+#include <mbggeo.h>
+
+
+#ifdef _GPSUTILS
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void swap_double( double *d ) ;
+ void swap_eph_doubles( EPH *ephp ) ;
+ void swap_alm_doubles( ALM *almp ) ;
+ void swap_utc_doubles( UTC *utcp ) ;
+ void swap_iono_doubles( IONO *ionop ) ;
+ void swap_pos_doubles( POS *posp ) ;
+ void sprint_dms( char *s, DMS *pdms, int prec ) ;
+ void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _GPSUTILS_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/identdec.c b/src/external/bsd/meinberg/dist/mbglib/common/identdec.c
new file mode 100755
index 0000000..cab5d97
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/identdec.c
@@ -0,0 +1,164 @@
+
+/**************************************************************************
+ *
+ * $Id: identdec.c 1.3 2009/04/01 14:15:05 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Supplies a function to decode various types of a GPS receiver's
+ * IDENT structure and generate a group code + S/N string.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: identdec.c $
+ * Revision 1.3 2009/04/01 14:15:05 martin
+ * Fixed compiler warning.
+ * Revision 1.2 2002/11/21 08:11:59Z martin
+ * Avoid usage of strcpy functions since they may not
+ * be available in kernel space for some targets.
+ * Revision 1.1 2002/02/19 13:46:19 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _IDENTDEC
+ #include <identdec.h>
+#undef _IDENTDEC
+
+#include <qsdefs.h>
+
+
+// Some targets don't support isdigit() from ctype.h:
+#define _is_digit( _c ) ( (_c) >= '0' && (_c) <= '9' )
+
+
+// Some targets are unable to call functions from the
+// stancard C library, so we provide necessary functions locally.
+
+static /*HDR*/
+char *do_strnpcpy( char *p_dst, const char *p_src, int n )
+{
+ int i;
+
+ for ( i = 0; i < n; i++ )
+ {
+ char c = *p_src++;
+ *p_dst++ = c;
+
+ if ( c == 0 )
+ break;
+ }
+
+ return p_dst;
+
+} // do_strnpcpy
+
+
+
+/*--------------------------------------------------------------
+ * Name: mbg_gps_ident_decode()
+ *
+ * Purpose: Convert a GPS ident code to a string with
+ * serial number.
+ *
+ * Input: p_id pointer to the IDENT
+ *
+ * Output: s the resulting string
+ *
+ * Ret value: --
+ *+-------------------------------------------------------------*/
+
+/*HDR*/
+char *mbg_gps_ident_swap( char *p_dst, const char *p_src )
+{
+ int i;
+
+ for ( i = 0; i < 4; i++ )
+ {
+ *p_dst++ = *( p_src + 3 );
+ *p_dst++ = *( p_src + 2 );
+ *p_dst++ = *( p_src + 1 );
+ *p_dst++ = *( p_src );
+ p_src += 4;
+ }
+
+ return( p_dst );
+
+} // mbg_gps_ident_swap
+
+
+
+/*HDR*/
+void mbg_gps_ident_decode( char *s, const IDENT *p_id )
+{
+ char ws[sizeof( *p_id ) + 1]; // tmp buffer
+ char *cp;
+ char c = 0;
+ int n_spaces = 0;
+ int i;
+
+ // get string from binary format used by firmware
+ mbg_gps_ident_swap( ws, (const char *) p_id );
+
+ // make sure the resulting string is terminated by 0
+ ws[sizeof( *p_id )] = 0;
+
+ // Now ws contains a raw string which may be in one
+ // of the following formats. The first one, which includes
+ // a group code is the preferred format:
+ //
+ // "gggg nnnnnnnn" group code, gap filled with spaces, S/N
+ // "nnnnnnnn........" S/N, plus non-digits
+ // "........nnnnnnnn" non-digits, followed by S/N
+
+ cp = ws;
+
+ // test for the number of digits at the beginning
+ for ( i = 0; i < MBG_SERNUM_LEN; i++ )
+ {
+ c = *cp++;
+
+ if ( !_is_digit( c ) )
+ break;
+ }
+
+ if ( i != MBG_GRP_CODE_LEN )
+ goto copy; // not a group code
+
+
+ // expect a number of spaces
+ n_spaces = sizeof( *p_id ) - MBG_GRP_SERNUM_LEN;
+
+ for ( i = 0; i < n_spaces; i++ )
+ {
+ if ( c != ' ' )
+ {
+ n_spaces = 0;
+ goto copy;
+ }
+
+ c = *cp++;
+ }
+
+
+ // test number of S/N digits
+ for ( i = 0; i < MBG_SERNUM_LEN; i++ )
+ {
+ if ( !_is_digit( c ) )
+ {
+ n_spaces = 0;
+ goto copy;
+ }
+
+ c = *cp++;
+ }
+
+copy:
+ cp = do_strnpcpy( s, ws, MBG_GRP_CODE_LEN );
+ i = MBG_GRP_CODE_LEN + n_spaces;
+ do_strnpcpy( cp, &ws[i], sizeof( ws ) - i );
+
+} // mbg_gps_ident_decode
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/identdec.h b/src/external/bsd/meinberg/dist/mbglib/common/identdec.h
new file mode 100755
index 0000000..6054ec7
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/identdec.h
@@ -0,0 +1,67 @@
+
+/**************************************************************************
+ *
+ * $Id: identdec.h 1.1 2002/02/19 13:46:19 MARTIN REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for identdec.h.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: identdec.h $
+ * Revision 1.1 2002/02/19 13:46:19 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _IDENTDEC_H
+#define _IDENTDEC_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+
+
+#ifdef _IDENTDEC
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ char *mbg_gps_ident_swap( char *p_dst, const char *p_src ) ;
+ void mbg_gps_ident_decode( char *s, const IDENT *p_id ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _IDENTDEC_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h b/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h
new file mode 100755
index 0000000..fb85639
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h
@@ -0,0 +1,1882 @@
+
+/**************************************************************************
+ *
+ * $Id: macioctl.h 1.33.1.13 2011/03/23 16:50:30 martin TRASH martin $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Macros used inside the IOCTL handlers of device drivers
+ * for Meinberg radio clocks.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: macioctl.h $
+ * Revision 1.33.1.13 2011/03/23 16:50:30 martin
+ * Support NetBSD beside FreeBSD.
+ * Revision 1.33.1.12 2011/03/21 16:25:23 martin
+ * Account for modified _pcpc_kfree().
+ * Revision 1.33.1.11 2011/03/02 09:59:50 daniel
+ * Bug fix: Use PCPS_TIME_STAMP with
+ * IOCTL_GET_FAST_HR_TIMESTAMP as output size.
+ * Revision 1.33.1.10 2011/02/15 14:50:39Z martin
+ * In a call to retrieve RECEIVER_INFO don't read from device
+ * but just copy the field from the device info structure.
+ * Revision 1.33.1.9 2011/02/15 11:08:33 daniel
+ * Preliminary support for PTP unicast
+ * Revision 1.33.1.8 2011/02/09 17:08:27Z martin
+ * Specify I/O range number when calling port I/O macros
+ * so they can be used for different ranges under BSD.
+ * Revision 1.33.1.7 2011/01/26 16:37:55 martin
+ * Modified inline declarations for gcc.
+ * Revision 1.33.1.6 2011/01/24 17:08:40 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.33.1.5 2010/11/09 10:57:33 martin
+ * Added _sem_inc_safe_no_irp() macro (Windows only).
+ * Revision 1.33.1.4 2010/07/16 08:31:32Z martin
+ * Revision 1.33.1.3 2010/07/15 15:47:07 martin
+ * Revision 1.33.1.2 2010/07/14 14:48:52 martin
+ * Simplified code and renamed some inline functions.
+ * Revision 1.33.1.1 2010/03/03 15:11:51 martin
+ * Fixed macro.
+ * Revision 1.33 2009/12/21 16:22:55 martin
+ * Moved code reading memory mapped timestamps to inline functions.
+ * Revision 1.32 2009/12/15 15:34:57 daniel
+ * Support reading the raw IRIG data bits for firmware versions
+ * which support this feature.
+ * Revision 1.31 2009/11/04 14:58:52Z martin
+ * Conditionally exclude port status query from build.
+ * Revision 1.30 2009/09/29 15:08:39 martin
+ * Support retrieving time discipline info.
+ * Revision 1.29 2009/08/18 08:45:16 martin
+ * Removed IOCTL switch macro, inline code used for all targets.
+ * Revision 1.28 2009/06/26 13:16:11Z martin
+ * Fixed duplicate case in inline code (copy and paste error).
+ * Revision 1.27 2009/06/22 13:52:56 martin
+ * Fixed a bug where the size of GPS data had been truncated to 8 bits,
+ * which resulted in an IOCTL error if a buffer larger than 256 bytes had been
+ * used. This had been observed with the PC_GPS_ALL_STR_TYPE_INFO
+ * command if more than 6 string types are supported by a card.
+ * Revision 1.26 2009/06/19 12:21:12 martin
+ * Support reading raw IRIG time.
+ * Revision 1.25 2009/06/09 10:01:01 daniel
+ * Support configuration of LAN intf. and PTP.
+ * Started to support ARM / firmware.
+ * Conditionally compile ioctl_switch as inline function.
+ * Revision 1.24 2009/03/19 15:25:19 martin
+ * Support UTC parms and configurable time scales.
+ * Support IOCTL_DEV_HAS_IRIG_CTRL_BITS and IOCTL_GET_IRIG_CTRL_BITS.
+ * Support reading MM timestamps without cycles.
+ * IOCTL_GET_PCI_ASIC_VERSION now returns the ASIC
+ * version code from the device info structure which already
+ * has the correct endianess.
+ * For consistent naming renamed IOCTL_GET_FAST_HR_TIMESTAMP
+ * to IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES.
+ * Use mbg_get_cycles...() instead of _pcps_get_cycles...().
+ * Revision 1.23 2008/12/11 10:30:38Z martin
+ * _pcps_get_cycles() is now called inside the low level routines
+ * immediately when the command byte is written.
+ * Mutex for hardware access is now acquired/released in _pcps_sem_inc()
+ * and _pcps_sem_dec(), so other IOCTLs which don't access the card
+ * can be run in parallel.
+ * Moved definitions of _pcps_sem_inc(), _pcps_sem_dec(), and
+ * _pcps_get_cycles() to pcpsdrvr.h.
+ * Defined a macro which checks if access is safe (may be unsafe
+ * with certain PEX cards which have IRQs enabled).
+ * Use _pcps_sem_inc_safe() macro to check if access is safe and
+ * inhibit access if this is not the case.
+ * Consistenly use pcps_drvr_name instead of mbgclock_name
+ * for debug messages.
+ * Don't return error for unmap_mm...() under Linux.
+ * Account for ASIC_FEATURES being coded as flags, and account
+ * for new symbol PCI_ASIC_HAS_MM_IO.
+ * Handle new IOCTLs IOCTL_HAS_PCI_ASIC_FEATURES, IOCTL_HAS_PCI_ASIC_VERSION,
+ * IOCTL_DEV_IS_MSF, IOCTL_DEV_IS_LWR, IOCTL_DEV_IS_WWVB,
+ * IOCTL_GET_IRQ_STAT_INFO, IOCTL_GET_CYCLES_FREQUENCY,
+ * IOCTL_HAS_FAST_HR_TIMESTAMP, and IOCTL_GET_FAST_HR_TIMESTAMP.
+ * Support mapped I/O resources.
+ * Revision 1.22 2008/01/17 09:28:49 daniel
+ * Support for memory mapped I/O under Linux and Windows.
+ * Added macros _io_get_mapped_mem_address(),
+ * _io_unmap_mapped_mem_address().
+ * Account for IOCTL_GET_PCI_ASIC_FEATURES
+ * Cleanup for PCI ASIC version.
+ * Revision 1.21 2007/09/26 07:31:47Z martin
+ * Support reading status port of USB devices.
+ * Use kernel malloc/free macros from pcpsdrvr.h.
+ * Modified _pcps_sem..() to take PCPS_DDEV argument.
+ * Revision 1.20 2007/05/21 15:00:00Z martin
+ * Unified naming convention for symbols related to ref_offs.
+ * Revision 1.19 2007/03/30 13:31:42 martin
+ * Changes due to renamed library symbol.
+ * Revision 1.18 2007/03/02 10:31:21Z martin
+ * Use generic port I/O macros.
+ * Preliminary support for *BSD.
+ * Preliminary _cmd_from_ioctl().
+ * Revision 1.17 2006/03/10 10:35:43 martin
+ * Added support for programmable pulse outputs.
+ * Revision 1.16 2005/06/02 10:16:37Z martin
+ * Implemented IOCTL_PCPS_GENERIC_.. calls.
+ * Added support for SYNTH_STATE.
+ * Moved Debug IOCTL handling here.
+ * Revision 1.15 2005/01/14 10:26:41Z martin
+ * Support IOCTLs which query device features.
+ * Revision 1.14 2004/12/09 11:03:36Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.13 2004/11/09 12:47:19Z martin
+ * Use new macro _pcps_ddev_has_gps_data() to check whether GPS large
+ * data I/O is supported.
+ * Changes due to renamed symbols, IRIG RX/TX.
+ * Modifications were required in order to be able to configure IRIG
+ * settings of cards which provide both IRIG input and output.
+ * GPS169PCI cards with IRIG output and early firmware versions
+ * used the same codes to configure the IRIG output as the TCR
+ * cards use to configure the IRIG input. Those codes are now
+ * exclusively used to configure the IRIG input. A workaround
+ * has been included for those GPS169PCI cards, because otherwise
+ * the IRIG configuration would not work properly after a driver
+ * update, without also doing a firmware update.
+ * Show debug msg if GPS169PCI workaround for IRIG cfg in effect.
+ * Use more specific data types than generic types.
+ * Modified contents of debug messages.
+ * Added (uchar FAR *) cast.
+ * Revision 1.12 2004/06/07 09:20:52 martin
+ * Account for renamed symbols.
+ * Revision 1.11 2004/04/07 09:05:17 martin
+ * Support OS dependent IOCTLs used to trigger debug events.
+ * Revision 1.10 2004/03/16 16:25:42Z martin
+ * Support new macro _pcps_has_irig().
+ * Revision 1.9 2004/01/08 10:57:23Z martin
+ * Support codes to read ASIC version, and read times
+ * with associated cycle counter values.
+ * Support higher baud rates for TCR510PCI and PCI510.
+ * Support PCPS_HR_TIME for TCR510PCI.
+ * Revision 1.8 2003/09/17 12:49:57Z martin
+ * Use PCPS_GIVE_TIME_NOCLEAR in API mbg_get_time().
+ * Revision 1.7 2003/09/09 13:33:55Z martin
+ * Support IOCTL_GET_PCPS_TIME_SEC_CHANGE.
+ * Revision 1.6 2003/06/19 09:18:02Z martin
+ * Supports new APIs IOCTL_PCPS_GET_UCAP_ENTRIES
+ * and IOCTL_PCPS_GET_UCAP_EVENT.
+ * Changes due to renamed symbols.
+ * Preliminary _pout_size for Linux.
+ * Revision 1.5 2003/04/15 08:50:38Z martin
+ * Support ALL_STR_TYPE_INFO, ALL_PORT_INFO for Win32.
+ * Revision 1.4 2003/04/09 16:51:29Z martin
+ * Use new common IOCTL codes from mbgioctl.h.
+ * Support almost all IOCTL codes.
+ * Support for Win32.
+ * Revision 1.3 2001/11/30 09:52:47Z martin
+ * Added support for event_time which, however, requires
+ * a custom GPS firmware.
+ * Revision 1.2 2001/09/14 12:01:17 martin
+ * Decode PCPS_IOCTL_SET_GPS_CMD.
+ * Added some comments.
+ * Revision 1.1 2001/04/09 07:47:01 MARTIN
+ *
+ **************************************************************************/
+
+#ifndef _MACIOCTL_H
+#define _MACIOCTL_H
+
+#include <pcpsdrvr.h>
+#include <mbgioctl.h>
+#include <pci_asic.h>
+#include <mbgddmsg.h>
+
+
+// The types below are used since the macros used in this file
+// have been written to use structs and compilers return errors
+// if those macros are used with array variables.
+
+typedef struct
+{
+ LLA lla;
+} LLAs;
+
+typedef struct
+{
+ XYZ xyz;
+} XYZs;
+
+
+#define USE_DEBUG_PORT !defined( MBG_ARCH_ARM )
+
+
+// OS dependent definitions
+#if defined( MBG_TGT_LINUX )
+
+ #define _pcps_iob( _type, _s ) _type _s
+ #define _pcps_iob_arr( _type, _s, n ) _type _s[_n]
+
+ #define _pcps_iob_to_pout_size( _type, _iob, _pout, _size ) \
+ if ( copy_to_user( (_type *)(_pout), &(_iob), _size ) ) \
+ goto err_to_user;
+
+ #define _pcps_iob_from_pin_size( _type, _iob, _pin, _size ) \
+ if ( copy_from_user( &(_iob), (_type *) (_pin), _size ) ) \
+ goto err_from_user;
+
+ #define _io_wait_pcps_sec_change( _pddev, _cmd, _type, _pout ) \
+ goto err_inval
+
+ #define _io_get_mapped_mem_address( _pddev, _pout ) \
+ { \
+ _pcps_iob( PCPS_MAPPED_MEM, _s ); \
+ _s.pfn_offset = ( pddev->rsrc_info.mem[0].start & ~PAGE_MASK ) + sizeof( PCI_ASIC ); \
+ _s.len = pddev->rsrc_info.mem[0].len - sizeof( PCI_ASIC ); \
+ _pcps_iob_to_pout_size( PCPS_MAPPED_MEM, _s, _pout, sizeof( PCPS_MAPPED_MEM ) ); \
+ }
+
+ #define _io_unmap_mapped_mem_address( _pddev, _pin ) \
+ _nop_macro_fnc()
+
+#elif defined( MBG_TGT_FREEBSD )
+
+ #include <sys/malloc.h>
+
+ #define _pcps_iob( _type, _s ) _type _s
+ #define _pcps_iob_arr( _type, _s, n ) _type _s[_n]
+
+ #define _pcps_iob_to_pout_size( _type, _iob, _pout, _size ) \
+ memcpy( (_type *)(_pout), &(_iob), _size )
+
+ #define _pcps_iob_from_pin_size( _type, _iob, _pin, _size ) \
+ memcpy( &(_iob), (_type *) (_pin), _size )
+
+ #define _io_wait_pcps_sec_change( _pddev, _cmd, _type, _pout ) \
+ goto err_inval
+
+ #define _io_get_mapped_mem_address( _pddev, _pout ) \
+ goto err_inval
+
+ #define _io_unmap_mapped_mem_address( _pddev, _pin ) \
+ goto err_inval
+
+#elif defined( MBG_TGT_NETBSD )
+
+ #include <sys/malloc.h>
+
+ #define _pcps_iob( _type, _s ) _type _s
+ #define _pcps_iob_arr( _type, _s, n ) _type _s[_n]
+
+ int
+ copyin(const void *uaddr, void *kaddr, size_t len); // to from user to kernel
+
+ int
+ copyout(const void *kaddr, void *uaddr, size_t len); // from kernel to user
+
+ #define _pcps_iob_to_pout_size( _type, _iob, _pout, _size ) \
+ if ( copyout( (_type *)(_pout), &(_iob), _size ) ) \
+ goto err_to_user;
+
+ #define _pcps_iob_from_pin_size( _type, _iob, _pin, _size ) \
+ if ( copyin( &(_iob), (_type *) (_pin), _size ) ) \
+ goto err_from_user;
+
+ #define _io_wait_pcps_sec_change( _pddev, _cmd, _type, _pout ) \
+ goto err_inval
+
+ #define _io_get_mapped_mem_address( _pddev, _pout ) \
+ goto err_inval
+
+ #define _io_unmap_mapped_mem_address( _pddev, _pin ) \
+ goto err_inval
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #define _pcps_iob( _type, _s ) _type _s
+ #define _pcps_iob_arr( _type, _s, n ) _type _s[_n]
+
+ #define _pcps_iob_to_pout_size( _type, _iob, _pout, _size ) \
+ { \
+ RtlCopyMemory( _pout, &_iob, _size ); \
+ *ret_size = _size; \
+ }
+
+ #define _pcps_iob_from_pin_size( _type, _iob, _pin, _size ) \
+ RtlCopyMemory( &_iob, _pin, _size );
+
+ // The following macros are defined in the OS dependent code:
+ //
+ // _io_wait_pcps_sec_change()
+ // _io_get_mapped_mem_address()
+ // _io_unmap_mapped_mem_address()
+ // _io_set_interrupt()
+ //
+
+#endif
+
+
+
+#define _pcps_iob_to_pout( _type, _iob, _pout ) \
+ _pcps_iob_to_pout_size( _type, _iob, _pout, sizeof( _iob ) )
+
+#define _pcps_iob_from_pin( _type, _iob, _pin ) \
+ _pcps_iob_from_pin_size( _type, _iob, _pin, sizeof( _iob ) )
+
+
+// For some cards it may be unsafe to access the card while
+// interrups are enabled for the card since IRQs may during
+// access may mess up the interface. The macro below checks
+// whether this is the case.
+#define _pcps_access_is_unsafe( _pddev ) \
+ ( ( (_pddev)->irq_stat_info & PCPS_IRQ_STATE_DANGER ) == PCPS_IRQ_STATE_DANGER )
+
+
+
+// Check whether a card can be accessed safely and set a flag
+// preventing the card from being accessed from IRQ handler.
+#if defined( MBG_TGT_WIN32 )
+
+ // Under Windows.we need to save a pointer to the current
+ // IRP by default.
+ #define _pcps_sem_inc_safe( _pddev ) \
+ if ( _pcps_access_is_unsafe( _pddev ) ) \
+ goto err_busy_unsafe; \
+ _pcps_sem_inc( _pddev ); \
+ (_pddev)->irp = pIrp
+
+ // If a function which is exported by our kernel driver
+ // is called from a different kernel driver then there is
+ // no IRP, so we provide a different, Windows-only macro
+ // which is used by those export functions and sets the
+ // IRP pointer of the device structure to NULL.
+ #define _pcps_sem_inc_safe_no_irp( _pddev ) \
+ if ( _pcps_access_is_unsafe( _pddev ) ) \
+ goto err_busy_unsafe; \
+ _pcps_sem_inc( _pddev ); \
+ (_pddev)->irp = NULL
+
+#else
+
+ // Other OSs don't use an IRP, so no IRP pointer
+ // needs to be set up.
+ #define _pcps_sem_inc_safe( _pddev ) \
+ if ( _pcps_access_is_unsafe( _pddev ) ) \
+ goto err_busy_unsafe; \
+ _pcps_sem_inc( _pddev ); \
+
+#endif
+
+
+
+
+
+// Read a data structure from a clock device.
+// Check the return code and if no error occurred,
+// copy the data to the caller's memory space.
+#define _io_read_var( _pddev, _cmd, _type, _pout ) \
+{ \
+ _pcps_iob( _type, _s ); \
+ \
+ _pcps_sem_inc_safe( _pddev ); \
+ rc = _pcps_read_var( _pddev, _cmd, _s ); \
+ _pcps_sem_dec( _pddev ); \
+ \
+ if ( rc != MBG_SUCCESS ) \
+ goto err_access; \
+ \
+ _pcps_iob_to_pout( _type, _s, _pout ); \
+}
+
+
+// Retrieve a data structure from the caller's
+// memory space, write it to a clock device and
+// check the return code.
+#define _io_write_var( _pddev, _cmd, _type, _pin ) \
+{ \
+ _pcps_iob( _type, _s ); \
+ \
+ _pcps_iob_from_pin( _type, _s, _pin ); \
+ \
+ _pcps_sem_inc_safe( _pddev ); \
+ rc = _pcps_write_var( _pddev, _cmd, _s ); \
+ _pcps_sem_dec( _pddev ); \
+ \
+ if ( rc != MBG_SUCCESS ) \
+ goto err_access; \
+}
+
+
+// Retrieve a data structure from the caller's
+// memory space, write it to a clock device and
+// check the return code.
+#define _io_write_cmd( _pddev, _cmd ) \
+{ \
+ _pcps_sem_inc_safe( _pddev ); \
+ rc = _pcps_write_byte( _pddev, _cmd ); \
+ _pcps_sem_dec( _pddev ); \
+ \
+ if ( rc != MBG_SUCCESS ) \
+ goto err_access; \
+}
+
+
+// Check if a clock is a GPS device. If it is,
+// read GPS data with variable size from the device.
+// Check the return code and if no error occurred,
+// copy the data to the caller's memory space.
+#define _io_read_gps( _pddev, _cmd, _type, _pout, _size ) \
+{ \
+ _pcps_iob( _type, _s ); \
+ \
+ if ( !_pcps_ddev_has_gps_data( _pddev ) ) \
+ goto err_support; \
+ \
+ _pcps_sem_inc_safe( _pddev ); \
+ rc = pcps_read_gps( _pddev, _cmd, (uchar FAR *) &_s, _size ); \
+ _pcps_sem_dec( _pddev ); \
+ \
+ if ( rc != MBG_SUCCESS ) \
+ goto err_access; \
+ \
+ _pcps_iob_to_pout_size( _type, _s, _pout, _size ); \
+}
+
+
+// Check if a clock is a GPS device. If it is,
+// read a GPS data structure from the device.
+// Check the return code and if no error occurred,
+// copy the data to the caller's memory space.
+#define _io_read_gps_var( _pddev, _cmd, _type, _pout ) \
+{ \
+ _pcps_iob( _type, _s ); \
+ \
+ if ( !_pcps_ddev_has_gps_data( _pddev ) ) \
+ goto err_support; \
+ \
+ _pcps_sem_inc_safe( _pddev ); \
+ rc = _pcps_read_gps_var( _pddev, _cmd, _s ); \
+ _pcps_sem_dec( _pddev ); \
+ \
+ if ( rc != MBG_SUCCESS ) \
+ goto err_access; \
+ \
+ _pcps_iob_to_pout( _type, _s, _pout ); \
+}
+
+
+// Check if a clock is a GPS device. If it is,
+// retrieve a data structure from the caller's
+// memory space, write it to the clock device and
+// check the return code.
+#define _io_write_gps_var( _pddev, _cmd, _type, _pin ) \
+{ \
+ _pcps_iob( _type, _s ); \
+ \
+ if ( !_pcps_ddev_has_gps_data( _pddev ) ) \
+ goto err_support; \
+ \
+ _pcps_iob_from_pin( _type, _s, _pin ); \
+ \
+ _pcps_sem_inc_safe( _pddev ); \
+ rc = _pcps_write_gps_var( _pddev, _cmd, _s ); \
+ _pcps_sem_dec( _pddev ); \
+ \
+ if ( rc != MBG_SUCCESS ) \
+ goto err_access; \
+}
+
+
+// Check a condition an go to an error handler
+// if the condition is not true.
+#define _io_chk_cond( _cond ) \
+ if ( !(_cond) ) \
+ goto err_support;
+
+
+
+// The macros below are similar to those defined above except
+// that they check if a condition is true before they really
+// do anything. This is used for IOCTL calls which may not
+// be supported with any type of clock device.
+#define _io_read_var_chk( _pddev, _cmd, _type, _pout, _cond ) \
+{ \
+ _io_chk_cond( _cond ); \
+ _io_read_var( _pddev, _cmd, _type, _pout ); \
+}
+
+#define _io_write_var_chk( _pddev, _cmd, _type, _pin, _cond ) \
+{ \
+ _io_chk_cond( _cond ); \
+ _io_write_var( _pddev, _cmd, _type, _pin ); \
+}
+
+#define _io_write_cmd_chk( _pddev, _cmd, _cond ) \
+{ \
+ _io_chk_cond( _cond ); \
+ _io_write_cmd( _pddev, _cmd ); \
+}
+
+#define _io_read_gps_chk( _pddev, _cmd, _type, _pout, _size, _cond ) \
+{ \
+ _io_chk_cond( _cond ); \
+ _io_read_gps( _pddev, _cmd, _type, _pout, _size ); \
+}
+
+#define _io_read_gps_var_chk( _pddev, _cmd, _type, _pout, _cond ) \
+{ \
+ _io_chk_cond( _cond ); \
+ _io_read_gps_var( _pddev, _cmd, _type, _pout ); \
+}
+
+#define _io_write_gps_var_chk( _pddev, _cmd, _type, _pin, _cond ) \
+{ \
+ _io_chk_cond( _cond ); \
+ _io_write_gps_var( _pddev, _cmd, _type, _pin ); \
+}
+
+
+#define _report_cond( _cond, _pout ) \
+{ \
+ int retval = _cond; \
+ _pcps_iob_to_pout( int, retval, _pout ); \
+}
+
+
+
+#define _mbg_dbg_set_bit( _d, _v ) \
+{ \
+ mbg_dbg_data |= (_v); \
+ _mbg_outp8( (_d), 0, mbg_dbg_port_mapped, mbg_dbg_data ); \
+}
+
+#define _mbg_dbg_clr_bit( _d, _v ) \
+{ \
+ mbg_dbg_data &= ~(_v); \
+ _mbg_outp8( (_d), 0, mbg_dbg_port_mapped, mbg_dbg_data ); \
+}
+
+#define _mbg_dbg_clr_all( _d ) \
+{ \
+ mbg_dbg_data = 0; \
+ _mbg_outp8( (_d), 0, mbg_dbg_port_mapped, mbg_dbg_data ); \
+}
+
+
+
+#define TEST_MM_ACCESS_TIME ( 0 && defined( MBG_TGT_LINUX ) )
+#define TEST_MM_ACCESS_64 0
+#define TEST_FRAC_ONLY 0
+
+#if TEST_MM_ACCESS_TIME
+ #include <pcpsutil.h>
+#endif
+
+
+#if defined( __GNUC__ )
+// Avoid "no previous prototype" with some gcc versions.
+__mbg_inline
+void swap_tstamp( PCPS_TIME_STAMP *p_ts ) __attribute__((always_inline));
+#endif
+
+__mbg_inline
+void swap_tstamp( PCPS_TIME_STAMP *p_ts )
+{
+ uint32_t tmp = p_ts->sec;
+ p_ts->sec = p_ts->frac;
+ p_ts->frac = tmp;
+
+} // swap_tstamp
+
+
+
+#if defined( __GNUC__ )
+// Avoid "no previous prototype" with some gcc versions.
+__mbg_inline
+void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts ) __attribute__((always_inline));
+#endif
+
+
+__mbg_inline
+void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts )
+{
+#if TEST_MM_ACCESS_64
+ volatile uint64_t *p = (volatile uint64_t *) pddev->mm_tstamp_addr;
+#else
+ volatile uint32_t *p = (volatile uint32_t *) pddev->mm_tstamp_addr;
+#endif
+
+#if TEST_MM_ACCESS_TIME
+ PCPS_TIME_STAMP tmp;
+ MBG_PC_CYCLES cyc_1;
+ MBG_PC_CYCLES cyc_2;
+ MBG_PC_CYCLES cyc_3;
+ long delta_frac;
+ unsigned delta_ns;
+#endif
+
+#if TEST_MM_ACCESS_TIME
+ mbg_get_pc_cycles( &cyc_1 );
+#endif
+
+ _pcps_spin_lock( &pddev->mm_lock );
+
+#if TEST_MM_ACCESS_64
+ *( (volatile uint64_t *) p_ts ) = *p;
+#else
+ p_ts->frac = _mbg32_to_cpu( *p );
+ #if !TEST_FRAC_ONLY
+ p_ts->sec = _mbg32_to_cpu( *( p + 1 ) );
+ #endif
+#endif
+
+#if TEST_MM_ACCESS_TIME
+ #if TEST_MM_ACCESS_64
+ *( (volatile uint64_t *) &tmp ) = *p;
+ #else
+ tmp.frac = _mbg32_to_cpu( *p );
+ #if !TEST_FRAC_ONLY
+ tmp.sec = _mbg32_to_cpu( *( p + 1 ) );
+ #endif
+ #endif
+#endif
+
+ _pcps_spin_unlock( &pddev->mm_lock );
+
+#if TEST_FRAC_ONLY
+ p_ts->sec = 0;
+ #if TEST_MM_ACCESS_TIME
+ tmp.sec = 0;
+ #endif
+#endif
+
+#if TEST_MM_ACCESS_64
+ swap_tstamp( p_ts );
+ #if TEST_MM_ACCESS_TIME
+ swap_tstamp( &tmp );
+ #endif
+#endif
+
+
+#if TEST_MM_ACCESS_TIME
+ mbg_get_pc_cycles( &cyc_2 );
+ mbg_get_pc_cycles( &cyc_3 );
+#endif
+
+#if TEST_MM_ACCESS_TIME
+ delta_frac = (long) ( tmp.frac - p_ts->frac );
+ delta_ns = (unsigned) frac_sec_from_bin( delta_frac, 1000000000UL );
+
+ printk( KERN_INFO "MM tstamp dev %04X: %li/%li cyc (%lu kHz)"
+ " %08lX.%08lX->%08lX.%08lX: %li (%u.%03u us)"
+ "\n",
+ _pcps_ddev_dev_id( pddev ),
+ (long) ( cyc_2 - cyc_1 ),
+ (long) ( cyc_3 - cyc_2 ),
+ (ulong) cpu_khz,
+ (ulong) p_ts->sec, (ulong) p_ts->frac,
+ (ulong) tmp.sec, (ulong) tmp.frac,
+ (long) ( tmp.frac - p_ts->frac ),
+ delta_ns / 1000,
+ delta_ns % 1000
+ );
+#endif
+
+} // do_get_fast_hr_timestamp_safe
+
+
+
+#if defined( __GNUC__ )
+// Avoid "no previous prototype" with some gcc versions.
+__mbg_inline
+void do_get_fast_hr_timestamp_cycles_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYCLES *p_ts_cyc ) __attribute__((always_inline));
+#endif
+
+__mbg_inline
+void do_get_fast_hr_timestamp_cycles_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYCLES *p_ts_cyc )
+{
+ volatile uint32_t *p = (volatile uint32_t *) pddev->mm_tstamp_addr;
+
+ _pcps_spin_lock( &pddev->mm_lock );
+ mbg_get_pc_cycles( &p_ts_cyc->cycles );
+ p_ts_cyc->tstamp.frac = _mbg32_to_cpu( *p++ );
+ p_ts_cyc->tstamp.sec = _mbg32_to_cpu( *p );
+ _pcps_spin_unlock( &pddev->mm_lock );
+
+} // do_get_fast_hr_timestamp_cycles_safe
+
+
+
+#if defined( __GNUC__ )
+// Avoid "no previous prototype" with some gcc versions.
+__mbg_inline
+int ioctl_switch( PCPS_DDEV *pddev, int ioctl_code,
+ #if defined( MBG_TGT_WIN32 )
+ IRP *pIrp, int *ret_size, uint16_t pout_size,
+ #endif
+ void *pin, void *pout ) __attribute__((always_inline));
+#endif
+
+__mbg_inline
+int ioctl_switch( PCPS_DDEV *pddev, int ioctl_code,
+ #if defined( MBG_TGT_WIN32 )
+ IRP *pIrp, int *ret_size, uint16_t pout_size,
+ #endif
+ void *pin, void *pout )
+{
+ int rc = MBG_SUCCESS;
+
+ switch ( ioctl_code )
+ {
+ case IOCTL_GET_PCPS_DRVR_INFO:
+ _pcps_iob_to_pout( PCPS_DRVR_INFO,
+ drvr_info, pout );
+ break;
+
+
+ case IOCTL_GET_PCPS_DEV:
+ _pcps_iob_to_pout( PCPS_DEV, pddev->dev, pout );
+ break;
+
+
+ #if !defined( OMIT_STATUS_PORT )
+ case IOCTL_GET_PCPS_STATUS_PORT:
+ {
+ if ( _pcps_ddev_is_usb( pddev ) )
+ {
+ _io_read_var( pddev, PCPS_GET_STATUS_PORT,
+ PCPS_STATUS_PORT, pout );
+
+ }
+ else
+ {
+ PCPS_STATUS_PORT status =
+ _pcps_ddev_read_status_port( pddev );
+ _pcps_iob_to_pout( PCPS_STATUS_PORT, status, pout );
+ }
+ break;
+ }
+ #endif
+
+
+ case IOCTL_PCPS_GENERIC_READ:
+ {
+ IOCTL_GENERIC_CTL ctl;
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buffer_size;
+
+ _pcps_iob_from_pin( IOCTL_GENERIC_CTL, ctl, pin );
+ buffer_size = sizeof( ctl ) + ctl.data_size_out;
+ p_buff = _pcps_kmalloc( buffer_size );
+
+ if ( p_buff == NULL )
+ goto err_no_mem;
+
+ _pcps_sem_inc_safe( pddev );
+ rc = _pcps_read( pddev, (uint8_t) ctl.info,
+ p_buff->data,
+ (uint8_t) ctl.data_size_out );
+ _pcps_sem_dec( pddev );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ p_buff->ctl = ctl;
+ _pcps_iob_to_pout_size( uint8_t, *p_buff, pout,
+ buffer_size );
+ }
+
+ _pcps_kfree( p_buff, buffer_size );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ break;
+ }
+
+
+ case IOCTL_PCPS_GENERIC_WRITE:
+ {
+ IOCTL_GENERIC_CTL ctl;
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buffer_size;
+
+ _pcps_iob_from_pin( IOCTL_GENERIC_CTL, ctl, pin );
+ buffer_size = sizeof( ctl ) + ctl.data_size_in;
+ p_buff = _pcps_kmalloc( buffer_size );
+
+ if ( p_buff == NULL )
+ goto err_no_mem;
+
+ _pcps_iob_from_pin_size( uint8_t, *p_buff, pin,
+ buffer_size );
+
+ _pcps_sem_inc_safe( pddev );
+ rc = pcps_write( pddev, (uint8_t) ctl.info,
+ p_buff->data,
+ (uint8_t) ctl.data_size_in );
+ _pcps_sem_dec( pddev );
+
+ _pcps_kfree( p_buff, buffer_size );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ break;
+ }
+
+
+ case IOCTL_PCPS_GENERIC_READ_GPS:
+ {
+ IOCTL_GENERIC_CTL ctl;
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buffer_size;
+
+ _pcps_iob_from_pin( IOCTL_GENERIC_CTL, ctl, pin );
+ buffer_size = sizeof( ctl ) + ctl.data_size_out;
+ p_buff = _pcps_kmalloc( buffer_size );
+
+ if ( p_buff == NULL )
+ goto err_no_mem;
+
+ _pcps_sem_inc_safe( pddev );
+ rc = pcps_read_gps( pddev, (uint8_t) ctl.info,
+ p_buff->data,
+ (uint16_t) ctl.data_size_out );
+ _pcps_sem_dec( pddev );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ p_buff->ctl = ctl;
+ _pcps_iob_to_pout_size( uint8_t, *p_buff, pout,
+ buffer_size );
+ }
+
+ _pcps_kfree( p_buff, buffer_size );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ break;
+ }
+
+
+ case IOCTL_PCPS_GENERIC_WRITE_GPS:
+ {
+ IOCTL_GENERIC_CTL ctl;
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buffer_size;
+
+ _pcps_iob_from_pin( IOCTL_GENERIC_CTL, ctl, pin );
+ buffer_size = sizeof( ctl ) + ctl.data_size_in;
+ p_buff = _pcps_kmalloc( buffer_size );
+
+ if ( p_buff == NULL )
+ goto err_no_mem;
+
+ _pcps_iob_from_pin_size( uint8_t, *p_buff, pin,
+ buffer_size );
+
+ _pcps_sem_inc_safe( pddev );
+ rc = pcps_write_gps( pddev, (uint8_t) ctl.info,
+ p_buff->data,
+ (uint8_t) ctl.data_size_in );
+ _pcps_sem_dec( pddev );
+
+ _pcps_kfree( p_buff, buffer_size );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ break;
+ }
+
+
+ case IOCTL_GET_PCPS_TIME:
+ _io_read_var( pddev, PCPS_GIVE_TIME_NOCLEAR,
+ PCPS_TIME, pout );
+ break;
+
+
+ case IOCTL_SET_PCPS_TIME:
+ _io_write_var_chk( pddev, PCPS_SET_TIME,
+ PCPS_STIME, pin,
+ _pcps_ddev_can_set_time( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_SYNC_TIME:
+ _io_read_var_chk( pddev, PCPS_GIVE_SYNC_TIME,
+ PCPS_TIME, pout,
+ _pcps_ddev_has_sync_time( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_TIME_SEC_CHANGE:
+ _io_wait_pcps_sec_change( pddev, PCPS_GIVE_TIME,
+ PCPS_TIME, pout );
+ break;
+
+
+ case IOCTL_GET_PCPS_HR_TIME:
+ _io_read_var_chk( pddev, PCPS_GIVE_HR_TIME,
+ PCPS_HR_TIME, pout,
+ _pcps_ddev_has_hr_time( pddev ) );
+ break;
+
+
+ case IOCTL_SET_PCPS_EVENT_TIME:
+ _io_write_var_chk( pddev, PCPS_SET_EVENT_TIME,
+ PCPS_TIME_STAMP, pin,
+ _pcps_ddev_has_event_time( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_SERIAL:
+ _io_read_var( pddev, PCPS_GET_SERIAL,
+ PCPS_SERIAL, pout );
+ break;
+
+
+ case IOCTL_SET_PCPS_SERIAL:
+ _io_write_var( pddev, PCPS_SET_SERIAL,
+ PCPS_SERIAL, pin );
+ break;
+
+
+ case IOCTL_GET_PCPS_TZCODE:
+ _io_read_var_chk( pddev, PCPS_GET_TZCODE,
+ PCPS_TZCODE, pout,
+ _pcps_ddev_has_tzcode( pddev ) );
+ break;
+
+
+ case IOCTL_SET_PCPS_TZCODE:
+ _io_write_var_chk( pddev, PCPS_SET_TZCODE,
+ PCPS_TZCODE, pin,
+ _pcps_ddev_has_tzcode( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_TZDL:
+ _io_read_var_chk( pddev, PCPS_GET_PCPS_TZDL,
+ PCPS_TZDL, pout,
+ _pcps_ddev_has_pcps_tzdl( pddev ) );
+ break;
+
+
+ case IOCTL_SET_PCPS_TZDL:
+ _io_write_var_chk( pddev, PCPS_SET_PCPS_TZDL,
+ PCPS_TZDL, pin,
+ _pcps_ddev_has_pcps_tzdl( pddev ) );
+ break;
+
+
+ case IOCTL_GET_REF_OFFS:
+ _io_read_var_chk( pddev, PCPS_GET_REF_OFFS,
+ MBG_REF_OFFS, pout,
+ _pcps_ddev_has_ref_offs( pddev ) );
+ break;
+
+
+ case IOCTL_SET_REF_OFFS:
+ _io_write_var_chk( pddev, PCPS_SET_REF_OFFS,
+ MBG_REF_OFFS, pin,
+ _pcps_ddev_has_ref_offs( pddev ) );
+ break;
+
+
+ case IOCTL_GET_MBG_OPT_INFO:
+ _io_read_var_chk( pddev, PCPS_GET_OPT_INFO,
+ MBG_OPT_INFO, pout,
+ _pcps_ddev_has_opt_flags( pddev ) );
+ break;
+
+
+ case IOCTL_SET_MBG_OPT_SETTINGS:
+ _io_write_var_chk( pddev, PCPS_SET_OPT_SETTINGS,
+ MBG_OPT_SETTINGS, pin,
+ _pcps_ddev_has_opt_flags( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_IRIG_RX_INFO:
+ _io_read_var_chk( pddev, PCPS_GET_IRIG_RX_INFO,
+ IRIG_INFO, pout,
+ _pcps_ddev_is_irig_rx( pddev ) );
+ break;
+
+
+ case IOCTL_SET_PCPS_IRIG_RX_SETTINGS:
+ _io_write_var_chk( pddev, PCPS_SET_IRIG_RX_SETTINGS,
+ IRIG_SETTINGS, pin,
+ _pcps_ddev_is_irig_rx( pddev ) );
+ break;
+
+
+ case IOCTL_PCPS_CLR_UCAP_BUFF:
+ _io_write_cmd_chk( pddev, PCPS_CLR_UCAP_BUFF,
+ _pcps_ddev_can_clr_ucap_buff( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_UCAP_ENTRIES:
+ _io_read_var_chk( pddev, PCPS_GIVE_UCAP_ENTRIES,
+ PCPS_UCAP_ENTRIES, pout,
+ _pcps_ddev_has_ucap( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCPS_UCAP_EVENT:
+ _io_read_var_chk( pddev, PCPS_GIVE_UCAP_EVENT,
+ PCPS_HR_TIME, pout,
+ _pcps_ddev_has_ucap( pddev ) );
+ break;
+
+
+ /* slow read/write operations with GPS data */
+
+ case IOCTL_GET_GPS_TZDL:
+ _io_read_gps_var( pddev, PC_GPS_TZDL, TZDL, pout );
+ break;
+
+
+ case IOCTL_SET_GPS_TZDL:
+ _io_write_gps_var( pddev, PC_GPS_TZDL, TZDL, pin );
+ break;
+
+
+ case IOCTL_GET_GPS_SW_REV:
+ _io_read_gps_var( pddev, PC_GPS_SW_REV,
+ SW_REV, pout );
+ break;
+
+
+ case IOCTL_GET_GPS_BVAR_STAT:
+ _io_read_gps_var( pddev, PC_GPS_BVAR_STAT,
+ BVAR_STAT, pout );
+ break;
+
+
+ case IOCTL_GET_GPS_TIME:
+ _io_read_gps_var( pddev, PC_GPS_TIME, TTM, pout );
+ break;
+
+
+ case IOCTL_SET_GPS_TIME:
+ _io_write_gps_var( pddev, PC_GPS_TIME, TTM, pin );
+ break;
+
+
+ case IOCTL_GET_GPS_PORT_PARM:
+ _io_read_gps_var( pddev, PC_GPS_PORT_PARM,
+ PORT_PARM, pout );
+ break;
+
+
+ case IOCTL_SET_GPS_PORT_PARM:
+ _io_write_gps_var( pddev, PC_GPS_PORT_PARM,
+ PORT_PARM, pin );
+ break;
+
+
+ case IOCTL_GET_GPS_ANT_INFO:
+ _io_read_gps_var( pddev, PC_GPS_ANT_INFO,
+ ANT_INFO, pout );
+ break;
+
+
+ case IOCTL_GET_GPS_UCAP:
+ _io_read_gps_var( pddev, PC_GPS_UCAP, TTM, pout );
+ break;
+
+
+ case IOCTL_GET_GPS_ENABLE_FLAGS:
+ _io_read_gps_var( pddev, PC_GPS_ENABLE_FLAGS,
+ ENABLE_FLAGS, pout );
+ break;
+
+
+ case IOCTL_SET_GPS_ENABLE_FLAGS:
+ _io_write_gps_var( pddev, PC_GPS_ENABLE_FLAGS,
+ ENABLE_FLAGS, pin );
+ break;
+
+
+ case IOCTL_GET_GPS_STAT_INFO:
+ _io_read_gps_var( pddev, PC_GPS_STAT_INFO,
+ STAT_INFO, pout );
+ break;
+
+
+ case IOCTL_SET_GPS_CMD:
+ _io_write_gps_var( pddev, PC_GPS_CMD,
+ GPS_CMD, pin );
+ break;
+
+
+ case IOCTL_GET_GPS_IDENT:
+ _io_read_gps_var( pddev, PC_GPS_IDENT,
+ IDENT, pout );
+ break;
+
+
+ case IOCTL_GET_GPS_POS:
+ _io_read_gps_var( pddev, PC_GPS_POS,
+ POS, pout );
+ break;
+
+
+ case IOCTL_SET_GPS_POS_XYZ:
+ _io_write_gps_var( pddev, PC_GPS_POS_XYZ,
+ XYZs, pin );
+ break;
+
+
+ case IOCTL_SET_GPS_POS_LLA:
+ _io_write_gps_var( pddev, PC_GPS_POS_LLA,
+ LLAs, pin );
+ break;
+
+
+ case IOCTL_GET_GPS_ANT_CABLE_LEN:
+ _io_read_gps_var_chk( pddev, PC_GPS_ANT_CABLE_LEN,
+ ANT_CABLE_LEN, pout,
+ _pcps_ddev_has_cab_len( pddev ) );
+ break;
+
+
+ case IOCTL_SET_GPS_ANT_CABLE_LEN:
+ _io_write_gps_var_chk( pddev, PC_GPS_ANT_CABLE_LEN,
+ ANT_CABLE_LEN, pin,
+ _pcps_ddev_has_cab_len( pddev ) );
+ break;
+
+
+ case IOCTL_GET_GPS_RECEIVER_INFO:
+ _io_chk_cond( _pcps_ddev_has_receiver_info( pddev ) );
+ // Just copy the saved RECEIVER_INFO ...
+ _pcps_iob_to_pout_size( RECEIVER_INFO, pddev->ri, pout,
+ sizeof( RECEIVER_INFO ) );
+ break;
+
+
+ #if _MBG_SUPP_VAR_ACC_SIZE
+ case IOCTL_GET_GPS_ALL_STR_TYPE_INFO:
+ _io_read_gps_chk( pddev, PC_GPS_ALL_STR_TYPE_INFO,
+ ALL_STR_TYPE_INFO, pout, pout_size,
+ _pcps_ddev_has_receiver_info( pddev ) );
+ break;
+ #endif
+
+
+ #if _MBG_SUPP_VAR_ACC_SIZE
+ case IOCTL_GET_GPS_ALL_PORT_INFO:
+ _io_read_gps_chk( pddev, PC_GPS_ALL_PORT_INFO,
+ ALL_PORT_INFO, pout, pout_size,
+ _pcps_ddev_has_receiver_info( pddev ) );
+ break;
+ #endif
+
+
+ case IOCTL_SET_GPS_PORT_SETTINGS_IDX:
+ _io_write_gps_var_chk( pddev, PC_GPS_PORT_SETTINGS_IDX,
+ PORT_SETTINGS_IDX, pin,
+ _pcps_ddev_has_receiver_info( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PCI_ASIC_VERSION:
+ _io_chk_cond( _pcps_ddev_has_asic_version( pddev ) );
+ {
+ _pcps_iob( PCI_ASIC_VERSION, _s );
+
+ _s = pddev->raw_asic_version;
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( PCI_ASIC_VERSION, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_GET_PCPS_TIME_CYCLES:
+ {
+ _pcps_iob( PCPS_TIME_CYCLES, _s );
+
+ _pcps_sem_inc_safe( pddev );
+ rc = _pcps_read_var( pddev, PCPS_GIVE_TIME_NOCLEAR,
+ _s.t );
+ if ( _pcps_ddev_is_usb( pddev ) )
+ _s.cycles =(pddev)->acc_cycles;
+ else
+ mbg_get_pc_cycles( &(_s).cycles );
+ _pcps_sem_dec( pddev );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ _pcps_iob_to_pout( PCPS_TIME_CYCLES, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_GET_PCPS_HR_TIME_CYCLES:
+ {
+ _pcps_iob( PCPS_HR_TIME_CYCLES, _s );
+
+ _pcps_sem_inc_safe( pddev );
+ rc = _pcps_read_var( pddev, PCPS_GIVE_HR_TIME,
+ _s.t );
+ _s.cycles =(pddev)->acc_cycles;
+ _pcps_sem_dec( pddev );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ _pcps_iob_to_pout( PCPS_HR_TIME_CYCLES, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_GET_PCPS_IRIG_TX_INFO:
+ {
+ /* This is a workaround for GPS169PCIs with early */
+ /* firmware versions. See RCS log for details. */
+ uint8_t pcps_cmd = PCPS_GET_IRIG_TX_INFO;
+
+ if ( _pcps_ddev_requires_irig_workaround( pddev ) )
+ {
+ pcps_cmd = PCPS_GET_IRIG_RX_INFO;
+ _mbgddmsg_1( MBG_DBG_INFO,
+ "%s: workaround for GPS169PCI \"get IRIG TX cfg\"",
+ pcps_driver_name );
+ }
+
+ _io_read_var_chk( pddev, pcps_cmd, IRIG_INFO, pout,
+ _pcps_ddev_has_irig_tx( pddev ) );
+ }
+ break;
+
+
+ case IOCTL_SET_PCPS_IRIG_TX_SETTINGS:
+ {
+ /* This is a workaround for GPS169PCIs with early */
+ /* firmware versions. See RCS log for details. */
+ uint8_t pcps_cmd = PCPS_SET_IRIG_TX_SETTINGS;
+
+ if ( _pcps_ddev_requires_irig_workaround( pddev ) )
+ {
+ pcps_cmd = PCPS_SET_IRIG_RX_SETTINGS;
+ _mbgddmsg_1( MBG_DBG_INFO,
+ "%s: workaround for GPS169PCI \"set IRIG TX cfg\"",
+ pcps_driver_name );
+ }
+
+ _io_write_var_chk( pddev, pcps_cmd,
+ IRIG_SETTINGS, pin,
+ _pcps_ddev_has_irig_tx( pddev ) );
+ }
+ break;
+
+
+ case IOCTL_GET_SYNTH:
+ _io_read_var_chk( pddev, PCPS_GET_SYNTH,
+ SYNTH, pout,
+ _pcps_ddev_has_synth( pddev ) );
+ break;
+
+
+ case IOCTL_SET_SYNTH:
+ _io_write_var_chk( pddev, PCPS_SET_SYNTH,
+ SYNTH, pin,
+ _pcps_ddev_has_synth( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_IS_GPS:
+ _report_cond( _pcps_ddev_is_gps( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_IS_DCF:
+ _report_cond( _pcps_ddev_is_dcf( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_IS_IRIG_RX:
+ _report_cond( _pcps_ddev_is_irig_rx( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_HR_TIME:
+ _report_cond( _pcps_ddev_has_hr_time( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_CAB_LEN:
+ _report_cond( _pcps_ddev_has_cab_len( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_TZDL:
+ _report_cond( _pcps_ddev_has_tzdl( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_PCPS_TZDL:
+ _report_cond( _pcps_ddev_has_pcps_tzdl( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_TZCODE:
+ _report_cond( _pcps_ddev_has_tzcode( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_TZ:
+ _report_cond( _pcps_ddev_has_tz( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_EVENT_TIME:
+ _report_cond( _pcps_ddev_has_event_time( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_RECEIVER_INFO:
+ _report_cond( _pcps_ddev_has_receiver_info( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_CAN_CLR_UCAP_BUFF:
+ _report_cond( _pcps_ddev_can_clr_ucap_buff( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_UCAP:
+ _report_cond( _pcps_ddev_has_ucap( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_IRIG_TX:
+ _report_cond( _pcps_ddev_has_irig_tx( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_SERIAL_HS:
+ _report_cond( _pcps_ddev_has_serial_hs( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_SIGNAL:
+ _report_cond( _pcps_ddev_has_signal( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_MOD:
+ _report_cond( _pcps_ddev_has_mod( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_IRIG:
+ _report_cond( _pcps_ddev_has_irig( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_REF_OFFS:
+ _report_cond( _pcps_ddev_has_ref_offs( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_OPT_FLAGS:
+ _report_cond( _pcps_ddev_has_opt_flags( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_GPS_DATA:
+ _report_cond( _pcps_ddev_has_gps_data( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_SYNTH:
+ _report_cond( _pcps_ddev_has_synth( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_GENERIC_IO:
+ _report_cond( _pcps_ddev_has_generic_io( pddev ), pout );
+ break;
+
+
+ case IOCTL_PCPS_GENERIC_IO:
+ {
+ IOCTL_GENERIC_CTL ctl;
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buffer_size;
+
+ _io_chk_cond( _pcps_ddev_has_generic_io( pddev ) );
+
+ _pcps_iob_from_pin( IOCTL_GENERIC_CTL, ctl, pin );
+ buffer_size = sizeof( ctl ) +
+ ( ( ctl.data_size_in > ctl.data_size_out ) ?
+ ctl.data_size_in : ctl.data_size_out );
+ p_buff = _pcps_kmalloc( buffer_size );
+
+ if ( p_buff == NULL )
+ goto err_no_mem;
+
+ _pcps_iob_from_pin_size( uint8_t, *p_buff, pin,
+ sizeof( p_buff->ctl ) + ctl.data_size_in );
+
+ _pcps_sem_inc_safe( pddev );
+ rc = pcps_generic_io( pddev, (uint8_t) ctl.info,
+ p_buff->data,
+ (uint8_t) ctl.data_size_in,
+ p_buff->data,
+ (uint8_t) ctl.data_size_out );
+ _pcps_sem_dec( pddev );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ p_buff->ctl = ctl;
+ _pcps_iob_to_pout_size( uint8_t, *p_buff, pout,
+ sizeof( p_buff->ctl ) + ctl.data_size_out );
+ }
+
+ _pcps_kfree( p_buff, buffer_size );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ break;
+ }
+
+
+ case IOCTL_GET_SYNTH_STATE:
+ _io_read_var_chk( pddev, PCPS_GET_SYNTH_STATE,
+ SYNTH_STATE, pout,
+ _pcps_ddev_has_synth( pddev ) );
+ break;
+
+
+ #if _MBG_SUPP_VAR_ACC_SIZE
+ case IOCTL_GET_GPS_ALL_POUT_INFO:
+ _io_read_gps_chk( pddev, PC_GPS_ALL_POUT_INFO,
+ ALL_POUT_INFO, pout, pout_size,
+ _pcps_ddev_has_receiver_info( pddev ) );
+ break;
+ #endif
+
+
+ case IOCTL_SET_GPS_POUT_SETTINGS_IDX:
+ _io_write_gps_var_chk( pddev, PC_GPS_POUT_SETTINGS_IDX,
+ POUT_SETTINGS_IDX, pin,
+ _pcps_ddev_has_receiver_info( pddev ) );
+ break;
+
+#if USE_DEBUG_PORT
+ case IOCTL_MBG_DBG_GET_PORT_ADDR:
+ {
+ _pcps_iob( MBG_DBG_PORT, _s );
+
+ _s = mbg_dbg_port;
+ _pcps_iob_to_pout( MBG_DBG_PORT, _s, pout );
+
+ rc = MBG_SUCCESS;
+ }
+ break;
+
+
+ case IOCTL_MBG_DBG_SET_PORT_ADDR:
+ {
+ _pcps_iob( MBG_DBG_PORT, _s );
+
+ _pcps_iob_from_pin( MBG_DBG_PORT, _s, pin );
+ mbg_dbg_port = _s;
+ mbg_dbg_port_mapped = _pcps_ioremap( mbg_dbg_port, sizeof( mbg_dbg_port ) );
+
+ rc = MBG_SUCCESS;
+ }
+ break;
+#endif // USE_DEBUG_PORT
+
+
+ case IOCTL_GET_MAPPED_MEM_ADDR:
+ {
+ _io_chk_cond( ( pddev->asic_features & PCI_ASIC_HAS_MM_IO ) );
+ _io_get_mapped_mem_address( pddev, pout );
+ }
+ break;
+
+
+ case IOCTL_UNMAP_MAPPED_MEM:
+ {
+ _io_chk_cond( ( pddev->asic_features & PCI_ASIC_HAS_MM_IO ) );
+ _io_unmap_mapped_mem_address( pddev, pin );
+ }
+ break;
+
+
+ case IOCTL_GET_PCI_ASIC_FEATURES:
+ _io_chk_cond( _pcps_ddev_has_asic_features( pddev ) );
+ {
+ _pcps_iob( PCI_ASIC_FEATURES, _s );
+
+ _s = pddev->asic_features;
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( PCI_ASIC_FEATURES, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_HAS_PCI_ASIC_FEATURES:
+ _report_cond( _pcps_ddev_has_asic_features( pddev ), pout );
+ break;
+
+
+ case IOCTL_HAS_PCI_ASIC_VERSION:
+ _report_cond( _pcps_ddev_has_asic_version( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_IS_MSF:
+ _report_cond( _pcps_ddev_is_msf( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_IS_WWVB:
+ _report_cond( _pcps_ddev_is_wwvb( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_IS_LWR:
+ _report_cond( _pcps_ddev_is_lwr( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_IRQ_STAT_INFO:
+ {
+ _pcps_iob( PCPS_IRQ_STAT_INFO, _s );
+
+ _s = pddev->irq_stat_info;
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( PCPS_IRQ_STAT_INFO, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_GET_CYCLES_FREQUENCY:
+ {
+ _pcps_iob( MBG_PC_CYCLES_FREQUENCY, _s );
+
+ mbg_get_pc_cycles_frequency( &(_s) );
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( MBG_PC_CYCLES_FREQUENCY, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_HAS_FAST_HR_TIMESTAMP:
+ _report_cond( _pcps_ddev_has_fast_hr_timestamp( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES:
+ {
+ _pcps_iob( PCPS_TIME_STAMP_CYCLES, _s );
+
+ if ( !_pcps_ddev_has_fast_hr_timestamp( pddev ) )
+ goto err_support;
+
+ do_get_fast_hr_timestamp_cycles_safe( pddev, &_s );
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( PCPS_TIME_STAMP_CYCLES, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_GET_FAST_HR_TIMESTAMP:
+ {
+ _pcps_iob( PCPS_TIME_STAMP, _s );
+
+ if ( !_pcps_ddev_has_fast_hr_timestamp( pddev ) )
+ goto err_support;
+
+ do_get_fast_hr_timestamp_safe( pddev, &_s );
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( PCPS_TIME_STAMP, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_DEV_HAS_GPS_TIME_SCALE:
+ _report_cond( _pcps_ddev_has_time_scale( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_GPS_TIME_SCALE_INFO:
+ _io_read_gps_var_chk( pddev, PC_GPS_TIME_SCALE,
+ MBG_TIME_SCALE_INFO, pout,
+ _pcps_ddev_has_time_scale( pddev ) );
+ break;
+
+
+ case IOCTL_SET_GPS_TIME_SCALE_SETTINGS:
+ _io_write_gps_var_chk( pddev, PC_GPS_TIME_SCALE,
+ MBG_TIME_SCALE_SETTINGS, pin,
+ _pcps_ddev_has_time_scale( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_HAS_GPS_UTC_PARM:
+ _report_cond( _pcps_ddev_has_utc_parm( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_GPS_UTC_PARM:
+ _io_read_gps_var_chk( pddev, PC_GPS_UTC,
+ UTC, pout,
+ _pcps_ddev_has_utc_parm( pddev ) );
+ break;
+
+
+ case IOCTL_SET_GPS_UTC_PARM:
+ _io_write_gps_var_chk( pddev, PC_GPS_UTC,
+ UTC, pin,
+ _pcps_ddev_has_utc_parm( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_HAS_IRIG_CTRL_BITS:
+ _report_cond( _pcps_ddev_has_irig_ctrl_bits( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_IRIG_CTRL_BITS:
+ _io_read_var_chk( pddev, PCPS_GET_IRIG_CTRL_BITS,
+ MBG_IRIG_CTRL_BITS, pout,
+ _pcps_ddev_has_irig_ctrl_bits( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_HAS_LAN_INTF:
+ _report_cond( _pcps_ddev_has_lan_intf( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_LAN_IF_INFO:
+ _io_read_gps_var_chk( pddev, PC_GPS_LAN_IF_INFO,
+ LAN_IF_INFO, pout,
+ _pcps_ddev_has_lan_intf( pddev ) );
+ break;
+
+
+ case IOCTL_GET_IP4_STATE:
+ _io_read_gps_var_chk( pddev, PC_GPS_IP4_STATE,
+ IP4_SETTINGS, pout,
+ _pcps_ddev_has_lan_intf( pddev ) );
+ break;
+
+
+ case IOCTL_GET_IP4_SETTINGS:
+ _io_read_gps_var_chk( pddev, PC_GPS_IP4_SETTINGS,
+ IP4_SETTINGS, pout,
+ _pcps_ddev_has_lan_intf( pddev ) );
+ break;
+
+
+ case IOCTL_SET_IP4_SETTINGS:
+ _io_write_gps_var_chk( pddev, PC_GPS_IP4_SETTINGS,
+ IP4_SETTINGS, pin,
+ _pcps_ddev_has_lan_intf( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_IS_PTP:
+ _report_cond( _pcps_ddev_is_ptp( pddev ), pout );
+ break;
+
+
+ case IOCTL_DEV_HAS_PTP:
+ _report_cond( _pcps_ddev_has_ptp( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_PTP_STATE:
+ _io_read_gps_var_chk( pddev, PC_GPS_PTP_STATE,
+ PTP_STATE, pout,
+ _pcps_ddev_has_ptp( pddev ) );
+ break;
+
+
+ case IOCTL_GET_PTP_CFG_INFO:
+ _io_read_gps_var_chk( pddev, PC_GPS_PTP_CFG,
+ PTP_CFG_INFO, pout,
+ _pcps_ddev_has_ptp( pddev ) );
+ break;
+
+
+ case IOCTL_SET_PTP_CFG_SETTINGS:
+ _io_write_gps_var_chk( pddev, PC_GPS_PTP_CFG,
+ PTP_CFG_SETTINGS, pin,
+ _pcps_ddev_has_ptp( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_HAS_IRIG_TIME:
+ _report_cond( _pcps_ddev_has_irig_time( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_IRIG_TIME:
+ _io_read_var_chk( pddev, PCPS_GIVE_IRIG_TIME,
+ PCPS_IRIG_TIME, pout,
+ _pcps_ddev_has_irig_time( pddev ) );
+ break;
+
+
+ case IOCTL_GET_RAW_IRIG_DATA:
+ _io_read_var_chk( pddev, PCPS_GET_RAW_IRIG_DATA,
+ MBG_RAW_IRIG_DATA, pout,
+ _pcps_ddev_has_raw_irig_data( pddev ) );
+ break;
+
+
+ case IOCTL_DEV_HAS_PTP_UNICAST:
+ _report_cond( _pcps_ddev_has_ptp_unicast( pddev ), pout );
+ break;
+
+
+ case IOCTL_GET_PTP_UNICAST_CFG_INFO:
+ _io_read_gps_var_chk( pddev, PC_GPS_PTP_UNICAST_CFG,
+ PTP_UNICAST_CFG_INFO, pout,
+ _pcps_ddev_has_ptp_unicast( pddev ) );
+ break;
+
+
+ case IOCTL_SET_PTP_UNICAST_CFG_SETTINGS:
+ _io_write_gps_var_chk( pddev, PC_GPS_PTP_UNICAST_CFG,
+ PTP_UNICAST_CFG_SETTINGS, pin,
+ _pcps_ddev_has_ptp_unicast( pddev ) );
+ break;
+
+
+ case IOCTL_GET_TIME_INFO_HRT:
+ {
+ _pcps_iob( MBG_TIME_INFO_HRT, _s );
+
+ if ( !_pcps_ddev_has_hr_time( pddev ) )
+ goto err_support;
+
+ mbg_get_pc_cycles( &_s.sys_time_cycles.cyc_before );
+ mbg_get_sys_time( &_s.sys_time_cycles.sys_time );
+ mbg_get_pc_cycles( &_s.sys_time_cycles.cyc_after );
+
+ _pcps_sem_inc_safe( pddev );
+ rc = _pcps_read_var( pddev, PCPS_GIVE_HR_TIME, _s.ref_hr_time_cycles.t );
+ _s.ref_hr_time_cycles.cycles =(pddev)->acc_cycles;
+ _pcps_sem_dec( pddev );
+
+ if ( rc != MBG_SUCCESS )
+ goto err_access;
+
+ _pcps_iob_to_pout( MBG_TIME_INFO_HRT, _s, pout );
+ }
+ break;
+
+
+ case IOCTL_GET_TIME_INFO_TSTAMP:
+ {
+ _pcps_iob( MBG_TIME_INFO_TSTAMP, _s );
+
+ if ( !_pcps_ddev_has_fast_hr_timestamp( pddev ) )
+ goto err_support;
+
+ mbg_get_pc_cycles( &_s.sys_time_cycles.cyc_before );
+ mbg_get_sys_time( &_s.sys_time_cycles.sys_time );
+ mbg_get_pc_cycles( &_s.sys_time_cycles.cyc_after );
+
+ do_get_fast_hr_timestamp_cycles_safe( pddev, &(_s).ref_tstamp_cycles );
+
+ rc = MBG_SUCCESS;
+
+ _pcps_iob_to_pout( MBG_TIME_INFO_TSTAMP, _s, pout );
+ }
+ break;
+
+#if USE_DEBUG_PORT
+ case IOCTL_MBG_DBG_SET_BIT:
+ {
+ _pcps_iob( MBG_DBG_DATA, _s );
+ _pcps_iob( MBG_PC_CYCLES, _c );
+
+ _pcps_iob_from_pin( MBG_DBG_DATA, _s, pin );
+
+ _mbg_dbg_set_bit( pddev, _s );
+ mbg_get_pc_cycles( &(_c) );
+
+ _pcps_iob_to_pout( MBG_PC_CYCLES, _c, pout );
+ }
+ break;
+
+
+ case IOCTL_MBG_DBG_CLR_BIT:
+ {
+ _pcps_iob( MBG_DBG_DATA, _s );
+ _pcps_iob( MBG_PC_CYCLES, _c );
+
+ _pcps_iob_from_pin( MBG_DBG_DATA, _s, pin );
+
+ _mbg_dbg_clr_bit( pddev, _s );
+ mbg_get_pc_cycles( &(_c) );
+
+ _pcps_iob_to_pout( MBG_PC_CYCLES, _c, pout );
+ }
+ break;
+
+
+ case IOCTL_MBG_DBG_CLR_ALL:
+ {
+ _pcps_iob( MBG_PC_CYCLES, _c );
+ _mbg_dbg_clr_all( pddev );
+ mbg_get_pc_cycles( &(_c) );
+
+ _pcps_iob_to_pout( MBG_PC_CYCLES, _c, pout );
+ }
+ break;
+#endif
+
+
+ default:
+ goto err_inval;
+
+ }
+
+ return rc;
+
+
+err_inval:
+ return MBG_ERR_INV_DEV_REQUEST;
+
+err_support:
+ return MBG_ERR_NOT_SUPP_BY_DEV;
+
+err_no_mem:
+ return MBG_ERR_NO_MEM;
+
+err_busy_unsafe:
+ return MBG_ERR_IRQ_UNSAFE;
+
+err_access:
+ return rc; // return the rc from the low level routine
+
+
+#if defined( MBG_TGT_LINUX ) || defined( MBG_TGT_NETBSD )
+
+err_to_user:
+ return -EFAULT;
+
+err_from_user:
+ return -EFAULT;
+
+#endif // defined( MBG_TGT_LINUX )
+
+} // ioctl_switch
+
+#endif /* _MACIOCTL_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h b/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h
new file mode 100755
index 0000000..cdf6f01
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h
@@ -0,0 +1,165 @@
+
+/**************************************************************************
+ *
+ * $Id: mbg_arch.h 1.3.1.2 2011/02/09 15:46:48 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions to support different computer hardware architectures.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbg_arch.h $
+ * Revision 1.3.1.2 2011/02/09 15:46:48 martin
+ * Revision 1.3.1.1 2011/02/09 15:26:58 martin
+ * Revision 1.3 2009/06/12 13:12:37Z martin
+ * Fixed compiler warning.
+ * Revision 1.2 2009/03/19 15:14:15 martin
+ * Fixed byte swapping of doubles for SPARC architecture.
+ * Revision 1.1 2008/12/05 13:47:42 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBG_ARCH_H
+#define _MBG_ARCH_H
+
+#include <mbg_tgt.h>
+
+#if !defined( MBG_TGT_KERNEL )
+ #include <stdlib.h>
+#endif
+
+
+#if defined( MBG_ARCH_SPARC )
+ #define MBG_ARCH_BIG_ENDIAN 1
+#endif
+
+
+#if !defined( MBG_ARCH_BIG_ENDIAN )
+ #define MBG_ARCH_LITTLE_ENDIAN 1
+#endif
+
+
+
+#if defined( MBG_TGT_LINUX )
+
+ #include <asm/byteorder.h>
+
+ #if defined( MBG_TGT_KERNEL )
+ #include <asm/unaligned.h>
+
+ #define _mbg_put_unaligned( _v, _p ) put_unaligned( _v, _p )
+ #define _mbg_get_unaligned( _p ) get_unaligned( _p )
+ #endif
+
+#endif
+
+
+
+// If no macros required to access unaligned data have yet been defined,
+// define some default macros assuming no special handling is required
+// to access unaligned data.
+
+#if !defined( _pcps_put_unaligned )
+ #define _pcps_put_unaligned( _v, _p ) ((void)( *(_p) = (_v) ))
+#endif
+
+#if !defined( _pcps_get_unaligned )
+ #define _pcps_get_unaligned( _p ) (*(_p))
+#endif
+
+
+
+// If no macros to convert endianess have yet been defined, define
+// some default macros assuming endianess conversion is not required.
+
+#if !defined( __le16_to_cpu )
+ #define __le16_to_cpu( _x ) (_x)
+#endif
+
+#if !defined( __le32_to_cpu )
+ #define __le32_to_cpu( _x ) (_x)
+#endif
+
+#if !defined( __le64_to_cpu )
+ #define __le64_to_cpu( _x ) (_x)
+#endif
+
+#if !defined( __cpu_to_le16 )
+ #define __cpu_to_le16( _x ) (_x)
+#endif
+
+#if !defined( __cpu_to_le32 )
+ #define __cpu_to_le32( _x ) (_x)
+#endif
+
+#if !defined( __cpu_to_le64 )
+ #define __cpu_to_le64( _x ) (_x)
+#endif
+
+
+
+// The macros below are used to convert the endianess
+// of the plug-in cards to the endianess of the host CPU
+
+#define _mbg8_to_cpu( _x ) ( _x )
+#define _mbg16_to_cpu( _x ) __le16_to_cpu( _x )
+#define _mbg32_to_cpu( _x ) __le32_to_cpu( _x )
+#define _mbg64_to_cpu( _x ) __le64_to_cpu( _x )
+
+#define _cpu_to_mbg8( _x ) ( _x )
+#define _cpu_to_mbg16( _x ) __cpu_to_le16( _x )
+#define _cpu_to_mbg32( _x ) __cpu_to_le32( _x )
+#define _cpu_to_mbg64( _x ) __cpu_to_le64( _x )
+
+
+
+// swap a double type variable bytewise e.g. to convert the endianess
+
+static __mbg_inline
+void mbg_swab_double( double *p )
+{
+#if 0 // The __swab64() may not work correctly for whatever reason ...
+ __swab64p( p );
+#else // ... so we do the swapping manually
+ double d = 0;
+ size_t i;
+
+ for ( i = 0; i < sizeof( double); i++ )
+ BYTE_OF( d, i ) = BYTE_OF( *p, ( sizeof( double) - 1 - i ) );
+
+ for ( i = 0; i < sizeof( double); i++ )
+ BYTE_OF( *p, i ) = BYTE_OF( d, i );
+#endif
+
+} // mbg_swab_double
+
+
+
+#if defined( MBG_ARCH_BIG_ENDIAN )
+
+ #define _mbg_swab16( _p ) *(_p) = __swab16( *(_p) )
+ #define _mbg_swab32( _p ) *(_p) = __swab32( *(_p) )
+
+ #define _mbg_swab_double( _p ) mbg_swab_double( _p )
+
+ #define _mbg_swab_doubles( _p, _n ) \
+ { \
+ int i; \
+ for ( i = 0; i < (_n); i++ ) \
+ _mbg_swab_double( &_p[i] ); \
+ }
+
+#else
+
+ #define _mbg_swab16( _p ) _nop_macro_fnc()
+ #define _mbg_swab32( _p ) _nop_macro_fnc()
+
+ #define _mbg_swab_double( _p ) _nop_macro_fnc()
+
+ #define _mbg_swab_doubles( _p, _n ) _nop_macro_fnc()
+
+#endif
+
+#endif /* _MBG_ARCH_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h b/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h
new file mode 100755
index 0000000..a3c45d1
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h
@@ -0,0 +1,443 @@
+
+/**************************************************************************
+ *
+ * $Id: mbg_tgt.h 1.22.2.11 2011/03/22 10:25:26 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Check the build environment and setup control definitions
+ * for the Meinberg library modules.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbg_tgt.h $
+ * Revision 1.22.2.11 2011/03/22 10:25:26 martin
+ * Fixed typo in comment.
+ * Revision 1.22.2.10 2011/02/09 15:46:48 martin
+ * Revision 1.22.2.9 2011/02/09 15:27:10 martin
+ * Revision 1.22.2.8 2011/02/04 10:15:54Z martin
+ * Revision 1.22.2.7 2011/02/01 17:11:54 martin
+ * Revision 1.22.2.6 2011/01/27 16:16:28 martin
+ * Support wchar_t for BSD.
+ * Revision 1.22.2.5 2011/01/24 17:08:40 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.22.2.4 2010/12/14 11:04:02 martin
+ * Revision 1.22.2.3 2010/05/25 14:42:32Z martin
+ * Don't use MM I/O on IA64 platform.
+ * Revision 1.22.2.2 2010/05/21 13:09:35 martin
+ * Initial support for IA64 platform.
+ * Revision 1.22.2.1 2010/04/22 09:35:56 martin
+ * Distinguish between different gcc target platforms.
+ * Revision 1.22 2009/10/01 08:20:50 martin
+ * Fixed inline code support with different BC versions.
+ * Revision 1.1 2009/11/20 12:24:05 philipp
+ * Revision 1.21 2009/09/01 10:34:23Z martin
+ * Don't define __mbg_inline for CVI and undefined targets.
+ * Revision 1.20 2009/08/18 15:14:26 martin
+ * Defined default MBG_INVALID_PORT_HANDLE for non-Windows targets.
+ * Revision 1.19 2009/06/09 10:03:58 daniel
+ * Preliminary support for ARM architecture.
+ * Revision 1.18 2009/04/01 14:10:55 martin
+ * Cleanup for CVI.
+ * Revision 1.17 2009/03/19 15:21:07Z martin
+ * Conditionally define DWORD_PTR type for old MS C compilers.
+ * Revision 1.16 2008/12/08 16:42:30 martin
+ * Defined _GNU_SOURCE for Linux.
+ * Revision 1.15 2008/11/19 15:31:49 martin
+ * Added symbol MBG_ARCH_I386.
+ * Revision 1.14 2008/09/03 15:06:04 martin
+ * Support DOS protected mode target.
+ * Support SUN SPARC architecture.
+ * Specified handle types for common host environments.
+ * Added macro MBG_USE_MM_IO_FOR_PCI.
+ * Added macro _nop_macro_fnc().
+ * Revision 1.13 2008/01/30 15:52:22 martin
+ * Modified checking for availability of wchar_t.
+ * Revision 1.13 2008/01/29 15:18:07Z martin
+ * Recognize DOS target under Watcom compilers.
+ * Flag Watcom C always supports wchar_t.
+ * Revision 1.12 2008/01/17 09:38:50Z daniel
+ * Added macros to determine whether C language extensions
+ * (e.g. C94, C99) are supported by the target environment.
+ * Added macro to check whether wchar_t and friends are
+ * supported, and some compatibility stuff.
+ * Revision 1.11 2007/10/31 16:58:03 martin
+ * Fixed __mbg_inline for Borland C (DOS).
+ * Revision 1.10 2007/09/25 08:10:27Z martin
+ * Support CVI target environment.
+ * Added MBG_PORT_HANDLE type for serial ports.
+ * Added macros for unified inline code syntax.
+ * Revision 1.9 2006/12/08 12:45:54Z martin
+ * Under Windows include ntddk.h rather than windows.h
+ * if building kernel driver .
+ * Revision 1.8 2006/10/25 12:20:45Z martin
+ * Initial support for FreeBSD, NetBSD, and OpenBSD.
+ * Added definitions for generic handle types.
+ * Revision 1.7 2006/08/23 13:43:55 martin
+ * Added definition for MBG_TGT_UNIX.
+ * Minor syntax fixes.
+ * Revision 1.6 2006/01/25 14:37:06 martin
+ * Added definitions for 64 bit Windows environments.
+ * Revision 1.5 2003/12/17 16:11:41Z martin
+ * Split API modifiers into _MBG_API and _MBG_API_ATTR.
+ * Revision 1.4 2003/06/19 08:20:22Z martin
+ * Added WINAPI attribute for DLL exported functions.
+ * Revision 1.3 2003/04/09 13:37:20Z martin
+ * Added definition for _MBG_API.
+ * Revision 1.2 2003/02/24 16:08:45Z martin
+ * Don't setup for Win32 PNP if explicitely configured non-PNP.
+ * Revision 1.1 2002/02/19 13:46:20Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBG_TGT_H
+#define _MBG_TGT_H
+
+
+/* Other headers to be included */
+
+#ifdef _MBG_TGT
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _CVI ) || defined( _CVI_ )
+
+ #define MBG_TGT_WIN32
+ #define MBG_TGT_CVI
+
+#elif defined( _WIN32_WINNT )
+
+ // MS platform SDK
+ // WinNT 4.0 and above
+ #define MBG_TGT_WIN32
+
+ #if ( _WIN32_WINNT >= 0x0500 )
+ // Win2k and above
+ #if !defined( MBG_TGT_WIN32_NON_PNP )
+ // only if not explicitely disabled
+ #define MBG_TGT_WIN32_PNP
+ #endif
+ #endif
+
+#elif defined( WINVER )
+
+ // MS platform SDK
+ // Win95, WinNT 4.0 and above
+ #define MBG_TGT_WIN32
+
+ #if ( WINVER >= 0x0500 )
+ // Win98, Win2k and above
+ // #define ...
+ #endif
+
+#elif defined( __WIN32__ )
+
+ // Borland C++ Builder
+ #define MBG_TGT_WIN32
+
+#elif defined( _WIN32 )
+
+ // MS Visual C++
+ #define MBG_TGT_WIN32
+
+#elif defined( __WINDOWS_386__ )
+
+ // Watcom C/C++ for target Win32
+ #define MBG_TGT_WIN32
+
+#elif defined( __NETWARE_386__ )
+
+ // Watcom C/C++ for target NetWare
+ #define MBG_TGT_NETWARE
+
+#elif defined( __OS2__ )
+
+ // Watcom C/C++ for target OS/2
+ #define MBG_TGT_OS2
+
+#elif defined( __linux )
+
+ // GCC for target Linux
+ #define MBG_TGT_LINUX
+ #define _GNU_SOURCE 1
+
+ #if defined( __KERNEL__ )
+ #define MBG_TGT_KERNEL
+ #endif
+
+#elif defined( __FreeBSD__ )
+
+ // GCC for target FreeBSD
+ #define MBG_TGT_FREEBSD
+
+#elif defined( __NetBSD__ )
+
+ // GCC for target NetBSD
+ #define MBG_TGT_NETBSD
+
+#elif defined( __OpenBSD__ )
+
+ // GCC for target OpenBSD
+ #define MBG_TGT_OPENBSD
+
+#elif defined( __QNX__ )
+
+ // any compiler for target QNX
+ #define MBG_TGT_QNX
+
+ #if defined( __QNXNTO__ )
+ // target QNX Neutrino
+ #define MBG_TGT_QNX_NTO
+ #endif
+
+#elif defined( __MSDOS__ ) || defined( __DOS__ )
+
+ // any compiler for target DOS
+ #define MBG_TGT_DOS
+
+ #if defined( __WATCOMC__ ) && defined( __386__ )
+
+ #define MBG_TGT_DOS_PM // protected mode DOS
+
+ #endif
+
+#endif
+
+// Some definitions which depend on the type of compiler ...
+
+#if defined( __GNUC__ )
+
+ #define __mbg_inline __inline__
+
+ #define MBG_TGT_HAS_WCHAR_T 1
+
+ #if defined( __i386__ )
+
+ #define MBG_ARCH_I386
+ #define MBG_ARCH_X86
+
+ #elif defined( __x86_64__ )
+
+ #define MBG_ARCH_X86_64
+ #define MBG_ARCH_X86
+
+ #elif defined( __ia64__ )
+
+ #define MBG_ARCH_IA64
+
+ #elif defined( __sparc__ )
+
+ #define MBG_ARCH_SPARC
+ #define MBG_USE_MM_IO_FOR_PCI 1
+
+ #elif defined( __arm__ )
+
+ #define MBG_ARCH_ARM
+
+ #endif
+
+#elif defined( _MSC_VER )
+
+ #define __mbg_inline __forceinline
+
+ #define MBG_TGT_HAS_WCHAR_T 1
+
+#elif defined( _CVI ) || defined( _CVI_ )
+
+ // Inline code is not supported.
+
+ #define MBG_TGT_HAS_WCHAR_T 0
+
+#elif defined( __BORLANDC__ )
+
+ #if defined( __cplusplus )
+ #define __mbg_inline inline // standard C++ syntax
+ #elif ( __BORLANDC__ > 0x410 ) // BC3.1 defines 0x410 !
+ #define __mbg_inline __inline // newer BC versions support this for C
+ #else
+ #define __mbg_inline // up to BC3.1 not supported for C
+ #endif
+
+ #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 )
+
+#elif defined( __WATCOMC__ )
+
+ #define __mbg_inline _inline
+
+ #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 )
+
+#endif
+
+
+
+#if defined( MBG_TGT_FREEBSD ) \
+ || defined( MBG_TGT_NETBSD ) \
+ || defined( MBG_TGT_OPENBSD )
+ #define MBG_TGT_BSD
+
+ #if defined( _KERNEL )
+ #define MBG_TGT_KERNEL
+ #endif
+
+#endif
+
+#if defined( MBG_TGT_LINUX ) \
+ || defined( MBG_TGT_BSD ) \
+ || defined( MBG_TGT_QNX_NTO )
+ #define MBG_TGT_UNIX
+#endif
+
+
+
+#if defined( MBG_TGT_WIN32 )
+
+ #if defined( _AMD64_ )
+ // This is used for AMD64 architecture and for
+ // Intel XEON CPUs with 64 bit extension.
+ #define MBG_TGT_WIN32_PNP_X64
+ #define WIN32_FLAVOR "x64"
+ #elif defined( _IA64_ )
+ #define MBG_TGT_WIN32_PNP_IA64
+ #define WIN32_FLAVOR "ia64"
+ #endif
+
+ #if defined( _KDD_ )
+ #include <ntddk.h>
+ #else
+ // This must not be used for kernel drivers.
+ #include <windows.h>
+ typedef HANDLE MBG_HANDLE;
+
+ #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE
+
+ #if defined( MBG_TGT_CVI )
+ // CVI uses an own set of functions to support serial ports
+ typedef int MBG_PORT_HANDLE;
+ #define MBG_INVALID_PORT_HANDLE -1
+ #else
+ typedef HANDLE MBG_PORT_HANDLE;
+ #endif
+
+ // The DWORD_PTR type is not defined in the headers shipping
+ // with VC6. However, if the SDK is installed then the SDK's
+ // headers may declare this type. This is at least the case
+ // in the Oct 2001 SDK which also defines the symbol _W64.
+ #if !defined( _W64 )
+ typedef DWORD DWORD_PTR;
+ #endif
+
+ #endif
+
+ #define _MBG_API WINAPI
+
+ #if defined( MBG_LIB_EXPORT )
+ #define _MBG_API_ATTR __declspec( dllexport )
+ #else
+ #define _MBG_API_ATTR __declspec( dllimport )
+ #endif
+
+#elif defined( MBG_TGT_UNIX )
+
+ typedef int MBG_HANDLE;
+ typedef int MBG_PORT_HANDLE;
+
+ #define MBG_INVALID_HANDLE -1
+
+#else
+
+ typedef int MBG_HANDLE;
+ typedef int MBG_PORT_HANDLE;
+
+ #define MBG_INVALID_HANDLE -1
+
+#endif
+
+
+#if !defined( _MBG_API )
+ #define _MBG_API
+#endif
+
+#if !defined( _MBG_API_ATTR )
+ #define _MBG_API_ATTR
+#endif
+
+#if !defined( MBG_INVALID_PORT_HANDLE )
+ #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE
+#endif
+
+#if !defined( MBG_USE_MM_IO_FOR_PCI )
+ #define MBG_USE_MM_IO_FOR_PCI 0
+#endif
+
+
+#if !defined( _nop_macro_fnc )
+ #define _nop_macro_fnc() do {} while (0)
+#endif
+
+
+// The macros below are defined in order to be able to check if
+// certain C language extensions are available on the target system:
+#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199409L )
+ #define MBG_TGT_C94 1
+#else
+ #define MBG_TGT_C94 0
+#endif
+
+
+#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L )
+ #define MBG_TGT_C99 1
+#else
+ #define MBG_TGT_C99 0
+#endif
+
+// Check if wchar_t is supported
+#if !defined( MBG_TGT_HAS_WCHAR_T )
+ #define MBG_TGT_HAS_WCHAR_T ( MBG_TGT_C94 || defined( WCHAR_MAX ) )
+#endif
+
+#if !MBG_TGT_HAS_WCHAR_T
+ // Even if wchar_t is not natively supported by the target platform
+ // there may already be a compatibility define (e.g. BC3.1)
+ // However, some functions may be missing (e.g. snwprintf()).
+ #if !defined( _WCHAR_T ) /* BC3.1 */ \
+ && !defined( _WCHAR_T_DEFINED_ ) /* WC11 */
+ #define _WCHAR_T
+ #define wchar_t char
+ #endif
+#endif
+
+
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _MBG_TGT_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h
new file mode 100755
index 0000000..d1aa8ae
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h
@@ -0,0 +1,152 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgddmsg.h 1.9 2011/01/26 18:13:49 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Print or remove debug messages by redefinitions.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgddmsg.h $
+ * Revision 1.9 2011/01/26 18:13:49 martin
+ * Support for *BSD.
+ * Revision 1.8 2009/04/22 09:54:55 martin
+ * Include mbg_tgt.h also if building without DEBUG.
+ * Revision 1.7 2009/03/19 15:22:54 martin
+ * Cleaned up debug levels.
+ * Revision 1.6 2008/12/05 13:31:47 martin
+ * Use do {} while (0) syntax to avoid potential syntax problems.
+ * Added _mbgddmsg_7().
+ * Revision 1.5 2006/06/19 15:26:19 martin
+ * Fixed compiler warnings if DEBUG or DBG not defined.
+ * Revision 1.4 2002/06/12 12:25:54 martin
+ * Bug fix: check for target MBG_TGT_WIN32 instead of MBG_TGT_W32.
+ * Revision 1.3 2002/02/19 14:50:48Z MARTIN
+ * Added support for Win32.
+ * Revision 1.2 2002/02/19 09:28:00 MARTIN
+ * Use new header mbg_tgt.h to check the target environment.
+ * Revision 1.1 2001/03/02 13:51:23 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBGDDMSG_H
+#define _MBGDDMSG_H
+
+
+#include <mbg_tgt.h>
+
+#if defined( DEBUG ) || ( defined( DBG ) && DBG )
+
+enum
+{
+ MBG_DBG_ERR,
+ MBG_DBG_WARN,
+ MBG_DBG_INFO,
+ MBG_DBG_DETAIL,
+ MBG_DBG_INIT_DEV,
+ MBG_DEBUG_SEM,
+ MBG_DBG_IRQ,
+ N_MBG_DBG_LVL
+};
+
+extern int debug;
+
+#define _chk_lvl( _lvl ) ( (_lvl) < debug )
+
+#if defined( MBG_TGT_NETWARE )
+ #include <conio.h>
+ #define _printf ConsolePrintf
+ #define _hd
+ #define _tl "\n"
+#elif defined( MBG_TGT_OS2 )
+ #include <iprintf.h>
+ #define _printf iprintf
+ #define _hd
+ #define _tl "\n"
+#elif defined( MBG_TGT_WIN32 )
+ #include <ntddk.h>
+ #define _printf DbgPrint
+ #define _hd
+ #define _tl "\n"
+#elif defined( MBG_TGT_LINUX )
+ // #include <printk.h>
+ #define _printf printk
+ #define _hd KERN_INFO
+ #define _tl "\n"
+#elif defined( MBG_TGT_BSD )
+ #define _printf printf
+ #define _hd
+ #define _tl "\n"
+#else // MBG_TGT_QNX, MBG_TGT_DOS, ...
+ #include <stdio.h>
+ #define _printf printf
+ #define _hd
+ #define _tl "\n"
+#endif
+
+
+#define _mbgddmsg_0( _lvl, _fmt ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl ); } \
+} while ( 0 )
+
+#define _mbgddmsg_1( _lvl, _fmt, _p1 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1) ); } \
+} while ( 0 )
+
+#define _mbgddmsg_2( _lvl, _fmt, _p1, _p2 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1), (_p2) ); } \
+} while ( 0 )
+
+#define _mbgddmsg_3( _lvl, _fmt, _p1, _p2, _p3 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3) ); } \
+} while ( 0 )
+
+#define _mbgddmsg_4( _lvl, _fmt, _p1, _p2, _p3, _p4 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4) ); } \
+} while ( 0 )
+
+#define _mbgddmsg_5( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5) ); } \
+} while ( 0 )
+
+#define _mbgddmsg_6( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6) ); } \
+} while ( 0 )
+
+#define _mbgddmsg_7( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6, _p7 ) \
+do { \
+ if ( _chk_lvl( _lvl ) ) \
+ { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6), (_p7) ); } \
+} while ( 0 )
+
+#else
+
+ #define _mbgddmsg_0( _lvl, _fmt ) _nop_macro_fnc()
+ #define _mbgddmsg_1( _lvl, _fmt, _p1 ) _nop_macro_fnc()
+ #define _mbgddmsg_2( _lvl, _fmt, _p1, _p2 ) _nop_macro_fnc()
+ #define _mbgddmsg_3( _lvl, _fmt, _p1, _p2, _p3 ) _nop_macro_fnc()
+ #define _mbgddmsg_4( _lvl, _fmt, _p1, _p2, _p3, _p4 ) _nop_macro_fnc()
+ #define _mbgddmsg_5( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5 ) _nop_macro_fnc()
+ #define _mbgddmsg_6( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6 ) _nop_macro_fnc()
+ #define _mbgddmsg_7( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6, _p7 ) _nop_macro_fnc()
+
+#endif
+
+#endif /* _MBGDDMSG_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c
new file mode 100755
index 0000000..e4f8c8b
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c
@@ -0,0 +1,6164 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgdevio.c 1.35.1.15 2011/02/16 10:15:13 martin TRASH martin(2011.02.16.10.15.13) $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions called from user space to access Meinberg device drivers.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgdevio.c $
+ * Revision 1.35.1.15 2011/02/16 10:15:13 martin
+ * Revision 1.35.1.14 2011/02/15 14:24:55Z martin
+ * Revision 1.35.1.13 2011/02/15 11:21:47 daniel
+ * Added API calls to support PTP unicast.
+ * Revision 1.35.1.12 2011/02/09 17:08:28Z martin
+ * Specify I/O range number when calling port I/O macros
+ * so they can be used for different ranges under BSD.
+ * Revision 1.35.1.11 2011/02/01 15:08:08 martin
+ * Revision 1.35.1.10 2011/01/28 09:33:21 martin
+ * Modifications to support FreeBSD.
+ * Revision 1.35.1.9 2010/12/14 11:23:47 martin
+ * Moved definition of MBG_HW_NAME to the header file.
+ * Revision 1.35.1.8 2010/12/14 10:56:33Z martin
+ * Revision 1.35.1.7 2010/08/18 13:43:20 martin
+ * Revision 1.35.1.6 2010/08/11 13:48:52 martin
+ * Cleaned up comments.
+ * Revision 1.35.1.5 2010/08/11 12:43:51 martin
+ * Revision 1.35.1.4 2010/05/21 13:10:37 martin
+ * Fixed platforms where cycles are not supported.
+ * Revision 1.35.1.3 2010/04/26 14:46:41 martin
+ * Compute PC cycles frequency under Linux if cpu_tick is not set by the kernel.
+ * Revision 1.35.1.2 2010/02/09 14:05:38 stefan
+ * Fixed a bug that kept the function mbg_open_device_by_name in a loop under certain conditions.
+ * Revision 1.35.1.1 2010/02/05 11:49:26 martin
+ * Made xhrt leap second check an inline function.
+ * Revision 1.35 2010/01/12 13:40:25 martin
+ * Fixed a typo in mbg_dev_has_raw_irig_data().
+ * Revision 1.34 2009/12/15 15:34:58Z daniel
+ * Support reading the raw IRIG data bits for firmware versions
+ * which support this feature.
+ * Revision 1.33 2009/09/29 15:08:40Z martin
+ * Support retrieving time discipline info.
+ * Revision 1.32 2009/08/17 13:46:29 martin
+ * Moved specific definition of symbol _HAVE_IOCTL_WITH_SIZE
+ * to mbgioctl.h and renamed it to _MBG_SUPP_VAR_ACC_SIZE.
+ * Revision 1.31 2009/08/12 14:28:26 daniel
+ * Included PTP functions in build.
+ * Revision 1.30 2009/06/19 12:19:41Z martin
+ * Support reading raw IRIG time.
+ * Revision 1.29 2009/06/08 18:23:22 daniel
+ * Added PTP configuration functions and PTP state functions, but
+ * they are still excluded from build.
+ * Added calls to support simple LAN interface configuration.
+ * Revision 1.28 2009/03/19 15:30:04 martin
+ * Added support for configurable time scales.
+ * Support reading/writing GPS UTC parameters.
+ * Support reading IRIG control function bits.
+ * Support reading MM timestamps without cycles.
+ * Fixed endianess correction in mbg_get_gps_pos().
+ * Endianess correction for ASIC version and ASIC features
+ * is now done by the kernel driver.
+ * Use generic cycles types and functions in mbg_get_default_cycles_frequency().
+ * mbg_tgt.h is now included in mbgdevio.h.
+ * Account for renamed IOCTL codes.
+ * Revision 1.27 2008/12/17 10:37:37 martin
+ * Fixed a bug in mbg_open_device_by_name() with sel. mode MBG_MATCH_ANY.
+ * Support variable read buffer sizes under Linux, so
+ * mbg_get_all_port_info() and mbg_get_all_str_type_info()
+ * can now be used under Linux.
+ * Support PC cycles under Linux via inline rdtsc call.
+ * Use predefined constants to convert fractions.
+ * New API calls mbg_get_fast_hr_timestamp_cycles(), and
+ * mbg_get_fast_hr_timestamp_comp() which take memory mapped HR time stamps
+ * in kernel space, and mbg_dev_has_fast_hr_timestamp() to check whether
+ * this is supported by a device.
+ * Removed mm_*() functions since these are obsolete now.
+ * Support extrapolated HR time (xhrt) for Windows and Linux
+ * by providing a function mbg_xhrt_poll_thread_create() which
+ * starts a poll thread for a specific device which to read
+ * HR time plus associated cycles in regular intervals.
+ * Added functions mbg_get_process_affinity(), mbg_set_process_affinity(),
+ * and mbg_set_current_process_affinity_to_cpu(), and mbg_create_thread()
+ * and mbg_set_thread_affinity() to control the extrapolation feature.
+ * Use new preprocessor symbol MBGDEVIO_HAVE_THREAD_AFFINITY.
+ * Added new functions mbg_get_xhrt_time_as_pcps_hr_time() and
+ * mbg_get_xhrt_time_as_filetime() (Windows only) to retrieve
+ * fast extrapolated timestamps.
+ * Added function mbg_get_xhrt_cycles_frequency() to retrieve the
+ * cycles counter frequency computed by the polling thread.
+ * Added function mbg_get_default_cycles_frequency_from_dev(),
+ * and mbg_get_default_cycles_frequency() (Windows only).
+ * Moved mbg_open_device..() functions upwards.
+ * Made device_info_list common.
+ * New functions mbg_dev_is_msf(), mbg_dev_is_wwvb(), mbg_dev_is_lwr(),
+ * mbg_dev_has_asic_version(), mbg_dev_has_asic_features(),
+ * and mbg_get_irq_stat_info().
+ * Exclude 2 more functions from build if symbol MBGDEVIO_SIMPLE is not 0.
+ * Account for MBG_VIRT_ADDR having beenrenamed to MBG_MEM_ADDR.
+ * Account Linux for device names renamed from /dev/mbgclk to /dev/mbgclock.
+ * Support bigendian target platforms.
+ * Revision 1.26 2008/02/26 16:54:21 martin
+ * New/changed functions for memory mapped access which are
+ * currently excluded from build.
+ * Changed separator for device names from ' ' to '_'.
+ * Added new type MBG_HW_NAME.
+ * Comment cleanup for doxygen.
+ * Revision 1.25 2008/02/04 13:42:45Z martin
+ * Account for preprocessor symbol MBG_TGT_SUPP_MMAP.
+ * Revision 1.24 2008/01/31 08:31:40Z martin
+ * Picked up changes from 1.19.1.2:
+ * Under DOS detect and disable any TSR while searching for devices.
+ * Exclude some complex configuration API calls from build
+ * If MBGDEVIO_SIMPLE is defined != 0.
+ * Revision 1.23 2008/01/30 10:32:35Z daniel
+ * Renamed mapped memory funtions.
+ * Revision 1.22 2008/01/25 15:27:42Z daniel
+ * Fixed a bug in mbg_get_hr_time_comp() where an overflow
+ * of the fractions was handled with wrong sign.
+ * Revision 1.21 2008/01/17 15:49:59Z daniel
+ * Added functions mbg_find_devices_with_hw_id() and
+ * mbg_free_devics_list() to work with Linux Win32 OSs.
+ * Added Doxygen compliant comments for API functions.
+ * Support for mapped memory I/O under linux and windows.
+ * Added functions mbg_get_mapped_memory_info(),
+ * mbg_unmap_mapped_memory() and
+ * mbg_get_hr_timestamp_memory_mapped().
+ * Account for PCI_ASIC_FEATURES.
+ * Cleanup for PCI ASIC version.
+ * Revision 1.20 2007/09/27 07:31:12 daniel
+ * Moved declaration of portable inline specifier to mbg_tgt.h.
+ * Support hotplugging of devices as used with USB by Daniel's new
+ * functions mbg_find_devices_with_names(), mbg_free_device_name_list(),
+ * mbg_open_device_by_hw_id(), and mbg_open_device_by_name().
+ * In mbg_get_serial_settings() account for devices which have no
+ * serial port at all.
+ * Register event source if Windows DLL is loaded.
+ * Revision 1.19 2007/05/21 15:00:00Z martin
+ * Unified naming convention for symbols related to ref_offs.
+ * Revision 1.18 2007/03/02 10:17:41Z martin
+ * Use generic port I/O macros.
+ * Changes due to modified/renamed macros.
+ * Changes due to renamed library symbols.
+ * Preliminary support for *BSD.
+ * Revision 1.17 2006/05/02 13:15:37 martin
+ * Added mbg_set_gps_port_settings(), mbg_get_gps_all_pout_info(),
+ * mbg_set_gps_pout_settings_idx(), mbg_set_gps_pout_settings().
+ * Revision 1.16 2005/06/02 11:53:12Z martin
+ * Implemented existing mbg_generic_..() functions.
+ * Added new functions mbg_generic_io() and mbg_dev_has_generic_io().
+ * Added new function mbg_get_synth_state().
+ * Partially use inline function.
+ * Changed order of some functions.
+ * More simplifications using macros.
+ * Unified macros for Win32 and Linux.
+ * Fixed warning under Win32 using type cast.
+ * Revision 1.15 2005/01/31 16:44:21Z martin
+ * Added function mbg_get_hr_time_comp() which returns HR time stamp
+ * which has latency compensated.
+ * Revision 1.14 2005/01/14 10:22:23Z martin
+ * Added functions which query device features.
+ * Revision 1.13 2004/12/09 11:23:59Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.12 2004/11/09 14:11:07Z martin
+ * Modifications were required in order to be able to configure IRIG
+ * settings of cards which provide both IRIG input and output.
+ * Renamed functions mbg_get_irig_info() and mbg_set_irig_settings()
+ * to mbg_get_irig_rx_info() and mbg_set_irig_rx_settings()
+ * New functions mbg_get_irig_tx_info() and mbg_set_irig_tx_settings().
+ * All API functions now use well defined parameter types instead of
+ * generic types. Some new types have been defined therefore.
+ * Added a workaround for GPS169PCI cards with early firmware versions
+ * which used the same codes to configure the IRIG output as the TCR
+ * cards use to configure the IRIG input. Those codes are now
+ * exclusively used to configure the IRIG input. The workaround
+ * has been included in order to let GPS169PCI cards work properly
+ * after a driver update, without requiring a firmware update.
+ * The macro _pcps_ddev_requires_irig_workaround() is used to check
+ * if the workaround is required.
+ * Renamed function mbg_get_gps_stat() to mbg_get_gps_bvar_stat().
+ * Revision 1.11 2004/08/17 11:13:45Z martin
+ * Account for renamed symbols.
+ * Revision 1.10 2004/04/14 09:39:17Z martin
+ * Allow [g|s]et_irig_info() also for new devices with IRIG output.
+ * Use MBGDEVIO_COMPAT_VERSION to check version.
+ * Revision 1.9 2003/12/22 15:30:52Z martin
+ * Added functions mbg_get_asic_version(), mbg_get_time_cycles(),
+ * and mbg_get_hr_time_cycles().
+ * Support higher baud rates for TCR510PCI and PCI510.
+ * Support PCPS_HR_TIME for TCR510PCI.
+ * API calls return ioctl results instead of success/-1.
+ * Moved some Win32 specific code to mbgsvctl DLL.
+ * Log Win32 ioctl errors to event log for debugging.
+ * Revision 1.8 2003/06/19 08:42:33Z martin
+ * Renamed function mbg_clr_cap_buff() to mbg_clr_ucap_buff().
+ * New functions mbg_get_ucap_entries() and mbg_get_ucap_event().
+ * New function mbg_get_hr_ucap().
+ * New functions mbgdevio_get_version() and mbgdevio_check_version().
+ * New functions for generic read/write access.
+ * New functions mbg_get_pcps_tzdl() and mbg_set_pcps_tzdl().
+ * Fixed a bug passing the wrong command code to a
+ * direct access target in mbg_get_sync_time().
+ * Return driver info for direct access targets.
+ * Include pcpsdrvr.h and pcps_dos.h, if applicable.
+ * For direct access targets, check if a function is supported
+ * before accessing the hardware.
+ * Use const parameter pointers if applicable.
+ * Changes due to renamed symbols/macros.
+ * Source code cleanup.
+ * Revision 1.7 2003/05/16 08:52:46 MARTIN
+ * Swap doubles inside API functions.
+ * Enhanced support for direct access targets.
+ * Removed obsolete code.
+ * Revision 1.6 2003/04/25 10:14:16 martin
+ * Renamed macros.
+ * Extended macro calls for direct access targets.
+ * Updated macros for Linux.
+ * Revision 1.5 2003/04/15 19:35:25Z martin
+ * New functions mbg_setup_receiver_info(),
+ * mbg_get_serial_settings(), mbg_save_serial_settings().
+ * Revision 1.4 2003/04/09 16:07:16Z martin
+ * New API functions mostly complete.
+ * Use renamed IOCTL codes from mbgioctl.h.
+ * Added DllEntry function foe Win32.
+ * Made MBG_Device_count and MBG_Device_Path local.
+ * Revision 1.3 2003/01/24 13:44:40Z martin
+ * Fixed get_ref_time_from_driver_at_sec_change() to be used
+ * with old kernel drivers.
+ * Revision 1.2 2002/09/06 11:04:01Z martin
+ * Some old API functions have been replaced by new ones
+ * for a common PnP/non-PnP API.
+ * New API function which clears capture buffer.
+ * New function get_ref_time_from_driver_at_sec_change().
+ * Revision 1.1 2002/02/19 13:48:20Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _MBGDEVIO
+ #include <mbgdevio.h>
+#undef _MBGDEVIO
+
+#include <parmpcps.h>
+#include <parmgps.h>
+#include <gpsutils.h>
+#include <mbgerror.h>
+
+#if defined( MBG_TGT_DOS_PM )
+ #include <mbg_dpmi.h>
+#endif
+
+#if defined( MBG_USE_KERNEL_DRIVER )
+
+ #include <mbgioctl.h>
+
+#else
+
+ #include <pcpsdrvr.h>
+ #include <pci_asic.h>
+ #include <stdio.h>
+
+ static PCPS_DRVR_INFO drvr_info = { MBGDEVIO_VERSION, 0, "MBGDEVIO direct" };
+
+#endif
+
+
+
+#define MAX_INFO_LEN 260
+
+typedef struct
+{
+ MBG_HW_NAME hw_name;
+ char model_name[PCPS_CLOCK_NAME_SZ];
+ PCPS_SN_STR serial_number;
+ char hardware_id[MAX_INFO_LEN]; // OS dependent hardware_id to identify and open the device
+} MBG_DEVICE_INFO;
+
+
+
+// target specific code for different environments
+
+#if defined( MBG_TGT_WIN32 )
+
+ #include <mbgsvctl.h>
+ #include <mbgnames.h>
+ #include <pci_asic.h>
+ #include <mbgutil.h> //##++
+ #include <timecnv.h>
+ #include <pcpsutil.h>
+
+ #include <tchar.h>
+ #include <stdio.h>
+
+ #define _mbgdevio_vars() \
+ DWORD rc
+
+ #define _mbgdevio_ret_val \
+ rc
+
+ #define _do_mbgdevio_io( _dh, _ioctl, _p, _insz, _outsz ) \
+ rc = do_mbgdevio_io( _dh, _ioctl, (LPVOID) _p, _insz, _outsz )
+
+ static __mbg_inline
+ DWORD do_mbgdevio_io( MBG_DEV_HANDLE dh, int ioctl_code,
+ LPVOID p, int in_sz, int out_sz )
+ {
+ DWORD ReturnedLength;
+
+ if ( !DeviceIoControl( dh, ioctl_code,
+ p, in_sz, p, out_sz,
+ &ReturnedLength,
+ NULL
+ ) )
+ {
+ DWORD rc = GetLastError();
+
+ // do not report a USB device timeout error
+ if ( rc != _mbg_err_to_os( MBG_ERR_USB_ACCESS ) )
+ mbgsvctl_log_mbgdevio_error( ioctl_code, rc );
+
+ return rc;
+ }
+
+ return MBG_SUCCESS;
+
+ } // do_mbgdevio_io
+
+#elif defined( MBG_TGT_UNIX )
+
+ #include <mbgioctl.h>
+
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h> // sprintf()
+ #include <sys/ioctl.h>
+ #include <sys/mman.h>
+
+ #define _mbgdevio_vars() \
+ int rc
+
+ #define _mbgdevio_ret_val \
+ ( ( rc < 0 ) ? rc : MBG_SUCCESS )
+
+ #define _do_mbgdevio_io( _dh, _ioctl, _p, _insz, _outsz ) \
+ rc = ioctl( _dh, _ioctl, _p )
+
+#else // other target OSs which access the hardware directly
+
+ #if defined( MBG_TGT_QNX_NTO )
+ #include <stdio.h>
+ #include <sys/neutrino.h>
+ #endif
+
+ #if MBG_USE_DOS_TSR
+ #include <pcps_dos.h>
+ #else
+ #define pcps_read_safe _pcps_read
+ #define pcps_write_safe pcps_write
+ #define pcps_read_gps_safe pcps_read_gps
+ #define pcps_write_gps_safe pcps_write_gps
+
+ #define _pcps_write_byte_safe _pcps_write_byte
+ #define _pcps_read_var_safe _pcps_read_var
+ #define _pcps_write_var_safe _pcps_write_var
+ #define _pcps_read_gps_var_safe _pcps_read_gps_var
+ #define _pcps_write_gps_var_safe _pcps_write_gps_var
+ #endif
+
+ #define _mbgdevio_vars() \
+ int rc
+
+ #define _mbgdevio_ret_val \
+ rc
+
+ #define _mbgdevio_chk_cond( _cond ) \
+ { \
+ if ( !(_cond) ) \
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); \
+ }
+
+#endif // end of target specific code
+
+
+#if !defined( _MBG_SUPP_VAR_ACC_SIZE )
+ // If this symbol has not yet been defined then mbgioctl.h has probably
+ // not yet been included. On target systems where the hardware is accessed
+ // directly without a kernel driver variable buffer sizes are supported,
+ // so we set the default to 1.
+ #define _MBG_SUPP_VAR_ACC_SIZE 1
+#endif
+
+
+#if !defined( _mbgdevio_chk_cond )
+ // If the macro has not been defined previously then
+ // it is not be required for the target environment and
+ // is defined as empty string.
+ #define _mbgdevio_chk_cond( _cond );
+#endif
+
+
+
+// The code below depends on whether the target device is accessed via
+// IOCTLs to a device driver, or the hardware is accessed directly.
+
+#if defined( _MBGIOCTL_H ) // using IOCTL to access device driver
+
+ #define _mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \
+ _do_mbgdevio_io( _dh, _ioctl, _p, 0, _sz )
+
+ #define _mbgdevio_write( _dh, _cmd, _ioctl, _p, _sz ) \
+ _do_mbgdevio_io( _dh, _ioctl, _p, _sz, 0 )
+
+ #define _mbgdevio_read_gps _mbgdevio_read
+
+ #define _mbgdevio_write_gps _mbgdevio_write
+
+
+ #define _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ) \
+ _mbgdevio_read( _dh, _cmd, _ioctl, _p, sizeof( *(_p) ) )
+
+ #define _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ) \
+ _mbgdevio_write( _dh, _cmd, _ioctl, _p, sizeof( *(_p) ) )
+
+ #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \
+ _mbgdevio_write( _dh, _cmd, _ioctl, NULL, 0 )
+
+ #define _mbgdevio_read_gps_var _mbgdevio_read_var
+
+ #define _mbgdevio_write_gps_var _mbgdevio_write_var
+
+
+ #define _mbgdevio_gen_read( _dh, _cmd, _p, _sz ) \
+ rc = mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_READ, NULL, 0, _p, _sz )
+
+ #define _mbgdevio_gen_write( _dh, _cmd, _p, _sz ) \
+ rc = mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_WRITE, _p, _sz, NULL, 0 )
+
+ #define _mbgdevio_gen_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ) \
+ rc = mbgdevio_do_gen_io( _dh, _type, IOCTL_PCPS_GENERIC_IO, _in_p, _in_sz, _out_p, _out_sz )
+
+ #define _mbgdevio_gen_read_gps( _dh, _cmd, _p, _sz ) \
+ rc = mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_READ_GPS, NULL, 0, _p, _sz )
+
+ #define _mbgdevio_gen_write_gps( _dh, _cmd, _p, _sz ) \
+ rc = mbgdevio_do_gen_io( _dh, _cmd, IOCTL_PCPS_GENERIC_WRITE_GPS, _p, _sz, NULL, 0 )
+
+
+ static __mbg_inline
+ int mbgdevio_do_gen_io( MBG_DEV_HANDLE dh, int info, int ioctl_code,
+ const void *in_p, int in_sz,
+ void *out_p, int out_sz )
+ {
+ IOCTL_GENERIC_BUFFER *p_buff;
+ int buff_size = sizeof( p_buff->ctl )
+ + ( ( in_sz > out_sz ) ? in_sz : out_sz );
+ int rc;
+
+ p_buff = (IOCTL_GENERIC_BUFFER *) malloc( buff_size );
+
+ if ( p_buff == NULL )
+ return _mbg_err_to_os( MBG_ERR_NO_MEM );
+
+ p_buff->ctl.info = info;
+ p_buff->ctl.data_size_in = in_sz;
+ p_buff->ctl.data_size_out = out_sz;
+
+ if ( in_p )
+ memcpy( p_buff->data, in_p, in_sz );
+
+ _do_mbgdevio_io( dh, ioctl_code,
+ p_buff,
+ sizeof( IOCTL_GENERIC_CTL ) + in_sz,
+ sizeof( IOCTL_GENERIC_CTL ) + out_sz );
+
+ if ( out_p && ( rc == MBG_SUCCESS ) )
+ memcpy( out_p, p_buff->data, out_sz );
+
+ free( p_buff );
+
+ return rc;
+
+ } // mbgdevio_do_gen_io
+
+#else // accessing hardware device directly
+
+ #define _mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \
+ rc = pcps_read_safe( _dh, _cmd, _p, _sz )
+
+ #define _mbgdevio_write( _dh, _cmd, _ioctl, _p, _sz ) \
+ rc = pcps_write_safe( _dh, _cmd, _p, _sz )
+
+ #define _mbgdevio_read_gps( _dh, _cmd, _ioctl, _p, _sz ) \
+ rc = pcps_read_gps_safe( _dh, _cmd, _p, _sz )
+
+ #define _mbgdevio_write_gps( _dh, _cmd, _ioctl, _p, _sz ) \
+ rc = pcps_write_gps_safe( _dh, _cmd, _p, _sz )
+
+
+ #define _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ) \
+ rc = _pcps_read_var_safe( _dh, _cmd, *(_p) )
+
+ #define _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ) \
+ rc = _pcps_write_var_safe( _dh, _cmd, *(_p) )
+
+ #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \
+ rc = _pcps_write_byte_safe( _dh, _cmd );
+
+ #define _mbgdevio_read_gps_var( _dh, _cmd, _ioctl, _p ) \
+ rc = _pcps_read_gps_var_safe( _dh, _cmd, *(_p) )
+
+ #define _mbgdevio_write_gps_var( _dh, _cmd, _ioctl, _p ) \
+ rc = _pcps_write_gps_var_safe( _dh, _cmd, *(_p) )
+
+
+ #define _mbgdevio_gen_read( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_read( _dh, _cmd, -1, _p, _sz )
+
+ #define _mbgdevio_gen_write( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_write( _dh, _cmd, -1, _p, _sz )
+
+ #define _mbgdevio_gen_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ); \
+ { \
+ _mbgdevio_chk_cond( _pcps_ddev_has_generic_io( _dh ) ); \
+ rc = pcps_generic_io( _dh, _type, _in_p, _in_sz, _out_p, _out_sz ); \
+ }
+
+ #define _mbgdevio_gen_read_gps( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_read_gps( _dh, _cmd, -1, _p, _sz )
+
+ #define _mbgdevio_gen_write_gps( _dh, _cmd, _p, _sz ) \
+ _mbgdevio_write_gps( _dh, _cmd, -1, _p, _sz )
+
+#endif
+
+
+
+
+#define _mbgdevio_read_chk( _dh, _cmd, _ioctl, _p, _sz, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ); \
+}
+
+#define _mbgdevio_read_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ); \
+}
+
+#define _mbgdevio_write_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ); \
+}
+
+#define _mbgdevio_write_cmd_chk( _dh, _cmd, _ioctl, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_write_cmd( _dh, _cmd, _ioctl ); \
+}
+
+#define _mbgdevio_read_gps_chk( _dh, _cmd, _ioctl, _p, _sz, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_read_gps( _dh, _cmd, _ioctl, _p, _sz ); \
+}
+
+#define _mbgdevio_read_gps_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_read_gps_var( _dh, _cmd, _ioctl, _p ); \
+}
+
+#define _mbgdevio_write_gps_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \
+{ \
+ _mbgdevio_chk_cond( _cond ); \
+ _mbgdevio_write_gps_var( _dh, _cmd, _ioctl, _p ); \
+}
+
+
+
+#if defined( _MBGIOCTL_H )
+ #define _mbgdevio_query_cond( _dh, _cond, _ioctl, _p ) \
+ { \
+ _mbgdevio_vars(); \
+ _mbgdevio_read_var( _dh, -1, _ioctl, _p ); \
+ return _mbgdevio_ret_val; \
+ }
+
+ #define _mbgdevio_query_ri_cond _mbgdevio_query_cond
+#else
+ #define _mbgdevio_query_cond( _dh, _cond, _ioctl, _p ) \
+ { \
+ *p = _cond( _dh ); \
+ return MBG_SUCCESS; \
+ }
+
+ #define _mbgdevio_query_ri_cond( _dh, _cond, _ioctl, _p ) \
+ { \
+ *p = _cond( &(_dh)->ri ); \
+ return MBG_SUCCESS; \
+ }
+#endif
+
+
+static MBG_PC_CYCLES_FREQUENCY pc_cycles_frequency;
+static MBG_DEVICE_INFO device_info_list[MBG_MAX_DEVICES];
+
+
+
+
+static /*HDR*/ //##++ make this public ?
+int mbg_comp_hr_latency( PCPS_TIME_STAMP *ts,
+ const MBG_PC_CYCLES *p_cyc_ts,
+ const MBG_PC_CYCLES *p_cyc_ontime,
+ const MBG_PC_CYCLES_FREQUENCY *p_cyc_freq,
+ int32_t *hns_latency )
+{
+ #if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+ int64_t cyc_latency;
+ int64_t frac_latency;
+ int64_t comp_frac; //uint??
+
+ // Compute latency in cycles counter units
+ cyc_latency = mbg_delta_pc_cycles( p_cyc_ts, p_cyc_ontime );
+
+ #if DEBUG && defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 )
+ printf( "comp_lat: %08llX.%08llX %llX - %llX = %lli",
+ (unsigned long long) ts->sec,
+ (unsigned long long) ts->frac,
+ (unsigned long long) *p_cyc_ts,
+ (unsigned long long) *p_cyc_ontime,
+ (unsigned long long) cyc_latency
+ );
+ #endif
+
+ // Account for cycles counter overflow. This is
+ // supposed to happen once every 2^^63 units of the
+ // cycles counter frequency, i.e. about every
+ // 97 years on a system with 3 GHz clock.
+ if ( cyc_latency < 0 )
+ {
+ cyc_latency += ( (uint64_t) -1 ) >> 1;
+
+ #if DEBUG && defined( MBG_TGT_LINUX )
+ printf( "->%lli (%llX)",
+ (unsigned long long) cyc_latency,
+ (unsigned long long) ( ( (uint64_t) -1 ) >> 1 )
+ );
+ #endif
+ }
+
+ // convert latency to binary fractions of seconds,
+ // i.e. units of 2^^-32.
+ frac_latency = (*p_cyc_freq) ? ( cyc_latency * ( ( (int64_t) 1 ) << 32 ) / *p_cyc_freq ) : 0;
+
+ // compute the compensated fractional part of the HR time stamp
+ // and account for borrows from the sec field
+ comp_frac = ts->frac - frac_latency;
+ ts->frac = (uint32_t) comp_frac; // yields 32 LSBs
+ ts->sec += (uint32_t) ( comp_frac >> 32 ); // yields 32 MSBs
+
+ #if DEBUG && defined( MBG_TGT_LINUX )
+ printf( " frac_lat: %llX comp_frac: %08llX.%08llX",
+ (unsigned long long) frac_latency,
+ (unsigned long long) ts->sec,
+ (unsigned long long) ts->frac
+ );
+ #endif
+
+ if ( hns_latency && *p_cyc_freq )
+ {
+ int64_t tmp_hns_latency;
+
+ // convert to hectonanoseconds
+ tmp_hns_latency = cyc_latency * 10000000 / *p_cyc_freq;
+
+ // check for range overflow
+ #define MAX_HNS_LATENCY 0x7FFFFFFF // int32_t
+ #define MIN_HNS_LATENCY ( -MAX_HNS_LATENCY - 1 )
+
+ if ( tmp_hns_latency > MAX_HNS_LATENCY )
+ tmp_hns_latency = MAX_HNS_LATENCY;
+ else
+ if ( tmp_hns_latency < MIN_HNS_LATENCY )
+ tmp_hns_latency = MIN_HNS_LATENCY;
+
+ *hns_latency = (int32_t) tmp_hns_latency;
+ }
+
+ #if DEBUG && defined( MBG_TGT_LINUX )
+ printf( "\n" );
+ #endif
+
+ return MBG_SUCCESS;
+
+ #else
+
+ // This is currently not supported by the target environment.
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+
+ #endif
+
+} // mbg_comp_hr_latency
+
+
+
+/*HDR*/
+/**
+ Get the version number of the compiled mbgdevio library.
+ If the mbgdevio library is built as a DLL/shared object then
+ the version number of the compiled library may differ from
+ the version number of the import library and header files
+ which have been used to build an application.
+
+ @return The version number
+
+ @see ::MBGDEVIO_VERSION defined in mbgdevio.h.
+ */
+_MBG_API_ATTR int _MBG_API mbgdevio_get_version( void )
+{
+
+ return MBGDEVIO_VERSION;
+
+} // mbgdevio_get_version
+
+
+
+/*HDR*/
+/**
+ Check if the version of the compiled mbgdevio library is compatible
+ with a certain version which is passed as parameter.
+
+ @param header_version Version number to be checked, should be ::MBGDEVIO_VERSION
+ defined in mbgdevio.h.
+
+ @return ::MBG_SUCCESS if compatible, ::MBG_ERR_LIB_NOT_COMPATIBLE if not.
+
+ @see ::MBGDEVIO_VERSION defined in mbgdevio.h.
+ */
+_MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version )
+{
+ if ( header_version >= MBGDEVIO_COMPAT_VERSION )
+ return MBG_SUCCESS;
+
+ return _mbg_err_to_os( MBG_ERR_LIB_NOT_COMPATIBLE );
+
+} // mbgdevio_check_version
+
+
+
+/*HDR*/
+/**
+ Open a device by index, starting from 0.
+ This function is <b>out of date</b>, mbg_open_device_by_name()
+ should be used instead.
+
+ See the <b>note</b> for mbg_find_device() for details.
+
+ @param device_index Index of the device, use 0 for the first device.
+ */
+_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device( unsigned int device_index )
+{
+#if defined( MBG_TGT_WIN32 )
+
+ const char *device_path;
+ HANDLE dh;
+
+ device_path = mbg_svc_get_device_path( device_index );
+
+ if ( device_path == NULL )
+ goto fail;
+
+
+ dh = CreateFile(
+ device_path, // file name
+ GENERIC_READ | GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // security descriptor
+ OPEN_EXISTING, // how to create
+ 0, // file attributes
+ NULL // handle to template file
+ );
+
+ if ( INVALID_HANDLE_VALUE == dh )
+ {
+ #if 0 //##++
+ printf( "mbg_open_device: CreateFile failed for index %i\n", device_index );
+ #endif
+
+ goto fail;
+ }
+
+ return dh;
+
+fail:
+ return MBG_INVALID_DEV_HANDLE;
+
+#elif defined( MBG_TGT_UNIX )
+
+ MBG_DEV_HANDLE dh;
+ char dev_fn[50];
+
+ if ( device_index > MBG_MAX_DEVICES )
+ device_index = MBG_MAX_DEVICES;
+
+ sprintf( dev_fn, "/dev/mbgclock%d", device_index ); //##++
+
+ dh = open( dev_fn, 0 );
+
+ return ( dh < 0 ) ? MBG_INVALID_DEV_HANDLE : dh;
+
+#else
+
+ return ( device_index < n_ddevs ) ? &pcps_ddev[device_index] : NULL;
+
+#endif
+
+} // mbg_open_device
+
+
+
+static /*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Return a handle to a device specified by a given hardware_id.
+ The format the hardware_id depends on the operating system, so
+ this function is used only internally to detect devices for
+ which a unique name of the format MBG_HW_NAME is generated,
+ which is in turn used with the public API functions.
+ */
+MBG_DEV_HANDLE _MBG_API mbg_open_device_by_hw_id( const char* hw_id )
+{
+#if defined( MBG_TGT_WIN32 )
+
+ HANDLE dh;
+ int ret = 0;
+ BOOL usb = FALSE;
+
+ if ( hw_id == NULL )
+ goto fail;
+
+ dh = CreateFile(
+ hw_id, // file name
+ GENERIC_READ | GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // security descriptor
+ OPEN_EXISTING, // how to create
+ strstr(hw_id,"usb") ? FILE_FLAG_OVERLAPPED : 0, // file attributes
+ NULL // handle to template file
+ );
+
+ if ( INVALID_HANDLE_VALUE == dh )
+ goto fail;
+
+ return dh;
+
+fail:
+ return MBG_INVALID_DEV_HANDLE;
+
+#elif defined ( MBG_TGT_UNIX )
+
+ MBG_DEV_HANDLE dh = -1;
+
+ if ( strlen( hw_id ) > 0 )
+ dh = open( hw_id, 0 );
+
+ return ( dh < 0 ) ? MBG_INVALID_DEV_HANDLE : dh;
+
+#else
+
+ return MBG_INVALID_DEV_HANDLE;
+
+#endif
+
+} // mbg_open_device_by_hw_id
+
+
+
+/*HDR*/
+/**
+ Get the number of supported devices installed on the computer.
+ This function is <b>out of date</b>, mbg_find_devices_with_names()
+ should be used instead.
+
+ <b>Note:</b> This function is out of date since it may not work
+ correctly for Meinberg devices which are disconnected and reconnected
+ while the system is running (e.g. USB devices). However, the function
+ will be kept for compatibility reasons and works correctly if all
+ Meinberg devices are connected at system boot and are not disconnected
+ and reconnected during operation
+
+ @return The number of devices found.
+
+ @see mbg_find_devices_with_names()
+ */
+_MBG_API_ATTR int _MBG_API mbg_find_devices( void )
+{
+ #if defined( _PCPSDRVR_H )
+
+ #if defined( MBG_TGT_QNX_NTO )
+ // Since this program accessed the hardware directly
+ // I/O privileges must be assigned to the thread.
+ if ( ThreadCtl( _NTO_TCTL_IO, NULL ) == -1 )
+ {
+ perror( "Fatal error" );
+ exit( 1 );
+ }
+ #endif
+
+ #if defined( MBG_TGT_DOS ) && MBG_USE_DOS_TSR
+ {
+ short prv_busy;
+
+ pcps_detect_any_tsr();
+ prv_busy = pcps_tsr_set_busy_flag( 1 );
+ pcps_detect_clocks( pcps_isa_ports, NULL );
+ pcps_tsr_set_busy_flag( prv_busy );
+ }
+ #else
+ pcps_detect_clocks( pcps_isa_ports, NULL );
+ #endif
+
+ return n_ddevs;
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ return mbg_svc_find_devices();
+
+#elif defined ( MBG_TGT_UNIX )
+
+ MBG_DEV_HANDLE dh;
+ int i = 0;
+ int n = 0;
+
+ while( i < MBG_MAX_DEVICES )
+ {
+ dh = mbg_open_device( i );
+
+ if ( dh != MBG_INVALID_DEV_HANDLE )
+ {
+ mbg_close_device( &dh );
+ n++;
+ }
+
+ i++;
+ }
+
+ return n;
+
+ #endif
+
+} // mbg_find_devices
+
+
+
+#if defined( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX )
+
+static /*HDR*/
+int mbg_find_devices_with_hw_id( MBG_DEVICE_LIST ** list, int max_devs )
+{
+ #if defined ( MBG_TGT_WIN32 )
+
+ return mbg_svc_find_devices_with_hw_id( list, max_devs );
+
+ #elif defined ( MBG_TGT_UNIX )
+
+ MBG_DEVICE_LIST *ListBegin;
+ int n = 0;
+ int i = 0;
+
+ (*list) = (MBG_DEVICE_LIST *) malloc( sizeof( **list ) );
+ memset( *list, 0, sizeof( **list ) );
+
+ ListBegin = (*list);
+
+ for (;;)
+ {
+ char dev_name[100];
+ MBG_DEV_HANDLE dh;
+
+ sprintf( dev_name, "/dev/mbgclock%d", i );
+
+ dh = mbg_open_device_by_hw_id( dev_name );
+
+ if ( dh != MBG_INVALID_HANDLE )
+ {
+ mbg_close_device( &dh );
+
+ (*list)->device_path = (char *) malloc( strlen( dev_name ) + 1 );
+ strcpy( (*list)->device_path, dev_name );
+
+ (*list)->next = (MBG_DEVICE_LIST *) malloc( sizeof( **list ) );
+ (*list) = (*list)->next;
+
+ memset( *list, 0, sizeof( **list ) );
+ n++;
+ }
+
+ if ( ++i >= MBG_MAX_DEVICES )
+ break;
+ }
+
+ if ( n > 0 )
+ *list = ListBegin;
+ else
+ {
+ free( *list );
+ *list = NULL;
+ }
+
+ return n;
+
+ #else
+
+ return 0;
+
+ #endif
+}
+
+#endif
+
+
+
+#if defined ( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX )
+
+static /*HDR*/
+void _MBG_API mbg_free_device_list( MBG_DEVICE_LIST *devices )
+{
+
+ #if defined ( MBG_TGT_WIN32 )
+ mbg_svc_free_device_list( devices );
+ #else
+ int i = 0;
+ MBG_DEVICE_LIST *Next = NULL;
+
+ while ( i < MBG_MAX_DEVICES)
+ {
+ if ( devices )
+ {
+ if ( devices->device_path )
+ {
+ free( devices->device_path );
+ devices->device_path = NULL;
+ }
+
+ if ( devices->next )
+ {
+ Next = devices->next;
+ free(devices);
+ devices = Next;
+ }
+ else
+ {
+ if ( devices )
+ {
+ free( devices );
+ devices = NULL;
+ }
+ break;
+ }
+ }
+ else
+ break;
+
+ i++;
+ }
+
+ #endif
+}
+
+#endif
+
+
+
+#if ( defined( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX ) )
+
+static /*HDR*/
+void get_hw_name_from_hw_id( MBG_DEVICE_INFO *dev_info )
+{
+ MBG_DEV_HANDLE dh;
+ PCPS_DEV pdev;
+
+ dh = MBG_INVALID_HANDLE;
+ memset( &pdev, 0, sizeof( pdev ) );
+
+ // Default initializers
+ strcpy( dev_info->model_name, "N/A" );
+ strcpy( dev_info->serial_number, "N/A" );
+ strcpy( dev_info->hw_name, "N/A" );
+
+ dh = mbg_open_device_by_hw_id( dev_info->hardware_id );
+
+ if ( dh != MBG_INVALID_HANDLE )
+ {
+ if ( mbg_get_device_info( dh, &pdev ) == MBG_SUCCESS )
+ {
+ strcpy( dev_info->model_name, _pcps_type_name( &pdev ) );
+ strcpy( dev_info->serial_number, _pcps_sernum( &pdev ) );
+ sprintf( dev_info->hw_name, "%s_%s", _pcps_type_name( &pdev ), _pcps_sernum( &pdev ) );
+ }
+
+ mbg_close_device( &dh );
+ }
+
+} // get_hw_name_from_hw_id
+
+#endif
+
+
+
+/*HDR*/
+/**
+ Return the number of supported devices installed on the system and
+ set up a list of unique names of those devices.
+
+ This function should be used preferably instead of mbg_find_devices().
+
+ @param device_list Pointer to a linked list of type ::MBG_DEVICENAME_LIST
+ with device names. The list will be allocated by this
+ function and has to be freed after usage by calling
+ mbg_free_device_name_list().
+ @param max_devices Maximum number of devices the function should look for
+ (can not exceed ::MBG_MAX_DEVICES).
+
+ @return Number of present devices
+
+ @see ::MBG_HW_NAME for the format of the unique names
+ @see mbg_free_device_name_list()
+ @see mbg_find_devices()
+ */
+_MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEVICENAME_LIST **device_list,
+ int max_devices )
+{
+#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+ MBG_DEVICE_LIST *hardware_list = NULL;
+ MBG_DEVICE_LIST *hardware_list_begin = NULL;
+ MBG_DEVICENAME_LIST *ListBegin = NULL;
+ MBG_DEVICE_INFO dev_info;
+
+ int n_devices = 0;
+ int i = 0;
+
+ n_devices = mbg_find_devices_with_hw_id( &hardware_list, max_devices );
+
+ hardware_list_begin = hardware_list;
+
+ if ( n_devices )
+ {
+ *device_list = (MBG_DEVICENAME_LIST *) malloc( sizeof( MBG_DEVICENAME_LIST ) );
+ (*device_list)->next = NULL;
+
+ // Save begin of the list
+ ListBegin = *device_list;
+
+ // Loop through the list of hardware_ids and get their readable names
+ for (;;)
+ {
+ if ( hardware_list->device_path && i++ < MBG_MAX_DEVICES )
+ {
+ strcpy( dev_info.hardware_id, hardware_list->device_path );
+
+ get_hw_name_from_hw_id( &dev_info );
+
+ strcpy( (*device_list)->device_name, dev_info.hw_name );
+
+ if ( hardware_list->next )
+ {
+ hardware_list = hardware_list->next;
+ (*device_list)->next = (MBG_DEVICENAME_LIST *) malloc( sizeof( MBG_DEVICENAME_LIST ) );
+ (*device_list) = (*device_list)->next;
+ (*device_list)->next = NULL;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ *device_list = ListBegin;
+ }
+
+ if ( hardware_list_begin )
+ mbg_free_device_list( hardware_list_begin );
+
+ return n_devices;
+
+#else
+
+ return 0;
+
+#endif
+
+} // mbg_find_devices_with_names
+
+
+
+/*HDR*/
+/**
+ Free the memory of the ::MBG_DEVICENAME_LIST that has been allocated before
+ by mbg_find_devices_with_names().
+
+ @param *list Linked list of type ::MBG_DEVICENAME_LIST
+
+ @see mbg_find_devices_with_names()
+ */
+_MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEVICENAME_LIST *list)
+{
+#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+ MBG_DEVICENAME_LIST *Next = NULL;
+ int i = 0;
+
+ // Deallocate members of linked list
+ while ( i < MBG_MAX_DEVICES )
+ {
+ if ( list )
+ {
+ Next = list->next;
+
+ free( list );
+ list = NULL;
+
+ if ( Next )
+ list = Next->next;
+ else
+ break;
+ }
+ else
+ break;
+
+ i++;
+ }
+
+#endif
+
+} // mbg_free_device_list
+
+
+
+/*HDR*/
+/**
+ Return a handle to a device with a certain unique name.
+ The names of the devices that are installed on the system can be retrieved by
+ the function mbg_find_devices_with_names().
+
+ This function should be used preferably instead of mbg_open_device().
+
+ @param hw_name String with the unique name of the device to be opened
+ @param selection_mode One of the enum values of ::MBG_MATCH_MODE
+
+ @return On success, the function returns a handle to the device, otherwise ::MBG_INVALID_DEV_HANDLE
+
+ @see ::MBG_HW_NAME for the format of the unique names.
+ @see ::MBG_MATCH_MODE
+ @see mbg_find_devices_with_names()
+ */
+_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char* hw_name, int selection_mode ) //##++++
+{
+
+#if ( defined( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX ) )
+
+ MBG_DEV_HANDLE dh;
+
+ MBG_DEVICE_LIST *devices = NULL;
+ MBG_DEVICE_LIST *ListBegin = NULL;
+ char hw_id[MAX_INFO_LEN];
+ char tmp_model_name[PCPS_CLOCK_NAME_SZ];
+ PCPS_SN_STR tmp_sn;
+ int n_devices = 0;
+ int i = 0;
+ int j = 0;
+
+ hw_id[0] = '\0';
+
+ memset( tmp_model_name, 0, sizeof( tmp_model_name) );
+ memset( device_info_list, 0, sizeof( device_info_list ) );
+ memset( tmp_sn, 0, sizeof( tmp_sn ) );
+
+ // separate hw_name into clock model and serial number
+ if ( hw_name && ( strlen( hw_name ) > 0 ) )
+ {
+ // clock model
+ for ( i = 0; ( i < PCPS_CLOCK_NAME_SZ ) && ( hw_name[i] != '_' ) && ( (unsigned int) i < strlen( hw_name ) ); i++ )
+ tmp_model_name[i] = hw_name[i];
+
+ tmp_model_name[i] = 0;
+ i++;
+
+ // serial number
+ if ( ( unsigned int ) i < strlen( hw_name ) )
+ {
+ j = 0;
+
+ while( ( unsigned int ) i < strlen(hw_name) && j < PCPS_SN_SIZE )
+ {
+ tmp_sn[j] = hw_name[i];
+ j++;
+ i++;
+ }
+ tmp_sn[j] = '\0';
+ }
+ }
+ else
+ goto fail;
+
+ i = 0;
+
+ // get OS-dependent hardware_id strings for devices that are present on the system
+ n_devices = mbg_find_devices_with_hw_id( &devices, MBG_MAX_DEVICES );
+
+ ListBegin = devices;
+
+ if ( n_devices )
+ {
+ for (;;)
+ {
+ if ( devices->device_path && i < MBG_MAX_DEVICES )
+ {
+ strncpy( device_info_list[i].hardware_id, devices->device_path, MAX_INFO_LEN );
+
+ // get readable hw_name for the device
+ get_hw_name_from_hw_id( &device_info_list[i] );
+
+ if ( hw_name && device_info_list[i].hw_name && strcmp( device_info_list[i].hw_name, hw_name ) == 0 ) //##+++++
+ {
+ // The requested device was found
+ strcpy( hw_id, device_info_list[i].hardware_id );
+ break;
+ }
+ else if ( devices->next )
+ devices = devices->next;
+ else
+ break;
+ }
+ else
+ break;
+ i++;
+ }
+
+ // If the requested CLOCK_MODEL/SN combination was not found,
+ // decide what to do depending on the selection mode
+ if ( ( hw_id[0] == '\0' ) && ( selection_mode != MBG_MATCH_EXACTLY ) )
+ {
+ for ( j = 0; j <= i; j++ )
+ {
+ // Search for the same clock model
+ if ( ( tmp_model_name[0] != '\0' ) && strcmp( device_info_list[j].model_name, tmp_model_name ) == 0 )
+ {
+ strcpy( hw_id, device_info_list[j].hardware_id );
+ break;
+ }
+ }
+
+ // Finally select the first device found on the system, if the clock model was not found
+ if ( ( selection_mode == MBG_MATCH_ANY ) && ( hw_id[0] == '\0' ) )
+ strcpy( hw_id, device_info_list[0].hardware_id );
+ }
+ }
+
+ mbg_free_device_list( ListBegin );
+
+#endif
+
+#if defined ( MBG_TGT_WIN32 )
+
+ if ( hw_id[0] == '\0' )
+ goto fail;
+
+ dh = CreateFile(
+ hw_id, // file name
+ GENERIC_READ | GENERIC_WRITE, // access mode
+ 0, // share mode
+ NULL, // security descriptor
+ OPEN_EXISTING, // how to create
+ strstr(hw_id,"usb") ? FILE_FLAG_OVERLAPPED : 0, // file attributes
+ NULL // handle to template file
+ );
+
+ if ( INVALID_HANDLE_VALUE == dh )
+ goto fail;
+
+ return dh;
+
+fail:
+ return MBG_INVALID_DEV_HANDLE;
+
+#elif defined ( MBG_TGT_UNIX )
+
+ if ( hw_id[0] != '\0' )
+ dh = open( hw_id, 0 );
+ else
+ goto fail;
+
+ return ( dh < 0 ) ? MBG_INVALID_DEV_HANDLE : dh;
+
+fail:
+ return MBG_INVALID_DEV_HANDLE;
+
+#else
+
+ //return ( device_index < n_ddevs ) ? &pcps_ddev[device_index] : NULL;
+ return MBG_INVALID_DEV_HANDLE;
+
+#endif
+
+} // mbg_open_device_by_name
+
+
+
+/*HDR*/
+/**
+ Close a handle to a device and set the handle value to ::MBG_INVALID_DEV_HANDLE.
+ If required, unmap mapped memory.
+
+ @param dev_handle Handle to a Meinberg device.
+ */
+_MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle )
+{
+ if ( *dev_handle != MBG_INVALID_DEV_HANDLE && *dev_handle != 0 ) //##++++ dev_handle NULL/0 ???
+ {
+ #if defined( MBG_TGT_WIN32 )
+ CloseHandle( *dev_handle );
+ #elif defined( MBG_TGT_UNIX )
+ close( *dev_handle );
+ #endif
+ }
+
+ *dev_handle = MBG_INVALID_DEV_HANDLE;
+
+} // mbg_close_device
+
+
+
+/*HDR*/
+/**
+ Return a ::PCPS_DRVR_INFO structure that provides information
+ about the kernel device driver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_DRVR_INFO structure which is filled up.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_DRVR_INFO, p );
+ return _mbgdevio_ret_val;
+ #else
+ #if defined( __BORLANDC__ )
+ dh; // avoid warnings "never used"
+ #endif
+ drvr_info.n_devs = n_ddevs;
+ *p = drvr_info;
+ return MBG_SUCCESS;
+ #endif
+
+} // mbg_get_drvr_info
+
+
+
+/*HDR*/
+/**
+ Return a ::PCPS_DEV structure that provides detailed information about the device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_DEV structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_DEV, p );
+ // Endianess is converted inside the kernel driver, if necessary.
+ return _mbgdevio_ret_val;
+ #else
+ *p = dh->dev;
+ return MBG_SUCCESS;
+ #endif
+
+} // mbg_get_device_info
+
+
+
+/*HDR*/
+/**
+ Return the current state of the on-board::PCPS_STATUS_PORT.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_STATUS_PORT value to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+
+ @see \ref group_status_port "bitmask"
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_STATUS_PORT, p );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+ #else
+ *p = _pcps_ddev_read_status_port( dh );
+ // No endianess conversion required.
+ return MBG_SUCCESS;
+ #endif
+
+} // mbg_get_status_port
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Generic read function which writes a command code to the device
+ and reads a number of replied data to a generic buffer.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device
+ @param *p Pointer to a buffer to be filled up
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_write()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_io()
+ */
+_MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd,
+ void *p, int size )
+{
+ _mbgdevio_vars();
+ _mbgdevio_gen_read( dh, cmd, p, size );
+ // No type information available, so endianess must be
+ // converted by the caller, if required.
+ return _mbgdevio_ret_val;
+
+} // mbg_generic_read
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Generic read function which writes a GPS command code to the device
+ and reads a number of replied data to a generic buffer.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any GPS command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be filled up
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_gps_data()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_io()
+ */
+_MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd,
+ void *p, int size )
+{
+ _mbgdevio_vars();
+ _mbgdevio_gen_read_gps( dh, cmd, p, size );
+ // No type information available, so endianess must be
+ // converted by the caller, if required.
+ return _mbgdevio_ret_val;
+
+} // mbg_generic_read_gps
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Generic write function which writes a command code plus an
+ associated number of data bytes to the device.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be written
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_read()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_io()
+ */
+_MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd,
+ const void *p, int size )
+{
+ _mbgdevio_vars();
+ // No type information available, so endianess must be
+ // converted by the caller, if required.
+ _mbgdevio_gen_write( dh, cmd, p, size );
+ return _mbgdevio_ret_val;
+
+} // mbg_generic_write
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Generic write function which writes a GPS command code plus an
+ associated number of data bytes to the device.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any GPS command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be written
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_gps_data()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_io()
+ */
+_MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd,
+ const void *p, int size )
+{
+ _mbgdevio_vars();
+ // No type information available, so endianess must be
+ // converted by the caller, if required.
+ _mbgdevio_gen_write_gps( dh, cmd, p, size );
+ return _mbgdevio_ret_val;
+
+} // mbg_generic_write_gps
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Write and/or read generic data to/from a device.
+ The macro _pcps_has_generic_io() or the API call mbg_dev_has_generic_io()
+ check whether this call is supported by a specific card.
+
+ <b>Warning</b>: This call is for debugging purposes and internal use only!
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_generic_io()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ */
+_MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type,
+ const void *in_p, int in_sz,
+ void *out_p, int out_sz )
+{
+ _mbgdevio_vars();
+ // No type information available, so endianess must be
+ // converted by the caller, if required.
+ _mbgdevio_gen_io( dh, type, in_p, in_sz, out_p, out_sz );
+ return _mbgdevio_ret_val;
+
+} // mbg_generic_io
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_TIME structure returning the current date/time/status.
+ The returned time is local time according to the card's time zone setting,
+ with a resolution of 10 ms (i.e. 10ths of seconds).
+
+ This call is supported by any device manufactured by Meinberg. However,
+ for higher accuracy and resolution the mbg_get_hr_time..() group of calls
+ should be used preferably if supported by the specific device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_set_time()
+ @see mbg_get_sync_time()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, PCPS_GIVE_TIME, IOCTL_GET_PCPS_TIME, p );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+
+} // mbg_get_time
+
+
+
+/*HDR*/
+/**
+ Set a device's on-board clock manually by passing a ::PCPS_STIME structure
+ The macro _pcps_can_set_time() checks whether this call
+ is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_STIME structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p )
+{
+ _mbgdevio_vars();
+ // No endianess conversion required.
+ _mbgdevio_write_var_chk( dh, PCPS_SET_TIME, IOCTL_SET_PCPS_TIME, p,
+ _pcps_ddev_can_set_time( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_time
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_TIME structure returning the date/time/status reporting
+ when the device was synchronized the last time to its time source,
+ e.g. the DCF77 signal or the GPS satellites.
+ The macro _pcps_has_sync_time() or the API call mbg_dev_has_sync_time()
+ check whether this call is supported by a specific card.
+
+ The macro _pcps_has_sync_time() checks whether this call
+ is supported by a specific card.
+
+ <b>Note:</b> If that information is not available on the board then
+ the value of the returned ::PCPS_TIME::sec field is set to 0xFF.
+ The macro _pcps_time_is_read() can be used to check whether the
+ returned information is valid, or not available.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GIVE_SYNC_TIME, IOCTL_GET_PCPS_SYNC_TIME,
+ p, _pcps_ddev_has_sync_time( dh ) );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+
+} // mbg_get_sync_time
+
+
+
+/*HDR*/
+/**
+ Wait until the next second change, then return a ::PCPS_TIME
+ structure similar to mbg_get_time().
+
+ <b>Note:</b> This API call is supported under Windows only.
+ The call blocks until the kernel driver detects a second change
+ reported by the device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_TIME_SEC_CHANGE, p );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+ #else
+ #if defined( __BORLANDC__ )
+ dh; p; // avoid warnings "never used"
+ #endif
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+ #endif
+
+} // mbg_get_time_sec_change
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_HR_TIME (High Resolution time) structure returning
+ the current %UTC time (seconds since 1970), %UTC offset, and status.
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This API call provides a higher accuracy and resolution
+ than mbg_get_time(). However, it does not account for the latency
+ which is introduced when accessing the board.
+ The mbg_get_hr_time_cycles() and mbg_get_hr_time_comp() calls
+ provides mechanisms to account for and/or compensate the latency.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_hr_time()
+ @see mbg_get_time()
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GIVE_HR_TIME, IOCTL_GET_PCPS_HR_TIME,
+ p, _pcps_ddev_has_hr_time( dh ) );
+ _mbg_swab_pcps_hr_time( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_hr_time
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen )
+ Write a high resolution time stamp ::PCPS_TIME_STAMP to the clock
+ to configure a %UTC time when the clock shall generate an event.
+ The macro _pcps_has_event_time() or the API call mbg_dev_has_event_time()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This is only supported by some special firmware.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_event_time()
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ PCPS_TIME_STAMP tmp = *p;
+ _mbg_swab_pcps_time_stamp( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_var_chk( dh, PCPS_SET_EVENT_TIME, IOCTL_SET_PCPS_EVENT_TIME,
+ p, _pcps_ddev_has_event_time( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_event_time
+
+
+
+/*HDR*/
+/**
+ Read the configuration of a device's serial port.
+ The macro _pcps_has_serial() checks whether this call
+ is supported by a specific card.
+
+ <b>Note:</b> This function is supported only by a certain class
+ of devices, so it should not be called directly. The generic
+ function mbg_get_serial_settings() should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_SERIAL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see \ref group_cmd_bytes
+ @see mbg_get_serial_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, PCPS_GET_SERIAL, IOCTL_GET_PCPS_SERIAL, p );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+
+} // mbg_get_serial
+
+
+
+/*HDR*/
+/**
+ Write the configuration of a device's serial port.
+ The macro _pcps_has_serial() checks whether this call
+ is supported by a specific card.
+
+ <b>Note:</b> This function is supported only by a certain class
+ of devices, so it should not be called directly. The generic
+ function mbg_save_serial_settings() should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_SERIAL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see \ref group_cmd_bytes
+ @see mbg_save_serial_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p )
+{
+ _mbgdevio_vars();
+ // No endianess conversion required.
+ _mbgdevio_write_var( dh, PCPS_SET_SERIAL, IOCTL_SET_PCPS_SERIAL, p );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_serial
+
+
+
+/*HDR*/
+/**
+ Read the card's time zone/daylight saving configuration code.
+ That tzcode is supported by some simpler cards and only allows only
+ a very basic configuration.
+ The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_get_pcps_tzdl() or mbg_get_gps_tzdl()
+ calls instead which allow for a more detailed configuration of the
+ time zone and daylight saving settings.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZCODE structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzcode()
+ @see mbg_set_tzcode()
+ @see mbg_get_pcps_tzdl()
+ @see mbg_get_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_TZCODE, IOCTL_GET_PCPS_TZCODE,
+ p, _pcps_ddev_has_tzcode( dh ) );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+
+} // mbg_get_tzcode
+
+
+
+/*HDR*/
+/**
+ Write the card's time zone/daylight saving configuration code.
+ That tzcode is supported by some simpler cards and only allows only
+ a very basic configuration.
+ The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_set_pcps_tzdl() or mbg_set_gps_tzdl()
+ calls instead which allow for a more detailed configuration of the
+ time zone and daylight saving settings.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZCODE structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzcode()
+ @see mbg_get_tzcode()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p )
+{
+ _mbgdevio_vars();
+ // No endianess conversion required.
+ _mbgdevio_write_var_chk( dh, PCPS_SET_TZCODE, IOCTL_SET_PCPS_TZCODE,
+ p, _pcps_ddev_has_tzcode( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_tzcode
+
+
+
+/*HDR*/
+/**
+ Read the card's time zone/daylight saving parameters using the
+ ::PCPS_TZDL structure.
+ The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_get_tzcode() or mbg_get_gps_tzdl()
+ calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZDL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_get_tzcode()
+ @see mbg_get_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_PCPS_TZDL, IOCTL_GET_PCPS_TZDL,
+ p, _pcps_ddev_has_pcps_tzdl( dh ) );
+ _mbg_swab_pcps_tzdl( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_pcps_tzdl
+
+
+
+/*HDR*/
+/**
+ Write the card's time zone/daylight saving parameters using the
+ ::PCPS_TZDL structure.
+ The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_set_tzcode() or mbg_set_gps_tzdl()
+ calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZDL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_get_pcps_tzdl()
+ @see mbg_set_tzcode()
+ @see mbg_set_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ PCPS_TZDL tmp = *p;
+ _mbg_swab_pcps_tzdl( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_var_chk( dh, PCPS_SET_PCPS_TZDL, IOCTL_SET_PCPS_TZDL,
+ p, _pcps_ddev_has_pcps_tzdl( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_pcps_tzdl
+
+
+
+/*HDR*/
+/**
+ Read the reference time offset from %UTC for clocks which can't determine
+ that offset automatically, e.g. from an IRIG input signal.
+ The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_REF_OFFS value to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ref_offs()
+ @see mbg_set_ref_offs()
+ @see ::PCPS_GET_REF_OFFS
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_REF_OFFS, IOCTL_GET_REF_OFFS,
+ p, _pcps_ddev_has_ref_offs( dh ) );
+ _mbg_swab_mbg_ref_offs( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ref_offs
+
+
+
+/*HDR*/
+/**
+ Write the reference time offset from %UTC for clocks which can't determine
+ that offset automatically, e.g. from an IRIG input signal.
+ The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_REF_OFFS value to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ref_offs()
+ @see mbg_get_ref_offs()
+ @see ::PCPS_SET_REF_OFFS
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ MBG_REF_OFFS tmp = *p;
+ _mbg_swab_mbg_ref_offs( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_var_chk( dh, PCPS_SET_REF_OFFS, IOCTL_SET_REF_OFFS,
+ p, _pcps_ddev_has_ref_offs( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_ref_offs
+
+
+
+/*HDR*/
+/**
+ Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags.
+ The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current
+ settings of those flags.
+ The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_OPT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_opt_flags()
+ @see mbg_set_opt_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_OPT_INFO, IOCTL_GET_MBG_OPT_INFO,
+ p, _pcps_ddev_has_opt_flags( dh ) );
+ _mbg_swab_mbg_opt_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_opt_info
+
+
+
+/*HDR*/
+/**
+ Write a ::MBG_OPT_SETTINGS structure contains optional settings, controlled by flags.
+ The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags()
+ check whether this call is supported by a specific card.
+ The ::MBG_OPT_INFO structure should be read first to check which of the specified
+ flags is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_OPT_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_opt_flags()
+ @see mbg_get_opt_info()
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ MBG_OPT_SETTINGS tmp = *p;
+ _mbg_swab_mbg_opt_settings( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_var_chk( dh, PCPS_SET_OPT_SETTINGS,
+ IOCTL_SET_MBG_OPT_SETTINGS, p,
+ _pcps_ddev_has_opt_flags( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_opt_settings
+
+
+
+/*HDR*/
+/**
+ Read an ::IRIG_INFO structure containing the configuration of an IRIG input
+ plus the possible settings supported by that input.
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_irig_rx_settings()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_IRIG_RX_INFO, IOCTL_GET_PCPS_IRIG_RX_INFO,
+ p, _pcps_ddev_is_irig_rx( dh ) );
+ _mbg_swab_irig_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_irig_rx_info
+
+
+
+/*HDR*/
+/**
+ Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG input.
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a specific card.
+ The ::IRIG_INFO structure should be read first to determine the possible
+ settings supported by this card's IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IRIG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_rx_info()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ IRIG_SETTINGS tmp = *p;
+ _mbg_swab_irig_settings( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_var_chk( dh, PCPS_SET_IRIG_RX_SETTINGS,
+ IOCTL_SET_PCPS_IRIG_RX_SETTINGS, p,
+ _pcps_ddev_is_irig_rx( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_irig_rx_settings
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_irig_ctrl_bits() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_ctrl_bits()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_irig_ctrl_bits, IOCTL_DEV_HAS_IRIG_CTRL_BITS, p );
+
+} // mbg_dev_has_irig_ctrl_bits
+
+
+
+/*HDR*/
+/**
+ Read a ::MBG_IRIG_CTRL_BITS type which contains the control function
+ bits of the latest IRIG input frame. Those bits may carry some
+ well-known information, as in the IEEE1344 code, but may also contain
+ some customized information, depending on the IRIG frame type and
+ the configuration of the IRIG generator. So these bits are returned
+ as-is and must be interpreted by the application.
+ The macro _pcps_has_irig_ctrl_bits() or the API call mbg_dev_has_irig_ctrl_bits()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_irig_ctrl_bits()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh,
+ MBG_IRIG_CTRL_BITS *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, PCPS_GET_IRIG_CTRL_BITS, IOCTL_GET_IRIG_CTRL_BITS, p );
+ _mbg_swab_irig_ctrl_bits( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_irig_ctrl_bits
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_raw_irig_data() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_raw_irig_data()
+ @see mbg_get_raw_irig_data_on_sec_change()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p)
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_raw_irig_data, IOCTL_DEV_HAS_RAW_IRIG_DATA, p );
+
+} // mbg_dev_has_raw_irig_data
+
+
+
+/*HDR*/
+/**
+ Read a ::MBG_RAW_IRIG_DATA type which contains all data
+ bits of the latest IRIG input frame.
+ The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_raw_irig_data()
+ @see mbg_get_raw_irig_data_on_sec_change()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh,
+ MBG_RAW_IRIG_DATA *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, PCPS_GET_RAW_IRIG_DATA, IOCTL_GET_RAW_IRIG_DATA, p );
+ // No endianess conversion required.
+ return _mbgdevio_ret_val;
+
+} // mbg_get_raw_irig_data
+
+
+
+/*HDR*/
+/**
+ Read a ::MBG_RAW_IRIG_DATA type just after a second change which contains all data
+ bits of the latest IRIG input frame.
+ The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The mbg_get_time_sec_change() function called by this function is
+ supported under Windows only, so this function can also only be used under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_raw_irig_data()
+ @see mbg_get_raw_irig_data()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh,
+ MBG_RAW_IRIG_DATA *p )
+{
+
+ PCPS_TIME t;
+
+ _mbgdevio_vars();
+
+ rc = mbg_get_time_sec_change( dh, &t);
+
+ if ( rc == MBG_SUCCESS )
+ rc = mbg_get_raw_irig_data( dh, p );
+ else
+ return rc;
+
+ return _mbgdevio_ret_val;
+
+} // mbg_get_raw_irig_data_on_sec_change
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_irig_time() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_time()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_irig_time, IOCTL_DEV_HAS_IRIG_TIME, p );
+
+} // mbg_dev_has_irig_time
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_IRIG_TIME type which returns the raw IRIG day-of-year number
+ and time decoded from the latest IRIG input frame. If the configured IRIG code
+ also contains the year number then the year number is also returned, otherwise
+ the returned year number is 0xFF.
+ The macro _pcps_has_irig_time() or the API call mbg_dev_has_irig_time()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_IRIG_TIME type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_irig_time()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh,
+ PCPS_IRIG_TIME *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, PCPS_GIVE_IRIG_TIME, IOCTL_GET_IRIG_TIME, p );
+ _mbg_swab_pcps_irig_time( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_irig_time
+
+
+
+/*HDR*/
+/**
+ Clear the card's on-board time capture FIFO buffer.
+ The macro _pcps_can_clr_ucap_buff() or the API call mbg_dev_can_clr_ucap_buff()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_can_clr_ucap_buff()
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ */
+_MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh )
+{
+ _mbgdevio_vars();
+ _mbgdevio_write_cmd_chk( dh, PCPS_CLR_UCAP_BUFF, IOCTL_PCPS_CLR_UCAP_BUFF,
+ _pcps_ddev_can_clr_ucap_buff( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_clr_ucap_buff
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_UCAP_ENTRIES structure to retrieve the number of saved
+ user capture events and the maximum capture buffer size.
+ The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ucap()
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_ENTRIES *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GIVE_UCAP_ENTRIES,
+ IOCTL_GET_PCPS_UCAP_ENTRIES, p,
+ _pcps_ddev_has_ucap( dh ) );
+ _mbg_swab_pcps_ucap_entries( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ucap_entries
+
+
+
+/*HDR*/
+/**
+ Retrieve a single time capture event from the on-board FIFO buffer
+ using a ::PCPS_HR_TIME structure. The oldest entry of the FIFO is retrieved
+ and then removed from the FIFO.
+ If no capture event is available in the FIFO buffer then both the seconds
+ and the fractions of the returned timestamp are 0.
+ The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This call is very much faster than the older mbg_get_gps_ucap()
+ call which is obsolete but still supported for compatibility with
+ older cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ucap()
+ @see mbg_get_ucap_entries()
+ @see mbg_clr_ucap_buff()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GIVE_UCAP_EVENT,
+ IOCTL_GET_PCPS_UCAP_EVENT, p,
+ _pcps_ddev_has_ucap( dh ) );
+ _mbg_swab_pcps_hr_time( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ucap_event
+
+
+
+/*HDR*/
+/**
+ Read the card's time zone/daylight saving parameters using the ::TZDL
+ structure.
+ The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> In spite of the function name this call may also be
+ supported by non-GPS cards. Other cards may support the mbg_get_tzcode()
+ or mbg_get_pcps_tzdl() calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TZDL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see mbg_get_tzcode()
+ @see mbg_get_pcps_tzdl()
+ @see \ref group_tzdl
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_TZDL, IOCTL_GET_GPS_TZDL, p );
+ _mbg_swab_tzdl( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_tzdl
+
+
+
+/*HDR*/
+/**
+ Write the card's time zone/daylight saving parameters using the ::TZDL
+ structure.
+ The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> In spite of the function name this call may also be
+ supported by non-GPS cards. Other cards may support the mbg_set_tzcode()
+ or mbg_set_pcps_tzdl() calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TZDL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_get_gps_tzdl()
+ @see mbg_set_tzcode()
+ @see mbg_set_pcps_tzdl()
+ @see \ref group_tzdl
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ TZDL tmp = *p;
+ _mbg_swab_tzdl( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var( dh, PC_GPS_TZDL, IOCTL_SET_GPS_TZDL, p );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_tzdl
+
+
+
+/*HDR*/
+/**
+ Retrieve the software revision of a GPS receiver.
+ This call is obsolete but still supported for compatibility
+ with older GPS cards.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The function mbg_get_gps_receiver_info() should
+ be used instead, if supported by the card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SW_REV structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_is_gps()
+ @see mbg_get_gps_receiver_info()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_SW_REV, IOCTL_GET_GPS_SW_REV, p );
+ _mbg_swab_sw_rev( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_sw_rev
+
+
+
+/*HDR*/
+/**
+ Retrieve the status of the battery buffered GPS variables.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+ The GPS receiver stays in cold boot mode until all of the
+ data sets are valid.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::BVAR_STAT structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_BVAR_STAT, IOCTL_GET_GPS_BVAR_STAT, p );
+ _mbg_swab_bvar_stat( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_stat
+
+
+
+/*HDR*/
+/**
+ Read the current board time using a ::TTM structure.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This call is pretty slow, so the mbg_get_hr_time_..()
+ group of calls should be used preferably.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_TIME, IOCTL_GET_GPS_TIME, p );
+ _mbg_swab_ttm( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_time
+
+
+
+/*HDR*/
+/**
+ Write a ::TTM structure to a GPS receiver in order to set the
+ on-board date and time.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ TTM tmp = *p;
+ _mbg_swab_ttm( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var( dh, PC_GPS_TIME, IOCTL_SET_GPS_TIME, p );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_time
+
+
+
+/*HDR*/
+/**
+ Read a ::PORT_PARM structure to retrieve the configuration
+ of the device's serial ports.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This function is obsolete since it is only
+ supported by a certain class of devices and can handle only
+ up to 2 ports. The generic function mbg_get_serial_settings()
+ should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PORT_PARM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_PORT_PARM, IOCTL_GET_GPS_PORT_PARM, p );
+ _mbg_swab_port_parm( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_port_parm
+
+
+
+/*HDR*/
+/**
+ Write a ::PORT_PARM structure to configure the on-board
+ serial ports.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This function is obsolete since it is only
+ supported by a certain class of devices and can handle only
+ up to 2 ports. The generic function mbg_save_serial_settings()
+ should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PORT_PARM structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_PARM *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ PORT_PARM tmp = *p;
+ _mbg_swab_port_parm( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var( dh, PC_GPS_PORT_PARM, IOCTL_SET_GPS_PORT_PARM, p );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_port_parm
+
+
+
+/*HDR*/
+/**
+ Read an ::ANT_INFO structure to retrieve status information of the GPS antenna.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Normally the antenna connection status can also be
+ determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal
+ fields.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ANT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_ANT_INFO, IOCTL_GET_GPS_ANT_INFO, p );
+ _mbg_swab_ant_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_ant_info
+
+
+
+/*HDR*/
+/**
+ Read a time capture event from the on-board FIFO buffer using a ::TTM structure.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This call is pretty slow and has been obsoleted by
+ mbg_get_ucap_event() which should be used preferably, if supported
+ by the card. Anyway, this call is still supported for compatibility
+ with older cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ @see mbg_clr_ucap_buff()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_UCAP, IOCTL_GET_GPS_UCAP, p );
+ _mbg_swab_ttm( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_ucap
+
+
+
+/*HDR*/
+/**
+ Read an ::ENABLE_FLAGS structure reporting whether certain outputs
+ shall be enabled immediately after the card's power-up, or only
+ after the card has synchronized to its input signal.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Not all of the input signals specified for the
+ ::ENABLE_FLAGS structure can be modified individually.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::ENABLE_FLAGS structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::ENABLE_FLAGS
+ @see mbg_set_gps_enable_flags()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_FLAGS *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_ENABLE_FLAGS,
+ IOCTL_GET_GPS_ENABLE_FLAGS, p );
+ _mbg_swab_enable_flags( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_enable_flags
+
+
+
+/*HDR*/
+/**
+ Write an ENABLE_FLAGS structure to configure whether certain outputs
+ shall be enabled immediately after the card's power-up, or only
+ after the card has synchronized to its input signal.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Not all of the input signals specified for the
+ ENABLE_FLAGS structure can be modified individually.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ENABLE_FLAGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ENABLE_FLAGS
+ @see mbg_get_gps_enable_flags()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh,
+ const ENABLE_FLAGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ ENABLE_FLAGS tmp = *p;
+ _mbg_swab_enable_flags( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var( dh, PC_GPS_ENABLE_FLAGS,
+ IOCTL_SET_GPS_ENABLE_FLAGS, p );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_enable_flags
+
+
+
+/*HDR*/
+/**
+ Read a ::STAT_INFO structure to retrieve the status of the
+ GPS receiver, including mode of operation and numer of
+ visible/usable satellites.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::STAT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::STAT_INFO
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_STAT_INFO, IOCTL_GET_GPS_STAT_INFO, p );
+ _mbg_swab_stat_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_stat_info
+
+
+
+/*HDR*/
+/**
+ Sends a ::GPS_CMD to a GPS receiver.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::GPS_CMD
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::PC_GPS_CMD_BOOT, ::PC_GPS_CMD_INIT_SYS, ::PC_GPS_CMD_INIT_USER, ::PC_GPS_CMD_INIT_DAC
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_cmd( MBG_DEV_HANDLE dh, const GPS_CMD *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ GPS_CMD tmp = *p;
+ _mbg_swab_gps_cmd( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var( dh, PC_GPS_CMD, IOCTL_SET_GPS_CMD, p );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_cmd
+
+
+/*HDR*/
+/**
+ Read the current GPS receiver position using the ::POS structure
+ which contains different coordinate formats.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POS structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_xyz()
+ @see mbg_set_gps_pos_lla()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var( dh, PC_GPS_POS, IOCTL_GET_GPS_POS, p );
+ swap_pos_doubles( p );
+ _mbg_swab_pos( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_pos
+
+
+
+/*HDR*/
+/**
+ Preset the GPS receiver position using ::XYZ coordinates
+ (ECEF: WGS84 "Earth Centered, Earth fixed" kartesian coordinates).
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param p Position in ::XYZ format to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_lla()
+ @see mbg_get_gps_pos()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p )
+{
+ _mbgdevio_vars();
+ XYZ xyz;
+ int i;
+
+ for ( i = 0; i < N_XYZ; i++ )
+ {
+ xyz[i] = p[i];
+ swap_double( &xyz[i] );
+ _mbg_swab_double( &xyz[i] );
+ }
+
+ _mbgdevio_write_gps_var( dh, PC_GPS_POS_XYZ, IOCTL_SET_GPS_POS_XYZ, xyz );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_pos_xyz
+
+
+
+/*HDR*/
+/**
+ Preset the GPS receiver position using ::LLA coordinates
+ (longitude, latitude, altitude)
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param p Position in ::LLA format to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_xyz()
+ @see mbg_get_gps_pos()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p )
+{
+ _mbgdevio_vars();
+ LLA lla;
+ int i;
+
+ for ( i = 0; i < N_LLA; i++ )
+ {
+ lla[i] = p[i];
+ swap_double( &lla[i] );
+ _mbg_swab_double( &lla[i] );
+ }
+
+ _mbgdevio_write_gps_var( dh, PC_GPS_POS_LLA, IOCTL_SET_GPS_POS_LLA, lla );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_pos_lla
+
+
+
+/*HDR*/
+/**
+ Read the configured length of the GPS antenna cable (::ANT_CABLE_LEN).
+ The cable delay is internally compensated by 5ns per meter cable.
+ The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::ANT_CABLE_LEN structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_cab_len()
+ @see mbg_set_gps_ant_cable_len()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_ANT_CABLE_LEN,
+ IOCTL_GET_GPS_ANT_CABLE_LEN, p,
+ _pcps_ddev_has_cab_len( dh ) );
+ _mbg_swab_ant_cable_len( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_ant_cable_len
+
+
+
+/*HDR*/
+/**
+ Write the length of the GPS antenna cable (::ANT_CABLE_LEN).
+ The cable delay is internally compensated by 5ns per meter cable.
+ The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::ANT_CABLE_LEN structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_cab_len()
+ @see mbg_get_gps_ant_cable_len()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh,
+ const ANT_CABLE_LEN *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ ANT_CABLE_LEN tmp = *p;
+ _mbg_swab_ant_cable_len( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_ANT_CABLE_LEN,
+ IOCTL_SET_GPS_ANT_CABLE_LEN, p,
+ _pcps_ddev_has_cab_len( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_ant_cable_len
+
+
+
+/*HDR*/
+/**
+ Read a ::RECEIVER_INFO structure from a card.
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Applications should call mbg_setup_receiver_info()
+ preferably, which also sets up a basic ::RECEIVER_INFO structure
+ for card which don't provide that structure by themselves.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::RECEIVER_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_RECEIVER_INFO,
+ IOCTL_GET_GPS_RECEIVER_INFO, p,
+ _pcps_ddev_has_receiver_info( dh ) );
+
+ _mbg_swab_receiver_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_receiver_info
+
+
+
+#if !MBGDEVIO_SIMPLE
+
+static /*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Read a ::STR_TYPE_INFO_IDX array of supported string types.
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+
+ <b>Note:</b> The function mbg_get_serial_settings() should be used preferably
+ to get retrieve the cuurrent port settings and configuration options.
+
+ @param dh Valid handle to a Meinberg device.
+ @param stii Pointer to a an array of string type information to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+ @see mbg_get_gps_all_port_info()
+ @see mbg_get_serial_settings()
+*/
+int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh,
+ STR_TYPE_INFO_IDX stii[],
+ const RECEIVER_INFO *p_ri )
+{
+ _mbgdevio_vars();
+
+ #if _MBG_SUPP_VAR_ACC_SIZE
+ _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_STR_TYPE_INFO,
+ IOCTL_GET_GPS_ALL_STR_TYPE_INFO, stii,
+ p_ri->n_str_type * sizeof( stii[0] ),
+ _pcps_ddev_has_receiver_info( dh ) );
+ #else
+ // We check the model_code to see whether the receiver info
+ // has been read from a device which really supports it, or
+ // a dummy structure has been setup.
+ if ( p_ri && ( p_ri->model_code != GPS_MODEL_UNKNOWN ) )
+ _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_STR_TYPE_INFO, stii,
+ p_ri->n_str_type * sizeof( stii[0] ) );
+ else
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV );
+ #endif
+
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ if ( rc == MBG_SUCCESS )
+ {
+ int i;
+ for ( i = 0; i < p_ri->n_str_type; i++ )
+ {
+ STR_TYPE_INFO_IDX *p = &stii[i];
+ _mbg_swab_str_type_info_idx( p );
+ }
+ }
+ #endif
+
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_all_str_type_info
+
+
+
+static /*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Read a ::PORT_INFO_IDX array of supported serial port configurations.
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+
+ <b>Note:</b> The function mbg_get_serial_settings() should be used preferably
+ to get retrieve the cuurrent port settings and configuration options.
+
+ @param dh Valid handle to a Meinberg device.
+ @param pii Pointer to a an array of port configuration information to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+ @see mbg_get_gps_all_str_type_info()
+ @see mbg_get_serial_settings()
+*/
+int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh,
+ PORT_INFO_IDX pii[],
+ const RECEIVER_INFO *p_ri )
+{
+ _mbgdevio_vars();
+
+ #if _MBG_SUPP_VAR_ACC_SIZE
+ _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_PORT_INFO,
+ IOCTL_GET_GPS_ALL_PORT_INFO, pii,
+ p_ri->n_com_ports * sizeof( pii[0] ),
+ _pcps_ddev_has_receiver_info( dh ) );
+ #else
+ // We check the model_code to see whether the receiver info
+ // has been read from a device which really supports it, or
+ // a dummy structure has been setup.
+ if ( p_ri && ( p_ri->model_code != GPS_MODEL_UNKNOWN ) )
+ _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_PORT_INFO, pii,
+ p_ri->n_com_ports * sizeof( pii[0] ) );
+ else
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV );
+ #endif
+
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ if ( rc == MBG_SUCCESS )
+ {
+ int i;
+ for ( i = 0; i < p_ri->n_com_ports; i++ )
+ {
+ PORT_INFO_IDX *p = &pii[i];
+ _mbg_swab_port_info_idx( p );
+ }
+ }
+ #endif
+
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_all_port_info
+
+
+
+/*HDR*/
+/**
+ Write the configuration for a single serial port using the ::PORT_SETTINGS_IDX
+ structure which contains both the ::PORT_SETTINGS and the port index value.
+ Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings().
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The function mbg_save_serial_settings() should be used preferably
+ to write new port configuration to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PORT_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+ @see mbg_set_gps_port_settings()
+ @see mbg_dev_has_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh,
+ const PORT_SETTINGS_IDX *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ PORT_SETTINGS_IDX tmp = *p;
+ _mbg_swab_port_settings_idx( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_PORT_SETTINGS_IDX,
+ IOCTL_SET_GPS_PORT_SETTINGS_IDX, p,
+ _pcps_ddev_has_receiver_info( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_port_settings_idx
+
+
+
+/*HDR*/
+/**
+ Write the configuration for a single serial port using the ::PORT_SETTINGS
+ structure plus the port index.
+ Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings_idx().
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The function mbg_save_serial_settings() should be used preferably
+ to write new port configuration to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PORT_SETTINGS structure to be filled up
+ @param idx Index of the serial port to be configured (starting from 0 ).
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+ @see mbg_set_gps_port_settings_idx()
+ @see mbg_dev_has_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh,
+ const PORT_SETTINGS *p, int idx )
+{
+ PORT_SETTINGS_IDX psi = { 0 };
+
+ psi.idx = idx;
+ psi.port_settings = *p;
+ _mbg_swab_port_settings_idx( &psi );
+
+ return mbg_set_gps_port_settings_idx( dh, &psi );
+
+} // mbg_set_gps_port_settings
+
+#endif // !MBGDEVIO_SIMPLE
+
+
+
+/*HDR*/
+/**
+ Set up a ::RECEIVER_INFO structure for a device.
+ If the device supports the ::RECEIVER_INFO structure then the structure
+ is read from the device, otherwise a structure is set up using
+ default values depending on the device type.
+ The function mbg_get_device_info() must have been called before,
+ and the returned PCPS_DEV structure passed to this function.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure returned by mbg_get_device_info()
+ @param *p Pointer to a ::RECEIVER_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_dev_has_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh,
+ const PCPS_DEV *pdev,
+ RECEIVER_INFO *p )
+{
+ // If the clock supports the receiver_info structure then
+ // read it from the clock, otherwise set up some default
+ // values depending on the clock type.
+ if ( _pcps_has_receiver_info( pdev ) )
+ {
+ int rc = mbg_get_gps_receiver_info( dh, p );
+
+ if ( rc != MBG_SUCCESS )
+ return rc;
+
+ goto check;
+ }
+
+ if ( _pcps_is_gps( pdev ) )
+ _setup_default_receiver_info_gps( p );
+ else
+ _setup_default_receiver_info_dcf( p, pdev );
+
+check:
+ // Make sure this program supports at least as many ports as
+ // the current clock device.
+ if ( p->n_com_ports > MAX_PARM_PORT )
+ return _mbg_err_to_os( MBG_ERR_N_COM_EXCEEDS_SUPP );
+
+ // Make sure this program supports at least as many string types
+ // as the current clock device.
+ if ( p->n_str_type > MAX_PARM_STR_TYPE )
+ return _mbg_err_to_os( MBG_ERR_N_STR_EXCEEDS_SUPP );
+
+
+ return MBG_SUCCESS;
+
+} // mbg_setup_receiver_info
+
+
+
+#if !MBGDEVIO_SIMPLE
+
+// The functions below can conditionally be excluded from build
+// for simple applications which don't do complex card configuration.
+// This reduces the number of modules needed to be linked to the
+// application.
+
+/*HDR*/
+/**
+ Read all serial port settings and supported configuration parameters.
+
+ The functions mbg_get_device_info() and mbg_setup_receiver_info()
+ must have been called before, and the returned ::PCPS_DEV and
+ ::RECEIVER_INFO structures must be passed to this function.
+
+ The complementary function mbg_save_serial_settings() should be used
+ to write the modified serial port configuration back to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure.
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up.
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+ @see mbg_save_serial_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_serial_settings( MBG_DEV_HANDLE dh,
+ const PCPS_DEV *pdev,
+ RECEIVER_PORT_CFG *pcfg,
+ const RECEIVER_INFO *p_ri )
+{
+ int rc;
+ int i;
+
+ memset( pcfg, 0, sizeof( *pcfg ) );
+
+ if ( _pcps_has_receiver_info( pdev ) )
+ {
+ rc = mbg_get_gps_all_port_info( dh, pcfg->pii, p_ri );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+
+ rc = mbg_get_gps_all_str_type_info( dh, pcfg->stii, p_ri );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+ }
+ else
+ {
+ if ( _pcps_is_gps( pdev ) )
+ {
+ rc = mbg_get_gps_port_parm( dh, &pcfg->tmp_pp );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+
+ for ( i = 0; i < p_ri->n_com_ports; i++ )
+ {
+ PORT_INFO_IDX *p_pii = &pcfg->pii[i];
+ PORT_INFO *p_pi = &p_pii->port_info;
+
+ p_pii->idx = i;
+ port_settings_from_port_parm( &p_pi->port_settings,
+ i, &pcfg->tmp_pp, 1 );
+
+ p_pi->supp_baud_rates = DEFAULT_GPS_BAUD_RATES_C166;
+ p_pi->supp_framings = DEFAULT_GPS_FRAMINGS_C166;
+ p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_GPS;
+ }
+ }
+ else
+ if ( _pcps_has_serial ( pdev ) ) // Not all non-GPS clocks have a serial port!
+ {
+ PCPS_SERIAL ser_code;
+
+ rc = mbg_get_serial( dh, &ser_code );
+ if ( rc != MBG_SUCCESS )
+ goto error;
+
+
+ port_info_from_pcps_serial( pcfg->pii, ser_code,
+ _pcps_has_serial_hs( pdev ) ?
+ DEFAULT_BAUD_RATES_DCF_HS :
+ DEFAULT_BAUD_RATES_DCF
+ );
+ }
+
+ for ( i = 0; i < p_ri->n_str_type; i++ )
+ {
+ STR_TYPE_INFO_IDX *stip = &pcfg->stii[i];
+ stip->idx = i;
+ stip->str_type_info = default_str_type_info[i];
+ }
+ }
+
+ return MBG_SUCCESS;
+
+
+error:
+ return rc;
+
+} // mbg_get_serial_settings
+
+
+
+/*HDR*/
+/**
+ Write the configuration settings for a single serial port to the board.
+
+ Modifications to the serial port configuration should be made only
+ after mbg_get_serial_settings() had been called to read all serial port
+ settings and supported configuration parameters.
+ This function has finally to be called once for every serial port
+ the configuration of which has been modified.
+
+ As also required by mbg_get_serial_settings(), the functions
+ mbg_get_device_info() and mbg_setup_receiver_info() must have been
+ called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures
+ must be passed to this function.
+
+ @param dh Valid handle to a Meinberg device
+ @param *pdev Pointer to a ::PCPS_DEV structure
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure
+ @param port_num Index of the ::serial port to be saved
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_save_serial_settings( MBG_DEV_HANDLE dh,
+ const PCPS_DEV *pdev,
+ RECEIVER_PORT_CFG *pcfg,
+ int port_num )
+{
+ int rc;
+
+ if ( _pcps_has_receiver_info( pdev ) )
+ {
+ rc = mbg_set_gps_port_settings( dh, &pcfg->pii[port_num].port_info.port_settings, port_num );
+ }
+ else
+ {
+ if ( _pcps_is_gps( pdev ) )
+ {
+ port_parm_from_port_settings( &pcfg->tmp_pp, port_num,
+ &pcfg->pii[port_num].port_info.port_settings, 1 );
+
+ rc = mbg_set_gps_port_parm( dh, &pcfg->tmp_pp );
+ }
+ else
+ {
+ PCPS_SERIAL ser_code;
+
+ pcps_serial_from_port_info( &ser_code, pcfg->pii );
+
+ rc = mbg_set_serial( dh, &ser_code );
+ }
+ }
+
+ return rc;
+
+} // mbg_save_serial_settings
+
+#endif // !MBGDEVIO_SIMPLE
+
+
+
+/*HDR*/
+/**
+ Read the version code of the on-board PCI/PCIe interface ASIC.
+ The macro _pcps_has_asic_version() or the API call mbg_dev_has_asic_version()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCI_ASIC_VERSION type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+
+ @see mbg_dev_has_asic_version()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p )
+{
+
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_PCI_ASIC_VERSION, p );
+ return _mbgdevio_ret_val;
+ #else
+ if ( !_pcps_ddev_has_asic_version( dh ) )
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV );
+
+ *p = _mbg_inp32_to_cpu( dh, 0, _pcps_ddev_io_base_mapped( dh, 0 )
+ + offsetof( PCI_ASIC, raw_version ) );
+
+ return MBG_SUCCESS;
+ #endif
+
+} // mbg_get_asic_version
+
+
+
+/*HDR*/
+/**
+ Read the features of the on-board PCI/PCIe interface ASIC.
+ The macro _pcps_has_asic_features() or the API call mbg_dev_has_asic_features()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PCI_ASIC_FEATURES type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_asic_features()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh,
+ PCI_ASIC_FEATURES *p )
+{
+
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_PCI_ASIC_FEATURES, p );
+ return _mbgdevio_ret_val;
+ #else
+ if ( !_pcps_ddev_has_asic_features( dh ) )
+ {
+ *p = 0;
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV );
+ }
+
+ *p = _mbg_inp32_to_cpu( dh, 0, _pcps_ddev_io_base_mapped( dh, 0 )
+ + offsetof( PCI_ASIC, features ) );
+
+ return MBG_SUCCESS;
+ #endif
+
+} // mbg_get_asic_features
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports configurable time scales.
+
+ By default the cards return UTC and/or local time. However, some cards
+ can be configured to return pure GPS time or TAI instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time_scale_info()
+ @see mbg_set_time_scale_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_time_scale, IOCTL_DEV_HAS_GPS_TIME_SCALE, p );
+
+} // mbg_dev_has_time_scale
+
+
+
+/*HDR*/
+/**
+ Read a ::MBG_TIME_SCALE_INFO structure from a card telling which time scales
+ are supported by a card, and the current settings of the card.
+
+ The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_time_scale().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_time_scale_settings()
+ @see mbg_dev_has_time_scale()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_TIME_SCALE,
+ IOCTL_GET_GPS_TIME_SCALE_INFO, p,
+ _pcps_ddev_has_time_scale( dh ) );
+ _mbg_swab_mbg_time_scale_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_time_scale_info
+
+
+
+/*HDR*/
+/**
+ Write a ::MBG_TIME_SCALE_SETTINGS structure to a card which determines
+ which time scale shall be represented by time stamps read from the card.
+
+ The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_time_scale().
+
+ The function mbg_get_time_scale_info() should have been called before
+ in order to determine which time scales are supported by the card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time_scale_info()
+ @see mbg_dev_has_time_scale()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ MBG_TIME_SCALE_SETTINGS tmp = *p;
+ _mbg_swab_mbg_time_scale_settings( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_TIME_SCALE,
+ IOCTL_SET_GPS_TIME_SCALE_SETTINGS, p,
+ _pcps_ddev_has_time_scale( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_time_scale_settings
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports reading/writing a GPS UTC parameter
+ set via the PC bus (reading/writing these parameters via the serial port
+ is supported by all GPS devices).
+
+ The UTC parameters are normally received from the satellites' broadcasts
+ and contain the current time offset between GPT time and UTC, plus information
+ on a pending leap second.
+
+ It may be useful to overwrite them to do some tests, or for applications
+ where a card is freewheeling.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_utc_parm()
+ @see mbg_set_utc_parm()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_utc_parm, IOCTL_DEV_HAS_GPS_UTC_PARM, p );
+
+} // mbg_dev_has_utc_parm
+
+
+
+/*HDR*/
+/**
+ Read a ::UTC structure from a card.
+
+ The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_utc_parm().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::UTC structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_utc_parm()
+ @see mbg_set_utc_parm()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_UTC,
+ IOCTL_GET_GPS_UTC_PARM, p,
+ _pcps_ddev_has_utc_parm( dh ) );
+ _mbg_swab_utc_parm( p );
+ swap_double( &p->A0 );
+ swap_double( &p->A1 );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_utc_parm
+
+
+
+/*HDR*/
+/**
+ Write a ::UTC structure to a card.
+
+ This should only be done for testing, or if a card is operated in
+ freewheeling mode. If the card receives any satellites the settings
+ written to the board are overwritten by the parameters broadcasted
+ by the satellites.
+
+ The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_utc_parm().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a valid ::UTC structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_utc_parm()
+ @see mbg_get_utc_parm()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ UTC tmp = *p;
+ _mbg_swab_utc_parm( &tmp );
+ p = &tmp;
+ #endif
+ swap_double( &p->A0 );
+ swap_double( &p->A1 );
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_UTC,
+ IOCTL_SET_GPS_UTC_PARM, p,
+ _pcps_ddev_has_utc_parm( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_utc_parm
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_TIME_CYCLES structure that contains a ::PCPS_TIME structure
+ and a PC cycle counter value which can be used to compensate the latency
+ of the call, i.e. the program execution time until the time stamp has actually
+ been read from the board.
+
+ This call is supported for any card, similar to mbg_get_time(). However,
+ the mbg_get_hr_time_cyles() call should be used preferably if supported by
+ the specific card since that call provides much better accuracy than this one.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On other operating systems the returned
+ cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYCLES *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, PCPS_GIVE_TIME, IOCTL_GET_PCPS_TIME_CYCLES, p );
+ // No endianess conversion required.
+ #if !defined( _MBGIOCTL_H )
+ // only if not using IOCTLs
+ // for PCPS_TIME, read stamp AFTER the call
+ p->cycles = 0; //##++
+ #endif
+ return _mbgdevio_ret_val;
+
+} // mbg_get_time_cycles
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_HR_TIME_CYCLES structure that contains a ::PCPS_HR_TIME structure
+ and a PC cycle counter value which can be used to compensate the latency
+ of the call, i.e. the program execution time until the time stamp has actually
+ been read from the board.
+
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a specific card.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On other operating systems the returned
+ cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time_cycles()
+ @see mbg_get_time()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh,
+ PCPS_HR_TIME_CYCLES *p )
+{
+ _mbgdevio_vars();
+ #if !defined( _MBGIOCTL_H )
+ // only if not using IOCTLs
+ // for PCPS_HR_TIME, read stamp BEFORE the call
+ p->cycles = 0; //##++
+ #endif
+ _mbgdevio_read_var_chk( dh, PCPS_GIVE_HR_TIME,
+ IOCTL_GET_PCPS_HR_TIME_CYCLES,
+ p, _pcps_ddev_has_hr_time( dh ) );
+ _mbg_swab_pcps_hr_time_cycles( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_hr_time_cycles
+
+
+
+/*HDR*/
+/**
+ Read a ::PCPS_HR_TIME structure plus cycle counter value, and correct the
+ time stamp for the latency of the call as described for mbg_get_hr_time_cycles(),
+ then return the compensated time stamp and optionally the latency.
+
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a specific card.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On other operating systems the returned
+ cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+ @param *hns_latency Optional pointer to an int32_t value to return
+ the latency in 100ns units. Pass NULL if not used.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time_cycles()
+ @see mbg_get_time()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p,
+ int32_t *hns_latency )
+{
+ PCPS_HR_TIME_CYCLES htc;
+ MBG_PC_CYCLES cyc_now;
+ int rc;
+
+ // First get current time stamp counter value, then read
+ // a high resolution time stamp from the board, plus the
+ // associated time stamp counter value.
+ mbg_get_pc_cycles( &cyc_now );
+
+ rc = mbg_get_hr_time_cycles( dh, &htc );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ mbg_init_pc_cycles_frequency( dh, &pc_cycles_frequency );
+ rc = mbg_comp_hr_latency( &htc.t.tstamp, &htc.cycles, &cyc_now, &pc_cycles_frequency, hns_latency );
+ *p = htc.t;
+ }
+
+ return rc;
+
+} // mbg_get_hr_time_comp
+
+
+
+/*HDR*/
+/**
+ Read an ::IRIG_INFO structure containing the configuration of an IRIG output
+ plus the possible settings supported by that output.
+ The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_irig_tx_settings()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p )
+{
+ _mbgdevio_vars();
+
+ #if !defined( _MBGIOCTL_H )
+ // This is a workaround for GPS169PCIs with early
+ // firmware versions. See RCS log for details.
+ uint8_t pcps_cmd = PCPS_GET_IRIG_TX_INFO;
+
+ if ( _pcps_ddev_requires_irig_workaround( dh ) )
+ pcps_cmd = PCPS_GET_IRIG_RX_INFO;
+
+ #define _PCPS_CMD pcps_cmd
+ #else
+ #define _PCPS_CMD PCPS_GET_IRIG_TX_INFO
+ #endif
+
+ _mbgdevio_read_var_chk( dh, _PCPS_CMD, IOCTL_GET_PCPS_IRIG_TX_INFO,
+ p, _pcps_ddev_has_irig_tx( dh ) );
+ #undef _PCPS_CMD
+
+ _mbg_swab_irig_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_irig_tx_info
+
+
+
+/*HDR*/
+/**
+ Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG output.
+ The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_tx_info()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if !defined( _MBGIOCTL_H )
+ uint8_t pcps_cmd;
+ #endif
+
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ IRIG_SETTINGS tmp = *p;
+ _mbg_swab_irig_settings( &tmp );
+ p = &tmp;
+ #endif
+
+ #if !defined( _MBGIOCTL_H )
+ // This is a workaround for GPS169PCIs with early
+ // firmware versions. See RCS log for details.
+ pcps_cmd = PCPS_SET_IRIG_TX_SETTINGS;
+
+ if ( _pcps_ddev_requires_irig_workaround( dh ) )
+ pcps_cmd = PCPS_SET_IRIG_RX_SETTINGS;
+
+ #define _PCPS_CMD pcps_cmd
+ #else
+ #define _PCPS_CMD PCPS_SET_IRIG_TX_SETTINGS
+ #endif
+
+ _mbgdevio_write_var_chk( dh, _PCPS_CMD, IOCTL_SET_PCPS_IRIG_TX_SETTINGS,
+ p, _pcps_ddev_has_irig_tx( dh ) );
+ #undef _PCPS_CMD
+
+ return _mbgdevio_ret_val;
+
+} // mbg_set_irig_tx_settings
+
+
+
+/*HDR*/
+/**
+ Read a ::SYNTH structure containing the configuration of an optional
+ on-board programmable frequency synthesizer.
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_set_synth()
+ @see mbg_get_synth_state()
+ @see \ref group_synth
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_SYNTH, IOCTL_GET_SYNTH,
+ p, _pcps_ddev_has_synth( dh ) );
+ _mbg_swab_synth( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_synth
+
+
+
+/*HDR*/
+/**
+ Write a ::SYNTH structure containing the configuration of an optional
+ on-board programmable frequency synthesizer.
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_get_synth()
+ @see mbg_get_synth_state()
+ @see \ref group_synth
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ SYNTH tmp = *p;
+ _mbg_swab_synth( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_var_chk( dh, PCPS_SET_SYNTH, IOCTL_SET_SYNTH,
+ p, _pcps_ddev_has_synth( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_synth
+
+
+
+/*HDR*/
+/**
+ Read a ::SYNTH_STATE structure reporting the current state
+ of an optional on-board programmable frequency synthesizer.
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH_STATE structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_get_synth()
+ @see mbg_set_synth()
+ @see \ref group_synth
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, PCPS_GET_SYNTH_STATE, IOCTL_GET_SYNTH_STATE,
+ p, _pcps_ddev_has_synth( dh ) );
+ _mbg_swab_synth_state( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_synth_state
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_fast_hr_timestamp_...() calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_fast_hr_timestamp_cycles()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_fast_hr_timestamp, IOCTL_HAS_FAST_HR_TIMESTAMP, p );
+
+} // mbg_dev_has_fast_hr_timestamp
+
+
+
+/*HDR*/
+/**
+ Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_cycles( MBG_DEV_HANDLE dh,
+ PCPS_TIME_STAMP_CYCLES *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES, p );
+ // native endianess, no need to swap bytes
+ return _mbgdevio_ret_val;
+ #else
+ // This is currently not supported by the target environment.
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+ #endif
+} // mbg_get_fast_hr_timestamp_cycles
+
+
+
+/*HDR*/
+/**
+ Read a high resolution ::PCPS_TIME_STAMP via memory mapped access,
+ and compensate the latency of the time stamp before it is returned.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up
+ @param *hns_latency Optionally receive the latency in hectonanoseconds
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_cycles()
+ @see mbg_get_fast_hr_timestamp()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh,
+ PCPS_TIME_STAMP *p,
+ int32_t *hns_latency )
+{
+ PCPS_TIME_STAMP_CYCLES tc;
+ MBG_PC_CYCLES cyc_now;
+ int rc;
+
+ // First get current time stamp counter value, then read
+ // a high resolution time stamp from the board, plus the
+ // associated time stamp counter value.
+ mbg_get_pc_cycles( &cyc_now );
+
+ rc = mbg_get_fast_hr_timestamp_cycles( dh, &tc );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ mbg_init_pc_cycles_frequency( dh, &pc_cycles_frequency );
+ rc = mbg_comp_hr_latency( &tc.tstamp, &tc.cycles, &cyc_now, &pc_cycles_frequency, hns_latency );
+ *p = tc.tstamp;
+ }
+
+ return rc;
+
+} // mbg_get_fast_hr_timestamp_comp
+
+
+
+/*HDR*/
+/**
+ Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access.
+
+ This function does not return or evaluate a cycles count, so the latency
+ of the call can not be determined. However, depending on the timer hardware
+ used as cycles counter it may take quite some time to read the cycles count
+ on some hardware architectures, so this call can be used to yield lower
+ latencies, under the restriction to be unable to determine the exact latency.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp_cycles()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp( MBG_DEV_HANDLE dh,
+ PCPS_TIME_STAMP *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_FAST_HR_TIMESTAMP, p );
+ // native endianess, no need to swap bytes
+ return _mbgdevio_ret_val;
+ #else
+ // This is currently not supported by the target environment.
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+ #endif
+} // mbg_get_fast_hr_timestamp
+
+
+
+/*HDR*/
+/**
+ Check if a specific device is a GPS receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_is_gps, IOCTL_DEV_IS_GPS, p );
+
+} // mbg_dev_is_gps
+
+
+
+/*HDR*/
+/**
+ Check if a specific device is a DCF77 receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_is_dcf, IOCTL_DEV_IS_DCF, p );
+
+} // mbg_dev_is_dcf
+
+
+
+/*HDR*/
+/**
+ Check if a specific device is a MSF receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_is_msf, IOCTL_DEV_IS_MSF, p );
+
+} // mbg_dev_is_msf
+
+
+
+/*HDR*/
+/**
+ Check if a specific device is a WWVB receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_is_wwvb, IOCTL_DEV_IS_WWVB, p );
+
+} // mbg_dev_is_msf
+
+
+
+/*HDR*/
+/**
+ Check if a specific device is a long wave signal receiver, e.g. DCF77, MSF or WWVB.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_is_lwr, IOCTL_DEV_IS_LWR, p );
+
+} // mbg_dev_is_lwr
+
+
+
+/*HDR*/
+/**
+ Check if a specific device is an IRIG receiver which supports
+ configuration of the IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_rx_info()
+ @see mbg_set_irig_rx_settings()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_is_irig_rx, IOCTL_DEV_IS_IRIG_RX, p );
+
+} // mbg_dev_is_irig_rx
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the HR_TIME functions.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_hr_time, IOCTL_DEV_HAS_HR_TIME, p );
+
+} // mbg_dev_has_hr_time
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports configuration of antenna cable length.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_ant_cable_len()
+ @see mbg_set_gps_ant_cable_len()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_cab_len, IOCTL_DEV_HAS_CAB_LEN, p );
+
+} // mbg_dev_has_cab_len
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports timezone / daylight saving configuration
+ using the ::TZDL structure.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see mbg_dev_has_tz()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_tzdl, IOCTL_DEV_HAS_TZDL, p );
+
+} // mbg_dev_has_tzdl
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports timezone / daylight saving configuration
+ using the ::PCPS_TZDL structure.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_pcps_tzdl()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_dev_has_tz()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_pcps_tzdl, IOCTL_DEV_HAS_PCPS_TZDL, p );
+
+} // mbg_dev_has_pcps_tzdl
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports timezone configuration
+ using the ::PCPS_TZCODE type.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_tzcode()
+ @see mbg_set_tzcode()
+ @see mbg_dev_has_tz()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_tzcode, IOCTL_DEV_HAS_TZCODE, p );
+
+} // mbg_dev_has_tzcode
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports any kind of timezone configuration.
+ This can be used e.g. to check if a specifig dialog or menu has to
+ be displayed.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_dev_has_tzcode()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_tz, IOCTL_DEV_HAS_TZ, p );
+
+} // mbg_dev_has_tz
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Check if a specific device supports setting an event time, i.e.
+ configure a %UTC time when the clock shall generate an event.
+
+ <b>Note:</b> This is only supported by some special firmware.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_event_time()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_event_time, IOCTL_DEV_HAS_EVENT_TIME, p );
+
+} // mbg_dev_has_event_time
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the ::RECEIVER_INFO structure and related calls.
+ Older GPS devices may not support that structure.
+
+ The mbg_get_gps_receiver_info() call uses this call to decide whether a
+ ::RECEIVER_INFO can be read directly from a device, or whether a default
+ structure has to be set up using default values depending on the device type.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_receiver_info, IOCTL_DEV_HAS_RECEIVER_INFO, p );
+
+} // mbg_dev_has_receiver_info
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_clr_ucap_buff() call
+ used to clear a card's on-board time capture FIFO buffer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_clr_ucap_buff()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_can_clr_ucap_buff, IOCTL_DEV_CAN_CLR_UCAP_BUFF, p );
+
+} // mbg_dev_can_clr_ucap_buff
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_ucap_entries() and
+ mbg_get_ucap_event() calls.
+
+ If the card does not but it is a GPS card then the card provides
+ a time capture FIFO buffer and the obsolete mbg_get_gps_ucap()
+ call can be used to retrieve entries from the FIFO buffer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ @see mbg_clr_ucap_buff()
+ @see mbg_get_gps_ucap()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_ucap, IOCTL_DEV_HAS_UCAP, p );
+
+} // mbg_dev_has_ucap
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides an IRIG output which can
+ be configured.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_tx_info()
+ @see mbg_set_irig_tx_settings()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_irig_tx, IOCTL_DEV_HAS_IRIG_TX, p );
+
+} // mbg_dev_has_irig_tx
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Check if a specific device provides a serial output supporting
+ higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS
+ rather than ::DEFAULT_BAUD_RATES_DCF.
+
+ The mbg_get_serial_settings() takes care of this, so applications
+ which use that call as suggested won't need to use this call directly.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_serial_hs, IOCTL_DEV_HAS_SERIAL_HS, p );
+
+} // mbg_dev_has_serial_hs
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides an input signal level value which
+ may be displayed, e.g. DCF77 or IRIG cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_signal, IOCTL_DEV_HAS_SIGNAL, p );
+
+} // mbg_dev_has_signal
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides an modulation signal which may be
+ displayed, e.g. the second marks of a DCF77 AM receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_mod, IOCTL_DEV_HAS_MOD, p );
+
+} // mbg_dev_has_mod
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides either an IRIG input or output.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_irig, IOCTL_DEV_HAS_IRIG, p );
+
+} // mbg_dev_has_irig
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides a configurable ref time offset
+ required to convert the received time to %UTC.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ref_offs()
+ @see mbg_set_ref_offs()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_ref_offs, IOCTL_DEV_HAS_REF_OFFS, p );
+
+} // mbg_dev_has_ref_offs
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS
+ structures containing optional settings, controlled by flags.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_opt_info()
+ @see mbg_set_opt_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_opt_flags, IOCTL_DEV_HAS_OPT_FLAGS, p );
+
+} // mbg_dev_has_opt_flags
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports large configuration data structures
+ as have been introducesde with the GPS receivers.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_gps_data, IOCTL_DEV_HAS_GPS_DATA, p );
+
+} // mbg_dev_has_gps_data
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides a programmable frequency synthesizer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_synth()
+ @see mbg_set_synth()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_synth, IOCTL_DEV_HAS_SYNTH, p );
+
+} // mbg_dev_has_synth
+
+
+
+/*HDR*/
+/* (Intentionally excluded from Doxygen)
+ Check if a specific device supports the mbg_generic_io() call.
+
+ <b>Warning</b>: That call is for debugging purposes and internal use only!
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_io()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_generic_io, IOCTL_DEV_HAS_GENERIC_IO, p );
+
+} // mbg_dev_has_generic_io
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_asic_version() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_asic_version()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_asic_version, IOCTL_HAS_PCI_ASIC_VERSION, p );
+
+} // mbg_dev_has_asic_version
+
+
+
+/*HDR*/
+/**
+ Check if a specific device supports the mbg_get_asic_features() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_asic_features()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_asic_features, IOCTL_HAS_PCI_ASIC_FEATURES, p );
+
+} // mbg_dev_has_asic_features
+
+
+
+/*HDR*/
+/**
+ Read a ::POUT_INFO_IDX array of current settings and configuration
+ options of a card's programmable pulse outputs.
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out
+ field (i.e. the number of programmable outputs on the board) is not 0.
+
+ The array passed to this function to receive the returned data
+ must be able to hold at least ::RECEIVER_INFO::n_prg_out elements.
+
+ @param dh Valid handle to a Meinberg device.
+ @param pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pout_settings_idx()
+ @see mbg_set_gps_pout_settings()
+ @see mbg_setup_receiver_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh,
+ POUT_INFO_IDX pii[],
+ const RECEIVER_INFO *p_ri )
+{
+ _mbgdevio_vars();
+
+ #if _MBG_SUPP_VAR_ACC_SIZE
+ _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_POUT_INFO,
+ IOCTL_GET_GPS_ALL_POUT_INFO, pii,
+ p_ri->n_prg_out * sizeof( pii[0] ),
+ _pcps_ddev_has_receiver_info( dh ) );
+ #else
+ // We check the model_code to see whether the receiver info
+ // has been read from a device which really supports it, or
+ // a dummy structure has been setup.
+ if ( p_ri && ( p_ri->model_code != GPS_MODEL_UNKNOWN ) )
+ _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_POUT_INFO, pii,
+ p_ri->n_prg_out * sizeof( pii[0] ) );
+ else
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV );
+ #endif
+
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ if ( rc == MBG_SUCCESS )
+ {
+ int i;
+ for ( i = 0; i < p_ri->n_prg_out; i++ )
+ {
+ POUT_INFO_IDX *p = &pii[i];
+ _mbg_swab_pout_info_idx( p );
+ }
+ }
+ #endif
+
+ return _mbgdevio_ret_val;
+
+} // mbg_get_gps_all_pout_info
+
+
+
+/*HDR*/
+/**
+ Write the configuration for a single programmable pulse output using
+ the ::POUT_SETTINGS_IDX structure which contains both the ::POUT_SETTINGS
+ and the output index value.
+ Except for the parameter types, this call is equivalent to
+ mbg_set_gps_pout_settings().
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out field
+ (i.e. the number of programmable outputs on the board) is not 0, and the
+ output index value must be in the range 0..::RECEIVER_INFO::n_prg_out.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POUT_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_all_pout_info()
+ @see mbg_set_gps_pout_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh,
+ const POUT_SETTINGS_IDX *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ POUT_SETTINGS_IDX tmp = *p;
+ _mbg_swab_pout_settings_idx( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_POUT_SETTINGS_IDX,
+ IOCTL_SET_GPS_POUT_SETTINGS_IDX, p,
+ _pcps_ddev_has_receiver_info( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_gps_pout_settings_idx
+
+
+
+/*HDR*/
+/**
+ Write the configuration for a single programmable pulse output using
+ the ::POUT_SETTINGS structure plus the index of the output to be configured.
+ Except for the parameter types, this call is equivalent to
+ mbg_set_gps_pout_settings_idx().
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out field
+ (i.e. the number of programmable outputs on the board) is not 0, and the
+ output index value must be in the range 0..::RECEIVER_INFO::n_prg_out.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POUT_SETTINGS structure to be written
+ @param idx Index of the programmable pulse output to be configured (starting from 0 ).
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_all_pout_info()
+ @see mbg_set_gps_pout_settings_idx()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh,
+ const POUT_SETTINGS *p, int idx )
+{
+ POUT_SETTINGS_IDX psi = { 0 };
+
+ psi.idx = idx;
+ psi.pout_settings = *p;
+
+ return mbg_set_gps_pout_settings_idx( dh, &psi );
+
+} // mbg_set_gps_pout_settings
+
+
+
+/*HDR*/
+/**
+ Read a card's IRQ status information which includes flags indicating
+ whether IRQs are currently enabled, and whether IRQ support by a card
+ is possibly unsafe due to the firmware and interface chip version.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_STAT_INFO *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_IRQ_STAT_INFO, p );
+ // native endianess, no need to swap bytes
+ return _mbgdevio_ret_val;
+ #else
+ *p = dh->irq_stat_info;
+ return MBG_SUCCESS;
+ #endif
+
+} // mbg_get_irq_stat_info
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides simple LAN interface API calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_state()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_lan_intf, IOCTL_DEV_HAS_LAN_INTF, p );
+
+} // mbg_dev_has_lan_intf
+
+
+
+/*HDR*/
+/**
+ Read LAN interface information from a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::LAN_IF_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_ip4_state()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_LAN_IF_INFO,
+ IOCTL_GET_LAN_IF_INFO, p,
+ _pcps_ddev_has_lan_intf( dh ) );
+ _mbg_swab_lan_if_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_lan_if_info
+
+
+
+/*HDR*/
+/**
+ Read LAN IPv4 state from a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IP4_SETTINGS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_IP4_STATE,
+ IOCTL_GET_IP4_STATE, p,
+ _pcps_ddev_has_lan_intf( dh ) );
+ _mbg_swab_ip4_settings( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ip4_state
+
+
+
+/*HDR*/
+/**
+ Read LAN IPv4 settings from a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IP4_SETTINGS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_state()
+ @see mbg_set_ip4_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_IP4_SETTINGS,
+ IOCTL_GET_IP4_SETTINGS, p,
+ _pcps_ddev_has_lan_intf( dh ) );
+ _mbg_swab_ip4_settings( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ip4_settings
+
+
+
+/*HDR*/
+/**
+ Write LAN IPv4 settings to a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::IP4_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh,
+ const IP4_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ IP4_SETTINGS tmp = *p;
+ _mbg_swab_ip4_settings( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_IP4_SETTINGS,
+ IOCTL_SET_IP4_SETTINGS, p,
+ _pcps_ddev_has_lan_intf( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_ip4_settings
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides PTP configuration/status calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_set_ptp_cfg_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_cond( dh, _pcps_ddev_has_ptp, IOCTL_DEV_HAS_PTP, p );
+
+} // mbg_dev_has_ptp
+
+
+
+/*HDR*/
+/**
+ Check if a specific device provides PTP Unicast feature/configuration.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_unicast_cfg_info()
+ @see mbg_set_ptp_unicast_cfg_settings()
+*/
+_MBG_API_ATTR int _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p )
+{
+ _mbgdevio_query_ri_cond( dh, _pcps_has_ri_ptp_unicast, IOCTL_DEV_HAS_PTP_UNICAST, p );
+
+} // mbg_dev_has_ptp_unicast
+
+
+
+/*HDR*/
+/**
+ Read PTP/IEEE1588 status from a card which supports this.
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_set_ptp_cfg_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_PTP_STATE,
+ IOCTL_GET_PTP_STATE, p,
+ _pcps_ddev_has_ptp( dh ) );
+ _mbg_swab_ptp_state( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ptp_state
+
+
+
+/*HDR*/
+/**
+ Read PTP/IEEE1588 config info and current settings from a card which supports this.
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp()
+ @see mbg_get_ptp_state()
+ @see mbg_set_ptp_cfg_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_PTP_CFG,
+ IOCTL_GET_PTP_CFG_INFO, p,
+ _pcps_ddev_has_ptp( dh ) );
+ _mbg_swab_ptp_cfg_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ptp_cfg_info
+
+
+
+/*HDR*/
+/**
+ Write PTP/IEEE1588 configuration settings to a card which supports this.
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::PTP_CFG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp()
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_cfg_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh,
+ const PTP_CFG_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ PTP_CFG_SETTINGS tmp = *p;
+ _mbg_swab_ptp_cfg_settings( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_PTP_CFG,
+ IOCTL_SET_PTP_CFG_SETTINGS, p,
+ _pcps_ddev_has_ptp( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_ptp_cfg_settings
+
+
+
+/*HDR*/
+/**
+ Read PTP/IEEE1588 unicast config info and current settings from a card which supports this.
+ The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_UNICAST_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast()
+ @see mbg_set_ptp_unicast_cfg_settings()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_ptp_unicast_cfg_info( MBG_DEV_HANDLE dh, PTP_UNICAST_CFG_INFO *p )
+{
+ _mbgdevio_vars();
+ _mbgdevio_read_gps_var_chk( dh, PC_GPS_PTP_UNICAST_CFG,
+ IOCTL_GET_PTP_UNICAST_CFG_INFO, p,
+ _pcps_has_ri_ptp_unicast( &dh->ri ) );
+ _mbg_swab_ptp_unicast_cfg_info( p );
+ return _mbgdevio_ret_val;
+
+} // mbg_get_ptp_unicast_cfg_info
+
+
+
+/*HDR*/
+/**
+ Write PTP/IEEE1588 unicast configuration settings to a card which supports this.
+ The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::PTP_UNICAST_CFG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast()
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_get_ptp_unicast_cfg_info()
+*/
+_MBG_API_ATTR int _MBG_API mbg_set_ptp_unicast_cfg_settings( MBG_DEV_HANDLE dh,
+ const PTP_UNICAST_CFG_SETTINGS *p )
+{
+ _mbgdevio_vars();
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ PTP_UNICAST_CFG_SETTINGS tmp = *p;
+ _mbg_swab_ptp_unicast_cfg_settings( &tmp );
+ p = &tmp;
+ #endif
+ _mbgdevio_write_gps_var_chk( dh, PC_GPS_PTP_UNICAST_CFG,
+ IOCTL_SET_PTP_UNICAST_CFG_SETTINGS, p,
+ _pcps_ddev_has_ptp_unicast( dh ) );
+ return _mbgdevio_ret_val;
+
+} // mbg_set_ptp_unicast_cfg_settings
+
+
+
+/*HDR*/
+/**
+ Read system time and card time from the kernel driver. The kernel
+ driver reads the current system time plus a HR time structure from
+ a card immediately after each other. The returned info structure also
+ contains some cycles counts to be able to determine the execution times
+ required to read those time stamps.
+
+ The advantage of this call compared to mbg_get_time_info_tstamp() is
+ that this call also returns the card's status. On the other hand, reading
+ the HR time from the card may block e.g. if another application accesses
+ the board.
+
+ This call makes a mbg_get_hr_time_cycles() call internally so the macro
+ _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() can be
+ used to check whether this call is supported with a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_INFO_HRT variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_hr_time()
+ @see mbg_get_time_info_tstamp()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_INFO_HRT *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, -1, IOCTL_GET_TIME_INFO_HRT, p,
+ _pcps_ddev_has_hr_time( dh ) );
+ _mbg_swab_mbg_time_info_hrt( p );
+ return _mbgdevio_ret_val;
+ #else
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+ #endif
+
+} // mbg_get_time_info_hrt
+
+
+
+/*HDR*/
+/**
+ This call is similar to mbg_get_time_info_hrt() except that a
+ mbg_get_fast_hr_timestamp_cycles() call is made internally, so the macro
+ _pcps_has_fast_hr_timestamp() or the API call mbg_dev_has_fast_hr_timestamp()
+ can be used to check whether this call is supported with a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_INFO_TSTAMP variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_time_info_hrt()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME_INFO_TSTAMP *p )
+{
+ #if defined( _MBGIOCTL_H )
+ _mbgdevio_vars();
+ _mbgdevio_read_var_chk( dh, -1, IOCTL_GET_TIME_INFO_TSTAMP, p,
+ _pcps_ddev_has_fast_hr_timestamp( dh ) );
+ _mbg_swab_mbg_time_info_tstamp( p );
+ return _mbgdevio_ret_val;
+ #else
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+ #endif
+
+} // mbg_get_time_info_tstamp
+
+
+
+/*HDR*/
+/**
+ Read the CPU affinity of a process, i.e. on which of the available
+ CPUs the process can be executed.
+
+ @param pid The process ID.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_set_process_affinity()
+ @see mbg_set_current_process_affinity_to_cpu()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p )
+{
+ #if defined( MBG_TGT_LINUX )
+
+ return sched_getaffinity( pid, sizeof( *p ), p );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ MBG_CPU_SET system_affinity_mask = 0;
+
+ return GetProcessAffinityMask( pid, p, &system_affinity_mask ) ? 0 : -1;
+
+ #else
+
+ return -1;
+
+ #endif
+
+} // mbg_get_process_affinity
+
+
+
+/*HDR*/
+/**
+ Set the CPU affinity of a process, i.e. on which of the available
+ CPUs the process is allowed to be executed.
+
+ @param pid The process ID.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_get_process_affinity()
+ @see mbg_set_current_process_affinity_to_cpu()
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p )
+{
+ #if defined( MBG_TGT_LINUX )
+
+ return sched_setaffinity( pid, sizeof( *p ), p );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ return SetProcessAffinityMask( pid, *p ) ? 0 : -1;
+
+ #else
+
+ return -1;
+
+ #endif
+
+} // mbg_set_process_affinity
+
+
+
+/*HDR*/
+/**
+ Set the CPU affinity of a process for a single CPU only, i.e. the process
+ may only be executed on that single CPU.
+
+ @param cpu_num The number of the CPU.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_get_process_affinity()
+ @see mbg_set_process_affinity()
+ */
+_MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num )
+{
+ MBG_CPU_SET cpu_set;
+
+ _mbg_cpu_clear( &cpu_set );
+ _mbg_cpu_set( cpu_num, &cpu_set );
+
+ return mbg_set_process_affinity( _mbg_get_current_process(), &cpu_set );
+
+} // mbg_set_current_process_affinity_to_cpu
+
+
+
+#if MBGDEVIO_USE_THREAD_API
+
+/*HDR*/
+/**
+ Create a new execution thread for the current process.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up.
+ @param fnc The name of the thread function to be started.
+ @param arg A generic argument passed to the thread function.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_stop()
+ @see mbg_thread_sleep_interruptible()
+ @see mbg_thread_set_affinity()
+ */
+_MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti,
+ MBG_THREAD_FNC_RET_VAL (MBG_THREAD_FNC_ATTR *fnc)(void *), void *arg )
+{
+ #if defined( MBG_TGT_LINUX )
+
+ return pthread_create( &p_ti->thread_id, NULL, fnc, arg );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ HANDLE h;
+ DWORD thread_id = 0;
+
+ p_ti->exit_request = CreateEvent( NULL, FALSE, FALSE, NULL );
+
+ if ( p_ti->exit_request == NULL )
+ goto fail;
+
+ h = CreateThread( NULL, 0, fnc, arg, 0, &thread_id );
+
+ if ( h == NULL )
+ {
+ CloseHandle( p_ti->exit_request );
+ goto fail;
+ }
+
+ p_ti->thread_id = h;
+
+ return 0;
+
+fail:
+ return GetLastError();
+
+ #else
+
+ return -1;
+
+ #endif
+
+} // mbg_thread_create
+
+
+
+/*HDR*/
+/**
+ Stop a thread which has been created by mbg_thread_create(). Wait
+ until the thread has finished and release all resources.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_create()
+ @see mbg_thread_sleep_interruptible()
+ @see mbg_thread_set_affinity()
+ */
+_MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti )
+{
+ #if defined( MBG_TGT_LINUX )
+
+ pthread_cancel( p_ti->thread_id );
+
+ return pthread_join( p_ti->thread_id, NULL );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ if ( SetEvent( p_ti->exit_request ) &&
+ WaitForSingleObject( p_ti->thread_id, 10000L ) == 0 )
+ {
+ CloseHandle( p_ti->exit_request );
+ p_ti->exit_request = NULL;
+
+ CloseHandle( p_ti->thread_id );
+ p_ti->thread_id = NULL;
+
+ return 0;
+ }
+
+ return GetLastError();
+
+ #else
+
+ return -1;
+
+ #endif
+
+} // mbg_thread_stop
+
+
+
+/*HDR*/
+/**
+ Let the current thread sleep for a certain interval unless a signal is
+ received indicating the thread should terminate.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+ @param sleep_ms The number of milliseconds to sleep
+ @return 0 if the sleep interval has expired normally
+ 1 if a signal to terminate has been received
+ <0 if an error has occurred
+
+ @see mbg_thread_create()
+ @see mbg_thread_stop()
+ @see mbg_thread_set_affinity()
+ */
+_MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti, ulong sleep_ms )
+{
+ #if defined( MBG_TGT_LINUX )
+
+ usleep( sleep_ms * 1000 );
+ return 0;
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ DWORD dw = WaitForSingleObject( p_ti->exit_request, sleep_ms );
+
+ switch ( dw )
+ {
+ case WAIT_OBJECT_0: // has been interrupted to terminate
+ return 1;
+
+ case WAIT_TIMEOUT: // sleep interval expired without interruption
+ return 0;
+ }
+
+ return -1;
+
+ #else
+
+ return -1;
+
+ #endif
+
+} // mbg_thread_sleep_interruptible
+
+
+
+#if MBGDEVIO_HAVE_THREAD_AFFINITY
+
+/*HDR*/
+/**
+ Set the CPU affinity of a single thread, i.e. on which of the available
+ CPUs the thread is allowed to be executed.
+ This function is only implemented for targets which support thread affinity.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_create()
+ @see mbg_thread_stop()
+ @see mbg_thread_sleep_interruptible()
+ */
+_MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_CPU_SET *p )
+{
+ #if defined( MBG_TGT_LINUX )
+
+ return pthread_setaffinity_np( tid, sizeof( *p ), p );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ MBG_CPU_SET prv_thread_affinity = SetThreadAffinityMask( p_ti->thread_id, *p );
+
+ return prv_thread_affinity ? 0 : -1;
+
+ #else
+
+ return -1;
+
+ #endif
+
+} // mbg_thread_set_affinity
+
+#endif
+
+
+
+static /*HDR*/
+/**
+ A thread function which implements polling of a device at a regular interval.
+ At each polling a high resolution time stamp and an associated cycles count
+ are saved which can be used to retrieve extrapolated time stamps using the
+ cycles counter. The thread also computes the frequency of the system's cycles
+ counter.
+ On systems where the cycles counter is implemented by a CPU's time stamp
+ counter (TSC) it maybe required to set the thread or process affinity to a
+ single CPU to get reliable cycles counts. In this case also care should be
+ taken that the CPU's clock frequency is not stepped up and down e.g. due
+ to power saving mechanisms (e.g. Intel SpeedStep, or AMD Cool'n'Quiet).
+ Otherwise time interpolation may be messed up.
+ This function is only implemented for targets which support threads.
+
+ @param *p_void Pointer to a ::MBG_POLL_THREAD_INFO structure.
+
+ @return ::MBG_SUCCESS or nothing, depending on the taget system.
+
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+MBG_THREAD_FNC_RET_VAL MBG_THREAD_FNC_ATTR mbg_xhrt_poll_thread_fnc( void *p_void )
+{
+ MBG_XHRT_VARS prv_xhrt_vars;
+
+ MBG_POLL_THREAD_INFO *p_pti = (MBG_POLL_THREAD_INFO *) p_void;
+ MBG_XHRT_INFO *p = &p_pti->xhrt_info;
+
+ memset( &prv_xhrt_vars, 0, sizeof( prv_xhrt_vars ) );
+
+ for (;;)
+ {
+ MBG_XHRT_VARS xhrt_vars;
+ MBG_PC_CYCLES_FREQUENCY freq = 0;
+ int sleep_ms;
+
+ int rc = mbg_get_hr_time_cycles( p->dh, &xhrt_vars.htc );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ xhrt_vars.pcps_hr_tstamp64 = pcps_time_stamp_to_uint64( &xhrt_vars.htc.t.tstamp );
+
+ if ( prv_xhrt_vars.pcps_hr_tstamp64 && ( ( xhrt_vars.htc.t.status & PCPS_LS_ENB ) == 0 ) )
+ freq = ( mbg_delta_pc_cycles( &xhrt_vars.htc.cycles, &prv_xhrt_vars.htc.cycles ) * PCPS_HRT_BIN_FRAC_SCALE )
+ / ( xhrt_vars.pcps_hr_tstamp64 - prv_xhrt_vars.pcps_hr_tstamp64 );
+ }
+
+
+ _mbg_mutex_lock( &p->mutex );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ p->vars = xhrt_vars;
+ p->prv_vars = prv_xhrt_vars;
+
+ if ( freq )
+ p->freq_hz = freq;
+ }
+
+ p->ioctl_status = rc;
+
+ sleep_ms = p->sleep_ms;
+
+ _mbg_mutex_unlock( &p->mutex );
+
+
+ if ( rc == MBG_SUCCESS )
+ prv_xhrt_vars = xhrt_vars;
+
+ if ( mbg_thread_sleep_interruptible( &p_pti->ti, sleep_ms ) )
+ break;
+ }
+
+ _mbg_thread_exit( 0 );
+
+} // mbg_xhrt_poll_thread_fnc
+
+
+
+/*HDR*/
+/**
+ Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread
+ which runs the mbg_xhrt_poll_thread_fnc() function.
+ This function is only implemented for targets which support threads.
+
+ @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure.
+ @param dh the handle of the device to be polled.
+ @param freq_hz The initial cycles frequency, if known, in Hz.
+ @param sleep_ms the sleep interval for the poll thread function in ms.
+ If this parameter is 0 then the default sleep interval is used.
+
+ @return ::MBG_SUCCESS on success,
+ ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time
+ else the result of mbg_thread_create()
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+_MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_pti, MBG_DEV_HANDLE dh,
+ MBG_PC_CYCLES_FREQUENCY freq_hz, int sleep_ms )
+{
+ int has_hr_time;
+ int rc = mbg_dev_has_hr_time( dh, &has_hr_time );
+
+ if ( ( rc != MBG_SUCCESS ) || !has_hr_time )
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV );
+
+ memset( p_pti, 0, sizeof( *p_pti ) );
+
+ p_pti->xhrt_info.dh = dh;
+ p_pti->xhrt_info.freq_hz = freq_hz;
+ p_pti->xhrt_info.sleep_ms = sleep_ms ? sleep_ms : 1000; // sleep 1 second by default
+ _mbg_mutex_init( &p_pti->xhrt_info.mutex );
+
+ rc = mbg_thread_create( &p_pti->ti, mbg_xhrt_poll_thread_fnc, p_pti );
+
+ return rc;
+
+} // mbg_xhrt_poll_thread_create
+
+
+
+/*HDR*/
+/**
+ Stop a polling thread started by mbg_xhrt_poll_thread_create()
+ and release all associated resources.
+
+ @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure.
+
+ @return the result of mbg_thread_stop()
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+_MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pti )
+{
+ int rc = mbg_thread_stop( &p_pti->ti );
+
+ if ( rc == MBG_SUCCESS )
+ _mbg_mutex_deinit( &p_pti->xhrt_info.mutex );
+
+ return rc;
+
+} // mbg_xhrt_poll_thread_stop
+
+
+
+static /*HDR*/
+int mbg_get_xhrt_data( MBG_XHRT_INFO *p, uint64_t *tstamp, MBG_XHRT_VARS *vars )
+{
+ MBG_XHRT_VARS xhrt_vars;
+ MBG_PC_CYCLES cyc_now;
+ uint64_t t_now = 0;
+ MBG_PC_CYCLES_FREQUENCY freq_hz;
+ int ioctl_status;
+
+ mbg_get_pc_cycles( &cyc_now );
+
+ _mbg_mutex_lock( &p->mutex );
+ xhrt_vars = p->vars;
+ freq_hz = p->freq_hz;
+ ioctl_status = p->ioctl_status;
+ _mbg_mutex_unlock( &p->mutex );
+
+ if ( freq_hz && xhrt_vars.pcps_hr_tstamp64 )
+ {
+ t_now = xhrt_vars.pcps_hr_tstamp64 +
+ ( mbg_delta_pc_cycles( &cyc_now, &xhrt_vars.htc.cycles ) * PCPS_HRT_BIN_FRAC_SCALE ) / freq_hz;
+ mbg_chk_tstamp64_leap_sec( &t_now, &xhrt_vars.htc.t.status );
+ }
+
+ if ( tstamp )
+ *tstamp = t_now;
+
+ if ( vars )
+ *vars = xhrt_vars;
+
+ return ioctl_status;
+
+} // mbg_get_xhrt_data
+
+
+
+/*HDR*/
+/**
+ Retrieve a time stamp in PCPS_HR_TIME format which is extrapolated
+ using the system's current cycles counter value and a time stamp
+ plus associated cycles counter value saved by the polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+ This function is only implemented for targets which support threads.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up.
+
+ @return MBG_SUCCESS or another return value from the polling thread's IOCTL call.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, PCPS_HR_TIME *p_hrt )
+{
+ uint64_t tstamp64;
+ MBG_XHRT_VARS xhrt_vars;
+
+ int rc = mbg_get_xhrt_data( p, &tstamp64, &xhrt_vars );
+
+ // Even if an IOCTL error has occurred recently in the polling thread
+ // the interpolation may still work correctly. So we just continue
+ // normally but pass the return code on to the calling function.
+
+ uint64_to_pcps_time_stamp( &p_hrt->tstamp, tstamp64 );
+
+ // Update status (valid only for the previous second!)
+ p_hrt->signal = xhrt_vars.htc.t.signal;
+ p_hrt->status = xhrt_vars.htc.t.status;
+ p_hrt->utc_offs = xhrt_vars.htc.t.utc_offs;
+
+ return rc;
+
+} // mbg_get_xhrt_time_as_pcps_hr_time
+
+
+
+#if defined( MBG_TGT_WIN32 )
+
+/*HDR*/
+/**
+ Retrieve a time stamp in FILETIME format which is extrapolated
+ using the system's current cycles counter value and a time stamp
+ plus associated cycles counter value saved by the polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+ Since FILETIME is a Windows specific type this function is only
+ implemented under Windows.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_ft Pointer to a ::FILETIME structure to be filled up.
+
+ @return MBG_SUCCESS or another return value from the polling thread's IOCTL call.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILETIME *p_ft )
+{
+ uint64_t tstamp64;
+
+ int rc = mbg_get_xhrt_data( p, &tstamp64, NULL );
+
+ // Even if an IOCTL error has occurred recently in the polling thread
+ // the interpolation may still work correctly. So we just continue
+ // normally but pass the return code on to the calling function.
+
+ mbg_pcps_tstamp64_to_filetime( p_ft, &tstamp64 );
+
+ return rc;
+
+} // mbg_get_xhrt_time_as_filetime
+
+#endif
+
+
+
+/*HDR*/
+/**
+ Retrieve the frequency of the system's cycles counter as determined
+ by the device polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+ This function is only implemented for targets which support threads.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned.
+ @return a status code from the polling thread: MBG_SUCCESS or an IOCTL error code.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_PC_CYCLES_FREQUENCY *p_freq_hz )
+{
+ MBG_PC_CYCLES_FREQUENCY freq_hz;
+ int ioctl_status;
+
+ _mbg_mutex_lock( &p->mutex );
+ freq_hz = p->freq_hz;
+ ioctl_status = p->ioctl_status;
+ _mbg_mutex_unlock( &p->mutex );
+
+ if ( p_freq_hz )
+ *p_freq_hz = freq_hz;
+
+ return ioctl_status;
+
+} // mbg_get_xhrt_cycles_frequency
+
+#endif // defined MBGDEVIO_USE_THREAD_API
+
+
+
+/*HDR*/
+/**
+ Retrieve the default system's cycles counter frequency from the kernel driver.
+
+ @param dh handle of the device to which the IOCTL call is sent.
+ @param *p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_default_cycles_frequency()
+ */
+_MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p )
+{
+ #if defined( _MBGIOCTL_H ) && defined( MBG_PC_CYCLES_SUPPORTED )
+ _mbgdevio_vars();
+ _mbgdevio_read_var( dh, -1, IOCTL_GET_CYCLES_FREQUENCY, p );
+ // native endianess, no need to swap bytes
+ if ( rc != MBG_SUCCESS )
+ *p = 0;
+
+ #if defined( MBG_TGT_LINUX )
+ if ( *p == 0 )
+ {
+ int has_hr_time = 0;
+
+ rc = mbg_dev_has_hr_time( dh, &has_hr_time );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+ if ( ( rc == MBG_SUCCESS ) && has_hr_time )
+ {
+ PCPS_HR_TIME_CYCLES htc1;
+ PCPS_HR_TIME_CYCLES htc2;
+ double delta_cycles;
+ double delta_t;
+
+ rc = mbg_get_hr_time_cycles( dh, &htc1 );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+ sleep( 1 );
+
+ rc = mbg_get_hr_time_cycles( dh, &htc2 );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+ // compute cycles frequency from delta htc
+ delta_cycles = mbg_delta_pc_cycles( &htc2.cycles, &htc1.cycles );
+ delta_t = pcps_time_stamp_to_uint64( &htc2.t.tstamp ) - pcps_time_stamp_to_uint64( &htc1.t.tstamp );
+ *p = ( delta_cycles * PCPS_HRT_BIN_FRAC_SCALE ) / delta_t;
+ }
+ }
+done:
+ #endif
+
+ return _mbgdevio_ret_val;
+
+ #else
+
+ *p = 0;
+
+ return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS );
+
+ #endif
+
+} // mbg_get_default_cycles_frequency_from_dev
+
+
+
+/*HDR*/
+/**
+ Retrieve the default system's cycles counter frequency.
+
+ @note This may not be supported on all target platforms, in which case the
+ returned frequency is 0 and the mbg_get_default_cycles_frequency_from_dev()
+ call should be used.
+
+ @return the default cycles counter frequency in Hz, or 0 if the value is not available.
+
+ @see mbg_get_default_cycles_frequency_from_dev()
+*/
+_MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void )
+{
+ #if defined MBG_TGT_WIN32
+
+ MBG_PC_CYCLES_FREQUENCY pc_cycles_frequency;
+
+ mbg_get_pc_cycles_frequency( &pc_cycles_frequency );
+
+ return pc_cycles_frequency;
+
+ #else
+
+ return 0;
+
+ #endif
+
+} // mbg_get_default_cycles_frequency
+
+
+
+#if defined( MBG_TGT_WIN32 )
+
+#if defined( _USRDLL )
+
+BOOL APIENTRY DllMain( HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved )
+{
+ if ( ul_reason_for_call == DLL_PROCESS_ATTACH )
+ mbg_svc_register_event_source( MBG_APP_EVTLOG_NAME_MBGDEVIO_DLL );
+
+ return TRUE;
+}
+
+#endif // defined( _USRDLL )
+
+#endif // defined( MBG_TGT_WIN32 )
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h
new file mode 100755
index 0000000..d1910e7
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h
@@ -0,0 +1,3157 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgdevio.h 1.39.1.13 2011/02/15 14:26:22 martin TRASH martin(2011.02.16.09.52.26) $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes used with Meinberg device driver I/O.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgdevio.h $
+ * Revision 1.39.1.13 2011/02/15 14:26:22 martin
+ * Revision 1.39.1.12 2011/02/15 11:22:29 daniel
+ * Updated function prototypes to support PTP unicast configuration
+ * Revision 1.39.1.11 2011/02/02 12:21:39Z martin
+ * Fixed a type.
+ * Revision 1.39.1.10 2011/01/28 09:33:45 martin
+ * Cosmetics.
+ * Revision 1.39.1.9 2010/12/14 11:23:49 martin
+ * Moved definition of MBG_HW_NAME to the header file.
+ * Revision 1.39.1.8 2010/12/14 10:56:35Z martin
+ * Revision 1.39.1.7 2010/08/11 13:48:53 martin
+ * Cleaned up comments.
+ * Revision 1.39.1.6 2010/08/11 12:43:52 martin
+ * Revision 1.39.1.5 2010/07/15 08:40:57 martin
+ * Revision 1.39.1.4 2010/01/08 15:04:17Z martin
+ * Revision 1.39.1.3 2010/01/08 11:24:02Z martin
+ * Compute and check time of day only if any leap second status bit set.
+ * Revision 1.39.1.2 2010/01/08 11:13:57Z martin
+ * Made xhrt leap second check an inline function.
+ * Revision 1.39.1.1 2010/01/07 15:49:37Z martin
+ * Fixed macro to avoid compiler warning.
+ * Revision 1.39 2009/12/15 15:34:59Z daniel
+ * Support reading the raw IRIG data bits for firmware versions
+ * which support this feature.
+ * Revision 1.38.1.2 2009/12/10 09:58:53Z daniel
+ * Revision 1.38.1.1 2009/12/10 09:45:29Z daniel
+ * Revision 1.38 2009/09/29 15:06:26Z martin
+ * Updated function prototypes.
+ * Revision 1.37 2009/08/12 14:31:51 daniel
+ * New version code 306, compatibility version still 210.
+ * Revision 1.36 2009/06/19 12:20:31Z martin
+ * Updated function prototypes.
+ * Revision 1.35 2009/06/09 08:57:09 daniel
+ * New version code 305, compatibility version still 210.
+ * Revision 1.34 2009/06/08 18:20:14Z daniel
+ * Updated function prototypes.
+ * Fixes for ARM target.
+ * Revision 1.33 2009/03/19 15:36:26 martin
+ * New version code 304, compatibility version still 210.
+ * Moved some inline functions dealing with MBG_PC_CYCLES
+ * from mbgdevio.h to pcpsdev.h.
+ * Include mbg_arch.h here.
+ * Removed unused doxygen comment.
+ * Updated function prototypes.
+ * Revision 1.32 2008/12/17 10:43:30Z martin
+ * New version code 303, compatibility version still 210.
+ * Increased MBG_MAX_DEVICES from 5 to 8.
+ * Added macros to read the time stamp counter (cycles), and
+ * added an inline rdtscll() call for user space Linux.
+ * Added some inline functions to deal with cycles and timestamps.
+ * Generic support for threads and process/thread affinity controlled
+ * by symbol MBGDEVIO_USE_THREAD_API.
+ * New preprocessor symbol MBGDEVIO_HAVE_THREAD_AFFINITY.
+ * Support extrapolated time stamps controlled
+ * by symbol MBGDEVIO_XHRT_API.
+ * Removed definition of MBG_TGT_SUPP_MMAP.
+ * Updated function prototypes and doxygen comments.
+ * Revision 1.31 2008/02/26 16:57:38Z martin
+ * Updated function prototypes and doxygen comments.
+ * Revision 1.30 2008/02/04 13:33:15Z martin
+ * New preprocessor symbol MBG_TGT_SUPP_MMAP.
+ * Revision 1.29 2008/01/31 08:55:39Z daniel
+ * Renamed functions related to mapped memory support
+ * Revision 1.28 2008/01/31 08:36:22Z martin
+ * Picked up changes from 1.24.1.1:
+ * Added default preprocessor symbol MBGDEVIO_SIMPLE.
+ * Revision 1.27 2008/01/17 15:56:37Z daniel
+ * New version code 302, compatibility version still 210.
+ * Added structure MBG_MAPPED_MEM_INFO.
+ * Updated function prototypes.
+ * Revision 1.26 2007/10/16 10:11:42Z daniel
+ * New version code 301, compatibility version still 210.
+ * Revision 1.25 2007/09/26 14:10:34Z martin
+ * New version code 300, compatibility version still 210.
+ * Added MBG_MAX_DEVICES.
+ * Added enum SELECTION_MODE.
+ * Added structures MBG_DEVICE_LIST and MBG_DEVICE_NAME_LIST.
+ * Updated function prototypes.
+ * Revision 1.24 2007/03/22 10:14:16Z martin
+ * New version code 219, compatibility version still 210.
+ * Revision 1.23 2007/03/02 10:18:10Z martin
+ * Updated function prototypes due to renamed data structures.
+ * Use new definitions of generic handle types.
+ * Preliminary support for *BSD.
+ * Revision 1.22 2006/08/09 13:47:29 martin
+ * New version code 218, compatibility version still 210.
+ * Revision 1.21 2006/06/08 12:30:22Z martin
+ * New version code 217, compatibility version still 210.
+ * Revision 1.20 2006/05/02 13:14:27Z martin
+ * New version code 216, compatibility version still 210.
+ * Updated function prototypes.
+ * Revision 1.19 2006/01/11 12:14:53Z martin
+ * New version code 215, compatibility version still 210.
+ * Revision 1.18 2005/12/15 09:38:39Z martin
+ * New version 214, compatibility version still 210.
+ * Revision 1.17 2005/06/02 11:54:40Z martin
+ * Updated function prototypes.
+ * Revision 1.16 2005/02/16 15:13:00Z martin
+ * New MBGDEVIO_VERSION 0x0212.
+ * Updated function prototypes.
+ * Revision 1.15 2005/01/14 10:22:44Z martin
+ * Updated function prototypes.
+ * Revision 1.14 2004/12/09 11:24:00Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.13 2004/11/09 14:13:00Z martin
+ * Updated function prototypes.
+ * Revision 1.12 2004/08/17 11:13:46Z martin
+ * Account for renamed symbols.
+ * Revision 1.11 2004/04/14 09:34:23Z martin
+ * New definition MBGDEVIO_COMPAT_VERSION.
+ * Pack structures 1 byte aligned.
+ * Revision 1.10 2003/12/22 15:35:10Z martin
+ * New revision 2.03.
+ * Moved some definitions to pcpsdev.h.
+ * New structures to read device time together with associated
+ * PC high resolution timer cycles.
+ * Updated function prototypes.
+ * Revision 1.9 2003/06/19 08:50:05Z martin
+ * Definition of MBGDEVIO_VERSION number to allow DLL
+ * API version checking.
+ * Replaced some defines by typedefs.
+ * Renamed USE_DOS_TSR to MBG_USE_DOS_TSR.
+ * New preprocessor symbol MBG_USE_KERNEL_DRIVER which
+ * is defined only for targets which use IOCTLs.
+ * Don't include pcps_dos.h here.
+ * Updated function prototypes.
+ * Revision 1.8 2003/05/16 08:44:26 MARTIN
+ * Cleaned up inclusion of headers.
+ * Removed obsolete definitions.
+ * Changes for direct access targets.
+ * Revision 1.7 2003/04/25 10:16:00 martin
+ * Updated inclusion of headers.
+ * Made prototypes available for all targets.
+ * Revision 1.6 2003/04/15 19:38:05Z martin
+ * Updated function prototypes.
+ * Revision 1.5 2003/04/09 13:44:53Z martin
+ * Use new common IOCTL codes from mbgioctl.h.
+ * Updated function prototypes.
+ * Revision 1.4 2002/09/06 11:06:35Z martin
+ * Updated function prototypes for Win32 API..
+ * Win32 compatibility macros to use old APIs with new functions.
+ * Support targets OS/2 and NetWare.
+ * Revision 1.3 2002/02/28 10:08:54Z MARTIN
+ * Syntax cleanup for Win32.
+ * Revision 1.2 2002/02/26 14:40:47 MARTIN
+ * Source code cleanup.
+ * Changes for DOS with and without TSR.
+ * Revision 1.1 2002/02/19 13:48:21 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBGDEVIO_H
+#define _MBGDEVIO_H
+
+
+/* Other headers to be included */
+
+#include <mbggeo.h>
+#include <mbg_tgt.h>
+#include <mbg_arch.h>
+#include <mbgerror.h>
+#include <pcpsdev.h>
+#include <pcpsutil.h>
+#include <pci_asic.h>
+#include <use_pack.h>
+#include <time.h>
+
+
+#define MBGDEVIO_VERSION 0x0307
+
+#define MBGDEVIO_COMPAT_VERSION 0x0210
+
+#define MBG_MAX_DEVICES 8
+
+#if defined( MBG_TGT_WIN32 )
+
+ #if !defined( MBGDEVIO_XHRT_API )
+ #define MBGDEVIO_XHRT_API 1
+ #endif
+
+ #if !defined( MBGDEVIO_USE_THREAD_API )
+ #define MBGDEVIO_USE_THREAD_API 1
+ #endif
+
+ #if !defined( MBGDEVIO_HAVE_THREAD_AFFINITY )
+ #define MBGDEVIO_HAVE_THREAD_AFFINITY 1
+ #endif
+
+ #define MBG_USE_KERNEL_DRIVER 1
+ #include <windows.h>
+
+#elif defined( MBG_TGT_LINUX )
+
+ #if !defined( MBGDEVIO_XHRT_API )
+ #define MBGDEVIO_XHRT_API 1
+ #endif
+
+ // Thread support under Linux depends strongly on
+ // the versions of some libraries, so the symbols
+ // MBGDEVIO_USE_THREAD_API and MBGDEVIO_HAVE_THREAD_AFFINITY
+ // should be set in the project's Makefile, depending on the
+ // target envionment. Otherwise thread support is disabled
+ // as per default.
+
+ #define MBG_USE_KERNEL_DRIVER 1
+ #include <fcntl.h>
+
+#elif defined( MBG_TGT_BSD )
+
+ #define MBG_USE_KERNEL_DRIVER 1
+ #include <fcntl.h>
+
+#elif defined( MBG_TGT_OS2 )
+
+ #define MBG_USE_KERNEL_DRIVER 1
+
+#elif defined( MBG_TGT_DOS )
+
+ #if !defined( MBG_USE_DOS_TSR )
+ #define MBG_USE_DOS_TSR 1
+ #endif
+
+ #include <pcpsdrvr.h>
+
+#else // other target OSs which access the hardware directly
+
+ #include <pcpsdrvr.h>
+
+#endif
+
+
+#if !defined( MBGDEVIO_XHRT_API )
+ #define MBGDEVIO_XHRT_API 0
+#endif
+
+#if !defined( MBGDEVIO_USE_THREAD_API )
+ #define MBGDEVIO_USE_THREAD_API 0
+#endif
+
+#if !defined( MBGDEVIO_HAVE_THREAD_AFFINITY )
+ #define MBGDEVIO_HAVE_THREAD_AFFINITY 0
+#endif
+
+#ifdef _MBGDEVIO
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+// If MBGDEVIO_SIMPLE != 0 then some complex configuration
+// API calls are excluded from build, which would otherwise
+// require some additional mbglib modules to be linked
+// to the application.
+#if !defined( MBGDEVIO_SIMPLE )
+ #define MBGDEVIO_SIMPLE 0
+#endif
+
+
+#if defined( MBG_USE_KERNEL_DRIVER )
+
+ typedef MBG_HANDLE MBG_DEV_HANDLE;
+
+ #define MBG_INVALID_DEV_HANDLE MBG_INVALID_HANDLE
+
+#else // other target OSs which access the hardware directly
+
+ typedef PCPS_DDEV *MBG_DEV_HANDLE;
+
+ #define MBG_INVALID_DEV_HANDLE NULL
+
+#endif
+
+
+
+/**
+ The type below is used to store a unique ID for a device which
+ is made up of the device model name and its serial number, i.e.:
+ Format: [model_name]_[serial_number], e.g. "GPS170PCI_028210040670"
+ */
+typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1];
+
+
+
+#if defined( MBG_TGT_LINUX ) && !defined( MBG_ARCH_ARM )
+
+ #include <sched.h>
+
+ #define MBG_PROCESS_ID pid_t
+ #define _mbg_get_current_process() 0
+
+ #define MBG_CPU_SET cpu_set_t
+ #define MBG_CPU_SET_SIZE CPU_SETSIZE
+ #define _mbg_cpu_clear( _ps ) CPU_ZERO( (_ps) )
+ #define _mbg_cpu_set( _i, _ps ) CPU_SET( (_i), (_ps) )
+ #define _mbg_cpu_isset( _i, _ps ) CPU_ISSET( (_i), (_ps) )
+
+ #if MBGDEVIO_USE_THREAD_API
+
+ #include <pthread.h>
+
+ #define MBG_THREAD_ID pthread_t
+ #define _mbg_get_current_thread() 0
+ #define MBG_THREAD_FNC_ATTR // empty
+ #define MBG_THREAD_FNC_RET_VAL void *
+ #define _mbg_thread_exit( _v ) return (void *) (_v)
+
+ #define MBG_MUTEX pthread_mutex_t
+ #define _mbg_mutex_init( _pm ) pthread_mutex_init( (_pm), NULL )
+ #define _mbg_mutex_deinit( _pm ) _nop_macro_fnc()
+ #define _mbg_mutex_lock( _pm ) pthread_mutex_lock( (_pm) )
+ #define _mbg_mutex_unlock( _pm ) pthread_mutex_unlock( (_pm) )
+
+ #endif
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #define MBG_PROCESS_ID HANDLE
+ #define _mbg_get_current_process() GetCurrentProcess()
+
+ #define MBG_CPU_SET DWORD_PTR // Attention: this is not used as pointer!
+ #define MBG_CPU_SET_SIZE ( sizeof( MBG_CPU_SET ) * 8 )
+
+ #define MBG_THREAD_ID HANDLE
+ #define _mbg_get_current_thread() GetCurrentThread()
+ #define MBG_THREAD_FNC_ATTR WINAPI
+ #define MBG_THREAD_FNC_RET_VAL DWORD
+ #define _mbg_thread_exit( _v ) ExitThread( _v ); return (_v)
+
+ #define MBG_MUTEX CRITICAL_SECTION
+ #define _mbg_mutex_init( _pm ) InitializeCriticalSection( (_pm) )
+ #define _mbg_mutex_deinit( _pm ) DeleteCriticalSection( (_pm) )
+ #define _mbg_mutex_lock( _pm ) EnterCriticalSection( (_pm) )
+ #define _mbg_mutex_unlock( _pm ) LeaveCriticalSection( (_pm) )
+
+#endif // target specific
+
+
+#if !defined( MBG_TGT_WIN32 )
+
+ #define FILETIME int // just a dummy to avoid build errors
+
+#endif
+
+
+#if !defined( MBG_PROCESS_ID )
+ #define MBG_PROCESS_ID int
+#endif
+
+#if !defined( _mbg_get_current_process )
+ #define _mbg_get_current_process() 0
+#endif
+
+#if !defined( MBG_CPU_SET )
+ #define MBG_CPU_SET int
+#endif
+
+#if !defined( MBG_CPU_SET_SIZE )
+ #define MBG_CPU_SET_SIZE ( sizeof( MBG_CPU_SET ) * 8 )
+#endif
+
+#if !defined( _mbg_cpu_clear )
+ #define _mbg_cpu_clear( _ps ) ( *(_ps) = 0 )
+#endif
+
+#if !defined( _mbg_cpu_set )
+ #define _mbg_cpu_set( _i, _ps ) ( *(_ps) |= ( 1UL << (_i) ) )
+#endif
+
+#if !defined( _mbg_cpu_isset )
+ #define _mbg_cpu_isset( _i, _ps ) ( *(_ps) & ( 1UL << (_i) ) )
+#endif
+
+
+#if !defined( MBG_THREAD_ID )
+ #define MBG_THREAD_ID int
+#endif
+
+#if !defined( _mbg_get_current_thread )
+ #define _mbg_get_current_thread() 0
+#endif
+
+#if !defined( MBG_THREAD_FNC_ATTR )
+ #define MBG_THREAD_FNC_ATTR // empty
+#endif
+
+#if !defined( MBG_THREAD_FNC_RET_VAL )
+ #define MBG_THREAD_FNC_RET_VAL void
+#endif
+
+#if !defined( _mbg_thread_exit )
+ #define _mbg_thread_exit( _v ) _nop_macro_fnc()
+#endif
+
+
+#if !defined( MBG_MUTEX )
+ #define MBG_MUTEX int
+#endif
+
+#if !defined( _mbg_mutex_init )
+ #define _mbg_mutex_init( _pm ) _nop_macro_fnc()
+#endif
+
+#if !defined( _mbg_mutex_deinit )
+ #define _mbg_mutex_deinit( _pm ) _nop_macro_fnc()
+#endif
+
+#if !defined( _mbg_mutex_lock )
+ #define _mbg_mutex_lock( _pm ) _nop_macro_fnc()
+#endif
+
+#if !defined( _mbg_mutex_unlock )
+ #define _mbg_mutex_unlock( _pm ) _nop_macro_fnc()
+#endif
+
+typedef struct
+{
+ MBG_THREAD_ID thread_id;
+ #if defined( MBG_TGT_WIN32 )
+ HANDLE exit_request;
+ #endif
+} MBG_THREAD_INFO;
+
+
+
+typedef struct
+{
+ PCPS_HR_TIME_CYCLES htc;
+ uint64_t pcps_hr_tstamp64;
+} MBG_XHRT_VARS;
+
+
+typedef struct
+{
+ MBG_XHRT_VARS vars;
+ MBG_XHRT_VARS prv_vars;
+ MBG_PC_CYCLES_FREQUENCY freq_hz;
+ int ioctl_status;
+ int sleep_ms;
+ MBG_MUTEX mutex;
+ MBG_DEV_HANDLE dh;
+} MBG_XHRT_INFO;
+
+
+typedef struct
+{
+ MBG_XHRT_INFO xhrt_info;
+ MBG_THREAD_INFO ti;
+} MBG_POLL_THREAD_INFO;
+
+
+
+/**
+ Match modes to decide how to proceed if a certain
+ model type with certain serial number can not be found
+ */
+enum MBG_MATCH_MODE
+{
+ MBG_MATCH_ANY, /**< open the next available device on the system */
+ MBG_MATCH_MODEL, /**< open the next available device on the system with the same clock type */
+ MBG_MATCH_EXACTLY, /**< force opening exactly the requested device otherwise exit with failure */
+ N_MBG_MATCH_MODE /**< number of known modes */
+};
+
+
+
+typedef struct _MBG_DEVICE_LIST
+{
+ char *device_path; /**< Hardware ID depending on the calling function */
+ struct _MBG_DEVICE_LIST *next;
+
+} MBG_DEVICE_LIST;
+
+
+
+typedef struct _MBG_DEVICENAME_LIST
+{
+ char device_name[40]; /**< readable name */
+ struct _MBG_DEVICENAME_LIST *next;
+
+} MBG_DEVICENAME_LIST;
+
+
+
+#define _mbg_generic_read_var( _dh, _cmd, _s ) \
+ mbg_generic_read( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbg_generic_write_var( _dh, _cmd, _s ) \
+ mbg_generic_write( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbg_generic_read_gps_var( _dh, _cmd, _s ) \
+ mbg_generic_read_gps( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+#define _mbg_generic_write_gps_var( _dh, _cmd, _s ) \
+ mbg_generic_write_gps( _dh, _cmd, &(_s), sizeof( (_s) ) )
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ /**
+ Get the version number of the compiled mbgdevio library.
+ If the mbgdevio library is built as a DLL/shared object then
+ the version number of the compiled library may differ from
+ the version number of the import library and header files
+ which have been used to build an application.
+
+ @return The version number
+
+ @see ::MBGDEVIO_VERSION defined in mbgdevio.h.
+ */
+ _MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) ;
+
+ /**
+ Check if the version of the compiled mbgdevio library is compatible
+ with a certain version which is passed as parameter.
+
+ @param header_version Version number to be checked, should be ::MBGDEVIO_VERSION
+ defined in mbgdevio.h.
+
+ @return ::MBG_SUCCESS if compatible, ::MBG_ERR_LIB_NOT_COMPATIBLE if not.
+
+ @see ::MBGDEVIO_VERSION defined in mbgdevio.h.
+ */
+ _MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) ;
+
+ /**
+ Open a device by index, starting from 0.
+ This function is <b>out of date</b>, mbg_open_device_by_name()
+ should be used instead.
+
+ See the <b>note</b> for mbg_find_device() for details.
+
+ @param device_index Index of the device, use 0 for the first device.
+ */
+ _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device( unsigned int device_index ) ;
+
+ /**
+ Get the number of supported devices installed on the computer.
+ This function is <b>out of date</b>, mbg_find_devices_with_names()
+ should be used instead.
+
+ <b>Note:</b> This function is out of date since it may not work
+ correctly for Meinberg devices which are disconnected and reconnected
+ while the system is running (e.g. USB devices). However, the function
+ will be kept for compatibility reasons and works correctly if all
+ Meinberg devices are connected at system boot and are not disconnected
+ and reconnected during operation
+
+ @return The number of devices found.
+
+ @see mbg_find_devices_with_names()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) ;
+
+ /**
+ Return the number of supported devices installed on the system and
+ set up a list of unique names of those devices.
+
+ This function should be used preferably instead of mbg_find_devices().
+
+ @param device_list Pointer to a linked list of type ::MBG_DEVICENAME_LIST
+ with device names. The list will be allocated by this
+ function and has to be freed after usage by calling
+ mbg_free_device_name_list().
+ @param max_devices Maximum number of devices the function should look for
+ (can not exceed ::MBG_MAX_DEVICES).
+
+ @return Number of present devices
+
+ @see ::MBG_HW_NAME for the format of the unique names
+ @see mbg_free_device_name_list()
+ @see mbg_find_devices()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEVICENAME_LIST **device_list, int max_devices ) ;
+
+ /**
+ Free the memory of the ::MBG_DEVICENAME_LIST that has been allocated before
+ by mbg_find_devices_with_names().
+
+ @param *list Linked list of type ::MBG_DEVICENAME_LIST
+
+ @see mbg_find_devices_with_names()
+ */
+ _MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEVICENAME_LIST *list) ;
+
+ /**
+ Return a handle to a device with a certain unique name.
+ The names of the devices that are installed on the system can be retrieved by
+ the function mbg_find_devices_with_names().
+
+ This function should be used preferably instead of mbg_open_device().
+
+ @param hw_name String with the unique name of the device to be opened
+ @param selection_mode One of the enum values of ::MBG_MATCH_MODE
+
+ @return On success, the function returns a handle to the device, otherwise ::MBG_INVALID_DEV_HANDLE
+
+ @see ::MBG_HW_NAME for the format of the unique names.
+ @see ::MBG_MATCH_MODE
+ @see mbg_find_devices_with_names()
+ */
+ _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char* hw_name, int selection_mode ) //##++++
+;
+
+ /**
+ Close a handle to a device and set the handle value to ::MBG_INVALID_DEV_HANDLE.
+ If required, unmap mapped memory.
+
+ @param dev_handle Handle to a Meinberg device.
+ */
+ _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) ;
+
+ /**
+ Return a ::PCPS_DRVR_INFO structure that provides information
+ about the kernel device driver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_DRVR_INFO structure which is filled up.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p ) ;
+
+ /**
+ Return a ::PCPS_DEV structure that provides detailed information about the device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_DEV structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) ;
+
+ /**
+ Return the current state of the on-board::PCPS_STATUS_PORT.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_STATUS_PORT value to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+
+ @see \ref group_status_port "bitmask"
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic read function which writes a command code to the device
+ and reads a number of replied data to a generic buffer.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device
+ @param *p Pointer to a buffer to be filled up
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_write()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic read function which writes a GPS command code to the device
+ and reads a number of replied data to a generic buffer.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any GPS command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be filled up
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_gps_data()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic write function which writes a command code plus an
+ associated number of data bytes to the device.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be written
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_read()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Generic write function which writes a GPS command code plus an
+ associated number of data bytes to the device.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Warning</b>: This is for debugging purposes only!
+ The specialized API calls should be used preferably.
+ A specific device may not support any GPS command code.
+
+ @param dh Valid handle to a Meinberg device
+ @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device.
+ @param *p Pointer to a buffer to be written
+ @param size Size of the buffer *p
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_gps_data()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_io()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Write and/or read generic data to/from a device.
+ The macro _pcps_has_generic_io() or the API call mbg_dev_has_generic_io()
+ check whether this call is supported by a specific card.
+
+ <b>Warning</b>: This call is for debugging purposes and internal use only!
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_generic_io()
+ @see mbg_generic_read()
+ @see mbg_generic_write()
+ @see mbg_generic_read_gps()
+ @see mbg_generic_write_gps()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, const void *in_p, int in_sz, void *out_p, int out_sz ) ;
+
+ /**
+ Read a ::PCPS_TIME structure returning the current date/time/status.
+ The returned time is local time according to the card's time zone setting,
+ with a resolution of 10 ms (i.e. 10ths of seconds).
+
+ This call is supported by any device manufactured by Meinberg. However,
+ for higher accuracy and resolution the mbg_get_hr_time..() group of calls
+ should be used preferably if supported by the specific device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_set_time()
+ @see mbg_get_sync_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ;
+
+ /**
+ Set a device's on-board clock manually by passing a ::PCPS_STIME structure
+ The macro _pcps_can_set_time() checks whether this call
+ is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_STIME structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p ) ;
+
+ /**
+ Read a ::PCPS_TIME structure returning the date/time/status reporting
+ when the device was synchronized the last time to its time source,
+ e.g. the DCF77 signal or the GPS satellites.
+ The macro _pcps_has_sync_time() or the API call mbg_dev_has_sync_time()
+ check whether this call is supported by a specific card.
+
+ The macro _pcps_has_sync_time() checks whether this call
+ is supported by a specific card.
+
+ <b>Note:</b> If that information is not available on the board then
+ the value of the returned ::PCPS_TIME::sec field is set to 0xFF.
+ The macro _pcps_time_is_read() can be used to check whether the
+ returned information is valid, or not available.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ;
+
+ /**
+ Wait until the next second change, then return a ::PCPS_TIME
+ structure similar to mbg_get_time().
+
+ <b>Note:</b> This API call is supported under Windows only.
+ The call blocks until the kernel driver detects a second change
+ reported by the device.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ;
+
+ /**
+ Read a ::PCPS_HR_TIME (High Resolution time) structure returning
+ the current %UTC time (seconds since 1970), %UTC offset, and status.
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This API call provides a higher accuracy and resolution
+ than mbg_get_time(). However, it does not account for the latency
+ which is introduced when accessing the board.
+ The mbg_get_hr_time_cycles() and mbg_get_hr_time_comp() calls
+ provides mechanisms to account for and/or compensate the latency.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_hr_time()
+ @see mbg_get_time()
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ;
+
+ /* (Intentionally excluded from Doxygen )
+ Write a high resolution time stamp ::PCPS_TIME_STAMP to the clock
+ to configure a %UTC time when the clock shall generate an event.
+ The macro _pcps_has_event_time() or the API call mbg_dev_has_event_time()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This is only supported by some special firmware.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_event_time()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p ) ;
+
+ /**
+ Read the configuration of a device's serial port.
+ The macro _pcps_has_serial() checks whether this call
+ is supported by a specific card.
+
+ <b>Note:</b> This function is supported only by a certain class
+ of devices, so it should not be called directly. The generic
+ function mbg_get_serial_settings() should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_SERIAL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see \ref group_cmd_bytes
+ @see mbg_get_serial_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) ;
+
+ /**
+ Write the configuration of a device's serial port.
+ The macro _pcps_has_serial() checks whether this call
+ is supported by a specific card.
+
+ <b>Note:</b> This function is supported only by a certain class
+ of devices, so it should not be called directly. The generic
+ function mbg_save_serial_settings() should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_SERIAL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see \ref group_cmd_bytes
+ @see mbg_save_serial_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p ) ;
+
+ /**
+ Read the card's time zone/daylight saving configuration code.
+ That tzcode is supported by some simpler cards and only allows only
+ a very basic configuration.
+ The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_get_pcps_tzdl() or mbg_get_gps_tzdl()
+ calls instead which allow for a more detailed configuration of the
+ time zone and daylight saving settings.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZCODE structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzcode()
+ @see mbg_set_tzcode()
+ @see mbg_get_pcps_tzdl()
+ @see mbg_get_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) ;
+
+ /**
+ Write the card's time zone/daylight saving configuration code.
+ That tzcode is supported by some simpler cards and only allows only
+ a very basic configuration.
+ The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_set_pcps_tzdl() or mbg_set_gps_tzdl()
+ calls instead which allow for a more detailed configuration of the
+ time zone and daylight saving settings.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZCODE structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzcode()
+ @see mbg_get_tzcode()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p ) ;
+
+ /**
+ Read the card's time zone/daylight saving parameters using the
+ ::PCPS_TZDL structure.
+ The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_get_tzcode() or mbg_get_gps_tzdl()
+ calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZDL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_get_tzcode()
+ @see mbg_get_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) ;
+
+ /**
+ Write the card's time zone/daylight saving parameters using the
+ ::PCPS_TZDL structure.
+ The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl()
+ check whether this call is supported by a specific card.
+ Other cards may support the mbg_set_tzcode() or mbg_set_gps_tzdl()
+ calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TZDL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_get_pcps_tzdl()
+ @see mbg_set_tzcode()
+ @see mbg_set_gps_tzdl()
+ @see \ref group_cmd_bytes
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p ) ;
+
+ /**
+ Read the reference time offset from %UTC for clocks which can't determine
+ that offset automatically, e.g. from an IRIG input signal.
+ The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_REF_OFFS value to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ref_offs()
+ @see mbg_set_ref_offs()
+ @see ::PCPS_GET_REF_OFFS
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p ) ;
+
+ /**
+ Write the reference time offset from %UTC for clocks which can't determine
+ that offset automatically, e.g. from an IRIG input signal.
+ The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_REF_OFFS value to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ref_offs()
+ @see mbg_get_ref_offs()
+ @see ::PCPS_SET_REF_OFFS
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p ) ;
+
+ /**
+ Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags.
+ The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current
+ settings of those flags.
+ The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_OPT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_opt_flags()
+ @see mbg_set_opt_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p ) ;
+
+ /**
+ Write a ::MBG_OPT_SETTINGS structure contains optional settings, controlled by flags.
+ The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags()
+ check whether this call is supported by a specific card.
+ The ::MBG_OPT_INFO structure should be read first to check which of the specified
+ flags is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_OPT_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_opt_flags()
+ @see mbg_get_opt_info()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p ) ;
+
+ /**
+ Read an ::IRIG_INFO structure containing the configuration of an IRIG input
+ plus the possible settings supported by that input.
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_irig_rx_settings()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ;
+
+ /**
+ Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG input.
+ The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx()
+ check whether this call is supported by a specific card.
+ The ::IRIG_INFO structure should be read first to determine the possible
+ settings supported by this card's IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IRIG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_rx_info()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_irig_ctrl_bits() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_ctrl_bits()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read a ::MBG_IRIG_CTRL_BITS type which contains the control function
+ bits of the latest IRIG input frame. Those bits may carry some
+ well-known information, as in the IEEE1344 code, but may also contain
+ some customized information, depending on the IRIG frame type and
+ the configuration of the IRIG generator. So these bits are returned
+ as-is and must be interpreted by the application.
+ The macro _pcps_has_irig_ctrl_bits() or the API call mbg_dev_has_irig_ctrl_bits()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_irig_ctrl_bits()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, MBG_IRIG_CTRL_BITS *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_raw_irig_data() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_raw_irig_data()
+ @see mbg_get_raw_irig_data_on_sec_change()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p) ;
+
+ /**
+ Read a ::MBG_RAW_IRIG_DATA type which contains all data
+ bits of the latest IRIG input frame.
+ The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_raw_irig_data()
+ @see mbg_get_raw_irig_data_on_sec_change()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ;
+
+ /**
+ Read a ::MBG_RAW_IRIG_DATA type just after a second change which contains all data
+ bits of the latest IRIG input frame.
+ The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The mbg_get_time_sec_change() function called by this function is
+ supported under Windows only, so this function can also only be used under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_raw_irig_data()
+ @see mbg_get_raw_irig_data()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_irig_time() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read a ::PCPS_IRIG_TIME type which returns the raw IRIG day-of-year number
+ and time decoded from the latest IRIG input frame. If the configured IRIG code
+ also contains the year number then the year number is also returned, otherwise
+ the returned year number is 0xFF.
+ The macro _pcps_has_irig_time() or the API call mbg_dev_has_irig_time()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_IRIG_TIME type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_irig_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh, PCPS_IRIG_TIME *p ) ;
+
+ /**
+ Clear the card's on-board time capture FIFO buffer.
+ The macro _pcps_can_clr_ucap_buff() or the API call mbg_dev_can_clr_ucap_buff()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_can_clr_ucap_buff()
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh ) ;
+
+ /**
+ Read a ::PCPS_UCAP_ENTRIES structure to retrieve the number of saved
+ user capture events and the maximum capture buffer size.
+ The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ucap()
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_ENTRIES *p ) ;
+
+ /**
+ Retrieve a single time capture event from the on-board FIFO buffer
+ using a ::PCPS_HR_TIME structure. The oldest entry of the FIFO is retrieved
+ and then removed from the FIFO.
+ If no capture event is available in the FIFO buffer then both the seconds
+ and the fractions of the returned timestamp are 0.
+ The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This call is very much faster than the older mbg_get_gps_ucap()
+ call which is obsolete but still supported for compatibility with
+ older cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ucap()
+ @see mbg_get_ucap_entries()
+ @see mbg_clr_ucap_buff()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ;
+
+ /**
+ Read the card's time zone/daylight saving parameters using the ::TZDL
+ structure.
+ The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> In spite of the function name this call may also be
+ supported by non-GPS cards. Other cards may support the mbg_get_tzcode()
+ or mbg_get_pcps_tzdl() calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TZDL structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see mbg_get_tzcode()
+ @see mbg_get_pcps_tzdl()
+ @see \ref group_tzdl
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p ) ;
+
+ /**
+ Write the card's time zone/daylight saving parameters using the ::TZDL
+ structure.
+ The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> In spite of the function name this call may also be
+ supported by non-GPS cards. Other cards may support the mbg_set_tzcode()
+ or mbg_set_pcps_tzdl() calls instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TZDL structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_get_gps_tzdl()
+ @see mbg_set_tzcode()
+ @see mbg_set_pcps_tzdl()
+ @see \ref group_tzdl
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p ) ;
+
+ /**
+ Retrieve the software revision of a GPS receiver.
+ This call is obsolete but still supported for compatibility
+ with older GPS cards.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The function mbg_get_gps_receiver_info() should
+ be used instead, if supported by the card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SW_REV structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_is_gps()
+ @see mbg_get_gps_receiver_info()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p ) ;
+
+ /**
+ Retrieve the status of the battery buffered GPS variables.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+ The GPS receiver stays in cold boot mode until all of the
+ data sets are valid.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::BVAR_STAT structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT *p ) ;
+
+ /**
+ Read the current board time using a ::TTM structure.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This call is pretty slow, so the mbg_get_hr_time_..()
+ group of calls should be used preferably.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p ) ;
+
+ /**
+ Write a ::TTM structure to a GPS receiver in order to set the
+ on-board date and time.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p ) ;
+
+ /**
+ Read a ::PORT_PARM structure to retrieve the configuration
+ of the device's serial ports.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This function is obsolete since it is only
+ supported by a certain class of devices and can handle only
+ up to 2 ports. The generic function mbg_get_serial_settings()
+ should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PORT_PARM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM *p ) ;
+
+ /**
+ Write a ::PORT_PARM structure to configure the on-board
+ serial ports.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This function is obsolete since it is only
+ supported by a certain class of devices and can handle only
+ up to 2 ports. The generic function mbg_save_serial_settings()
+ should be used instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PORT_PARM structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_PARM *p ) ;
+
+ /**
+ Read an ::ANT_INFO structure to retrieve status information of the GPS antenna.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Normally the antenna connection status can also be
+ determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal
+ fields.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ANT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p ) ;
+
+ /**
+ Read a time capture event from the on-board FIFO buffer using a ::TTM structure.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> This call is pretty slow and has been obsoleted by
+ mbg_get_ucap_event() which should be used preferably, if supported
+ by the card. Anyway, this call is still supported for compatibility
+ with older cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::TTM structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ @see mbg_clr_ucap_buff()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p ) ;
+
+ /**
+ Read an ::ENABLE_FLAGS structure reporting whether certain outputs
+ shall be enabled immediately after the card's power-up, or only
+ after the card has synchronized to its input signal.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Not all of the input signals specified for the
+ ::ENABLE_FLAGS structure can be modified individually.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::ENABLE_FLAGS structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::ENABLE_FLAGS
+ @see mbg_set_gps_enable_flags()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_FLAGS *p ) ;
+
+ /**
+ Write an ENABLE_FLAGS structure to configure whether certain outputs
+ shall be enabled immediately after the card's power-up, or only
+ after the card has synchronized to its input signal.
+ The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Not all of the input signals specified for the
+ ENABLE_FLAGS structure can be modified individually.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ENABLE_FLAGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ENABLE_FLAGS
+ @see mbg_get_gps_enable_flags()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, const ENABLE_FLAGS *p ) ;
+
+ /**
+ Read a ::STAT_INFO structure to retrieve the status of the
+ GPS receiver, including mode of operation and numer of
+ visible/usable satellites.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::STAT_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::STAT_INFO
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO *p ) ;
+
+ /**
+ Sends a ::GPS_CMD to a GPS receiver.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::GPS_CMD
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see ::PC_GPS_CMD_BOOT, ::PC_GPS_CMD_INIT_SYS, ::PC_GPS_CMD_INIT_USER, ::PC_GPS_CMD_INIT_DAC
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_cmd( MBG_DEV_HANDLE dh, const GPS_CMD *p ) ;
+
+ /**
+ Read the current GPS receiver position using the ::POS structure
+ which contains different coordinate formats.
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POS structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_xyz()
+ @see mbg_set_gps_pos_lla()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p ) ;
+
+ /**
+ Preset the GPS receiver position using ::XYZ coordinates
+ (ECEF: WGS84 "Earth Centered, Earth fixed" kartesian coordinates).
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param p Position in ::XYZ format to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_lla()
+ @see mbg_get_gps_pos()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) ;
+
+ /**
+ Preset the GPS receiver position using ::LLA coordinates
+ (longitude, latitude, altitude)
+ The macro _pcps_is_gps() or the API call mbg_dev_is_gps()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param p Position in ::LLA format to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pos_xyz()
+ @see mbg_get_gps_pos()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) ;
+
+ /**
+ Read the configured length of the GPS antenna cable (::ANT_CABLE_LEN).
+ The cable delay is internally compensated by 5ns per meter cable.
+ The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::ANT_CABLE_LEN structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_cab_len()
+ @see mbg_set_gps_ant_cable_len()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p ) ;
+
+ /**
+ Write the length of the GPS antenna cable (::ANT_CABLE_LEN).
+ The cable delay is internally compensated by 5ns per meter cable.
+ The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::ANT_CABLE_LEN structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_cab_len()
+ @see mbg_get_gps_ant_cable_len()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, const ANT_CABLE_LEN *p ) ;
+
+ /**
+ Read a ::RECEIVER_INFO structure from a card.
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> Applications should call mbg_setup_receiver_info()
+ preferably, which also sets up a basic ::RECEIVER_INFO structure
+ for card which don't provide that structure by themselves.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::RECEIVER_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_setup_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p ) ;
+
+ /**
+ Write the configuration for a single serial port using the ::PORT_SETTINGS_IDX
+ structure which contains both the ::PORT_SETTINGS and the port index value.
+ Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings().
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The function mbg_save_serial_settings() should be used preferably
+ to write new port configuration to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PORT_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+ @see mbg_set_gps_port_settings()
+ @see mbg_dev_has_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, const PORT_SETTINGS_IDX *p ) ;
+
+ /**
+ Write the configuration for a single serial port using the ::PORT_SETTINGS
+ structure plus the port index.
+ Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings_idx().
+ The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info()
+ check whether this call is supported by a specific card.
+
+ <b>Note:</b> The function mbg_save_serial_settings() should be used preferably
+ to write new port configuration to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PORT_SETTINGS structure to be filled up
+ @param idx Index of the serial port to be configured (starting from 0 ).
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_save_serial_settings()
+ @see mbg_set_gps_port_settings_idx()
+ @see mbg_dev_has_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, const PORT_SETTINGS *p, int idx ) ;
+
+ /**
+ Set up a ::RECEIVER_INFO structure for a device.
+ If the device supports the ::RECEIVER_INFO structure then the structure
+ is read from the device, otherwise a structure is set up using
+ default values depending on the device type.
+ The function mbg_get_device_info() must have been called before,
+ and the returned PCPS_DEV structure passed to this function.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure returned by mbg_get_device_info()
+ @param *p Pointer to a ::RECEIVER_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_dev_has_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_INFO *p ) ;
+
+ /**
+ Read all serial port settings and supported configuration parameters.
+
+ The functions mbg_get_device_info() and mbg_setup_receiver_info()
+ must have been called before, and the returned ::PCPS_DEV and
+ ::RECEIVER_INFO structures must be passed to this function.
+
+ The complementary function mbg_save_serial_settings() should be used
+ to write the modified serial port configuration back to the board.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *pdev Pointer to a ::PCPS_DEV structure.
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up.
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+ @see mbg_save_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, const RECEIVER_INFO *p_ri ) ;
+
+ /**
+ Write the configuration settings for a single serial port to the board.
+
+ Modifications to the serial port configuration should be made only
+ after mbg_get_serial_settings() had been called to read all serial port
+ settings and supported configuration parameters.
+ This function has finally to be called once for every serial port
+ the configuration of which has been modified.
+
+ As also required by mbg_get_serial_settings(), the functions
+ mbg_get_device_info() and mbg_setup_receiver_info() must have been
+ called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures
+ must be passed to this function.
+
+ @param dh Valid handle to a Meinberg device
+ @param *pdev Pointer to a ::PCPS_DEV structure
+ @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure
+ @param port_num Index of the ::serial port to be saved
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+ @see mbg_get_device_info()
+ @see mbg_setup_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, int port_num ) ;
+
+ /**
+ Read the version code of the on-board PCI/PCIe interface ASIC.
+ The macro _pcps_has_asic_version() or the API call mbg_dev_has_asic_version()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCI_ASIC_VERSION type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function
+
+ @see mbg_dev_has_asic_version()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p ) ;
+
+ /**
+ Read the features of the on-board PCI/PCIe interface ASIC.
+ The macro _pcps_has_asic_features() or the API call mbg_dev_has_asic_features()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::PCI_ASIC_FEATURES type to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_asic_features()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh, PCI_ASIC_FEATURES *p ) ;
+
+ /**
+ Check if a specific device supports configurable time scales.
+
+ By default the cards return UTC and/or local time. However, some cards
+ can be configured to return pure GPS time or TAI instead.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time_scale_info()
+ @see mbg_set_time_scale_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read a ::MBG_TIME_SCALE_INFO structure from a card telling which time scales
+ are supported by a card, and the current settings of the card.
+
+ The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_time_scale().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_time_scale_settings()
+ @see mbg_dev_has_time_scale()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p ) ;
+
+ /**
+ Write a ::MBG_TIME_SCALE_SETTINGS structure to a card which determines
+ which time scale shall be represented by time stamps read from the card.
+
+ The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_time_scale().
+
+ The function mbg_get_time_scale_info() should have been called before
+ in order to determine which time scales are supported by the card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_time_scale_info()
+ @see mbg_dev_has_time_scale()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_SETTINGS *p ) ;
+
+ /**
+ Check if a specific device supports reading/writing a GPS UTC parameter
+ set via the PC bus (reading/writing these parameters via the serial port
+ is supported by all GPS devices).
+
+ The UTC parameters are normally received from the satellites' broadcasts
+ and contain the current time offset between GPT time and UTC, plus information
+ on a pending leap second.
+
+ It may be useful to overwrite them to do some tests, or for applications
+ where a card is freewheeling.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_utc_parm()
+ @see mbg_set_utc_parm()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read a ::UTC structure from a card.
+
+ The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_utc_parm().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::UTC structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_utc_parm()
+ @see mbg_set_utc_parm()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ;
+
+ /**
+ Write a ::UTC structure to a card.
+
+ This should only be done for testing, or if a card is operated in
+ freewheeling mode. If the card receives any satellites the settings
+ written to the board are overwritten by the parameters broadcasted
+ by the satellites.
+
+ The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm()
+ check whether this call is supported by a specific card.
+ See also the notes for mbg_dev_has_utc_parm().
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a valid ::UTC structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_utc_parm()
+ @see mbg_get_utc_parm()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ;
+
+ /**
+ Read a ::PCPS_TIME_CYCLES structure that contains a ::PCPS_TIME structure
+ and a PC cycle counter value which can be used to compensate the latency
+ of the call, i.e. the program execution time until the time stamp has actually
+ been read from the board.
+
+ This call is supported for any card, similar to mbg_get_time(). However,
+ the mbg_get_hr_time_cyles() call should be used preferably if supported by
+ the specific card since that call provides much better accuracy than this one.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On other operating systems the returned
+ cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYCLES *p ) ;
+
+ /**
+ Read a ::PCPS_HR_TIME_CYCLES structure that contains a ::PCPS_HR_TIME structure
+ and a PC cycle counter value which can be used to compensate the latency
+ of the call, i.e. the program execution time until the time stamp has actually
+ been read from the board.
+
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a specific card.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On other operating systems the returned
+ cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time_cycles()
+ @see mbg_get_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, PCPS_HR_TIME_CYCLES *p ) ;
+
+ /**
+ Read a ::PCPS_HR_TIME structure plus cycle counter value, and correct the
+ time stamp for the latency of the call as described for mbg_get_hr_time_cycles(),
+ then return the compensated time stamp and optionally the latency.
+
+ The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time()
+ check whether this call is supported by a specific card.
+
+ The cycle counter value corresponds to a value returned by QueryPerformanceCounter()
+ under Windows, and get_cycles() under Linux. On other operating systems the returned
+ cycles value is always 0.
+
+ Applications should first pick up their own cycle counter value and then call
+ this function. The difference of the cycle counter values corresponds to the
+ latency of the call in units of the cycle counter clock frequency, e.g as reported
+ by QueryPerformanceFrequency() under Windows.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up
+ @param *hns_latency Optional pointer to an int32_t value to return
+ the latency in 100ns units. Pass NULL if not used.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time_comp()
+ @see mbg_get_hr_time()
+ @see mbg_get_time_cycles()
+ @see mbg_get_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p, int32_t *hns_latency ) ;
+
+ /**
+ Read an ::IRIG_INFO structure containing the configuration of an IRIG output
+ plus the possible settings supported by that output.
+ The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_irig_tx_settings()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ;
+
+ /**
+ Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG output.
+ The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an ::IRIG_INFO structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_tx_info()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ;
+
+ /**
+ Read a ::SYNTH structure containing the configuration of an optional
+ on-board programmable frequency synthesizer.
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_set_synth()
+ @see mbg_get_synth_state()
+ @see \ref group_synth
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p ) ;
+
+ /**
+ Write a ::SYNTH structure containing the configuration of an optional
+ on-board programmable frequency synthesizer.
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_get_synth()
+ @see mbg_get_synth_state()
+ @see \ref group_synth
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p ) ;
+
+ /**
+ Read a ::SYNTH_STATE structure reporting the current state
+ of an optional on-board programmable frequency synthesizer.
+ The macro _pcps_has_synth() or the API call mbg_dev_has_synth()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::SYNTH_STATE structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_synth()
+ @see mbg_get_synth()
+ @see mbg_set_synth()
+ @see \ref group_synth
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_fast_hr_timestamp_...() calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_fast_hr_timestamp_cycles()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP_CYCLES *p ) ;
+
+ /**
+ Read a high resolution ::PCPS_TIME_STAMP via memory mapped access,
+ and compensate the latency of the time stamp before it is returned.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up
+ @param *hns_latency Optionally receive the latency in hectonanoseconds
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_cycles()
+ @see mbg_get_fast_hr_timestamp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p, int32_t *hns_latency ) ;
+
+ /**
+ Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access.
+
+ This function does not return or evaluate a cycles count, so the latency
+ of the call can not be determined. However, depending on the timer hardware
+ used as cycles counter it may take quite some time to read the cycles count
+ on some hardware architectures, so this call can be used to yield lower
+ latencies, under the restriction to be unable to determine the exact latency.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_fast_hr_timestamp_comp()
+ @see mbg_get_fast_hr_timestamp_cycles()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p ) ;
+
+ /**
+ Check if a specific device is a GPS receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device is a DCF77 receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device is a MSF receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device is a WWVB receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device is a long wave signal receiver, e.g. DCF77, MSF or WWVB.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device is an IRIG receiver which supports
+ configuration of the IRIG input.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_rx_info()
+ @see mbg_set_irig_rx_settings()
+ @see mbg_dev_has_irig_tx()
+ @see mbg_dev_has_irig()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the HR_TIME functions.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_hr_time()
+ @see mbg_get_hr_time_cycles()
+ @see mbg_get_hr_time_comp()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports configuration of antenna cable length.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_ant_cable_len()
+ @see mbg_set_gps_ant_cable_len()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports timezone / daylight saving configuration
+ using the ::TZDL structure.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_tzdl()
+ @see mbg_set_gps_tzdl()
+ @see mbg_dev_has_tz()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports timezone / daylight saving configuration
+ using the ::PCPS_TZDL structure.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_pcps_tzdl()
+ @see mbg_set_pcps_tzdl()
+ @see mbg_dev_has_tz()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports timezone configuration
+ using the ::PCPS_TZCODE type.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_tzcode()
+ @see mbg_set_tzcode()
+ @see mbg_dev_has_tz()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports any kind of timezone configuration.
+ This can be used e.g. to check if a specifig dialog or menu has to
+ be displayed.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_tzdl()
+ @see mbg_dev_has_pcps_tzdl()
+ @see mbg_dev_has_tzcode()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Check if a specific device supports setting an event time, i.e.
+ configure a %UTC time when the clock shall generate an event.
+
+ <b>Note:</b> This is only supported by some special firmware.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_event_time()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the ::RECEIVER_INFO structure and related calls.
+ Older GPS devices may not support that structure.
+
+ The mbg_get_gps_receiver_info() call uses this call to decide whether a
+ ::RECEIVER_INFO can be read directly from a device, or whether a default
+ structure has to be set up using default values depending on the device type.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_clr_ucap_buff() call
+ used to clear a card's on-board time capture FIFO buffer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_clr_ucap_buff()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_ucap_entries() and
+ mbg_get_ucap_event() calls.
+
+ If the card does not but it is a GPS card then the card provides
+ a time capture FIFO buffer and the obsolete mbg_get_gps_ucap()
+ call can be used to retrieve entries from the FIFO buffer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ucap_entries()
+ @see mbg_get_ucap_event()
+ @see mbg_clr_ucap_buff()
+ @see mbg_get_gps_ucap()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides an IRIG output which can
+ be configured.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_irig_tx_info()
+ @see mbg_set_irig_tx_settings()
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig()
+ @see \ref group_icode
+
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Check if a specific device provides a serial output supporting
+ higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS
+ rather than ::DEFAULT_BAUD_RATES_DCF.
+
+ The mbg_get_serial_settings() takes care of this, so applications
+ which use that call as suggested won't need to use this call directly.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_serial_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides an input signal level value which
+ may be displayed, e.g. DCF77 or IRIG cards.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides an modulation signal which may be
+ displayed, e.g. the second marks of a DCF77 AM receiver.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides either an IRIG input or output.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_is_irig_rx()
+ @see mbg_dev_has_irig_tx()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides a configurable ref time offset
+ required to convert the received time to %UTC.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ref_offs()
+ @see mbg_set_ref_offs()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS
+ structures containing optional settings, controlled by flags.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_opt_info()
+ @see mbg_set_opt_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports large configuration data structures
+ as have been introducesde with the GPS receivers.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides a programmable frequency synthesizer.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_synth()
+ @see mbg_set_synth()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /* (Intentionally excluded from Doxygen)
+ Check if a specific device supports the mbg_generic_io() call.
+
+ <b>Warning</b>: That call is for debugging purposes and internal use only!
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_generic_io()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_asic_version() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_asic_version()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device supports the mbg_get_asic_features() call.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_asic_features()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read a ::POUT_INFO_IDX array of current settings and configuration
+ options of a card's programmable pulse outputs.
+ The function mbg_setup_receiver_info() must have been called before,
+ and the returned ::RECEIVER_INFO structure passed to this function.
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out
+ field (i.e. the number of programmable outputs on the board) is not 0.
+
+ The array passed to this function to receive the returned data
+ must be able to hold at least ::RECEIVER_INFO::n_prg_out elements.
+
+ @param dh Valid handle to a Meinberg device.
+ @param pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up
+ @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info()
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_set_gps_pout_settings_idx()
+ @see mbg_set_gps_pout_settings()
+ @see mbg_setup_receiver_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, POUT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ;
+
+ /**
+ Write the configuration for a single programmable pulse output using
+ the ::POUT_SETTINGS_IDX structure which contains both the ::POUT_SETTINGS
+ and the output index value.
+ Except for the parameter types, this call is equivalent to
+ mbg_set_gps_pout_settings().
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out field
+ (i.e. the number of programmable outputs on the board) is not 0, and the
+ output index value must be in the range 0..::RECEIVER_INFO::n_prg_out.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POUT_SETTINGS_IDX structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_all_pout_info()
+ @see mbg_set_gps_pout_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh, const POUT_SETTINGS_IDX *p ) ;
+
+ /**
+ Write the configuration for a single programmable pulse output using
+ the ::POUT_SETTINGS structure plus the index of the output to be configured.
+ Except for the parameter types, this call is equivalent to
+ mbg_set_gps_pout_settings_idx().
+ The function should only be called if the ::RECEIVER_INFO::n_prg_out field
+ (i.e. the number of programmable outputs on the board) is not 0, and the
+ output index value must be in the range 0..::RECEIVER_INFO::n_prg_out.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p Pointer to a ::POUT_SETTINGS structure to be written
+ @param idx Index of the programmable pulse output to be configured (starting from 0 ).
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_gps_all_pout_info()
+ @see mbg_set_gps_pout_settings_idx()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh, const POUT_SETTINGS *p, int idx ) ;
+
+ /**
+ Read a card's IRQ status information which includes flags indicating
+ whether IRQs are currently enabled, and whether IRQ support by a card
+ is possibly unsafe due to the firmware and interface chip version.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_STAT_INFO *p ) ;
+
+ /**
+ Check if a specific device provides simple LAN interface API calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_state()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read LAN interface information from a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::LAN_IF_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_ip4_state()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO *p ) ;
+
+ /**
+ Read LAN IPv4 state from a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IP4_SETTINGS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_settings()
+ @see mbg_set_ip4_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ;
+
+ /**
+ Read LAN IPv4 settings from a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::IP4_SETTINGS variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_state()
+ @see mbg_set_ip4_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ;
+
+ /**
+ Write LAN IPv4 settings to a card which supports this.
+ The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::IP4_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_lan_intf()
+ @see mbg_get_lan_if_info()
+ @see mbg_get_ip4_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, const IP4_SETTINGS *p ) ;
+
+ /**
+ Check if a specific device provides PTP configuration/status calls.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_set_ptp_cfg_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Check if a specific device provides PTP Unicast feature/configuration.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to an int which is set 0 or != 0 unless the call fails.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_unicast_cfg_info()
+ @see mbg_set_ptp_unicast_cfg_settings()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) ;
+
+ /**
+ Read PTP/IEEE1588 status from a card which supports this.
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_set_ptp_cfg_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p ) ;
+
+ /**
+ Read PTP/IEEE1588 config info and current settings from a card which supports this.
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp()
+ @see mbg_get_ptp_state()
+ @see mbg_set_ptp_cfg_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO *p ) ;
+
+ /**
+ Write PTP/IEEE1588 configuration settings to a card which supports this.
+ The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::PTP_CFG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp()
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_cfg_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, const PTP_CFG_SETTINGS *p ) ;
+
+ /**
+ Read PTP/IEEE1588 unicast config info and current settings from a card which supports this.
+ The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::PTP_UNICAST_CFG_INFO variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast()
+ @see mbg_set_ptp_unicast_cfg_settings()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_ptp_unicast_cfg_info( MBG_DEV_HANDLE dh, PTP_UNICAST_CFG_INFO *p ) ;
+
+ /**
+ Write PTP/IEEE1588 unicast configuration settings to a card which supports this.
+ The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast()
+ check whether this call is supported by a specific card.
+
+ @param dh Valid handle to a Meinberg device.
+ @param *p ::PTP_UNICAST_CFG_SETTINGS structure to be written
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_ptp_unicast()
+ @see mbg_get_ptp_state()
+ @see mbg_get_ptp_cfg_info()
+ @see mbg_get_ptp_unicast_cfg_info()
+*/
+ _MBG_API_ATTR int _MBG_API mbg_set_ptp_unicast_cfg_settings( MBG_DEV_HANDLE dh, const PTP_UNICAST_CFG_SETTINGS *p ) ;
+
+ /**
+ Read system time and card time from the kernel driver. The kernel
+ driver reads the current system time plus a HR time structure from
+ a card immediately after each other. The returned info structure also
+ contains some cycles counts to be able to determine the execution times
+ required to read those time stamps.
+
+ The advantage of this call compared to mbg_get_time_info_tstamp() is
+ that this call also returns the card's status. On the other hand, reading
+ the HR time from the card may block e.g. if another application accesses
+ the board.
+
+ This call makes a mbg_get_hr_time_cycles() call internally so the macro
+ _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() can be
+ used to check whether this call is supported with a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_INFO_HRT variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_hr_time()
+ @see mbg_get_time_info_tstamp()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_INFO_HRT *p ) ;
+
+ /**
+ This call is similar to mbg_get_time_info_hrt() except that a
+ mbg_get_fast_hr_timestamp_cycles() call is made internally, so the macro
+ _pcps_has_fast_hr_timestamp() or the API call mbg_dev_has_fast_hr_timestamp()
+ can be used to check whether this call is supported with a specific card.
+
+ @param dh Valid handle to a Meinberg device
+ @param *p Pointer to a ::MBG_TIME_INFO_TSTAMP variable to be filled up
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_dev_has_fast_hr_timestamp()
+ @see mbg_get_time_info_hrt()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME_INFO_TSTAMP *p ) ;
+
+ /**
+ Read the CPU affinity of a process, i.e. on which of the available
+ CPUs the process can be executed.
+
+ @param pid The process ID.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_set_process_affinity()
+ @see mbg_set_current_process_affinity_to_cpu()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ;
+
+ /**
+ Set the CPU affinity of a process, i.e. on which of the available
+ CPUs the process is allowed to be executed.
+
+ @param pid The process ID.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_get_process_affinity()
+ @see mbg_set_current_process_affinity_to_cpu()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ;
+
+ /**
+ Set the CPU affinity of a process for a single CPU only, i.e. the process
+ may only be executed on that single CPU.
+
+ @param cpu_num The number of the CPU.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_get_process_affinity()
+ @see mbg_set_process_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num ) ;
+
+ /**
+ Create a new execution thread for the current process.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up.
+ @param fnc The name of the thread function to be started.
+ @param arg A generic argument passed to the thread function.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_stop()
+ @see mbg_thread_sleep_interruptible()
+ @see mbg_thread_set_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, MBG_THREAD_FNC_RET_VAL (MBG_THREAD_FNC_ATTR *fnc)(void *), void *arg ) ;
+
+ /**
+ Stop a thread which has been created by mbg_thread_create(). Wait
+ until the thread has finished and release all resources.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_create()
+ @see mbg_thread_sleep_interruptible()
+ @see mbg_thread_set_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) ;
+
+ /**
+ Let the current thread sleep for a certain interval unless a signal is
+ received indicating the thread should terminate.
+ This function is only implemented for targets which support threads.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+ @param sleep_ms The number of milliseconds to sleep
+ @return 0 if the sleep interval has expired normally
+ 1 if a signal to terminate has been received
+ <0 if an error has occurred
+
+ @see mbg_thread_create()
+ @see mbg_thread_stop()
+ @see mbg_thread_set_affinity()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti, ulong sleep_ms ) ;
+
+ /**
+ Set the CPU affinity of a single thread, i.e. on which of the available
+ CPUs the thread is allowed to be executed.
+ This function is only implemented for targets which support thread affinity.
+
+ @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread.
+ @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs.
+
+ @return ::MBG_SUCCESS or error code returned by the system call.
+
+ @see mbg_thread_create()
+ @see mbg_thread_stop()
+ @see mbg_thread_sleep_interruptible()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_CPU_SET *p ) ;
+
+ /**
+ Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread
+ which runs the mbg_xhrt_poll_thread_fnc() function.
+ This function is only implemented for targets which support threads.
+
+ @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure.
+ @param dh the handle of the device to be polled.
+ @param freq_hz The initial cycles frequency, if known, in Hz.
+ @param sleep_ms the sleep interval for the poll thread function in ms.
+ If this parameter is 0 then the default sleep interval is used.
+
+ @return ::MBG_SUCCESS on success,
+ ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time
+ else the result of mbg_thread_create()
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_pti, MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY freq_hz, int sleep_ms ) ;
+
+ /**
+ Stop a polling thread started by mbg_xhrt_poll_thread_create()
+ and release all associated resources.
+
+ @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure.
+
+ @return the result of mbg_thread_stop()
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pti ) ;
+
+ /**
+ Retrieve a time stamp in PCPS_HR_TIME format which is extrapolated
+ using the system's current cycles counter value and a time stamp
+ plus associated cycles counter value saved by the polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+ This function is only implemented for targets which support threads.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up.
+
+ @return MBG_SUCCESS or another return value from the polling thread's IOCTL call.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_filetime()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, PCPS_HR_TIME *p_hrt ) ;
+
+ /**
+ Retrieve a time stamp in FILETIME format which is extrapolated
+ using the system's current cycles counter value and a time stamp
+ plus associated cycles counter value saved by the polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+ Since FILETIME is a Windows specific type this function is only
+ implemented under Windows.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_ft Pointer to a ::FILETIME structure to be filled up.
+
+ @return MBG_SUCCESS or another return value from the polling thread's IOCTL call.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILETIME *p_ft ) ;
+
+ /**
+ Retrieve the frequency of the system's cycles counter as determined
+ by the device polling thread.
+ See mbg_xhrt_poll_thread_fnc() for details and limitations.
+ This function is only implemented for targets which support threads.
+
+ @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread.
+ @param *p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned.
+ @return a status code from the polling thread: MBG_SUCCESS or an IOCTL error code.
+
+ @see mbg_xhrt_poll_thread_fnc()
+ @see mbg_xhrt_poll_thread_create()
+ @see mbg_xhrt_poll_thread_stop()
+ @see mbg_get_xhrt_time_as_pcps_hr_time()
+ @see mbg_get_xhrt_time_as_filetime()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_PC_CYCLES_FREQUENCY *p_freq_hz ) ;
+
+ /**
+ Retrieve the default system's cycles counter frequency from the kernel driver.
+
+ @param dh handle of the device to which the IOCTL call is sent.
+ @param *p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up.
+
+ @return ::MBG_SUCCESS or error code returned by device I/O control function.
+
+ @see mbg_get_default_cycles_frequency()
+ */
+ _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) ;
+
+ /**
+ Retrieve the default system's cycles counter frequency.
+
+ @note This may not be supported on all target platforms, in which case the
+ returned frequency is 0 and the mbg_get_default_cycles_frequency_from_dev()
+ call should be used.
+
+ @return the default cycles counter frequency in Hz, or 0 if the value is not available.
+
+ @see mbg_get_default_cycles_frequency_from_dev()
+*/
+ _MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void ) ;
+
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+static __mbg_inline
+void mbg_chk_tstamp64_leap_sec( uint64_t *tstamp64, PCPS_TIME_STATUS_X *status )
+{
+ if ( *status & ( PCPS_LS_ANN | PCPS_LS_ENB ) )
+ {
+ time_t t = (uint32_t) ( *tstamp64 >> 32 );
+ struct tm tm = *gmtime( &t );
+
+ // Handle leap second and status
+ if ( tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0 )
+ {
+ if ( *status & PCPS_LS_ANN )
+ {
+ // Set leap second enabled flag on rollover to the leap second and clear announce flag
+ *status &= ~PCPS_LS_ANN;
+ *status |= PCPS_LS_ENB;
+
+ // Decrement interpolated second to avoid automated overflow during the leap second.
+ // Second 59 appears for the second time.
+ *tstamp64 -= PCPS_HRT_BIN_FRAC_SCALE;
+ }
+ else
+ if ( *status & PCPS_LS_ENB ) // Clear bits when leap second expires and 0:00:00 UTC is reached
+ *status &= ~( PCPS_LS_ANN | PCPS_LS_ENB );
+ }
+ }
+
+} // mbg_chk_tstamp64_leap_sec
+
+#endif // defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX )
+
+
+
+static __mbg_inline
+void mbg_init_pc_cycles_frequency( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p )
+{
+ if ( *p == 0 )
+ mbg_get_default_cycles_frequency_from_dev( dh, p );
+
+} // mbg_init_pc_cycles_frequency
+
+
+
+#if MBG_TGT_HAS_64BIT_TYPES
+
+static __mbg_inline
+uint64_t pcps_time_stamp_to_uint64( const PCPS_TIME_STAMP *ts )
+{
+ return ( ( (uint64_t) ts->sec ) << 32 ) + ts->frac;
+
+} // pcps_time_stamp_to_uint64
+
+
+
+static __mbg_inline
+void uint64_to_pcps_time_stamp( PCPS_TIME_STAMP *ts, uint64_t n )
+{
+ ts->sec = (uint32_t) ( n >> 32 );
+ ts->frac = (uint32_t) ( n & 0xFFFFFFFFUL );
+
+} // uint64_to_pcps_time_stamp
+
+#endif
+
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+
+#endif /* _MBGDEVIO_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h
new file mode 100755
index 0000000..f51c61d
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h
@@ -0,0 +1,156 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgerror.h 1.4 2008/12/05 13:28:50 martin REL_M $
+ * $Name: $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Error codes used with Meinberg devices and drivers.
+ * The codes can be translated into an OS dependent error code.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgerror.h $
+ * Revision 1.4 2008/12/05 13:28:50 martin
+ * Added new code MBG_ERR_IRQ_UNSAFE.
+ * Revision 1.3 2008/02/26 14:50:14Z daniel
+ * Added codes:
+ * MBG_ERR_NOT_SUPP_ON_OS, MBG_ERR_LIB_NOT_COMPATIBLE,
+ * MBG_ERR_N_COM_EXCEEDS_SUPP, MBG_ERR_N_STR_EXCEEDS_SUPP
+ * Added doxygen compatible comments.
+ * Revision 1.2 2007/09/27 07:26:22Z martin
+ * Define STATUS_SUCCESS for Windows if not in kernel mode.
+ * Revision 1.1 2007/09/26 08:08:54Z martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _MBGERROR_H
+#define _MBGERROR_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+
+#ifdef _MBGERROR
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+/**
+ @defgroup group_error_codes Error codes
+
+ Error codes used with Meinberg devices and drivers.
+ The codes will be translated into an OS dependent error code,
+ when they are returned to the calling function.
+
+ For Windows, these codes are made positive and or'ed with 0xE0000000 afterwards.
+
+ Example: Code -19 (#MBG_ERR_GENERIC) will be converted to 0xE0000013 under Windows.
+
+ @{
+*/
+
+// Attention!!
+// These error codes below must fit exactly to the corresponding codes that are evaluated in user space.
+// For Windows, they are located in messages.mc/.h in mbgsvctl.dll
+
+#define MBG_SUCCESS PCPS_SUCCESS /**< 0, no error */
+
+// The codes below are defined in pcpsdefs.h and returned by the firmware:
+#define MBG_ERR_STIME PCPS_ERR_STIME /**< -1, invalid date/time/status passed */
+#define MBG_ERR_CFG PCPS_ERR_CFG /**< -2, invalid parms with a PCPS_CFG_GROUP cmd */
+
+// Codes returned by the driver's low level functions:
+#define MBG_ERR_GENERIC -19 /**< Generic error */
+#define MBG_ERR_TIMEOUT -20 /**< Timeout accessing the board */
+#define MBG_ERR_FW_ID -21 /**< Invalid firmware ID */
+#define MBG_ERR_NBYTES -22 /**< The number of parameter bytes
+ passed to the board did not match
+ the number of bytes expected. */
+#define MBG_ERR_INV_TIME -23 /**< The device's time is not valid */
+#define MBG_ERR_FIFO -24 /**< The device's FIFO is empty, though
+ it shouldn't be */
+#define MBG_ERR_NOT_READY -25 /**< Board is temporary unable to respond
+ (during initialization after RESET) */
+#define MBG_ERR_INV_TYPE -26 /**< Board did not recognize data type */
+
+
+// Codes returned by the driver's high level functions:
+#define MBG_ERR_NO_MEM -27 /**< Failed to allocate memory */
+#define MBG_ERR_CLAIM_RSRC -28 /**< Failed to claim port or mem resource */
+#define MBG_ERR_DEV_NOT_SUPP -29 /**< Specified device type not supported by driver */
+#define MBG_ERR_INV_DEV_REQUEST -30 /**< IOCTL call not supported by driver */
+#define MBG_ERR_NOT_SUPP_BY_DEV -31 /**< Cmd or feature not supported by device */
+#define MBG_ERR_USB_ACCESS -32 /**< USB access failed */
+#define MBG_ERR_CYCLIC_TIMEOUT -33 /**< Cyclic event (IRQ, etc.) didn't occur */
+#define MBG_ERR_NOT_SUPP_ON_OS -34 /**< The function is not supported on this operating system */
+#define MBG_ERR_LIB_NOT_COMPATIBLE -35 /**< The installed version of the DLL/shared object is not
+ compatible with version used to build the application */
+#define MBG_ERR_N_COM_EXCEEDS_SUPP -36 /**< The number of COM ports provided by the device
+ exceeds the maximum supported by the driver */
+#define MBG_ERR_N_STR_EXCEEDS_SUPP -37 /**< The number of string formats supported by the device
+ exceeds the maximum supported by the driver */
+#define MBG_ERR_IRQ_UNSAFE -38 /**< The enabled IRQs are unsafe with this firmware/ASIC version */
+
+
+// Codes used with DOS TSRs only:
+#define MBG_ERR_INV_INTNO -40 /**< Invalid interrupt number */
+#define MBG_ERR_NO_DRIVER -41 /**< A driver could not be found */
+#define MBG_ERR_DRV_VERSION -42 /**< The driver is too old */
+
+/** @} */ // endgroup
+
+// Depending on the operating system, the codes above have to be converted before
+// they are sent up to user space
+#if defined( MBG_TGT_WIN32 )
+ #if !defined( STATUS_SUCCESS ) // not in kernel mode
+ #define STATUS_SUCCESS 0
+ #endif
+
+ #define _mbg_err_to_os( _c ) \
+ ( ( _c == MBG_SUCCESS ) ? STATUS_SUCCESS : ( abs( _c ) | 0xE0000000 ) )
+#endif
+
+
+// If no specific conversion has been defined
+// then use the original codes.
+#if !defined( _mbg_err_to_os )
+ #define _mbg_err_to_os( _c ) ( _c )
+#endif
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGERROR_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h b/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h
new file mode 100755
index 0000000..0d6c1ef
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h
@@ -0,0 +1,176 @@
+
+/**************************************************************************
+ *
+ * $Id: mbggenio.h 1.5.1.3 2011/02/09 17:08:30 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions for generic port I/O.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbggenio.h $
+ * Revision 1.5.1.3 2011/02/09 17:08:30 martin
+ * Specify I/O range number when calling port I/O macros
+ * so they can be used for different ranges under BSD.
+ * Revision 1.5.1.2 2011/02/01 12:12:18 martin
+ * Revision 1.5.1.1 2011/01/31 17:29:26 martin
+ * Account for modified resource handling under *BSD.
+ * Revision 1.5 2008/12/05 13:27:33 martin
+ * Generally put macro arguments in brackets for evaluation
+ * to avoid potential side effects.
+ * There has been a problem with an improper written outp() macro
+ * in the Borland C 3.1 library's conio.h file.
+ * Support mapped I/O resources.
+ * Revision 1.4 2008/02/05 13:38:57 martin
+ * Added support for QNX.
+ * Revision 1.3 2007/03/21 14:48:56 martin
+ * Use standard inp(), outp() also under Windows since the generic
+ * Windows functions READ_PORT_UCHA(), etc., are not very
+ * compatible across DDK versions.
+ * Revision 1.2 2007/03/02 10:23:34Z martin
+ * Renamed generic port I/O macros.
+ * Fully support Linux, *BSD, Windows, NetWare, DOS, and OS/2.
+ * Revision 1.1 2006/09/20 10:47:21 martin
+ *
+ **************************************************************************/
+
+#ifndef _MBGGENIO_H
+#define _MBGGENIO_H
+
+
+/* Other headers to be included */
+
+#include <mbg_arch.h>
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined( MBG_TGT_LINUX )
+
+ #if MBG_USE_MM_IO_FOR_PCI
+ #define _mbg_inp8( _d, _i, _p ) ( readb( (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( readw( (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( readl( (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) writeb( (_v), (_p) )
+ #define _mbg_outp16( _d, _i, _p, _v ) writew( (_v), (_p) )
+ #define _mbg_outp32( _d, _i, _p, _v ) writel( (_v), (_p) )
+ #else
+ #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) inb( (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( (uint16_t) inw( (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( (uint32_t) inl( (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) outb( (_v), (_p) )
+ #define _mbg_outp16( _d, _i, _p, _v ) outw( (_v), (_p) )
+ #define _mbg_outp32( _d, _i, _p, _v ) outl( (_v), (_p) )
+ #endif
+
+#elif defined( MBG_TGT_BSD )
+
+ #include <sys/types.h>
+ #include <sys/bus.h>
+ #include <machine/bus.h>
+
+ #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) bus_space_read_1( ( (_d)->rsrc_info.port[_i].bsd.bst ), \
+ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( (uint16_t) bus_space_read_2( ( (_d)->rsrc_info.port[_i].bsd.bst ), \
+ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( (uint32_t) bus_space_read_4( ( (_d)->rsrc_info.port[_i].bsd.bst), \
+ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) bus_space_write_1( ( (_d)->rsrc_info.port[_i].bsd.bst ), \
+ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p), (_v) )
+ #define _mbg_outp16( _d, _i, _p, _v ) bus_space_write_2( ( (_d)->rsrc_info.port[_i].bsd.bst ), \
+ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p), (_v) )
+ #define _mbg_outp32( _d, _i, _p, _v ) bus_space_write_4( ( (_d)->rsrc_info.port[_i].bsd.bst ), \
+ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p), (_v) )
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) inp( (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( (uint16_t) inpw( (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( (uint32_t) inpd( (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) outp( (_p), (_v) )
+ #define _mbg_outp16( _d, _i, _p, _v ) outpw( (_p), (_v) )
+ #define _mbg_outp32( _d, _i, _p, _v ) outpd( (_p), (_v) )
+
+#elif defined( MBG_TGT_DOS ) || defined( MBG_TGT_NETWARE ) || defined( MBG_TGT_OS2 )
+
+ #include <conio.h>
+
+ #if defined( MBG_TGT_DOS ) || defined( MBG_TGT_OS2 )
+ #include <xportio.h>
+ #endif
+
+ #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) inp( (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( (uint16_t) inpw( (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( (uint32_t) inpd( (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) outp( (_p), (_v) )
+ #define _mbg_outp16( _d, _i, _p, _v ) outpw( (_p), (_v) )
+ #define _mbg_outp32( _d, _i, _p, _v ) outpd( (_p), (_v) )
+
+#elif defined( MBG_TGT_QNX )
+
+ #if defined( MBG_TGT_QNX_NTO ) // compiling for QNX Neutrino
+ // don't know if we have to distinguish between different compilers
+ #include <hw/inout.h>
+
+ // ATTENTION: mmap_device_io() must be called on non-x86 architectures
+ // to remap the ports, otherwise a segmentation fault will occur if
+ // the port I/O functions are being called.
+
+ #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) in8( (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( (uint16_t) in16( (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( (uint32_t) in32( (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) out8( (_p), (_v) )
+ #define _mbg_outp16( _d, _i, _p, _v ) out16( (_p), (_v) )
+ #define _mbg_outp32( _d, _i, _p, _v ) out32( (_p), (_v) )
+
+ #else // compiling for QNX 4
+
+ #if defined( __WATCOMC__ ) // using Watcom C
+
+ // Include prototypes of port I/O functions
+ // which should match the calls used in the mbglib functions.
+ #include <conio.h>
+
+ #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) inp( (_p) ) )
+ #define _mbg_inp16( _d, _i, _p ) ( (uint16_t) inpw( (_p) ) )
+ #define _mbg_inp32( _d, _i, _p ) ( (uint32_t) inpd( (_p) ) )
+
+ #define _mbg_outp8( _d, _i, _p, _v ) outp( (_p), (_v) )
+ #define _mbg_outp16( _d, _i, _p, _v ) outpw( (_p), (_v) )
+ #define _mbg_outp32( _d, _i, _p, _v ) outpd( (_p), (_v) )
+
+ #endif
+
+ #endif
+
+#endif
+
+
+
+#define _mbg_inp16_to_cpu( _d, _i, _p ) _mbg16_to_cpu( _mbg_inp16( (_d), (_i), (_p) ) )
+#define _mbg_inp32_to_cpu( _d, _i, _p ) _mbg32_to_cpu( _mbg_inp32( (_d), (_i), (_p) ) )
+
+#define _mbg_outp16_to_mbg( _d, _i, _p, _v ) _mbg_outp16( (_d), (_i), (_p), _cpu_to_mbg16( (_v) ) )
+#define _mbg_outp32_to_mbg( _d, _i, _p, _v ) _mbg_outp32( (_d), (_i), (_p), _cpu_to_mbg32( (_v) ) )
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#endif /* _MBGGENIO_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h b/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h
new file mode 100755
index 0000000..c375570
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h
@@ -0,0 +1,297 @@
+
+/**************************************************************************
+ *
+ * $Id: mbggeo.h 1.10 2008/09/03 14:54:28 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for mbggeo.c.
+ *
+ * Terms used:
+ *
+ * WGS84 world geodetic system of 1984
+ *
+ * XYZ WGS84 earth centered, earth fixed (ECEF) kartesian
+ * coordinates
+ *
+ * LLA longitude, latitude, altitude depending on the reference
+ * ellipsoid used.
+ *
+ * DMS degrees, minutes, seconds
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbggeo.h $
+ * Revision 1.10 2008/09/03 14:54:28 martin
+ * Added macros to swap endianess of structures.
+ * Revision 1.9 2008/01/17 09:31:33 daniel
+ * Made comments compatible for doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.8 2004/11/09 14:16:00Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Revision 1.7 2003/02/14 13:23:04Z martin
+ * Omit inclusion of mystd.h.
+ * Revision 1.6 2003/01/13 15:17:15 martin
+ * Structures were defined with default alignment which
+ * could result in different data sizes on different platforms.
+ * Revision 1.5 2002/12/18 14:46:41Z martin
+ * Removed variable USER_POS meinberg.
+ * Updated function prototypes.
+ * Revision 1.4 2002/12/12 12:04:25Z martin
+ * Moved some definitions here.
+ * Use standard file format.
+ *
+ **************************************************************************/
+
+#ifndef _MBGGEO_H
+#define _MBGGEO_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+#include <use_pack.h>
+
+#ifdef _MBGGEO
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+/**
+ Geographic longitude or latitude in [degrees, minutes, seconds]
+ longitude East latitude North and positve, South or West angles negative
+ */
+typedef struct
+{
+ uint16_t prefix; /**< 'N', 'E', 'S' or 'W' */
+ uint16_t deg; /**< [0...90 (lat) or 0...180 (lon)] */
+ uint16_t min; /**< [0...59] */
+ double sec; /**< [0...59.999] */
+} DMS;
+
+// The corresponding macro _mbg_swab_dms() is defined in gpsdefs.h.
+#define _mbg_swab_dms( _p ) \
+{ \
+ _mbg_swab16( &(_p)->prefix ); \
+ _mbg_swab16( &(_p)->deg ); \
+ _mbg_swab16( &(_p)->min ); \
+ _mbg_swab_double( &(_p)->sec ); \
+}
+
+
+
+typedef struct
+{
+ XYZ xyz; /**< always WGS84 ECEF coordinates */
+ LLA lla; /**< depending on the ellipsoid used for reference */
+ DMS longitude; /**< longitude in degrees, minutes, seconds */
+ DMS latitude; /**< latitude in degrees, minutes, seconds */
+ int16_t ellipsoid; /**< ellipsoid used for reference */
+} POS;
+
+#define _mbg_swab_pos( _p ) \
+{ \
+ _mbg_swab_xyz( (_p)->xyz ); \
+ _mbg_swab_lla( (_p)->lla ); \
+ _mbg_swab_dms( &(_p)->longitude ); \
+ _mbg_swab_dms( &(_p)->latitude ); \
+ _mbg_swab16( &(_p)->ellipsoid ); \
+}
+
+
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ char name[40];
+ POS pos; /* the position in WGS84 ECEF coords and LLA */
+ double det;
+
+
+/* The components below hold the results of intermediate terms */
+/* computed in complete_user_pos(). */
+
+/* The sin.., cos.., nt.. and ut.. variables are used to compute the */
+/* enu_dcos[] parameters of a SV structure in xyz_to_ead(). */
+
+/* The e_radius.. variables are used to compute the latitude, longitude */
+/* and altitude from ECEF coordinates in lla_to_xyz(). */
+
+ double sin_lat; /* sin( latitude ) */
+ double cos_lat; /* cos( latitude ) */
+ double sin_lon; /* sin( longitude ) */
+ double cos_lon; /* cos( longitude ) */
+
+ double nt1; /* -sin_lat * cos_lon */
+ double nt2; /* -sin_lat * sin_lon */
+ double utx; /* cos_lat * cos_lon */
+ double uty; /* cos_lat * sin_lon */
+
+ double e_radius; /* N */
+ double e_radius_alt; /* N + h */
+
+} USER_POS;
+
+
+
+typedef struct
+{
+ CSUM csum; /* checksum of the remaining bytes */
+ int16_t valid; /* flag data are valid */
+
+ char name[40];
+ XYZ dxyz; /* offset from the WGS84 ECEF coords */
+ double a; /* semi major axis */
+ double rcp_f; /* reciproke of flatness */
+
+/* the variables below will be computed in the init_mbggeo() function: */
+
+ double f; /* flatness */
+ double b; /* semi minor axis */
+ double sqr_e; /* square of numerical eccentricity */
+} ELLIPSOID;
+
+
+
+enum { WGS84, BESSEL, N_ELLIPSOIDS };
+
+_ext ELLIPSOID ellipsoid[N_ELLIPSOIDS]
+#ifdef _DO_INIT
+ = { { 0, 0,
+ "WGS 84",
+ { 0.0, 0.0, 0.0 },
+ 6378137.0,
+ 298.257223563
+ },
+
+ { 0, 0,
+ "Bessel",
+ { -128.0, 481.0, 664.0 },
+ 6377397.0,
+ 299.15
+ }
+
+ }
+#endif
+;
+
+
+/* WGS84 constants used */
+
+_ext double OMEGADOTe /* earth's rotation rate [rad/sec] */
+#ifdef _DO_INIT
+ = 7.2921151467e-5
+#endif
+;
+
+_ext double mue /* earth's gravitational constant [m^3/sec^2] */
+#ifdef _DO_INIT
+ = 3.986005e14
+#endif
+;
+
+
+
+_ext double vr_to_doppler;
+
+
+_ext double gps_pi
+#ifdef _DO_INIT
+ = 3.1415926535898
+#endif
+;
+
+_ext double gps_c0
+#ifdef _DO_INIT
+ = 2.99792458e8
+#endif
+;
+
+
+#ifndef PI
+ #define PI 3.1415926535897932
+#endif
+
+
+_ext double pi
+#ifdef _DO_INIT
+ = PI
+#endif
+;
+
+
+_ext double r2d
+#ifdef _DO_INIT
+ = 180.0 / PI
+#endif
+;
+
+
+_ext double d2r
+#ifdef _DO_INIT
+ = PI / 180.0
+#endif
+;
+
+
+/* variables for simplifying computations */
+
+_ext double gps_two_pi;
+_ext double sqrt_mue; /* sqrt( mue ) */
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void dms_to_rad( const DMS *dms, double *rad ) ;
+ void rad_to_dms( const double *rad, DMS *dms, const char prefix ) ;
+ void dms_to_lla( POS *pos ) ;
+ void lla_to_dms( POS *pos ) ;
+ void lla_to_xyz( USER_POS *pos ) ;
+ void xyz_to_lla( POS *pos, void (*cyclic_func)( void ) ) ;
+ void dms_to_xyz( USER_POS *pos ) ;
+ void setup_user_pos_from_dms( USER_POS *user ) ;
+ void setup_user_pos_from_lla( USER_POS *user ) ;
+ void setup_user_pos_from_xyz( USER_POS *user, void (*cyclic_func)( void ) ) ;
+ double distance( XYZ xyz_1, XYZ xyz_2 ) ;
+ void init_mbggeo( void ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGGEO_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h
new file mode 100755
index 0000000..e4f94f0
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h
@@ -0,0 +1,459 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgioctl.h 1.24.1.2 2011/03/22 11:19:46 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used with device driver IOCTL.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgioctl.h $
+ * Revision 1.24.1.2 2011/03/22 11:19:46 martin
+ * Use IOTYPE 'Z' under *BSD since this means passthrough on NetBSD.
+ * Revision 1.24.1.1 2011/02/15 11:21:21 daniel
+ * Added ioctls to support PTP unicast configuration
+ * Revision 1.24 2009/12/15 15:34:59Z daniel
+ * Support reading the raw IRIG data bits for firmware versions
+ * which support this feature.
+ * Revision 1.23 2009/09/29 15:08:41Z martin
+ * Support retrieving time discipline info.
+ * Revision 1.22 2009/08/17 13:48:17 martin
+ * Moved specific definition of symbol _HAVE_IOCTL_WITH_SIZE from
+ * mbgdevio.c here and renamed it to _MBG_SUPP_VAR_ACC_SIZE.
+ * Revision 1.21 2009/06/19 12:18:53 martin
+ * Added PCPS_GIVE_IRIG_TIME command and associated definitions.
+ * Fixed a declaration which might have led to syntax errors.
+ * Revision 1.20 2009/06/09 10:02:36Z daniel
+ * Support PTP configuration and state.
+ * Support simple LAN interface configuration.
+ * Revision 1.19 2009/03/19 15:17:59 martin
+ * Support reading MM timestamps without cycles.
+ * Support UTC parms and configurable time scales.
+ * For consistent naming renamed IOCTL_GET_FAST_HR_TIMESTAMP
+ * to IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES.
+ * Added IOCTL_DEV_HAS_IRIG_CTRL_BITS and IOCTL_GET_IRIG_CTRL_BITS.
+ * Revision 1.18 2008/12/11 10:32:56Z martin
+ * Added _cmd_from_ioctl_code() macro for Linux.
+ * Added IOCTL codes for .._has_asic_version() and .._has_asic_features().
+ * Added IOCTL codes for ..._is_msf(), .._is_lwr(), .._is_wwvb().
+ * Added IOCTL codes IOCTL_GET_IRQ_STAT_INFO, IOCTL_GET_CYCLES_FREQUENCY,
+ * IOCTL_HAS_FAST_HR_TIMESTAMP, and IOCTL_GET_FAST_HR_TIMESTAMP.
+ * Revision 1.17 2008/01/17 09:35:15 daniel
+ * Added ioctl calls IOCTL_GET_MAPPED_MEM_ADDR and
+ * IOCTL_UNMAP_MAPPED_MEM.
+ * Cleanup for PCI ASIC version and features.
+ * Revision 1.16 2007/09/25 10:37:04Z martin
+ * Added macro _cmd_from_ioctl_code() for Windows.
+ * Revision 1.15 2007/05/21 15:00:01Z martin
+ * Unified naming convention for symbols related to ref_offs.
+ * Revision 1.14 2007/03/02 10:27:03 martin
+ * Preliminary support for *BSD.
+ * Preliminary _cmd_from_ioctl().
+ * Revision 1.13 2006/03/10 10:36:54 martin
+ * Added support for programmable pulse outputs.
+ * Revision 1.12 2005/06/02 10:22:05Z martin
+ * Added IOCTL code IOCTL_GET_SYNTH_STATE.
+ * Added IOCTL codes IOCTL_DEV_HAS_GENERIC_IO,
+ * IOCTL_PCPS_GENERIC_IO, and IOCTL_GET_SYNTH_STATE.
+ * Revision 1.11 2005/01/14 10:21:11Z martin
+ * Added IOCTLs which query device features.
+ * Revision 1.10 2004/12/09 11:03:36Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.9 2004/11/09 12:49:41Z martin
+ * Modifications were required in order to be able to configure IRIG
+ * settings of cards which provide both IRIG input and output.
+ * The existing codes have been renamed with .._RX.. and are used to
+ * configure the IRIG receiver (input). New codes have been defined
+ * used to configure the IRIG transmitter.
+ * Renamed IOCTL_GET_GPS_STAT to IOCTL_GET_GPS_BVAR_STAT.
+ * Use more specific data types than generic types.
+ * Modified IOCTL codes used for hardware debugging.
+ * Revision 1.8 2004/09/06 15:46:04Z martin
+ * Changed definition of IOCTL codes to support syntax used
+ * with Linux kernel 2.6.x.
+ * Account for renamed symbols.
+ * Revision 1.7 2004/04/07 10:08:11 martin
+ * Added IOCTL codes used to trigger hardware debug events.
+ * Revision 1.6 2003/12/22 15:37:18Z martin
+ * Added codes to read ASIC version, and read times
+ * with associated cycle counter values.
+ * Revision 1.5 2003/06/19 09:02:30Z martin
+ * New codes IOCTL_GET_PCPS_UCAP_ENTRIES and IOCTL_GET_PCPS_UCAP_EVENT.
+ * Renamed IOCTL_PCPS_CLR_CAP_BUFF to IOCTL_PCPS_CLR_UCAP_BUFF.
+ * Cleaned up IOCTL code names related to PCPS_TZDL.
+ * Reordered upper IOCTL code numbers again.
+ * Revision 1.4 2003/04/09 13:50:39Z martin
+ * Re-organized IOCTL codes.
+ * Supports Win32.
+ * Added missing pragma pack().
+ * Revision 1.3 2003/02/14 13:20:08Z martin
+ * Include mbggeo.h instead of mygeo.h.
+ * Revision 1.2 2001/11/30 09:52:48 martin
+ * Added support for event_time which, however, requires
+ * a custom GPS firmware.
+ * Revision 1.1 2001/03/05 16:34:22 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBGIOCTL_H
+#define _MBGIOCTL_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <pcpsdev.h>
+#include <mbggeo.h>
+#include <use_pack.h>
+
+#if defined( MBG_TGT_LINUX )
+
+ #include <linux/ioctl.h>
+
+ // a magic number used to generate IOCTL cmd codes
+ #define IOTYPE 'M'
+
+ #define _MBG_IO _IO
+ #define _MBG_IOR _IOR
+ #define _MBG_IOW _IOW
+
+ #define _cmd_from_ioctl_code( _ioc ) \
+ _IOC_NR( _ioc )
+
+#elif defined( MBG_TGT_BSD )
+
+ #include <sys/ioccom.h>
+
+ // Under NetBSD 'Z' marks passthrough IOCTLs, under FreeBSD the code
+ // does not seem to matter, so we use 'Z' anyway.
+ #define IOTYPE 'Z'
+
+ #define _MBG_IO _IO
+ #define _MBG_IOR _IOR
+ #define _MBG_IOW _IOW
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #if !defined( _MBG_SUPP_VAR_ACC_SIZE )
+ // Windows supports IOCTL commands where the sizes of
+ // input and output buffer can be specified dynamically.
+ #define _MBG_SUPP_VAR_ACC_SIZE 1
+ #endif
+
+ #ifndef _KDD_ // must be defined in the KDDs' SOURCES file
+ #include <windows.h>
+ #include <winioctl.h>
+ #endif
+
+ #if !defined( MBG_TGT_WIN32_NON_PNP )
+ #ifdef _MBGIOCTL
+ #include <initguid.h> // instance the GUID
+ #else
+ #include <guiddef.h> // just define the GUID
+ #endif
+ #endif
+
+ #ifdef DEFINE_GUID // don't break compiles of drivers that
+ // include this header but don't want the
+ // GUIDs
+
+ // ClassGuid = { 78A1C341-4539-11d3-B88D-00C04FAD5171 }
+ DEFINE_GUID( GUID_MEINBERG_DEVICE,
+ 0x78A1C341L, 0x4539, 0x11D3,
+ 0xB8, 0x8D, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71 );
+ #endif
+
+ // Device type in the "User Defined" range."
+ #define PCPS_TYPE 40000
+
+ // IOCTL function codes from 0x800 to 0xFFF are for customer use.
+ #define _MBG_IOCTL_BIAS 0x930
+
+ #define _MBG_IO( _t, _n ) \
+ CTL_CODE( PCPS_TYPE, _MBG_IOCTL_BIAS + _n, METHOD_BUFFERED, FILE_READ_ACCESS )
+
+ #define _MBG_IOR( _t, _n, _sz ) \
+ _MBG_IO( _t, _n )
+
+ #define _MBG_IOW _MBG_IOR
+
+ #define _cmd_from_ioctl_code( _ioc ) \
+ ( ( ( (_ioc) >> 2 ) & 0x0FFF ) - _MBG_IOCTL_BIAS )
+
+#endif
+
+
+#if !defined( _MBG_SUPP_VAR_ACC_SIZE )
+ // Many operating systems don't support specifying the sizes of IOCTL
+ // input and output buffers dynamically, so we disable this by default.
+ #define _MBG_SUPP_VAR_ACC_SIZE 0
+#endif
+
+
+#ifdef _MBGIOCTL
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+/* Start of header body */
+
+// read general driver info, device info, and status port
+#define IOCTL_GET_PCPS_DRVR_INFO _MBG_IOR( IOTYPE, 0x00, PCPS_DRVR_INFO )
+#define IOCTL_GET_PCPS_DEV _MBG_IOR( IOTYPE, 0x01, PCPS_DEV )
+#define IOCTL_GET_PCPS_STATUS_PORT _MBG_IOR( IOTYPE, 0x02, PCPS_STATUS_PORT )
+
+// generic read/write operations (preliminary)
+#define IOCTL_PCPS_GENERIC_READ _MBG_IO( IOTYPE, 0x03 )
+#define IOCTL_PCPS_GENERIC_WRITE _MBG_IO( IOTYPE, 0x04 )
+#define IOCTL_PCPS_GENERIC_READ_GPS _MBG_IO( IOTYPE, 0x05 )
+#define IOCTL_PCPS_GENERIC_WRITE_GPS _MBG_IO( IOTYPE, 0x06 )
+
+// normal direct read/write operations
+#define IOCTL_GET_PCPS_TIME _MBG_IOR( IOTYPE, 0x10, PCPS_TIME )
+#define IOCTL_SET_PCPS_TIME _MBG_IOW( IOTYPE, 0x11, PCPS_STIME )
+
+#define IOCTL_GET_PCPS_SYNC_TIME _MBG_IOR( IOTYPE, 0x12, PCPS_TIME )
+
+#define IOCTL_GET_PCPS_TIME_SEC_CHANGE _MBG_IOR( IOTYPE, 0x13, PCPS_TIME )
+
+#define IOCTL_GET_PCPS_HR_TIME _MBG_IOR( IOTYPE, 0x14, PCPS_HR_TIME )
+
+// the next one is supported with custom GPS firmware only:
+#define IOCTL_SET_PCPS_EVENT_TIME _MBG_IOW( IOTYPE, 0x15, PCPS_TIME_STAMP )
+
+#define IOCTL_GET_PCPS_SERIAL _MBG_IOR( IOTYPE, 0x16, PCPS_SERIAL )
+#define IOCTL_SET_PCPS_SERIAL _MBG_IOW( IOTYPE, 0x17, PCPS_SERIAL )
+
+#define IOCTL_GET_PCPS_TZCODE _MBG_IOR( IOTYPE, 0x18, PCPS_TZCODE )
+#define IOCTL_SET_PCPS_TZCODE _MBG_IOW( IOTYPE, 0x19, PCPS_TZCODE )
+
+#define IOCTL_GET_PCPS_TZDL _MBG_IOR( IOTYPE, 0x1A, PCPS_TZDL )
+#define IOCTL_SET_PCPS_TZDL _MBG_IOW( IOTYPE, 0x1B, PCPS_TZDL )
+
+#define IOCTL_GET_REF_OFFS _MBG_IOR( IOTYPE, 0x1C, MBG_REF_OFFS )
+#define IOCTL_SET_REF_OFFS _MBG_IOW( IOTYPE, 0x1D, MBG_REF_OFFS )
+
+#define IOCTL_GET_MBG_OPT_INFO _MBG_IOR( IOTYPE, 0x1E, MBG_OPT_INFO )
+#define IOCTL_SET_MBG_OPT_SETTINGS _MBG_IOW( IOTYPE, 0x1F, MBG_OPT_SETTINGS )
+
+#define IOCTL_GET_PCPS_IRIG_RX_INFO _MBG_IOR( IOTYPE, 0x20, IRIG_INFO )
+#define IOCTL_SET_PCPS_IRIG_RX_SETTINGS _MBG_IOW( IOTYPE, 0x21, IRIG_SETTINGS )
+
+#define IOCTL_PCPS_CLR_UCAP_BUFF _MBG_IO( IOTYPE, 0x22 )
+#define IOCTL_GET_PCPS_UCAP_ENTRIES _MBG_IOR( IOTYPE, 0x23, PCPS_UCAP_ENTRIES )
+#define IOCTL_GET_PCPS_UCAP_EVENT _MBG_IOR( IOTYPE, 0x24, PCPS_HR_TIME )
+
+
+#define IOCTL_GET_GPS_TZDL _MBG_IOR( IOTYPE, 0x25, TZDL )
+#define IOCTL_SET_GPS_TZDL _MBG_IOW( IOTYPE, 0x26, TZDL )
+
+#define IOCTL_GET_GPS_SW_REV _MBG_IOR( IOTYPE, 0x27, SW_REV )
+
+#define IOCTL_GET_GPS_BVAR_STAT _MBG_IOR( IOTYPE, 0x28, BVAR_STAT )
+
+#define IOCTL_GET_GPS_TIME _MBG_IOR( IOTYPE, 0x29, TTM )
+#define IOCTL_SET_GPS_TIME _MBG_IOW( IOTYPE, 0x2A, TTM )
+
+#define IOCTL_GET_GPS_PORT_PARM _MBG_IOR( IOTYPE, 0x2B, PORT_PARM )
+#define IOCTL_SET_GPS_PORT_PARM _MBG_IOW( IOTYPE, 0x2C, PORT_PARM )
+
+#define IOCTL_GET_GPS_ANT_INFO _MBG_IOR( IOTYPE, 0x2D, ANT_INFO )
+
+#define IOCTL_GET_GPS_UCAP _MBG_IOR( IOTYPE, 0x2E, TTM )
+
+#define IOCTL_GET_GPS_ENABLE_FLAGS _MBG_IOR( IOTYPE, 0x2F, ENABLE_FLAGS )
+#define IOCTL_SET_GPS_ENABLE_FLAGS _MBG_IOW( IOTYPE, 0x30, ENABLE_FLAGS )
+
+#define IOCTL_GET_GPS_STAT_INFO _MBG_IOR( IOTYPE, 0x31, STAT_INFO )
+
+#define IOCTL_SET_GPS_CMD _MBG_IOW( IOTYPE, 0x32, GPS_CMD )
+
+#define IOCTL_GET_GPS_IDENT _MBG_IOR( IOTYPE, 0x33, IDENT )
+
+#define IOCTL_GET_GPS_POS _MBG_IOR( IOTYPE, 0x34, POS )
+#define IOCTL_SET_GPS_POS_XYZ _MBG_IOW( IOTYPE, 0x35, XYZ )
+#define IOCTL_SET_GPS_POS_LLA _MBG_IOW( IOTYPE, 0x36, LLA )
+
+#define IOCTL_GET_GPS_ANT_CABLE_LEN _MBG_IOR( IOTYPE, 0x37, ANT_CABLE_LEN )
+#define IOCTL_SET_GPS_ANT_CABLE_LEN _MBG_IOW( IOTYPE, 0x38, ANT_CABLE_LEN )
+
+#define IOCTL_GET_GPS_RECEIVER_INFO _MBG_IOR( IOTYPE, 0x39, RECEIVER_INFO )
+#define IOCTL_GET_GPS_ALL_STR_TYPE_INFO _MBG_IO( IOTYPE, 0x3A ) // size variable
+#define IOCTL_GET_GPS_ALL_PORT_INFO _MBG_IO( IOTYPE, 0x3B ) // size variable
+
+#define IOCTL_SET_GPS_PORT_SETTINGS_IDX _MBG_IOW( IOTYPE, 0x3C, PORT_SETTINGS_IDX )
+
+#define IOCTL_GET_PCI_ASIC_VERSION _MBG_IOR( IOTYPE, 0x3D, PCI_ASIC_VERSION )
+
+#define IOCTL_GET_PCPS_TIME_CYCLES _MBG_IOR( IOTYPE, 0x3E, PCPS_TIME_CYCLES )
+#define IOCTL_GET_PCPS_HR_TIME_CYCLES _MBG_IOR( IOTYPE, 0x3F, PCPS_HR_TIME_CYCLES )
+
+#define IOCTL_GET_PCPS_IRIG_TX_INFO _MBG_IOR( IOTYPE, 0x40, IRIG_INFO )
+#define IOCTL_SET_PCPS_IRIG_TX_SETTINGS _MBG_IOW( IOTYPE, 0x41, IRIG_SETTINGS )
+
+#define IOCTL_GET_SYNTH _MBG_IOR( IOTYPE, 0x42, SYNTH )
+#define IOCTL_SET_SYNTH _MBG_IOW( IOTYPE, 0x43, SYNTH )
+
+
+#define IOCTL_DEV_IS_GPS _MBG_IOR( IOTYPE, 0x44, int )
+#define IOCTL_DEV_IS_DCF _MBG_IOR( IOTYPE, 0x45, int )
+#define IOCTL_DEV_IS_IRIG_RX _MBG_IOR( IOTYPE, 0x46, int )
+
+#define IOCTL_DEV_HAS_HR_TIME _MBG_IOR( IOTYPE, 0x47, int )
+#define IOCTL_DEV_HAS_CAB_LEN _MBG_IOR( IOTYPE, 0x48, int )
+#define IOCTL_DEV_HAS_TZDL _MBG_IOR( IOTYPE, 0x49, int )
+#define IOCTL_DEV_HAS_PCPS_TZDL _MBG_IOR( IOTYPE, 0x4A, int )
+#define IOCTL_DEV_HAS_TZCODE _MBG_IOR( IOTYPE, 0x4B, int )
+#define IOCTL_DEV_HAS_TZ _MBG_IOR( IOTYPE, 0x4C, int )
+#define IOCTL_DEV_HAS_EVENT_TIME _MBG_IOR( IOTYPE, 0x4D, int )
+#define IOCTL_DEV_HAS_RECEIVER_INFO _MBG_IOR( IOTYPE, 0x4E, int )
+#define IOCTL_DEV_CAN_CLR_UCAP_BUFF _MBG_IOR( IOTYPE, 0x4F, int )
+#define IOCTL_DEV_HAS_UCAP _MBG_IOR( IOTYPE, 0x50, int )
+#define IOCTL_DEV_HAS_IRIG_TX _MBG_IOR( IOTYPE, 0x51, int )
+#define IOCTL_DEV_HAS_SERIAL_HS _MBG_IOR( IOTYPE, 0x52, int )
+#define IOCTL_DEV_HAS_SIGNAL _MBG_IOR( IOTYPE, 0x53, int )
+#define IOCTL_DEV_HAS_MOD _MBG_IOR( IOTYPE, 0x54, int )
+#define IOCTL_DEV_HAS_IRIG _MBG_IOR( IOTYPE, 0x55, int )
+#define IOCTL_DEV_HAS_REF_OFFS _MBG_IOR( IOTYPE, 0x56, int )
+#define IOCTL_DEV_HAS_OPT_FLAGS _MBG_IOR( IOTYPE, 0x57, int )
+#define IOCTL_DEV_HAS_GPS_DATA _MBG_IOR( IOTYPE, 0x58, int )
+#define IOCTL_DEV_HAS_SYNTH _MBG_IOR( IOTYPE, 0x59, int )
+#define IOCTL_DEV_HAS_GENERIC_IO _MBG_IOR( IOTYPE, 0x5A, int )
+
+#define IOCTL_PCPS_GENERIC_IO _MBG_IO( IOTYPE, 0x5B )
+
+#define IOCTL_GET_SYNTH_STATE _MBG_IOR( IOTYPE, 0x5C, SYNTH_STATE )
+
+#define IOCTL_GET_GPS_ALL_POUT_INFO _MBG_IO( IOTYPE, 0x5D ) // size variable
+#define IOCTL_SET_GPS_POUT_SETTINGS_IDX _MBG_IOW( IOTYPE, 0x5E, POUT_SETTINGS_IDX )
+
+#define IOCTL_GET_MAPPED_MEM_ADDR _MBG_IOR( IOTYPE, 0x5F, PCPS_MAPPED_MEM )
+#define IOCTL_UNMAP_MAPPED_MEM _MBG_IOR( IOTYPE, 0x60, PCPS_MAPPED_MEM )
+
+#define IOCTL_GET_PCI_ASIC_FEATURES _MBG_IOR( IOTYPE, 0x61, PCI_ASIC_FEATURES )
+
+#define IOCTL_HAS_PCI_ASIC_FEATURES _MBG_IOR( IOTYPE, 0x62, int )
+#define IOCTL_HAS_PCI_ASIC_VERSION _MBG_IOR( IOTYPE, 0x63, int )
+
+#define IOCTL_DEV_IS_MSF _MBG_IOR( IOTYPE, 0x64, int )
+#define IOCTL_DEV_IS_LWR _MBG_IOR( IOTYPE, 0x65, int )
+#define IOCTL_DEV_IS_WWVB _MBG_IOR( IOTYPE, 0x66, int )
+
+#define IOCTL_GET_IRQ_STAT_INFO _MBG_IOR( IOTYPE, 0x67, PCPS_IRQ_STAT_INFO )
+#define IOCTL_GET_CYCLES_FREQUENCY _MBG_IOR( IOTYPE, 0x68, MBG_PC_CYCLES_FREQUENCY )
+
+#define IOCTL_HAS_FAST_HR_TIMESTAMP _MBG_IOR( IOTYPE, 0x69, int )
+#define IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES _MBG_IOR( IOTYPE, 0x6A, PCPS_TIME_STAMP_CYCLES )
+#define IOCTL_GET_FAST_HR_TIMESTAMP _MBG_IOR( IOTYPE, 0x6B, PCPS_TIME_STAMP )
+
+#define IOCTL_DEV_HAS_GPS_TIME_SCALE _MBG_IOR( IOTYPE, 0x6C, int )
+#define IOCTL_GET_GPS_TIME_SCALE_INFO _MBG_IOR( IOTYPE, 0x6D, MBG_TIME_SCALE_INFO )
+#define IOCTL_SET_GPS_TIME_SCALE_SETTINGS _MBG_IOW( IOTYPE, 0x6E, MBG_TIME_SCALE_SETTINGS )
+
+#define IOCTL_DEV_HAS_GPS_UTC_PARM _MBG_IOR( IOTYPE, 0x6F, int )
+#define IOCTL_GET_GPS_UTC_PARM _MBG_IOR( IOTYPE, 0x70, UTC )
+#define IOCTL_SET_GPS_UTC_PARM _MBG_IOW( IOTYPE, 0x71, UTC )
+
+#define IOCTL_DEV_HAS_IRIG_CTRL_BITS _MBG_IOR( IOTYPE, 0x72, int )
+#define IOCTL_GET_IRIG_CTRL_BITS _MBG_IOR( IOTYPE, 0x73, MBG_IRIG_CTRL_BITS )
+
+#define IOCTL_DEV_HAS_LAN_INTF _MBG_IOR( IOTYPE, 0x74, int )
+#define IOCTL_GET_LAN_IF_INFO _MBG_IOR( IOTYPE, 0x75, LAN_IF_INFO )
+#define IOCTL_GET_IP4_STATE _MBG_IOR( IOTYPE, 0x76, IP4_SETTINGS )
+#define IOCTL_GET_IP4_SETTINGS _MBG_IOR( IOTYPE, 0x77, IP4_SETTINGS )
+#define IOCTL_SET_IP4_SETTINGS _MBG_IOW( IOTYPE, 0x78, IP4_SETTINGS )
+
+#define IOCTL_DEV_IS_PTP _MBG_IOR( IOTYPE, 0x79, int )
+#define IOCTL_DEV_HAS_PTP _MBG_IOR( IOTYPE, 0x7A, int )
+#define IOCTL_GET_PTP_STATE _MBG_IOR( IOTYPE, 0x7B, PTP_STATE )
+#define IOCTL_GET_PTP_CFG_INFO _MBG_IOR( IOTYPE, 0x7C, PTP_CFG_INFO )
+#define IOCTL_SET_PTP_CFG_SETTINGS _MBG_IOW( IOTYPE, 0x7D, PTP_CFG_SETTINGS )
+
+#define IOCTL_DEV_HAS_IRIG_TIME _MBG_IOR( IOTYPE, 0x7E, int )
+#define IOCTL_GET_IRIG_TIME _MBG_IOR( IOTYPE, 0x7F, PCPS_IRIG_TIME )
+
+#define IOCTL_GET_TIME_INFO_HRT _MBG_IOR( IOTYPE, 0x80, MBG_TIME_INFO_HRT )
+#define IOCTL_GET_TIME_INFO_TSTAMP _MBG_IOR( IOTYPE, 0x81, MBG_TIME_INFO_TSTAMP )
+
+#define IOCTL_DEV_HAS_RAW_IRIG_DATA _MBG_IOR( IOTYPE, 0x82, int )
+#define IOCTL_GET_RAW_IRIG_DATA _MBG_IOR( IOTYPE, 0x83, MBG_RAW_IRIG_DATA )
+
+#define IOCTL_DEV_HAS_PTP_UNICAST _MBG_IOR( IOTYPE, 0x84, int )
+#define IOCTL_GET_PTP_UNICAST_CFG_INFO _MBG_IOR( IOTYPE, 0x85, PTP_UNICAST_CFG_INFO )
+#define IOCTL_SET_PTP_UNICAST_CFG_SETTINGS _MBG_IOW( IOTYPE, 0x86, PTP_UNICAST_CFG_SETTINGS )
+
+// The codes below are subject to changes without notice. They may be supported
+// by some kernel drivers, but usage is restricted to Meinberg software development.
+// Unrestricted usage may cause system malfunction !!
+#define IOCTL_MBG_DBG_GET_PORT_ADDR _MBG_IOR( IOTYPE, 0xF0, uint16_t )
+#define IOCTL_MBG_DBG_SET_PORT_ADDR _MBG_IOW( IOTYPE, 0xF1, uint16_t )
+#define IOCTL_MBG_DBG_SET_BIT _MBG_IOW( IOTYPE, 0xF2, uint8_t )
+#define IOCTL_MBG_DBG_CLR_BIT _MBG_IOW( IOTYPE, 0xF3, uint8_t )
+#define IOCTL_MBG_DBG_CLR_ALL _MBG_IO( IOTYPE, 0xF4 )
+
+
+#if !defined( _cmd_from_ioctl_code )
+ #define _cmd_from_ioctl_code( _ioctl_code ) _ioctl_code
+#endif
+
+
+
+// The structure below is used by the IOCTL_PCPS_GENERIC_... calls.
+typedef struct
+{
+ uint32_t info;
+ uint32_t data_size_in;
+ uint32_t data_size_out;
+} IOCTL_GENERIC_CTL;
+
+
+typedef struct
+{
+ IOCTL_GENERIC_CTL ctl;
+ uint8_t data[1];
+} IOCTL_GENERIC_BUFFER;
+
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack()
+#endif
+
+#endif /* _MBGIOCTL_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c
new file mode 100755
index 0000000..3285b73
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c
@@ -0,0 +1,117 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgmktm.c 1.1 2006/08/22 08:57:15 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Function to convert broken down time to Unix time (seconds since 1970)
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgmktm.c $
+ * Revision 1.1 2006/08/22 08:57:15 martin
+ * Former function totalsec() moved here from pcpsmktm.c.
+ *
+ **************************************************************************/
+
+#define _MBGMKTM
+ #include <mbgmktm.h>
+#undef _MBGMKTM
+
+#include <sys/types.h>
+
+
+static const char Days[12] =
+{
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static int YDays[12] =
+{
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+
+/*--------------------------------------------------------------
+ * Name: mbg_mktime()
+ *
+ * Purpose: This function works like the standard mktime()
+ * function but does not account for a timezone
+ * setting configured for the standard C library.
+ * Also, it does not take a structure but a set
+ * of variables which makes it more versatile.
+ * The accepted variables are in the same ranges
+ * as the struct tm members used by mktime().
+ *
+ * Input: int year year - 1900
+ * int month months since January, 0..11
+ * int day days after 1st, 0..30
+ * int hour 0..23
+ * int min 0..59
+ * int sec 0..59, 60 if leap second
+ *
+ * Output: --
+ *
+ * Ret value: seconds since 1970 (Unix time_t format)
+ * or -1 if range overflow
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+long mbg_mktime( int year, int month, int day,
+ int hour, int min, int sec )
+{
+ int leaps;
+ long days;
+ long secs;
+
+
+ if ( year < 70 || year > 138 )
+ return ( -1 );
+
+ min += sec / 60;
+ sec %= 60; /* Seconds are normalized */
+ hour += min / 60;
+ min %= 60; /* Minutes are normalized */
+ day += hour / 24;
+ hour %= 24; /* Hours are normalized */
+
+ year += month / 12; /* Normalize month (not necessarily final) */
+ month %= 12;
+
+ while ( day >= Days[month] )
+ {
+ if ( !( year & 3 ) && ( month == 1 ) )
+ {
+ if (day > 28)
+ {
+ day -= 29;
+ month++;
+ }
+ else
+ break;
+ }
+ else
+ {
+ day -= Days[month];
+ month++;
+ }
+
+ year += month / 12; /* Normalize month */
+ month %= 12;
+ }
+
+ year -= 70;
+ leaps = ( year + 2 ) / 4;
+
+ if ( !( ( year + 70 ) & 3 ) && ( month < 2 ) )
+ --leaps;
+
+ days = year * 365L + leaps + YDays[month] + day;
+
+ secs = days * 86400L + hour * 3600L + min * 60L + sec;
+
+ return( secs > 0 ? secs : -1 );
+
+} // mbg_mktime
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h
new file mode 100755
index 0000000..2aada2a
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h
@@ -0,0 +1,57 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgmktm.h 1.1 2006/08/22 08:57:15 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for mbgmktm.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgmktm.h $
+ * Revision 1.1 2006/08/22 08:57:15 martin
+ * Former function totalsec() moved here from pcpsmktm.c.
+ *
+ **************************************************************************/
+
+#ifndef _MBGMKTM_H
+#define _MBGMKTM_H
+
+
+/* Other headers to be included */
+
+#ifdef _MBGMKTM
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+long mbg_mktime( int year, int month, int day, int hour, int min, int sec ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _MBGMKTM_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h
new file mode 100755
index 0000000..c7ab670
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h
@@ -0,0 +1,322 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgtime.h 1.17.1.4 2011/02/09 15:46:48 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for mbgtime.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgtime.h $
+ * Revision 1.17.1.4 2011/02/09 15:46:48 martin
+ * Revision 1.17.1.3 2011/01/24 17:09:20 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.17.1.2 2010/08/13 11:57:13 martin
+ * Revision 1.17.1.1 2010/08/13 11:39:20Z martin
+ * Revision 1.17 2010/08/06 13:03:03 martin
+ * Removed obsolete code.
+ * Revision 1.16 2010/07/16 10:22:07Z martin
+ * Moved definitions of HNS_PER_SEC and HNS_PER_MS here.
+ * Conditionally define FILETIME_1970.
+ * Defined MASK_CLOCK_T for ARM/Cortex.
+ * Revision 1.15 2009/10/23 09:55:21 martin
+ * Added MJD numbers for commonly used epochs.
+ * Revision 1.14 2009/08/12 10:28:12 daniel
+ * Added definition NSECS_PER_SEC.
+ * Revision 1.13 2009/06/12 13:31:44Z martin
+ * Fix build errors with arm-linux-gcc.
+ * Revision 1.12 2009/03/27 14:14:00 martin
+ * Cleanup for CVI.
+ * Revision 1.11 2009/03/13 09:30:06Z martin
+ * Include mystd.h in mbgtime.c rather than here. The bit type used
+ * here is now defined in words.h.
+ * Updated comments for GPS_SEC_BIAS.
+ * Revision 1.10 2008/12/11 10:45:41Z martin
+ * Added clock_t mask for gcc (GnuC).
+ * Revision 1.9 2006/08/25 09:33:46Z martin
+ * Updated function prototypes.
+ * Revision 1.8 2004/12/28 11:29:02Z martin
+ * Added macro _n_days.
+ * Updated function prototypes.
+ * Revision 1.7 2002/09/06 07:15:48Z martin
+ * Added MASK_CLOCK_T for Linux.
+ * Revision 1.6 2002/02/25 08:37:44 Andre
+ * definition MASK_CLOCK_T for ARM added
+ * Revision 1.5 2001/03/02 10:18:10Z MARTIN
+ * Added MASK_CLOCK_T for Watcom C.
+ * Revision 1.4 2000/09/15 07:57:53 MARTIN
+ * Removed outdated function prototypes.
+ * Revision 1.3 2000/07/21 14:05:18 MARTIN
+ * Defined some new constants.
+ *
+ **************************************************************************/
+
+#ifndef _MBGTIME_H
+#define _MBGTIME_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+
+#if !defined( MBG_ARCH_ARM ) && \
+ !defined( MBG_TGT_KERNEL )
+ #include <time.h>
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _MBGTIME
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+// The Unix time_t epoche is usually 1970-01-01 00:00 whereas
+// the GPS epoche is 1980-01-06 00:00, so the difference is 10 years,
+// plus 2 days due to leap years (1972 and 1976), plus the difference
+// of the day-of-month (6 - 1).
+#define GPS_SEC_BIAS 315964800UL // ( ( ( 10UL * 365UL ) + 2 + 5 ) * SECS_PER_DAY )
+
+// time_t t = ( gps_week * SECS_PER_WEEK ) + sec_of_week + GPS_SEC_BIAS
+
+
+// Modified Julian Day (MJD) numbers for some commonly used epochs.
+// To compute the MJD for a given date just compute the days since epoch
+// and add the constant number of days according to the epoch, e.g.:
+// current_unix_mjd = ( time( NULL ) / SECS_PER_DAY ) + MJD_AT_UNIX_EPOCH;
+#define MJD_AT_GPS_EPOCH 44244UL // MJD at 1980-01-06
+#define MJD_AT_UNIX_EPOCH 40587UL // MJD at 1970-01-01
+#define MJD_AT_NTP_EPOCH 40587UL // MJD at 1900-01-01
+
+
+// The constant below defines the Windows FILETIME number (100 ns intervals
+// since 1601-01-01) for 1970-01-01, which is usually the epoche for the time_t
+// type used by the standard C library.
+#if !defined( FILETIME_1970 )
+ // FILETIME represents a 64 bit number, so we need to defined the
+ // constant with an appendix depending on the compiler.
+ #if MBG_TGT_C99 || defined( __GNUC__ )
+ // syntax introduced by C99 standard
+ #define FILETIME_1970 0x019db1ded53e8000ULL // Epoch offset from FILETIME to UNIX
+ #elif defined( MBG_TGT_WIN32 )
+ // MSC-specific syntax
+ #define FILETIME_1970 0x019db1ded53e8000ui64
+ #endif
+#endif
+
+
+#if defined( _C166 )
+ #if _C166 >= 50
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+ #else
+ #define MASK_CLOCK_T 0x7FFF /* time.h not shipped with compiler */
+ #endif
+#endif
+
+#if defined( __WATCOMC__ )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( _CVI ) || defined( _CVI_ )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( _MSC_VER )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( __NETWARE_386__ )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( __ARM )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+#endif
+
+#if defined( __ARMCC_VERSION )
+ #define MASK_CLOCK_T ( ( (ulong) (clock_t) -1 ) >> 1 )
+#endif
+
+#if defined( __GNUC__ )
+ #if defined( __linux )
+ #define MASK_CLOCK_T ( ( (ulong) (clock_t) -1 ) >> 1 )
+ #else // Windows / MinGW
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+ #endif
+#endif
+
+
+#if !defined( MASK_CLOCK_T )
+ #if sizeof( clock_t ) == sizeof( short )
+ #define MASK_CLOCK_T 0x7FFF
+ #elif sizeof( clock_t ) == sizeof( long )
+ #define MASK_CLOCK_T 0x7FFFFFFFL
+ #endif
+#endif
+
+typedef struct
+{
+ clock_t start;
+ clock_t stop;
+ short is_set;
+} TIMEOUT;
+
+
+#define DAYS_PER_WEEK 7
+
+#define SECS_PER_MIN 60
+#define MINS_PER_HOUR 60
+#define HOURS_PER_DAY 24
+#define DAYS_PER_WEEK 7
+
+#define MINS_PER_DAY ( MINS_PER_HOUR * HOURS_PER_DAY )
+
+#define SECS_PER_HOUR 3600
+#define SECS_PER_DAY 86400L
+#define SECS_PER_WEEK 604800L
+
+#define SEC100S_PER_SEC 100L
+#define SEC100S_PER_MIN ( SEC100S_PER_SEC * SECS_PER_MIN )
+#define SEC100S_PER_HOUR ( SEC100S_PER_SEC * SECS_PER_HOUR )
+#define SEC100S_PER_DAY ( SEC100S_PER_SEC * SECS_PER_DAY )
+
+#if !defined( MSEC_PER_SEC )
+ #define MSEC_PER_SEC 1000L
+#endif
+
+#define MSEC_PER_MIN ( MSEC_PER_SEC * SECS_PER_MIN )
+#define MSEC_PER_HOUR ( MSEC_PER_SEC * SECS_PER_HOUR )
+#define MSEC_PER_DAY ( MSEC_PER_SEC * SECS_PER_DAY )
+
+#define NSECS_PER_SEC 1000000000UL
+
+#if !defined( HNS_PER_SEC )
+ #define HNS_PER_SEC 10000000UL
+#endif
+
+#if !defined( HNS_PER_MS )
+ #define HNS_PER_MS 10000UL
+#endif
+
+
+
+_ext TM_GPS dhms;
+_ext TM_GPS datum;
+
+
+_ext const char *short_time_fmt
+#ifdef _MBGTIME
+ = "%2i:%02i"
+#endif
+;
+
+_ext const char *time_fmt
+#ifdef _MBGTIME
+ = "%2i:%02i:%02i"
+#endif
+;
+
+_ext const char *long_time_fmt
+#ifdef _MBGTIME
+ = "%2i:%02i:%02i.%02i"
+#endif
+;
+
+_ext const char *date_fmt
+#ifdef _MBGTIME
+ = "%2i.%02i.%04i"
+#endif
+;
+
+_ext const char *day_date_fmt
+#ifdef _MBGTIME
+ = "%s, %2i.%02i.%04i"
+#endif
+;
+
+_ext const char *day_name_eng[]
+#ifdef _MBGTIME
+ = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }
+#endif
+;
+
+_ext const char *day_name_ger[]
+#ifdef _MBGTIME
+ = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" }
+#endif
+;
+
+_ext const TM_GPS init_tm
+#ifdef _MBGTIME
+ = { 1980, 1, 1, 0, 0, 0, 0, 0, 0, 0 }
+#endif
+;
+
+
+_ext char days_of_month[2][12]
+#ifdef _MBGTIME
+ = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+ }
+#endif
+;
+
+
+// simplify call to n_days with structures
+#define _n_days( _s ) \
+ n_days( (_s)->mday, (_s)->month, (_s)->year )
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void set_timeout( TIMEOUT *t, clock_t clk, clock_t interval ) ;
+ void stretch_timeout( TIMEOUT *t, clock_t interval ) ;
+ bit check_timeout( TIMEOUT *t, clock_t clk ) ;
+ int err_tm( TM_GPS *tm ) ;
+ TM_GPS *clear_time( TM_GPS *tm ) ;
+ TM_GPS *wsec_to_tm( long wsec, TM_GPS *tm ) ;
+ long tm_to_wsec( TM_GPS *tm ) ;
+ int is_leap_year( int y ) ;
+ int day_of_year( int day, int month, int year ) ;
+ void date_of_year ( int year, int day_num, TM_GPS *tm ) ;
+ int day_of_week( int day, int month, int year ) ;
+ int days_to_years( long *day_num, int year ) ;
+ long n_days( ushort mday, ushort month, ushort year ) ;
+ double nano_time_to_double( const NANO_TIME *p ) ;
+ void double_to_nano_time( NANO_TIME *p, double d ) ;
+ int sprint_time( char *s, const TM_GPS *tm ) ;
+ int sprint_short_time( char *s, TM_GPS *time ) ;
+ int sprint_date( char *s, const TM_GPS *tm ) ;
+ int sprint_day_date( char *s, const TM_GPS *tm ) ;
+ int sprint_tm( char *s, const TM_GPS *tm ) ;
+ void sscan_time( char *s, TM_GPS *tm ) ;
+ void sscan_date( char *s, TM_GPS *tm ) ;
+
+/* ----- function prototypes end ----- */
+
+
+/* End of header body */
+
+
+#undef _ext
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _MBGTIME_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c
new file mode 100755
index 0000000..1a4156e
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c
@@ -0,0 +1,615 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgutil.c 1.5.2.1 2010/07/15 13:06:59 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Utility function used by Meinberg device drivers.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgutil.c $
+ * Revision 1.5.2.1 2010/07/15 13:06:59 martin
+ * Revision 1.5 2009/03/19 09:09:55Z daniel
+ * Fixed ambiguous syntax in mbg_str_dev_name().
+ * Support TAI and GPS time scales in mbg_str_pcps_hr_tstamp_loc().
+ * In mbg_str_pcps_hr_time_offs() append offset only if != 0.
+ * Revision 1.4 2009/01/12 09:34:12Z daniel
+ * Added function mbg_str_dev_name().
+ * Revision 1.3 2006/05/10 10:57:44Z martin
+ * Generally use and export mbg_snprintf().
+ * Revision 1.2 2005/02/18 15:12:13Z martin
+ * Made functions mbg_strncpy() and mbg_strchar() public.
+ * New function mbg_str_tm_gps_date_time().
+ * Don't expand year number if already expanded.
+ * Revision 1.1 2005/02/18 10:39:49Z martin
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _MBGUTIL
+ #include <mbgutil.h>
+#undef _MBGUTIL
+
+#include <pcpsutil.h>
+#include <pcpslstr.h>
+//#include <gpsutils.h>
+#include <pcpsdev.h>
+
+#include <stdio.h>
+#include <time.h>
+
+// required at least for Linux:
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#if defined( MBG_TGT_WIN32 )
+ #include <tchar.h>
+#else
+// #include <>
+#endif
+
+
+static int mbg_date_time_dist = 2;
+//##++ static int mbg_time_tz_dist = 1;
+static int mbg_pos_dist = 2;
+
+static uint16_t mbg_year_lim = 1980;
+
+
+#if defined( MBG_TGT_WIN32 )
+ #define mbg_vsnprintf _vsnprintf
+#else
+ #define mbg_vsnprintf vsnprintf
+#endif
+
+
+#if defined( MBG_TGT_DOS )
+
+static /*HDR*/
+int vsnprintf( char *s, int max_len, const char *fmt, va_list arg_list )
+{
+ return vsprintf( s, fmt, arg_list );
+
+} // vsnprintf
+
+#endif
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbgutil_get_version( void )
+{
+
+ return MBGUTIL_VERSION;
+
+} // mbgutil_get_version
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbgutil_check_version( int header_version )
+{
+ if ( header_version >= MBGUTIL_COMPAT_VERSION )
+ return PCPS_SUCCESS;
+
+ return -1;
+
+} // mbgutil_check_version
+
+
+
+// We have our own version of snprintf() since under Windows
+// _snprintf(), returns -1 and does not write a terminating 0
+// if the output exceeds the buffer size.
+//
+// This function terminates the output string properly. However,
+// the maximum return value is (max_len - 1), so the function
+// can not be used to determine the buffer size that would be
+// required for an untruncated string.
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... )
+{
+ int n;
+
+ va_list ap;
+
+ va_start( ap, fmt );
+
+ n = mbg_vsnprintf( s, max_len, fmt, ap );
+
+ va_end( ap );
+
+
+ #if defined( MBG_TGT_WIN32 )
+
+ // Terminate the output string properly under Windows.
+ // For other targets assume the POSIX version is available.
+ if ( n < 0 || n >= (int) max_len )
+ {
+ n = max_len - 1;
+ s[n] = 0;
+ }
+
+ #endif
+
+
+ return n;
+
+} // mbg_snprintf
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_strncpy( char *s, size_t max_len, const char *src )
+{
+ //##++ This could be coded more efficiently
+ return mbg_snprintf( s, max_len, "%s", src );
+
+} // mbg_strncpy
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t n )
+{
+ size_t i;
+
+ max_len--;
+
+ for ( i = 0; i < n; i++ )
+ {
+ if ( i >= max_len )
+ break;
+
+ s[i] = c;
+ }
+
+ s[i] = 0;
+
+ return i;
+
+} // mbg_strchar
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len,
+ int mday, int month )
+{
+ return mbg_snprintf( s, max_len, "%02u.%02u.", mday, month );
+
+} // mbg_str_date_short
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len,
+ int mday, int month, int year )
+{
+ int n = mbg_str_date_short( s, max_len, mday, month );
+ n += mbg_snprintf( s + n, max_len - n, "%04u",
+ ( year < 256 ) ?
+ pcps_exp_year( (uint8_t) year, mbg_year_lim ) :
+ year
+ );
+ return n;
+
+} // mbg_str_date
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len,
+ int hour, int min )
+{
+ return mbg_snprintf( s, max_len, "%2u:%02u", hour, min );
+
+} // mbg_str_time_short
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_time( char *s, int max_len,
+ int hour, int min, int sec )
+{
+ int n = mbg_str_time_short( s, max_len, hour, min );
+
+ n += mbg_snprintf( s + n, max_len - n, ":%02u", sec );
+
+ return n;
+
+} // mbg_str_time
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_time_long( char *s, int max_len,
+ int hour, int min, int sec, int sec100 )
+{
+ int n = mbg_str_time( s, max_len, hour, min, sec );
+
+ n += mbg_snprintf( s + n, max_len - n, ".%02u", sec100 );
+
+ return n;
+
+} // mbg_str_time_long
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_tm_gps_date_time( char *s, int max_len,
+ const TM_GPS *pt )
+{
+ int n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year );
+ n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist );
+ n += mbg_str_time( s + n, max_len - n, pt->hour, pt->min, pt->sec );
+
+ return n;
+
+} // mbg_str_tm_gps_date_time
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len,
+ const PCPS_TIME *pt )
+{
+ return mbg_str_date_short( s, max_len, pt->mday, pt->month );
+
+} // mbg_str_pcps_date_short
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len,
+ const PCPS_TIME *pt )
+{
+ return mbg_str_date( s, max_len, pt->mday, pt->month, pt->year );
+
+} // mbg_str_pcps_date
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_time_short( char *s, int max_len,
+ const PCPS_TIME *pt )
+{
+ return mbg_str_time_short( s, max_len, pt->hour, pt->min );
+
+} // mbg_str_pcps_time_short
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_time( char *s, int max_len,
+ const PCPS_TIME *pt )
+{
+ return mbg_str_time( s, max_len, pt->hour, pt->min, pt->sec );
+
+} // mbg_str_pcps_time
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_time_long( char *s, int max_len,
+ const PCPS_TIME *pt )
+{
+ return mbg_str_time_long( s, max_len, pt->hour, pt->min, pt->sec, pt->sec100 );
+
+} // mbg_str_pcps_time_long
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len,
+ const PCPS_TIME *pt,
+ const char *tz_str )
+{
+ int n = mbg_str_pcps_date( s, max_len, pt );
+ n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist );
+ n += mbg_str_pcps_time( s + n, max_len - n, pt );
+
+ return n;
+
+} // mbg_str_pcps_date_time
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len,
+ uint32_t sec )
+{
+ time_t t = sec;
+ struct tm tm = *gmtime( &t );
+ return mbg_str_date( s, max_len, tm.tm_mday, tm.tm_mon + 1, tm.tm_year );
+
+} // mbg_str_pcps_hr_date
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len,
+ uint32_t sec )
+{
+ time_t t = sec;
+ struct tm tm = *gmtime( &t );
+ return mbg_str_time( s, max_len, tm.tm_hour, tm.tm_min, tm.tm_sec );
+
+} // mbg_str_pcps_hr_time
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len,
+ const PCPS_HR_TIME *pt )
+{
+ time_t t = pt->tstamp.sec;
+ struct tm tm = *gmtime( &t );
+ int n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year );
+ n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist );
+ n += mbg_str_time( s + n, max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec );
+
+ return n;
+
+} // mbg_str_pcps_hr_date_time_utc
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len,
+ const PCPS_HR_TIME *pt )
+{
+ time_t t = pt->tstamp.sec + pt->utc_offs;
+ struct tm tm = *gmtime( &t );
+ int n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year );
+ n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist );
+ n += mbg_str_time( s + n, max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec );
+
+ return n;
+
+} // mbg_str_pcps_hr_date_time_loc
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len,
+ uint32_t frac )
+{
+ return mbg_snprintf( s, max_len, PCPS_HRT_FRAC_SCALE_FMT,
+ frac_sec_from_bin( frac, PCPS_HRT_FRAC_SCALE ) );
+
+} // mbg_str_pcps_hr_time_frac
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len,
+ const PCPS_HR_TIME *pt,
+ const char *info )
+{
+ int n = mbg_snprintf( s, max_len, "%s", info );
+
+ if ( pt->utc_offs )
+ {
+ ldiv_t ldt = ldiv( labs( pt->utc_offs ) / 60, 60 );
+
+ n += mbg_snprintf( s + n, max_len - n, "%c%02u:%02uh",
+ ( pt->utc_offs < 0 ) ? '-' : '+',
+ ldt.quot, ldt.rem );
+ }
+
+ return n;
+
+} // mbg_str_pcps_hr_time_offs
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len,
+ const PCPS_HR_TIME *pt )
+{
+ int n = mbg_str_pcps_hr_date_time_utc( s, max_len, pt );
+
+ if ( n < ( max_len - 1 ) )
+ {
+ s[n++] = '.';
+ n += mbg_str_pcps_hr_time_frac( s + n, max_len - n, pt->tstamp.frac );
+ }
+
+ return n;
+
+} // mbg_str_pcps_hr_tstamp_utc
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len,
+ const PCPS_HR_TIME *pt )
+{
+ int n = mbg_str_pcps_hr_date_time_loc( s, max_len, pt );
+
+ if ( n < ( max_len - 1 ) )
+ {
+ s[n++] = '.';
+ n += mbg_str_pcps_hr_time_frac( s + n, max_len - n, pt->tstamp.frac );
+ }
+
+ if ( n < ( max_len - 1 ) )
+ {
+ const char *cp = "UTC";
+
+ if ( pt->status & PCPS_SCALE_TAI )
+ cp = "TAI";
+ else
+ if ( pt->status & PCPS_SCALE_GPS )
+ cp = "GPS";
+
+ s[n++] = ' ';
+ n += mbg_str_pcps_hr_time_offs( s + n, max_len - n, pt, cp );
+ }
+
+ return n;
+
+} // mbg_str_pcps_hr_tstamp_loc
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len,
+ const PCPS_TIME_STAMP *pt )
+{
+ return mbg_snprintf( s, max_len, "%08lX.%08lX", pt->sec, pt->frac );
+
+} // mbg_str_pcps_tstamp_raw
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len,
+ const PCPS_HR_TIME *pt )
+{
+ int n = mbg_str_pcps_tstamp_raw( s, max_len, &pt->tstamp );
+ n += mbg_str_pcps_hr_time_offs( s + n, max_len - n, pt, ", Loc: " );
+ n += mbg_snprintf( s + n, max_len - n, ", st: 0x%04X", pt->status );
+
+ return n;
+
+} // mbg_str_pcps_hr_time_raw
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len,
+ const PCPS_HR_TIME *pt )
+{
+ int n = mbg_snprintf( s, max_len, "CAP%u: ", pt->signal );
+ n += mbg_str_pcps_hr_tstamp_loc( s + n, max_len - n, pt );
+
+ return n;
+
+} // mbg_str_ucap
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len,
+ const DMS *pdms, int prec )
+{
+ return mbg_snprintf( s, max_len, "%c %i" DEG "%02i'%02.*f\"",
+ pdms->prefix,
+ pdms->deg,
+ pdms->min,
+ prec,
+ pdms->sec
+ );
+
+} // mbg_str_pos_dms
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pos_alt( char *s, int max_len, double alt )
+{
+ return mbg_snprintf( s, max_len, "%.0fm", alt );
+
+} // mbg_str_pos_alt
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len,
+ const POS *ppos, int prec )
+{
+ int n;
+
+ if ( ppos->lla[LON] || ppos->lla[LAT] || ppos->lla[ALT] )
+ {
+ n = mbg_str_pos_dms( s, max_len, &ppos->latitude, prec );
+ n += mbg_strchar( s + n, max_len - n, ',', 1 );
+ n += mbg_strchar( s + n, max_len - n, ' ', mbg_pos_dist );
+ n += mbg_str_pos_dms( s + n, max_len - n, &ppos->longitude, prec );
+ n += mbg_strchar( s + n, max_len - n, ',', 1 );
+ n += mbg_strchar( s + n, max_len - n, ' ', mbg_pos_dist );
+ n += mbg_str_pos_alt( s + n, max_len - n, ppos->lla[ALT] );
+ }
+ else
+ n = mbg_strncpy( s, max_len, "N/A" );
+
+ return n;
+
+} // mbg_str_pos
+
+
+
+/*HDR*/
+_MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name,
+ uint16_t fw_rev_num, PCI_ASIC_VERSION asic_version_num )
+{
+ #define HW_NAME_SZ PCPS_CLOCK_NAME_SZ+PCPS_SN_SIZE+1
+
+ char model_code[HW_NAME_SZ];
+ PCPS_SN_STR sernum;
+ unsigned int i = 0;
+ int n = 0;
+
+ memset( model_code, 0, sizeof( model_code ) );
+ memset( sernum, 0, sizeof( sernum ) );
+
+ if ( strlen( short_name ) > 0 )
+ {
+ if ( strstr( short_name, "COM") )
+ return mbg_snprintf(s, max_len,"%s", short_name);
+
+ for ( i = 0; ( i < HW_NAME_SZ ) && ( i < strlen( short_name ) ); i++ )
+ {
+ if ( short_name[i] == '_' )
+ {
+ i++;
+ break;
+ }
+ model_code[i] = short_name[i];
+ }
+ strncpy( sernum, &short_name[i], PCPS_SN_SIZE-1 );
+
+ if ( sernum[12] == ' ' )
+ sernum[12] = '\0';
+ }
+
+ n = mbg_snprintf( s, max_len, "%s, S/N %s", model_code, sernum );
+
+ if ( fw_rev_num > 0 )
+ n += mbg_snprintf( &s[n], max_len," (FW v%X.%02X", fw_rev_num>>8, fw_rev_num & 0x00FF );
+
+ if ( asic_version_num > 0 )
+ {
+ mbg_snprintf( &s[n], max_len," / ASIC v%X.%02X)", _convert_asic_version_number( asic_version_num ) >> 8,
+ ( _convert_asic_version_number( asic_version_num ) ) & 0xFF );
+ }
+ else
+ mbg_snprintf( &s[n], max_len,")" );
+
+ return strlen(s);
+
+} // mbg_str_dev_name
+
+
+
+
+#if defined( MBG_TGT_WIN32 )
+
+BOOL APIENTRY DllMain( HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved )
+{
+ return TRUE;
+}
+
+#endif // defined( MBG_TGT_WIN32 )
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h
new file mode 100755
index 0000000..9d26c62
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h
@@ -0,0 +1,183 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgutil.h 1.16.1.1 2011/02/09 15:27:23 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used with mbgutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgutil.h $
+ * Revision 1.16.1.1 2011/02/09 15:27:23 martin
+ * Revision 1.16 2009/08/14 10:11:53Z daniel
+ * New version code 306, compatibility version still 110.
+ * Revision 1.15 2009/06/09 08:57:47Z daniel
+ * Rev No. 305
+ * Revision 1.14 2009/03/19 09:06:00Z daniel
+ * New version code 304, compatibility version still 110.
+ * Revision 1.13 2009/01/12 09:35:41Z daniel
+ * New version code 303, compatibility version still 110.
+ * Updated function prototypes.
+ * Revision 1.12 2008/01/17 10:15:26Z daniel
+ * New version code 302, compatibility version still 110.
+ * Revision 1.11 2007/10/16 10:01:17Z daniel
+ * New version code 301, compatibility version still 110.
+ * Revision 1.9 2007/03/21 16:48:31Z martin
+ * New version code 219, compatibility version still 110.
+ * Revision 1.8 2006/08/09 13:18:18Z martin
+ * New version code 218, compatibility version still 110.
+ * Revision 1.7 2006/06/08 10:48:52Z martin
+ * New version code 217, compatibility version still 110.
+ * Added macro _mbg_strncpy().
+ * Revision 1.6 2006/05/10 10:56:54Z martin
+ * Updated function prototypes.
+ * Revision 1.5 2006/05/02 13:24:49Z martin
+ * New version code 216, compatibility version still 110.
+ * Revision 1.4 2006/01/11 12:24:05Z martin
+ * New version code 215, compatibility version still 110.
+ * Revision 1.3 2005/12/15 10:01:51Z martin
+ * New version 214, compatibility version still 110.
+ * Revision 1.2 2005/02/18 15:13:42Z martin
+ * Updated function prototypes.
+ * Revision 1.1 2005/02/18 10:39:49Z martin
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _MBGUTIL_H
+#define _MBGUTIL_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <use_pack.h>
+#include <pcpsdefs.h>
+#include <mbggeo.h>
+#include <pci_asic.h>
+
+#include <stdlib.h>
+
+
+#define MBGUTIL_VERSION 0x0306
+
+#define MBGUTIL_COMPAT_VERSION 0x0110
+
+
+#if defined( MBG_TGT_WIN32 )
+
+ #include <windows.h>
+
+#elif defined( MBG_TGT_LINUX )
+
+
+#elif defined( MBG_TGT_OS2 )
+
+
+#elif defined( MBG_TGT_DOS )
+
+ #if !defined( MBG_USE_DOS_TSR )
+ #endif
+
+#else
+
+#endif
+
+#ifdef _MBGUTIL
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+#if defined( MBG_TGT_WIN32 )
+
+#elif defined( MBG_TGT_LINUX )
+
+#elif defined( MBG_TGT_OS2 )
+
+#else
+
+#endif
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// The macro below can be used to simplify the API call if
+// a string variable is used rather than a char *.
+#define _mbg_strncpy( _s, _src ) \
+ mbg_strncpy( _s, sizeof( _s ), _src )
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ _MBG_API_ATTR int _MBG_API mbgutil_get_version( void ) ;
+ _MBG_API_ATTR int _MBG_API mbgutil_check_version( int header_version ) ;
+ _MBG_API_ATTR int _MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) ;
+ _MBG_API_ATTR int _MBG_API mbg_strncpy( char *s, size_t max_len, const char *src ) ;
+ _MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t n ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, int mday, int month ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, int mday, int month, int year ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, int hour, int min ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_time( char *s, int max_len, int hour, int min, int sec ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_time_long( char *s, int max_len, int hour, int min, int sec, int sec100 ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_tm_gps_date_time( char *s, int max_len, const TM_GPS *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, const PCPS_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, const PCPS_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_short( char *s, int max_len, const PCPS_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time( char *s, int max_len, const PCPS_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_long( char *s, int max_len, const PCPS_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, const PCPS_TIME *pt, const char *tz_str ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, uint32_t sec ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, uint32_t sec ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, uint32_t frac ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, const PCPS_HR_TIME *pt, const char *info ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, const PCPS_TIME_STAMP *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, const PCPS_HR_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, const PCPS_HR_TIME *pt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, const DMS *pdms, int prec ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pos_alt( char *s, int max_len, double alt ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, const POS *ppos, int prec ) ;
+ _MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, uint16_t fw_rev_num, PCI_ASIC_VERSION asic_version_num ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _MBGUTIL_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/myutil.h b/src/external/bsd/meinberg/dist/mbglib/common/myutil.h
new file mode 100755
index 0000000..7e6b901
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/myutil.h
@@ -0,0 +1,221 @@
+
+/**************************************************************************
+ *
+ * $Id: myutil.h 1.14 2011/02/16 14:02:35 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for myutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: myutil.h $
+ * Revision 1.14 2011/02/16 14:02:35 martin
+ * Added STRINGIFY() macro.
+ * Revision 1.13 2010/12/13 15:59:39 martin
+ * Moved definition of macro _frac() here.
+ * Revision 1.12 2008/01/30 10:28:17Z martin
+ * Moved some macro definitions to words.h.
+ * Revision 1.11 2004/11/09 14:20:24Z martin
+ * Redefined some data types using C99 fixed-size definitions.
+ * Removed duplicate definition of macro _mask().
+ * Revision 1.10 2004/04/14 08:57:59Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.9 2003/05/20 10:22:25Z MARTIN
+ * Corrected endianess of union UL for CC51.
+ * Revision 1.8 2002/09/03 13:40:43 MARTIN
+ * New macros _memfill() and _memclr().
+ * Revision 1.7 2002/03/14 13:45:56 MARTIN
+ * Changed type CSUM from short to ushort.
+ * Revision 1.6 2002/03/05 14:14:21 MARTIN
+ * New macro _isdigit() to avoid inclusion of ctype.h.
+ * Revision 1.5 2002/01/25 10:54:26 MARTIN
+ * Added some useful macros.
+ * Revision 1.4 2001/03/30 09:07:52 Andre
+ * union UL byte order set to Big Endian if SH2 is used
+ * Revision 1.3 2000/08/18 07:22:07Z MARTIN
+ * Modified the _csum() macro to support far data objects.
+ * Revision 1.2 2000/07/21 13:50:49 MARTIN
+ * Added some definitions and macros.
+ *
+ **************************************************************************/
+
+#ifndef _MYUTIL_H
+#define _MYUTIL_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+#include <use_pack.h>
+
+
+// _CS_FAR should be define far if the csum of far data
+// structures must be computed
+#if !defined( _CSFAR )
+ #define _CSFAR
+#endif
+
+
+#ifdef _MYUTIL
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+// The two macros below can be used to define a constant string on the
+// compiler's command line, e.g. like -DVERSION_STRING="v1.0 BETA".
+// Source code like
+// const char version_string[] = VERSION_STRING;
+// may not work for every compiler since the double quotes
+// in VERSION_STRING may be removed when the definition is evaluated.
+// A proper solution is to use the STRINGIFY() macro below:
+// const char version_string[] = STRINGIFY( VERSION_STRING );
+// The XSTRINGIFY() macro is simply a helper macro which should not
+// be used alone.
+#define STRINGIFY(x) XSTRINGIFY(x)
+#define XSTRINGIFY(x) #x
+
+
+
+#if MBG_TGT_HAS_64BIT_TYPES
+ #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (int64_t) (_x) ) ) )
+#else
+ #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (long) (_x) ) ) )
+#endif
+
+
+#define _isdigit( _c ) ( (_c) >= '0' && (_c) <= '9' )
+
+#define _eos( _s ) ( &(_s)[strlen( _s )] )
+
+#define MIN( _x, _y ) ( ( (_x) < (_y) ) ? (_x) : (_y) )
+#define MAX( _x, _y ) ( ( (_x) > (_y) ) ? (_x) : (_y) )
+#define SWAP( _x, _y ) { temp = (_x); (_x) = (_y); (_y) = temp; }
+#define SQR( _x ) ( (_x) * (_x) )
+
+#define DP (double *)
+
+#define bcd_from_bin( _x ) ( ( ( (_x) / 10 ) << 4 ) | ( (_x) % 10 ) )
+#define bin_from_bcd( _x ) ( ( ( (_x) >> 4 ) * 10 ) + ( (_x) & 0x0F ) )
+
+
+typedef union
+{
+ uint32_t ul;
+
+ struct
+ {
+ #if defined( _CC51 ) || defined( _SH2 )
+ uint16_t hi; // big endian
+ uint16_t lo;
+ #else
+ uint16_t lo; // little endian
+ uint16_t hi;
+ #endif
+ } us;
+
+} UL;
+
+
+#ifndef _CSUM_DEFINED
+ typedef uint16_t CSUM;
+ #define _CSUM_DEFINED
+#endif
+
+
+// compute the csum of a structure
+#define _csum( _p ) checksum( (void _CSFAR *)(_p), sizeof( *(_p) ) )
+
+// set a structure's csum
+#define _set_csum( _p ) (_p)->csum = _csum( (_p) )
+
+// compare a structure's computed csum with its csum field
+#define _valid_csum( _p ) ( (_p)->csum == _csum( (_p) ) )
+
+// check if a value is in range
+#define _inrange( _val, _min, _max ) \
+ ( ( (_val) >= (_min) ) && ( (_val) <= (_max) ) )
+
+// Return a bit mask with (_n) LSBs set to 1
+#define _mask( _n ) \
+ ( ( 1UL << (_n) ) - 1 )
+
+// Return a bit mask with the (_i)th LSB set to 1
+#define _idx_bit( _i ) \
+ ( 1UL << (_i) )
+
+// Check if the (_i)th bit is set in a mask (_msk)
+#define _is_supported( _i, _msk ) \
+ ( ( (_msk) & _idx_bit( _i ) ) != 0 )
+
+
+/*
+ * The macro below copies a string, taking care not to
+ * write past the end of the destination buffer, and
+ * making sure the string is terminated by 0.
+ */
+#define _strncpy_0( _dst, _src ) \
+{ \
+ int n = sizeof( _dst ) - 1; \
+ \
+ strncpy( _dst, _src, n ); \
+ (_dst)[n] = 0; \
+}
+
+
+/*
+ * The macros below set a memory range used by a variable
+ * to a specified value, avoiding the need to type the name
+ * twice for base address and size.
+ */
+#define _memfill( _p, _v ) \
+ memset( _p, _v, sizeof( *(_p) ) )
+
+#define _memclr( _p ) \
+ _memfill( _p, 0 )
+
+
+
+// generate a DOS idle interrupt to release CPU time
+#define _dos_idle() geninterrupt( 0x28 )
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void spaces_to_zeros( char *s ) ;
+ CSUM checksum( const void _CSFAR *vp, int n ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+
+
+#endif /* _MYUTIL_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmgps.c b/src/external/bsd/meinberg/dist/mbglib/common/parmgps.c
new file mode 100755
index 0000000..44e620b
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/parmgps.c
@@ -0,0 +1,242 @@
+
+/**************************************************************************
+ *
+ * $Id: parmgps.c 1.5 2008/10/21 10:47:26 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions to handle/convert Meinberg GPS specific parameters.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmgps.c $
+ * Revision 1.5 2008/10/21 10:47:26 martin
+ * Renamed check_port_info() to check_valid_port_info()
+ * to avoid naming conflicts.
+ * Revision 1.4 2008/09/15 14:11:25 martin
+ * New function check_port_info() which returns a bit mask indicating
+ * which fields of a PORT_SETTINGS structure are not valid.
+ * This is based on code taken from valid_port_info(), which now calls
+ * check_port_info() and returns a value compatible to the earlier version.
+ * Revision 1.3 2004/11/09 14:21:36 martin
+ * Redefined some data types using C99 fixed-size definitions.
+ * Revision 1.2 2002/02/19 13:30:23Z MARTIN
+ * Bug fix in port_settings_from_port_parm_mode().
+ * Revision 1.1 2002/01/30 10:30:26 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PARMGPS
+ #include <parmgps.h>
+#undef _PARMGPS
+
+#include <myutil.h>
+#include <string.h>
+
+
+
+/*HDR*/
+int get_str_idx( const char *search,
+ const char *str_table[],
+ int n_entries )
+{
+ int i;
+
+ for ( i = 0; i < n_entries; i++ )
+ if ( strcmp( search, str_table[i] ) == 0 )
+ return i;
+
+ return -1;
+
+} // get_str_idx
+
+
+
+/*HDR*/
+int get_baud_rate_idx( BAUD_RATE baud_rate )
+{
+ int i;
+
+ for ( i = 0; i < N_MBG_BAUD_RATES; i++ )
+ if ( baud_rate == mbg_baud_rate[i] )
+ return i;
+
+ return -1;
+
+} // get_baud_rate_idx
+
+
+
+/*HDR*/
+int get_framing_idx( const char *framing )
+{
+ return get_str_idx( framing, mbg_framing_str, N_MBG_FRAMINGS );
+
+} // get_framing_idx
+
+
+
+/*HDR*/
+void port_settings_from_port_parm_mode(
+ PORT_SETTINGS *p_ps,
+ uint8_t pp_mode,
+ int str_type_cap
+ )
+{
+ if ( pp_mode >= STR_UCAP )
+ {
+ p_ps->str_type = str_type_cap;
+ p_ps->mode = ( pp_mode == STR_UCAP ) ? STR_AUTO : STR_ON_REQ;
+ }
+ else
+ {
+ p_ps->str_type = 0;
+ p_ps->mode = pp_mode;
+ }
+
+} // port_settings_from_port_parm_mode
+
+
+
+/*HDR*/
+void port_parm_mode_from_port_settings(
+ uint8_t *pp_mode,
+ const PORT_SETTINGS *p_ps,
+ int str_type_cap
+ )
+{
+ if ( p_ps->str_type == str_type_cap )
+ *pp_mode = ( p_ps->mode == STR_ON_REQ ) ? STR_UCAP_REQ : STR_UCAP;
+ else
+ *pp_mode = p_ps->mode;
+
+} // port_parm_mode_from_port_settings
+
+
+
+/*HDR*/
+void port_settings_from_port_parm(
+ PORT_SETTINGS *p_ps,
+ int port_num,
+ const PORT_PARM *p_pp,
+ int cap_str_idx
+)
+{
+ p_ps->parm = p_pp->com[port_num];
+
+ port_settings_from_port_parm_mode( p_ps, p_pp->mode[port_num],
+ cap_str_idx );
+
+} // port_info_from_port_parm
+
+
+
+/*HDR*/
+void port_parm_from_port_settings(
+ PORT_PARM *p_pp,
+ int port_num,
+ const PORT_SETTINGS *p_ps,
+ int cap_str_idx
+)
+{
+ p_pp->com[port_num] = p_ps->parm;
+
+ port_parm_mode_from_port_settings( &p_pp->mode[port_num],
+ p_ps, cap_str_idx );
+
+} // port_parm_from_port_settings
+
+
+
+/*HDR*/
+int check_valid_port_info( const PORT_INFO *p_pi,
+ const STR_TYPE_INFO_IDX str_type_info_idx[],
+ int n_str_type )
+
+{
+ const PORT_SETTINGS *p_ps = &p_pi->port_settings;
+ int idx;
+ int flags = 0;
+
+
+ if ( p_pi->supp_baud_rates & ~_mask( N_MBG_BAUD_RATES ) )
+ flags |= MBG_PS_MSK_BAUD_RATE_OVR_SW; // dev. supports more baud rates than driver
+
+ idx = get_baud_rate_idx( p_ps->parm.baud_rate );
+
+ if ( !_inrange( idx, 0, N_MBG_BAUD_RATES ) ||
+ !_is_supported( idx, p_pi->supp_baud_rates ) )
+ flags |= MBG_PS_MSK_BAUD_RATE;
+
+
+ if ( p_pi->supp_framings & ~_mask( N_MBG_FRAMINGS ) )
+ flags |= MBG_PS_MSK_FRAMING_OVR_SW; // dev. supports more framings than driver
+
+ idx = get_framing_idx( p_ps->parm.framing );
+
+ if ( !_inrange( idx, 0, N_MBG_FRAMINGS ) ||
+ !_is_supported( idx, p_pi->supp_framings ) )
+ flags |= MBG_PS_MSK_FRAMING;
+
+
+ if ( p_ps->parm.handshake >= N_COM_HS )
+ flags |= MBG_PS_MSK_HS_OVR_SW; // handshake index exceeds max.
+
+ if ( p_ps->parm.handshake != HS_NONE ) // currently no device supports any handshake
+ flags |= MBG_PS_MSK_HS; // handshake mode not supp. by dev.
+
+
+ if ( p_pi->supp_str_types & ~_mask( n_str_type ) )
+ flags |= MBG_PS_MSK_STR_TYPE_OVR_SW; // firmware error: more string types supported than reported
+
+ idx = p_ps->str_type;
+
+ if ( idx >= n_str_type )
+ flags |= MBG_PS_MSK_STR_TYPE_OVR_DEV; // string type index exceeds max.
+ else
+ {
+ if ( !_is_supported( idx, p_pi->supp_str_types ) )
+ flags |= MBG_PS_MSK_STR_TYPE; // string type not supported by this port
+ else
+ {
+ // Use the str_type index to get the supported output mode mask
+ // from the string type info table. This is required to check
+ // whether the selected mode is supported by the selected
+ // string type.
+ ulong supp_modes = str_type_info_idx[idx].str_type_info.supp_modes;
+
+ if ( supp_modes & ~_mask( N_STR_MODE ) )
+ flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // dev. supports more string modes than driver
+
+ idx = p_ps->mode;
+
+ if ( idx >= N_STR_MODE ) // mode is always >= 0
+ flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // string mode index exceeds max.
+ else
+ if ( !_is_supported( idx, supp_modes ) )
+ flags |= MBG_PS_MSK_STR_MODE; // string mode not supp. by this string type and port
+ }
+ }
+
+
+ if ( p_ps->flags != 0 ) /* currently always 0 */
+ flags |= MBG_PS_MSK_FLAGS_OVR_SW | MBG_PS_MSK_FLAGS;
+
+
+ return flags;
+
+} // check_valid_port_info
+
+
+
+/*HDR*/
+int valid_port_info( const PORT_INFO *p_pi,
+ const STR_TYPE_INFO_IDX str_type_info_idx[],
+ int n_str_type )
+{
+ return check_valid_port_info( p_pi, str_type_info_idx, n_str_type ) == 0;
+
+} // valid_port_info
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmgps.h b/src/external/bsd/meinberg/dist/mbglib/common/parmgps.h
new file mode 100755
index 0000000..46d28fc
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/parmgps.h
@@ -0,0 +1,138 @@
+
+/**************************************************************************
+ *
+ * $Id: parmgps.h 1.7 2011/02/16 10:12:13 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for parmgps.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmgps.h $
+ * Revision 1.7 2011/02/16 10:12:13 martin
+ * Fixed macro syntax for _setup_default_receiver_info_gps().
+ * Revision 1.6 2008/10/21 10:41:09Z martin
+ * Renamed check_port_info() to check_valid_port_info()
+ * to avoid naming conflicts.
+ * Revision 1.5 2008/09/10 16:22:32 martin
+ * Updated function prototypes.
+ * Revision 1.4 2004/11/09 14:22:34 martin
+ * Updated function prototypes.
+ * Revision 1.3 2004/05/19 07:50:16Z martin
+ * Use symbolic constant as initializer.
+ * Revision 1.2 2004/04/14 09:21:23Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.1 2002/01/30 10:33:38Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PARMGPS_H
+#define _PARMGPS_H
+
+
+/* Other headers to be included */
+
+#include <gpsdefs.h>
+#include <use_pack.h>
+
+
+#ifdef _PARMGPS
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define DEFAULT_N_STR_TYPE_GPS 2
+
+#define DEFAULT_SUPP_STR_TYPES_GPS \
+ ( ( 1UL << DEFAULT_N_STR_TYPE_GPS ) - 1 )
+
+
+/*
+ * The macro below can be used to initialize a
+ * RECEIVER_INFO structure for old GPS receiver models
+ * which don't supply that structure.
+ *
+ * Parameters: (RECEIVER_INFO *) _p
+ */
+#define _setup_default_receiver_info_gps( _p ) \
+do \
+{ \
+ memset( (_p), 0, sizeof( *(_p) ) ); \
+ \
+ (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \
+ (_p)->n_ucaps = 2; \
+ (_p)->n_com_ports = DEFAULT_N_COM; \
+ (_p)->n_str_type = DEFAULT_N_STR_TYPE_GPS; \
+} while ( 0 )
+
+
+_ext BAUD_RATE mbg_baud_rate[N_MBG_BAUD_RATES]
+#ifdef _DO_INIT
+ = MBG_BAUD_RATES
+#endif
+;
+
+_ext const char *mbg_baud_str[N_MBG_BAUD_RATES]
+#ifdef _DO_INIT
+ = MBG_BAUD_STRS
+#endif
+;
+
+_ext const char *mbg_framing_str[N_MBG_FRAMINGS]
+#ifdef _DO_INIT
+ = MBG_FRAMING_STRS
+#endif
+;
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int get_str_idx( const char *search, const char *str_table[], int n_entries ) ;
+ int get_baud_rate_idx( BAUD_RATE baud_rate ) ;
+ int get_framing_idx( const char *framing ) ;
+ void port_settings_from_port_parm_mode( PORT_SETTINGS *p_ps, uint8_t pp_mode, int str_type_cap ) ;
+ void port_parm_mode_from_port_settings( uint8_t *pp_mode, const PORT_SETTINGS *p_ps, int str_type_cap ) ;
+ void port_settings_from_port_parm( PORT_SETTINGS *p_ps, int port_num, const PORT_PARM *p_pp, int cap_str_idx ) ;
+ void port_parm_from_port_settings( PORT_PARM *p_pp, int port_num, const PORT_SETTINGS *p_ps, int cap_str_idx ) ;
+ int check_valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ;
+ int valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ;
+
+/* ----- function prototypes end ----- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PARMGPS_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.c b/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.c
new file mode 100755
index 0000000..cd02754
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.c
@@ -0,0 +1,115 @@
+
+/**************************************************************************
+ *
+ * $Id: parmpcps.c 1.4 2004/11/09 14:24:15 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions to handle/convert parameters used by Meinberg plug-in
+ * radio clocks.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmpcps.c $
+ * Revision 1.4 2004/11/09 14:24:15 martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Revision 1.3 2003/04/17 10:43:35Z martin
+ * Moved some definitions to parmpcps.h.
+ * Removed some functions which are now in mbgdevio.c.
+ * Revision 1.2 2002/03/25 09:03:43Z MARTIN
+ * Fixed a bug where the wrong framing was configured for DCF77 clocks.
+ * Revision 1.1 2002/02/19 14:00:19 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PARMPCPS
+ #include <parmpcps.h>
+#undef _PARMPCPS
+
+#include <parmgps.h>
+#include <pcpsutil.h>
+#include <myutil.h>
+
+#include <string.h>
+
+
+static const int pcps_to_mbg_framing_tbl[N_PCPS_FR_DCF] =
+{
+ MBG_FRAMING_8N1,
+ MBG_FRAMING_7E2,
+ MBG_FRAMING_8N2,
+ MBG_FRAMING_8E1
+};
+
+
+
+/*HDR*/
+void port_info_from_pcps_serial(
+ PORT_INFO_IDX *p_pii,
+ PCPS_SERIAL pcps_serial,
+ uint32_t supp_baud_rates
+)
+{
+ PCPS_SER_PACK ser_pack;
+ PORT_INFO *p_pi;
+ PORT_SETTINGS *p_ps;
+
+ ser_pack.pack = pcps_serial;
+ pcps_unpack_serial( &ser_pack );
+
+ p_pi = &p_pii[0].port_info;
+ p_ps = &p_pi->port_settings;
+
+ p_ps->parm.baud_rate = mbg_baud_rate[ser_pack.baud];
+
+ _strncpy_0( p_ps->parm.framing,
+ mbg_framing_str[pcps_to_mbg_framing_tbl[ser_pack.frame]] );
+
+ p_ps->parm.handshake = HS_NONE;
+
+ p_ps->str_type = 0;
+ p_ps->mode = ser_pack.mode;
+
+ p_pi->supp_baud_rates = supp_baud_rates;
+ p_pi->supp_framings = DEFAULT_FRAMINGS_DCF;
+ p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_DCF;
+
+} // port_info_from_pcps_serial
+
+
+/*HDR*/
+void pcps_serial_from_port_info(
+ PCPS_SERIAL *p,
+ const PORT_INFO_IDX *p_pii
+)
+{
+ PCPS_SER_PACK ser_pack;
+ const PORT_INFO *p_pi = &p_pii[0].port_info;
+ const PORT_SETTINGS *p_ps = &p_pi->port_settings;
+ int framing_idx = get_framing_idx( p_ps->parm.framing );
+ int i;
+
+
+ ser_pack.baud = get_baud_rate_idx( p_ps->parm.baud_rate );
+
+ // Translate the common framing index to the corresponding
+ // number used with the old PCPS_SERIAL parameter.
+ // This should always return a valid result since the
+ // framing index is expected to be selected from
+ // supported framings.
+ for ( i = 0; i < N_PCPS_FR_DCF; i++ )
+ if ( pcps_to_mbg_framing_tbl[i] == framing_idx )
+ break;
+
+ ser_pack.frame = i;
+
+ ser_pack.mode = p_ps->mode;
+
+ pcps_pack_serial( &ser_pack );
+
+ *p = ser_pack.pack;
+
+} // pcps_serial_from_port_info
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.h b/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.h
new file mode 100755
index 0000000..eafe487
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.h
@@ -0,0 +1,157 @@
+
+/**************************************************************************
+ *
+ * $Id: parmpcps.h 1.6 2011/02/16 10:13:12 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for parmpcps.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: parmpcps.h $
+ * Revision 1.6 2011/02/16 10:13:12 martin
+ * Fixed macro syntax for _setup_default_receiver_info_pcps().
+ * Revision 1.5 2004/11/09 14:24:58Z martin
+ * Updated function prototypes.
+ * Revision 1.4 2004/05/19 07:52:25Z martin
+ * Fixed macro setting default number of string types.
+ * Revision 1.3 2004/04/14 09:21:44Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.2 2003/04/17 10:42:46Z martin
+ * Moved typedef RECEIVER_PORT_CFG to pcpsdev.h.
+ * Moved some definitions from parmpcps.c here.
+ * Removed some global variables.
+ * Updated function prototypes.
+ * Revision 1.1 2002/02/19 14:00:19Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PARMPCPS_H
+#define _PARMPCPS_H
+
+/* Other headers to be included */
+
+#include <pcpsdev.h>
+#include <use_pack.h>
+
+
+#ifdef _PARMPCPS
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define DEFAULT_BAUD_RATES_DCF \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 \
+)
+
+#define DEFAULT_BAUD_RATES_DCF_HS \
+( \
+ MBG_PORT_HAS_300 | \
+ MBG_PORT_HAS_600 | \
+ MBG_PORT_HAS_1200 | \
+ MBG_PORT_HAS_2400 | \
+ MBG_PORT_HAS_4800 | \
+ MBG_PORT_HAS_9600 | \
+ MBG_PORT_HAS_19200 | \
+ MBG_PORT_HAS_38400 \
+)
+
+
+#define DEFAULT_FRAMINGS_DCF \
+( \
+ MBG_PORT_HAS_7E2 | \
+ MBG_PORT_HAS_8N1 | \
+ MBG_PORT_HAS_8N2 | \
+ MBG_PORT_HAS_8E1 \
+)
+
+
+#define DEFAULT_N_STR_TYPE_DCF 1
+
+#define DEFAULT_SUPP_STR_TYPES_DCF \
+ ( ( 1UL << DEFAULT_N_STR_TYPE_DCF ) - 1 )
+
+
+/*
+ * The macro below can be used to initialize a
+ * RECEIVER_INFO structure for DCF77 receivers
+ * which don't supply that structure.
+ *
+ * Parameters: (RECEIVER_INFO *) _p
+ */
+#define _setup_default_receiver_info_dcf( _p, _pdev ); \
+do \
+{ \
+ memset( (_p), 0, sizeof( *(_p) ) ); \
+ \
+ (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \
+ (_p)->n_ucaps = 0; \
+ (_p)->n_com_ports = _pcps_has_serial( _pdev ) ? 1 : 0; \
+ (_p)->n_str_type = ( (_p)->n_com_ports != 0 ) ? \
+ DEFAULT_N_STR_TYPE_DCF : 0; \
+} while ( 0 )
+
+
+#define DEFAULT_MAX_STR_TYPE 2 //##++DEFAULT_N_STR_TYPE_GPS
+
+_ext STR_TYPE_INFO default_str_type_info[DEFAULT_MAX_STR_TYPE]
+#ifdef _DO_INIT
+ = {
+ { DEFAULT_STR_MODES, "Default Time String", "Time", 0 },
+ { DEFAULT_STR_MODES_UCAP, "Capture String", "Cap", 0 }
+ }
+#endif
+;
+
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ void port_info_from_pcps_serial( PORT_INFO_IDX *p_pii, PCPS_SERIAL pcps_serial, uint32_t supp_baud_rates ) ;
+ void pcps_serial_from_port_info( PCPS_SERIAL *p, const PORT_INFO_IDX *p_pii ) ;
+
+/* ----- function prototypes end ----- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PARMPCPS_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pci.h b/src/external/bsd/meinberg/dist/mbglib/common/pci.h
new file mode 100755
index 0000000..fc8abb5
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pci.h
@@ -0,0 +1,162 @@
+
+/**************************************************************************
+ *
+ * $Id: pci.h 1.9 2008/01/30 13:42:29 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used to access the PC PCI BIOS.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pci.h $
+ * Revision 1.9 2008/01/30 13:42:29 martin
+ * Code cleanup to support different build environments properly.
+ * Revision 1.8 2006/07/11 08:59:00Z martin
+ * Account for PCI functions having been renamed in the library.
+ * Revision 1.7 2003/02/19 16:51:21Z martin
+ * Include pci_nt.h for Win32 non-pnp.
+ * Revision 1.6 2002/02/19 09:28:00Z MARTIN
+ * Use new header mbg_tgt.h to check the target environment.
+ * Revision 1.5 2002/01/15 15:47:30 Udo
+ * Don't include pci_nt.h under Win32.
+ * Revision 1.4 2001/03/15 13:01:40Z MARTIN
+ * Redefined preprocessor control for Win32.
+ * Revision 1.3 2001/03/01 09:23:36 MARTIN
+ * Added QNX support.
+ * Modified preprocessor syntax.
+ * Revision 1.2 2000/07/21 12:18:16 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCI_H
+#define _PCI_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+
+#if defined( MBG_TGT_NETWARE )
+
+ #include <pci_nw.h> // PCI functions for NetWare
+
+#elif defined( MBG_TGT_OS2 )
+
+ #include <pci_os2.h> // PCI functions for OS/2
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #if !defined( MBG_TGT_WIN32_PNP )
+ #include <pci_nt.h> // PCI functions for Win32/non-pnp
+ #endif
+
+#elif defined( MBG_TGT_LINUX )
+
+ #include <pci_lx.h> // PCI functions for Linux
+
+#elif defined( MBG_TGT_QNX )
+
+ #include <pci_qnx.h> // PCI functions for QNX
+
+#elif defined( MBG_TGT_DOS )
+
+ #include <pci_dos.h> // PCI functions for DOS
+
+#endif
+
+
+
+#ifdef _PCI
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if !defined( pci_fnc_init )
+ #define pci_fnc_init() 0
+#endif
+
+#if !defined( pci_fnc_deinit )
+ #define pci_fnc_deinit()
+#endif
+
+
+#if !defined( _mbg_pci_find_bios )
+ #define _mbg_pci_find_bios mbg_pci_find_bios
+#endif
+
+#if !defined( _mbg_pci_find_device )
+ #define _mbg_pci_find_device mbg_pci_find_device
+#endif
+
+
+#if defined( MBG_PCI_MACROS_MAP_DIRECT )
+
+ #define _mbg_pci_find_device mbg_pci_find_device
+ #define _mbg_pci_read_cfg_byte mbg_pci_read_cfg_byte
+ #define _mbg_pci_read_cfg_word mbg_pci_read_cfg_word
+ #define _mbg_pci_read_cfg_dword mbg_pci_read_cfg_dword
+ #define _mbg_pci_write_cfg_byte mbg_pci_write_cfg_byte
+ #define _mbg_pci_write_cfg_word mbg_pci_write_cfg_word
+ #define _mbg_pci_write_cfg_dword mbg_pci_write_cfg_dword
+
+#endif // defined( MBG_PCI_MACROS_MAP_DIRECT )
+
+
+#if defined( MBG_PCI_MACROS_MAP_GENERIC )
+
+ #define _mbg_pci_read_cfg_byte( bus, dev_fnc, reg, addr ) \
+ mbg_pci_read_cfg_reg( bus, dev_fnc, reg, sizeof( uint8_t ), addr )
+
+ #define _mbg_pci_read_cfg_word( bus, dev_fnc, reg, addr ) \
+ mbg_pci_read_cfg_reg( bus, dev_fnc, reg, sizeof( uint16_t ), addr )
+
+ #define _mbg_pci_read_cfg_dword( bus, dev_fnc, reg, addr ) \
+ mbg_pci_read_cfg_reg( bus, dev_fnc, reg, sizeof( uint32_t ), addr )
+
+
+ #define _mbg_pci_write_cfg_byte( bus, dev_fnc, reg, addr ) \
+ mbg_pci_write_cfg_reg( bus, dev_fnc, reg, sizeof( uint8_t ), addr )
+
+ #define _mbg_pci_write_cfg_word( bus, dev_fnc, reg, addr ) \
+ mbg_pci_write_cfg_reg( bus, dev_fnc, reg, sizeof( uint16_t ), addr )
+
+ #define _mbg_pci_write_cfg_dword( bus, dev_fnc, reg, addr ) \
+ mbg_pci_write_cfg_reg( bus, dev_fnc, reg, sizeof( uint32_t ), addr )
+
+#endif // defined( MBG_PCI_MACROS_MAP_GENERIC )
+
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PCI_H */
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h b/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h
new file mode 100755
index 0000000..2feef9b
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h
@@ -0,0 +1,333 @@
+
+/**************************************************************************
+ *
+ * $Id: pci_asic.h 1.16 2010/04/16 11:12:21 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions for the Meinberg PCI interface ASIC.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pci_asic.h $
+ * Revision 1.16 2010/04/16 11:12:21 martin
+ * Updated GPS170PEX ASIC version.
+ * Revision 1.15 2009/03/27 09:39:15 martin
+ * Increased current ASIC minor number for TCR170PEX to 0x02.
+ * Renamed some symbols.
+ * Revision 1.14 2009/03/11 16:54:10Z martin
+ * Increased current ASIC minor number for TCR511PEX to 0x04.
+ * Fixed a typo.
+ * Revision 1.13 2008/12/05 12:28:18Z martin
+ * Modified syntax of macro _convert_asic_version_number().
+ * Added macros to deal with the ASIC version number.
+ * Added definition PCI_ASIC_HAS_PGMB_IRQ.
+ * Added ASIC revision numbers for PEX511, TCR511PEX, and GPS170PEX
+ * which fix an IRQ bug with these cards.
+ * Added definitions for PTP270PEX, FRC511PEX, and TCR170PEX.
+ * Revision 1.12 2008/07/21 10:30:00Z martin
+ * Added macros to convert the endianess of data types.
+ * Added PCI_ASIC_CURRENT_MINOR_... symbols.
+ * Revision 1.11 2008/06/11 09:49:43 martin
+ * Added definitions and comments how to handle version numbers
+ * of the PCI and PEX interface chips and EPLDs.
+ * Revision 1.10 2008/02/29 15:21:48Z martin
+ * Added definition PCI_ASIC_HAS_MM_IO.
+ * Revision 1.9 2008/01/17 09:51:05 daniel
+ * Added macro _convert_asic_version_number().
+ * Cleanup for PCI ASIC version and features.
+ * Revision 1.8 2006/06/14 12:59:12Z martin
+ * Added support for TCR511PCI.
+ * Revision 1.7 2006/03/10 10:47:03 martin
+ * Added support for PCI511.
+ * Revision 1.6 2005/11/03 15:30:44Z martin
+ * Added support for GPS170PCI.
+ * Revision 1.5 2004/11/09 12:51:56Z martin
+ * Redefined fixed width data types using standard C99 types.
+ * Defined some constants unsigned.
+ * Revision 1.4 2004/10/14 15:01:23 martin
+ * Added support for TCR167PCI.
+ * Revision 1.3 2003/05/13 14:38:55Z MARTIN
+ * Added ushort fields to unions PCI_ASIC_REG and
+ * PCI_ASIC_ADDON_DATA.
+ * Revision 1.2 2003/04/03 10:56:38 martin
+ * Use unions for registers.
+ * Modified BADR0 initializer due to fixed size of address decoder.
+ * Revision 1.1 2003/02/07 11:42:52 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCI_ASIC_H
+#define _PCI_ASIC_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+#include <use_pack.h>
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+#ifdef _PCI_ASIC
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+typedef struct
+{
+ uint32_t cfg_class_rev_id;
+ uint16_t cfg_badr_0;
+ uint16_t cfg_dev_id;
+} PCI_ASIC_CFG;
+
+
+typedef union
+{
+ uint32_t ul;
+ uint16_t us[2];
+ uint8_t b[4];
+} PCI_ASIC_REG;
+
+
+typedef uint32_t PCI_ASIC_VERSION;
+#define _mbg_swab_asic_version( _p ) _mbg_swab32( _p )
+
+typedef uint32_t PCI_ASIC_FEATURES;
+#define _mbg_swab_asic_features( _p ) _mbg_swab32( _p )
+
+#define PCI_ASIC_HAS_MM_IO 0x0001
+#define PCI_ASIC_HAS_PGMB_IRQ 0x0002
+
+
+typedef union
+{
+ uint32_t ul[4];
+ uint16_t us[8];
+ uint8_t b[16];
+} PCI_ASIC_ADDON_DATA;
+
+
+typedef struct
+{
+ PCI_ASIC_CFG cfg; // writeable from add-on once after power-up
+ PCI_ASIC_VERSION raw_version;
+ PCI_ASIC_FEATURES features;
+ PCI_ASIC_REG status_port;
+ PCI_ASIC_REG control_status; // codes defined below
+ PCI_ASIC_REG pci_data; // pass byte from PCI bus to add-on
+ PCI_ASIC_REG reserved_1;
+
+ PCI_ASIC_ADDON_DATA addon_data; // returns data from add-on to PCI bus
+ PCI_ASIC_ADDON_DATA reserved_2; // currently not implemented
+} PCI_ASIC;
+
+
+// The following bits are used with the control_status register.
+// All other bits are reserved for future use.
+
+// The IRQ flag for the add-on side is set whenever data is
+// written to the cmd register. It is cleared if the add-on
+// microcontroller writes this bit back to the control_status
+// register. If the bit is set, the add-on signals /ADD_ON_IRQ
+// and ADD_ON_BUSY are asserted.
+#define PCI_ASIC_ADD_ON_IRQF 0x00000001UL
+
+// The IRQ flag for the PCI bus is set whenever the add-on
+// microcontroller asserts the ASIC's /PCI_IRQ line, or the
+// add-on microcontroller sets this bit to 1. It is cleared
+// if this bit is written back from the PCI side. If the bit
+// is set, an IRQ is asserted on the PCI bus.
+#define PCI_ASIC_PCI_IRQF 0x00010000UL
+
+
+// The ASIC's address decoder always decodes 8 bits, so
+// each device must request at least that number of
+// addresses from the PCI BIOS:
+#define PCI_ASIC_ADDR_RANGE 0x100U
+
+
+// Initializers for device configurations
+
+#define PCPS_DEV_CLASS_CODE 0x08800000UL
+#define PCI_ASIC_BADR0_INIT ( ~( PCI_ASIC_ADDR_RANGE - 1 ) | 0x01 )
+
+
+#define PCI_ASIC_CFG_PCI510 \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_PCI510 ) \
+}
+
+#define PCI_ASIC_CFG_GPS169PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_GPS169PCI ) \
+}
+
+#define PCI_ASIC_CFG_TCR510PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_TCR510PCI ) \
+}
+
+#define PCI_ASIC_CFG_TCR167PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_TCR167PCI ) \
+}
+
+#define PCI_ASIC_CFG_GPS170PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_GPS170PCI ) \
+}
+
+#define PCI_ASIC_CFG_PCI511 \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_PCI511 ) \
+}
+
+#define PCI_ASIC_CFG_TCR511PCI \
+{ \
+ _hilo_32( PCPS_DEV_CLASS_CODE ), \
+ _hilo_16( PCI_ASIC_BADR0_INIT ), \
+ _hilo_16( PCI_DEV_TCR511PCI ) \
+}
+
+/*
+ Handling of the version numbers of the PCI interface
+ chips has changed between the ASICs used for standard PCI
+ and the EPLDs used to configure the PEX8311 chip
+ for a specific device.
+
+ The macro below can be used to convert both types
+ of version number into the same format so that the
+ version numbers can be handled in the same way:
+*/
+#define _convert_asic_version_number( _n ) \
+ ( ( (_n) < 0x100 ) ? ( (_n) << 8 ) : (_n) )
+
+
+
+/*
+ * Macros to extract the major and minor part of an ASIC version number */
+
+#define _pcps_asic_version_major( _v ) \
+ ( ( (_v) >> 8 ) & 0xFF )
+
+#define _pcps_asic_version_minor( _v ) \
+ ( (_v) & 0xFF )
+
+
+/*
+ * Macros to check whether a version number is correct
+ * and matches a required minimum version
+ */
+#define _pcps_asic_version_greater_equal( _v, _v_major, _v_minor ) \
+ ( \
+ ( _pcps_asic_version_major( _v ) == (_v_major) ) && \
+ ( _pcps_asic_version_minor( _v ) >= (_v_minor) ) \
+ )
+
+
+/*
+ The low byte of the converted version number is handled
+ as a minor version, whereas the remaining upper bytes are
+ interpreted as a major number which may be specific
+ for a device.
+*/
+enum
+{
+ PCI_ASIC_MAJOR_PCI_0, // PCI ASIC with CRC bug
+ PCI_ASIC_MAJOR_PCI_1, // fixed version of PCI ASIC
+ PCI_ASIC_MAJOR_PEX511, // PEX EPLD for PEX511
+ PCI_ASIC_MAJOR_GPS170PEX, // PEX EPLD for GPS170PEX
+ PCI_ASIC_MAJOR_TCR511PEX, // PEX EPLD for TCR511PEX
+ PCI_ASIC_MAJOR_PTP270PEX, // PEX EPLD for PTP270PEX
+ PCI_ASIC_MAJOR_FRC511PEX, // PEX EPLD for FRC511PEX
+ PCI_ASIC_MAJOR_TCR170PEX, // PEX EPLD for TCR170PEX
+ N_PCI_ASIC_MAJOR // the number of known codes
+};
+
+/*
+ The minor number increases when a new EPLD image is released.
+ At least EPLD images with the following "required minor" numbers
+ should be installed for proper operation. The "current minor"
+ numbers can be used to check if a newer EPLD image is available:
+*/
+#define PCI_ASIC_CURRENT_MINOR_PEX511 0x04
+#define PCI_ASIC_REQUIRED_MINOR_PEX511 0x03
+#define PCI_ASIC_FIX_HRT_MINOR_PEX511 0x04 // increases HRT accuracy
+#define PCI_ASIC_FIX_IRQ_MINOR_PEX511 0x03 // fixes IRQ problem
+#define PCI_ASIC_HR_TIME_MINOR_PEX511 0x02 // supports HR time with PEX511
+
+#define PCI_ASIC_CURRENT_MINOR_GPS170PEX 0x05
+#define PCI_ASIC_REQUIRED_MINOR_GPS170PEX 0x03
+#define PCI_ASIC_ENH_HRT_MINOR_GPS170PEX 0x05 // enhanced MM HRT accuracy
+#define PCI_ASIC_FIX_HRT_MINOR_GPS170PEX 0x04 // increases MM HRT accuracy
+#define PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX 0x03 // fixes IRQ problem
+
+#define PCI_ASIC_CURRENT_MINOR_TCR511PEX 0x04
+#define PCI_ASIC_REQUIRED_MINOR_TCR511PEX 0x03
+// 0x04 // EPLD sources shared with PEX511 0x04
+#define PCI_ASIC_FIX_IRQ_MINOR_TCR511PEX 0x03 // fixes IRQ problem, increases HRT accuracy
+
+#define PCI_ASIC_CURRENT_MINOR_PTP270PEX 0x01
+#define PCI_ASIC_REQUIRED_MINOR_PTP270PEX 0x01
+
+#define PCI_ASIC_CURRENT_MINOR_FRC511PEX 0x01
+#define PCI_ASIC_REQUIRED_MINOR_FRC511PEX 0x01
+
+#define PCI_ASIC_CURRENT_MINOR_TCR170PEX 0x02
+#define PCI_ASIC_REQUIRED_MINOR_TCR170PEX 0x02
+#define PCI_ASIC_FIX_EE_ACCESS_TCR170PEX 0x02 // fixes EE access problem after reset
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PCI_ASIC_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h b/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h
new file mode 100755
index 0000000..ed365d2
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h
@@ -0,0 +1,251 @@
+
+/**************************************************************************
+ *
+ * $Id: pcidefs.h 1.7 2008/06/09 10:43:09 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Common definitions to be used with PCI.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcidefs.h $
+ * Revision 1.7 2008/06/09 10:43:09 martin
+ * Added PCI_CMD_ENB_MEM_ACC code.
+ * Revision 1.6 2005/09/19 13:06:15Z martin
+ * Added definition for number of base address registers.
+ * Revision 1.5 2004/11/09 13:15:05Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Revision 1.4 2001/02/05 16:28:21Z MARTIN
+ * Don't include stdlib.h.
+ * Revision 1.3 2000/09/11 13:51:10 MARTIN
+ * Moved structure PCI_IRQ_ROUTE_BUFFER to pci_dos.h.
+ * Revision 1.2 2000/07/21 11:56:20 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCIDEFS_H
+#define _PCIDEFS_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+
+
+#ifdef _PCIDEFS
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+// Available PCI subfunction codes depend on the operating system
+// so they are defined in the associated headers.
+
+// The interrupt number used to access PCI BIOS in real mode:
+#define PCI_BIOS_INT 0x1A
+
+
+// The function code is put into the AH register when a PCI function
+// is called:
+#define PCI_BIOS_FNC 0xB1
+
+
+// The PCI subfunction codes listed below are put into the AL register
+// when PCI functions are called. Other registers must be set according
+// to the subfunction specs:
+#define PCI_BIOS_PRESENT 0x01
+#define PCI_FIND_DEVICE 0x02
+#define PCI_FIND_CLASS_CODE 0x03
+#define PCI_GEN_SPECIAL_CYCLE 0x06
+#define PCI_READ_CFG_BYTE 0x08
+#define PCI_READ_CFG_WORD 0x09
+#define PCI_READ_CFG_DWORD 0x0A
+#define PCI_WRITE_CFG_BYTE 0x0B
+#define PCI_WRITE_CFG_WORD 0x0C
+#define PCI_WRITE_CFG_DWORD 0x0D
+#define PCI_GET_IRQ_ROUTING 0x0E
+
+
+// List of PCI BIOS return codes:
+#define PCI_SUCCESS 0x00
+#define PCI_NO_SUCCESS 0x01 // (not returned by BIOS)
+#define PCI_FUNC_NOT_SUPP 0x81
+#define PCI_BAD_VENDOR_ID 0x83
+#define PCI_DEVICE_NOT_FOUND 0x86
+#define PCI_BAD_REGISTER_NUMB 0x87
+#define PCI_BUFFER_TOO_SMALL 0x89
+
+
+// The 80x86 Flags Register Carry Flag bit returns completion status.
+// If the Carry Flag is set, the function call did not succeed.
+#define CARRY_FLAG 0x01
+
+
+// The signature "PCI " is returned in EDX when the subfunction
+// PCI_BIOS_PRESENT has been called:
+#define PCI_BIOS_SIGNATURE 0x20494350UL
+
+
+// The code below represents an invalid vendor id
+// or wildcard:
+#define PCI_INV_VENDOR_ID 0xFFFFU
+
+
+// The number of possible PCI devices per bus:
+#define PCI_DEVICES_PER_BUS 32
+
+
+// A variable of the type below is used to keep
+// the PCI interrupt routing information:
+typedef struct
+{
+ uint8_t bus;
+ uint8_t device_number;
+ uint8_t inta_link;
+ uint16_t inta_map;
+ uint8_t intb_link;
+ uint16_t intb_map;
+ uint8_t intc_link;
+ uint16_t intc_map;
+ uint8_t intd_link;
+ uint16_t intd_map;
+ uint8_t slot;
+ uint8_t reserved;
+} PCI_IRQ_ROUTE_ENTRY;
+
+
+// List of PCI BIOS return codes
+
+#define PCI_SUCCESS 0x00
+#define PCI_NO_SUCCESS 0x01 // not returned by BIOS
+#define PCI_FUNC_NOT_SUPP 0x81
+#define PCI_BAD_VENDOR_ID 0x83
+#define PCI_DEVICE_NOT_FOUND 0x86
+#define PCI_BAD_REGISTER_NUMB 0x87
+#define PCI_BUFFER_TOO_SMALL 0x89
+
+
+
+// The 80x86 flags register carry flag bit returns completion status.
+// If the carry flag is set, the function call did not succeed.
+
+#ifndef CARRY_FLAG
+ #define CARRY_FLAG 0x01
+#endif
+
+
+// The signature "PCI " is returned in EDX when the subfunction
+// PCI_BIOS_PRESENT has been called.
+
+#define PCI_BIOS_SIGNATURE 0x20494350UL
+
+
+// PCI configuration space registers
+
+#define PCI_CS_VENDOR_ID 0x00
+#define PCI_CS_DEVICE_ID 0x02
+#define PCI_CS_COMMAND 0x04
+#define PCI_CS_STATUS 0x06
+#define PCI_CS_REVISION_ID 0x08
+#define PCI_CS_CLASS_CODE 0x09
+#define PCI_CS_CACHE_LINE_SIZE 0x0C
+#define PCI_CS_MASTER_LATENCY 0x0D
+#define PCI_CS_HEADER_TYPE 0x0E
+#define PCI_CS_BIST 0x0F
+#define PCI_CS_BASE_ADDRESS_0 0x10
+#define PCI_CS_BASE_ADDRESS_1 0x14
+#define PCI_CS_BASE_ADDRESS_2 0x18
+#define PCI_CS_BASE_ADDRESS_3 0x1C
+#define PCI_CS_BASE_ADDRESS_4 0x20
+#define PCI_CS_BASE_ADDRESS_5 0x24
+#define PCI_CS_EXPANSION_ROM 0x30
+#define PCI_CS_INTERRUPT_LINE 0x3C
+#define PCI_CS_INTERRUPT_PIN 0x3D
+#define PCI_CS_MIN_GNT 0x3E
+#define PCI_CS_MAX_LAT 0x3F
+
+#define PCI_CS_N_BASE_ADDRESS 6 /* max number of address spaces */
+
+
+#define PCI_CMD_ENB_IO_ACC 0x01
+#define PCI_CMD_ENB_MEM_ACC 0x02
+
+
+typedef struct
+{
+ uint8_t prog_if;
+ uint8_t sub;
+ uint8_t base;
+} PCI_CLASS;
+
+#define PCI_N_BASE_ADDR_FIELD 6
+
+typedef struct
+{
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t command;
+ uint16_t status;
+ uint8_t revision_id;
+ PCI_CLASS class_code;
+ uint8_t cache_line_size;
+ uint8_t latency_timer;
+ uint8_t header_type;
+ uint8_t bist;
+ uint32_t base_addr[PCI_N_BASE_ADDR_FIELD];
+ uint32_t cardbus_cis;
+ uint16_t sub_vendor_id;
+ uint16_t sub_system_id;
+ uint32_t expansion_rom_base;
+ uint32_t res_0;
+ uint32_t res_1;
+ uint8_t irq_line;
+ uint8_t irq_pin;
+ uint8_t min_gnt;
+ uint8_t max_lat;
+} PCI_CFG_SPACE;
+
+
+
+// some known vendor IDs, in alphabetical order:
+
+#define PCI_VENDOR_3COM 0x10B7
+#define PCI_VENDOR_ADAPTEC_1 0x9004
+#define PCI_VENDOR_ADAPTEC_2 0x9005
+#define PCI_VENDOR_AMCC 0x10E8
+#define PCI_VENDOR_AMD 0x1022
+#define PCI_VENDOR_ASUS 0x1000
+#define PCI_VENDOR_CIRRUS_LOGIC 0x1013
+#define PCI_VENDOR_ELSA 0x5333
+#define PCI_VENDOR_IBM 0x1014
+#define PCI_VENDOR_INTEL 0x8086
+#define PCI_VENDOR_MATROX 0x102B
+#define PCI_VENDOR_MEINBERG 0x1360
+
+/* End of header body */
+
+#undef _ext
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// currently none
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PCIDEFS_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h
new file mode 100755
index 0000000..f36b251
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h
@@ -0,0 +1,1276 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsdefs.h 1.46.1.1 2011/02/15 10:55:28 daniel TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * General definitions for Meinberg plug-in radio clocks
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsdefs.h $
+ * Revision 1.46.1.1 2011/02/15 10:55:28 daniel
+ * New command PC_GPS_PTP_UNICAST_CFG
+ * Revision 1.46 2011/01/13 11:44:29Z martin
+ * Moved status port register definitions here.
+ * Revision 1.45 2010/09/06 07:36:24 martin
+ * Support GPS180PEX and TCR180PEX.
+ * Moved some IRIG related definitions to gpsdefs.h.
+ * Revision 1.44 2010/06/30 11:09:49 martin
+ * Added definitions for JJY longwave transmitter.
+ * Renamed MBG_RAW_IRIG_DATA::data field to data_bytes
+ * since "data" is a reserved word for C51 architecture.
+ * Revision 1.43 2010/02/09 11:20:17Z martin
+ * Renamed yet unused CORR_INFO::flags field to signal and updated comments.
+ * Revision 1.42 2010/01/12 14:02:37 daniel
+ * Added definitions to support reading the raw IRIG data bits.
+ * Revision 1.41 2009/06/19 12:16:42Z martin
+ * Added PCPS_GIVE_IRIG_TIME command and associated definitions.
+ * Revision 1.40 2009/06/08 19:29:11 daniel
+ * Support PTP configuration.
+ * Support LAN_IF configuration
+ * Added definition of PCPS_CMD_INFO.
+ * Revision 1.39 2009/03/19 08:58:09 martin
+ * Added PCPS_GET_IRIG_CTRL_BITS cmd and associated data type.
+ * Revision 1.38 2009/03/10 17:07:09 martin
+ * Support configurable time scales and GPS UTC parameters.
+ * Added ext. status flag for time scales, and PCPS_LS_ANN_NEG.
+ * Added bit mask PCPS_SCALE_MASK.
+ * Revision 1.37 2008/12/05 16:01:37Z martin
+ * Added ref types PTP, FRC, and WWVB.
+ * Added ref names MSF, PTP, FRC, and WWVB.
+ * Added device codes TCR170PEX, PTP270PEX, and FRC511PEX.
+ * Added macros to convert the endianess of structures.
+ * Moved definitions of PCPS_HRT_FRAC_SCALE and
+ * PCPS_HRT_FRAC_SCALE_FMT here.
+ * Added definitions of PCPS_HRT_FRAC_CONVERSION_TYPE
+ * and PCPS_HRT_BIN_FRAC_SCALE.
+ * Escaped '<' and '>' characters for doxygen.
+ * Modified comments for PCPS_TZDL.
+ * Removed trailing spaces and obsolete comments.
+ * Revision 1.36 2008/01/17 09:20:25Z daniel
+ * Added new REF type PCPS_REF_MSF.
+ * Revision 1.35 2008/01/17 09:18:46Z daniel
+ * Made comments compatible for doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.34 2007/07/17 08:22:47Z martin
+ * Added support for TCR511PEX and GPS170PEX.
+ * Revision 1.33 2007/05/20 21:39:51Z martin
+ * Added support for PEX511.
+ * Added PCPS_GET_STATUS_PORT cmd code for devices
+ * that do not support a hardware status port.
+ * Revision 1.32 2007/03/29 12:57:32Z martin
+ * Renamed some TZCODE numbers for unique naming conventions.
+ * Added definitions of the older symbols for compatibility.
+ * Revision 1.31 2007/03/26 15:42:31Z martin
+ * Replaced PCPS_REF_OFFS and associated definitions by MBG_REF_OFFS, etc.,
+ * which are defined in gpsdefs.h.
+ * Added PCPS_GET_DEBUG_STATUS code.
+ * Revision 1.30 2006/06/29 10:13:13 martin
+ * Added some descriptive comments.
+ * Revision 1.29 2006/06/14 12:59:12Z martin
+ * Added support for TCR511PCI.
+ * Revision 1.28 2006/05/18 09:45:16 martin
+ * Added data types used with PZF receivers.
+ * Revision 1.27 2006/05/03 10:19:14Z martin
+ * Added initializers for reference source names.
+ * Revision 1.26 2006/03/10 10:24:45Z martin
+ * New definitions for PCI511.
+ * Added command codes to configure programmable pulse outputs.
+ * Revision 1.25 2005/11/03 15:05:16Z martin
+ * New definitions for GPS170PCI.
+ * New types PCPS_TIME_STATUS and PCPS_TIME_STATUS_X.
+ * Removed obsolete enumeration of PCPS_TIME fields.
+ * Revision 1.24 2005/05/03 07:56:55Z martin
+ * Added command PCPS_GET_SYNTH_STATE.
+ * Revision 1.23 2005/03/29 12:51:10Z martin
+ * New cmd code PCPS_GENERIC_IO.
+ * Revision 1.22 2004/12/09 11:03:37Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.21 2004/11/09 12:55:32Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Added workaround macros for some structure sizes because the C166
+ * compiler always reports an even structure size even if the structure
+ * size is in fact odd, which might lead to different sizes in C166 and
+ * other environments.
+ * Modifications were required in order to be able to configure IRIG
+ * settings of cards which provide both IRIG input and output.
+ * The existing codes have been renamed with .._RX.. and are used to
+ * configure the IRIG receiver (input). New codes have been defined
+ * used to configure the IRIG transmitter.
+ * Renamed PC_GPS_STAT to PC_GPS_BVAR_STAT.
+ * Use more specific data types than generic types.
+ * Revision 1.20 2004/10/14 15:01:23 martin
+ * Added support for TCR167PCI.
+ * Revision 1.19 2004/06/16 12:46:33Z martin
+ * Moved OPT_SETTINGS related definitions to gpsdefs.h,
+ * and renamed symbols from PCPS_.. to to MBG_...
+ * Revision 1.18 2004/04/26 14:27:08Z martin
+ * Added union PCPS_TIME_UNION.
+ * Revision 1.17 2003/05/27 08:50:35Z MARTIN
+ * New commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT
+ * and associated definitions which allow faster reading of
+ * user capture events and monitoring of the capture buffer
+ * fill level.
+ * Revision 1.16 2003/04/03 10:48:53 martin
+ * Support for PCI510, GPS169PCI, and TCR510PCI.
+ * New codes PCPS_GET_REF_OFFS, PCPS_SET_REF_OFFS
+ * and related structures.
+ * New codes PCPS_GET_OPT_INFO, PCPS_SET_OPT_SETTINGS
+ * and related structures.
+ * New codes PCPS_GET_IRIG_INFO, PCPS_SET_IRIG_SETTINGS.
+ * Preliminary PCPS_TZDL structure and cmd codes
+ * to read/write that structure.
+ * Revision 1.15 2002/08/08 13:24:03 MARTIN
+ * Moved definition of ref time sources here.
+ * Added new ref time source IRIG.
+ * Added new cmd to clear time capture buffer.
+ * Fixed some comments.
+ * Revision 1.14 2002/01/31 13:39:38 MARTIN
+ * Added new GPS data type codes for RECEIVER_INFO, etc.
+ * New PCPS_HR_TIME status flag PCPS_IO_BLOCKED.
+ * Moved REV_NUMs defining special features to pcpsdev.h.
+ * Removed obsolete initializer for framing string table.
+ * Updated some comments.
+ * Removed obsolete code.
+ * Revision 1.13 2001/12/03 16:15:14 martin
+ * Introduced PCPS_TIME_STAMP which allows to handle high precision
+ * time stamps.
+ * Replaced the sec/frac fields in PCPS_HR_TIME by PCPS_TIME_STAMP.
+ * This is compatible on byte level but may require source code
+ * modifications.
+ * Introduced new command PCPS_SET_EVENT_TIME which is used
+ * EXCLUSIVELY with a custom GPS firmware.
+ * Revision 1.12 2001/10/16 10:07:42 MARTIN
+ * Defined PCI509 firmware revision number which supports
+ * baud rate higher than standard.
+ * Revision 1.11 2001/03/30 13:02:39 MARTIN
+ * Control alignment of structures from new file use_pack.h.
+ * Defined initializers with valid framing parameters.
+ * Revision 1.10 2001/02/28 15:39:25 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.9 2001/02/16 11:32:05 MARTIN
+ * Renamed "PROM" or "EPROM" in comments or and names to
+ * "FW" or firmware.
+ * This includes the cmd codes PCPS_GIVE_PROM_ID_... which have
+ * been renamed to PCPS_GIVE_FW_ID_...
+ * Renamed structure PCPS_TIME_SET to PCPS_STIME.
+ * Renamed return code PCPS_ERR_NONE to PCPS_SUCCESS.
+ * Modified some comments.
+ * Revision 1.8 2000/10/11 09:17:09 MARTIN
+ * Cleaned up comment syntax.
+ * Revision 1.7 2000/07/21 14:16:30 MARTIN
+ * Modified some comments.
+ * Added PCI definitions.
+ * Renamed PCPS_GET_GPS_DATA to PCPS_READ_GPS_DATA.
+ * Renamed PCPS_SET_GPS_DATA to PCPS_WRITE_GPS_DATA.
+ * New types PCPS_SERIAL and PCPS_TZCODE.
+ * Removed PCPS_SERIAL_BYTES and PCPS_TZCODE_BYTES, may use sizeof()
+ * the types instead.
+ * New type PCPS_TIME_SET which can be used to write date and time
+ * to the clock.
+ * Revision 1.6 2000/06/07 12:09:31 MARTIN
+ * renamed PCPS_SERIAL_GROUP to PCPS_CFG_GROUP
+ * renamed PCPS_ERR_SERIAL to PCPS_ERR_CFG
+ * modified definitions for baud rate, framing, and mode
+ * added PCPS_SN_... definitions
+ * added PCPS_GET_TZCODE and PCPS_SET_TZCODE definitions
+ * added PC_GPS_ANT_CABLE_LEN definition
+ * added RCS keywords
+ * updated some comments
+ *
+ * -----------------------------------------------------------------------
+ * Changes before put under RCS control:
+ *
+ * Revision 1.5 2000/03/24
+ * Introduced PCPS_GIVE_SERNUM
+ * Cleaned up for definitions for serial parameter byte
+ * Reviewed and updated comments.
+ *
+ * 1998/07/22
+ * Introduced PCPS_HR_TIME.
+ * Rearranged order of definitions.
+ * Reviewed and updated comments.
+ *
+ * 1997/06/12
+ * GPS definitions added.
+ *
+ * 1996/01/25
+ * PCPS_TIME redefined from an array of bytes to a structure.
+ *
+ **************************************************************************/
+
+#ifndef _PCPSDEFS_H
+#define _PCPSDEFS_H
+
+
+/* Other headers to be included */
+
+#include <words.h>
+#include <use_pack.h>
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+/**
+ * The following codes enumerate the ref time sources
+ * from which the clocks receive the reference time.
+ */
+enum
+{
+ PCPS_REF_NONE, /**< (unknown or not defined) */
+ PCPS_REF_DCF, /**< see http://www.meinberg.de/english/info/dcf77.htm */
+ PCPS_REF_GPS, /**< see http://www.meinberg.de/english/info/gps.htm */
+ PCPS_REF_IRIG, /**< see http://www.meinberg.de/english/info/irig.htm */
+ PCPS_REF_MSF, /**< MSF Receiver (UK) */
+ PCPS_REF_PTP, /**< PTP Timestamp card */
+ PCPS_REF_FRC, /**< Free Running Clock */
+ PCPS_REF_WWVB, /**< WWVB Receiver (US) */
+ PCPS_REF_JJY, /**< JJY Receiver (Japan) */
+ N_PCPS_REF /**< number of valid ref time sources */
+};
+
+
+/* Initializers for the reference source names */
+
+#define PCPS_REF_NAME_NONE_ENG "unknown"
+#define PCPS_REF_NAME_NONE_GER "nicht bekannt"
+#define PCPS_REF_NAME_DCF "DCF77"
+#define PCPS_REF_NAME_GPS "GPS"
+#define PCPS_REF_NAME_IRIG "IRIG"
+#define PCPS_REF_NAME_MSF "MSF"
+#define PCPS_REF_NAME_PTP "PTP"
+#define PCPS_REF_NAME_FRC "FRC"
+#define PCPS_REF_NAME_WWVB "WWVB"
+#define PCPS_REF_NAME_JJY "JJY"
+
+
+#define PCPS_REF_NAMES_ENG \
+{ \
+ PCPS_REF_NAME_NONE_ENG, \
+ PCPS_REF_NAME_DCF, \
+ PCPS_REF_NAME_GPS, \
+ PCPS_REF_NAME_IRIG, \
+ PCPS_REF_NAME_MSF, \
+ PCPS_REF_NAME_PTP, \
+ PCPS_REF_NAME_FRC, \
+ PCPS_REF_NAME_WWVB, \
+ PCPS_REF_NAME_JJY \
+}
+
+
+#define PCPS_REF_NAMES_LSTR \
+{ \
+ { PCPS_REF_NAME_NONE_ENG, PCPS_REF_NAME_NONE_GER }, \
+ { PCPS_REF_NAME_DCF, NULL }, \
+ { PCPS_REF_NAME_GPS, NULL }, \
+ { PCPS_REF_NAME_IRIG, NULL }, \
+ { PCPS_REF_NAME_MSF, NULL }, \
+ { PCPS_REF_NAME_PTP, NULL }, \
+ { PCPS_REF_NAME_FRC, NULL }, \
+ { PCPS_REF_NAME_WWVB, NULL }, \
+ { PCPS_REF_NAME_JJY, NULL } \
+}
+
+
+
+/**
+ PCI vendor ID number (assigned by PCI SIG)
+*/
+#define PCI_VENDOR_MEINBERG 0x1360
+
+/* PCI device ID numbers (assigned by Meinberg) *
+ * High byte: type of ref time source
+ * Low Byte: enumeration of device types
+ */
+#define PCI_DEV_PCI32 ( ( PCPS_REF_DCF << 8 ) | 0x01 )
+#define PCI_DEV_PCI509 ( ( PCPS_REF_DCF << 8 ) | 0x02 )
+#define PCI_DEV_PCI510 ( ( PCPS_REF_DCF << 8 ) | 0x03 )
+#define PCI_DEV_PCI511 ( ( PCPS_REF_DCF << 8 ) | 0x04 )
+#define PCI_DEV_PEX511 ( ( PCPS_REF_DCF << 8 ) | 0x05 )
+
+#define PCI_DEV_GPS167PCI ( ( PCPS_REF_GPS << 8 ) | 0x01 )
+#define PCI_DEV_GPS168PCI ( ( PCPS_REF_GPS << 8 ) | 0x02 )
+#define PCI_DEV_GPS169PCI ( ( PCPS_REF_GPS << 8 ) | 0x03 )
+#define PCI_DEV_GPS170PCI ( ( PCPS_REF_GPS << 8 ) | 0x04 )
+#define PCI_DEV_GPS170PEX ( ( PCPS_REF_GPS << 8 ) | 0x05 )
+#define PCI_DEV_GPS180PEX ( ( PCPS_REF_GPS << 8 ) | 0x06 )
+
+#define PCI_DEV_TCR510PCI ( ( PCPS_REF_IRIG << 8 ) | 0x01 )
+#define PCI_DEV_TCR167PCI ( ( PCPS_REF_IRIG << 8 ) | 0x02 )
+#define PCI_DEV_TCR511PCI ( ( PCPS_REF_IRIG << 8 ) | 0x03 )
+#define PCI_DEV_TCR511PEX ( ( PCPS_REF_IRIG << 8 ) | 0x04 )
+#define PCI_DEV_TCR170PEX ( ( PCPS_REF_IRIG << 8 ) | 0x05 )
+#define PCI_DEV_TCR180PEX ( ( PCPS_REF_IRIG << 8 ) | 0x06 )
+
+#define PCI_DEV_PTP270PEX ( ( PCPS_REF_PTP << 8 ) | 0x01 )
+
+#define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 )
+
+
+
+// definitions used for the status port register
+// (not to be intermixed with PCPS_TIME_STATUS)
+typedef uint8_t PCPS_STATUS_PORT; /**< see \ref group_status_port "Bitmask" */
+
+/** @defgroup group_status_port Bit masks of PCPS_STATUS_PORT
+
+ Bit definitions used with the #PCPS_STATUS_PORT register.
+
+ The flags #PCPS_ST_SEC and #PCPS_ST_MIN are cleared whenever the clock
+ is read, so they are not very reliable in multitasking environments.
+
+ <b>NOTE</b>: The PCPS_ST_IRQF flag originates from old ISA cards.
+ Some PCI cards also support this, but in case of PCI cards the
+ associated flag of the PCI interface chip should be checked to see
+ if a certain card has generated an IRQ on the PC bus.
+
+ The macro _pcps_ddev_has_gen_irq() cares about this and should be used
+ to determine in a portable way whether a card has generated an IRQ.
+
+ * @{
+ */
+
+#define PCPS_ST_BUSY 0x01 /**< the clock is busy filling the output FIFO */
+#define PCPS_ST_IRQF 0x02 /**< the clock has generated an IRQ on the PC bus (ISA only)*/
+#define PCPS_ST_MOD 0x20 /**< the raw demodulated DCF77 signal */
+#define PCPS_ST_SEC 0x40 /**< seconds have changed since last reading */
+#define PCPS_ST_MIN 0x80 /**< minutes have changed since last reading */
+
+/** @} */
+
+
+
+/** @defgroup group_cmd_bytes Command bytes used to access the device
+
+ The commands described below can be used to access the Meinberg
+ computer peripherals. However, some of the commands have not been
+ implemented with older clock models, or firmware versions.
+
+ The device driver library contains functions which detect the clocks
+ and check which features are supported by a given clock model/firmware
+ The header files pcpsdev.h and pcpsdrvr.h contain macros which can be
+ used to query whether a detected clock supports a feature.
+ If checking is required, the name of the macro is given in the
+ comments below.
+
+ Some commands expect parameters to be passed to the board. In that
+ case, the board returns the number of parameter bytes expected when
+ the command code is passed. Every parameter byte has to be supplied
+ to the board exactly like a command byte.
+ Refer to function pcps_write_data() and the macro _pcps_write_var()
+ for details.
+
+
+ - #PCPS_GIVE_TIME<br>
+ Return a PCPS_TIME structure with current date,
+ time and status. Supported by all clocks.
+
+ - #PCPS_GIVE_TIME_NOCLEAR<br>
+ Same as #PCPS_GIVE_TIME but the bits #PCPS_ST_SEC
+ and #PCPS_ST_MIN (see pcpsdev.h) of the status
+ port are not cleared.
+ Supported by all clocks except PC31/PS31 with
+ firmware version older than v3.0.
+ This is mainly used by the DOS TSR and should
+ not be used in other environments.
+
+ - #PCPS_GIVE_SYNC_TIME<br>
+ Return a ::PCPS_TIME structure with date and time
+ of last synchronization of the clock or
+ the last time set via the interface.
+ _pcps_has_sync_time() checks whether supported.
+
+ - #PCPS_GIVE_HR_TIME<br>
+ Return a PCPS_HR_TIME structure with current
+ date, time and status. This command should be
+ used to read the clock with higher resolution.
+ _pcps_has_hr_time() checks whether supported.
+
+ - #PCPS_GIVE_IRIG_TIME<br>
+ Return a PCPS_IRIG_TIME structure with day-of-year,
+ time and status as decoded from the IRIG signal.
+ _pcps_has_irig_time() checks whether supported.
+
+ - #PCPS_SET_TIME<br>
+ Set the board date, time and status. This
+ command expects sizeof( ::PCPS_STIME ) parameter
+ bytes.
+ _pcps_can_set_time() checks whether supported.
+
+ - #PCPS_SET_EVENT_TIME<br>
+ Send a high resolution time stamp to the clock to
+ configure a UTC time when the clock shall generate
+ some event. This command expects a PCPS_TIME_STAMP
+ parameter.
+ _pcps_has_event_time() checks whether supported.
+ (requires custom GPS CERN firmware)
+
+ - #PCPS_IRQ_NONE<br>
+ Disable the board's hardware IRQ<br>
+ - #PCPS_IRQ_1_SEC<br>
+ Enable hardware IRQs once per second<br>
+ - #PCPS_IRQ_1_MIN<br>
+ Enable hardware IRQs once per minute<br>
+ - #PCPS_IRQ_10_MIN<br>
+ Enable hardware IRQs once per 10 minutes<br>
+ - #PCPS_IRQ_30_MIN<br>
+ Enable hardware IRQs once per 30 minutes<br>
+
+ - #PCPS_GET_SERIAL<br>
+ #PCPS_SET_SERIAL<br>
+ These commands read or set the configuration
+ of a clock's serial port COM0. The commands
+ expect PCPS_SERIAL_BYTES parameter bytes and
+ should be used preferably with the DCF77
+ clocks which have only one COM port.
+ _pcps_has_serial() checks whether supported.
+ Recent GPS clocks' COM ports should be cfg'd
+ using the structures RECEIVER_INFO, PORT_INFO,
+ and STR_TYPE_INFO.
+ _pcps_has_receiver_info() checks whether
+ these are supported. If they are not, then
+ the code #PC_GPS_PORT_PARM together with the
+ #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA
+ commands should be used.
+
+ - #PCPS_GET_TZCODE<br>
+ #PCPS_SET_TZCODE<br>
+ These commands read or set a DCF77 clock's
+ time zone code and should be used preferably
+ with the newer DCF77 clocks which have limited
+ support of different time zones.
+ _pcps_has_tzcode() checks whether supported.
+ A GPS clock's time zone must be cfg'd using
+ the code #PC_GPS_TZDL together with the
+ #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA
+ commands.
+
+ - #PCPS_GET_PCPS_TZDL<br>
+ #PCPS_SET_PCPS_TZDL<br>
+ These commands read or set a DCF77 clock's
+ time zone / daylight saving configuration.
+ _pcps_has_pcps_tzdl() checks whether supported.
+ A GPS clock's time zone must be cfg'd using
+ the code #PC_GPS_TZDL together with the
+ #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA
+ commands.
+
+ - #PCPS_GET_REF_OFFS<br>
+ #PCPS_SET_REF_OFFS<br>
+ These commands can be used to configure the
+ reference time offset from UTC for clocks
+ which can't determine the offset automatically,
+ e.g. from an IRIG input signal.
+ _pcps_has_ref_offs() checks whether supported.
+
+ - #PCPS_GET_OPT_INFO<br>
+ #PCPS_SET_OPT_SETTINGS<br>
+ These commands can be used to configure some
+ optional settings, controlled by flags.
+ When reading, the clock returns a MBG_OPT_INFO
+ structure which contains the supported values,
+ plus the current settings.
+ When writing, clocks accepts a MBG_OPT_SETTINGS
+ structure only which contain the desired settings
+ of the supported flags only.
+ _pcps_has_opt_flags() checks whether supported.
+
+ - #PCPS_GET_IRIG_RX_INFO<br>
+ #PCPS_SET_IRIG_RX_SETTINGS<br>
+ #PCPS_GET_IRIG_TX_INFO<br>
+ #PCPS_SET_IRIG_TX_SETTINGS<br>
+ These commands can be used to configure IRIG
+ inputs and outputs.<br>
+ When reading, the clock returns an IRIG_INFO
+ structure which contains the supported values,
+ plus the current settings.<br>
+ When writing, clocks accepts an IRIG_SETTINGS
+ structure only which contain the desired settings
+ only. _pcps_is_irig_rx() and _pcps_is_irig_tx()
+ check whether supported.
+
+ - #PCPS_GET_IRIG_CTRL_BITS<br>
+ This command can be used to retrieve the control function
+ bits of the latest IRIG input frame. Those bits may carry
+ some well-known information as in the IEEE1344 code, but
+ may also contain some customized information, depending on
+ the IRIG frame type and the configuration of the IRIG generator.
+ So these bits are returned as-is and must be interpreted
+ by the application.
+ _pcps_has_irig_ctrl_bits() checks whether supported.
+
+ - #PCPS_GET_SYNTH<br>
+ #PCPS_SET_SYNTH<br>
+ #PCPS_GET_SYNTH_STATE<br>
+ These commands can be used to configure an on-board
+ frequency synthesizer and query the synthesizer
+ status. The commands are only supported if the board
+ supports the RECEIVER_INFO structure and the flag
+ #GPS_HAS_SYNTH is set in the RECEIVER_INFO::features.
+ _pcps_has_synth() checks whether supported.
+ The structures SYNTH and SYNTH_STATE used with these
+ commands are defined in gpsdefs.h.
+
+ - #PCPS_GIVE_FW_ID_1<br>
+ #PCPS_GIVE_FW_ID_2<br>
+ Returns the first/second block of PCPS_FIFO_SIZE
+ characters of the firmware ID string. These
+ commands can be used to check if the board
+ responds properly. This is done by the clock
+ detection functions.
+
+ - #PCPS_GIVE_SERNUM<br>
+ Returns PCPS_FIFO_SIZE characters of the
+ clock's serial number.
+ _pcps_has_sernum() checks whether supported.
+
+ - #PCPS_GENERIC_IO<br>
+ Generic I/O read and write. Can be used to query
+ specific data, e.g. a selected element of an array.
+ _pcps_has_generic_io() checks whether supported.
+
+ - #PCPS_GET_DEBUG_STATUS<br>
+ This command reads a MBG_DEBUG_STATUS structure
+ which represents the internal status of the
+ IRIG decoder and some additional debug info.
+ _pcps_has_debug_status() checks whether supported.
+
+ - #PCPS_READ_GPS_DATA<br>
+ #PCPS_WRITE_GPS_DATA<br>
+ These commands are used by the functions
+ pcps_read_gps_data() and pcps_write_gps_data()
+ to read or write large data structures to
+ Meinberg GPS plug-in clocks.
+ _pcps_is_gps() checks whether supported.
+
+ - #PCPS_CLR_UCAP_BUFF<br>
+ Clear a clock's time capture buffer.
+ _pcps_can_clr_ucap_buff() checks whether
+ supported.
+
+ - #PCPS_GIVE_UCAP_ENTRIES<br>
+ Read a PCPS_UCAP_ENTRIES structure which
+ reports the max number of entries and the
+ currently used number of entries in the
+ user capture buffer.
+ _pcps_has_ucap() checks whether supported.
+
+ - #PCPS_GIVE_UCAP_EVENT<br>
+ Read capture events using a PCPS_HR_TIME
+ structure. This is faster than reading using the
+ GPS command #PC_GPS_UCAP. If no capture event is
+ available then the structure is filled with 0s.
+ _pcps_has_ucap() checks whether supported.
+
+ - #PCPS_FORCE_RESET<br>
+ Resets the microprocessor on the radio clock
+ board. This is for debug purposes only and
+ should not be used by standard applications.
+
+ The command codes listed above are defined below. The commands are
+ grouped for bytes having the same high nibble:
+ @{
+*/
+#define PCPS_GIVE_TIME_GROUP 0x00
+#define PCPS_SET_TIME_GROUP 0x10
+#define PCPS_IRQ_GROUP 0x20
+#define PCPS_CFG_GROUP 0x30
+#define PCPS_GIVE_DATA_GROUP 0x40
+#define PCPS_GPS_DATA_GROUP 0x50
+#define PCPS_CTRL_GROUP 0x60
+#define PCPS_CFG2_GROUP 0x70
+
+
+/* PCPS_GIVE_TIME_GROUP */
+#define PCPS_GIVE_TIME ( PCPS_GIVE_TIME_GROUP | 0x0 )
+#define PCPS_GIVE_TIME_NOCLEAR ( PCPS_GIVE_TIME_GROUP | 0x1 )
+#define PCPS_GIVE_SYNC_TIME ( PCPS_GIVE_TIME_GROUP | 0x2 ) // only supported if _pcps_has_sync_time()
+#define PCPS_GIVE_HR_TIME ( PCPS_GIVE_TIME_GROUP | 0x3 ) // only supported if _pcps_has_hr_time()
+#define PCPS_GIVE_IRIG_TIME ( PCPS_GIVE_TIME_GROUP | 0x4 ) // only supported if _pcps_has_irig_time()
+
+
+/* PCPS_SET_TIME_GROUP */
+#define PCPS_SET_TIME ( PCPS_SET_TIME_GROUP | 0x0 )
+/* on error, return PCPS_ERR_STIME */
+
+/* Attention: The code below can be used EXCLUSIVELY */
+/* with a GPS167PCI with customized CERN firmware !! */
+/* _pcps_has_event_time() checks whether supported. */
+#define PCPS_SET_EVENT_TIME ( PCPS_SET_TIME_GROUP | 0x4 )
+
+
+/* PCPS_IRQ_GROUP */
+#define PCPS_IRQ_NONE ( PCPS_IRQ_GROUP | 0x0 )
+#define PCPS_IRQ_1_SEC ( PCPS_IRQ_GROUP | 0x1 )
+#define PCPS_IRQ_1_MIN ( PCPS_IRQ_GROUP | 0x2 )
+#define PCPS_IRQ_10_MIN ( PCPS_IRQ_GROUP | 0x4 )
+#define PCPS_IRQ_30_MIN ( PCPS_IRQ_GROUP | 0x8 )
+
+
+/* PCPS_CFG_GROUP */
+
+#define PCPS_GET_SERIAL ( PCPS_CFG_GROUP | 0x0 )
+#define PCPS_SET_SERIAL ( PCPS_CFG_GROUP | 0x1 )
+/* on error, return PCPS_ERR_CFG */
+
+typedef uint8_t PCPS_SERIAL;
+
+
+#define PCPS_GET_TZCODE ( PCPS_CFG_GROUP | 0x2 )
+#define PCPS_SET_TZCODE ( PCPS_CFG_GROUP | 0x3 )
+/* on error, return PCPS_ERR_CFG */
+
+typedef uint8_t PCPS_TZCODE;
+
+/* the following codes are used with the PCPS_TZCODE parameter: */
+enum
+{
+ PCPS_TZCODE_CET_CEST, /* default as broadcasted by DCF77 (UTC+1h/UTC+2h) */
+ PCPS_TZCODE_CET, /* always CET (UTC+1h), discard DST */
+ PCPS_TZCODE_UTC, /* always UTC */
+ PCPS_TZCODE_EET_EEST, /* East European Time, CET/CEST + 1h */
+ N_PCPS_TZCODE /* the number of valid codes */
+};
+
+/* the definitions below are for compatibily only: */
+#define PCPS_TZCODE_MEZMESZ PCPS_TZCODE_CET_CEST
+#define PCPS_TZCODE_MEZ PCPS_TZCODE_CET
+#define PCPS_TZCODE_OEZ PCPS_TZCODE_EET_EEST
+
+
+#define PCPS_GET_PCPS_TZDL ( PCPS_CFG_GROUP | 0x4 )
+#define PCPS_SET_PCPS_TZDL ( PCPS_CFG_GROUP | 0x5 )
+/* on error, return PCPS_ERR_CFG */
+
+/**
+ * The structures below can be used to configure a clock's
+ * time zone/daylight saving setting. This structure is shorter
+ * than the TZDL structure used with GPS clocks.
+ */
+typedef struct
+{
+ // The year_or_wday field below contains the full year number
+ // or 0..6 == Sun..Sat if the DL_AUTO_FLAG is set; see below.
+ uint16_t year_or_wday;
+ uint8_t month;
+ uint8_t mday;
+ uint8_t hour;
+ uint8_t min;
+} PCPS_DL_ONOFF;
+
+#define _mbg_swab_pcps_dl_onoff( _p ) \
+{ \
+ _mbg_swab16( &(_p)->year_or_wday ); \
+}
+
+/**
+ * If the field year_or_wday is or'ed with the constant DL_AUTO_FLAG
+ * defined below then this means that start and end of daylight saving
+ * time shall be computed automatically for each year. In this case
+ * the remaining bits represent the day-of-week after the specified
+ * mday/month at which the change shall occur. If that flag is not set
+ * then the field contains the full four-digit year number and the
+ * mday/month values specify the exact date of that year.
+ */
+#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h
+
+typedef struct
+{
+ int16_t offs; /**< offset from UTC to local time [min] */
+ int16_t offs_dl; /**< additional offset if DST enabled [min] */
+ PCPS_DL_ONOFF tm_on; /**< date/time when daylight saving starts */
+ PCPS_DL_ONOFF tm_off; /**< date/time when daylight saving ends */
+} PCPS_TZDL;
+
+#define _mbg_swab_pcps_tzdl( _p ) \
+{ \
+ _mbg_swab16( &(_p)->offs ); \
+ _mbg_swab16( &(_p)->offs_dl ); \
+ _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \
+ _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \
+}
+
+
+
+#define PCPS_GET_REF_OFFS ( PCPS_CFG_GROUP | 0x6 )
+#define PCPS_SET_REF_OFFS ( PCPS_CFG_GROUP | 0x7 )
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated type MBG_REF_OFFS is defined in gpsdefs.h. */
+
+
+#define PCPS_GET_OPT_INFO ( PCPS_CFG_GROUP | 0x8 )
+#define PCPS_SET_OPT_SETTINGS ( PCPS_CFG_GROUP | 0x9 )
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated structures MBG_OPT_INFO and MBG_OPT_SETTINGS
+ are defined in gpsdefs.h. */
+
+
+#define PCPS_GET_IRIG_RX_INFO ( PCPS_CFG_GROUP | 0xA )
+#define PCPS_SET_IRIG_RX_SETTINGS ( PCPS_CFG_GROUP | 0xB )
+/* on error, return PCPS_ERR_CFG */
+
+#define PCPS_GET_IRIG_TX_INFO ( PCPS_CFG_GROUP | 0xC )
+#define PCPS_SET_IRIG_TX_SETTINGS ( PCPS_CFG_GROUP | 0xD )
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated structures IRIG_INFO and IRIG_SETTINGS
+ are defined in gpsdefs.h. */
+
+
+#define PCPS_GET_SYNTH ( PCPS_CFG_GROUP | 0xE )
+#define PCPS_SET_SYNTH ( PCPS_CFG_GROUP | 0xF )
+/* on error, return PCPS_ERR_CFG */
+
+/* The associated structure SYNTH is defined in gpsdefs.h. */
+
+
+
+/* PCPS_GIVE_DATA_GROUP */
+#define PCPS_GIVE_FW_ID_1 ( PCPS_GIVE_DATA_GROUP | 0x0 )
+#define PCPS_GIVE_FW_ID_2 ( PCPS_GIVE_DATA_GROUP | 0x1 )
+#define PCPS_GIVE_SERNUM ( PCPS_GIVE_DATA_GROUP | 0x2 )
+#define PCPS_GENERIC_IO ( PCPS_GIVE_DATA_GROUP | 0x3 )
+#define PCPS_GET_SYNTH_STATE ( PCPS_GIVE_DATA_GROUP | 0x4 )
+#define PCPS_GET_IRIG_CTRL_BITS ( PCPS_GIVE_DATA_GROUP | 0x5 )
+#define PCPS_GET_RAW_IRIG_DATA ( PCPS_GIVE_DATA_GROUP | 0x6 )
+
+
+
+#define PCPS_GET_STATUS_PORT ( PCPS_GIVE_DATA_GROUP | 0xB )
+#define PCPS_GET_DEBUG_STATUS ( PCPS_GIVE_DATA_GROUP | 0xC )
+// expects sizeof( MBG_DEBUG_STATUS ) chars
+
+// PCPS_GIVE_DATA_GROUP codes 0x0D, 0x0E, and 0x0F are reserved.
+
+
+/* PCPS_GPS_DATA_GROUP */
+#define PCPS_READ_GPS_DATA ( PCPS_GPS_DATA_GROUP | 0x0 )
+#define PCPS_WRITE_GPS_DATA ( PCPS_GPS_DATA_GROUP | 0x1 )
+
+
+/* PCPS_CTRL_GROUP */
+#define PCPS_CLR_UCAP_BUFF ( PCPS_CTRL_GROUP | 0x0 )
+#define PCPS_GIVE_UCAP_ENTRIES ( PCPS_CTRL_GROUP | 0x1 )
+#define PCPS_GIVE_UCAP_EVENT ( PCPS_CTRL_GROUP | 0x2 )
+
+typedef struct
+{
+ uint32_t used; /**< the number of saved capture events */
+ uint32_t max; /**< capture buffer size */
+} PCPS_UCAP_ENTRIES;
+
+#define _mbg_swab_pcps_ucap_entries( _p ) \
+{ \
+ _mbg_swab32( &(_p)->used ); \
+ _mbg_swab32( &(_p)->max ); \
+}
+
+
+
+/**
+ special -- use with care !
+*/
+#define PCPS_FORCE_RESET 0x80
+
+/** @} */
+
+/* Codes returned when commands with parameters have been passed */
+/* to the board */
+#define PCPS_SUCCESS 0 /**< OK, no error */
+#define PCPS_ERR_STIME -1 /**< invalid date/time/status passed */
+#define PCPS_ERR_CFG -2 /**< invalid parms with a PCPS_CFG_GROUP cmd */
+
+
+
+#ifndef BITMASK
+ #define BITMASK( b ) ( ( 1 << b ) - 1 )
+#endif
+
+
+/** The size of the plug-in radio clock's on-board FIFO: */
+#define PCPS_FIFO_SIZE 16
+
+typedef int8_t PCPS_BUFF[PCPS_FIFO_SIZE];
+
+
+#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */
+typedef char PCPS_ID_STR[PCPS_ID_SIZE];
+
+
+#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */
+typedef char PCPS_SN_STR[PCPS_SN_SIZE];
+
+
+/**
+ * The structure has been introduced to be able to handle
+ * high resolution time stamps.
+ */
+typedef struct
+{
+ uint32_t sec; /**< seconds since 1970 (UTC) */
+ uint32_t frac; /**< fractions of second ( 0xFFFFFFFF == 0.9999.. sec) */
+} PCPS_TIME_STAMP;
+
+#define _mbg_swab_pcps_time_stamp( _p ) \
+{ \
+ _mbg_swab32( &(_p)->sec ); \
+ _mbg_swab32( &(_p)->frac ); \
+}
+
+
+
+// Depending on the target environment define a data type
+// which can be used to convert binary fractions without
+// range overflow.
+#if defined( MBG_TGT_UNIX )
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t
+#elif defined( MBG_TGT_WIN32 )
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t
+#elif defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t
+#else
+ #define PCPS_HRT_FRAC_CONVERSION_TYPE double
+#endif
+
+// Max value of PCPS_TIME_STAMP::frac + 1 used for scaling
+#define PCPS_HRT_BIN_FRAC_SCALE ( (PCPS_HRT_FRAC_CONVERSION_TYPE) 4294967296.0 ) // == 0x100000000
+
+
+// The scale and format to be used to print the fractions
+// of a second as returned in the PCPS_TIME_STAMP structure.
+// The function frac_sec_from_bin() can be used for
+// the conversion.
+#ifndef PCPS_HRT_FRAC_SCALE
+ #define PCPS_HRT_FRAC_SCALE 10000000UL
+#endif
+
+#ifndef PCPS_HRT_FRAC_SCALE_FMT
+ #define PCPS_HRT_FRAC_SCALE_FMT "%07lu"
+#endif
+
+
+
+typedef uint16_t PCPS_TIME_STATUS_X; /**< extended status */
+
+#define _mbg_swab_pcps_time_status_x( _p ) _mbg_swab16( _p )
+
+
+/**
+ * The structure has been introduced to be able to read the
+ * current time with higher resolution of fractions of seconds and
+ * more detailed information on the time zone and status.
+ * The structure is returned if the new command #PCPS_GIVE_HR_TIME
+ * is written to the board.
+ * _pcps_has_hr_time() checks whether supported.
+ *
+ * Newer GPS boards also accept the #PCPS_GIVE_UCAP_EVENT command
+ * to return user capture event times using this format. In this
+ * case, the "signal" field contains the number of the capture
+ * input line, e.g. 0 or 1.
+ * _pcps_has_ucap() checks whether supported.
+ */
+typedef struct
+{
+ PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */
+ int32_t utc_offs; /**< UTC offs [sec] (loc_time = UTC + utc_offs) */
+ PCPS_TIME_STATUS_X status; /**< status flags as defined below */
+ uint8_t signal; /**< for normal time, the relative RF signal level, for ucap, the channel number */
+} PCPS_HR_TIME;
+
+#define _mbg_swab_pcps_hr_time( _p ) \
+{ \
+ _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \
+ _mbg_swab32( &(_p)->utc_offs ); \
+ _mbg_swab_pcps_time_status_x( &(_p)->status ); \
+}
+
+
+typedef uint8_t PCPS_TIME_STATUS;
+
+/**
+ The standard structure used to read times from the board.
+ The time has a resultion of 10 ms.
+*/
+typedef struct PCPS_TIME_s
+{
+ uint8_t sec100; /**< hundredths of seconds, 0..99 */
+ uint8_t sec; /**< seconds, 0..59, or 60 if leap second */
+ uint8_t min; /**< minutes, 0..59 */
+ uint8_t hour; /**< hours, 0..23 */
+
+ uint8_t mday; /**< day of month, 0..31 */
+ uint8_t wday; /**< day of week, 1..7, 1 = Monday */
+ uint8_t month; /**< month, 1..12 */
+ uint8_t year; /**< year of the century, 0..99 */
+
+ PCPS_TIME_STATUS status; /**< status bits, see below */
+ uint8_t signal; /**< relative signal strength, range depends on device type */
+ int8_t offs_utc; /**< [hours], 0 if !_pcps_has_utc_offs() */
+} PCPS_TIME;
+
+
+/**
+ The structure is passed as parameter with the PCPS_SET_TIME cmd
+*/
+typedef struct PCPS_STIME_s
+{
+ uint8_t sec100; /**< hundredths of seconds, 0..99 */
+ uint8_t sec; /**< seconds, 0..59, or 60 if leap second */
+ uint8_t min; /**< minutes, 0..59 */
+ uint8_t hour; /**< hours, 0..23 */
+
+ uint8_t mday; /**< day of month, 0..31 */
+ uint8_t wday; /**< day of week, 1..7, 1 = Monday */
+ uint8_t month; /**< month, 1..12 */
+ uint8_t year; /**< year of the century, 0..99 */
+
+ PCPS_TIME_STATUS status; /**< status bits, see below */
+} PCPS_STIME;
+
+#ifdef _C166
+ // This is a workaround to specify some structure sizes. The C166 compiler
+ // always reports an even structure size although the structure size may
+ // be odd due to the number of bytes. This might lead to errors between
+ // the C166 and other build environments.
+ #define sizeof_PCPS_TIME ( sizeof( PCPS_TIME ) - 1 )
+ #define sizeof_PCPS_STIME ( sizeof( PCPS_STIME ) - 1 )
+#else
+ #define sizeof_PCPS_TIME sizeof( PCPS_TIME )
+ #define sizeof_PCPS_STIME sizeof( PCPS_STIME )
+#endif
+
+typedef union
+{
+ PCPS_TIME t;
+ PCPS_STIME stime;
+} PCPS_TIME_UNION;
+
+
+
+/**
+ The structure below can be used to read the raw IRIG time
+ from an IRIG receiver card, if the card supports this.
+ See the #PCPS_GIVE_IRIG_TIME command.
+
+ The granularity of the value in the .frac field depends on
+ the update interval of the structure as implementation
+ in the firmware. I.e. if the raw IRIG time is updated
+ only once per second, the .frac value can always be 0.
+*/
+typedef struct PCPS_IRIG_TIME_s
+{
+ PCPS_TIME_STATUS_X status; /**< status bits, see below */
+ int16_t offs_utc; /**< [minutes] */
+ uint16_t yday; /**< day of year, 1..365/366 */
+ uint16_t frac; /**< fractions of seconds, 0.1 ms units */
+ uint8_t sec; /**< seconds, 0..59, or 60 if leap second */
+ uint8_t min; /**< minutes, 0..59 */
+ uint8_t hour; /**< hours, 0..23 */
+ uint8_t year; /**< 2 digit year number, 0xFF if year not supp. by the IRIG code */
+ uint8_t signal; /**< relative signal strength, range depends on device type */
+ uint8_t reserved; /**< currently not used, always 0 */
+} PCPS_IRIG_TIME;
+
+#define _mbg_swab_pcps_irig_time( _p ) \
+{ \
+ _mbg_swab_pcps_time_status_x( &(_p)->status ); \
+ _mbg_swab16( &(_p)->offs_utc ); \
+ _mbg_swab16( &(_p)->yday ); \
+ _mbg_swab16( &(_p)->frac ); \
+}
+
+
+
+
+/* Bit masks used with both PCPS_TIME_STATUS and PCPS_TIME_STATUS_X */
+
+#define PCPS_FREER 0x01 /**< DCF77 clock running on xtal */
+ /**< GPS receiver has not verified its position */
+
+#define PCPS_DL_ENB 0x02 /**< daylight saving enabled */
+
+#define PCPS_SYNCD 0x04 /**< clock has sync'ed at least once after pwr up */
+
+#define PCPS_DL_ANN 0x08 /**< a change in daylight saving is announced */
+
+#define PCPS_UTC 0x10 /**< a special UTC firmware is installed */
+
+#define PCPS_LS_ANN 0x20 /**< leap second announced */
+ /**< (requires firmware rev. REV_PCPS_LS_ANN_...) */
+
+#define PCPS_IFTM 0x40 /**< the current time was set via PC */
+ /**< (requires firmware rev. REV_PCPS_IFTM_...) */
+
+#define PCPS_INVT 0x80 /**< invalid time because battery was disconn'd */
+
+
+/* Bit masks used only with PCPS_TIME_STATUS_X */
+
+#define PCPS_LS_ENB 0x0100 /**< current second is leap second */
+#define PCPS_ANT_FAIL 0x0200 /**< antenna failure */
+#define PCPS_LS_ANN_NEG 0x0400 /**< announced leap second is negative */
+#define PCPS_SCALE_GPS 0x0800 /**< time stamp is GPS scale */
+#define PCPS_SCALE_TAI 0x1000 /**< time stamp is TAI scale */
+
+/* The next two bits are used only if the structure */
+/* PCPS_HR_TIME contains a user capture event */
+#define PCPS_UCAP_OVERRUN 0x2000 /**< events interval too short */
+#define PCPS_UCAP_BUFFER_FULL 0x4000 /**< events read too slow */
+
+/**
+ * Immediately after a clock has been accessed, subsequent accesses
+ * are blocked for up to 1.5 msec to give the clock's microprocessor
+ * some time to decode the incoming time signal.
+ * The flag below is set if a program tries to read the PCPS_HR_TIME
+ * during this interval. In this case the read function returns the
+ * proper time stamp which is taken if the command byte is written,
+ * however, the read function returns with delay.
+ * This flag is not supported by all clocks.
+ */
+#define PCPS_IO_BLOCKED 0x8000
+
+/**
+ This bit mask can be used to extract the time scale information out
+ of a PCPS_TIME_STATUS_X value.
+*/
+#define PCPS_SCALE_MASK ( PCPS_SCALE_TAI | PCPS_SCALE_GPS )
+
+
+/**
+ * Some DCF77 clocks have a serial interface that can be controlled
+ * using the commands PCPS_SET_SERIAL and PCPS_GET_SERIAL. Both commands
+ * use a parameter byte describing transmission speed, framing and mode
+ * of operation. The parameter byte can be build using the constants
+ * defined below, by or'ing one of the constants of each group, shifted
+ * to the right position. PCPS_GET_SERIAL expects that parameter byte
+ * and PCPS_GET_SERIAL returns the current configuration from the board.
+ * _pcps_has_serial() checks whether supported.
+ * For GPS clocks, please refer to the comments for the PCPS_GET_SERIAL
+ * command.
+ */
+
+/**
+ * Baud rate indices. The values below are obsolete and should
+ * be replaced by the codes named MBG_BAUD_RATE_... which are
+ * defined in gpsdefs.h. The resulting index numbers, however,
+ * have not changed.
+ */
+enum
+{
+ PCPS_BD_300,
+ PCPS_BD_600,
+ PCPS_BD_1200,
+ PCPS_BD_2400,
+ PCPS_BD_4800,
+ PCPS_BD_9600,
+ PCPS_BD_19200,
+ N_PCPS_BD /* number of codes */
+};
+
+#define PCPS_BD_BITS 4 /* field with in the cfg byte */
+#define PCPS_BD_SHIFT 0 /* num of bits to shift left */
+
+/*
+ * Initializers for a table of all baud rate strings
+ * and values can be found in gpsdefs.h.
+ */
+
+
+/**
+ * Unfortunately, the framing codes below can not simply be
+ * replaced by the newer MBG_FRAMING_... definitions since
+ * the order of indices does not match.
+ */
+enum
+{
+ PCPS_FR_8N1,
+ PCPS_FR_7E2,
+ PCPS_FR_8N2,
+ PCPS_FR_8E1,
+ N_PCPS_FR_DCF /* number of valid codes */
+};
+
+#define PCPS_FR_BITS 2 /* field with in the cfg byte */
+#define PCPS_FR_SHIFT PCPS_BD_BITS /* num of bits to shift left */
+
+/*
+ * An initializer for a table of framing strings is only defined for
+ * the new MBG_FRAMING_... definitions. For editing the serial port
+ * configuration, the old codes above should be translated to the new
+ * codes to unify handling inside the edit functions.
+ */
+
+/**
+ Modes of operation
+
+ * Indices for modes of operation. The values below are obsolete
+ * and should be replaced by the codes named STR_... which are
+ * defined in gpsdefs.h. The resulting index numbers, however,
+ * have not changed.
+ */
+enum
+{
+ PCPS_MOD_REQ, /* time string on request '?' only */
+ PCPS_MOD_SEC, /* time string once per second */
+ PCPS_MOD_MIN, /* time string once per minute */
+ PCPS_MOD_RSVD, /* reserved */
+ N_PCPS_MOD_DCF /* number of possible codes */
+};
+
+#define PCPS_MOD_BITS 2 /* field with in the cfg byte */
+#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS )
+ /* num of bits to shift left */
+
+/**
+ * The fixed-length standard time string being sent on the serial
+ * output is described below:
+ *
+ * \<STX\>D:dd.mm.yy;T:d;U:hh.mm.ss;uvwx\<ETX\>
+ *
+ * where \<STX\> and \<ETX\> represent the ASCII codes 0x02 and 0x03,
+ * 'dd.mm.yy' is the format of the current date, 'd' is the current
+ * day of week (1..7, 1 == Monday ) and 'hh.mm.ss' is the format of
+ * the current time. The characters 'uvwx' reflect the clock's status:
+ *
+ * u clock status character:
+ * '#' clock has not synchronized after reset
+ * ' ' (space, 20h) clock has synchronized after reset
+ *
+ * v clock status character, different for DCF77 or GPS receivers:
+ * '*' DCF77 clock currently runs on XTAL
+ * GPS receiver has not checked its position
+ * ' ' (space, 20h):
+ * DCF77 clock is syncronized with transmitter
+ * GPS receiver has determined its position
+ *
+ * x time zone indicator:
+ * 'U' UTC Universal Time, Coordinated
+ * ' ' MEZ European Standard Time, daylight saving disabled
+ * 'S' MESZ European Summertime, daylight saving enabled
+ *
+ * y anouncement of discontinuity of time, enabled during last hour
+ * before discontinuity comes in effect:
+ * '!' announcement of start or end of daylight saving
+ * 'A' announcement of leap second insertion
+ * ' ' (space, 20h): nothing announced
+ */
+
+
+
+/**
+ * Some definitions used with PZF receivers
+ */
+
+/* receiver distance from transmitter [km] */
+typedef uint16_t TR_DISTANCE;
+
+/* correlation status info */
+typedef struct
+{
+ uint8_t val; /**< correlation value, or check count if status == PZF_CORR_CHECK */
+ uint8_t status; /**< status codes, see below */
+ char corr_dir; /**< space, '<', or '>' */
+ uint8_t signal; /**< signal level, may always be 0 for devices which do not support this */
+} CORR_INFO;
+
+/** Codes used with CORR_INFO::status: */
+enum
+{
+ PZF_CORR_RAW, /**< trying raw correlation, combi receivers running in AM mode */
+ PZF_CORR_CHECK, /**< raw correlation achieved, doing plausibility checks */
+ PZF_CORR_FINE, /**< fine correlation achieved */
+ N_PZF_CORR_STATE
+};
+
+
+/**
+ * @defgroup gps_cmds_bus GPS commands passed via the system bus
+ *
+ * This enumeration defines the various types of data that can be read
+ * from or written to Meinberg bus level devices which support this.
+ * Access should be done using the functions ::pcps_read_gps_data()
+ * and ::pcps_write_gps_data() since the size of some of the structures
+ * exceeds the size of the devices's I/O buffer and must therefore be
+ * accessed in several portions.
+ *
+ * The structures to be used are defined in gpsdefs.h. Not all structures
+ * are supportet, yet. Check the R/W indicators for details.
+ */
+enum
+{ // R/W data type description
+ // system data -----------------------------------------------
+ PC_GPS_TZDL = 0, // R/W TZDL time zone / daylight saving
+ PC_GPS_SW_REV, // R/- SW_REV software revision
+ PC_GPS_BVAR_STAT, // R/- BVAR_STAT status of buffered variables
+ PC_GPS_TIME, // R/W TTM curr. time
+ PC_GPS_POS_XYZ, // -/W XYZ curr. pos. in ECEF coords
+ PC_GPS_POS_LLA, // -/W LLA curr. pos. in geogr. coords
+ PC_GPS_PORT_PARM, // R/W PORT_PARM param. of the serial ports
+ PC_GPS_ANT_INFO, // R/- ANT_INFO time diff after ant. disconn.
+ PC_GPS_UCAP, // R/- TTM user capture
+ PC_GPS_ENABLE_FLAGS, // R/W ENABLE_FLAGS controls when to enable outp.
+ PC_GPS_STAT_INFO, // R/- GPS_STAT_INFO
+ PC_GPS_CMD, // -/W GPS_CMD commands as described below
+ PC_GPS_IDENT, // R/- GPS_IDENT serial number
+ PC_GPS_POS, // R/- POS position XYZ, LLA, and DMS
+ PC_GPS_ANT_CABLE_LEN, // R/W ANT_CABLE_LEN used to compensate delay
+ // The codes below are supported by new GPS receiver boards:
+ PC_GPS_RECEIVER_INFO, // R/- RECEIVER_INFO rcvr model info
+ PC_GPS_ALL_STR_TYPE_INFO, // R/- n*STR_TYPE_INFO_IDX all string types
+ PC_GPS_ALL_PORT_INFO, // R/- n*PORT_INFO_IDX all port info
+ PC_GPS_PORT_SETTINGS_IDX, // -/W PORT_SETTINGS_IDX port settings only
+ PC_GPS_ALL_POUT_INFO, // R/- n*POUT_INFO_IDX all pout info
+ PC_GPS_POUT_SETTINGS_IDX, // -/W POUT_SETTINGS_IDX pout settings only
+ PC_GPS_TIME_SCALE, // R/W MBG_TIME_SCALE_{SETTINGS|INFO}, only if PCPS_HAS_TIME_SCALE
+ PC_GPS_LAN_IF_INFO, // R/- LAN_IF_INFO LAN interface info, only if PCPS_HAS_LAN_INTF
+ PC_GPS_IP4_STATE, // R/- IP4_SETTINGS LAN interface state, only if PCPS_HAS_LAN_INTF
+ PC_GPS_IP4_SETTINGS, // R/W IP4_SETTINGS LAN interface configuration, only if PCPS_HAS_LAN_INTF
+ PC_GPS_PTP_STATE, // R/- PTP_STATE, only if PCPS_HAS_PTP
+ PC_GPS_PTP_CFG, // R/W PTP_CFG_{SETTINGS|INFO}, only if PCPS_HAS_PTP
+ PC_GPS_PTP_UNICAST_CFG, // R/W PTP_CFG_UNICAST_{SETTINGS|INFO}, only if PCPS_HAS_PTP
+
+ // GPS data
+ PC_GPS_CFGH = 0x80, // -/- CFGH SVs' config. and health codes
+ PC_GPS_ALM, // -/- SV_ALM one SV's num and almanac
+ PC_GPS_EPH, // -/- SV_EPH one SV's num and ephemeris
+ PC_GPS_UTC, // R/W UTC UTC corr. param., only if PCPS_HAS_UTC_PARM
+ PC_GPS_IONO, // -/- IONO ionospheric corr. param.
+ PC_GPS_ASCII_MSG // -/- ASCII_MSG the GPS ASCII message
+};
+
+
+/** codes used with PC_GPS_CMD */
+enum
+{
+ PC_GPS_CMD_BOOT = 1, /**< force the clock to boot mode */
+ PC_GPS_CMD_INIT_SYS, /**< let the clock clear its system variables */
+ PC_GPS_CMD_INIT_USER, /**< reset the clock's user parameters to defaults */
+ PC_GPS_CMD_INIT_DAC, /**< initialize the oscillator disciplining values */
+ N_PC_GPS_CMD /**< no command, just the number of known commands */
+};
+
+// The type below can be used to store an unambiguous command code.
+// In case of the standard PCPS_... commands the lower byte contains
+// the command code and the upper byte is 0.
+// In case of a GPS command the lower byte contains PCPS_READ_GPS_DATA
+// or PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains
+// the associated PC_GPS_... type code.
+typedef uint16_t PCPS_CMD_INFO;
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+#endif /* _PCPSDEFS_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h
new file mode 100755
index 0000000..f8cf9e8
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h
@@ -0,0 +1,1732 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsdev.h 1.49.1.32 2011/03/25 11:09:43 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used to share information on radio clock devices
+ * between device drivers which have direct access to the hardware
+ * devices and user space programs which evaluate and present that
+ * information.
+ *
+ * At the bottom of the file there are some macros defined which
+ * should be used to access the structures to extract characteristics
+ * of an individual clock.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsdev.h $
+ * Revision 1.49.1.32 2011/03/25 11:09:43 martin
+ * Optionally support timespec for sys time (USE_TIMESPEC).
+ * Started to support NetBSD.
+ * Revision 1.49.1.31 2011/02/16 10:10:49 martin
+ * Fixed macro syntax for _pcps_time_set_unread().
+ * Revision 1.49.1.30 2011/02/15 14:24:56Z martin
+ * Revision 1.49.1.29 2011/02/10 13:34:21 martin
+ * Revision 1.49.1.28 2011/02/10 13:21:59 martin
+ * Revision 1.49.1.27 2011/02/10 12:26:17 martin
+ * Revision 1.49.1.26 2011/02/09 15:46:49 martin
+ * Revision 1.49.1.25 2011/02/04 14:44:44 martin
+ * Revision 1.49.1.24 2011/02/04 10:10:00 martin
+ * Revision 1.49.1.23 2011/02/02 12:34:10 martin
+ * Revision 1.49.1.22 2011/02/01 17:12:04 martin
+ * Revision 1.49.1.21 2011/01/28 13:11:11 martin
+ * Preliminary implementation of mbg_get_sys_time for FreeBSD traps.
+ * Revision 1.49.1.20 2011/01/28 10:34:37 martin
+ * Moved MBG_TGT_SUPP_MEM_ACC definition here.
+ * Revision 1.49.1.19 2011/01/26 16:39:05 martin
+ * Preliminarily support FreeBSD build.
+ * Revision 1.49.1.18 2011/01/24 17:09:51 martin
+ * Preliminarily fixed build under FreeBSD.
+ * Revision 1.49.1.17 2010/12/14 13:19:58 martin
+ * Fixed doxgen comments.
+ * Revision 1.49.1.16 2010/12/14 12:20:10 martin
+ * Revision 1.49.1.15 2010/11/25 14:54:22 martin
+ * Moved status port register definitions to pcpsdefs.h.
+ * Revision 1.49.1.14 2010/11/11 09:15:38 martin
+ * Added definitions to support DCF600USB.
+ * Revision 1.49.1.13 2010/09/27 13:09:06 martin
+ * Features are now defined using enum and bit masks.
+ * Added initializer for feature names (used for debug).
+ * Revision 1.49.1.12 2010/08/25 12:44:42 martin
+ * Revision 1.49.1.11 2010/08/20 09:34:41Z martin
+ * Added macro _pcps_features().
+ * Revision 1.49.1.10 2010/08/17 15:34:23 martin
+ * Revision 1.49.1.9 2010/08/16 15:41:32 martin
+ * Revision 1.49.1.8 2010/08/13 12:14:46 daniel
+ * Revision 1.49.1.7 2010/08/13 11:57:54Z martin
+ * Revision 1.49.1.6 2010/08/13 11:39:28Z martin
+ * Revision 1.49.1.5 2010/08/13 11:19:41 martin
+ * Implemented portable mbg_get_sys_uptime() and mbg_sleep_sec()
+ * functions and associated types.
+ * Revision 1.49.1.4 2010/08/11 14:32:14 martin
+ * Revision 1.49.1.3 2010/08/11 13:47:42 martin
+ * Cleanup.
+ * Revision 1.49.1.2 2010/07/14 14:50:42 martin
+ * Revision 1.49.1.1 2010/06/30 13:17:18 martin
+ * Support GPS180PEX and TCR180PEX.
+ * Revision 1.49 2010/06/30 13:03:48 martin
+ * Use new preprocessor symbol MBG_ARCH_X86.
+ * Use ulong port addresses for all platforms but x86.
+ * Support mbg_get_pc_cycles() for IA64, but mbg_get_pc_cycles_frequency()
+ * is not yet supported.
+ * Don't pack interface structures on Sparc and IA64 architecture.
+ * Revision 1.48 2010/04/26 14:47:42 martin
+ * Define symbol MBG_PC_CYCLES_SUPPORTED if this is the case.
+ * Revision 1.47 2010/01/12 14:03:22 daniel
+ * Added definitions to support reading the raw IRIG data bits.
+ * Revision 1.46 2009/09/29 15:10:35Z martin
+ * Support generic system time, and retrieving time discipline info.
+ * Added _pcps_has_fast_hr_timestamp() macro and associated feature flag.
+ * Revision 1.45 2009/06/19 12:15:18 martin
+ * Added has_irig_time feature and associated macros.
+ * Revision 1.44 2009/06/08 19:30:48 daniel
+ * Account for new features PCPS_HAS_LAN_INTF and
+ * PCPS_HAS_PTP.
+ * Revision 1.43 2009/04/08 08:26:20 daniel
+ * Define firmware version at which the TCR511PCI starts
+ * to support IRIG control bits.
+ * Revision 1.42 2009/03/19 14:58:47Z martin
+ * Tmp. workaround in mbg_delta_pc_cycles() under SPARC which might
+ * generate bus errors due to unaligned access.
+ * Revision 1.41 2009/03/16 16:01:22 martin
+ * Support reading IRIG control function bits.
+ * Revision 1.40 2009/03/13 09:13:39 martin
+ * Support new features .._has_time_scale() and .._has_utc_parm().
+ * Moved some inline functions dealing with MBG_PC_CYCLES
+ * from mbgdevio.h here.
+ * Merged the code from _pcps_get_cycles() and _pcps_get_cycles_frequency()
+ * to the mbg_get_pc_cycles...() inline functions which now replace the
+ * _pcps_get_cycles...() macros.
+ * Fixed cycles code for non-x86 architectures.
+ * Revision 1.39 2008/12/05 16:24:24Z martin
+ * Changed MAX_PARM_STR_TYPE from 10 to 20.
+ * Added support for WWVB signal source.
+ * Support new devices PTP270PEX, FRC511PEX, TCR170PEX, and WWVB51USB.
+ * Added macros _pcps_is_ptp(), _pcps_is_frc(), and _pcps_is_wwvb().
+ * Defined firmware version numbers which fix an IRQ problem with PEX511,
+ * TCR511PEX, and GPS170PEX cards. The fix also requires specific ASIC
+ * versions specified in pci_asic.h.
+ * Defined firmware versions at which PCI511 and PEX511 start
+ * to support HR time.
+ * Support mapped I/O resources.
+ * Changed MBG_PC_CYCLES type for Windows to int64_t.
+ * Renamed MBG_VIRT_ADDR to MBG_MEM_ADDR.
+ * Added MBG_PC_CYCLES_FREQUENCY type.
+ * Added definition of PCPS_TIME_STAMP_CYCLES.
+ * Added PCPS_IRQ_STAT_INFO type and associated flags.
+ * Added macros to convert the endianess of structures.
+ * Added macros _pcps_fw_rev_num_major() and _pcps_fw_rev_num_minor().
+ * Made irq_num signed to use -1 for unassigned IRQ numbers.
+ * Revision 1.38 2008/01/17 10:12:34 daniel
+ * Added support for TCR51USB and MSF51USB.
+ * New type MBG_VIRT_ADDR to specify virtual address values.
+ * New struct PCPS_MAPPED_MEM
+ * Cleanup for PCI ASIC version and features.
+ * Added macros _pcps_is_msf(), _pcps_is_lwr(),
+ * _psps_has_asic_version(), _pcps_has_asic_features().
+ * Revision 1.37 2008/01/17 09:58:11Z daniel
+ * Made comments compatible for doxygen parser.
+ * No sourcecode changes.
+ * Revision 1.36 2007/09/26 09:34:38Z martin
+ * Added support for USB in general and new USB device USB5131.
+ * Added new types PCPS_DEV_ID and PCPS_REF_TYPE.
+ * Removed old PCPS_ERR_... codes. Use MBG_ERR_... codes
+ * from mbgerror.h instead. The old values haven't changed.
+ * Revision 1.35 2007/07/17 08:22:47Z martin
+ * Added support for TCR511PEX and GPS170PEX.
+ * Revision 1.34 2007/07/16 12:50:41Z martin
+ * Added support for PEX511.
+ * Modified/renamed some macros and symbols.
+ * Revision 1.33 2007/03/02 09:40:04Z martin
+ * Changes due to renamed library symbols.
+ * Removed obsolete inclusion of headers.
+ * Preliminary support for *BSD.
+ * Preliminary support for USB.
+ * Revision 1.32 2006/10/23 08:47:55Z martin
+ * Don't use abs() in _pcps_ref_offs_out_of_range() since this might
+ * not work properly for 16 bit integers and value 0x8000.
+ * Revision 1.31 2006/06/14 12:59:13Z martin
+ * Added support for TCR511PCI.
+ * Revision 1.30 2006/04/05 14:58:41 martin
+ * Support higher baud rates for PCI511.
+ * Revision 1.29 2006/04/03 07:29:07Z martin
+ * Added a note about the missing PCPS_ST_IRQF signal
+ * on PCI510 cards.
+ * Revision 1.28 2006/03/10 10:32:56Z martin
+ * Added support for PCI511.
+ * Added support for programmable pulse outputs.
+ * Revision 1.27 2005/11/04 08:48:00Z martin
+ * Added support for GPS170PCI.
+ * Revision 1.26 2005/06/02 08:34:38Z martin
+ * New types MBG_DBG_PORT, MBG_DBG_DATA.
+ * Revision 1.25 2005/05/03 10:04:14 martin
+ * Added macro _pcps_is_pci_amcc().
+ * Revision 1.24 2005/03/29 12:58:19Z martin
+ * Support GENERIC_IO feature.
+ * Revision 1.23 2004/12/09 11:03:37Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.22 2004/11/09 12:57:52Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Added support for TCR167PCI.
+ * New macro _pcps_has_gps_data().
+ * New type PCPS_STATUS_PORT.
+ * Removed obsolete inclusion of asm/timex.h for Linux.
+ * Revision 1.21 2004/09/06 15:19:49Z martin
+ * Support a GPS_DATA interface where sizes are specified
+ * by 16 instead of the original 8 bit quantities, thus allowing
+ * to transfer data blocks which exceed 255 bytes.
+ * Modified inclusion of header files under Linux.
+ * Modified definition of MBG_PC_CYCLES for Linux.
+ * Revision 1.20 2004/04/14 09:09:11 martin
+ * Source code cleanup.
+ * Revision 1.19 2004/04/07 09:49:14Z martin
+ * Support new feature PCPS_HAS_IRIG_TX.
+ * New macros _pcps_has_irig(), _pcps_has_irig_tx().
+ * Revision 1.18 2004/01/14 11:02:14Z MARTIN
+ * Added formal type MBG_PC_CYCLES for OS/2,
+ * though it's not really required or used.
+ * Revision 1.17 2003/12/22 15:40:16 martin
+ * Support higher baud rates for TCR510PCI and PCI510.
+ * Supports PCPS_HR_TIME for TCR510PCI.
+ * New structures used to read device time together with associated
+ * PC CPU cycles.
+ * For Win32, differentiate between kernel mode and non-kernel mode.
+ * Moved some definitions here from mbgdevio.h.
+ * New type PCPS_ASIC_VERSION.
+ * New macro _pcps_ref_offs_out_of_range().
+ * Revision 1.16 2003/06/19 09:48:30Z MARTIN
+ * Renamed symbols ..clr_cap_buffer to ..clr_ucap_buffer.
+ * New macro _pcps_has_ucap().
+ * New definitions to support cmds PCPS_GIVE_UCAP_ENTRIES
+ * and PCPS_GIVE_UCAP_EVENT.
+ * Revision 1.15 2003/04/15 09:57:25 martin
+ * New typedefs ALL_STR_TYPE_INFO, ALL_PORT_INFO,
+ * RECEIVER_PORT_CFG.
+ * Revision 1.14 2003/04/09 14:07:01Z martin
+ * Supports PCI510, GPS169PCI, and TCR510PCI,
+ * and new PCI_ASIC used by those devices.
+ * Renamed macro _pcps_is_irig() to _pcps_is_irig_rx().
+ * New macros _pcps_has_ref_offs(), _pcps_has_opt_flags().
+ * Fixed macro _pcps_has_hr_time().
+ * New type PCPS_BUS_FLAGS.
+ * Preliminary support for PCPS_TZDL.
+ * Revision 1.13 2002/08/09 07:19:49 MARTIN
+ * Moved definition of ref time sources to pcpsdefs.h.
+ * New feature PCPS_CAN_CLR_CAP_BUFF and
+ * associated macro _pcps_can_clr_cap_buff().
+ * New macros _pcps_is_irig(), _pcps_has_signal(),
+ * _pcps_has_mod().
+ * Revision 1.12 2002/02/19 09:22:53 MARTIN
+ * Added definitions for the maximum number of clocks' serial ports
+ * and string types that can be handled by the configuration programs.
+ * Revision 1.11 2002/02/01 11:36:58 MARTIN
+ * Added new definitions for GPS168PCI.
+ * Inserted definitions of firmware REV_NUMs for supported features
+ * which had previously been defined in pcpsdefs.h.
+ * Include use_pack.h.
+ * Updated comments.
+ * Source code cleanup.
+ * Revision 1.10 2001/11/30 09:52:48 martin
+ * Added support for event_time which, however, requires
+ * a custom GPS firmware.
+ * Revision 1.9 2001/10/16 10:11:14 MARTIN
+ * New Macro _pcps_has_serial_hs() which determines whether
+ * DCF77 clock supports baud rate higher than default.
+ * Re-arranged order of macro definitions.
+ * Revision 1.8 2001/09/03 07:15:05 MARTIN
+ * Added macro to access the firmware revision number.
+ * Cleaned up macro syntax.
+ * Added some comments.
+ * Revision 1.7 2001/08/30 13:20:04 MARTIN
+ * New macro to mark a PCPS_TIME variable as unread.
+ * New macro to check if a PCPS_TIME variable is unread.
+ * Revision 1.6 2001/03/15 15:45:01 MARTIN
+ * Added types PCPS_ERR_FLAGS, PCPS_BUS_NUM, PCPS_SLOT_NUM.
+ * Revision 1.5 2001/03/01 13:53:10 MARTIN
+ * Initial version for the new driver library.
+ *
+ **************************************************************************/
+
+#ifndef _PCPSDEV_H
+#define _PCPSDEV_H
+
+#include <pcpsdefs.h>
+#include <gpsdefs.h>
+#include <usbdefs.h>
+#include <mbg_tgt.h>
+#include <mbgtime.h>
+#include <use_pack.h>
+
+#if defined( MBG_TGT_LINUX )
+
+ #if !defined( USE_TIMESPEC )
+ #define USE_TIMESPEC 0
+ #endif
+
+ #if defined( MBG_TGT_KERNEL )
+ #include <linux/delay.h>
+ #include <linux/time.h>
+ #else
+ #include <unistd.h>
+ #include <sys/time.h>
+ #include <sys/sysinfo.h>
+ #endif
+
+ #if defined( MBG_ARCH_IA64 )
+ #include <asm/ia64regs.h>
+ #include <asm/intel_intrin.h>
+ #endif
+
+#endif
+
+#if defined( MBG_TGT_BSD )
+
+ #if !defined( USE_TIMESPEC )
+ #define USE_TIMESPEC 1
+ #endif
+
+ #if defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 ) && defined( MBG_TGT_KERNEL )
+ #include <machine/clock.h> /* for symbol 'tsc_freq' */
+ #endif
+
+ #if defined( MBG_TGT_NETBSD ) && defined( MBG_TGT_KERNEL )
+ #include <machine/cpu.h>
+ #include <machine/cpu_counter.h> /* for cycle counter abstractionb */
+ #endif
+
+#endif
+
+#if defined( MBG_TGT_DOS )
+ #include <dos.h> // for delay()
+#endif
+
+
+
+/* Start of header body */
+
+#if defined( MBG_ARCH_SPARC ) || defined( MBG_ARCH_IA64 )
+ #undef _USE_PACK // don't pack interface structures
+#endif
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+#if !defined( USE_TIMESPEC )
+ #define USE_TIMESPEC 0
+#endif
+
+
+
+/**
+ Define generic types to hold PC cycle counter values and system timestamps.
+ The generic types are defined using native types used by the target operating
+ systems.
+
+ The cycle counter value is usually derived from the PC CPU's TSC or some other
+ timer hardware on the mainboard.
+ */
+#if defined( MBG_TGT_WIN32 )
+
+ #define MBG_TGT_SUPP_MEM_ACC 1
+
+ // used with QueryPerformanceCounter()
+ typedef int64_t MBG_PC_CYCLES;
+ typedef uint64_t MBG_PC_CYCLES_FREQUENCY;
+
+ typedef int64_t MBG_SYS_UPTIME; // [s]
+
+ typedef LARGE_INTEGER MBG_SYS_TIME;
+
+#elif defined( MBG_TGT_LINUX )
+
+ #define MBG_TGT_SUPP_MEM_ACC 1
+
+ typedef uint64_t MBG_PC_CYCLES;
+ typedef uint64_t MBG_PC_CYCLES_FREQUENCY;
+
+ typedef int64_t MBG_SYS_UPTIME; // [s]
+
+ typedef struct timeval MBG_SYS_TIME;
+
+#elif defined( MBG_TGT_BSD )
+
+ #define MBG_TGT_SUPP_MEM_ACC 1
+
+ typedef uint64_t MBG_PC_CYCLES;
+ typedef uint64_t MBG_PC_CYCLES_FREQUENCY;
+
+ typedef int64_t MBG_SYS_UPTIME; // [s]
+
+ #if USE_TIMESPEC
+ typedef struct timespec MBG_SYS_TIME;
+ #else
+ typedef struct timeval MBG_SYS_TIME;
+ #endif
+
+ #if defined( MBG_TGT_FREEBSD ) && defined( MBG_TGT_KERNEL )
+ #include <sys/sysproto.h>
+ #include <sys/pcpu.h>
+ #else
+ #include <sys/time.h>
+ #endif
+
+ #if defined( MBG_TGT_NETBSD )
+ #ifdef __LP64__
+ #define MBG_MEM_ADDR uint64_t
+ #else
+ #define MBG_MEM_ADDR uint32_t
+ #endif
+ #endif
+#elif defined( MBG_TGT_OS2 )
+
+ typedef uint32_t MBG_PC_CYCLES; //##++ should differentiate more
+ typedef uint32_t MBG_PC_CYCLES_FREQUENCY;
+
+ typedef long MBG_SYS_UPTIME; //## dummy
+
+ typedef uint32_t MBG_SYS_TIME; //## dummy
+
+#elif defined( MBG_TGT_DOS )
+
+ typedef uint32_t MBG_PC_CYCLES; //##++ should differentiate more
+ typedef uint32_t MBG_PC_CYCLES_FREQUENCY;
+ #define MBG_MEM_ADDR uint32_t // 64 bit not supported, nor required.
+
+ typedef long MBG_SYS_UPTIME; //## dummy
+
+ typedef uint32_t MBG_SYS_TIME; //## dummy
+
+#else // other target OSs which access the hardware directly
+
+ typedef uint32_t MBG_PC_CYCLES; //##++ should differentiate more
+ typedef uint32_t MBG_PC_CYCLES_FREQUENCY;
+
+ typedef long MBG_SYS_UPTIME; //## dummy
+
+ typedef uint32_t MBG_SYS_TIME; //## dummy
+
+#endif
+
+
+#if !defined( MBG_TGT_SUPP_MEM_ACC )
+ #define MBG_TGT_SUPP_MEM_ACC 0
+#endif
+
+
+// MBG_PC_CYCLES, MBG_PC_CYCLES_FREQUENCY, and MBG_SYS_TIME are always read
+// in native machine endianess, so no endianess conversion is required.
+#define _mbg_swab_mbg_pc_cycles( _p ) \
+ _nop_macro_fnc()
+
+#define _mbg_swab_mbg_pc_cycles_frequency( _p ) \
+ _nop_macro_fnc()
+
+#define _mbg_swab_mbg_sys_time( _p ) \
+ _nop_macro_fnc()
+
+
+
+/**
+ The structure holds a system timestamp in a format depending on the target OS
+ plus two cycles counter values which can be taken before and after reading
+ the system time. These cycles values can be used to determine the execution
+ time required to read the system time.
+
+ Limitations of the operating system need to be taken into account,
+ e.g. the Windows system time may increase once every ~16 ms only.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cyc_before; /**< cycles count before sys time is read */
+ MBG_PC_CYCLES cyc_after; /**< cycles count after sys time has been read */
+ MBG_SYS_TIME sys_time; /**< system time stamp */
+} MBG_SYS_TIME_CYCLES;
+
+#define _mbg_swab_mbg_sys_time_cycles( _p ) \
+{ \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cyc_before ); \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cyc_after ); \
+ _mbg_swab_mbg_sys_time( &(_p)->sys_time ); \
+}
+
+
+
+
+#if ( defined( MBG_TGT_LINUX ) || defined( MBG_TGT_BSD ) ) && defined( MBG_ARCH_X86 )
+
+ static __mbg_inline unsigned long long int mbg_rdtscll( void )
+ {
+ // The code below is a hack to get around issues with
+ // different versions of gcc.
+ //
+ // Normally the inline asm code could look similar to:
+ //
+ // __asm__ volatile ( "rdtsc" : "=A" (x) )
+ //
+ // which would copy the output regs edx:eax as a 64 bit
+ // number to a variable x.
+ //
+ // The "=A" expression should implicitely tell the compiler
+ // the edx and eax registers have been clobbered. However,
+ // this does not seem to work properly at least with gcc 4.1.2
+ // shipped with Centos 5.
+ //
+ // If optimization level 1 or higher is used then function
+ // parameters are also passed in registers. If the inline
+ // code above is used inside a function then the edx register
+ // is clobbered but the gcc 4.1.2 is not aware of this and
+ // assumes edx is unchanged, which may yield faulty results
+ // or even lead to segmentation faults.
+ //
+ // A possible workaround could be to mark edx explicitely as
+ // being clobbered in the asm inline code, but unfortunately
+ // other gcc versions report an error if a register which is
+ // implicitely (by "=A") known to be clobbered is also listed
+ // explicitely to be clobbered.
+ //
+ // So the code below is a workaround which tells the compiler
+ // implicitely that the eax ("=a") and edx ("=d") registers
+ // are being used and thus clobbered.
+
+ union
+ {
+ struct
+ {
+ uint32_t lo;
+ uint32_t hi;
+ } u32;
+
+ uint64_t u64;
+
+ } tsc_val;
+
+ __asm__ __volatile__( "rdtsc" : "=a" (tsc_val.u32.lo), "=d" (tsc_val.u32.hi) );
+
+ return tsc_val.u64;
+
+ } // mbg_rdtscll
+
+#endif
+
+
+
+static __mbg_inline
+void mbg_get_pc_cycles( MBG_PC_CYCLES *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( _KDD_ ) // kernel space
+ *p = (MBG_PC_CYCLES) KeQueryPerformanceCounter( NULL ).QuadPart;
+ #else // user space
+ QueryPerformanceCounter( (LARGE_INTEGER *) p );
+ #endif
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 )
+
+ #if 0 && ( defined( CONFIG_X86_TSC ) || defined( CONFIG_M586TSC ) ) //##++++
+ #define _pcps_get_cycles( _c ) \
+ _c = get_cycles()
+ #else
+ *p = mbg_rdtscll();
+ #endif
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+#elif defined( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL )
+ *p = cpu_counter_serializing();
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_BSD ) && defined( MBG_ARCH_X86 )
+
+ *p = mbg_rdtscll();
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 )
+
+ unsigned long result = ia64_getreg( _IA64_REG_AR_ITC );
+ ia64_barrier();
+
+ #ifdef CONFIG_ITANIUM
+ while (unlikely((__s32) result == -1)) {
+ result = ia64_getreg(_IA64_REG_AR_ITC);
+ ia64_barrier();
+ }
+ #endif
+
+ *p = result;
+
+ #define MBG_PC_CYCLES_SUPPORTED 1
+
+ #else
+
+ *p = 0;
+
+ #endif
+
+} // mbg_get_pc_cycles
+
+
+
+static __mbg_inline
+void mbg_get_pc_cycles_frequency( MBG_PC_CYCLES_FREQUENCY *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+ LARGE_INTEGER li;
+
+ #if defined( _KDD_ ) // kernel space
+ KeQueryPerformanceCounter( &li );
+ #else // user space
+ QueryPerformanceFrequency( &li );
+ #endif
+
+ *p = li.QuadPart;
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 )
+
+ #if defined( MBG_TGT_KERNEL )
+
+ *p = ( cpu_khz * 1000 );
+
+ #else
+
+ *p = 0;
+
+ #endif
+
+ #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 )
+
+ #error A way to get cycles frequency needs to be defined for Linux/IA64.
+
+ // we probably can use
+ // ia64_sal_freq_base(unsigned long which, unsigned long *ticks_per_second,
+ // unsigned long *drift_info)
+ // However, this is not tested.
+
+ #elif defined( MBG_TGT_BSD )
+
+ #if defined( MBG_TGT_NETBSD ) && defined( MBG_TGT_KERNEL )
+
+ *p = cpu_frequency(curcpu());
+
+ #elif defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 ) && defined( MBG_TGT_KERNEL )
+
+ *p = tsc_freq;
+
+ #else
+
+ *p = 0;
+
+ #endif
+
+ #else
+
+ #if MBG_PC_CYCLES_SUPPORTED
+
+ #error A way to get cycles frequency needs to be defined for this target.
+
+ #else
+ *p = 0;
+ #endif
+
+ #endif
+
+} // mbg_get_pc_cycles_frequency
+
+
+
+static __mbg_inline
+MBG_PC_CYCLES mbg_delta_pc_cycles( const MBG_PC_CYCLES *p1, const MBG_PC_CYCLES *p2 )
+{
+#if !defined( MBG_PC_CYCLES_SUPPORTED )
+ // Cycle counts not supported on this target platform.
+ // Under SPARC this may even result in bus errors
+ // due to alignment of the underlying data structures.
+ return 0;
+#else
+ return *p1 - *p2;
+#endif
+
+} // mbg_delta_pc_cycles
+
+
+
+static __mbg_inline
+void mbg_get_sys_time( MBG_SYS_TIME *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( _KDD_ ) // kernel space
+ KeQuerySystemTime( p );
+ #else // user space
+ {
+ FILETIME ft;
+ GetSystemTimeAsFileTime( &ft );
+ p->LowPart = ft.dwLowDateTime;
+ p->HighPart = ft.dwHighDateTime;
+ }
+ #endif
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+ do_gettimeofday( p );
+ #else
+ gettimeofday( p, NULL );
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ #if USE_TIMESPEC // use struct timespec
+ #if defined( MBG_TGT_KERNEL )
+ nanotime( p );
+ #else
+ #if defined( MBG_TGT_FREEBSD )
+ clock_gettime( CLOCK_REALTIME_PRECISE, p );
+ #else // MBG_TGT_NETBSD, ...
+ clock_gettime( CLOCK_REALTIME, p );
+ #endif
+ #endif
+ #else // use struct timeval
+ #if defined( MBG_TGT_KERNEL )
+ microtime( p );
+ #else
+ gettimeofday( p, NULL );
+ #endif
+ #endif
+
+ #else
+
+ *p = 0;
+
+ #endif
+
+} // mbg_get_sys_time
+
+
+
+static __mbg_inline
+void mbg_get_sys_uptime( MBG_SYS_UPTIME *p )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( _KDD_ ) // kernel space
+
+ ULONGLONG time_increment = KeQueryTimeIncrement();
+ LARGE_INTEGER tick_count;
+
+ KeQueryTickCount( &tick_count );
+
+ // multiplication by time_increment yields HNS units,
+ // but we need seconds
+ *p = ( tick_count.QuadPart * time_increment ) / HNS_PER_SEC;
+
+ #else // user space
+
+ DWORD tickCount;
+ DWORD timeAdjustment;
+ DWORD timeIncrement;
+ BOOL timeAdjustmentDisabled;
+
+ if ( !GetSystemTimeAdjustment( &timeAdjustment, &timeIncrement, &timeAdjustmentDisabled ) )
+ *p = -1; // failed
+
+ // ATTENTION: This is compatible with older Windows versions, but
+ // the returned tick count wraps around to zero after 49.7 days.
+ // A new GetTickCount64() call is available under Windows Vista and newer,
+ // but the function call had to be imported dynamically since otherwise
+ // programs refused to start under pre-Vista versions due to undefined DLL symbol.
+ tickCount = GetTickCount();
+
+ *p = ( ( (MBG_SYS_UPTIME) tickCount ) * timeIncrement ) / HNS_PER_SEC;
+
+ #endif
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+ {
+ // Using a simple 64 bit division may result in a linker error
+ // in kernel mode due to a missing symbol __udivdi3, so we use
+ // a specific inline function do_div().
+ // Also, the jiffies counter is not set to 0 at startup but to
+ // a defined initialization value we need to account for.
+ uint64_t tmp = get_jiffies_64() - INITIAL_JIFFIES;
+ do_div( tmp, HZ );
+ *p = tmp;
+ }
+ #else
+ {
+ struct sysinfo si;
+ int rc = sysinfo( &si );
+ *p = ( rc == 0 ) ? si.uptime : -1;
+ }
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ #if defined( MBG_TGT_KERNEL )
+ {
+ struct timespec ts;
+
+ getnanouptime( &ts );
+
+ *p = ts.tv_sec;
+ }
+ #elif defined( MBG_TGT_FREEBSD )
+ {
+ struct timespec ts;
+ // CLOCK_UPTIME_FAST is specific to FreeBSD
+ int rc = clock_gettime( CLOCK_UPTIME_FAST, &ts );
+ *p = ( rc == 0 ) ? ts.tv_sec : -1;
+ }
+ #else // MBG_TGT_NETBSD, ...
+
+ *p = -1; //##++ needs to be implemented
+
+ #endif
+
+ #else
+
+ *p = -1; // not supported
+
+ #endif
+
+} // mbg_get_sys_uptime
+
+
+
+static __mbg_inline
+void mbg_sleep_sec( long sec )
+{
+ #if defined( MBG_TGT_WIN32 )
+
+ #if defined( _KDD_ ) // kernel space
+ LARGE_INTEGER delay;
+
+ // we need to pass a negative value to KeDelayExecutionThread()
+ // since the given time is a relative time interval, not absolute
+ // time. See the API docs for KeDelayExecutionThread().
+ delay.QuadPart = (LONGLONG) sec * HNS_PER_SEC;
+
+ KeDelayExecutionThread( KernelMode, FALSE, &delay );
+ #else // user space
+ // Sleep() expects milliseconds
+ Sleep( sec * 1000 );
+ #endif
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #if defined( MBG_TGT_KERNEL )
+ // msleep is not defined in older kernels, so we use this
+ // only if it is surely supported.
+ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 16 ) ) //##+++++
+ msleep( sec * 1000 );
+ #else
+ {
+ DECLARE_WAIT_QUEUE_HEAD( tmp_wait );
+ wait_event_interruptible_timeout( tmp_wait, 0, sec * HZ + 1 );
+ }
+ #endif
+ #else
+ sleep( sec );
+ #endif
+
+ #elif defined( MBG_TGT_BSD )
+
+ //##+++++++++++++++++++ needs to be defined
+
+ #elif defined( MBG_TGT_DOS )
+
+ delay( sec * 1000 );
+
+ #else
+
+ // This needs to be implemented for the target OS
+ // and thus will probably yield a linker error.
+ do_sleep_sec( sec );
+
+ #endif
+
+} // mbg_sleep_sec
+
+
+
+#if !defined( MBG_MEM_ADDR )
+ // By default a memory address is stored
+ // as a 64 bit quantitiy.
+ #define MBG_MEM_ADDR uint64_t
+#endif
+
+
+typedef uint8_t MBG_DBG_DATA;
+typedef uint16_t MBG_DBG_PORT;
+
+
+// The following flags describe the bus types which are
+// supported by the plugin clocks.
+#define PCPS_BUS_ISA 0x0001 // IBM compatible PC/AT ISA bus
+#define PCPS_BUS_MCA 0x0002 // IBM PS/2 micro channel
+#define PCPS_BUS_PCI 0x0004 // PCI
+#define PCPS_BUS_USB 0x0008 // USB
+
+// The flags below are or'ed to the PC_BUS_PCI code
+// in order to indicate which PCI interface chip is used
+// on a PCI card. If no flag is set then the S5933 chip is
+// installed which has been used for the first generation
+// of Meinberg PCI cards.
+
+// S5920 PCI interface chip.
+#define PCPS_BUS_PCI_CHIP_S5920 0x8000
+
+// Meinberg's own PCI interface chip.
+#define PCPS_BUS_PCI_CHIP_ASIC 0x4000
+
+// PEX8311 PCI Express interface chip
+#define PCPS_BUS_PCI_CHIP_PEX8311 0x2000
+
+// Meinberg's own PCI Express interface chip
+#define PCPS_BUS_PCI_CHIP_MBGPEX 0x1000
+
+
+// The constant below combines the PCI bus flags.
+#define PCPS_BUS_PCI_S5933 ( PCPS_BUS_PCI )
+#define PCPS_BUS_PCI_S5920 ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_S5920 )
+#define PCPS_BUS_PCI_ASIC ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_ASIC )
+#define PCPS_BUS_PCI_PEX8311 ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_PEX8311 )
+#define PCPS_BUS_PCI_MBGPEX ( PCPS_BUS_PCI | PCPS_BUS_PCI_CHIP_MBGPEX )
+
+
+
+/** A list of known radio clocks. */
+enum PCPS_TYPES
+{
+ PCPS_TYPE_PC31,
+ PCPS_TYPE_PS31_OLD,
+ PCPS_TYPE_PS31,
+ PCPS_TYPE_PC32,
+ PCPS_TYPE_PCI32,
+ PCPS_TYPE_GPS167PC,
+ PCPS_TYPE_GPS167PCI,
+ PCPS_TYPE_PCI509,
+ PCPS_TYPE_GPS168PCI,
+ PCPS_TYPE_PCI510,
+ PCPS_TYPE_GPS169PCI,
+ PCPS_TYPE_TCR510PCI,
+ PCPS_TYPE_TCR167PCI,
+ PCPS_TYPE_GPS170PCI,
+ PCPS_TYPE_PCI511,
+ PCPS_TYPE_TCR511PCI,
+ PCPS_TYPE_PEX511,
+ PCPS_TYPE_TCR511PEX,
+ PCPS_TYPE_GPS170PEX,
+ PCPS_TYPE_USB5131,
+ PCPS_TYPE_TCR51USB,
+ PCPS_TYPE_MSF51USB,
+ PCPS_TYPE_PTP270PEX,
+ PCPS_TYPE_FRC511PEX,
+ PCPS_TYPE_TCR170PEX,
+ PCPS_TYPE_WWVB51USB,
+ PCPS_TYPE_GPS180PEX,
+ PCPS_TYPE_TCR180PEX,
+ PCPS_TYPE_DCF600USB,
+ N_PCPS_DEV_TYPE
+};
+
+
+#define PCPS_CLOCK_NAME_SZ 10 // including terminating 0
+
+typedef uint16_t PCPS_DEV_ID;
+typedef uint16_t PCPS_REF_TYPE;
+typedef uint16_t PCPS_BUS_FLAGS;
+
+/**
+ The structure contains the characteristics of each
+ of the clocks listed above. These fields are always the
+ same for a single type of clock and do not change with
+ firmware version, port address, etc.
+ */
+typedef struct
+{
+ uint16_t num;
+ char name[PCPS_CLOCK_NAME_SZ];
+ PCPS_DEV_ID dev_id;
+ PCPS_REF_TYPE ref_type;
+ PCPS_BUS_FLAGS bus_flags;
+} PCPS_DEV_TYPE;
+
+
+
+#if !defined( MBG_TGT_LINUX ) || defined( MBG_ARCH_X86 )
+ typedef uint16_t PCPS_PORT_ADDR;
+#else
+ typedef ulong PCPS_PORT_ADDR;
+#endif
+
+
+
+/**
+ The structure below describes an I/O port resource
+ used by a clock.
+*/
+typedef struct
+{
+ PCPS_PORT_ADDR base;
+ uint16_t num;
+} PCPS_PORT_RSRC;
+
+/** The max number of I/O port resources used by a clock. */
+#define N_PCPS_PORT_RSRC 2
+
+
+
+typedef struct
+{
+ MBG_MEM_ADDR user_virtual_address;
+ ulong len;
+ #if defined( MBG_TGT_LINUX )
+ uint32_t pfn_offset;
+ #endif
+} PCPS_MAPPED_MEM;
+
+
+
+typedef uint32_t PCPS_ERR_FLAGS; /**< see \ref group_err_flags "Error flags" */
+typedef uint32_t PCPS_FEATURES; /**< see \ref group_features "Features" */
+typedef uint16_t PCPS_BUS_NUM;
+typedef uint16_t PCPS_SLOT_NUM;
+
+/**
+ The structure below contains data which depends
+ on a individual instance of the clock, e.g.
+ the firmware which is currently installed, the
+ port address which has been configured, etc.
+*/
+typedef struct
+{
+ PCPS_ERR_FLAGS err_flags; /**< See \ref group_err_flags "Error flags" */
+ PCPS_BUS_NUM bus_num;
+ PCPS_SLOT_NUM slot_num;
+ PCPS_PORT_RSRC port[N_PCPS_PORT_RSRC];
+ uint16_t status_port;
+ int16_t irq_num;
+ uint32_t timeout_clk;
+ uint16_t fw_rev_num;
+ PCPS_FEATURES features; /**< See \ref group_features "Feature flags" */
+ PCPS_ID_STR fw_id;
+ PCPS_SN_STR sernum;
+} PCPS_DEV_CFG;
+
+/** @defgroup group_err_flags Error flags in PCPS_DEV_CFG
+ Flags used with PCPS_DEV_CFG::err_flags
+ @{
+*/
+#define PCPS_EF_TIMEOUT 0x00000001 /**< timeout occured */
+#define PCPS_EF_INV_EPROM_ID 0x00000002 /**< invalid EPROM ID */
+#define PCPS_EF_IO_INIT 0x00000004 /**< I/O intf not init'd */
+#define PCPS_EF_IO_CFG 0x00000008 /**< I/O intf not cfg'd */
+#define PCPS_EF_IO_ENB 0x00000010 /**< I/O intf not enabled */
+#define PCPS_EF_IO_RSRC 0x00000020 /**< I/O not registered w/ rsrcmgr */
+/** @} */
+
+/** @defgroup group_features Feature flags used with PCPS_FEATURES
+
+ Some features of the radio clocks have been introduced with
+ specific firmware versions, so depending on the firmware version
+ a clock may support a feature or not. The clock detection function
+ checks the clock model and firmware version and updates the field
+ PCPS_DEV_CFG::features accordingly. There are some macros which
+ can easily be used to query whether a clock device actually
+ supports a function, or not. The definitions define
+ the possible features.
+ @{
+*/
+enum
+{
+ PCPS_BIT_CAN_SET_TIME,
+ PCPS_BIT_HAS_SERIAL,
+ PCPS_BIT_HAS_SYNC_TIME,
+ PCPS_BIT_HAS_TZDL,
+ PCPS_BIT_HAS_IDENT,
+ PCPS_BIT_HAS_UTC_OFFS,
+ PCPS_BIT_HAS_HR_TIME,
+ PCPS_BIT_HAS_SERNUM,
+ PCPS_BIT_HAS_TZCODE,
+ PCPS_BIT_HAS_CABLE_LEN,
+ PCPS_BIT_HAS_EVENT_TIME, // custom GPS firmware only
+ PCPS_BIT_HAS_RECEIVER_INFO,
+ PCPS_BIT_CAN_CLR_UCAP_BUFF,
+ PCPS_BIT_HAS_PCPS_TZDL,
+ PCPS_BIT_HAS_UCAP,
+ PCPS_BIT_HAS_IRIG_TX,
+ PCPS_BIT_HAS_GPS_DATA_16, // use 16 bit size specifiers
+ PCPS_BIT_HAS_SYNTH,
+ PCPS_BIT_HAS_GENERIC_IO,
+ PCPS_BIT_HAS_TIME_SCALE,
+ PCPS_BIT_HAS_UTC_PARM,
+ PCPS_BIT_HAS_IRIG_CTRL_BITS,
+ PCPS_BIT_HAS_LAN_INTF,
+ PCPS_BIT_HAS_PTP,
+ PCPS_BIT_HAS_IRIG_TIME,
+ PCPS_BIT_HAS_FAST_HR_TSTAMP,
+ PCPS_BIT_HAS_RAW_IRIG_DATA,
+ N_PCPS_FEATURE
+};
+
+
+#define PCPS_CAN_SET_TIME ( 1UL << PCPS_BIT_CAN_SET_TIME )
+#define PCPS_HAS_SERIAL ( 1UL << PCPS_BIT_HAS_SERIAL )
+#define PCPS_HAS_SYNC_TIME ( 1UL << PCPS_BIT_HAS_SYNC_TIME )
+#define PCPS_HAS_TZDL ( 1UL << PCPS_BIT_HAS_TZDL )
+#define PCPS_HAS_IDENT ( 1UL << PCPS_BIT_HAS_IDENT )
+#define PCPS_HAS_UTC_OFFS ( 1UL << PCPS_BIT_HAS_UTC_OFFS )
+#define PCPS_HAS_HR_TIME ( 1UL << PCPS_BIT_HAS_HR_TIME )
+#define PCPS_HAS_SERNUM ( 1UL << PCPS_BIT_HAS_SERNUM )
+#define PCPS_HAS_TZCODE ( 1UL << PCPS_BIT_HAS_TZCODE )
+#define PCPS_HAS_CABLE_LEN ( 1UL << PCPS_BIT_HAS_CABLE_LEN )
+#define PCPS_HAS_EVENT_TIME ( 1UL << PCPS_BIT_HAS_EVENT_TIME )
+#define PCPS_HAS_RECEIVER_INFO ( 1UL << PCPS_BIT_HAS_RECEIVER_INFO )
+#define PCPS_CAN_CLR_UCAP_BUFF ( 1UL << PCPS_BIT_CAN_CLR_UCAP_BUFF )
+#define PCPS_HAS_PCPS_TZDL ( 1UL << PCPS_BIT_HAS_PCPS_TZDL )
+#define PCPS_HAS_UCAP ( 1UL << PCPS_BIT_HAS_UCAP )
+#define PCPS_HAS_IRIG_TX ( 1UL << PCPS_BIT_HAS_IRIG_TX )
+#define PCPS_HAS_GPS_DATA_16 ( 1UL << PCPS_BIT_HAS_GPS_DATA_16 )
+#define PCPS_HAS_SYNTH ( 1UL << PCPS_BIT_HAS_SYNTH )
+#define PCPS_HAS_GENERIC_IO ( 1UL << PCPS_BIT_HAS_GENERIC_IO )
+#define PCPS_HAS_TIME_SCALE ( 1UL << PCPS_BIT_HAS_TIME_SCALE )
+#define PCPS_HAS_UTC_PARM ( 1UL << PCPS_BIT_HAS_UTC_PARM )
+#define PCPS_HAS_IRIG_CTRL_BITS ( 1UL << PCPS_BIT_HAS_IRIG_CTRL_BITS )
+#define PCPS_HAS_LAN_INTF ( 1UL << PCPS_BIT_HAS_LAN_INTF )
+#define PCPS_HAS_PTP ( 1UL << PCPS_BIT_HAS_PTP )
+#define PCPS_HAS_IRIG_TIME ( 1UL << PCPS_BIT_HAS_IRIG_TIME )
+#define PCPS_HAS_FAST_HR_TSTAMP ( 1UL << PCPS_BIT_HAS_FAST_HR_TSTAMP )
+#define PCPS_HAS_RAW_IRIG_DATA ( 1UL << PCPS_BIT_HAS_RAW_IRIG_DATA )
+
+
+
+#define PCPS_FEATURE_NAMES \
+{ \
+ "PCPS_CAN_SET_TIME", \
+ "PCPS_HAS_SERIAL", \
+ "PCPS_HAS_SYNC_TIME", \
+ "PCPS_HAS_TZDL", \
+ "PCPS_HAS_IDENT", \
+ "PCPS_HAS_UTC_OFFS", \
+ "PCPS_HAS_HR_TIME", \
+ "PCPS_HAS_SERNUM", \
+ "PCPS_HAS_TZCODE", \
+ "PCPS_HAS_CABLE_LEN", \
+ "PCPS_HAS_EVENT_TIME", \
+ "PCPS_HAS_RECEIVER_INFO", \
+ "PCPS_CAN_CLR_UCAP_BUFF", \
+ "PCPS_HAS_PCPS_TZDL", \
+ "PCPS_HAS_UCAP", \
+ "PCPS_HAS_IRIG_TX", \
+ "PCPS_HAS_GPS_DATA_16", \
+ "PCPS_HAS_SYNTH", \
+ "PCPS_HAS_GENERIC_IO", \
+ "PCPS_HAS_TIME_SCALE", \
+ "PCPS_HAS_UTC_PARM", \
+ "PCPS_HAS_IRIG_CTRL_BITS", \
+ "PCPS_HAS_LAN_INTF", \
+ "PCPS_HAS_PTP", \
+ "PCPS_HAS_IRIG_TIME", \
+ "PCPS_HAS_FAST_HR_TSTAMP", \
+ "PCPS_HAS_RAW_IRIG_DATA" \
+}
+
+/** @} */
+
+
+
+// The constants below define those features which are available
+// in ALL firmware versions which have been shipped with a
+// specific clock.
+
+#define PCPS_FEAT_PC31PS31 0
+
+// Some of the features are available in all newer clocks,
+// so these have been put together in one definition:
+#define PCPS_FEAT_LVL2 ( PCPS_CAN_SET_TIME \
+ | PCPS_HAS_SERIAL \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_UTC_OFFS )
+
+#define PCPS_FEAT_PC32 ( PCPS_FEAT_LVL2 )
+
+#define PCPS_FEAT_PCI32 ( PCPS_FEAT_LVL2 )
+
+#define PCPS_FEAT_PCI509 ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_TZCODE )
+
+#define PCPS_FEAT_PCI510 ( PCPS_FEAT_PCI509 )
+
+#define PCPS_FEAT_PCI511 ( PCPS_FEAT_PCI510 )
+
+#define PCPS_FEAT_GPS167PC ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_IDENT )
+
+#define PCPS_FEAT_GPS167PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_IDENT \
+ | PCPS_HAS_HR_TIME )
+
+#define PCPS_FEAT_GPS168PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_IDENT \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_CABLE_LEN \
+ | PCPS_HAS_RECEIVER_INFO )
+
+#define PCPS_FEAT_GPS169PCI ( PCPS_FEAT_GPS168PCI \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP )
+
+#define PCPS_FEAT_GPS170PCI ( PCPS_FEAT_GPS169PCI \
+ | PCPS_HAS_IRIG_TX \
+ | PCPS_HAS_GPS_DATA_16 \
+ | PCPS_HAS_GENERIC_IO )
+
+#define PCPS_FEAT_TCR510PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_SERNUM )
+
+#define PCPS_FEAT_TCR167PCI ( PCPS_FEAT_LVL2 \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_TZDL \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_IRIG_TX \
+ | PCPS_HAS_GPS_DATA_16 \
+ | PCPS_HAS_GENERIC_IO )
+
+#define PCPS_FEAT_TCR511PCI ( PCPS_FEAT_TCR510PCI \
+ | PCPS_HAS_HR_TIME )
+
+#define PCPS_FEAT_PEX511 ( PCPS_FEAT_PCI511 )
+
+#define PCPS_FEAT_TCR511PEX ( PCPS_FEAT_TCR511PCI )
+
+#define PCPS_FEAT_GPS170PEX ( PCPS_FEAT_GPS170PCI )
+
+#define PCPS_FEAT_USB5131 ( PCPS_HAS_UTC_OFFS \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_CAN_SET_TIME \
+ | PCPS_HAS_TZCODE )
+
+#define PCPS_FEAT_TCR51USB ( PCPS_HAS_UTC_OFFS \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_CAN_SET_TIME )
+
+#define PCPS_FEAT_MSF51USB ( PCPS_HAS_UTC_OFFS \
+ | PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_CAN_SET_TIME )
+
+#define PCPS_FEAT_PTP270PEX ( PCPS_HAS_SERNUM \
+ | PCPS_HAS_SYNC_TIME \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_SET_TIME \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_GPS_DATA_16 )
+
+#define PCPS_FEAT_FRC511PEX ( PCPS_HAS_SERNUM \
+ | PCPS_HAS_HR_TIME \
+ | PCPS_HAS_RECEIVER_INFO \
+ | PCPS_CAN_SET_TIME \
+ | PCPS_CAN_CLR_UCAP_BUFF \
+ | PCPS_HAS_UCAP \
+ | PCPS_HAS_GPS_DATA_16 )
+
+#define PCPS_FEAT_TCR170PEX ( PCPS_FEAT_TCR167PCI )
+
+#define PCPS_FEAT_WWVB51USB ( PCPS_FEAT_MSF51USB )
+
+#define PCPS_FEAT_GPS180PEX ( PCPS_FEAT_GPS170PEX | PCPS_HAS_FAST_HR_TSTAMP )
+
+#define PCPS_FEAT_TCR180PEX ( PCPS_FEAT_TCR170PEX | PCPS_HAS_FAST_HR_TSTAMP )
+
+#define PCPS_FEAT_DCF600USB ( PCPS_FEAT_USB5131 )
+
+// Some features of the API used to access Meinberg plug-in radio clocks
+// have been implemented starting with the special firmware revision
+// numbers defined below.
+//
+// If no number is specified for a feature/clock model then the feature
+// is either always supported by that clock model, or not at all.
+
+
+// There are some versions of PCI Express cards out there which do not
+// safely support hardware IRQs. The following firmware versions are required
+// for safe IRQ operation:
+#define REV_HAS_IRQ_FIX_MINOR_PEX511 0x0106
+#define REV_HAS_IRQ_FIX_MINOR_TCR511PEX 0x0105
+#define REV_HAS_IRQ_FIX_MINOR_GPS170PEX 0x0104
+// Additionally there are certain revisions of the bus interface logic
+// required. The associated version codes are defined in pci_asic.h.
+
+// The macro below can be used to check whether the required versions are there:
+#define _pcps_pex_irq_is_safe( _curr_fw_ver, _req_fw_ver, _curr_asic_ver, \
+ _req_asic_ver_major, _req_asic_ver_minor ) \
+ ( ( (_curr_fw_ver) >= (_req_fw_ver) ) && _pcps_asic_version_greater_equal( \
+ (_curr_asic_ver), (_req_asic_ver_major), (_req_asic_ver_minor ) ) \
+ )
+
+/* command PCPS_GIVE_RAW_IRIG_DATA: */
+#define REV_HAS_RAW_IRIG_DATA_TCR511PEX 0x0111
+#define REV_HAS_RAW_IRIG_DATA_TCR511PCI 0x0111
+#define REV_HAS_RAW_IRIG_DATA_TCR51USB 0x0106
+
+/* command PCPS_GIVE_IRIG_TIME: */
+#define REV_HAS_IRIG_TIME_TCR511PEX 0x0109
+#define REV_HAS_IRIG_TIME_TCR511PCI 0x0109
+#define REV_HAS_IRIG_TIME_TCR51USB 0x0106
+
+/* command PCPS_GET_IRIG_CTRL_BITS: */
+#define REV_HAS_IRIG_CTRL_BITS_TCR511PEX 0x0107
+#define REV_HAS_IRIG_CTRL_BITS_TCR511PCI 0x0107
+#define REV_HAS_IRIG_CTRL_BITS_TCR51USB 0x0106
+
+/* This board uses the GPS_DATA interface with 16 bit buffer sizes
+ instead of the original 8 bit sizes, thus allowing to transfer
+ data blocks which exceed 255 bytes (PCPS_HAS_GPS_DATA_16) */
+#define REV_HAS_GPS_DATA_16_GPS169PCI 0x0202
+
+/* the clock supports a higher baud rate than N_PCPS_BD_DCF */
+#define REV_HAS_SERIAL_HS_PCI509 0x0104
+
+/* commands PCPS_GIVE_UCAP_ENTRIES, PCPS_GIVE_UCAP_EVENT */
+#define REV_HAS_UCAP_GPS167PCI 0x0421
+#define REV_HAS_UCAP_GPS168PCI 0x0104
+
+/* command PCPS_CLR_UCAP_BUFF */
+#define REV_CAN_CLR_UCAP_BUFF_GPS167PCI 0x0419
+#define REV_CAN_CLR_UCAP_BUFF_GPS168PCI 0x0101
+
+/* commands PCPS_READ_GPS_DATA and PCPS_WRITE_GPS_DATA with */
+/* code PC_GPS_ANT_CABLE_LEN */
+#define REV_HAS_CABLE_LEN_GPS167PCI 0x0411
+#define REV_HAS_CABLE_LEN_GPS167PC 0x0411
+
+/* command PCPS_GIVE_HR_TIME, structure PCPS_HR_TIME: */
+#define REV_HAS_HR_TIME_GPS167PC 0x0305
+#define REV_HAS_HR_TIME_TCR510PCI 0x0200
+#define REV_HAS_HR_TIME_PEX511 0x0105 // This also requires a certain ASIC version.
+#define REV_HAS_HR_TIME_PCI511 0x0103
+
+/* field offs_utc in structure PCPS_TIME: */
+#define REV_HAS_UTC_OFFS_PC31PS31 0x0300
+
+/* command PCPS_GIVE_SYNC_TIME: */
+#define REV_HAS_SYNC_TIME_PC31PS31 0x0300
+
+/* command PCPS_GET_SERIAL, PCPS_SET_SERIAL: */
+#define REV_HAS_SERIAL_PC31PS31 0x0300
+
+/* command PCPS_GIVE_TIME_NOCLEAR: */
+#define REV_GIVE_TIME_NOCLEAR_PC31PS31 0x0300
+
+/* status bit PCPS_LS_ANN: */
+#define REV_PCPS_LS_ANN_PC31PS31 0x0300
+
+/* status bit PCPS_IFTM: */
+#define REV_PCPS_IFTM_PC31PS31 0x0300
+
+/* command PCPS_SET_TIME: */
+#define REV_CAN_SET_TIME_PC31PS31 0x0240
+
+/* command PCPS_GIVE_TIME_NOCLEAR: */
+// This is supported by all clocks but PC31/PS31 with
+// firmware versions before v3.0. If such a card shall
+// be used then the firmware should be updated to the
+// last recent version.
+
+
+/**
+ The structure has been defined to pass all
+ information on a clock device from a device driver
+ to a user program. */
+typedef struct
+{
+ PCPS_DEV_TYPE type;
+ PCPS_DEV_CFG cfg;
+} PCPS_DEV;
+
+
+// The macros below simplify access to the data
+// stored in PCPS_DEV structure and should be used
+// to extract the desired information.
+// If the formal parameter is called _d then a pointer
+// to device structure PCPS_DEV is expected.
+// If the formal parameter is called _c then a pointer
+// to configuration structure PCPS_DEV_CFG is expected.
+
+// Access device type information:
+#define _pcps_type_num( _d ) ( (_d)->type.num )
+#define _pcps_type_name( _d ) ( (_d)->type.name )
+#define _pcps_dev_id( _d ) ( (_d)->type.dev_id )
+#define _pcps_ref_type( _d ) ( (_d)->type.ref_type )
+#define _pcps_bus_flags( _d ) ( (_d)->type.bus_flags )
+
+// Query device type features:
+#define _pcps_is_gps( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_GPS )
+#define _pcps_is_dcf( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_DCF )
+#define _pcps_is_msf( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_MSF )
+#define _pcps_is_wwvb( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_WWVB )
+#define _pcps_is_irig_rx( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_IRIG )
+#define _pcps_is_ptp( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_PTP )
+#define _pcps_is_frc( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_FRC )
+
+#define _pcps_is_lwr( _d ) ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) )
+
+#define _pcps_is_isa( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_ISA )
+#define _pcps_is_mca( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_MCA )
+#define _pcps_is_pci( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_PCI )
+#define _pcps_is_usb( _d ) ( _pcps_bus_flags( _d ) & PCPS_BUS_USB )
+
+#define _pcps_is_pci_s5933( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_S5933 )
+#define _pcps_is_pci_s5920( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_S5920 )
+#define _pcps_is_pci_amcc( _d ) ( _pcps_is_pci_s5920( _d ) || _pcps_is_pci_s5933( _d ) )
+#define _pcps_is_pci_asic( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_ASIC )
+#define _pcps_is_pci_pex8311( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_PEX8311 )
+#define _pcps_is_pci_mbgpex( _d ) ( _pcps_bus_flags( _d ) == PCPS_BUS_PCI_MBGPEX )
+
+
+// Access device configuration information:
+#define _pcps_bus_num( _d ) ( (_d)->cfg.bus_num )
+#define _pcps_slot_num( _d ) ( (_d)->cfg.slot_num )
+
+#define _pcps_cfg_port_rsrc( _c, _n ) ( (_c)->port[_n] )
+#define _pcps_port_rsrc( _d, _n ) _pcps_cfg_port_rsrc( &(_d)->cfg, (_n) )
+#define _pcps_port_rsrc_unused( _d ) ( (_d)->base == 0 || (_d)->num == 0 )
+
+#define _pcps_cfg_port_base( _c, _n ) ( _pcps_cfg_port_rsrc( (_c), (_n) ).base )
+#define _pcps_port_base( _d, _n ) ( _pcps_port_rsrc( (_d), (_n) ).base )
+
+#define _pcps_cfg_irq_num( _c ) ( (_c)->irq_num )
+#define _pcps_irq_num( _d ) _pcps_cfg_irq_num( &(_d)->cfg )
+
+#define _pcps_cfg_timeout_clk( _c ) ( (_c)->timeout_clk )
+#define _pcps_timeout_clk( _d ) _pcps_cfg_timeout_clk( &(_d)->cfg )
+
+#define _pcps_fw_rev_num( _d ) ( (_d)->cfg.fw_rev_num )
+#define _pcps_features( _d ) ( (_d)->cfg.features )
+#define _pcps_fw_id( _d ) ( (_d)->cfg.fw_id )
+#define _pcps_sernum( _d ) ( (_d)->cfg.sernum )
+
+
+// The macros below handle the clock device's err_flags.
+#define _pcps_err_flags( _d ) ( (_d)->cfg.err_flags )
+#define _pcps_chk_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) & (_msk) )
+#define _pcps_set_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) |= (_msk) )
+#define _pcps_clr_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) &= ~(_msk) )
+
+
+// Query whether a special feature is supported:
+#define _pcps_has_feature( _d, _f ) ( ( (_d)->cfg.features & (_f) ) != 0 )
+
+// Query whether a special feature is supported according to RECEIVER_INFO:
+#define _pcps_has_ri_feature( _p_ri, _f ) ( ( (_p_ri)->features & (_f) ) != 0 )
+
+
+#define _pcps_can_set_time( _d ) _pcps_has_feature( (_d), PCPS_CAN_SET_TIME )
+#define _pcps_has_serial( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERIAL )
+#define _pcps_has_sync_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_SYNC_TIME )
+#define _pcps_has_ident( _d ) _pcps_has_feature( (_d), PCPS_HAS_IDENT )
+#define _pcps_has_utc_offs( _d ) _pcps_has_feature( (_d), PCPS_HAS_UTC_OFFS )
+#define _pcps_has_hr_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_HR_TIME )
+#define _pcps_has_sernum( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERNUM )
+#define _pcps_has_cab_len( _d ) _pcps_has_feature( (_d), PCPS_HAS_CABLE_LEN )
+#define _pcps_has_tzdl( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZDL )
+#define _pcps_has_pcps_tzdl( _d ) _pcps_has_feature( (_d), PCPS_HAS_PCPS_TZDL )
+#define _pcps_has_tzcode( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZCODE )
+#define _pcps_has_tz( _d ) _pcps_has_feature( (_d), PCPS_HAS_TZDL \
+ | PCPS_HAS_PCPS_TZDL \
+ | PCPS_HAS_TZCODE )
+// The next one is supported only with a certain GPS firmware version:
+#define _pcps_has_event_time( _d ) _pcps_has_feature( (_d), PCPS_HAS_EVENT_TIME )
+#define _pcps_has_receiver_info( _d ) _pcps_has_feature( (_d), PCPS_HAS_RECEIVER_INFO )
+#define _pcps_can_clr_ucap_buff( _d ) _pcps_has_feature( (_d), PCPS_CAN_CLR_UCAP_BUFF )
+#define _pcps_has_ucap( _d ) _pcps_has_feature( (_d), PCPS_HAS_UCAP )
+#define _pcps_has_irig_tx( _d ) _pcps_has_feature( (_d), PCPS_HAS_IRIG_TX )
+
+// The macro below determines whether a DCF77 clock
+// supports a higher baud rate than standard
+#define _pcps_has_serial_hs( _d ) \
+ ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR511PEX ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PEX511 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_TCR511PCI ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_TCR510PCI ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PCI511 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PCI510 ) || \
+ ( _pcps_type_num( _d ) == PCPS_TYPE_PCI509 && \
+ _pcps_fw_rev_num( _d ) >= REV_HAS_SERIAL_HS_PCI509 ) )
+
+
+#define _pcps_has_signal( _d ) \
+ ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) || _pcps_is_irig_rx( _d ) )
+
+#define _pcps_has_mod( _d ) \
+ ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) )
+
+
+#define _pcps_has_irig( _d ) \
+ ( _pcps_is_irig_rx( _d ) || _pcps_has_irig_tx( _d ) )
+
+#define _pcps_has_irig_ctrl_bits( _d ) \
+ _pcps_has_feature( (_d), PCPS_HAS_IRIG_CTRL_BITS )
+
+#define _pcps_has_irig_time( _d ) \
+ _pcps_has_feature( (_d), PCPS_HAS_IRIG_TIME )
+
+#define _pcps_has_raw_irig_data( _d ) \
+ _pcps_has_feature( (_d), PCPS_HAS_RAW_IRIG_DATA )
+
+#define _pcps_has_ref_offs( _d ) \
+ _pcps_is_irig_rx( _d )
+
+#define _pcps_ref_offs_out_of_range( _n ) \
+ ( ( (_n) > MBG_REF_OFFS_MAX ) || ( (_n) < -MBG_REF_OFFS_MAX ) )
+
+#define _pcps_has_opt_flags( _d ) \
+ _pcps_is_irig_rx( _d )
+
+#define _pcps_has_gps_data_16( _d ) _pcps_has_feature( (_d), PCPS_HAS_GPS_DATA_16 )
+
+#define _pcps_has_gps_data( _d ) \
+ ( _pcps_is_gps( _d ) || _pcps_has_gps_data_16( _d ) )
+
+#define _pcps_has_synth( _d ) _pcps_has_feature( (_d), PCPS_HAS_SYNTH )
+
+#define _pcps_has_generic_io( _d ) _pcps_has_feature( (_d), PCPS_HAS_GENERIC_IO )
+
+#define _pcps_has_time_scale( _d ) _pcps_has_feature( (_d), PCPS_HAS_TIME_SCALE )
+
+#define _pcps_has_utc_parm( _d ) _pcps_has_feature( (_d), PCPS_HAS_UTC_PARM )
+
+#define _pcps_has_fast_hr_timestamp( _d ) _pcps_has_feature( (_d), PCPS_HAS_FAST_HR_TSTAMP )
+
+#define _pcps_has_lan_intf( _d ) _pcps_has_feature( (_d), PCPS_HAS_LAN_INTF )
+
+#define _pcps_has_ptp( _d ) _pcps_has_feature( (_d), PCPS_HAS_PTP )
+
+#define _pcps_has_ri_ptp_unicast( _p_ri ) _pcps_has_ri_feature( (_p_ri), GPS_HAS_PTP_UNICAST )
+
+#define _pcps_has_asic_version( _d ) ( _pcps_is_pci_asic( _d ) \
+ || _pcps_is_pci_pex8311( _d ) \
+ || _pcps_is_pci_mbgpex( _d ) )
+
+#define _pcps_has_asic_features( _d ) _pcps_has_asic_version( _d )
+
+
+
+// There are some versions of IRIG receiver cards which ignore the TFOM code
+// of an incoming IRIG signal even if an IRIG code has been configured which
+// supports this. In this case these cards synchronize to the incoming IRIG
+// signal even if the TFOM code reports the IRIG generator is not synchronized.
+// The intended behaviour is that the IRIG receiver card changes its status
+// to "freewheeling" in this case, unless it has been configured to ignore
+// the TFOM code of the incoming IRIG signal (see the IFLAGS_DISABLE_TFOM flag
+// defined in gpsdefs.h).
+
+// The macro below can be used to check based on the device info if a specific
+// card with a specific firmware always ignores the TFOM code:
+#define _pcps_incoming_tfom_ignored( _d ) \
+ ( ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR167PCI ) && ( _pcps_fw_rev_num( _d ) <= 0x121 ) ) \
+ || ( ( _pcps_type_num( _d ) == PCPS_TYPE_TCR170PEX ) && ( _pcps_fw_rev_num( _d ) <= 0x103 ) ) )
+
+
+
+/**
+ The structure is used to return info
+ on the device driver.*/
+typedef struct
+{
+ uint16_t ver_num; /**< the device driver's version number */
+ uint16_t n_devs; /**< the number of radio clocks handled by the driver */
+ PCPS_ID_STR id_str; /**< the device driver's ID string */
+} PCPS_DRVR_INFO;
+
+
+
+/*
+ * The definitions and types below are used to collect
+ * all configuration parameters of a clock's serial ports
+ * that can be handled by this library:
+ */
+
+// The maximum number of clocks' serial ports and string types
+// that can be handled by the configuration programs:
+#define MAX_PARM_PORT 4
+#define MAX_PARM_STR_TYPE 20
+
+typedef PORT_INFO_IDX ALL_PORT_INFO[MAX_PARM_PORT];
+typedef STR_TYPE_INFO_IDX ALL_STR_TYPE_INFO[MAX_PARM_STR_TYPE];
+
+typedef struct
+{
+ ALL_PORT_INFO pii;
+ ALL_STR_TYPE_INFO stii;
+ PORT_PARM tmp_pp;
+
+} RECEIVER_PORT_CFG;
+
+
+
+/*
+ * The definitions and types below are used to collect
+ * all configuration parameters of a clock's programmable
+ * pulse outputs that can be handled by this library:
+ */
+
+#define MAX_PARM_POUT 4
+
+typedef POUT_INFO_IDX ALL_POUT_INFO[MAX_PARM_POUT];
+
+
+
+// The macros below can be used to mark a PCPS_TIME variable
+// as unread, i.e. its contents have not been read from the clock,
+// and to check if such a variable is marked as unread.
+#define _pcps_time_set_unread( _t ) do { (_t)->sec = 0xFF; } while ( 0 )
+#define _pcps_time_is_read( _t ) ( (uchar) (_t)->sec != 0xFF )
+
+
+
+/**
+ The structure is used to read the current time from
+ a device, combined with an associated PC cycle counter value
+ to compensate program execution time.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cycles;
+ PCPS_TIME t;
+} PCPS_TIME_CYCLES;
+
+
+
+/**
+ The structure is used to read a high resolution UTC time stamp
+ plus associated PC cycles counter value to compensate the latency.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cycles;
+ PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */
+} PCPS_TIME_STAMP_CYCLES;
+
+#define _mbg_swab_pcps_time_stamp_cycles( _p ) \
+{ \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \
+ _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \
+}
+
+
+
+/**
+ The structure is used to read the current high resolution time
+ from a device, combined with an associated PC cycle counter value
+ to compensate program execution time.
+ */
+typedef struct
+{
+ MBG_PC_CYCLES cycles;
+ PCPS_HR_TIME t;
+} PCPS_HR_TIME_CYCLES;
+
+#define _mbg_swab_pcps_hr_time_cycles( _p ) \
+{ \
+ _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \
+ _mbg_swab_pcps_hr_time( &(_p)->t ); \
+}
+
+
+
+/**
+ The structure below can be used to let the kernel driver read
+ the current system time plus the associated HR time from a plugin card
+ as close as possibly, and return the results to a user space application
+ which can then compute the time difference and latencies.
+ This structure also contains the card's status information (e.g. sync status).
+ */
+typedef struct
+{
+ PCPS_HR_TIME_CYCLES ref_hr_time_cycles; /**< HR time read from the card, plus cycles */
+ MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */
+} MBG_TIME_INFO_HRT;
+
+#define _mbg_swab_mbg_time_info_hrt( _p ) \
+{ \
+ _mbg_swab_pcps_hr_time_cycles( &(_p)->ref_hr_time_cycles ); \
+ _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \
+}
+
+
+
+/**
+ The structure below can be used to let the kernel driver read
+ the current system time plus an associated HR timestamp from a plugin card
+ as close as possibly, and return the results to a user space application
+ which can then compute the time difference and latencies.
+ Since the card's time stamp is usually taken using the fast memory mapped
+ access this structure does *not* contain the card's status information
+ (e.g. sync status).
+ */
+typedef struct
+{
+ PCPS_TIME_STAMP_CYCLES ref_tstamp_cycles; /**< HR timestamp from the card, plus cycles */
+ MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */
+} MBG_TIME_INFO_TSTAMP;
+
+#define _mbg_swab_mbg_time_info_tstamp( _p ) \
+{ \
+ _mbg_swab_pcps_time_stamp_cycles( &(_p)->ref_tstamp_cycles ); \
+ _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \
+}
+
+
+
+typedef uint32_t PCPS_IRQ_STAT_INFO;
+
+// Flags used with PCPS_IRQ_STAT_INFO:
+#define PCPS_IRQ_STAT_ENABLE_CALLED 0x01
+#define PCPS_IRQ_STAT_ENABLED 0x02
+#define PCPS_IRQ_STAT_UNSAFE 0x04 // IRQs unsafe with this firmeware version / ASIC
+
+#define PCPS_IRQ_STATE_DANGER ( PCPS_IRQ_STAT_ENABLED | PCPS_IRQ_STAT_UNSAFE )
+
+#define _pcps_fw_rev_num_major( _v ) \
+ ( ( (_v) >> 8 ) & 0xFF )
+
+#define _pcps_fw_rev_num_minor( _v ) \
+ ( (_v) & 0xFF )
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _PCPSDEV_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c
new file mode 100755
index 0000000..78531c4
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c
@@ -0,0 +1,3459 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsdrvr.c 1.46.2.35 2011/03/25 11:10:34 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Driver functions that detect Meinberg PC plug-in devices and set up
+ * the software environment (port base address, clock features, etc.).
+ *
+ * These functions should be used with programs which have direct
+ * access to the hardware (e.g. device drivers).
+ *
+ * Programs which access the devices via device drivers should
+ * use the functions provided by the mbgdevio module.
+ *
+ * There are several preprocessor symbols defined at the top of
+ * pcpsdrvr.h which control the default support of some features
+ * under the different operating systems. If required, each of
+ * those symbols can be overridden by compiler arguments.
+ *
+ * Basically the following radio clocks are supported:
+ * USB: USB5131, TCR51USB, MSF51USB, WWVB51USB, DCF600USB
+ * PCI express: PEX511, TCR511PEX, GPS170PEX, PTP270PEX,
+ * FRC511PEX, TCR170PEX, GPS180PEX, TCR180PEX
+ * PCI bus 5V/3.3V: PCI510, PCI511, GPS169PCI, GPS170PCI,
+ * TCR510PCI, TCR167PCI, TCR511PCI
+ * PCI bus 5V: PCI32, GPS167PCI, PCI509, GPS168PCI
+ * MCA bus: PS31
+ * ISA bus: PC31, PC32, GPS167PC
+ *
+ * USB is not supported for some target environments, mainly because
+ * those operating systems don't provide full USB support.
+ *
+ * PCI support is possible in two different ways. The preferred
+ * functions are compiled in if one of the symbols _PCPS_USE_PCI_PNP
+ * or _PCPS_USE_PCI_BIOS is defined != 0.
+ *
+ * If _PCPS_USE_PCI_PNP is != 0 it is assumed that the operating
+ * system's PCI layer detects a new PCI device and calls a driver's
+ * add_device()/start_device() function to initialize the device.
+ * This new technique is supported with PNP operating systems
+ * (e.g. Win98, Win2K, newer Linux versions).
+ *
+ * If _PCPS_USE_PCI_BIOS is != 0 the program scans the PCI bus
+ * during startup to detect and initialize supported PCI devices.
+ * This techique is used with non-PNP operating systems.
+ *
+ * The symbol _PCPS_USE_RSRCMGR must be defined != 0 to include
+ * support of resource managers, if necessary.
+ *
+ * If the symbol _PCPS_USE_MCA is defined != 0 then Micro Channel
+ * detection (and therefore auto-detection of a MCA clock) is
+ * supported.
+ *
+ * MCA clocks are accessed using the same low level functions as
+ * ISA clocks, so if autodetection of MCA clocks is not supported
+ * then a MCA clock's known port number can be passed to
+ * pcps_detect_clocks() to let it be treated like an ISA clock.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsdrvr.c $
+ * Revision 1.46.2.35 2011/03/25 11:10:34 martin
+ * Optionally support timespec for sys time (USE_TIMESPEC).
+ * Revision 1.46.2.34 2011/03/22 10:25:57 martin
+ * Modifications to support NetBSD.
+ * Revision 1.46.2.33 2011/03/21 16:26:03 martin
+ * Account for modified _pcps_kfree().
+ * Revision 1.46.2.32 2011/02/16 10:14:37 martin
+ * Set up basic default receiver info for devices which don't
+ * support this structure.
+ * Revision 1.46.2.31 2011/02/15 14:24:57Z martin
+ * Revision 1.46.2.30 2011/02/10 09:18:07 martin
+ * Revision 1.46.2.29 2011/02/09 17:08:30Z martin
+ * Specify I/O range number when calling port I/O macros
+ * so they can be used for different ranges under BSD.
+ * Revision 1.46.2.28 2011/02/09 16:42:12 martin
+ * Revision 1.46.2.27 2011/02/09 15:27:49 martin
+ * Revision 1.46.2.26 2011/02/09 14:43:19Z martin
+ * Revision 1.46.2.25 2011/02/07 15:47:28 martin
+ * Fixed a potential trap in kernel messages.
+ * Revision 1.46.2.24 2011/02/04 14:44:45 martin
+ * Revision 1.46.2.23 2011/02/01 17:12:04 martin
+ * Revision 1.46.2.22 2011/02/01 15:08:34 martin
+ * Revision 1.46.2.21 2011/02/01 12:12:18 martin
+ * Revision 1.46.2.20 2011/01/31 17:30:28 martin
+ * Preliminary virt addr under *BSD.
+ * Revision 1.46.2.19 2011/01/28 10:34:06 martin
+ * Moved MBG_TGT_SUPP_MEM_ACC definition to pcpsdev.h.
+ * Revision 1.46.2.18 2011/01/27 15:13:08 martin
+ * Added some debug messages in pcps_start_device().
+ * Revision 1.46.2.17 2011/01/27 13:39:33 martin
+ * Revision 1.46.2.16 2011/01/27 11:01:48 martin
+ * Support static device list (no malloc) and use it under FreeBSD.
+ * Revision 1.46.2.15 2011/01/26 16:40:14 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.46.2.14 2011/01/26 11:30:29 martin
+ * Fixed PTP270PEX boot delay.
+ * Revision 1.46.2.13 2011/01/07 14:00:58 daniel
+ * Re-enabled wait period for PTP270PEX
+ * Revision 1.46.2.12 2010/11/23 11:07:56Z martin
+ * Support memory mapped access under DOS.
+ * Revision 1.46.2.11 2010/11/22 14:19:27Z martin
+ * Support DCF600USB.
+ * Cleanup.
+ * Revision 1.46.2.10 2010/10/06 09:24:02 martin
+ * Revision 1.46.2.9 2010/09/27 13:09:22Z martin
+ * Revision 1.46.2.8 2010/09/21 13:10:15 daniel
+ * Check for raw IRIG data support in reciver info.
+ * Revision 1.46.2.7 2010/09/02 12:19:24Z martin
+ * Introduced and use new function check_ri_feature().
+ * Also detect support for raw IRIG data from RECEIVER_INFO.
+ * Added debug code.
+ * Sleeping for PTP270PEX if uptime is too low needs to be fixed.
+ * Revision 1.46.2.6 2010/08/16 15:41:28 martin
+ * Revision 1.46.2.5 2010/08/13 11:56:49 martin
+ * Fixed build on WIN32_NON_PNP.
+ * Revision 1.46.2.4 2010/08/13 11:20:23Z martin
+ * If required, wait until PTP270PEX has finished booting.
+ * Revision 1.46.2.3 2010/08/11 13:41:47Z martin
+ * Code cleanup.
+ * Revision 1.46.2.2 2010/07/14 14:51:56 martin
+ * Use direct pointer to memory maopped timestamp.
+ * Revision 1.46.2.1 2010/06/30 15:02:12 martin
+ * Support GPS180PEX and TCR180PEX.
+ * Revision 1.46 2009/12/15 14:45:33 daniel
+ * Account for feature to read the raw IRIG bits.
+ * Revision 1.45 2009/09/29 07:24:50Z martin
+ * Use standard feature flag to check if fast HR time is supported.
+ * Revision 1.44 2009/06/23 07:10:47 martin
+ * Fixed/modified some debug messages.
+ * Revision 1.43 2009/06/19 12:13:59 martin
+ * Check if TCR cards support raw IRIG time.
+ * Revision 1.42 2009/06/09 10:15:33 daniel
+ * Check if card has LAN interface and supports PTP.
+ * Revision 1.41 2009/04/08 08:33:20 daniel
+ * Check whether the TCR511PCI or devices with
+ * RECEIVER_INFO support IRIG control function bits.
+ * Revision 1.40 2009/03/27 09:55:13Z martin
+ * Added some debug messages.
+ * Account for renamed library symbols.
+ * Revision 1.39 2009/03/19 12:04:31Z martin
+ * Adjust endianess of ASIC version and ASIC features after having read.
+ * Revision 1.38 2009/03/17 15:33:53 martin
+ * Support reading IRIG control function bits.
+ * Revision 1.37 2009/03/13 09:17:00Z martin
+ * Bug fix: Hadn't checked whether TCR170PEX card provides the
+ * programmable synthesizer.
+ * As a fix moved the code from the body of check_opt_features()
+ * into pcps_start_device() so that the check is done for every
+ * type of card.
+ * Swap receiver_info to make this work on non-x86 architectures.
+ * Support configurable time scales, and reading/writing GPS UTC
+ * parameters via the PC bus.
+ * Use mbg_get_pc_cycles() instead of _pcps_get_cycles().
+ * Revision 1.36 2009/01/13 12:03:57Z martin
+ * Generate a separate warning message if the firmware could not
+ * be read from an ISA card.
+ * Care about "long long" in debug msg.
+ * Revision 1.35 2008/12/16 14:38:49Z martin
+ * Account for new devices PTP270PEX, FRC270PEX, TCR170PEX, and WWVB51USB.
+ * Check the firmware / ASIC version of PEX cards and flag the device
+ * unsafe for IRQs if the versions are older than required.
+ * Check whether PEX511 and PCI511 support HR time.
+ * Moved initialization of common spinlocks and mutexes to pcps_start_device().
+ * Take access cycles count in the low level routines, with interrupts disabled.
+ * Cleanup for pcps_read_usb() which is now possible since access cycles count
+ * is now taken inside the low evel routines.
+ * Support mapped I/O resources, unaligned access and endianess conversion.
+ * Account for ASIC_FEATURES being coded as flags, and account for
+ * new symbol PCI_ASIC_HAS_MM_IO.
+ * Account for new MBG_PC_CYCLES type.
+ * Account for signed irq_num.
+ * Renamed MBG_VIRT_ADDR to MBG_MEM_ADDR.
+ * Use MBG_MEM_ADDR type for memory rather than split high/low types.
+ * Distinguish device port variables for IRQ handling.
+ * Preliminarily support USB latency compensation under Win32 PNP targets
+ * and account for USB EHCI microframe timing which requires a different
+ * latency compensation approach. This is useful if a USB 2.0 hub is connected
+ * between device and host.
+ * Also read the ASIC version at device initialization.
+ * pcps_alloc_ddev() does not take a parameter anymore.
+ * Cleaned up comments.
+ * Revision 1.34 2008/02/27 10:03:02 martin
+ * Support TCR51USB and MSF51USB.
+ * Preliminary support for mapped memory access under Windows and Linux.
+ * Enabled PCPS_IRQ_1_SEC for USB within WIN32 targets
+ * in pcps_start_device().
+ * Fixed a bug in pcps_write() where the error code
+ * that was returned from a USB device was misinterpreted
+ * due to a signed/unsigned mismatch (added typecast).
+ * Removed obsolete function pcps_cleanup_all_devices().
+ * Code cleanup.
+ * Revision 1.33 2008/01/31 08:51:30Z martin
+ * Picked up changes from 1.31.2.1:
+ * Changed default definition of PCI_DWORD to uint32_t.
+ * Removed erraneous brace from debug code.
+ * Revision 1.32 2007/09/26 11:05:57Z martin
+ * Added support for USB in general and new USB device USB5131.
+ * Renamed ..._USE_PCIMGR symbols to ..._USE_PCI_PNP.
+ * Renamed ..._USE_PCIBIOS symbols to ..._USE_PCI_BIOS.
+ * Added new symbol _USE_ISA_PNP to exclude non-PNP stuff.
+ * from build if ISA devices are also handled by the PNP manager.
+ * Use new MBG_... codes defined in mbgerror.h.
+ * Unified timeout handling in low level functions by using an inline function.
+ * Renamed pcps_pnp_start_device() to pcps_start_device().
+ * Renamed pcps_setup_pci_dev() to pcps_setup_and_startpci_dev().
+ * Merged code from init_ddev_cfg() and finish_ddev_cfg() into pcps_start_device().
+ * Improved and unified handling of ISA devices.
+ * Removed calling register_pnp_devices() from pcps_detect_clocks(),
+ * this is now called directly.
+ * Added missing IRIG support to pcps_rsrc_register_device().
+ * Revision 1.31 2007/07/17 08:22:47Z martin
+ * Added support for TCR511PEX and GPS170PEX.
+ * Revision 1.30 2007/07/16 12:56:01Z martin
+ * Added support for PEX511.
+ * Rewrote common resource handling code in order to simplify
+ * OS specific code.
+ * Revision 1.29 2007/03/02 09:40:33Z martin
+ * Use generic port I/O macros.
+ * Pass PCPS_DDEV structure to the low level read functions.
+ * Use new _pcps_..._timeout_clk() macros.
+ * Added init code qualifier.
+ * Preliminary support for *BSD.
+ * Preliminary support for USB.
+ * Revision 1.28 2006/07/11 10:24:20 martin
+ * Use _fmemcpy() in pcps_generic_io() to support environments which
+ * require far data pointers.
+ * Revision 1.27 2006/07/07 09:41:15 martin
+ * Renamed pci_..() function calls to _mbg_pci_..() calls which are defined according to the
+ * OS requirements, in order to avoid naming conflicts.
+ * Revision 1.26 2006/06/19 15:28:52 martin
+ * Added support for TCR511PCI.
+ * Modified parameters required to detect ISA cards.
+ * The array of port addresses does no more require a 0 address
+ * as last value.
+ * Revision 1.25 2006/03/10 11:01:27 martin
+ * Added support for PCI511.
+ * Revision 1.24 2005/11/03 15:50:45Z martin
+ * Added support for GPS170PCI.
+ * Revision 1.23 2005/09/16 08:21:08Z martin
+ * Also flag PCI cards which have base_addr set to 0 as uninitialized.
+ * Revision 1.22 2005/06/02 10:32:07Z martin
+ * Changed more types to C99 fixed size types.
+ * New function pcps_generic_io().
+ * Revision 1.21 2004/12/13 14:19:38Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.20 2004/11/09 13:02:48Z martin
+ * Redefined fixed width data types using standard C99 types.
+ * Fixed warnings about lvalue casts.
+ * Revision 1.19 2004/10/14 15:01:24 martin
+ * Added support for TCR167PCI.
+ * Revision 1.18 2004/09/06 15:16:57Z martin
+ * Support a GPS_DATA interface where sizes are specified
+ * by 16 instead of the original 8 bit quantities, thus allowing
+ * to transfer data blocks which exceed 255 bytes.
+ * Conditionally skip assertions under Linux.
+ * Revision 1.17 2004/04/22 14:47:54 martin
+ * Fixed conversion of firmware rev. number.
+ * Revision 1.16 2004/04/07 09:45:04Z martin
+ * Support new feature PCPS_HAS_IRIG_TX for GPS169PCI.
+ * Revision 1.15 2003/12/22 16:15:21Z martin
+ * Support PCPS_HR_TIME for TCR510PCI.
+ * Revision 1.14 2003/07/30 07:28:23Z martin
+ * Moved prototype for register_pci_devices() outside to top of file.
+ * Revision 1.13 2003/07/08 15:11:55 martin
+ * Support PCI PNP interface under Linux.
+ * New function pcps_rsrc_release().
+ * Made some functions public.
+ * Renamed some public functions to start with pcps_...
+ * Revision 1.12 2003/06/19 10:08:43 MARTIN
+ * Renamed some functions to follow common naming conventions.
+ * Made a function's parameter pointer const.
+ * Changes due to renamed symbols in pcpsdev.h.
+ * Check devices for _pcps_has_ucap() support.
+ * Revision 1.11 2003/05/16 09:28:06 MARTIN
+ * Moved inclusion of some headers to pcpsdrvr.h.
+ * Revision 1.10 2003/04/09 16:35:57 martin
+ * Supports PCI510, GPS169PCI, and TCR510PCI,
+ * and new PCI_ASIC used by those devices.
+ * Revision 1.9 2003/03/20 11:42:37 martin
+ * Fixed syntax for QNX.
+ * Revision 1.8 2002/08/09 08:25:50 MARTIN
+ * Support feature PCPS_CAN_CLR_CAP_BUFF.
+ * Fixed a bug resulting in an unterminated string
+ * if SERNUM was being read.
+ * Revision 1.7 2002/02/26 09:31:57 MARTIN
+ * New function pcps_read_sernum().
+ * Revision 1.6 2002/02/19 09:46:26 MARTIN
+ * Use new header mbg_tgt.h to check the target environment.
+ * Removed function pcps_sn_str_from_ident(), use new
+ * function mbg_gps_ident_decode() from identdec.c now.
+ * If a PCI clock's interface is not properly configured don't
+ * enable the device and set the read function to the new
+ * dummy function pcps_read_null() to prevent driver from
+ * accessing random ports.
+ * Revision 1.5 2002/02/01 12:06:12 MARTIN
+ * Added support for GPS168PCI.
+ * Removed obsolete code.
+ * Revision 1.4 2001/11/30 09:52:48 martin
+ * Added support for event_time which, however, requires
+ * a custom GPS firmware.
+ * Revision 1.3 2001/09/18 06:59:18 MARTIN
+ * Account for new preprocessor symbols in the header file.
+ * Added some type casts to avoid compiler warnings under Win32.
+ * Added some debug messages to clock detection functions.
+ * Revision 1.2 2001/03/16 14:45:33 MARTIN
+ * New functions and definitions to support PNP drivers.
+ * Revision 1.1 2001/03/01 16:26:41 MARTIN
+ * Initial revision for the new library.
+ *
+ **************************************************************************/
+
+#define _PCPSDRVR
+ #include <pcpsdrvr.h>
+#undef _PCPSDRVR
+
+#include <parmpcps.h>
+#include <parmgps.h>
+#include <identdec.h>
+#include <mbgddmsg.h>
+#include <plxdefs.h>
+#include <pci_asic.h>
+#include <amccdefs.h>
+
+#if defined( MBG_TGT_WIN32_PNP )
+ #include <usbdrv.h>
+ #include <pcpsdefs.h>
+ #include <ntddk.h>
+ #include <stdio.h>
+#elif defined( MBG_TGT_WIN32 )
+ #include <pcps_ioc.h>
+ #include <stdio.h>
+#endif
+
+#if !defined( MBG_TGT_LINUX ) && !defined( MBG_TGT_BSD )
+ #include <assert.h>
+#endif
+
+#if defined( MBG_TGT_FREEBSD )
+ #include <sys/rman.h>
+ #include <sys/libkern.h>
+#endif
+
+#if _PCPS_USE_MCA
+ #include <mca.h>
+#endif
+
+#if _PCPS_USE_PCI
+ #include <pci.h>
+#endif
+
+#if _PCPS_USE_USB
+ #define MBGUSB_MIN_ENDPOINTS_REQUIRED 3
+#endif
+
+
+// time required for PTP270PEX to be ready after booting
+#define MAX_BOOT_TIME_PTP270PEX 27 // [s]
+
+
+#if !defined( DEBUG_IO )
+ #define DEBUG_IO ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_IO ) )
+#endif
+
+#if !defined( DEBUG_PORTS )
+ #define DEBUG_PORTS ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_PORTS ) )
+#endif
+
+#if !defined( DEBUG_SERNUM )
+ #define DEBUG_SERNUM ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_SERNUM ) )
+#endif
+
+extern const char pcps_driver_name[];
+
+
+// In some environments special far functions are are neither
+// required nor supported, so redefine calls to those functions
+// to appropriate standard function calls.
+#if defined( MBG_TGT_NETWARE ) || defined( MBG_TGT_WIN32 ) || \
+ defined( MBG_TGT_LINUX ) || defined( MBG_TGT_BSD ) || \
+ defined( MBG_TGT_QNX )
+ #define _fmemcpy( _d, _s, _n ) memcpy( _d, _s, _n )
+ #define _fstrlen( _s ) strlen( _s )
+ #define _fstrncmp( _s1, _s2, _n ) strncmp( (_s1), (_s2), (_n) )
+#elif defined( MBG_TGT_OS2 )
+ #define _fstrncmp( _s1, _s2, _n ) _fmemcmp( (_s1), (_s2), (_n) )
+#endif
+
+#if defined( MBG_TGT_OS2 )
+ // Watcom C Compiler options for the OS/2 device driver result in
+ // warnings if automatic stack addresses are passed to functions.
+ #define static_wc static
+ #define FMT_03X "%X"
+ #define FMT_08X "%X"
+#else
+ #define static_wc
+ #define FMT_03X "%03X"
+ #define FMT_08X "%08lX"
+#endif
+
+#if defined( MBG_TGT_LINUX )
+ typedef unsigned int PCI_DWORD;
+#else
+ typedef uint32_t PCI_DWORD;
+#endif
+
+
+#if defined( MBG_TGT_LINUX )
+
+ #define _pcps_irq_flags \
+ unsigned long irq_flags;
+
+ #define _pcps_disb_local_irq_save() \
+ local_irq_save( irq_flags )
+
+ #define _pcps_local_irq_restore() \
+ local_irq_restore( irq_flags )
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #define _pcps_irq_flags \
+ KIRQL old_irq_lvl;
+
+ #define _pcps_disb_local_irq_save() \
+ KeRaiseIrql( HIGH_LEVEL, &old_irq_lvl )
+
+ #define _pcps_local_irq_restore() \
+ KeLowerIrql( old_irq_lvl )
+
+#else
+
+ // Nothing to define here.
+
+#endif
+
+#if !defined( _pcps_irq_flags ) && \
+ !defined( _pcps_disb_local_irq_save ) && \
+ !defined( _pcps_local_irq_restore)
+ #define _pcps_irq_flags
+ #define _pcps_disb_local_irq_save();
+ #define _pcps_local_irq_restore();
+#endif
+
+
+#if defined( MBG_TGT_LINUX ) && defined( time_after )
+ #define _pcps_time_after( _curr, _tmo ) \
+ time_after( (unsigned long) _curr, (unsigned long) _tmo )
+#else
+ #define _pcps_time_after( _curr, _tmo ) ( _curr >= _tmo )
+#endif
+
+
+
+static /*HDR*/
+long mbg_delta_sys_time_ms( const MBG_SYS_TIME *t2, const MBG_SYS_TIME *t1 )
+{
+ #if defined( MBG_TGT_LINUX ) || defined( MBG_TGT_BSD )
+ long dt = ( t2->tv_sec - t1->tv_sec ) * 1000;
+ #if USE_TIMESPEC
+ dt += ( t2->tv_nsec - t1->tv_nsec ) / 1000000;
+ #else
+ dt += ( t2->tv_usec - t1->tv_usec ) / 1000;
+ #endif
+ return dt;
+ #elif defined( MBG_TGT_WIN32 )
+ return (long) ( ( t2->QuadPart - t1->QuadPart ) / HNS_PER_MS );
+ #else
+ return 0;
+ #endif
+
+} // mbg_delta_sys_time_ms
+
+
+
+static /*HDR*/
+void report_uptime( const MBG_SYS_UPTIME *p_uptime )
+{
+ #if defined( MBG_TGT_LINUX )
+ printk( KERN_INFO "%s: system uptime %llu jiffies -> %llu s, required %u s\n",
+ pcps_driver_name, (unsigned long long) ( get_jiffies_64() - INITIAL_JIFFIES ),
+ (unsigned long long) *p_uptime, MAX_BOOT_TIME_PTP270PEX );
+ #elif defined( MBG_TGT_BSD )
+ printf( "%s: system uptime %llu s, required %u s\n",
+ pcps_driver_name, (unsigned long long) *p_uptime, MAX_BOOT_TIME_PTP270PEX );
+ #elif defined( MBG_TGT_WIN32 )
+ WCHAR wcs_msg[120];
+
+ swprintf( wcs_msg, L"system uptime: %I64u s, required %u s",
+ (int64_t) *p_uptime, MAX_BOOT_TIME_PTP270PEX );
+ _evt_msg( GlbDriverObject, wcs_msg );
+ #endif
+
+} // report_uptime
+
+
+
+static /*HDR*/
+void check_uptime( void )
+{
+ #if !defined( MBG_TGT_DOS )
+ MBG_SYS_TIME t1;
+ MBG_SYS_TIME t2;
+ MBG_SYS_UPTIME uptime;
+ int delayed = 0;
+
+ mbg_get_sys_time( &t1 );
+
+ for (;;)
+ {
+ mbg_get_sys_uptime( &uptime );
+
+ #if !defined( DEBUG )
+ if ( !delayed )
+ #endif
+ report_uptime( &uptime );
+
+ if ( uptime == 0 )
+ break; // assume uptime not supported
+
+ if ( uptime >= MAX_BOOT_TIME_PTP270PEX )
+ break;
+
+ mbg_sleep_sec( 1 );
+ delayed = 1;
+ }
+
+ if ( delayed )
+ {
+ long dt;
+
+ mbg_get_sys_time( &t2 );
+
+ dt = mbg_delta_sys_time_ms( &t2, &t1 );
+
+ #if defined( MBG_TGT_LINUX )
+ printk( KERN_INFO "PTP270PEX startup delay: %li.%03li s\n",
+ dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 );
+ #elif defined( MBG_TGT_BSD )
+ printf( "PTP270PEX startup delay: %li.%03li s\n",
+ dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 );
+ #elif defined( MBG_TGT_WIN32 )
+ {
+ WCHAR wcs_msg[128];
+ swprintf( wcs_msg, L"PTP270PEX startup delay: %li.%03li s",
+ dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 );
+ _evt_msg( GlbDriverObject, wcs_msg );
+ }
+ #endif
+ }
+ #endif
+
+} // check_uptime
+
+
+
+static /*HDR*/
+int pcps_check_pex_irq_unsafe( PCPS_DDEV *pddev, uint16_t req_fw_ver,
+ uint8_t req_asic_ver_major, uint8_t req_asic_ver_minor )
+{
+ int rc = !_pcps_pex_irq_is_safe( _pcps_ddev_fw_rev_num( pddev ), req_fw_ver,
+ _pcps_ddev_asic_version( pddev ),
+ req_asic_ver_major, req_asic_ver_minor );
+
+ if ( rc )
+ {
+ pddev->irq_stat_info |= PCPS_IRQ_STAT_UNSAFE;
+
+ // Prevent the driver from writing IRQ ACK to the card even if IRQs
+ // should be unintentionally enabled.
+ pddev->irq_ack_port = 0;
+ pddev->irq_ack_mask = 0;
+ }
+
+ return rc;
+
+} // pcps_check_pex_irq_unsafe
+
+
+
+#if MBG_TGT_SUPP_MEM_ACC
+
+static __mbg_inline /*HDR*/
+int map_sys_virtual_address( PCPS_DDEV *pddev )
+{
+ pddev->mm_tstamp_addr = NULL; // unless configured below
+
+ #if defined ( MBG_TGT_WIN32 )
+ {
+ PHYSICAL_ADDRESS pAD;
+
+ pAD.QuadPart = pddev->rsrc_info.mem[0].start;
+ pddev->mm_addr = MmMapIoSpace( pAD, sizeof( *pddev->mm_addr ), MmNonCached );
+ }
+ #elif defined ( MBG_TGT_LINUX )
+
+ pddev->mm_addr = ioremap( ( (ulong) pddev->rsrc_info.mem[0].start ), sizeof( *pddev->mm_addr ) );
+
+ #elif defined ( MBG_TGT_FREEBSD )
+
+ pddev->mm_addr = rman_get_virtual( pddev->rsrc_info.mem[0].bsd.res );
+
+ #elif defined ( MBG_TGT_NETBSD )
+
+ pddev->mm_addr = bus_space_vaddr( pddev->rsrc_info.mem[0].bsd.bst, pddev->rsrc_info.mem[0].bsd.bsh );
+
+ #else // DOS, ...
+
+ pddev->mm_addr = (PCPS_MM_LAYOUT FAR *) pddev->rsrc_info.mem[0].start;
+
+ #endif // target specific code
+
+ if ( pddev->mm_addr == NULL )
+ return -1;
+
+ if ( _pcps_ddev_is_pci_mbgpex( pddev ) )
+ pddev->mm_tstamp_addr = &pddev->mm_addr->mbgpex.tstamp;
+ else
+ if ( _pcps_ddev_is_pci_pex8311( pddev ) )
+ pddev->mm_tstamp_addr = &pddev->mm_addr->pex8311.tstamp;
+
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "MM addr: base: 0x%p, tstamp: 0x%p, offs: 0x%02lX",
+ pddev->mm_addr, pddev->mm_tstamp_addr,
+ (ulong) pddev->mm_tstamp_addr - (ulong) pddev->mm_addr );
+
+ return 0;
+
+} // map_sys_virtual_address
+
+
+
+static __mbg_inline /*HDR*/
+void unmap_sys_virtual_address( PCPS_DDEV *pddev )
+{
+ if ( pddev->mm_addr )
+ {
+ #if defined ( MBG_TGT_WIN32 )
+ MmUnmapIoSpace( pddev->mm_addr, sizeof( *pddev->mm_addr ) );
+ #elif defined ( MBG_TGT_LINUX )
+ iounmap( pddev->mm_addr );
+ #else // DOS, ...
+ // nothing to do
+ #endif
+
+ pddev->mm_addr = NULL;
+ pddev->mm_tstamp_addr = NULL;
+ }
+
+} // unmap_sys_virtual_address
+
+#endif // MBG_TGT_SUPP_MEM_ACC
+
+
+
+#if defined( __GNUC__ )
+// Avoid "no previous prototype" with some gcc versions.
+__mbg_inline
+int pcps_wait_busy( PCPS_DDEV *pddev ) __attribute__((always_inline));
+#endif
+
+__mbg_inline /*HDR*/
+int pcps_wait_busy( PCPS_DDEV *pddev )
+{
+ if ( _pcps_ddev_status_busy( pddev ) )
+ {
+ #if defined( MBG_TGT_BSD )
+ struct timeval tv_start;
+
+ getmicrouptime( &tv_start );
+
+ while ( _pcps_ddev_status_busy( pddev ) )
+ {
+ struct timeval tv_now;
+ long long delta_ms;
+
+ getmicrouptime( &tv_now );
+ delta_ms = ( ( tv_now.tv_sec - tv_start.tv_sec ) * 1000 )
+ + ( ( tv_now.tv_usec - tv_start.tv_usec ) / 1000 );
+ if ( delta_ms > _pcps_ddev_timeout_clk( pddev ) )
+ return MBG_ERR_TIMEOUT;
+ }
+ #elif _PCPS_USE_CLOCK_TICK
+ clock_t timeout_val = clock() + _pcps_ddev_timeout_clk( pddev );
+
+ while ( _pcps_ddev_status_busy( pddev ) )
+ if ( _pcps_time_after( clock(), timeout_val ) )
+ return MBG_ERR_TIMEOUT;
+ #else
+ long cnt = _pcps_ddev_timeout_clk( pddev );
+
+ for ( ; _pcps_ddev_status_busy( pddev ); cnt-- )
+ if ( cnt == 0 )
+ return MBG_ERR_TIMEOUT;
+ #endif
+ }
+
+ return 0;
+
+} // pcps_wait_busy
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_read_null()
+ * pcps_read_std()
+ * pcps_read_amcc_s5933()
+ * pcps_read_amcc_s5920()
+ * pcps_read_asic()
+ * pcps_read_usb()
+ *
+ * Purpose: These functions are used for low level access
+ * to Meinberg plug-in radio clocks. The function
+ * to be used depends on the clock's bus type and
+ * interface chip.
+ *
+ * Input: pcfg pointer to the clock's configuration
+ * cmd the command code for the board
+ * count the number of bytes to be read
+ *
+ * Output: buffer the bytes that could be read
+ *
+ * Ret value: MBG_SUCCESS no error
+ * MBG_ERR_TIMEOUT board is busy for too long
+ *-------------------------------------------------------------*/
+
+// The dummy read function below is used if a clock is
+// not properly initialized, in order to avoid I/O access
+// on unspecified ports.
+
+static /*HDR*/ /* type: PCPS_READ_FNC */
+short pcps_read_null( PCPS_DDEV *pddev, uint8_t cmd,
+ uint8_t FAR *buffer, uint8_t count )
+{
+
+ return MBG_ERR_TIMEOUT;
+
+} // pcps_read_null
+
+
+
+// The function below must be used to access a clock with
+// standard ISA or micro channel bus.
+
+static /*HDR*/ /* type: PCPS_READ_FNC */
+short pcps_read_std( PCPS_DDEV *pddev, uint8_t cmd,
+ uint8_t FAR *buffer, uint8_t count )
+{
+ PCPS_IO_ADDR_MAPPED port = _pcps_ddev_io_base_mapped( pddev, 0 );
+ int i;
+ _pcps_irq_flags
+
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_std: cmd %02X", cmd );
+ #endif
+
+ _pcps_disb_local_irq_save();
+ mbg_get_pc_cycles( &pddev->acc_cycles );
+ // write the command byte
+ _mbg_outp8( pddev, 0, port, cmd );
+ _pcps_local_irq_restore();
+
+ // wait until BUSY flag goes low or timeout
+ if ( pcps_wait_busy( pddev ) < 0 )
+ return MBG_ERR_TIMEOUT;
+
+
+ // no timeout: read bytes from the board's FIFO
+ for ( i = 0; i < count; i++ )
+ {
+ *buffer++ = _mbg_inp8( pddev, 0, port );
+
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_read_std: %02X", buffer[i] );
+ #endif
+ }
+
+ return MBG_SUCCESS;
+
+} // pcps_read_std
+
+
+
+#if _PCPS_USE_PCI
+
+// The function below must be used to access a clock with
+// PCI bus and AMCC S5933 interface chip.
+
+static /*HDR*/ /* type: PCPS_READ_FNC */
+short pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd,
+ uint8_t FAR *buffer, uint8_t count )
+{
+ PCPS_IO_ADDR_MAPPED port = _pcps_ddev_io_base_mapped( pddev, 0 );
+ int i;
+ _pcps_irq_flags
+
+
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5933: cmd %02X", cmd );
+ #endif
+
+ // reset inbound mailbox and FIFO status
+ _mbg_outp8( pddev, 0, port + AMCC_OP_REG_MCSR + 3, 0x0C );
+
+ // set FIFO
+ _mbg_outp8( pddev, 0, port + AMCC_OP_REG_INTCSR + 3, 0x3C );
+
+ _pcps_disb_local_irq_save();
+ mbg_get_pc_cycles( &pddev->acc_cycles );
+ // write the command byte
+ _mbg_outp8( pddev, 0, port + AMCC_OP_REG_OMB1, cmd );
+ _pcps_local_irq_restore();
+
+ // wait until BUSY flag goes low or timeout
+ if ( pcps_wait_busy( pddev ) < 0 )
+ return MBG_ERR_TIMEOUT;
+
+
+ // no timeout: read bytes from the board's FIFO
+ for ( i = 0; i < count; i++ )
+ {
+ if ( _mbg_inp16_to_cpu( pddev, 0, port + AMCC_OP_REG_MCSR ) & 0x20 )
+ return MBG_ERR_FIFO;
+
+ buffer[i] = _mbg_inp8( pddev, 0, port + AMCC_OP_REG_FIFO + ( i % sizeof( uint32_t) ) );
+
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_read_amcc_s5933: %02X", buffer[i] );
+ #endif
+ }
+
+ return MBG_SUCCESS;
+
+} /* pcps_read_amcc_s5933 */
+
+#endif /* _PCPS_USE_PCI */
+
+
+
+#if _PCPS_USE_PCI
+
+// The function below must be used to access a clock with
+// PCI bus and AMCC S5920 interface chip.
+
+static /*HDR*/ /* type: PCPS_READ_FNC */
+short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd,
+ uint8_t FAR *buffer, uint8_t count )
+{
+ uint8_t FAR *p = buffer;
+ PCPS_IO_ADDR_MAPPED data_port = _pcps_ddev_io_base_mapped( pddev, 1 );
+ int i;
+ int dt_quot;
+ int dt_rem;
+ _pcps_irq_flags
+
+
+ #if DEBUG_IO
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5920: cmd %02X, port: %04lX, data_port: %04lX",
+ cmd, (ulong) _pcps_ddev_io_base_mapped( pddev, 0 ) + AMCC_OP_REG_OMB,
+ (ulong) data_port );
+ #endif
+
+ _pcps_disb_local_irq_save();
+ mbg_get_pc_cycles( &pddev->acc_cycles );
+ // write the command byte
+ _mbg_outp8( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + AMCC_OP_REG_OMB, cmd );
+ _pcps_local_irq_restore();
+
+ dt_quot = count / 4;
+ dt_rem = count % 4;
+
+ // wait until BUSY flag goes low or timeout
+ if ( pcps_wait_busy( pddev ) < 0 )
+ return MBG_ERR_TIMEOUT;
+
+
+ if ( count )
+ {
+ // do this only if we must read data
+
+ uint32_t ul;
+
+ // first read full 32 bit words
+ for ( i = 0; i < dt_quot; i++ )
+ {
+ ul = _mbg_inp32_to_cpu( pddev, 1, data_port );
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5920: %08X", ul );
+ #endif
+ _pcps_put_unaligned( ul, (uint32_t FAR *) p );
+ p += sizeof( ul );
+ }
+
+ // then read the remaining bytes, if required
+ if ( dt_rem )
+ {
+ ul = _mbg_inp32_to_cpu( pddev, 1, data_port );
+
+ for ( i = 0; i < dt_rem; i++ )
+ {
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5920: %02X", BYTE_OF( ul, i ) );
+ #endif
+
+ *p++ = BYTE_OF( ul, i );
+ }
+ }
+ }
+ else
+ _mbg_inp32( pddev, 1, data_port ); // do a dummy read
+
+ return MBG_SUCCESS;
+
+} // pcps_read_amcc_s5920
+
+#endif /* _PCPS_USE_PCI */
+
+
+
+#if _PCPS_USE_PCI
+
+// The function below must be used to access a clock with
+// PCI bus and Meinberg PCI interface ASIC.
+
+static /*HDR*/ /* type: PCPS_READ_FNC */
+short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd,
+ uint8_t FAR *buffer, uint8_t count )
+{
+ uint8_t FAR *p = buffer;
+ PCPS_IO_ADDR_MAPPED data_port;
+ PCI_ASIC_REG ar;
+ int i;
+ int dt_quot;
+ int dt_rem;
+ _pcps_irq_flags
+
+
+ #if DEBUG_IO
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "pcps_read_asic: cmd: 0x%02X (0x%08X), cnt: %u",
+ cmd, _cpu_to_mbg32( cmd ), count );
+ #endif
+
+ _pcps_disb_local_irq_save();
+ mbg_get_pc_cycles( &pddev->acc_cycles );
+ // write the command byte
+ _mbg_outp32( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 )
+ + offsetof( PCI_ASIC, pci_data ), cmd );
+ _pcps_local_irq_restore();
+
+ data_port = _pcps_ddev_io_base_mapped( pddev, 0 )
+ + offsetof( PCI_ASIC, addon_data );
+ dt_quot = count / 4;
+ dt_rem = count % 4;
+
+ // wait until BUSY flag goes low or timeout
+ if ( pcps_wait_busy( pddev ) < 0 )
+ return MBG_ERR_TIMEOUT;
+
+
+ // no timeout: read bytes from the board's FIFO
+
+ // first read full 32 bit words
+ for ( i = 0; i < dt_quot; i++ )
+ {
+ ar.ul = _mbg_inp32_to_cpu( pddev, 0, data_port );
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_asic: %08X", ar.ul );
+ #endif
+ _pcps_put_unaligned( ar.ul, (uint32_t FAR *) p );
+ p += sizeof( ar.ul );
+ data_port += sizeof( ar.ul );
+ }
+
+ // then read the remaining bytes, if required
+ if ( dt_rem )
+ {
+ ar.ul = _mbg_inp32_to_cpu( pddev, 0, data_port );
+
+ for ( i = 0; i < dt_rem; i++ )
+ {
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_asic: %02X", ar.b[i] );
+ #endif
+
+ *p++ = ar.b[i];
+ }
+ }
+
+ return MBG_SUCCESS;
+
+} // pcps_read_asic
+
+#endif /* _PCPS_USE_PCI */
+
+
+
+#if _PCPS_USE_USB
+
+// The function below must be used to access a clock
+// connected via USB bus.
+
+static /*HDR*/ /* type: PCPS_READ_FNC */
+short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd,
+ uint8_t FAR *buffer, uint8_t count )
+{
+ int actual_count = 0;
+ short rc;
+
+ mbg_get_pc_cycles( &pddev->acc_cycles );
+
+ rc = _pcps_usb_write_var( pddev, &cmd );
+
+ if ( ( rc == MBG_SUCCESS ) && ( count && buffer ) )
+ {
+ #if defined( MBG_TGT_WIN32_PNP )
+ int temp_fn1 = frame_number_1;
+ int temp_fn2 = frame_number_2;
+ LARGE_INTEGER UsbPreCount = Count1;
+ LARGE_INTEGER UsbPostCount = Count2;
+ #endif
+
+ rc = _pcps_usb_read( pddev, buffer, count );
+
+ #if defined( MBG_TGT_WIN32_PNP )
+ if ( cmd == PCPS_GIVE_HR_TIME && rc == PCPS_SUCCESS )
+ {
+ ULONGLONG usb_latency_cycles;
+ ULONGLONG cycles_diff;
+ ULONGLONG time_diff;
+ ULONGLONG frame_length_cycles;
+ int FrameNumberDiff;
+
+ if ( pddev->usb_20_mode )
+ {
+ // USB 2.0 microframe timing.
+ // Just add an offset to compensate constant latency.
+ // This value has been determined experimentally on different hardware platforms
+ usb_latency_cycles = ( (ULONGLONG) PerfFreq.QuadPart ) / 20000UL; // represents 50 us
+ }
+ else
+ {
+ // USB 1.1 mode with millisecond timing.
+ // Compensate latency to millisecond frame boundaries.
+
+ if ( (temp_fn2 - temp_fn1) < 0 )
+ FrameNumberDiff = 2;
+ else
+ FrameNumberDiff = temp_fn2 - temp_fn1;
+
+ cycles_diff = (ULONGLONG) ( UsbPostCount.QuadPart - UsbPreCount.QuadPart );
+ frame_length_cycles = (ULONGLONG) ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL;
+
+ if ( ( temp_fn1 == 0 ) && ( temp_fn2 == 0 ) )
+ {
+ if ( cycles_diff > frame_length_cycles )
+ usb_latency_cycles = cycles_diff - frame_length_cycles;
+ else
+ usb_latency_cycles = frame_length_cycles - cycles_diff;
+ }
+ else
+ usb_latency_cycles = cycles_diff - ( ( FrameNumberDiff - 1 ) * frame_length_cycles );
+
+ #if DBG
+ swprintf( pddev->wcs_msg, L"FD %d CD %I64u l %I64u fl %I64u", FrameNumberDiff, cycles_diff, usb_latency_cycles, frame_length_cycles );
+ _dbg_evt_msg( GlbDriverObject, pddev->wcs_msg );
+ #endif
+ }
+
+ pddev->acc_cycles += usb_latency_cycles;
+ }
+ #endif
+ }
+
+ return rc;
+
+} // pcps_read_usb
+
+#endif
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_write()
+ *
+ * Purpose: Write data to the radio clock.
+ *
+ * Input: pddev pointer to the device information
+ * cmd the address of buffer holding the
+ * date/time/status information
+ * read_fnc function to access the board
+ *
+ * Output: --
+ *
+ * Ret value: MBG_SUCCESS no error
+ * MBG_ERR_TIMEOUT board is busy for too long
+ * MBG_ERR_NBYTES the number of parameter bytes
+ * did not match the number of
+ * data bytes expected
+ * MBG_ERR_STIME the date, time or status
+ * has been invalid
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_write( PCPS_DDEV *pddev, uint8_t cmd,
+ const void FAR *buffer, uint8_t count )
+{
+ short rc;
+
+#if _PCPS_USE_USB
+ if ( _pcps_ddev_is_usb( pddev ) )
+ {
+ int actual_count = 0; // required by macro
+ int n = sizeof( cmd ) + count;
+ uint8_t *p = _pcps_kmalloc( n );
+
+ if ( p == NULL )
+ return MBG_ERR_NO_MEM;
+
+ p[0] = cmd;
+ memcpy( &p[1], buffer, count );
+
+ rc = _pcps_usb_write( pddev, p, n );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ rc = _pcps_usb_read( pddev, p, 1 );
+
+ if ( rc == MBG_SUCCESS )
+ rc = (int8_t) p[0]; // return the rc from the board
+ }
+
+ _pcps_kfree( p, n );
+ }
+ else
+#endif // _PCPS_USE_USB
+ {
+ const uint8_t FAR *p = (const uint8_t FAR *) buffer;
+ int i;
+ uint8_t bytes_expected;
+ int8_t write_rc;
+
+ // Write the command and read one byte which will contain
+ // the number of data bytes that must follow.
+ rc = _pcps_read_var( pddev, cmd, bytes_expected );
+
+ #if DEBUG_IO
+ _mbgddmsg_4( MBG_DBG_DETAIL, "pcps_write: cmd %02X, %u bytes, expects %u, rc: %i",
+ cmd, count, bytes_expected, rc );
+ #endif
+
+ if ( rc < 0 )
+ goto done;
+
+
+ // Check if the number of data bytes to be written is correct.
+ if ( bytes_expected != count )
+ {
+ rc = MBG_ERR_NBYTES;
+ goto done;
+ }
+
+
+ // Write all bytes but the last one without reading anything.
+ bytes_expected--;
+
+ for ( i = 0; i < bytes_expected; i++ )
+ {
+ #if DEBUG_IO
+ _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_write: byte %i: 0x%02X", i, *p );
+ #endif
+
+ rc = _pcps_write_byte( pddev, *p++ );
+
+ if ( rc < 0 )
+ goto done;
+ }
+
+ // Write the last byte and read the completion code.
+ #if DEBUG_IO
+ _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_write: last byte %i: 0x%02X", i, *p );
+ #endif
+
+ rc = _pcps_read_var( pddev, *p++, write_rc );
+
+ // If an error code has been returned by the I/O function,
+ // return that code, otherwise return the completion code
+ // read from the board.
+ if ( !( rc < 0 ) )
+ rc = write_rc;
+ }
+
+done:
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_write: return %i", rc );
+ #endif
+
+ return rc;
+
+} // pcps_write
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_generic_io()
+ *
+ * Purpose: Write data to the radio clock.
+ *
+ * Input: pddev pointer to the device information
+ * cmd the address of buffer holding the
+ * date/time/status information
+ * read_fnc function to access the board
+ *
+ * Output: --
+ *
+ * Ret value: MBG_SUCCESS no error
+ * MBG_ERR_TIMEOUT board is busy for too long
+ * MBG_ERR_NBYTES the number of parameter bytes
+ * did not match the number of
+ * data bytes expected
+ * MBG_ERR_STIME the date, time or status
+ * has been invalid
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type,
+ const void FAR *in_buff, uint8_t in_cnt,
+ void FAR *out_buff, uint8_t out_cnt )
+{
+ const uint8_t FAR *p;
+ int i;
+ short rc;
+ uint8_t tmp_byte;
+ int8_t data_read[PCPS_FIFO_SIZE];
+ uint8_t bytes_to_read;
+
+ // Write the command and read one byte which will contain
+ // the number of data bytes that must follow.
+ rc = _pcps_read_var( pddev, PCPS_GENERIC_IO, tmp_byte );
+
+ if ( rc < 0 )
+ return rc;
+
+
+ // Check if the number of data bytes to be written is correct.
+ if ( tmp_byte != 3 )
+ return MBG_ERR_NBYTES;
+
+
+ // Write the 3 bytes which are expected:
+ rc = _pcps_write_byte( pddev, type );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+
+ rc = _pcps_write_byte( pddev, in_cnt );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+
+ if ( in_cnt == 0 )
+ tmp_byte = out_cnt;
+ else
+ {
+ rc = _pcps_write_byte( pddev, out_cnt );
+
+ if ( rc != MBG_SUCCESS )
+ goto done;
+
+
+ // Write the input parameters
+ p = (const uint8_t FAR *) in_buff;
+ tmp_byte = in_cnt - 1;
+
+ for ( i = 0; i < tmp_byte; i++ )
+ {
+ rc = _pcps_write_byte( pddev, *p++ );
+
+ if ( rc < 0 )
+ goto done;
+ }
+
+ tmp_byte = *p;
+ }
+
+
+ bytes_to_read = 2 + out_cnt;
+
+ if ( bytes_to_read > sizeof( data_read ) )
+ bytes_to_read = sizeof( data_read );
+
+
+ // Write the last byte and read the completion code.
+ rc = _pcps_read( pddev, tmp_byte, data_read, bytes_to_read );
+
+ if ( out_cnt ) //##++ should do some more plausibility checks
+ if ( rc == MBG_SUCCESS )
+ {
+ _fmemcpy( out_buff, &data_read[2], out_cnt );
+ }
+
+done:
+ // If an error code has been returned by the I/O function,
+ // return that code, otherwise return the completion code
+ // read from the board.
+ return ( rc < 0 ) ? rc : data_read[0];
+
+} // pcps_generic_io
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_read_gps_block()
+ *
+ * Purpose: Get a block of data from GPS clock device.
+ * This is a local function which is called
+ * by pcps_read_gps().
+ *
+ * Input: pddev pointer to the device information
+ * data_type the code assigned to the data type
+ * buffer_size the size of the buffer
+ * block_num the number of the block to read
+ * block_size the size of the block to read
+ *
+ * Output: buffer filled with data
+ *
+ * Ret value: MBG_SUCCESS
+ * MBG_ERR_TIMEOUT
+ * MBG_ERR_NBYTES
+ *-------------------------------------------------------------*/
+
+static /*HDR*/
+short pcps_read_gps_block( PCPS_DDEV *pddev,
+ uint8_t data_type,
+ void FAR *buffer,
+ uint16_t buffer_size,
+ uint8_t block_num,
+ uint8_t block_size )
+{
+ short rc;
+ uint16_t n_bytes;
+ uint8_t size_n_bytes;
+ uint8_t uc;
+
+
+ /* Determine which interface buffer size is supported
+ and use the appropriate size specification */
+ if ( _pcps_ddev_has_gps_data_16( pddev ) )
+ size_n_bytes = 2;
+ else
+ {
+ if ( buffer_size > 255 )
+ return MBG_ERR_NBYTES; // Error ...
+
+ size_n_bytes = 1;
+ }
+
+ #if DEBUG_IO
+ _mbgddmsg_4( MBG_DBG_DETAIL,
+ "pcps_read_gps_block: cmd 0x%02X, block %u (%u), size_n_bytes = %u",
+ data_type, block_num, block_size, size_n_bytes );
+ #endif
+
+ // Write the command, expect to read one byte.
+ rc = _pcps_read_var( pddev, PCPS_READ_GPS_DATA, uc );
+
+ if ( rc != MBG_SUCCESS ) // Error ...
+ return rc;
+
+ if ( uc != 1 ) // The board doesn't expect exactly one more byte
+ {
+ if ( uc == 0 )
+ {
+ // The board can't respond now. This may occur if a
+ // GPS receiver is still initializing after power-up.
+ #if DEBUG_IO
+ _mbgddmsg_0( MBG_DBG_DETAIL, "pcps_read_gps_block: board not yet initialized" );
+ #endif
+
+ return MBG_ERR_NOT_READY;
+ }
+ else
+ {
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_read_gps_block: board expects %u bytes rather than 1", uc );
+ #endif
+
+ return MBG_ERR_NBYTES; // Error ...
+ }
+ }
+
+ // Write the code corresponding to the type of data we
+ // want to read, expect to read the expected size.
+ n_bytes = 0;
+ rc = _pcps_read( pddev, data_type, &n_bytes, size_n_bytes );
+
+ if ( rc != MBG_SUCCESS ) // Error ...
+ return rc;
+
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ // Swap n_bytes regardless of whether we have actuall read 1 or 2 bytes.
+ // If we have read only 1 byte then the other one is 0.
+ n_bytes = _mbg16_to_cpu( n_bytes );
+ #endif
+
+ #if DEBUG_IO
+ _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_read_gps_block: board expects data size %u, buffer size %u",
+ n_bytes, buffer_size );
+ #endif
+
+ if ( n_bytes == 0 )
+ return MBG_ERR_INV_TYPE;
+
+ if ( n_bytes != buffer_size ) // Size of data structure does not match.
+ return MBG_ERR_NBYTES;
+
+
+ // Write the block number and read n bytes of data.
+ rc = _pcps_read( pddev, block_num, buffer, block_size );
+
+ return rc;
+
+} // pcps_read_gps_block
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_read_gps()
+ *
+ * Purpose: Get a data structure from a GPS clock.
+ *
+ * Input: pddev pointer to the device information
+ * data_type the code assigned to the data type
+ * buffer_size the size of the buffer
+ *
+ * Output: buffer filled with data
+ *
+ * Ret value: MBG_SUCCESS
+ * MBG_ERR_TIMEOUT
+ * MBG_ERR_NBYTES
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_read_gps( PCPS_DDEV *pddev,
+ uint8_t data_type,
+ void FAR *buffer,
+ uint16_t buffer_size )
+{
+ uint8_t FAR *p = (uint8_t FAR *) buffer;
+ short rc = 0;
+ int dt_quot;
+ int dt_rem;
+ int block_num;
+
+
+ #if DEBUG_IO
+ _mbgddmsg_3( MBG_DBG_DETAIL, "Going to read GPS data, type: %02X, addr: %p, size: %u",
+ data_type, buffer, buffer_size );
+ #endif
+
+ // Split buffer size to a number of blocks of PCPS_FIFO_SIZE
+ // and a number of remaining bytes (less than PCPS_FIFO_SIZE).
+ dt_quot = buffer_size / PCPS_FIFO_SIZE;
+ dt_rem = buffer_size % PCPS_FIFO_SIZE;
+
+ // Read dt_quot full blocks of data.
+ for ( block_num = 0; block_num < dt_quot; block_num++ )
+ {
+ rc = pcps_read_gps_block( pddev, data_type, p, buffer_size,
+ (uint8_t) block_num, PCPS_FIFO_SIZE );
+
+ if ( rc != MBG_SUCCESS ) // Error ...
+ goto done;
+
+ // Move the destination pointer to the next free byte.
+ p += PCPS_FIFO_SIZE;
+ }
+
+
+ // Read dt_rem additional bytes of data.
+ if ( dt_rem )
+ rc = pcps_read_gps_block( pddev, data_type, p, buffer_size,
+ (uint8_t) block_num, (uint8_t) dt_rem );
+
+done:
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "Done reading GPS data, rc: %i", rc );
+ #endif
+
+ return rc;
+
+} // pcps_read_gps
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_write_gps()
+ *
+ * Purpose: Write a data structure to a GPS clock.
+ *
+ * Input: pddev pointer to the device information
+ * data_type the code assigned to the data type
+ * buffer the data to write
+ * buffer_size the size of the buffer
+ * read_fnc function to access the board
+ *
+ * Output: --
+ *
+ * Ret value: MBG_SUCCESS
+ * MBG_ERR_TIMEOUT
+ * MBG_ERR_NBYTES
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_write_gps( PCPS_DDEV *pddev,
+ uint8_t data_type,
+ const void FAR *buffer,
+ uint16_t buffer_size )
+{
+ const uint8_t FAR *p = (const uint8_t FAR *) buffer;
+ short rc;
+ short i;
+ uint16_t n_bytes;
+ uint8_t size_n_bytes;
+ uint8_t uc;
+
+
+ /* Determine which interface buffer size is supported
+ and use the appropriate size specification */
+ if ( _pcps_ddev_has_gps_data_16( pddev ) )
+ size_n_bytes = 2;
+ else
+ {
+ if ( buffer_size > 255 )
+ return MBG_ERR_NBYTES; // Error ...
+
+ size_n_bytes = 1;
+ }
+
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_write_gps: size_n_bytes = %u", size_n_bytes );
+ #endif
+
+ // Write the command, expect to read one byte.
+ rc = _pcps_read_var( pddev, PCPS_WRITE_GPS_DATA, uc );
+
+ if ( rc != MBG_SUCCESS ) // Error ...
+ return rc;
+
+ if ( uc != 1 ) // The board doesn't expect exactly one more byte
+ {
+ if ( uc == 0 )
+ {
+ // The board can't respond now. This may occur if a
+ // GPS receiver is still initializing after power-up.
+ #if DEBUG_IO
+ _mbgddmsg_0( MBG_DBG_DETAIL, "pcps_write_gps: board not yet initialized" );
+ #endif
+
+ return MBG_ERR_NOT_READY;
+ }
+ else
+ {
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_write_gps: board expects %u bytes rather than 1", uc );
+ #endif
+
+ return MBG_ERR_NBYTES; // Error ...
+ }
+ }
+
+ // Write the code corresponding to the type of data we
+ // want to write, expect to read the expected size.
+ n_bytes = 0;
+ rc = _pcps_read( pddev, data_type, &n_bytes, size_n_bytes );
+
+ if ( rc != MBG_SUCCESS ) // Error ...
+ return rc;
+
+ #if defined( MBG_ARCH_BIG_ENDIAN )
+ // Swap n_bytes regardless of whether we have actuall read 1 or 2 bytes.
+ // If we have read only 1 byte then the other one is 0.
+ n_bytes = _mbg16_to_cpu( n_bytes );
+ #endif
+
+ #if DEBUG_IO
+ _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_write_gps: board expects data size %u, buffer size %u",
+ n_bytes, buffer_size );
+ #endif
+
+ if ( n_bytes != buffer_size ) // The board doesn't expect the number
+ return MBG_ERR_NBYTES; // of bytes we were going to write.
+
+
+ // Write all bytes but the last one without reading.
+ buffer_size--;
+
+ for ( i = 0; i < buffer_size; i++ )
+ {
+ rc = _pcps_write_byte( pddev, *p++ );
+
+ if ( rc != MBG_SUCCESS ) // Error ...
+ return rc;
+ }
+
+
+ // Write the last byte and read the completion code.
+ rc = _pcps_read_var( pddev, *p, n_bytes );
+
+ // If an error code has been returned by read_fnc, return that
+ // code, otherwise return the completion code read from the board.
+ return rc ? rc : n_bytes;
+
+} // pcps_write_gps
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_get_fw_id()
+ *
+ * Purpose: This function tries to read the firmware ID
+ * from the board. It should be used to check
+ * if the board is properly installed and can
+ * be accessed without problems.
+ *
+ * Input: pddev pointer to the device information
+ *
+ * Output: fw_id buffer filled with ASCIIZ string
+ *
+ * Ret value: MBG_SUCCESS no error
+ * MBG_ERR_TIMEOUT the board is busy for too long
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_get_fw_id( PCPS_DDEV *pddev, PCPS_ID_STR FAR fw_id )
+{
+ short rc;
+
+
+ // read first part of the firmware ID
+ rc = _pcps_read( pddev, PCPS_GIVE_FW_ID_1, &fw_id[0], PCPS_FIFO_SIZE );
+
+ if ( rc != MBG_SUCCESS )
+ return rc; // may be timeout
+
+
+ // read second part of the firmware ID
+ rc = _pcps_read( pddev, PCPS_GIVE_FW_ID_2, &fw_id[PCPS_FIFO_SIZE], PCPS_FIFO_SIZE );
+
+ if ( rc != MBG_SUCCESS )
+ return rc; // may be timeout
+
+
+ // terminate the string with 0
+
+ fw_id[PCPS_ID_SIZE - 1] = 0;
+
+
+ return MBG_SUCCESS;
+
+} // pcps_get_fw_id
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_check_id()
+ *
+ * Purpose: Check an ASCIIZ string for a valid signature.
+ *
+ * Input: pddev pointer to the device information
+ * ref the reference signature
+ *
+ * Output: --
+ *
+ * Ret value: MBG_SUCCESS no error
+ * MBG_ERR_FW_ID the firmware ID is not valid
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_check_id( PCPS_DDEV *pddev, const char FAR *ref )
+{
+ // check if the first characters of the string match the reference
+
+ if ( ref )
+ if ( _fstrncmp( _pcps_ddev_fw_id( pddev ), ref, _fstrlen( ref ) ) )
+ return MBG_ERR_FW_ID;
+
+ return MBG_SUCCESS;
+
+} // pcps_check_id
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_get_rev_num()
+ *
+ * Purpose: Get a version number from an ID string.
+ *
+ * Input: idstr the ID string
+ *
+ * Output: --
+ *
+ * Ret value: on success: the version number in hex
+ * (e.g. 0x0270 for version 2.7)
+ * on error: 0
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+short pcps_get_rev_num( char FAR *idstr )
+{
+ int i;
+ int len = _fstrlen( idstr ) - 2;
+ char c;
+
+ uchar rev_num_hi;
+ uchar rev_num_lo;
+
+ for ( i = 0; i < len; i++ )
+ {
+ if ( idstr[i + 1] == '.' )
+ {
+ rev_num_hi = idstr[i] & 0x0F;
+ rev_num_lo = ( idstr[i + 2] & 0x0F ) << 4;
+
+ c = idstr[i + 3];
+
+ if ( c >= '0' && c <= '9' )
+ rev_num_lo |= c & 0x0F;
+
+ return ( rev_num_hi << 8 ) | rev_num_lo;
+ }
+ }
+
+ return 0;
+
+} // pcps_get_rev_num
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_read_sernum()
+ *
+ * Purpose: This function tries to read the clock's S/N
+ * from the board, if supported by the clock.
+ *
+ * Input: pddev pointer to the device information
+ *
+ * Output: pddev sernum field filled with ASCIIZ
+ *
+ * Ret value: MBG_SUCCESS no error
+ * other error
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+int pcps_read_sernum( PCPS_DDEV *pddev )
+{
+ char *cp;
+ int i;
+ int rc = MBG_SUCCESS;
+
+
+ memset( pddev->dev.cfg.sernum, 0, sizeof( pddev->dev.cfg.sernum ) );
+
+ // There are different ways to read the clock's S/N.
+ // Check which way is supported by the clock, and
+ // read the S/N,
+
+
+ // The S/N is part of the RECEIVER_INFO structure. If this
+ // structure is supported by the device then it should have
+ // already been set up, so we can simply copy the serial number.
+ if ( _pcps_ddev_has_receiver_info( pddev ) )
+ {
+ #if DEBUG_SERNUM
+ _mbgddmsg_0( MBG_DBG_DETAIL, "copying S/N from receiver info" );
+ #endif
+
+ strncpy( pddev->dev.cfg.sernum, pddev->ri.sernum,
+ sizeof( pddev->dev.cfg.sernum ) );
+ goto check;
+ }
+
+
+ // Read directly. This is supported by newer DCF77 clocks.
+ if ( _pcps_ddev_has_sernum( pddev ) )
+ {
+ #if DEBUG_SERNUM
+ _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N via PCPS_GIVE_SERNUM cmd" );
+ #endif
+
+ rc = _pcps_read( pddev, PCPS_GIVE_SERNUM, pddev->dev.cfg.sernum, PCPS_FIFO_SIZE );
+
+ if ( rc != MBG_SUCCESS )
+ {
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read SERNUM %X: rc = %i",
+ _pcps_ddev_dev_id( pddev ), rc );
+ goto fail;
+ }
+
+ goto check;
+ }
+
+
+ // Older GPS clocks store the S/N in an IDENT structure
+ // which must be decoded to get the S/N.
+ if ( _pcps_ddev_has_ident( pddev ) )
+ {
+ static_wc IDENT ident = { { 0 } };
+
+ #if DEBUG_SERNUM
+ _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N from ident" );
+ #endif
+
+ rc = _pcps_read_gps_var( pddev, PC_GPS_IDENT, ident );
+
+ #if !defined( MBG_TGT_LINUX ) && !defined( MBG_TGT_BSD )
+ assert( sizeof( ident ) < sizeof( pddev->dev.cfg.sernum ) );
+ #endif
+
+ if ( rc != MBG_SUCCESS )
+ {
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read GPS ident %X: rc = %i",
+ _pcps_ddev_dev_id( pddev ), rc );
+ goto fail;
+ }
+
+ // The ident union must never be swapped due to endianess since we are
+ // using it only as an array of characters.
+
+ #if DEBUG_SERNUM
+ for ( i = 0; i < sizeof( ident ); i += 4 )
+ _mbgddmsg_5( MBG_DBG_DETAIL, "ident[%02i]: %02X %02X %02X %02X",
+ i, ident.c[i], ident.c[i+1], ident.c[i+2], ident.c[i+3] );
+ #endif
+
+ mbg_gps_ident_decode( _pcps_ddev_sernum( pddev ), &ident );
+ goto check;
+ }
+
+ // The clock doesn't support a S/N.
+ // Assume the rc is still set to MBG_SUCCESS.
+ strcpy( _pcps_ddev_sernum( pddev ), "N/A" );
+ goto done;
+
+
+check:
+ // Remove unprintable characters.
+ for ( i = 0, cp = pddev->dev.cfg.sernum;
+ i < sizeof( pddev->dev.cfg.sernum ); i++, cp++ )
+ if ( ( *cp < 0x20 ) || ( *cp >= 0x7F ) )
+ {
+ #if DEBUG_SERNUM
+ *cp = '#';
+ #else
+ *cp = 0;
+ #endif
+ }
+
+#if DEBUG_SERNUM
+
+fail:
+ goto done;
+
+#else
+ // Remove trailing spaces which may unfortunately
+ // be returned by some devices.
+ for ( i = strlen( pddev->dev.cfg.sernum ); ; )
+ {
+ if ( i == 0 )
+ break;
+
+ --i;
+ cp = &pddev->dev.cfg.sernum[i];
+ if ( *cp > ' ' ) // not a trailing space, done
+ break;
+
+ *cp = 0;
+ }
+
+ if ( strlen( pddev->dev.cfg.sernum ) )
+ goto done;
+
+
+fail:
+ // No valid serial number has been found, though the device
+ // should have one. In order to distinguish from devices which
+ // don't even support a serial number we return a number of '?'
+ // rather than "N/A".
+ memset( pddev->dev.cfg.sernum, '?', 8 );
+ pddev->dev.cfg.sernum[8] = 0;
+#endif
+
+done:
+ // Make sure the S/N is terminated by 0.
+ pddev->dev.cfg.sernum[sizeof( pddev->dev.cfg.sernum ) - 1] = 0;
+
+ return rc;
+
+} // pcps_read_sernum
+
+
+
+#if _PCPS_USE_RSRCMGR
+
+/*HDR*/
+int pcps_rsrc_claim( PCPS_DDEV *pddev )
+{
+ ushort decode_width;
+ int i;
+
+ if ( _pcps_ddev_is_pci( pddev ) )
+ decode_width = PCPS_DECODE_WIDTH_PCI;
+ else
+ if ( _pcps_ddev_is_mca( pddev ) )
+ decode_width = PCPS_DECODE_WIDTH_MCA;
+ else
+ decode_width = PCPS_DECODE_WIDTH_ISA;
+
+ for ( i = 0; i < pddev->rsrc_info.num_rsrc_io; i++ )
+ {
+ PCPS_IO_RSRC *p = &_pcps_ddev_io_rsrc( pddev, i );
+ ushort rc;
+
+ rc = _rsrc_alloc_ports( &pddev->rsrc, p->base_raw, p->num, decode_width ); //##++
+
+ // If the resource manager was unable to alloc the resources
+ // then the selected range of ports is probably in use
+ // by another hardware device and/or driver
+ if ( rc )
+ {
+ _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_RSRC );
+ return MBG_ERR_CLAIM_RSRC;
+ }
+ }
+
+ return 0;
+
+} // pcps_rsrc_claim
+
+
+
+/*HDR*/
+void pcps_rsrc_release( PCPS_DDEV *pddev )
+{
+ int i;
+
+ for ( i = 0; i < N_PCPS_PORT_RSRC; i++ )
+ {
+ PCPS_PORT_RSRC *p = &_pcps_ddev_port_rsrc( pddev, i );
+
+ if ( _pcps_port_rsrc_unused( p ) )
+ continue;
+
+ // clean up if clock not found
+ _rsrc_dealloc_ports( &pddev->rsrc.hResource[i], p->base, p->num );
+ }
+
+} // pcps_rsrc_release
+
+
+
+#if defined( MBG_TGT_OS2 )
+
+static /*HDR*/
+void pcps_rsrc_register_device( PCPS_DDEV *pddev )
+{
+ #define RSRC_BASE_NAME "RADIOCLK_# Meinberg Radio Clock "
+ static const char rsrc_type_dcf77[] = RSRC_BASE_NAME "(DCF77)";
+ static const char rsrc_type_gps[] = RSRC_BASE_NAME "(GPS)";
+ static const char rsrc_type_irig[] = RSRC_BASE_NAME "(IRIG)";
+
+ uchar bus_type;
+ ushort rc;
+ const char *cp;
+
+ #if _PCPS_USE_USB
+ #error USB not supported for this target environment!
+ #endif
+
+ if ( _pcps_ddev_is_pci( pddev ) )
+ bus_type = RSRC_BUS_PCI;
+ else
+ if ( _pcps_ddev_is_mca( pddev ) )
+ bus_type = RSRC_BUS_MCA;
+ else
+ bus_type = RSRC_BUS_ISA;
+
+ if ( _pcps_ddev_is_irig_rx( pddev ) )
+ cp = rsrc_type_irig;
+ else
+ if ( _pcps_ddev_is_gps( pddev ) )
+ cp = rsrc_type_gps;
+ else
+ cp = rsrc_type_dcf77;
+
+ rc = rsrc_register_device( &pddev->hDev, &pddev->rsrc, n_ddevs - 1, cp, bus_type );
+
+} // pcps_rsrc_register_device
+
+#endif // defined( MBG_TGT_OS2 )
+
+#endif // _PCPS_USE_RSRCMGR
+
+
+
+#if _PCPS_USE_MCA
+
+/*--------------------------------------------------------------
+ * PS31 only:
+ *
+ * The scheme below shows the way the bits of the POS 103
+ * configuration byte are mapped to the PS31's programmable
+ * address decoder:
+ *
+ * MSB LSB
+ * | || |
+ * 0bbbbbb1000bxxxx <-- 16 bit port base address (binary)
+ * |||||| |
+ * \\\\\\ | b: configurable bit
+ * \\\\\\ | x: don't care bit
+ * |||||||
+ * 1bbbbbbb <-- 8 bit configuration byte (POS 103)
+ * |
+ * |
+ * decoder enable bit, always 1 if adapter enabled
+ *
+ *-------------------------------------------------------------*/
+
+/*--------------------------------------------------------------
+ * Convert the code read from PS/2 POS to the port base address.
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+ushort pcps_port_from_pos( ushort pos )
+{
+ ushort us = ( ( pos & 0x007E ) << 8 ) | 0x0100;
+
+ if ( pos & 0x0001 )
+ us |= 0x0010;
+
+ return us;
+
+} // pcps_port_from_pos
+
+
+
+/*--------------------------------------------------------------
+ * Convert the port base address to a PS/2 POS code.
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+uchar pcps_pos_from_port( ushort port )
+{
+ uchar uc;
+
+
+ uc = *( ( (uchar *) (&port) ) + 1 ) & 0x7E;
+
+ if ( port & 0x0010 )
+ uc |= 1;
+
+ return uc;
+
+} // pcps_pos_from_port
+
+
+
+static /*HDR*/
+void pcps_detect_mca_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg )
+{
+ short rc;
+ ushort type_idx;
+
+ rc = mca_fnc_init();
+
+ if ( rc != MCA_SUCCESS )
+ return;
+
+
+ // MCA is installed, now try to find a MCA clock with
+ // known ID.
+ for ( type_idx = 0; type_idx < N_PCPS_DEV_TYPE; type_idx++ )
+ {
+ static_wc MCA_POS_DATA pos_data;
+ PCPS_DDEV *pddev;
+ PCPS_DEV_TYPE *p = &pcps_dev_type[type_idx];
+
+ static_wc uchar slot_num; // the slot in which the board is installed
+
+
+ if ( !( p->bus_flags & PCPS_BUS_MCA ) )
+ continue;
+
+
+ rc = mca_find_adapter( p->dev_id, &slot_num, &pos_data );
+
+ if ( rc != MCA_SUCCESS )
+ continue;
+
+
+ // New device found, try to add to list.
+ pddev = alloc_fnc( alloc_arg );
+
+ if ( pddev ) // Setup only if successful.
+ {
+ pddev->dev.type = *p;
+ pcps_add_rsrc_io( pddev, pcps_port_from_pos( pos_data.pos_103 ),
+ PCPS_NUM_PORTS_MCA );
+
+ //##++ Should try to read the interrupt line assigned to the clock.
+ // The standard functions, however, don't use any interrupt.
+
+ pcps_start_device( pddev, 0, slot_num );
+ }
+ }
+
+ mca_fnc_deinit();
+
+} // pcps_detect_mca_clocks
+
+#endif /* _PCPS_USE_MCA */
+
+
+
+// The function below takes a bus flag and device ID to search
+// the table of known devices for a device which matches the
+// given criteria.
+
+/*HDR*/
+PCPS_DEV_TYPE *pcps_get_dev_type( int bus_mask, ushort dev_id )
+{
+ int i;
+
+ for ( i = 0; i < N_PCPS_DEV_TYPE; i++ )
+ {
+ PCPS_DEV_TYPE *p = &pcps_dev_type[i];
+
+ if ( !( p->bus_flags & bus_mask ) )
+ continue;
+
+ if ( p->dev_id == dev_id )
+ return p;
+ }
+
+ return NULL;
+
+} // pcps_get_dev_type
+
+
+
+/*HDR*/
+PCPS_DDEV *pcps_alloc_ddev( void )
+{
+ PCPS_DDEV *pddev;
+
+ #if !_PCPS_STATIC_DEV_LIST
+ pddev = _pcps_kmalloc( sizeof( *pddev ) );
+ #else
+ if ( n_ddevs >= PCPS_MAX_DDEVS )
+ {
+ _mbgddmsg_0( MBG_DBG_INIT_DEV,
+ "Unable to add new device: max count reached" );
+
+ return NULL;
+ }
+
+ pddev = &pcps_ddev[n_ddevs];
+ n_ddevs++;
+ #endif
+
+ if ( pddev )
+ memset( pddev, 0, sizeof( *pddev ) );
+
+ return pddev;
+
+} // pcps_alloc_ddev
+
+
+
+/*HDR*/
+void pcps_free_ddev( PCPS_DDEV *pddev )
+{
+ #if !_PCPS_STATIC_DEV_LIST
+ if ( pddev )
+ _pcps_kfree( pddev, sizeof( *pddev ) );
+ #else
+ memset( pddev, 0, sizeof( *pddev ) );
+
+ if ( n_ddevs )
+ n_ddevs--;
+ #endif
+
+} // pcps_free_ddev
+
+
+
+static /*HDR*/
+void rsrc_port_to_cfg_port( PCPS_PORT_RSRC *p_port_rsrc, const PCPS_IO_RSRC *p_io_rsrc )
+{
+ p_port_rsrc->base = (PCPS_PORT_ADDR) p_io_rsrc->base_raw;
+ p_port_rsrc->num = p_io_rsrc->num;
+
+} // rsrc_port_to_cfg_port
+
+
+
+/*HDR*/
+int pcps_add_rsrc_io( PCPS_DDEV *pddev, ulong base, ulong num )
+{
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+
+ if ( prsrci->num_rsrc_io < N_PCPS_PORT_RSRC )
+ {
+ PCPS_IO_RSRC *p = &prsrci->port[prsrci->num_rsrc_io];
+
+ p->base_mapped = (PCPS_IO_ADDR_MAPPED) _pcps_ioremap( base, num );
+ p->base_raw = (PCPS_IO_ADDR_RAW) base;
+ p->num = (uint16_t) num;
+
+ prsrci->num_rsrc_io++;
+
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "Adding I/O rsrc #%i: %03lX(%lu)",
+ prsrci->num_rsrc_io, (ulong) base, (ulong) num );
+
+ return MBG_SUCCESS;
+ }
+
+ return MBG_ERR_GENERIC;
+
+} // pcps_add_rsrc_io
+
+
+
+/*HDR*/
+int pcps_add_rsrc_mem( PCPS_DDEV *pddev, MBG_MEM_ADDR start, ulong len )
+{
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+
+ if ( prsrci->num_rsrc_mem < N_PCPS_MEM_RSRC )
+ {
+ PCPS_MEM_RSRC *p = &prsrci->mem[prsrci->num_rsrc_mem];
+ p->start = start;
+ p->len = len;
+ prsrci->num_rsrc_mem++;
+
+ #if defined( MBG_TGT_UNIX )
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "Adding mem rsrc #%i: %08llX(%lu)",
+ prsrci->num_rsrc_mem, (unsigned long long) start, len );
+ #else
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "Adding mem rsrc #%i: %08lX(%lu)",
+ prsrci->num_rsrc_mem, (unsigned long) start, len );
+ #endif
+
+ return MBG_SUCCESS;
+ }
+
+ return MBG_ERR_GENERIC;
+
+} // pcps_add_rsrc_mem
+
+
+
+/*HDR*/
+int pcps_add_rsrc_irq( PCPS_DDEV *pddev, int16_t irq_num )
+{
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+
+ if ( prsrci->num_rsrc_irq == 0 )
+ {
+ prsrci->irq.num = irq_num;
+ prsrci->num_rsrc_irq++;
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "Adding IRQ rsrc #%i: %i",
+ prsrci->num_rsrc_irq, irq_num );
+
+ return MBG_SUCCESS;
+ }
+
+ return MBG_ERR_GENERIC;
+
+} // pcps_add_rsrc_irq
+
+
+
+#if _PCPS_USE_PNP
+
+/*HDR*/
+int pcps_init_ddev( PCPS_DDEV *pddev, int bus_flags, ushort dev_id )
+{
+ // First check if we really support the device to be added.
+ PCPS_DEV_TYPE *pdt = pcps_get_dev_type( bus_flags, dev_id );
+
+ if ( pdt == NULL )
+ {
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS add PNP device %X: unknown type",
+ dev_id );
+
+ return MBG_ERR_DEV_NOT_SUPP;
+ }
+
+
+ pddev->dev.type = *pdt;
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS add PNP device %X: found %s",
+ dev_id, pdt->name );
+
+ return MBG_SUCCESS;
+
+} // pcps_init_ddev
+
+#endif // _PCPS_USE_PNP
+
+
+
+#if defined( DEBUG )
+static /*HDR*/
+const char *get_feature_name( PCPS_FEATURES flag )
+{
+ static const char *pcps_feature_names[N_PCPS_FEATURE] = PCPS_FEATURE_NAMES;
+
+ int i;
+
+ for ( i = 0; i < N_PCPS_FEATURE; i++ )
+ if ( ( 1UL << i ) == flag )
+ return pcps_feature_names[i];
+
+ return "unknown";
+
+} // get_feature_name
+
+#endif
+
+
+
+static /*HDR*/
+void check_feature( PCPS_DDEV *pddev, ushort req_rev_num,
+ PCPS_FEATURES flag )
+{
+ int supported = _pcps_ddev_fw_rev_num( pddev ) >= req_rev_num;
+
+ if ( supported )
+ pddev->dev.cfg.features |= flag;
+
+ #if defined( DEBUG )
+ _mbgddmsg_5( MBG_DBG_INIT_DEV, "%s v%03X: feature 0x%08lX (%s) %ssupported",
+ _pcps_ddev_type_name( pddev ),
+ _pcps_ddev_fw_rev_num( pddev ),
+ (ulong) flag, get_feature_name( flag ),
+ supported ? "" : "not " );
+ #endif
+
+} // check_feature
+
+
+
+static /*HDR*/
+void check_ri_feature( PCPS_DDEV *pddev, const RECEIVER_INFO *p_ri,
+ RI_FEATURES ri_flag, PCPS_FEATURES flag )
+{
+ int supported = ( p_ri->features & ri_flag ) != 0;
+
+ if ( supported )
+ pddev->dev.cfg.features |= flag;
+
+ #if defined( DEBUG )
+ _mbgddmsg_5( MBG_DBG_INIT_DEV, "%s v%03X: feature 0x%08lX (%s) %ssupported according to RECEIVER_INFO",
+ _pcps_ddev_type_name( pddev ),
+ _pcps_ddev_fw_rev_num( pddev ),
+ (ulong) flag, get_feature_name( flag ),
+ supported ? "" : "not " );
+ #endif
+
+} // check_ri_feature
+
+
+
+/*HDR*/
+int pcps_start_device( PCPS_DDEV *pddev,
+ PCPS_BUS_NUM bus_num,
+ PCPS_SLOT_NUM dev_fnc_num )
+{
+ ushort port_rsrc_len[N_PCPS_PORT_RSRC] = { 0 };
+ int port_ranges_required = 0;
+ ushort status_port_offs = 0;
+ int i;
+ int rc;
+
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS start device %X",
+ _pcps_ddev_dev_id( pddev ) );
+
+ pddev->read = pcps_read_null;
+ pddev->dev.cfg.bus_num = bus_num;
+ pddev->dev.cfg.slot_num = dev_fnc_num;
+
+ if ( _pcps_ddev_chk_err_flags( pddev, PCPS_EF_IO_INIT | PCPS_EF_IO_ENB ) )
+ {
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS start device %X: failing due to error flags.",
+ _pcps_ddev_dev_id( pddev ) );
+ goto fail;
+ }
+
+ _pcps_mutex_init( &pddev->dev_mutex );
+ _pcps_spin_lock_init( &pddev->mm_lock );
+ _pcps_spin_lock_init( &pddev->irq_lock );
+
+ switch ( _pcps_ddev_bus_flags( pddev ) )
+ {
+ #if _PCPS_USE_USB
+ case PCPS_BUS_USB:
+ // No direct port I/O required.
+ pddev->read = pcps_read_usb;
+
+ // In case of an USB device, do some additional
+ // USB initializiation
+ #if defined( MBG_TGT_WIN32_PNP )
+ rc = pcps_usb_init( pddev );
+ #elif defined( MBG_TGT_LINUX )
+ rc = usb_set_interface( pddev->udev, 0, 0 );
+
+ if ( rc )
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "usb_set_interface returned %d", rc );
+ else
+ {
+ struct usb_host_interface *iface_desc = pddev->intf->cur_altsetting;
+ int i;
+
+ pddev->n_usb_ep = 0;
+
+ for ( i = 0; i < iface_desc->desc.bNumEndpoints; i++ )
+ {
+ struct usb_endpoint_descriptor *endpoint = &iface_desc->endpoint[i].desc;
+ PCPS_USB_EP *pep = &pddev->ep[i];
+ pep->addr = endpoint->bEndpointAddress;
+ pep->max_packet_size = le16_to_cpu( endpoint->wMaxPacketSize );
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "endpoint %d: addr %02X, size: %d",
+ i, pep->addr, pep->max_packet_size );
+ pddev->n_usb_ep++;
+ }
+ }
+ #else
+ #error USB endpoint configuration can not be determined for this target.
+ #endif
+
+ if ( rc == MBG_SUCCESS )
+ if ( pddev->n_usb_ep < MBGUSB_MIN_ENDPOINTS_REQUIRED )
+ {
+ #if defined( MBG_TGT_LINUX )
+ printk( KERN_INFO "device supports only %d endpoints while %d are required\n",
+ pddev->n_usb_ep, MBGUSB_MIN_ENDPOINTS_REQUIRED );
+ #elif defined( MBG_TGT_WIN32_PNP )
+ swprintf( pddev->wcs_msg, L"device supports only %d endpoints while %d are required",
+ pddev->n_usb_ep, MBGUSB_MIN_ENDPOINTS_REQUIRED );
+ _evt_msg( GlbDriverObject, pddev->wcs_msg );
+ #else
+ //##++
+ #endif
+
+ rc = MBG_ERR_GENERIC;
+ }
+ #if defined( MBG_TGT_WIN32_PNP )
+ else
+ {
+ LARGE_INTEGER Count1, Count2, PerfFreq;
+ PCPS_HR_TIME t;
+
+ uint8_t irq_cmd = PCPS_IRQ_1_SEC;
+ rc = _pcps_usb_write_var( pddev, &irq_cmd );
+
+ // get access time to determine latency compensation mode
+ Count1 = KeQueryPerformanceCounter( &PerfFreq );
+ rc = _pcps_read_var( pddev, PCPS_GIVE_HR_TIME, t );
+ Count2 = KeQueryPerformanceCounter( NULL );
+
+ // If access time is below 1 ms then there might be a V2.0 Hub between device and host.
+ // In this case, you can expect that there is the 125 us microframe timing of USB 2.0.
+ if ( ( (ULONGLONG) ( Count2.QuadPart - Count1.QuadPart ) ) < ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL )
+ pddev->usb_20_mode = 1;
+ else
+ pddev->usb_20_mode = 0;
+ }
+ #endif
+
+ if ( rc != MBG_SUCCESS )
+ {
+ _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_INIT );
+ goto fail;
+ }
+ break;
+ #endif
+
+ case PCPS_BUS_PCI_PEX8311:
+ port_rsrc_len[0] = 0;
+ port_rsrc_len[1] = sizeof( PCI_ASIC ); // same as ASIC
+ port_ranges_required = 2; // will be swapped later
+ status_port_offs = offsetof( PCI_ASIC, status_port ); // same as ASIC
+ pddev->read = pcps_read_asic;
+ break;
+
+ case PCPS_BUS_PCI_ASIC:
+ case PCPS_BUS_PCI_MBGPEX:
+ port_rsrc_len[0] = sizeof( PCI_ASIC );
+ port_ranges_required = 1;
+ status_port_offs = offsetof( PCI_ASIC, status_port );
+ pddev->read = pcps_read_asic;
+ break;
+
+ case PCPS_BUS_PCI_S5920:
+ port_rsrc_len[0] = AMCC_OP_REG_RANGE_S5920;
+ port_rsrc_len[1] = 16; //##++
+ port_ranges_required = 2;
+ status_port_offs = AMCC_OP_REG_IMB4 + 3;
+ pddev->read = pcps_read_amcc_s5920;
+ break;
+
+ case PCPS_BUS_PCI_S5933:
+ port_rsrc_len[0] = AMCC_OP_REG_RANGE_S5933;
+ port_ranges_required = 1;
+ status_port_offs = AMCC_OP_REG_IMB4 + 3;
+ pddev->read = pcps_read_amcc_s5933;
+ break;
+
+ case PCPS_BUS_MCA:
+ case PCPS_BUS_ISA:
+ // resource lengths have always been set
+ port_ranges_required = 1;
+ status_port_offs = 1;
+ pddev->read = pcps_read_std;
+ break;
+
+ } // switch ( _pcps_ddev_bus_flags( pddev ) )
+
+
+ // check if all required resources have been assigned
+ if ( pddev->rsrc_info.num_rsrc_io < port_ranges_required )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "PCPS start device %X fails: port ranges (%u) less than required (%u)",
+ _pcps_ddev_dev_id( pddev ), pddev->rsrc_info.num_rsrc_io, port_ranges_required );
+ _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_INIT );
+ goto fail;
+ }
+
+ if ( _pcps_ddev_is_pci_mbgpex( pddev ) )
+ {
+ pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 0 )
+ + offsetof( PCI_ASIC, control_status );
+ pddev->irq_flag_port = pddev->irq_enb_disb_port;
+ pddev->irq_flag_mask = PCI_ASIC_PCI_IRQF;
+
+ pddev->irq_ack_port = pddev->irq_enb_disb_port;
+ pddev->irq_ack_mask = PCI_ASIC_PCI_IRQF;
+ goto chip_setup_done;
+ }
+
+
+ // setup additional properties depending on the
+ // type of bus interface chip
+ if ( _pcps_ddev_is_pci_pex8311( pddev ) )
+ {
+ // I/O and memory ranges must be swapped for the
+ // low level functions because otherwise the first
+ // range addressed the chip configuration registers
+ // while the second range addressed data registers.
+
+ PCPS_MEM_RSRC tmp_mem_rsrc;
+ PCPS_IO_RSRC tmp_io_rsrc;
+
+ tmp_mem_rsrc = pddev->rsrc_info.mem[0];
+ pddev->rsrc_info.mem[0] = pddev->rsrc_info.mem[1];
+ pddev->rsrc_info.mem[1] = tmp_mem_rsrc;
+
+ #if DEBUG_IO
+ _mbgddmsg_4( MBG_DBG_DETAIL, "Ports before swapping: %04lX (%08lX), %04lX (%08lX)",
+ (ulong) pddev->rsrc_info.port[0].base_raw, (ulong) pddev->rsrc_info.port[0].base_mapped,
+ (ulong) pddev->rsrc_info.port[1].base_raw, (ulong) pddev->rsrc_info.port[1].base_mapped );
+ #endif
+
+ tmp_io_rsrc = pddev->rsrc_info.port[0];
+ pddev->rsrc_info.port[0] = pddev->rsrc_info.port[1];
+ pddev->rsrc_info.port[1] = tmp_io_rsrc;
+
+ #if DEBUG_IO
+ _mbgddmsg_4( MBG_DBG_DETAIL, "Ports after swapping: %04lX (%08lX), %04lX (%08lX)",
+ (ulong) pddev->rsrc_info.port[0].base_raw, (ulong) pddev->rsrc_info.port[0].base_mapped,
+ (ulong) pddev->rsrc_info.port[1].base_raw, (ulong) pddev->rsrc_info.port[1].base_mapped );
+ #endif
+
+ // Attention: the interrupt control/status register is located in
+ // the PLX configuration space which is addressed by a different
+ // port address range than the normal data ports !!
+ pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 1 ) + PLX8311_REG_INTCSR;
+ pddev->irq_enb_mask = PLX8311_INT_ENB;
+ pddev->irq_disb_mask = PLX8311_INT_ENB;
+
+ pddev->irq_flag_port = _pcps_ddev_io_base_mapped( pddev, 1 ) + PLX8311_REG_INTCSR;
+ pddev->irq_flag_mask = PLX8311_INT_FLAG;
+
+ pddev->irq_ack_port = _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, control_status );
+ pddev->irq_ack_mask = PCI_ASIC_PCI_IRQF;
+ goto chip_setup_done;
+ }
+
+ if ( _pcps_ddev_is_pci_asic( pddev ) )
+ {
+ pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 0 )
+ + offsetof( PCI_ASIC, control_status );
+ pddev->irq_flag_port = pddev->irq_enb_disb_port;
+ pddev->irq_flag_mask = PCI_ASIC_PCI_IRQF;
+
+ pddev->irq_ack_port = pddev->irq_enb_disb_port;
+ pddev->irq_ack_mask = PCI_ASIC_PCI_IRQF;
+ goto chip_setup_done;
+ }
+
+ if ( _pcps_ddev_is_pci_amcc( pddev ) )
+ {
+ pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 0 )
+ + AMCC_OP_REG_INTCSR;
+ pddev->irq_enb_mask = AMCC_INT_ENB;
+ pddev->irq_disb_mask = AMCC_INT_MASK;
+
+ pddev->irq_flag_port = pddev->irq_enb_disb_port;
+ pddev->irq_flag_mask = AMCC_INT_FLAG;
+
+ pddev->irq_ack_port = pddev->irq_enb_disb_port;
+ pddev->irq_ack_mask = AMCC_INT_ACK;
+ goto chip_setup_done;
+ }
+
+chip_setup_done:
+
+ pddev->status_port = _pcps_ddev_io_base_mapped( pddev, 0 ) + status_port_offs;
+
+ // Set up the resource list in pddev->dev.cfg which
+ // isn't real required anymore, but just informational:
+
+ for ( i = 0; i < N_PCPS_PORT_RSRC; i++ )
+ {
+ PCPS_IO_RSRC *prsrc;
+
+ if ( i >= port_ranges_required )
+ break;
+
+ prsrc = &pddev->rsrc_info.port[i];
+
+ // if the resource len has not yet been set
+ // then use the default resource len
+ if ( prsrc->num == 0 )
+ prsrc->num = port_rsrc_len[i];
+
+ rsrc_port_to_cfg_port( &pddev->dev.cfg.port[i], &pddev->rsrc_info.port[i] );
+ }
+
+ pddev->dev.cfg.irq_num = pddev->rsrc_info.num_rsrc_irq ?
+ pddev->rsrc_info.irq.num : -1;
+ pddev->dev.cfg.status_port = _pcps_ddev_port_base( pddev, 0 ) + status_port_offs;
+
+ pddev->dev.cfg.timeout_clk = PCPS_TIMEOUT_CNT;
+
+ #if DEBUG_PORTS
+ _mbgddmsg_3( MBG_DBG_DETAIL, "IRQ enb/disb port: %04lX, enb: %08lX, disb: %08lX",
+ (ulong) pddev->irq_enb_disb_port,
+ (ulong) pddev->irq_enb_mask,
+ (ulong) pddev->irq_disb_mask
+ );
+ _mbgddmsg_2( MBG_DBG_DETAIL, "IRQ flag port: %04lX, mask: %08lX",
+ (ulong) pddev->irq_flag_port,
+ (ulong) pddev->irq_flag_mask
+ );
+ _mbgddmsg_2( MBG_DBG_DETAIL, "IRQ ack port: %04lX, mask: %08lX",
+ (ulong) pddev->irq_ack_port,
+ (ulong) pddev->irq_ack_mask
+ );
+ _mbgddmsg_1( MBG_DBG_DETAIL, "status port: %04lX", (ulong) pddev->status_port );
+ #endif
+
+ #if _PCPS_USE_RSRCMGR
+ rc = pcps_rsrc_claim( pddev );
+
+ if ( rc < 0 )
+ {
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS start device %X: failed to alloc resources",
+ _pcps_ddev_dev_id( pddev ) );
+
+ goto fail_with_cleanup;
+ }
+ #endif
+
+ // Make sure a PTP270PEX card has finished booting.
+ if ( _pcps_ddev_dev_id( pddev ) == PCI_DEV_PTP270PEX )
+ check_uptime();
+
+ // try to read EPROM ID
+ rc = pcps_get_fw_id( pddev, pddev->dev.cfg.fw_id );
+
+ if ( rc < 0 )
+ {
+ if ( _pcps_ddev_is_isa( pddev ) )
+ {
+ // ISA devices are detected by trying to read a firmware ID via
+ // a given port, so if the firmware ID could not be read then this
+ // just means there is no device using the given port address.
+ #if defined( MBG_TGT_WIN32 )
+ swprintf( pddev->wcs_msg, L"No ISA card found at port %03lXh.",
+ (ulong) _pcps_ddev_port_base( pddev, 0 ) );
+ _evt_msg( GlbDriverObject, pddev->wcs_msg );
+ #else
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "No ISA card found at port %03lXh.",
+ (ulong) _pcps_ddev_port_base( pddev, 0 ) );
+ #endif
+ }
+ else
+ {
+ // Non-ISA devices are detected by some other means, so if the firmware
+ // ID could not be read this is a serious error.
+ #if defined( MBG_TGT_WIN32 ) //##+++ debug or not debug ... ;-)
+ _evt_msg( GlbDriverObject, L"StartDevice: failed to read firmware ID" );
+ #else
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS start device %X: failed to read firmware ID",
+ _pcps_ddev_dev_id( pddev ) );
+ #endif
+ }
+
+ _pcps_ddev_set_err_flags( pddev, PCPS_EF_TIMEOUT );
+ goto fail_with_cleanup;
+ }
+
+ if ( _pcps_ddev_bus_flags( pddev ) == PCPS_BUS_ISA )
+ {
+ ushort dev_type;
+
+ // Still need to find out which type of ISA clock we have found.
+ // Check EPROM ID to find out which kind of clock is installed.
+ if ( pcps_check_id( pddev, fw_id_ref_gps ) == MBG_SUCCESS )
+ dev_type = PCPS_TYPE_GPS167PC;
+ else
+ {
+ if ( pcps_check_id( pddev, fw_id_ref_pcps ) == MBG_SUCCESS )
+ {
+ // Device is a PC31, or a PC32 if it has signature code.
+ // If no support for MCA has been compiled in, it may even
+ // be a PS31 which is software compatible with a PC31.
+ dev_type =
+ ( _mbg_inp16_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + 2 )
+ == pcps_dev_type[PCPS_TYPE_PC32].dev_id ) ?
+ PCPS_TYPE_PC32 : PCPS_TYPE_PC31;
+ }
+ else
+ {
+ _pcps_ddev_set_err_flags( pddev, PCPS_EF_INV_EPROM_ID );
+ goto fail_with_cleanup;
+ }
+ }
+
+ pddev->dev.type = pcps_dev_type[dev_type];
+ }
+
+ #if defined( MBG_TGT_OS2 )
+ pcps_rsrc_register_device( pddev );
+ #endif
+
+ // Extract the firmware revision number from the ID string.
+ pddev->dev.cfg.fw_rev_num = pcps_get_rev_num( _pcps_ddev_fw_id( pddev ) );
+
+ // If the device has an ASIC or EPLD read the ASIC version number
+ if ( _pcps_ddev_has_asic_version( pddev ) )
+ {
+ pddev->raw_asic_version = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 )
+ + offsetof( PCI_ASIC, raw_version ) );
+
+ _mbg_swab_asic_version( &pddev->raw_asic_version );
+
+ pddev->asic_version = _convert_asic_version_number( pddev->raw_asic_version );
+ }
+
+ // Setup some feature flags which depend on the device type
+ // and firmware version.
+ switch( _pcps_ddev_type_num( pddev ) )
+ {
+ case PCPS_TYPE_PC31:
+ case PCPS_TYPE_PS31_OLD:
+ case PCPS_TYPE_PS31:
+ pddev->dev.cfg.features = PCPS_FEAT_PC31PS31;
+ check_feature( pddev, REV_CAN_SET_TIME_PC31PS31, PCPS_CAN_SET_TIME );
+ check_feature( pddev, REV_HAS_SERIAL_PC31PS31, PCPS_HAS_SERIAL );
+ check_feature( pddev, REV_HAS_SYNC_TIME_PC31PS31, PCPS_HAS_SYNC_TIME );
+ check_feature( pddev, REV_HAS_UTC_OFFS_PC31PS31, PCPS_HAS_UTC_OFFS );
+ break;
+
+ case PCPS_TYPE_PC32:
+ pddev->dev.cfg.features = PCPS_FEAT_PC32;
+ break;
+
+ case PCPS_TYPE_PCI32:
+ pddev->dev.cfg.features = PCPS_FEAT_PCI32;
+ break;
+
+ case PCPS_TYPE_GPS167PC:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS167PC;
+ check_feature( pddev, REV_HAS_HR_TIME_GPS167PC, PCPS_HAS_HR_TIME );
+ check_feature( pddev, REV_HAS_CABLE_LEN_GPS167PC, PCPS_HAS_CABLE_LEN );
+ break;
+
+ case PCPS_TYPE_GPS167PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS167PCI;
+ check_feature( pddev, REV_HAS_CABLE_LEN_GPS167PCI, PCPS_HAS_CABLE_LEN );
+ check_feature( pddev, REV_CAN_CLR_UCAP_BUFF_GPS167PCI, PCPS_CAN_CLR_UCAP_BUFF );
+ check_feature( pddev, REV_HAS_UCAP_GPS167PCI, PCPS_HAS_UCAP );
+ break;
+
+ case PCPS_TYPE_PCI509:
+ pddev->dev.cfg.features = PCPS_FEAT_PCI509;
+ break;
+
+ case PCPS_TYPE_GPS168PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS168PCI;
+ check_feature( pddev, REV_CAN_CLR_UCAP_BUFF_GPS168PCI, PCPS_CAN_CLR_UCAP_BUFF );
+ check_feature( pddev, REV_HAS_UCAP_GPS168PCI, PCPS_HAS_UCAP );
+ break;
+
+ case PCPS_TYPE_PCI510:
+ pddev->dev.cfg.features = PCPS_FEAT_PCI510;
+ break;
+
+ case PCPS_TYPE_GPS169PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS169PCI;
+ check_feature( pddev, REV_HAS_GPS_DATA_16_GPS169PCI, PCPS_HAS_GPS_DATA_16 );
+ break;
+
+ case PCPS_TYPE_TCR510PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR510PCI;
+ check_feature( pddev, REV_HAS_HR_TIME_TCR510PCI, PCPS_HAS_HR_TIME );
+ break;
+
+ case PCPS_TYPE_TCR167PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR167PCI;
+ break;
+
+ case PCPS_TYPE_GPS170PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS170PCI;
+ break;
+
+ case PCPS_TYPE_PCI511:
+ pddev->dev.cfg.features = PCPS_FEAT_PCI511;
+ check_feature( pddev, REV_HAS_HR_TIME_PCI511, PCPS_HAS_HR_TIME );
+ break;
+
+ case PCPS_TYPE_TCR511PCI:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR511PCI;
+ check_feature( pddev, REV_HAS_IRIG_CTRL_BITS_TCR511PCI, PCPS_HAS_IRIG_CTRL_BITS );
+ check_feature( pddev, REV_HAS_IRIG_TIME_TCR511PCI, PCPS_HAS_IRIG_TIME );
+ check_feature( pddev, REV_HAS_RAW_IRIG_DATA_TCR511PCI, PCPS_HAS_RAW_IRIG_DATA );
+ break;
+
+ case PCPS_TYPE_PEX511:
+ pddev->dev.cfg.features = PCPS_FEAT_PEX511;
+ // HR time support for the PEX511 requires both a certain ASIC
+ // version plus a certain firmware version.
+ if ( _pcps_asic_version_greater_equal( _pcps_ddev_asic_version( pddev ),
+ PCI_ASIC_MAJOR_PEX511, PCI_ASIC_HR_TIME_MINOR_PEX511 ) )
+ check_feature( pddev, REV_HAS_HR_TIME_PEX511, PCPS_HAS_HR_TIME );
+
+ pcps_check_pex_irq_unsafe( pddev, REV_HAS_IRQ_FIX_MINOR_PEX511,
+ PCI_ASIC_MAJOR_PEX511, PCI_ASIC_FIX_IRQ_MINOR_PEX511 );
+ break;
+
+ case PCPS_TYPE_TCR511PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR511PEX;
+ check_feature( pddev, REV_HAS_IRIG_CTRL_BITS_TCR511PEX, PCPS_HAS_IRIG_CTRL_BITS );
+ check_feature( pddev, REV_HAS_IRIG_TIME_TCR511PEX, PCPS_HAS_IRIG_TIME );
+ check_feature( pddev, REV_HAS_RAW_IRIG_DATA_TCR511PEX, PCPS_HAS_RAW_IRIG_DATA );
+ pcps_check_pex_irq_unsafe( pddev, REV_HAS_IRQ_FIX_MINOR_TCR511PEX,
+ PCI_ASIC_MAJOR_TCR511PEX, PCI_ASIC_FIX_IRQ_MINOR_TCR511PEX );
+ break;
+
+ case PCPS_TYPE_GPS170PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS170PEX;
+ pcps_check_pex_irq_unsafe( pddev, REV_HAS_IRQ_FIX_MINOR_GPS170PEX,
+ PCI_ASIC_MAJOR_GPS170PEX, PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX );
+ break;
+
+ case PCPS_TYPE_USB5131:
+ pddev->dev.cfg.features = PCPS_FEAT_USB5131;
+ break;
+
+ case PCPS_TYPE_TCR51USB:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR51USB;
+ check_feature( pddev, REV_HAS_IRIG_CTRL_BITS_TCR51USB, PCPS_HAS_IRIG_CTRL_BITS );
+ check_feature( pddev, REV_HAS_IRIG_TIME_TCR51USB, PCPS_HAS_IRIG_TIME );
+ check_feature( pddev, REV_HAS_RAW_IRIG_DATA_TCR51USB, PCPS_HAS_RAW_IRIG_DATA );
+ break;
+
+ case PCPS_TYPE_MSF51USB:
+ pddev->dev.cfg.features = PCPS_FEAT_MSF51USB;
+ break;
+
+ case PCPS_TYPE_PTP270PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_PTP270PEX;
+ break;
+
+ case PCPS_TYPE_FRC511PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_FRC511PEX;
+ break;
+
+ case PCPS_TYPE_TCR170PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR170PEX;
+ break;
+
+ case PCPS_TYPE_WWVB51USB:
+ pddev->dev.cfg.features = PCPS_FEAT_WWVB51USB;
+ break;
+
+ case PCPS_TYPE_GPS180PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_GPS180PEX;
+ break;
+
+ case PCPS_TYPE_TCR180PEX:
+ pddev->dev.cfg.features = PCPS_FEAT_TCR180PEX;
+ break;
+
+ case PCPS_TYPE_DCF600USB:
+ pddev->dev.cfg.features = PCPS_FEAT_DCF600USB;
+ break;
+
+ } // switch
+
+
+ if ( _pcps_ddev_has_receiver_info( pddev ) )
+ {
+ int lrc;
+
+ lrc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, pddev->ri );
+
+ if ( lrc == MBG_SUCCESS )
+ {
+ _mbg_swab_receiver_info( &rcvr_info );
+ goto check;
+ }
+ }
+
+ _mbgddmsg_1( MBG_DBG_INIT_DEV, "Setting up default receiver info for dev %X",
+ _pcps_ddev_dev_id( pddev ) );
+
+ if ( _pcps_ddev_is_gps( pddev ) )
+ _setup_default_receiver_info_gps( &pddev->ri );
+ else {
+ _setup_default_receiver_info_dcf( &pddev->ri, &pddev->dev );
+ }
+
+check:
+ #if DEBUG_IO
+ _mbgddmsg_1( MBG_DBG_DETAIL, "ri.sw_rev.code: %04X", pddev->ri.sw_rev.code );
+ _mbgddmsg_1( MBG_DBG_DETAIL, "ri.model_code: %04X", pddev->ri.model_code );
+ _mbgddmsg_3( MBG_DBG_DETAIL, "ri.model_name: %-*.*s", (int) sizeof( pddev->ri.model_name ),
+ (int) sizeof( pddev->ri.model_name ), pddev->ri.model_name );
+ #endif
+
+
+#if 0 //##+++++++++ check if this is reasonnable
+
+ // Make sure this program supports at least as many ports as
+ // the current clock device.
+ if ( pddev->ri.n_com_ports > MAX_PARM_PORT )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s provides %i COM ports, but this driver only supports %i",
+ _pcps_ddev_type_name( pddev ), pddev->ri.n_com_ports, MAX_PARM_PORT );
+ pddev->ri.n_com_ports = MAX_PARM_PORT;
+ }
+
+ // Make sure this program supports at least as many string types
+ // as the current clock device.
+ if ( pddev->ri.n_str_type > MAX_PARM_STR_TYPE )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s supports %i serial string formats, but this driver only supports %i",
+ _pcps_ddev_type_name( pddev ), pddev->ri.n_str_type, MAX_PARM_STR_TYPE );
+ pddev->ri.n_str_type = MAX_PARM_STR_TYPE;
+ }
+#endif
+
+
+ // detect the presence of some optional features at run time
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X RECEIVER_INFO features: 0x%08lX",
+ _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ),
+ (ulong) pddev->ri.features );
+
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_IRIG_TX, PCPS_HAS_IRIG_TX );
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_IRIG_CTRL_BITS, PCPS_HAS_IRIG_CTRL_BITS );
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_SYNTH, PCPS_HAS_SYNTH );
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_TIME_SCALE, PCPS_HAS_TIME_SCALE );
+
+ // Devices which support a configurable time scale do also
+ // support reading/writing the GPS UTC parameters via the PC bus.
+ // This is not explicitely coded in the rcvr_info structure
+ // since the the rcvr_info structure can also be read via
+ // the serial port, and reading/writing the GPS UTC parameters
+ // via the serial port is supported by all GPS devices anyway.
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_TIME_SCALE, PCPS_HAS_UTC_PARM );
+
+ // Devices which support reading raw IRIG data via the PC interface also support
+ // reading the raw IRIG time. However, there is no receiver info feature flag
+ // since this call is not supported via the serial interface, so we use the
+ // GPS_HAS_RAW_IRIG_DATA flag to check both features.
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_IRIG_TIME );
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_RAW_IRIG_DATA );
+
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_LAN_IP4, PCPS_HAS_LAN_INTF );
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_PTP, PCPS_HAS_PTP );
+ check_ri_feature( pddev, &pddev->ri, GPS_HAS_PTP_UNICAST, 0 ); // no equivalent in PCPS_DDEV features
+
+ #if !defined( MBG_TGT_OS2 ) && !defined( MBG_TGT_BSD )
+ // Function strstr may not be supported at kernel level,
+ // but this is not required, in most cases, either.
+ if ( strstr( _pcps_ddev_fw_id( pddev ), "CERN" ) != NULL )
+ pddev->dev.cfg.features |= PCPS_HAS_EVENT_TIME;
+ #endif
+
+ #if DEBUG_IO && defined( MBG_TGT_LINUX )
+ {
+ PCPS_TIME t = { 0 };
+ rc = _pcps_read( pddev, PCPS_GIVE_TIME, &t, sizeof( t ) );
+ printk( KERN_INFO "read time, sz: %lu, returned %i\n", (ulong) sizeof( t ), rc );
+ printk( KERN_INFO " sec100 %02X, sec %02X, min %02X hour %02X\n",
+ t.sec100, t.sec, t.min, t.hour );
+ printk( KERN_INFO " mday %02X, wday %02X, month %02X year %02X\n",
+ t.mday, t.wday, t.month, t.year );
+ printk( KERN_INFO " status %02X, sig %02X, offs_utc %02X\n",
+ t.status, t.signal, t.offs_utc );
+ }
+ #endif
+
+ if ( _pcps_ddev_has_asic_features( pddev ) )
+ {
+ pddev->asic_features = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 )
+ + offsetof( PCI_ASIC, features ) );
+
+ _mbg_swab_asic_features( &pddev->asic_features );
+
+ #if MBG_TGT_SUPP_MEM_ACC
+ if ( pddev->asic_features & PCI_ASIC_HAS_MM_IO )
+ pddev->dev.cfg.features |= PCPS_HAS_FAST_HR_TSTAMP;
+ else
+ if ( pddev->dev.cfg.features & PCPS_HAS_FAST_HR_TSTAMP )
+ {
+ // The device supports memory mapped time stamps by default.
+ // However, this is not reflected by the ASIC features.
+ _mbgddmsg_0( MBG_DBG_INIT_DEV,
+ "Warning: ASIC features don't reflect memory mapped time stamp support." );
+ }
+
+ if ( pddev->dev.cfg.features & PCPS_HAS_FAST_HR_TSTAMP )
+ if ( map_sys_virtual_address( pddev ) < 0 )
+ goto fail_with_cleanup;
+
+ #endif
+ }
+
+ pcps_read_sernum( pddev );
+
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X actual features: 0x%08lX",
+ _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ),
+ (ulong) _pcps_ddev_features( pddev ) );
+
+ return MBG_SUCCESS;
+
+
+fail_with_cleanup:
+ pcps_cleanup_device( pddev );
+
+fail:
+ return MBG_ERR_GENERIC;
+
+} // pcps_start_device
+
+
+
+/*HDR*/
+void pcps_cleanup_device( PCPS_DDEV *pddev )
+{
+ pddev->read = pcps_read_null;
+
+ #if MBG_TGT_SUPP_MEM_ACC
+ unmap_sys_virtual_address( pddev );
+ #endif
+
+ #if _PCPS_USE_RSRCMGR
+ pcps_rsrc_release( pddev );
+ #endif
+
+} // pcps_cleanup_device
+
+
+
+/*--------------------------------------------------------------
+ * PCI functions
+ *-------------------------------------------------------------*/
+
+#if _PCPS_USE_PCI_BIOS
+
+static /*HDR*/
+PCPS_ERR_FLAGS pcps_read_pci_rsrc( PCPS_BUS_NUM bus_num,
+ PCPS_SLOT_NUM dev_fnc_num,
+ PCPS_DDEV *pddev,
+ PCPS_BUS_FLAGS bus_flags )
+{
+ PCPS_ERR_FLAGS err_flags = 0;
+ uchar irq;
+ short rc;
+ PCI_DWORD dw;
+ int i;
+
+ // Clear resources
+ memset( &pddev->rsrc_info, 0, sizeof( pddev->rsrc_info ) );
+
+ for ( i = 0; i < MAX_PCPS_RSRC; i++ )
+ {
+ rc = _mbg_pci_read_cfg_dword( bus_num, dev_fnc_num,
+ PCI_CS_BASE_ADDRESS_0 + i * sizeof( uint32_t ), &dw );
+
+ if ( rc != PCI_SUCCESS )
+ break;
+
+ if ( dw == 0 ) // base address register not used
+ continue;
+
+ if ( dw & 0x0001 ) // is an I/O resource
+ {
+ if ( dw & 0xFFFF0000UL )
+ {
+ // The PCI interface chip is not initialized. This
+ // should occur ONLY at the first-time installation
+ // at the factory.
+ err_flags |= PCPS_EF_IO_INIT;
+ goto done;
+ }
+
+ pcps_add_rsrc_io( pddev, (uint16_t) ( dw & ~0x0001 ), 0 );
+ }
+ else
+ pcps_add_rsrc_mem( pddev, dw, 0 ); //##++ range length?
+ }
+
+ // Read the interrupt line assigned to the clock.
+ // The standard functions, however, don't use any
+ // interrupt.
+ rc = _mbg_pci_read_cfg_byte( bus_num, dev_fnc_num,
+ PCI_CS_INTERRUPT_LINE, &irq );
+
+ if ( rc == PCI_SUCCESS )
+ pcps_add_rsrc_irq( pddev, irq );
+
+done:
+ return err_flags;
+
+} // pcps_read_pci_rsrc
+
+
+
+static /*HDR*/
+PCPS_ERR_FLAGS pcps_enable_pci_dev( PCPS_BUS_NUM bus_num,
+ PCPS_SLOT_NUM dev_fnc_num,
+ int num_rsrc_mem )
+{
+ PCPS_ERR_FLAGS err_flags = 0;
+ uint16_t pci_command;
+ uint16_t new_pci_command;
+ int rc;
+
+
+ // If the option "PNP OS installed" is set to "YES" in the
+ // PC's BIOS setup, then I/O access to the board may still
+ // be disabled, so check if the clock is enabled and enable
+ // access to the board, if nessessary.
+ rc = _mbg_pci_read_cfg_word( bus_num, dev_fnc_num,
+ PCI_CS_COMMAND, &pci_command );
+ new_pci_command = pci_command | PCI_CMD_ENB_IO_ACC;
+
+ if ( num_rsrc_mem )
+ new_pci_command |= PCI_CMD_ENB_MEM_ACC;
+
+ if ( new_pci_command != pci_command )
+ {
+ rc = _mbg_pci_write_cfg_word( bus_num, dev_fnc_num,
+ PCI_CS_COMMAND, pci_command );
+ if ( rc != PCI_SUCCESS )
+ {
+ err_flags |= PCPS_EF_IO_ENB;
+
+ _mbgddmsg_1( MBG_DBG_INIT_DEV,
+ "PCI enable device returned %d", rc );
+ }
+ }
+
+ return err_flags;
+
+} // pcps_enable_pci_dev
+
+
+
+/*HDR*/
+void pcps_setup_and_start_pci_dev( PCPS_DDEV *pddev,
+ PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num )
+{
+ PCPS_ERR_FLAGS err_flags;
+
+ err_flags = pcps_read_pci_rsrc( bus_num, dev_fnc_num,
+ pddev, _pcps_ddev_bus_flags( pddev ) );
+ _pcps_ddev_set_err_flags( pddev, err_flags );
+
+ if ( !( err_flags & PCPS_EF_IO_INIT ) )
+ {
+ err_flags = pcps_enable_pci_dev( bus_num, dev_fnc_num,
+ pddev->rsrc_info.num_rsrc_mem );
+ _pcps_ddev_set_err_flags( pddev, err_flags );
+ }
+
+ pcps_start_device( pddev, bus_num, dev_fnc_num );
+
+} // pcps_setup_and_start_pci_dev
+
+
+
+/*HDR*/
+void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg,
+ PCPS_DDEV_CLEANUP_FNC cleanup_fnc,
+ ushort vendor_id, PCPS_DEV_TYPE dev_type[],
+ int n_dev_types )
+{
+ #if defined( MBG_TGT_QNX )
+ #if defined( MBG_TGT_QNX_NTO )
+ unsigned int pci_handle; // specific to QNX Neutrino
+ #endif
+ unsigned int pci_hardware_mechanism;
+ unsigned int pci_last_bus_number;
+ unsigned int pci_interface_level_version;
+ #elif defined( MBG_TGT_LINUX )
+ // not yet supported/used
+ #else
+ uchar pci_hardware_mechanism;
+ uchar pci_last_bus_number;
+ ushort pci_interface_level_version;
+ #endif
+ ushort type_idx;
+ int rc;
+
+
+ #ifdef _mbg_pci_fnc_init
+ rc = _mbg_pci_fnc_init();
+
+ if ( rc != PCI_SUCCESS )
+ return;
+ #endif
+
+
+ // See if PCI BIOS is installed on the machine.
+ rc = _mbg_pci_find_bios( &pci_hardware_mechanism,
+ &pci_interface_level_version,
+ &pci_last_bus_number
+ );
+
+ if ( rc == PCI_SUCCESS )
+ {
+ // PCI BIOS is installed, now try to find a PCI clock with
+ // known ID (the list is terminated with a ID of 0).
+ for ( type_idx = 0; type_idx < n_dev_types; type_idx++ )
+ {
+ ushort dev_idx;
+ PCPS_DEV_TYPE *p = &dev_type[type_idx];
+
+ if ( !( p->bus_flags & PCPS_BUS_PCI ) )
+ continue;
+
+
+ for ( dev_idx = 0; ; dev_idx++ )
+ {
+ PCPS_DDEV *pddev;
+ #if defined( MBG_TGT_QNX )
+ unsigned bus_num;
+ unsigned dev_fnc_num;
+ #else
+ uchar bus_num;
+ uchar dev_fnc_num;
+ #endif
+
+ rc = _mbg_pci_find_device( p->dev_id, vendor_id,
+ dev_idx, &bus_num, &dev_fnc_num );
+
+ if ( rc != PCI_SUCCESS )
+ break; // go to try next device ID
+
+
+ // New device found, try to add to list.
+ pddev = alloc_fnc();
+
+ if ( pddev ) // Setup only if successful.
+ {
+ #if _PCPS_USE_PCI_PNP //##++
+ // This can be used to test the PNP functions in a
+ // non-PNP environment.
+ pcps_init_ddev( pddev, PCPS_BUS_PCI, p->dev_id );
+ #else
+ pddev->dev.type = *p;
+ #endif
+
+ pcps_setup_and_start_pci_dev( pddev, bus_num, dev_fnc_num );
+
+ #if !_ACCEPT_UNINITD_CLOCKS
+ if ( pddev->dev.cfg.err_flags )
+ {
+ _mbgddmsg_1( MBG_DBG_INIT_DEV,
+ "Remove PCI device: err_flags " FMT_08X "h",
+ (ulong) pddev->dev.cfg.err_flags );
+
+ if ( cleanup_fnc )
+ cleanup_fnc( pddev );
+ }
+ #endif
+ }
+ }
+ }
+ }
+
+ #ifdef _mbg_pci_fnc_deinit
+ _mbg_pci_fnc_deinit();
+ #endif
+
+} // pcps_detect_pci_clocks
+
+#endif // _PCPS_USE_PCI_BIOS
+
+
+
+/*--------------------------------------------------------------
+ * Try to detect ISA clocks
+ *-------------------------------------------------------------*/
+
+#if !_PCPS_USE_ISA_PNP
+
+/*HDR*/
+void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc,
+ PCPS_DDEV_CLEANUP_FNC cleanup_fnc,
+ PCPS_DDEV_REGISTER_FNC register_fnc,
+ int isa_ports[PCPS_MAX_ISA_CARDS],
+ int isa_irqs[PCPS_MAX_ISA_CARDS] )
+{
+ int *p_port = isa_ports;
+ int *p_irq = isa_irqs;
+ PCPS_DDEV *pddev;
+ int i;
+
+ if ( p_port == NULL ) // No list has been passed
+ return; // so don't try to detect ISA clocks.
+
+
+ for( i = 0; i < PCPS_MAX_ISA_CARDS;
+ i++, p_port++, p_irq ? ( p_irq++ ) : p_irq )
+ {
+ int irq_num;
+
+ if ( *p_port == 0 )
+ continue;
+
+ irq_num = p_irq ? *p_irq : -1;
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV,
+ "Check ISA device at port " FMT_03X "h, irq %d",
+ *p_port, irq_num );
+
+ // Assume ISA device is available,
+ // but clock type is unknown, yet.
+ pddev = alloc_fnc();
+
+ if ( pddev ) // Setup only if successfull.
+ {
+ pddev->dev.type.bus_flags = PCPS_BUS_ISA;
+
+ // Set up basic cfg for ISA devices.
+ pcps_add_rsrc_io( pddev, (uint16_t) *p_port, PCPS_NUM_PORTS_ISA );
+
+ if ( irq_num != -1 )
+ pcps_add_rsrc_irq( pddev, (uint16_t) *p_irq );
+
+ // Init the device structure. This includes registration
+ // of I/O ports with the OS's resource manager (if supported),
+ // and reading the firmware ID.
+ pcps_start_device( pddev, 0, 0 );
+
+ // If an error has occurred, then remove the last
+ // device from the list and try next.
+ if ( pddev->dev.cfg.err_flags )
+ {
+ _mbgddmsg_1( MBG_DBG_INIT_DEV,
+ "ISA device not found: err_flags " FMT_08X "h",
+ (ulong) pddev->dev.cfg.err_flags );
+ if ( cleanup_fnc )
+ cleanup_fnc( pddev );
+
+ continue;
+ }
+
+ // Register the device with the OS, if required.
+ if ( register_fnc )
+ register_fnc( pddev ); //##++
+ }
+ }
+
+} // pcps_detect_isa_clocks
+
+#endif //!_PCPS_USE_ISA_PNP
+
+
+
+#if !_PCPS_USE_PNP
+
+/*--------------------------------------------------------------
+ * Try to detect any plug-in radio clock. If a DOS TSR is
+ * installed, be sure it is disabled (BUSY flag set) when
+ * this function is called.
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+void _MBG_INIT_CODE_ATTR pcps_detect_clocks_alloc( PCPS_DDEV_ALLOC_FNC alloc_fnc,
+ void *alloc_arg,
+ PCPS_DDEV_CLEANUP_FNC cleanup_fnc,
+ int isa_ports[PCPS_MAX_ISA_CARDS],
+ int isa_irqs[PCPS_MAX_ISA_CARDS] )
+{
+ #if defined( MBG_TGT_OS2 )
+ rsrc_register_driver(); // register driver and init resource manager
+ #endif
+
+ #if _PCPS_USE_PCI_BIOS
+ pcps_detect_pci_clocks( alloc_fnc, alloc_arg, cleanup_fnc,
+ PCI_VENDOR_MEINBERG, pcps_dev_type, N_PCPS_DEV_TYPE );
+ #endif
+
+ #if _PCPS_USE_MCA
+ pcps_detect_mca_clocks( alloc_fnc, alloc_arg );
+ #endif
+
+ #if !_PCPS_USE_ISA_PNP
+ pcps_detect_isa_clocks( alloc_fnc, cleanup_fnc, NULL, isa_ports, isa_irqs );
+ #endif
+
+} // pcps_detect_clocks_alloc
+
+
+
+/*HDR*/
+void _MBG_INIT_CODE_ATTR pcps_detect_clocks( int isa_ports[PCPS_MAX_ISA_CARDS],
+ int isa_irqs[PCPS_MAX_ISA_CARDS] )
+{
+ pcps_detect_clocks_alloc( pcps_alloc_ddev, NULL, pcps_free_ddev,
+ isa_ports, isa_irqs );
+
+} // pcps_detect_clocks
+
+#endif // !_PCPS_USE_PNP
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h
new file mode 100755
index 0000000..2b8fd26
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h
@@ -0,0 +1,1445 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsdrvr.h 1.41.1.20 2011/03/25 11:11:44 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpsdrvr.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsdrvr.h $
+ * Revision 1.41.1.20 2011/03/25 11:11:44 martin
+ * Optionally support timespec for sys time (USE_TIMESPEC).
+ * Started to support NetBSD.
+ * Revision 1.41.1.19 2011/02/15 14:24:58 martin
+ * Revision 1.41.1.18 2011/02/09 17:08:31 martin
+ * Specify I/O range number when calling port I/O macros
+ * so they can be used for different ranges under BSD.
+ * Revision 1.41.1.17 2011/02/04 14:44:46 martin
+ * Revision 1.41.1.16 2011/02/04 10:10:18 martin
+ * Revision 1.41.1.15 2011/02/02 12:20:42 martin
+ * Revision 1.41.1.14 2011/02/01 17:12:05 martin
+ * Revision 1.41.1.13 2011/02/01 14:49:43 martin
+ * Revision 1.41.1.12 2011/02/01 12:12:19 martin
+ * Revision 1.41.1.11 2011/01/31 17:30:02 martin
+ * Modified resource storage for *BSD.
+ * Revision 1.41.1.10 2011/01/27 13:39:01 martin
+ * Revision 1.41.1.9 2011/01/27 11:04:45 martin
+ * Revision 1.41.1.8 2011/01/27 11:01:49 martin
+ * Support static device list (no malloc) and use it under FreeBSD.
+ * Revision 1.41.1.7 2011/01/26 16:42:07 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.41.1.6 2011/01/25 09:47:27 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.41.1.5 2010/11/23 11:07:57 martin
+ * Support memory mapped access under DOS.
+ * Revision 1.41.1.4 2010/11/11 09:15:39Z martin
+ * Added definitions to support DCF600USB.
+ * Revision 1.41.1.3 2010/08/20 09:35:12 martin
+ * Added macro _pcps_ddev_features().
+ * Revision 1.41.1.2 2010/07/14 14:52:12 martin
+ * Revision 1.41.1.1 2010/06/30 15:01:52 martin
+ * Support GPS180PEX and TCR180PEX.
+ * Revision 1.41 2010/06/30 13:44:49 martin
+ * Use new preprocessor symbol MBG_ARCH_X86.
+ * Revision 1.40 2010/01/12 14:05:05 daniel
+ * Added macro to check if reading the
+ * raw IRIG data bits is supported.
+ * Revision 1.39 2009/09/29 07:24:51Z martin
+ * Use standard feature flag to check if fast HR time is supported.
+ * Revision 1.38 2009/06/19 12:13:05 martin
+ * Added _pcps_ddev_has_irig_time() macro.
+ * Revision 1.37 2009/06/09 10:13:59 daniel
+ * Added macros _pcps_ddev_has_lan_intf( _p ) and
+ * _pcps_ddev_has_ptp_cfg( _p ).
+ * Cleaned up the low level interface and provided a
+ * possibility to override the macros for special purposes.
+ * Set USB cyclic timeout interval to 1200 ms as default.
+ * Revision 1.36 2009/03/16 16:01:24Z martin
+ * Support reading IRIG control function bits.
+ * Revision 1.35 2009/03/13 09:23:36 martin
+ * Added _pcps_ddev_has_time_scale( _p ) and _pcps_ddev_has_utc_parm( _p ).
+ * Moved _pcps_get_cycles() and _pcps_get_cycles_frequency() to pcpsdev.h
+ * and replaced/merged them with mbg_get_pc_cycles...() functions.
+ * Under Linux use own inline function to read TSC on x86 architectures.
+ * Normally USB timeouts are short with retries in order to increase
+ * responsiveness. On some systems this may lead to problems, so
+ * optionally one long timeout can be used now by define.
+ * Revision 1.34 2008/12/16 14:40:47 martin
+ * Account for new devices PTP270PEX, FRC270PEX, TCR170PEX, and WWVB51USB.
+ * Added macros _pcps_ddev_is_ptp(), _pcps_ddev_is_frc(),
+ * and _pcps_ddev_is_wwvb().
+ * Don't use pragma pack( 1 ) but use native alignment since structures
+ * defined here are not used across system boundaries.
+ * Added fields to PCPS_DDEV to store the ASIC version, and macros
+ * _pcps_ddev_raw_asic_version() and _pcps_ddev_asic_version().
+ * Moved PC cycles types and macros here, and defined dummy _pcps_get_cycles()
+ * for targets which don't support this.
+ * Use generic spinlock/mutex macros and common device access mutex.
+ * Support getting cycles frequency from device driver.
+ * Use MBG_MEM_ADDR type for memory rather than split high/low types.
+ * Renamed MBG_VIRT_ADDR to MBG_MEM_ADDR.
+ * Additional device port variables for IRQ handling.
+ * Use new MBG_ARCH_I386 symbol.
+ * Added DEBUG_LVL_... symbols.
+ * Use PCPS_IRQ_STAT_INFO type.
+ * Account for signed irq_num.
+ * New PCPS_DDEV field acc_cycles.
+ * Added variable usb_20_mode in PCPS_DDEV.
+ * Added connected flag to PCPS_DDEV structure.
+ * Added macro _pcps_ddev_has_fast_hr_timestamp().
+ * Use macros for unaligned access and endianess conversion.
+ * Support mapped I/O resources.
+ * Use some atomic_t types under Linux.
+ * Conditionally use Linux kthread API.
+ * Updated function prototypes.
+ * Revision 1.33 2008/02/27 10:25:30 martin
+ * Added support for TCR51USB and MSF51USB.
+ * Increased N_PCPS_MEM_RSRC to 2.
+ * Modified PCPS_MEM_RSRC to support memory mapped I/O.
+ * Added PCI_ASIC_FEATURES to PCPS_DDEV.
+ * Added new macros and modified some older macros to support
+ * cyclic reading for USB within WIN32 targets.
+ * New macros _pcps_ddev_is_lwr() (long wave receiver),
+ * _pcps_ddev_is_msf(), _pcps_ddev_has_asic_version(),
+ * _pcps_ddev_has_asic_features().
+ * Moved Linux version-specific stuff to mbg_lx.h.
+ * Don't support MCA under DOS by default.
+ * Updated function prototypes.
+ * Revision 1.32 2008/01/31 09:06:03Z martin
+ * Don't support MCA under DOS by default.
+ * Revision 1.31 2007/09/26 09:28:03Z martin
+ * Added support for USB in general and new USB device USB5131.
+ * Renamed ..._USE_PCIMGR symbols to ..._USE_PCI_PNP.
+ * Renamed ..._USE_PCIBIOS symbols to ..._USE_PCI_BIOS.
+ * Added definition _PCPS_USE_PNP.
+ * Added new symbol _USE_ISA_PNP to exclude non-PNP stuff.
+ * from build if ISA devices are also handled by the PNP manager.
+ * Include mbgerror.h for new MBG_... codes.
+ * Added macro _pcps_ddev_status_busy().
+ * Added kernel malloc/free macros and USB I/O macros.
+ * Use PCPS_DDEV as private device data.
+ * Use ms values for USB timeouts also under Linux. This may not be
+ * appropriate for older kernels.
+ * Limited length of some older RCS log messages.
+ * Revision 1.30 2007/07/25 14:22:23Z martin
+ * Under Linux include param.h for definition of HZ under
+ * kernels 2.6.21 and newer.
+ * Revision 1.29 2007/07/17 08:22:48 martin
+ * Added support for TCR511PEX and GPS170PEX.
+ * Revision 1.28 2007/07/16 12:58:00Z martin
+ * Added support for PEX511.
+ * Added new structures used for unified resource handling.
+ * Account for renamed library symbols.
+ * Revision 1.27 2007/03/02 09:41:05Z martin
+ * Use generic port I/O macros.
+ * Added DEVICE_OBJECT to PCPS_DDEV under Windows.
+ * Define init code qualifier.
+ * Added new _pcps_..._timeout_clk() macros.
+ * Preliminary support for *BSD.
+ * Preliminary support for USB.
+ * Revision 1.26 2006/07/07 09:44:23 martin
+ * Fixed definition of control macros for the case where
+ * _PCPS_USE_PCI_PNP is overridden from the command line.
+ * Revision 1.25 2006/06/19 15:31:09 martin
+ * Added support for TCR511PCI.
+ * Updated function prototypes.
+ * Revision 1.24 2006/03/10 11:01:51 martin
+ * Added support for PCI511.
+ * Revision 1.23 2005/11/03 15:50:45Z martin
+ * Added support for GPS170PCI.
+ * Revision 1.22 2005/06/02 10:35:09Z martin
+ * Added macro _pcps_ddev_is_pci_amcc().
+ * Added macro _pcps_ddev_has_generic_io().
+ * Updated function prototypes.
+ * Revision 1.21 2004/12/09 11:03:38Z martin
+ * Support configuration of on-board frequency synthesizer.
+ * Revision 1.20 2004/11/09 13:05:12Z martin
+ * Fixed syntax bug in macro _pcps_ddev_fw_rev_num().
+ * New macro _pcps_ddev_has_gps_data().
+ * New macro _pcps_ddev_requires_irig_workaround().
+ * Revision 1.19 2004/10/14 15:01:24Z martin
+ * Added support for TCR167PCI.
+ * Revision 1.18 2004/09/06 15:11:04Z martin
+ * Support a GPS_DATA interface where sizes are specified
+ * by 16 instead of the original 8 bit quantities, thus allowing
+ * to transfer data blocks which exceed 255 bytes.
+ * Revision 1.17 2004/04/14 10:29:45Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.16 2004/04/07 09:47:19Z martin
+ * New macros _pcps_ddev_has_irig() and
+ * _pcps_ddev_has_irig_tx().
+ * Revision 1.15 2004/03/10 17:32:23Z martin
+ * Use CLOCKS_PER_SEC for timeout under QNX6 (Neutrino).
+ * Revision 1.14 2003/11/17 16:15:01 martin
+ * Support clock tick timeout for QNX.
+ * Revision 1.13 2003/07/08 15:07:32Z martin
+ * Simplified definitions of default preprocessor macros.
+ * Compile for plug'n'play for Linux kernels 2.4.0 or newer.
+ * Updated function prototypes.
+ * Revision 1.12 2003/06/19 09:56:29 MARTIN
+ * Renamed macro ..clr_cap_buffer to ..clr_ucap_buffer.
+ * New macro _pcps_ddev_has_ucap().
+ * Changes due to renamed symbols.
+ * Updated function prototypes.
+ * Revision 1.11 2003/05/16 09:31:54 MARTIN
+ * Increased timeout loop count from 0x1000 to 0x7FFFFF.
+ * Rearranged inclusion of headers depending on the target.
+ * Added array for ISA port addresses.
+ * Revision 1.10 2003/04/09 16:30:24 martin
+ * Supports PCI510, GPS169PCI, and TCR510PCI,
+ * and new PCI_ASIC used by those devices.
+ * Renamed macro _pcps_ddev_is_irig() to _pcps_ddev_is_irig_rx().
+ * New macros _pcps_ddev_has_ref_offs(), _pcps_ddev_has_opt_flags().
+ * Preliminary support for PCPS_TZDL.
+ * Revision 1.9 2002/08/09 08:53:53 MARTIN
+ * New macro _pcps_ddev_can_clr_cap_buff().
+ * New macro _pcps_ddev_is_irig().
+ * New macro _pcps_ddev_has_signal().
+ * New macro _pcps_ddev_has_mod().
+ * Revision 1.8 2002/02/26 09:34:03 MARTIN
+ * Removed macro _pcps_read_sernum() which was replaced
+ * by a function pcps_read_sernum() which reads the S/N from
+ * any clock that supports a S/N.
+ * Updated function prototypes.
+ * Revision 1.7 2002/02/19 09:28:01 MARTIN
+ * Use new header mbg_tgt.h to check the target environment.
+ * Revision 1.6 2002/02/01 12:00:10 MARTIN
+ * Added new definitions for GPS168PCI.
+ * Renamed macro _pcps_ddev_rev_num to _pcps_ddev_fw_rev_num
+ * to follow naming conventions.
+ * Source code cleanup.
+ * Revision 1.5 2001/11/30 09:52:48 martin
+ * Added support for event_time which, however, requires
+ * a custom GPS firmware.
+ * Revision 1.4 2001/10/16 10:15:44 MARTIN
+ * New Macro _pcps_ddev_has_serial_hs() which determines
+ * whether DCF77 clock supports baud rate higher than default.
+ * Added some macros and comments corresponding to
+ * pcpsdev.h.
+ * Revision 1.3 2001/09/18 06:53:57 MARTIN
+ * Two sets of preprocessor symbols for Win9x/ME and WinNT/2k.
+ * New preprocessor symbol controls usage of clock ticks for timeout.
+ * Changed type of PCPS_RSRC.irq_num from int to ushort.
+ * Updated function prototypes.
+ * Revision 1.2 2001/03/16 14:45:34 MARTIN
+ * New functions and definitions to support PNP drivers.
+ * Revision 1.1 2001/03/01 16:29:22 MARTIN
+ * Initial version for the new library.
+ *
+ **************************************************************************/
+
+#ifndef _PCPSDRVR_H
+#define _PCPSDRVR_H
+
+// Setup default controls to include support for
+// special features.
+
+#define DEBUG_LVL_SEM 7
+#define DEBUG_LVL_PORTS 10
+#define DEBUG_LVL_SERNUM 11
+#define DEBUG_LVL_IO 12
+
+
+#include <mbg_tgt.h>
+
+#if defined( MBG_TGT_NETWARE )
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_PCI_PNP 0
+ #define _DEFAULT_PCPS_USE_USB 0
+ #define _DEFAULT_PCPS_USE_RSRCMGR 0
+#elif defined( MBG_TGT_OS2 )
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 0
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_PCI_PNP 0
+ #define _DEFAULT_PCPS_USE_USB 0
+ #define _DEFAULT_PCPS_USE_RSRCMGR 1
+#elif defined( MBG_TGT_WIN32_PNP )
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 1
+ #define _DEFAULT_PCPS_USE_PCI_PNP 1
+ #define _DEFAULT_PCPS_USE_USB 1
+ #define _DEFAULT_PCPS_USE_RSRCMGR 0
+#elif defined( MBG_TGT_WIN32 )
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_PCI_PNP 0
+ #define _DEFAULT_PCPS_USE_USB 0
+ #define _DEFAULT_PCPS_USE_RSRCMGR 0
+#elif defined( MBG_TGT_LINUX )
+ #include <mbg_lx.h>
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA defined( MBG_ARCH_X86 )
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_PCI_PNP _DEFAULT_MBG_TGT_LINUX_USE_PCI_PNP
+ #define _DEFAULT_PCPS_USE_USB _DEFAULT_MBG_TGT_LINUX_USE_USB
+ #define _DEFAULT_PCPS_USE_RSRCMGR 1
+#elif defined( MBG_TGT_BSD ) //##++
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_PCI_PNP 1
+ #define _DEFAULT_PCPS_USE_USB 0
+ #define _DEFAULT_PCPS_USE_RSRCMGR 1
+#elif defined( MBG_TGT_QNX )
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_PCI_PNP 0
+ #define _DEFAULT_PCPS_USE_USB 0
+ #define _DEFAULT_PCPS_USE_RSRCMGR 0
+#else // DOS ...
+ #define _DEFAULT_PCPS_USE_CLOCK_TICK 1
+ #define _DEFAULT_PCPS_USE_ISA 1
+ #define _DEFAULT_PCPS_USE_MCA 0
+ #define _DEFAULT_PCPS_USE_PCI 1
+ #define _DEFAULT_PCPS_USE_PCI_PNP 0
+ #define _DEFAULT_PCPS_USE_ISA_PNP 0
+ #define _DEFAULT_PCPS_USE_USB 0
+ #define _DEFAULT_PCPS_USE_RSRCMGR 0
+#endif
+
+#ifndef _PCPS_USE_CLOCK_TICK
+ #define _PCPS_USE_CLOCK_TICK _DEFAULT_PCPS_USE_CLOCK_TICK
+#endif
+
+#ifndef _PCPS_USE_ISA
+ #define _PCPS_USE_ISA _DEFAULT_PCPS_USE_ISA
+#endif
+
+#ifndef _PCPS_USE_MCA
+ #define _PCPS_USE_MCA _DEFAULT_PCPS_USE_MCA
+#endif
+
+#ifndef _PCPS_USE_PCI
+ #define _PCPS_USE_PCI _DEFAULT_PCPS_USE_PCI
+#endif
+
+#ifndef _PCPS_USE_ISA_PNP
+ #define _PCPS_USE_ISA_PNP _DEFAULT_PCPS_USE_ISA_PNP
+#endif
+
+#ifndef _PCPS_USE_PCI_PNP
+ #define _PCPS_USE_PCI_PNP _DEFAULT_PCPS_USE_PCI_PNP
+#endif
+
+#ifndef _PCPS_USE_USB
+ #define _PCPS_USE_USB _DEFAULT_PCPS_USE_USB
+#endif
+
+#ifndef _PCPS_USE_RSRCMGR
+ #define _PCPS_USE_RSRCMGR _DEFAULT_PCPS_USE_RSRCMGR
+#endif
+
+
+#ifndef _PCPS_USE_PCI_BIOS
+ #define _PCPS_USE_PCI_BIOS ( _PCPS_USE_PCI && !_PCPS_USE_PCI_PNP )
+#endif
+
+#define _PCPS_USE_PNP ( _PCPS_USE_PCI_PNP || _PCPS_USE_ISA_PNP || _PCPS_USE_USB )
+
+#if _PCPS_USE_PCI_PNP && _PCPS_USE_PCI_BIOS
+ #error "PCI PNP and non-PNP can't be used at the same time"
+#endif
+
+
+#if !defined( _MBG_INIT_CODE_ATTR )
+ // define to empty string by default
+ #define _MBG_INIT_CODE_ATTR
+#endif
+
+
+
+/* Other headers to be included */
+#include <pci_asic.h>
+#include <pcpsdev.h>
+#include <mbgerror.h>
+#include <use_pack.h>
+#include <mbggenio.h>
+
+#if defined( MBG_TGT_FREEBSD )
+ #include <mbg_bsd.h>
+ #include <sys/malloc.h>
+ #include <sys/_null.h>
+ #include <sys/param.h>
+ #include <sys/lock.h>
+ #include <sys/mutex.h>
+ #include <machine/bus.h>
+#elif defined( MBG_TGT_NETBSD )
+ #include <sys/kmem.h>
+ #include <sys/mutex.h>
+#else
+ #include <stddef.h>
+#endif
+
+#if defined( MBG_TGT_DOS )
+ #include <string.h>
+ #include <time.h>
+#endif
+
+#if defined( MBG_TGT_WIN32 )
+ #include <mbg_w32.h>
+#endif
+
+#if defined( MBG_TGT_LINUX )
+ #if _PCPS_USE_USB
+ #include <linux/usb.h>
+ #endif
+#endif
+
+#if defined( MBG_TGT_QNX )
+ #include <mbg_qnx.h>
+ #include <string.h>
+ #include <time.h>
+#endif
+
+#if defined( MBG_TGT_NETWARE )
+ #include <string.h>
+ #include <time.h>
+ #include <conio.h>
+#endif
+
+#if defined( MBG_TGT_OS2 )
+ #ifndef OS2_INCLUDED
+ #define INCL_DOSSEMAPHORES
+ #include <os2.h>
+ #include <rmbase.h>
+ #endif
+
+ #include <string.h>
+ #include <time.h>
+ #include <conio.h>
+ #include <xportio.h>
+#elif defined( MBG_TGT_DOS )
+ #define FAR far
+#else
+ #define FAR
+#endif
+
+#if _PCPS_USE_RSRCMGR
+ #include <rsrc.h>
+#endif
+
+#ifdef _PCPSDRVR
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+// We use native alignment for structures which are not accessed across system boundaries.
+
+#if defined( MBG_TGT_LINUX )
+
+ #define _pcps_kmalloc( _sz ) kmalloc( _sz, GFP_ATOMIC )
+ #define _pcps_kfree( _p, _sz ) kfree( _p )
+
+ #define MBG_SPINLOCK spinlock_t
+ #define _pcps_spin_lock_init( _spl ) spin_lock_init( _spl )
+ #define _pcps_spin_lock_deinit( _spl ) nop_macro_fnc()
+ #define _pcps_spin_lock( _spl ) spin_lock( _spl )
+ #define _pcps_spin_unlock( _spl ) spin_unlock( _spl )
+
+ #define MBG_SYS_MUTEX struct semaphore
+ #define _pcps_mutex_init( _pmtx ) sema_init( _pmtx, 1 )
+
+ // The special versions of _pcps_sem_inc() and _pcps_sem_dec() below
+ // are only required to prevent interference with the IRQ handler
+ // under Linux which implements the serial port emulation for the
+ // NTP parse driver.
+ #define _pcps_sem_inc( _pddev ) \
+ { \
+ ulong flags; \
+ \
+ if ( down_interruptible( &(_pddev)->dev_mutex ) < 0 ) \
+ return -ERESTARTSYS; \
+ \
+ spin_lock_irqsave( &(_pddev)->irq_lock, flags ); \
+ atomic_inc( &(_pddev)->access_in_progress ); \
+ spin_unlock_irqrestore( &(_pddev)->irq_lock, flags ); \
+ }
+
+ #define _pcps_sem_dec( _pddev ) \
+ atomic_dec( &(_pddev)->access_in_progress ); \
+ up( &(_pddev)->dev_mutex )
+
+#elif defined( MBG_TGT_FREEBSD )
+
+ // malloc/free in kernel mode require usage of the
+ // MALLOC_DECLARE() / MALLOC_DEFINE() macros.
+ // See "man 9 malloc" for details.
+
+ MALLOC_DECLARE( M_MBGCLOCK );
+ #define _pcps_kmalloc( _sz ) malloc( _sz, M_MBGCLOCK, M_NOWAIT | M_ZERO )
+ #define _pcps_kfree( _p, _sv ) free( _p, M_MBGCLOCK )
+
+ #define MBG_SPINLOCK struct mtx
+ #define _pcps_spin_lock_init( _spl ) mtx_init( _spl, "mbgclock_spin", NULL, MTX_SPIN )
+ #define _pcps_spin_lock( _spl ) mtx_lock_spin( _spl )
+ #define _pcps_spin_unlock( _spl ) mtx_unlock_spin( _spl )
+
+ #define MBG_SYS_MUTEX struct mtx
+ #define _pcps_mutex_init( _pmtx ) mtx_init( _pmtx, "mbgclock_sema", NULL, MTX_DEF )
+ #define _pcps_mutex_acquire( _pmtx ) mtx_lock( _pmtx )
+ #define _pcps_mutex_release( _pmtx ) mtx_unlock( _pmtx )
+
+#elif defined( MBG_TGT_NETBSD )
+
+ // For older NetBSD versions which do not suppport the calls
+ // used below, see 'man 9 malloc'.
+ #define _pcps_kmalloc( _sz ) kmem_alloc( _sz, KM_NOSLEEP )
+ #define _pcps_kfree( _p, _sz ) kmem_free( _p, _sz )
+
+ // The API used below has been introduced in NetBSD 5.0
+ // For earlier NetBSD versions see 'man 9 lockinit'.
+
+ #define MBG_SPINLOCK kmutex_t
+ #define _pcps_spin_lock_init( _spl ) mutex_init( _spl, MUTEX_DEFAULT, IPL_HIGH )
+ #define _pcps_spin_lock_deinit( _spl ) mutex_destroy( _spl )
+ #define _pcps_spin_lock( _spl ) mutex_spin_enter( _spl )
+ #define _pcps_spin_unlock( _spl ) mutex_spin_exit( _spl )
+
+ #define MBG_SYS_MUTEX kmutex_t
+ #define _pcps_mutex_init( _pmtx ) mutex_init( _pmtx, MUTEX_DEFAULT, IPL_NONE )
+ #define _pcps_mutex_deinit( _spl ) mutex_destroy( _spl )
+ #define _pcps_mutex_acquire( _pmtx ) mutex_enter( _pmtx )
+ #define _pcps_mutex_release( _pmtx ) mutex_exit( _pmtx )
+
+#elif defined( MBG_TGT_WIN32 )
+
+ #define _pcps_kmalloc( _sz ) ExAllocatePool( PagedPool, _sz )
+ #define _pcps_kfree( _p, , _sz ) ExFreePool( _p )
+
+ #define MBG_SPINLOCK KSPIN_LOCK
+ #define _pcps_spin_lock_init( _spl ) KeInitializeSpinLock( _spl )
+ #define _pcps_spin_lock( _spl ) KeAcquireSpinLockAtDpcLevel( _spl )
+ #define _pcps_spin_unlock( _spl ) KeReleaseSpinLockFromDpcLevel( _spl )
+
+ #define MBG_SYS_MUTEX FAST_MUTEX
+ #define _pcps_mutex_init( _pmtx ) ExInitializeFastMutex( _pmtx )
+ #define _pcps_mutex_acquire( _pmtx ) ExAcquireFastMutex( _pmtx )
+ #define _pcps_mutex_release( _pmtx ) ExReleaseFastMutex( _pmtx )
+
+#endif
+
+
+#if !defined( _PCPS_STATIC_DEV_LIST )
+ // On PNP systems buffers for device specific data are by default malloc'ed
+ // whenever a device appears. However, a static array of a given maximum number
+ // of devices is used on non-PNP systems.
+ // This can be overridden for testing to avoid calling malloc in kernel space.
+ #define _PCPS_STATIC_DEV_LIST ( !_PCPS_USE_PNP )
+#endif
+
+
+
+// If the macros below have not yet been defined then define some dummies:
+
+#if !defined( MBG_SYS_MUTEX )
+
+ #define _pcps_mutex_init( _pmtx ) _nop_macro_fnc()
+ #define _pcps_mutex_acquire( _pmtx ) _nop_macro_fnc()
+ #define _pcps_mutex_release( _pmtx ) _nop_macro_fnc()
+
+#endif
+
+
+#if !defined( MBG_SPINLOCK )
+
+ #define _pcps_spin_lock_init( _spl ) _nop_macro_fnc()
+ #define _pcps_spin_lock( _spl ) _nop_macro_fnc()
+ #define _pcps_spin_unlock( _spl ) _nop_macro_fnc()
+
+#endif
+
+
+#if !defined( _pcps_sem_inc ) || !defined( _pcps_sem_dec )
+
+ #define _pcps_sem_inc( _pddev ) \
+ _pcps_mutex_acquire( &(_pddev)->dev_mutex )
+
+ #define _pcps_sem_dec( _pddev ) \
+ _pcps_mutex_release( &(_pddev)->dev_mutex )
+
+#endif
+
+
+
+/* ------ definitions used with PCI clocks -------------------------- */
+
+/* Default timeout count accessing the board */
+
+#if _PCPS_USE_CLOCK_TICK
+ #if defined( MBG_TGT_NETWARE )
+ #define PCPS_TIMEOUT_CNT ( (ulong)( 200 * __get_CLK_TCK() ) / 1000 )
+ #elif defined( MBG_TGT_LINUX )
+ #define PCPS_TIMEOUT_CNT ( (ulong)( 200 * HZ ) / 1000 )
+ #elif defined( MBG_TGT_BSD )
+ #define PCPS_TIMEOUT_CNT ( (ulong)( 200 ) ) // [ms]
+ #elif defined( MBG_TGT_WIN32 )
+ #define PCPS_TIMEOUT_CNT ( (ulong)( 200 * MBG_TICKS_PER_SEC ) / 1000 )
+ #elif defined( MBG_TGT_QNX_NTO )
+ #define PCPS_TIMEOUT_CNT ( (ulong)( 200 * CLOCKS_PER_SEC ) / 1000 )
+ #else
+ #define PCPS_TIMEOUT_CNT ( (ulong)( 200 * CLK_TCK ) / 1000 )
+ #endif
+#else
+ #define PCPS_TIMEOUT_CNT 0x7FFFFFUL
+#endif
+
+
+// The structures below are used to provide a consistent
+// resource handling across different platforms.
+// This is kept completely inside the kernel drivers, so these
+// structures can be modified safely to suit our needs.
+
+#if MBG_USE_MM_IO_FOR_PCI
+
+ typedef ulong PCPS_IO_ADDR_RAW;
+
+ #if defined( MBG_TGT_LINUX )
+
+ typedef volatile void __iomem *PCPS_IO_ADDR_MAPPED;
+
+ #define _pcps_ioremap( _base, _num ) ioremap_nocache( (_base), (_num) )
+
+ #else
+
+ #error Not supported for target environment.
+
+ #endif
+
+#else
+
+ typedef PCPS_PORT_ADDR PCPS_IO_ADDR_RAW;
+ typedef PCPS_IO_ADDR_RAW PCPS_IO_ADDR_MAPPED;
+
+ #if defined( MBG_TGT_BSD )
+ // Under *BSD we use only the offset. The base address
+ // is determined by a handle.
+ #define _pcps_ioremap( _base, _num ) 0
+ #else
+ #define _pcps_ioremap( _base, _num ) ( _base )
+ #endif
+#endif
+
+
+
+#if defined( MBG_TGT_BSD )
+
+typedef struct
+{
+#if defined ( MBG_TGT_FREEBSD )
+ int rid; /* resource ID */
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+#elif defined ( MBG_TGT_NETBSD )
+ int reg; /* BAR */
+ int type; /* type */
+ int valid; /* valid flag */
+ bus_space_tag_t bst; /* bus space tag */
+ bus_space_handle_t bsh; /* bus space handle */
+ bus_addr_t base; /* base address */
+ bus_size_t size; /* size */
+#endif
+} BSD_RSRC_INFO;
+
+#endif
+
+
+
+/**
+ The structure below describes an I/O port resource
+ used by a clock.
+*/
+typedef struct
+{
+ #if defined( MBG_TGT_BSD )
+ BSD_RSRC_INFO bsd;
+ #endif
+ PCPS_IO_ADDR_MAPPED base_mapped;
+ PCPS_IO_ADDR_RAW base_raw;
+ uint16_t num;
+} PCPS_IO_RSRC;
+
+
+// The structure below describes a bus memory resource
+// used by a clock.
+
+typedef struct
+{
+ #if defined( MBG_TGT_BSD )
+ BSD_RSRC_INFO bsd;
+ #endif
+ MBG_MEM_ADDR start;
+ ulong len;
+
+} PCPS_MEM_RSRC;
+
+
+
+// The structure below describes a bus IRQ resource
+// used by a clock.
+
+typedef struct
+{
+ #if defined( MBG_TGT_BSD )
+ BSD_RSRC_INFO bsd;
+ #endif
+ ushort num;
+
+} PCPS_IRQ_RSRC;
+
+
+
+// The max number of bus memory resources used by a device.
+#define N_PCPS_MEM_RSRC 2
+
+// The max number of bus memory and I/O resources used by a device.
+#define MAX_PCPS_RSRC ( N_PCPS_MEM_RSRC + N_PCPS_PORT_RSRC )
+
+typedef struct
+{
+ int num_rsrc_io;
+ int num_rsrc_mem;
+ int num_rsrc_irq;
+ PCPS_IO_RSRC port[N_PCPS_PORT_RSRC];
+ PCPS_MEM_RSRC mem[N_PCPS_MEM_RSRC];
+ PCPS_IRQ_RSRC irq;
+} PCPS_RSRC_INFO;
+
+
+
+#if _PCPS_USE_USB
+
+ typedef struct
+ {
+ uint8_t addr;
+ uint16_t max_packet_size;
+ } PCPS_USB_EP;
+
+
+ #if defined( MBG_TGT_LINUX )
+
+ // definitions used to control the cyclic USB read thread
+
+ #if _PCPS_USE_LINUX_KTHREAD
+
+ // use kthread_run() / kthread_stop()
+ typedef struct task_struct *PCPS_THREAD_INFO;
+
+ #else
+
+ // use kernel_thread() / daemonize() / kill_proc()
+ typedef struct
+ {
+ pid_t pid;
+ char name[17]; // 16 chars as supported by the kernel, plus trailing 0
+ struct completion exit;
+ } PCPS_THREAD_INFO;
+
+ #endif // _PCPS_USE_LINUX_KTHREAD
+
+ #endif // defined( MBG_TGT_LINUX )
+
+#endif // _PCPS_USE_USB
+
+
+
+typedef union
+{
+ struct
+ {
+ PCI_ASIC asic;
+ PCPS_TIME_STAMP tstamp;
+ } pex8311;
+
+ struct
+ {
+ PCI_ASIC asic;
+ uint8_t b[256 - sizeof( PCI_ASIC ) ];
+ PCPS_TIME_STAMP ucap[2];
+ PCPS_TIME_STAMP tstamp;
+ } mbgpex;
+
+} PCPS_MM_LAYOUT;
+
+
+
+typedef struct PCPS_DDEV_s
+{
+ // the device info data
+ PCPS_DEV dev;
+
+ // the read function to be used to access the clock
+ short (*read)( struct PCPS_DDEV_s *pddev, uchar cmd,
+ uchar FAR *buffer, uchar count );
+
+ PCPS_IO_ADDR_MAPPED status_port;
+ PCPS_IO_ADDR_MAPPED irq_enb_disb_port;
+ PCPS_IO_ADDR_MAPPED irq_flag_port;
+ PCPS_IO_ADDR_MAPPED irq_ack_port;
+ uint32_t irq_enb_mask;
+ uint32_t irq_disb_mask;
+ uint32_t irq_flag_mask;
+ uint32_t irq_ack_mask;
+
+ PCI_ASIC_VERSION raw_asic_version;
+ PCI_ASIC_VERSION asic_version;
+ PCI_ASIC_FEATURES asic_features;
+ PCPS_RSRC_INFO rsrc_info;
+
+ MBG_PC_CYCLES acc_cycles;
+
+ #if defined( MBG_SYS_MUTEX )
+ MBG_SYS_MUTEX dev_mutex;
+ #endif
+
+ PCPS_MM_LAYOUT FAR *mm_addr;
+ volatile PCPS_TIME_STAMP FAR *mm_tstamp_addr;
+
+ #if defined( MBG_SPINLOCK )
+ MBG_SPINLOCK mm_lock;
+ MBG_SPINLOCK irq_lock;
+ #endif
+
+ // The flag below holds IRQ information, e.g. whether the device's
+ // IRQ is possibly unsafe, and whether IRQ has been enabled on the device.
+ PCPS_IRQ_STAT_INFO irq_stat_info;
+
+ RECEIVER_INFO ri;
+
+ #if _PCPS_USE_USB
+ int n_usb_ep; // number of endpoints supp. by the device
+ PCPS_USB_EP ep[MBGUSB_MAX_ENDPOINTS];
+ uint8_t usb_20_mode;
+ #endif
+
+ #if defined( MBG_TGT_WIN32 )
+ _pcps_ddev_data_win
+ #endif
+
+ #if defined( MBG_TGT_LINUX )
+ atomic_t connected;
+ atomic_t access_in_progress;
+ atomic_t data_avail;
+ unsigned long jiffies_at_irq;
+ struct fasync_struct *fasyncptr;
+ PCPS_TIME t;
+
+ #if NEW_WAIT_QUEUE
+ wait_queue_head_t wait_queue;
+ #else
+ struct wait_queue *wait_queue;
+ #endif
+
+ dev_t lx_dev;
+ atomic_t open_count;
+
+ #if _PCPS_USE_LINUX_CHRDEV
+ struct cdev cdev;
+ #elif _PCPS_USE_LINUX_MISC_DEV
+ struct miscdevice mdev;
+ #endif
+
+ #if _PCPS_USE_USB
+ struct usb_device *udev;
+ struct usb_interface *intf;
+ PCPS_THREAD_INFO usb_read_thread;
+ struct semaphore sem_usb_cyclic;
+ #endif
+ #endif
+
+ #if defined( MBG_TGT_BSD )
+ int connected;
+ int open_count;
+ #endif
+
+ #if _PCPS_USE_RSRCMGR
+ #if defined( MBG_TGT_OS2 )
+ PCPS_HDEV hDev;
+ RSRC_LIST rsrc;
+ #endif
+ #endif
+
+} PCPS_DDEV;
+
+
+
+/* The PCI vendor ID and device ID numbers are used to detect a
+ * PCI clock in a system and query which resources have been
+ * assigned by the BIOS.
+ * (PCI vendor ID and PCI device IDs are defined in PCPSDEFS.H)
+ */
+
+/* the number of address lines decoded by a PCI clock */
+#define PCPS_DECODE_WIDTH_PCI 16
+
+
+/* ------ definitions used with MCA clocks -------------------------- */
+
+/* The MCA adapter ID number is used to detect a MCA clock in a
+ * system and query which resources have been assigned by the
+ * system's POS (programmable option select).
+ */
+
+/* MCA Adapter ID numbers */
+#define MCA_ID_PS31 0x6AAC /* assigned by IBM */
+#define MCA_ID_PS31_OLD 0x6303 /* assigned by Meinberg, used with */
+ /* the first series of PS31 boards */
+
+/* the total number of ports acquired by a MCA clock */
+#define PCPS_NUM_PORTS_MCA 16
+
+/* the number of address lines decoded by a MCA clock */
+#define PCPS_DECODE_WIDTH_MCA 16
+
+
+/* ------ definitions used with ISA clocks -------------------------- */
+
+/* A board ID for the newer clocks with ISA bus. The number can
+ * be read at port_base+2 (low byte) and port_base+3 (high byte)
+ * of ISA clocks. This ID number matches the MCA adapter ID
+ * defined above and is not available on PC31 clocks.
+ */
+#define ISA_ID_PCPS MCA_ID_PS31
+
+/* The default port base address for ISA clocks.
+ * Some programs assume a default port for an ISA clock,
+ * others do not but require a cmd line parameter.
+ */
+#define PCPS_DEFAULT_PORT 0x0300
+
+/* the total number of ports acquired by a ISA clock */
+#define PCPS_NUM_PORTS_ISA 4
+
+/* the number of address lines decoded by a ISA clock */
+#define PCPS_DECODE_WIDTH_ISA 10
+
+
+/* ------ common definitions -------------------------- */
+
+_ext PCPS_DEV_TYPE pcps_dev_type[N_PCPS_DEV_TYPE]
+#ifdef _DO_INIT
+= {
+ { PCPS_TYPE_PC31, "PC31", 0, PCPS_REF_DCF, PCPS_BUS_ISA },
+ { PCPS_TYPE_PS31_OLD, "PS31", MCA_ID_PS31_OLD, PCPS_REF_DCF, PCPS_BUS_MCA },
+ { PCPS_TYPE_PS31, "PS31", MCA_ID_PS31, PCPS_REF_DCF, PCPS_BUS_MCA },
+ { PCPS_TYPE_PC32, "PC32", ISA_ID_PCPS, PCPS_REF_DCF, PCPS_BUS_ISA },
+ { PCPS_TYPE_PCI32, "PCI32", PCI_DEV_PCI32, PCPS_REF_DCF, PCPS_BUS_PCI_S5933 },
+ { PCPS_TYPE_GPS167PC, "GPS167PC", 0, PCPS_REF_GPS, PCPS_BUS_ISA },
+ { PCPS_TYPE_GPS167PCI, "GPS167PCI", PCI_DEV_GPS167PCI, PCPS_REF_GPS, PCPS_BUS_PCI_S5933 },
+ { PCPS_TYPE_PCI509, "PCI509", PCI_DEV_PCI509, PCPS_REF_DCF, PCPS_BUS_PCI_S5920 },
+ { PCPS_TYPE_GPS168PCI, "GPS168PCI", PCI_DEV_GPS168PCI, PCPS_REF_GPS, PCPS_BUS_PCI_S5920 },
+ { PCPS_TYPE_PCI510, "PCI510", PCI_DEV_PCI510, PCPS_REF_DCF, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_GPS169PCI, "GPS169PCI", PCI_DEV_GPS169PCI, PCPS_REF_GPS, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_TCR510PCI, "TCR510PCI", PCI_DEV_TCR510PCI, PCPS_REF_IRIG, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_TCR167PCI, "TCR167PCI", PCI_DEV_TCR167PCI, PCPS_REF_IRIG, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_GPS170PCI, "GPS170PCI", PCI_DEV_GPS170PCI, PCPS_REF_GPS, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_PCI511, "PCI511", PCI_DEV_PCI511, PCPS_REF_DCF, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_TCR511PCI, "TCR511PCI", PCI_DEV_TCR511PCI, PCPS_REF_IRIG, PCPS_BUS_PCI_ASIC },
+ { PCPS_TYPE_PEX511, "PEX511", PCI_DEV_PEX511, PCPS_REF_DCF, PCPS_BUS_PCI_PEX8311 },
+ { PCPS_TYPE_TCR511PEX, "TCR511PEX", PCI_DEV_TCR511PEX, PCPS_REF_IRIG, PCPS_BUS_PCI_PEX8311 },
+ { PCPS_TYPE_GPS170PEX, "GPS170PEX", PCI_DEV_GPS170PEX, PCPS_REF_GPS, PCPS_BUS_PCI_PEX8311 },
+ { PCPS_TYPE_USB5131, "USB5131", USB_DEV_USB5131, PCPS_REF_DCF, PCPS_BUS_USB },
+ { PCPS_TYPE_TCR51USB, "TCR51USB", USB_DEV_TCR51USB, PCPS_REF_IRIG, PCPS_BUS_USB },
+ { PCPS_TYPE_MSF51USB, "MSF51USB", USB_DEV_MSF51USB, PCPS_REF_MSF, PCPS_BUS_USB },
+ { PCPS_TYPE_PTP270PEX, "PTP270PEX", PCI_DEV_PTP270PEX, PCPS_REF_PTP, PCPS_BUS_PCI_PEX8311 },
+ { PCPS_TYPE_FRC511PEX, "FRC511PEX", PCI_DEV_FRC511PEX, PCPS_REF_FRC, PCPS_BUS_PCI_PEX8311 },
+ { PCPS_TYPE_TCR170PEX, "TCR170PEX", PCI_DEV_TCR170PEX, PCPS_REF_IRIG, PCPS_BUS_PCI_PEX8311 },
+ { PCPS_TYPE_WWVB51USB, "WWVB51USB", USB_DEV_WWVB51USB, PCPS_REF_WWVB, PCPS_BUS_USB },
+ { PCPS_TYPE_GPS180PEX, "GPS180PEX", PCI_DEV_GPS180PEX, PCPS_REF_GPS, PCPS_BUS_PCI_MBGPEX },
+ { PCPS_TYPE_TCR180PEX, "TCR180PEX", PCI_DEV_TCR180PEX, PCPS_REF_IRIG, PCPS_BUS_PCI_MBGPEX },
+ { PCPS_TYPE_DCF600USB, "DCF600USB", USB_DEV_DCF600USB, PCPS_REF_DCF, PCPS_BUS_USB }
+
+ // If a new device is added here, don't forget to add it also
+ // to the Windows .inf file of supported PCI an USB devices,
+ // and in case of USB to the Linux driver file mbgdrvr.c.
+}
+#endif
+;
+
+
+#if !defined( PCPS_MAX_DDEVS )
+ #define PCPS_MAX_DDEVS 4
+#endif
+
+#if !defined( PCPS_MAX_ISA_CARDS )
+ #define PCPS_MAX_ISA_CARDS PCPS_MAX_DDEVS // the number of ISA cards supported
+#endif
+
+_ext int pcps_isa_ports[PCPS_MAX_ISA_CARDS + 1];
+
+#if _PCPS_STATIC_DEV_LIST
+ _ext PCPS_DDEV pcps_ddev[PCPS_MAX_DDEVS];
+ _ext int n_ddevs;
+#endif
+
+#if defined( MBG_TGT_DOS ) || defined( MBG_TGT_NETWARE ) //##++
+ _ext int curr_ddev_num;
+ _ext PCPS_DDEV *curr_ddev
+ #ifdef _DO_INIT
+ = &pcps_ddev[0]
+ #endif
+ ;
+#endif
+
+/* the first characters of a valid EPROM ID */
+
+_ext const char *fw_id_ref[]
+#ifdef _DO_INIT
+ = {
+ "PC3", // PC31, PS31, PC32
+ "PCI", // PCI32, PCI509, PCI510, PCI511
+ "GPS", // GPS167PC, GPS167PCI, GPS168PCI, GPS169PCI, GPS170PCI, GPS170PEX, GPS180PEX
+ "TCR", // TCR510PCI, TCR167PCI, TCR511PCI, TCR511PEX, TCR51USB, TCR170PEX, TCR180PEX
+ "PEX", // PEX511
+ "USB", // USB5131
+ "MSF", // MSF51USB
+ "WWVB", // WWVB51USB
+ "DCF", // DCF600USB
+ NULL
+ }
+#endif
+;
+
+
+// The macros below are used to distinguish ISA cards:
+
+#define fw_id_ref_pcps fw_id_ref[0]
+#define fw_id_ref_gps fw_id_ref[2]
+
+
+
+// The macros below accept a (PCPS_DDEV *) for easy access
+// to the information stored in PCPS_DDEV structures.
+
+// Access device type information:
+#define _pcps_ddev_type_num( _p ) _pcps_type_num( &(_p)->dev )
+#define _pcps_ddev_type_name( _p ) _pcps_type_name( &(_p)->dev )
+#define _pcps_ddev_dev_id( _p ) _pcps_dev_id( &(_p)->dev )
+#define _pcps_ddev_ref_type( _p ) _pcps_ref_type( &(_p)->dev )
+#define _pcps_ddev_bus_flags( _p ) _pcps_bus_flags( &(_p)->dev )
+
+// Query device type features:
+#define _pcps_ddev_is_gps( _p ) _pcps_is_gps( &(_p)->dev )
+#define _pcps_ddev_is_dcf( _p ) _pcps_is_dcf( &(_p)->dev )
+#define _pcps_ddev_is_msf( _p ) _pcps_is_msf( &(_p)->dev )
+#define _pcps_ddev_is_wwvb( _p ) _pcps_is_wwvb( &(_p)->dev )
+#define _pcps_ddev_is_irig_rx( _p ) _pcps_is_irig_rx( &(_p)->dev )
+#define _pcps_ddev_is_ptp( _p ) _pcps_is_ptp( &(_p)->dev )
+#define _pcps_ddev_is_frc( _p ) _pcps_is_frc( &(_p)->dev )
+
+#define _pcps_ddev_is_lwr( _p ) _pcps_is_lwr( &(_p)->dev )
+
+#define _pcps_ddev_is_isa( _p ) _pcps_is_isa( &(_p)->dev )
+#define _pcps_ddev_is_mca( _p ) _pcps_is_mca( &(_p)->dev )
+#define _pcps_ddev_is_pci( _p ) _pcps_is_pci( &(_p)->dev )
+#define _pcps_ddev_is_usb( _p ) _pcps_is_usb( &(_p)->dev )
+
+#define _pcps_ddev_is_pci_s5933( _p ) _pcps_is_pci_s5933( &(_p)->dev )
+#define _pcps_ddev_is_pci_s5920( _p ) _pcps_is_pci_s5920( &(_p)->dev )
+#define _pcps_ddev_is_pci_amcc( _p ) _pcps_is_pci_amcc( &(_p)->dev )
+#define _pcps_ddev_is_pci_asic( _p ) _pcps_is_pci_asic( &(_p)->dev )
+#define _pcps_ddev_is_pci_pex8311( _p ) _pcps_is_pci_pex8311( &(_p)->dev )
+#define _pcps_ddev_is_pci_mbgpex( _p ) _pcps_is_pci_mbgpex( &(_p)->dev )
+
+
+// Access device configuration information:
+#define _pcps_ddev_bus_num( _p ) _pcps_bus_num( &(_p)->dev )
+#define _pcps_ddev_slot_num( _p ) _pcps_slot_num( &(_p)->dev )
+
+#define _pcps_ddev_port_rsrc( _p, _n ) _pcps_port_rsrc( &(_p)->dev, _n )
+#define _pcps_ddev_port_base( _p, _n ) _pcps_port_base( &(_p)->dev, _n )
+#define _pcps_ddev_io_rsrc( _p, _n ) ( (_p)->rsrc_info.port[_n] )
+#define _pcps_ddev_io_base_mapped( _p, _n ) ( _pcps_ddev_io_rsrc( _p, _n ).base_mapped )
+#define _pcps_ddev_irq_num( _p ) _pcps_irq_num( &(_p)->dev )
+#define _pcps_ddev_timeout_clk( _p ) _pcps_timeout_clk( &(_p)->dev )
+
+#define _pcps_ddev_fw_rev_num( _p ) _pcps_fw_rev_num( &(_p)->dev )
+#define _pcps_ddev_features( _p ) _pcps_features( &(_p)->dev )
+#define _pcps_ddev_fw_id( _p ) _pcps_fw_id( &(_p)->dev )
+#define _pcps_ddev_sernum( _p ) _pcps_sernum( &(_p)->dev )
+#define _pcps_ddev_raw_asic_version( _p ) ( (_p)->raw_asic_version )
+#define _pcps_ddev_asic_version( _p ) ( (_p)->asic_version )
+
+// The macros below handle the clock device's err_flags.
+#define _pcps_ddev_set_err_flags( _p, _msk ) \
+ _pcps_set_err_flags( &(_p)->dev, _msk )
+
+#define _pcps_ddev_clr_err_flags( _p, _msk ) \
+ _pcps_clr_err_flags( &(_p)->dev, _msk )
+
+#define _pcps_ddev_chk_err_flags( _p, _msk ) \
+ _pcps_chk_err_flags( &(_p)->dev, _msk )
+
+
+// Query whether a special feature is supported:
+#define _pcps_ddev_has_feature( _p, _f ) _pcps_has_feature( &(_p)->dev, _f )
+#define _pcps_ddev_can_set_time( _p ) _pcps_can_set_time( &(_p)->dev )
+#define _pcps_ddev_has_serial( _p ) _pcps_has_serial( &(_p)->dev )
+#define _pcps_ddev_has_sync_time( _p ) _pcps_has_sync_time( &(_p)->dev )
+#define _pcps_ddev_has_ident( _p ) _pcps_has_ident( &(_p)->dev )
+#define _pcps_ddev_has_utc_offs( _p ) _pcps_has_utc_offs( &(_p)->dev )
+#define _pcps_ddev_has_hr_time( _p ) _pcps_has_hr_time( &(_p)->dev )
+#define _pcps_ddev_has_sernum( _p ) _pcps_has_sernum( &(_p)->dev )
+#define _pcps_ddev_has_cab_len( _p ) _pcps_has_cab_len( &(_p)->dev )
+#define _pcps_ddev_has_tzdl( _p ) _pcps_has_tzdl( &(_p)->dev )
+#define _pcps_ddev_has_pcps_tzdl( _p ) _pcps_has_pcps_tzdl( &(_p)->dev )
+#define _pcps_ddev_has_tzcode( _p ) _pcps_has_tzcode( &(_p)->dev )
+#define _pcps_ddev_has_tz( _p ) _pcps_has_tz( &(_p)->dev )
+// The next one is supported only with a certain GPS firmware version:
+#define _pcps_ddev_has_event_time( _p ) _pcps_has_event_time( &(_p)->dev )
+#define _pcps_ddev_has_receiver_info( _p ) _pcps_has_receiver_info( &(_p)->dev )
+#define _pcps_ddev_can_clr_ucap_buff( _p ) _pcps_can_clr_ucap_buff( &(_p)->dev )
+#define _pcps_ddev_has_ucap( _p ) _pcps_has_ucap( &(_p)->dev )
+#define _pcps_ddev_has_irig_tx( _p ) _pcps_has_irig_tx( &(_p)->dev )
+
+// The macro below determines whether a DCF77 clock
+// supports a higher baud rate than standard
+#define _pcps_ddev_has_serial_hs( _p ) \
+ _pcps_has_serial_hs( &(_p)->dev )
+
+
+#define _pcps_ddev_has_signal( _p ) \
+ _pcps_has_signal( &(_p)->dev )
+
+#define _pcps_ddev_has_mod( _p ) \
+ _pcps_has_mod( &(_p)->dev )
+
+
+#define _pcps_ddev_has_irig( _p ) \
+ _pcps_has_irig( &(_p)->dev )
+
+#define _pcps_ddev_has_irig_ctrl_bits( _p ) \
+ _pcps_has_irig_ctrl_bits( &(_p)->dev )
+
+#define _pcps_ddev_has_irig_time( _p ) \
+ _pcps_has_irig_time( &(_p)->dev )
+
+#define _pcps_ddev_has_raw_irig_data( _p ) \
+ _pcps_has_raw_irig_data( &(_p)->dev )
+
+#define _pcps_ddev_has_ref_offs( _p ) \
+ _pcps_has_ref_offs( &(_p)->dev )
+
+#define _pcps_ddev_has_opt_flags( _p ) \
+ _pcps_has_opt_flags( &(_p)->dev )
+
+#define _pcps_ddev_has_gps_data( _p ) \
+ _pcps_has_gps_data( &(_p)->dev )
+
+#define _pcps_ddev_has_gps_data_16( _p ) \
+ _pcps_has_gps_data_16( &(_p)->dev )
+
+#define _pcps_ddev_has_synth( _p ) \
+ _pcps_has_synth( &(_p)->dev )
+
+#define _pcps_ddev_has_generic_io( _p ) \
+ _pcps_has_generic_io( &(_p)->dev )
+
+#define _pcps_ddev_has_time_scale( _p ) \
+ _pcps_has_time_scale( &(_p)->dev )
+
+#define _pcps_ddev_has_utc_parm( _p ) \
+ _pcps_has_utc_parm( &(_p)->dev )
+
+#define _pcps_ddev_has_asic_version( _p ) \
+ _pcps_has_asic_version( &(_p)->dev )
+
+#define _pcps_ddev_has_asic_features( _p ) \
+ _pcps_has_asic_features( &(_p)->dev )
+
+#define _pcps_ddev_has_fast_hr_timestamp( _p ) \
+ _pcps_has_fast_hr_timestamp( &(_p)->dev )
+
+#define _pcps_ddev_has_lan_intf( _p ) \
+ _pcps_has_lan_intf( &(_p)->dev )
+
+#define _pcps_ddev_has_ptp( _p ) \
+ _pcps_has_ptp( &(_p)->dev )
+
+#define _pcps_ddev_has_ptp_unicast( _p ) \
+ _pcps_has_ri_ptp_unicast( &(_p)->ri )
+
+
+// The macros below simplify read/write access to the clocks.
+
+// Call the device's read function to write the command byte _cmd
+// and read _n bytes to buffer _s.
+#if !defined( _pcps_read )
+ #define _pcps_read( _pddev, _cmd, _p, _n ) \
+ ( (_pddev)->read( _pddev, (_cmd), (uchar FAR *)(_p), (_n) ) )
+#endif
+
+// Write a byte _b to the radio clock device. This is typically
+// done by just writing the command byte from inside the read function.
+#if !defined( _pcps_write_byte )
+ #define _pcps_write_byte( _pddev, _b ) \
+ _pcps_read( (_pddev), (_b), NULL, 0 )
+#endif
+
+// write a command plus the contents of a data buffer to the device.
+// This is typically implemented as a function which uses the
+// _pcps_write_byte() macro repeatedly.
+#if !defined( _pcps_write )
+ #define _pcps_write( _pddev, _cmd, _p, _n ) \
+ pcps_write( (_pddev), (_cmd), (uchar FAR *)(_p), (_n) )
+#endif
+
+// Read data structures which exceed PCPS_FIFO_SIZE bytes.
+// This can't be handled in a single read cycle and due to limitations
+// of the clock's microprocessor these calls can up to 20 milliseconds.
+// Currently these function is only used to read GPS specific data
+// from GPS clocks.
+#define _pcps_read_gps( _pddev, _cmd, _p, _n ) \
+ pcps_read_gps( (_pddev), (_cmd), (uchar FAR *) (_p), (_n) )
+
+// The write function opposite to the read function above.
+#define _pcps_write_gps( _pddev, _cmd, _p, _n ) \
+ pcps_write_gps( (_pddev), (_cmd), (uchar FAR *) (_p), (_n) )
+
+
+
+// The macros below simplify reading/writing typed variables by
+// determining the size automatically from the type of the variable.
+
+// Read data from the radio clock board to variable _s.
+// The number of bytes to read is determined by the size
+// of _s. The accepted type of _s depends on the _cmd code.
+#define _pcps_read_var( _pddev, _cmd, _s ) \
+ _pcps_read( (_pddev), (_cmd), &(_s), sizeof( (_s) ) )
+
+// Write data from variable _s to the radio clock board .
+// The number of bytes to write is determined by the size
+// of _s. The accepted type of _s depends on the _cmd code.
+#define _pcps_write_var( _pddev, _cmd, _s ) \
+ _pcps_write( (_pddev), (_cmd), &(_s), sizeof( (_s) ) )
+
+
+// Read data structures which exceed PCPS_FIFO_SIZE bytes.
+// This can't be handled in a single read cycle and due to limitations
+// of the clock's microprocessor these calls can up to 20 milliseconds.
+// Currently these function is only used to read GPS specific data
+// from GPS clocks.
+#define _pcps_read_gps_var( _pddev, _cmd, _s ) \
+ _pcps_read_gps( (_pddev), (_cmd), &(_s), sizeof( (_s) ) )
+
+// The write function opposite to the read function above.
+#define _pcps_write_gps_var( _pddev, _cmd, _s ) \
+ _pcps_write_gps( (_pddev), (_cmd), &(_s), sizeof( (_s) ) )
+
+
+// Generate a hardware reset on the radio clock board. This
+// macro should be used VERY carefully and should be avoided
+// if possible.
+#define _pcps_force_reset( _pddev ) \
+ _pcps_write_byte( (_pddev), PCPS_FORCE_RESET )
+
+
+// The macro below reads a radio clock's status port which
+// includes the BUSY flag and the modulation signal of DCF77
+// clocks. The macro takes a (PCPS_DDEV *) as argument.
+#define _pcps_ddev_read_status_port( _d ) \
+ _mbg_inp8( (_d), 0, (_d)->status_port )
+
+#define _pcps_ddev_status_busy( _d ) \
+ ( _pcps_ddev_read_status_port( pddev ) & PCPS_ST_BUSY )
+
+
+// The macro below checks whether a workaround is required to get/set
+// IRIG cfg from a GPS169PCI with IRIG output and early firmware version
+// This is handled in mbgdevio.c for direct access environments, and in
+// macioctl.h for kernel device drivers.
+#define _pcps_ddev_requires_irig_workaround( _d ) \
+ ( ( _pcps_ddev_type_num( _d ) == PCPS_TYPE_GPS169PCI ) && \
+ ( _pcps_ddev_fw_rev_num( _d ) < REV_HAS_GPS_DATA_16_GPS169PCI ) )
+
+
+#if _PCPS_USE_USB
+
+ #if !defined( MBGUSB_TIMEOUT_SEND_MS )
+ #define MBGUSB_TIMEOUT_SEND_MS 500 // [ms]
+ #endif
+
+ #if !defined( MBGUSB_TIMEOUT_RECEIVE_MS )
+ #define MBGUSB_TIMEOUT_RECEIVE_MS 500 // [ms]
+ #endif
+
+ #if !defined( MBGUSB_TIMEOUT_RECEIVE_CYCLIC_MS )
+ // The USB read function may block until a packet has been received, or a
+ // receive timeout has occurred. The cyclic USB read function has an overall
+ // timeout of more than 1 second. In order to increase responsiveness we use
+ // by default a shorter timeout interval plus some retries, if required.
+ //
+ // For some target environments it may be preferable to use only one
+ // full timeout interval, so this setting can be overridden if required.
+ #if !defined( _PCPS_USB_FULL_CYCLIC_INTV )
+ #define _PCPS_USB_FULL_CYCLIC_INTV 1
+ #endif
+
+ #if _PCPS_USB_FULL_CYCLIC_INTV
+ #define MBGUSB_TIMEOUT_RECEIVE_CYCLIC_MS 1200
+ #else
+ #define MBGUSB_TIMEOUT_RECEIVE_CYCLIC_MS 50
+ #endif
+ #endif
+
+
+ #if !defined( _pcps_ms_to_usb_timeout )
+ #define _pcps_ms_to_usb_timeout( _ms ) (_ms)
+ #endif
+
+
+ #if !defined( MBGUSB_TIMEOUT_SEND )
+ #define MBGUSB_TIMEOUT_SEND _pcps_ms_to_usb_timeout( MBGUSB_TIMEOUT_SEND_MS )
+ #endif
+
+ #if !defined( MBGUSB_TIMEOUT_RECEIVE )
+ #define MBGUSB_TIMEOUT_RECEIVE _pcps_ms_to_usb_timeout( MBGUSB_TIMEOUT_RECEIVE_MS )
+ #endif
+
+ #if !defined( MBGUSB_TIMEOUT_RECEIVE_CYCLIC )
+ #define MBGUSB_TIMEOUT_RECEIVE_CYCLIC _pcps_ms_to_usb_timeout( MBGUSB_TIMEOUT_RECEIVE_CYCLIC_MS )
+ #endif
+
+
+ #if defined( MBG_TGT_WIN32_PNP )
+
+ #define _pcps_usb_write_ep_tmo( _d, _p, _sz, _ep_idx, _tmo, _irp ) \
+ pcps_usb_transfer( _d, _ep_idx, _p, _sz, 1, _tmo, _irp )
+
+ #define _pcps_usb_read_ep_tmo( _d, _p, _sz, _ep_idx, _tmo, _irp ) \
+ pcps_usb_transfer( _d, _ep_idx, _p, _sz, 0, _tmo, _irp )
+
+ #define _pcps_usb_write( _d, _p, _sz ) \
+ _pcps_usb_write_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_OUT, MBGUSB_TIMEOUT_SEND, (_d)->irp )
+
+ #define _pcps_usb_read( _d, _p, _sz ) \
+ _pcps_usb_read_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_IN, MBGUSB_TIMEOUT_RECEIVE, (_d)->irp )
+
+ #define _pcps_usb_read_cyclic( _d, _p, _sz, _irp ) \
+ _pcps_usb_read_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_IN_CYCLIC, MBGUSB_TIMEOUT_RECEIVE_CYCLIC, _irp )
+
+ #define _pcps_usb_read_var_cyclic( _d, _p, _irp ) \
+ _pcps_usb_read_cyclic( _d, _p, sizeof( *(_p) ), _irp )
+
+ #elif defined( MBG_TGT_LINUX )
+
+ #define _pcps_usb_write_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \
+ usb_bulk_msg( (_d)->udev, \
+ usb_sndbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \
+ _p, _sz, &actual_count, _tmo )
+
+ #define _pcps_usb_read_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \
+ usb_bulk_msg( (_d)->udev, \
+ usb_rcvbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \
+ _p, _sz, &actual_count, _tmo )
+
+ #define _pcps_usb_write( _d, _p, _sz ) \
+ _pcps_usb_write_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_OUT, MBGUSB_TIMEOUT_SEND )
+
+ #define _pcps_usb_read( _d, _p, _sz ) \
+ _pcps_usb_read_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_IN, MBGUSB_TIMEOUT_RECEIVE )
+
+ #define _pcps_usb_read_cyclic( _d, _p, _sz ) \
+ _pcps_usb_read_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_IN_CYCLIC, MBGUSB_TIMEOUT_RECEIVE_CYCLIC )
+
+ #define _pcps_usb_read_var_cyclic( _d, _p ) \
+ _pcps_usb_read_cyclic( _d, _p, sizeof( *(_p) ) )
+
+ #endif // target specific definitions
+
+
+ #define _pcps_usb_write_var( _d, _p ) \
+ _pcps_usb_write( _d, _p, sizeof( *(_p) ) )
+
+ #define _pcps_usb_read_var( _d, _p ) \
+ _pcps_usb_read( _d, _p, sizeof( *(_p) ) )
+
+#endif
+
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PCPS_DDEV *(*PCPS_DDEV_ALLOC_FNC)( void );
+typedef void (*PCPS_DDEV_CLEANUP_FNC)( PCPS_DDEV * );
+typedef int (*PCPS_DDEV_REGISTER_FNC)( PCPS_DDEV * );
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ short pcps_write( PCPS_DDEV *pddev, uint8_t cmd, const void FAR *buffer, uint8_t count ) ;
+ short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, const void FAR *in_buff, uint8_t in_cnt, void FAR *out_buff, uint8_t out_cnt ) ;
+ short pcps_read_gps( PCPS_DDEV *pddev, uint8_t data_type, void FAR *buffer, uint16_t buffer_size ) ;
+ short pcps_write_gps( PCPS_DDEV *pddev, uint8_t data_type, const void FAR *buffer, uint16_t buffer_size ) ;
+ short pcps_get_fw_id( PCPS_DDEV *pddev, PCPS_ID_STR FAR fw_id ) ;
+ short pcps_check_id( PCPS_DDEV *pddev, const char FAR *ref ) ;
+ short pcps_get_rev_num( char FAR *idstr ) ;
+ int pcps_read_sernum( PCPS_DDEV *pddev ) ;
+ int pcps_rsrc_claim( PCPS_DDEV *pddev ) ;
+ void pcps_rsrc_release( PCPS_DDEV *pddev ) ;
+ ushort pcps_port_from_pos( ushort pos ) ;
+ uchar pcps_pos_from_port( ushort port ) ;
+ PCPS_DEV_TYPE *pcps_get_dev_type( int bus_mask, ushort dev_id ) ;
+ PCPS_DDEV *pcps_alloc_ddev( void ) ;
+ void pcps_free_ddev( PCPS_DDEV *pddev ) ;
+ int pcps_add_rsrc_io( PCPS_DDEV *pddev, ulong base, ulong num ) ;
+ int pcps_add_rsrc_mem( PCPS_DDEV *pddev, MBG_MEM_ADDR start, ulong len ) ;
+ int pcps_add_rsrc_irq( PCPS_DDEV *pddev, int16_t irq_num ) ;
+ int pcps_init_ddev( PCPS_DDEV *pddev, int bus_flags, ushort dev_id ) ;
+ int pcps_start_device( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) ;
+ void pcps_cleanup_device( PCPS_DDEV *pddev ) ;
+ void pcps_setup_and_start_pci_dev( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) ;
+ void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, PCPS_DDEV_CLEANUP_FNC cleanup_fnc, ushort vendor_id, PCPS_DEV_TYPE dev_type[], int n_dev_types ) ;
+ void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, PCPS_DDEV_CLEANUP_FNC cleanup_fnc, PCPS_DDEV_REGISTER_FNC register_fnc, int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ;
+ void _MBG_INIT_CODE_ATTR pcps_detect_clocks_alloc( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, PCPS_DDEV_CLEANUP_FNC cleanup_fnc, int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ;
+ void _MBG_INIT_CODE_ATTR pcps_detect_clocks( int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+// We have used native alignment here, so no need to undo alignment at this place.
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PCPSDRVR_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h
new file mode 100755
index 0000000..7bb2b1f
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h
@@ -0,0 +1,212 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsirq.h 1.7 2008/12/05 12:20:36 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * OS independent definitions used to handle interrupts from
+ * Meinberg radio clock devices.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsirq.h $
+ * Revision 1.7 2008/12/05 12:20:36 martin
+ * Protect HW access to enable/disable IRQ by mutex.
+ * Support mapped I/O resources.
+ * Changes due to renamed library macros.
+ * Revision 1.6 2007/07/20 10:16:52 martin
+ * Reworte some IRQ macros.
+ * Moved some AMCC specific definitions to amccdefs.h.
+ * Removed obsolete code.
+ * Revision 1.5 2007/06/06 11:15:27Z martin
+ * Fixed syntax of some macros.
+ * Revision 1.4 2007/03/01 16:15:34Z martin
+ * Use generic port I/O macros.
+ * Revision 1.3 2004/11/09 14:44:21 martin
+ * Use C99 fixed-size data types if required.
+ * Revision 1.2 2003/04/02 07:51:37 martin
+ * Added support for devices with PCI_ASIC.
+ * Revision 1.1 2001/03/28 09:36:43Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCPSIRQ_H
+#define _PCPSIRQ_H
+
+
+#include <pcpsdrvr.h>
+#include <amccdefs.h>
+#include <pci_asic.h>
+
+
+#define _set_port_bit( _d, _adr, _msk ) \
+ _mbg_outp8( (_d), _adr, _mbg_inp8( (_d), _adr ) | (_msk) )
+
+#define _clear_port_bit( _d, _adr, _msk ) \
+ _mbg_outp8( (_d), _adr, _mbg_inp8( (_d), _adr ) & ~(_msk) )
+
+
+// Each of the macros below expects a parameter _d which is
+// a pointer to the PCPS_DDEV structure which represents the
+// hardware device.
+
+// The macros below generate code only if MCA support is enabled.
+
+#if _PCPS_USE_MCA
+ #define MCIC_IRQ 0x04
+ #define _mcic_enb_reg( _r ) ( (_r) + 0x0A )
+ #define _mcic_ack_reg( _r ) ( (_r) + 0x0B )
+
+ // No MCA dependent local variables required, and no
+ // MCA dependent interrupt flag to check.
+
+ // In ISR function, pass acknowledge to the MCA
+ // interface chip.
+ #define _pcps_ddev_ack_irq_mca( _d ) \
+ if ( _pcps_ddev_is_mca( _d ) ) \
+ { \
+ PCPS_IO_ADDR_MAPPED port = _mcic_ack_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \
+ _set_port_bit( (_d), port, MCIC_IRQ ); \
+ }
+
+ // In IRQ init function, enable IRQ on the
+ // interface chip.
+ #define _pcps_ddev_enb_irq_mca( _d ) \
+ if ( _pcps_ddev_is_mca( _d ) ) \
+ { \
+ uint16_t port = _mcic_enb_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \
+ set_pos_reg( 4, _pcps_ddev_slot_num( _d ), active_irq.map_code ); \
+ _set_port_bit( (_d), port, MCIC_IRQ ); \
+ }
+
+ // In IRQ de-init function, disable IRQ on the
+ // interface chip.
+ #define _pcps_ddev_disb_irq_mca( _d ) \
+ if ( _pcps_ddev_is_mca( _d ) ) \
+ { \
+ uint16_t port = _mcic_enb_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \
+ _clear_port_bit( (_d), port, MCIC_IRQ ); \
+ }
+
+#else
+
+ // Do nothing if MCA not supported.
+ #define _pcps_ddev_enb_irq_mca( _d );
+ #define _pcps_ddev_disb_irq_mca( _d );
+ #define _pcps_ddev_ack_irq_mca( _d );
+
+#endif
+
+
+
+// The macros below generate code only if PCI support is enabled.
+
+#if ( _PCPS_USE_PCI )
+ // In ISR function, pass acknowledge to the PCI
+ // interface chip.
+ // 1.) Read PCI incoming mailbox to clear IRQ.
+ // 2.) Clear interrupt source, deassert INTA# signal
+ // and leave interrupt enabled by writing '1's to
+ // the interrupt flag and interrupt enable bits.
+ #define _pcps_ddev_ack_irq_pci( _d ) \
+ if ( (_d)->irq_ack_mask ) \
+ { \
+ if ( _pcps_ddev_is_pci_amcc( _d ) ) \
+ _mbg_inp32( (_d), _pcps_ddev_io_base_mapped( _d, 0 ) \
+ + AMCC_OP_REG_IMB4 ); \
+ \
+ _mbg_outp32( (_d), (_d)->irq_ack_port, (_d)->irq_ack_mask ); \
+ }
+
+ // In IRQ init function, enable IRQ on the
+ // interface chip.
+ #define _pcps_ddev_enb_irq_pci( _d ) \
+ if ( (_d)->irq_enb_mask ) \
+ { \
+ uint32_t intcsr = _mbg_inp32_to_cpu( (_d), (_d)->irq_enb_disb_port ); \
+ _mbg_outp32( (_d), (_d)->irq_enb_disb_port, \
+ intcsr | (_d)->irq_enb_mask ); \
+ }
+
+ // In IRQ de-init function, disable IRQ on the
+ // interface chip.
+ #define _pcps_ddev_disb_irq_pci( _d ) \
+ if ( (_d)->irq_disb_mask ) \
+ { \
+ uint32_t intcsr = _mbg_inp32_to_cpu( (_d), (_d)->irq_enb_disb_port ); \
+ _mbg_outp32( (_d), (_d)->irq_enb_disb_port, \
+ intcsr & ~(_d)->irq_disb_mask ); \
+ }
+
+#else
+ // Do nothing if PCI not supported.
+ #define _pcps_ddev_enb_irq_pci( _d );
+ #define _pcps_ddev_disb_irq_pci( _d );
+ #define _pcps_ddev_ack_irq_pci( _d );
+#endif
+
+
+
+// In ISR function, verify that the hardware device has
+// really generated the current IRQ.
+// If device is PCI the interface chip's IRQ flag is set.
+// For non-PCI devices check the IRQ flag of the clock's
+// status port.
+#if ( _PCPS_USE_PCI )
+ #define _pcps_ddev_has_gen_irq( _d ) \
+ ( ( (_d)->irq_flag_mask ) ? \
+ ( _mbg_inp32( (_d), (_d)->irq_flag_port ) & (_d)->irq_flag_mask ) : \
+ ( _pcps_ddev_read_status_port( _d ) & PCPS_ST_IRQF ) \
+ )
+
+#else
+ #define _pcps_ddev_has_gen_irq( _d ) \
+ ( _pcps_ddev_read_status_port( _d ) & PCPS_ST_IRQF )
+#endif
+
+
+// In ISR function, acknowledge IRQ requests to the
+// hardware device.
+#define _pcps_ddev_ack_irq( _d ) \
+{ \
+ _pcps_ddev_ack_irq_pci( _d ); \
+ _pcps_ddev_ack_irq_mca( _d ); \
+}
+
+
+// The macro below should be called at the end of the
+// interrupt initialization function to instruct the
+// radio clock hardware to generate IRQs. This code
+// must be executed after the IRQ service function
+// has been registered.
+// The _cmd parameter must be one of the PCPS_IRQ_...
+// codes defined in pcpsdefs.h which determine the
+// IRQ rate (per second, per minute, etc.)
+#define _pcps_ddev_enb_irq( _d, _cmd ) \
+{ \
+ _pcps_sem_inc( _d ); \
+ _pcps_ddev_enb_irq_mca( _d ); \
+ _pcps_ddev_enb_irq_pci( _d ); \
+ _pcps_write_byte( _d, _cmd ); \
+ _pcps_sem_dec( _d ); \
+}
+
+
+// The macro below should be called at the beginning
+// of the interrupt deinitialization function to instruct
+// the radio clock hardware to stop generating IRQs.
+// This code must be executed before the IRQ service function
+// is deregistered.
+#define _pcps_ddev_disb_irq( _d ) \
+{ \
+ _pcps_sem_inc( _d ); \
+ _pcps_write_byte( _d, PCPS_IRQ_NONE ); \
+ _pcps_ddev_disb_irq_mca( _d ); \
+ _pcps_ddev_disb_irq_pci( _d ); \
+ _pcps_sem_dec( _d ); \
+}
+
+
+#endif /* _PCPSIRQ_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c
new file mode 100755
index 0000000..944cee0
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c
@@ -0,0 +1,502 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpslstr.c 1.22.1.4 2011/02/07 10:34:59 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Functions generating commonly used multi-language strings used
+ * with programs for Meinberg radio clocks.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpslstr.c $
+ * Revision 1.22.1.4 2011/02/07 10:34:59 martin
+ * Fixed potential compiler warning for sprintf().
+ * Revision 1.22.1.3 2011/01/28 09:34:20 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.22.1.2 2010/11/05 12:55:10 martin
+ * Revision 1.22.1.1 2010/07/15 12:39:34 martin
+ * Added function sprint_utc_offs().
+ * Revision 1.22 2010/06/25 13:57:57Z daniel
+ * Account for time zone offsets with minutes other than 0.
+ * Revision 1.21 2009/03/19 08:06:58Z daniel
+ * Added function pcps_tz_name_hr_status() to
+ * handle different time scales.
+ * Revision 1.20 2008/11/14 12:12:26Z martin
+ * Made some parameters for some functions const.
+ * Revision 1.19 2008/07/18 10:50:46Z martin
+ * Use _snwprintf with underscore for MS compilers.
+ * Revision 1.18 2008/01/30 14:51:12Z martin
+ * Fixed gcc compiler warnings.
+ * Revision 1.17 2008/01/17 09:08:12 daniel
+ * Added function pcps_date_time_wstr().
+ * Changed function pcps_tz_name() to support MSF related time zones.
+ * Exclude functions using wchar_t from build if wide chars are
+ * not supported by the target environment.
+ * Revision 1.16 2007/08/14 09:08:25Z martin
+ * Addad a workaround for older Borland compilers which don't
+ * like "const" inside structures.
+ * Revision 1.15 2007/07/20 10:55:27Z martin
+ * Some modifications to avoid compiler warnings.
+ * Revision 1.14 2007/03/30 13:23:42 martin
+ * In pcps_status_strs() handle case where time has been
+ * set manually.
+ * Revision 1.13 2007/03/29 12:58:18Z martin
+ * Moved some definitions to the header file to make them public.
+ * Revision 1.12 2006/05/04 14:56:03Z martin
+ * Strings returned by inv_str() ar surrounded by "**"s.
+ * Revision 1.11 2004/11/09 15:06:44Z martin
+ * Type cast to avoid warning with format string.
+ * Revision 1.10 2004/08/18 14:58:02 martin
+ * pcps_tz_name() now expects a flags parameter which controls
+ * the format of the output string.
+ * Revision 1.9 2004/04/28 08:06:12Z martin
+ * Append DST status to TZ names labeled "UTC+xh"
+ * in pcps_tz_name().
+ * Revision 1.8 2003/04/15 10:46:31Z martin
+ * Pass RECEIVER_INFO to pcps_serial_str().
+ * Revision 1.7 2002/12/18 09:57:03Z martin
+ * Made some vaiables and definitions global.
+ * Revision 1.6 2002/02/19 10:03:16Z MARTIN
+ * New function pcps_serial_str().
+ * Revision 1.5 2001/09/17 13:17:40 MARTIN
+ * New function pcps_tz_name_from_status() which should be used
+ * instead of pcps_tz_name() if offset from UTC is not known.
+ * New function pcps_status_strs().
+ * Enhanced language support.
+ * Don't require myutil.h anymore.
+ * Added some comments.
+ * Source code cleanup.
+ * Revision 1.4 2001/08/14 11:32:24 MARTIN
+ * Modified pcps_date_time_str() to allow for variable
+ * spacing between date, time, and time zone..
+ * Revision 1.3 2001/02/28 15:47:29 MARTIN
+ * Replaced access to some structure elements by new macro calls.
+ * Revision 1.2 2000/08/31 14:03:46 MARTIN
+ * Modified initializers for tzcode_name for non CPP-compilers.
+ * Revision 1.1 2000/07/21 12:14:01 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PCPSLSTR
+ #include <pcpslstr.h>
+#undef _PCPSLSTR
+
+#include <pcpsutil.h>
+#include <mbgtime.h>
+#include <ctry.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define _eos( _s ) ( &(_s)[strlen( _s )] )
+
+typedef struct
+{
+ #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0500 )
+ // old BCs don't like "const" inside the structure
+ LSTR ok;
+ LSTR err;
+ #else
+ CLSTR ok;
+ CLSTR err;
+ #endif
+} CLSTR_STATUS;
+
+
+static const char *tz_name_utc = TZ_NAME_UTC;
+static CLSTR str_dst = { "DST", "Sommerzeit" };
+
+
+
+/*HDR*/
+const char *inv_str( void )
+{
+ static CLSTR s = { "** invalid **", "** ung" LCUE "ltig **" };
+
+ return _lstr( s );
+
+} /* inv_str */
+
+
+
+/*HDR*/
+int sprint_utc_offs( char *s, const char *info, long utc_offs )
+{
+ int n = 0;
+
+ // utc_offs is in [s]
+ char utc_offs_sign = ( utc_offs < 0 ) ? '-' : '+';
+ ulong abs_utc_offs = labs( utc_offs );
+ ulong utc_offs_hours = abs_utc_offs / SECS_PER_HOUR;
+ ulong tmp = abs_utc_offs % SECS_PER_HOUR;
+ ulong utc_offs_mins = tmp / MINS_PER_HOUR;
+ ulong utc_offs_secs = tmp % MINS_PER_HOUR;
+
+ if ( info )
+ n += sprintf( &s[n], "%s", info );
+
+ n += sprintf( &s[n], "%c%lu", utc_offs_sign, utc_offs_hours );
+
+ if ( utc_offs_mins || utc_offs_secs )
+ n += sprintf( &s[n], ":%02lu", utc_offs_mins );
+
+ if ( utc_offs_secs )
+ n += sprintf( &s[n], ":%02lu", utc_offs_secs );
+
+ n += sprintf( &s[n], "h" );
+
+ return n;
+
+} // sprint_utc_offs
+
+
+
+static /*HDR*/
+const char *get_tz_name( PCPS_TIME_STATUS_X pcps_status, long utc_offs,
+ ushort flags, int is_msf )
+{
+ static char ws[40];
+ const char *cp = NULL;
+ int n = 0;
+
+ if ( ( pcps_status & PCPS_UTC ) && ( utc_offs == 0 ) )
+ return tz_name_utc; // no offset, no DST
+
+ if ( pcps_status & PCPS_DL_ENB )
+ {
+ if ( utc_offs == ( 2 * SECS_PER_HOUR ) )
+ {
+ cp = _lstr( lstr_cest );
+ goto check_flags;
+ }
+ else
+ if ( ( utc_offs == SECS_PER_HOUR ) && is_msf )
+ {
+ cp = _lstr( lstr_bst );
+ goto check_flags;
+ }
+ }
+
+ if ( !( pcps_status & PCPS_DL_ENB ) )
+ {
+ if ( utc_offs == SECS_PER_HOUR )
+ {
+ cp = _lstr( lstr_cet );
+ goto check_flags;
+ }
+ else
+ if ( ( utc_offs == 0 ) && is_msf )
+ {
+ cp = _lstr( lstr_gmt );
+ goto check_flags;
+ }
+ }
+
+ n = sprint_utc_offs( ws, tz_name_utc, utc_offs );
+
+check_flags:
+ if ( cp )
+ {
+ if ( flags == 0 )
+ return cp;
+
+ strcpy( ws, cp );
+
+ if ( flags & PCPS_TZ_NAME_FORCE_UTC_OFFS )
+ {
+ n = strlen( ws );
+ n += sprintf( &ws[n], "%*c(", pcps_time_tz_dist, ' ' );
+ n += sprint_utc_offs( &ws[n], tz_name_utc, utc_offs );
+ sprintf( &ws[n], ")" );
+ }
+ }
+
+ if ( flags & PCPS_TZ_NAME_APP_DST )
+ {
+ if ( pcps_status & PCPS_DL_ENB )
+ sprintf( _eos( ws ), ",%*c%s", pcps_time_tz_dist,
+ ' ', _lstr( str_dst ) );
+ }
+
+ return ws;
+}
+
+
+
+/*HDR*/
+const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf )
+{
+ return get_tz_name( t->status, t->offs_utc * SECS_PER_HOUR, flags, is_msf );
+
+} // pcps_tz_name
+
+
+
+/*HDR*/
+const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf )
+{
+ return get_tz_name( hrt->status, hrt->utc_offs, flags, is_msf );
+
+} // pcps_tz_name_from_hr_time
+
+
+
+// The function below can be used to build a name for
+// the time zone if the TIMESCALE, the UTC/DST status and the
+// UTC offset are known, e.g. from plug-in clocks.
+
+/*HDR*/
+const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf )
+{
+ static char ws[40];
+
+ if ( t->status & PCPS_SCALE_GPS )
+ strcpy( ws, "GPS" );
+ else
+ if ( t->status & PCPS_SCALE_TAI )
+ strcpy( ws, "TAI" );
+ else
+ return pcps_tz_name_from_hr_time( t, flags, is_msf);
+
+ return ws;
+
+} // pcps_tz_name_hr_status
+
+
+
+// The function below can be used to build a name for
+// the time zone if only the UTC/DST status is known
+// but the UTC offset is not. This is the case, for example,
+// if the Meinberg standard time string is decoded.
+
+/*HDR*/
+const char *pcps_tz_name_from_status( ushort status )
+{
+ if ( status & PCPS_UTC )
+ return tz_name_utc;
+
+ return ( status & PCPS_DL_ENB ) ? _lstr( str_dst ) : "";
+
+} // pcps_tz_name_from_status
+
+
+
+/*HDR*/
+char *pcps_date_time_str( char *s, const PCPS_TIME *t,
+ ushort year_limit, const char *tz_str )
+{
+ if ( !_pcps_time_is_read( t ) )
+ strcpy( s, str_not_avail );
+ else
+ {
+ char *cp;
+ int i;
+
+ _pcps_sprint_wday( s, t, language );
+ cp = _eos( s );
+ *cp++ = ',';
+ for ( i = 0; i < pcps_wday_date_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_date( cp, t, year_limit );
+ cp = _eos( s );
+ for ( i = 0; i < pcps_date_time_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_time_long( cp, t );
+
+ if ( tz_str )
+ {
+ cp = _eos( s );
+ for ( i = 0; i < pcps_time_tz_dist; i++ )
+ *cp++ = ' ';
+ strcpy( cp, tz_str );
+ }
+ }
+
+ return s;
+
+} // pcps_date_time_str
+
+
+
+#if MBG_TGT_HAS_WCHAR_T && defined( MBG_TGT_WIN32 )
+
+/*HDR*/
+wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t,
+ ushort year_limit, const wchar_t *tz_str )
+{
+ char stemp[80];
+ wchar_t wstemp[80];
+
+ if ( !_pcps_time_is_read( t ) )
+ mbstowcs( ws, str_not_avail, 32 );
+ else
+ {
+ char *cp;
+ int i;
+
+ _pcps_sprint_wday( stemp, t, language );
+ cp = _eos( stemp );
+ *cp++ = ',';
+ for ( i = 0; i < pcps_wday_date_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_date( cp, t, year_limit );
+ cp = _eos( stemp );
+ for ( i = 0; i < pcps_date_time_dist; i++ )
+ *cp++ = ' ';
+ _pcps_sprint_time_long( cp, t );
+
+ mbstowcs( wstemp, stemp, sizeof( wstemp ) );
+
+ if ( tz_str )
+ _snwprintf( ws, sizeof( wstemp ) + 32, L"%s %s", wstemp, tz_str );
+ }
+
+ return ws;
+
+} // pcps_date_time_wstr
+
+#endif // MBG_TGT_HAS_WCHAR
+
+
+
+static /*HDR*/
+void pcps_setup_status_str( PCPS_STATUS_STR *pstr, int err_cond,
+ CLSTR_STATUS *pss )
+{
+ pstr->is_err = err_cond != 0;
+ pstr->cp = _lstr( pstr->is_err ? pss->err : pss->ok );
+
+} // pcps_setup_status_str
+
+
+
+// to return status strings to be displayed depending on the
+// a clocks PCPS_TIME.status.
+
+/*HDR*/
+void pcps_status_strs( ushort status, int status_is_read,
+ int is_gps, PCPS_STATUS_STRS *pstrs )
+{
+ CLSTR clstr_time_inval = DEFAULT_STR_TIME_INVAL;
+ CLSTR clstr_set_manually = DEFAULT_STR_SET_MANUALLY;
+
+ CLSTR_STATUS lstr_dcf_has_syncd =
+ { DEFAULT_STR_DCF_HAS_SYNCD, DEFAULT_STR_DCF_HAS_NOT_SYNCD };
+
+ CLSTR_STATUS lstr_gps_syncd =
+ { DEFAULT_STR_GPS_SYNCD, DEFAULT_STR_GPS_NOT_SYNCD };
+
+ CLSTR_STATUS lstr_dcf_not_free_running =
+ { DEFAULT_STR_DCF_NOT_FREE_RUNNING, DEFAULT_STR_DCF_FREE_RUNNING };
+
+ CLSTR_STATUS lstr_gps_pos =
+ { DEFAULT_STR_GPS_POS_OK, DEFAULT_STR_GPS_POS_NOT_OK };
+
+ CLSTR clstr_ann_dst = DEFAULT_STR_ANN_DST;
+ CLSTR clstr_ann_ls = DEFAULT_STR_ANN_LS;
+
+ PCPS_STATUS_STRS tmp_strs;
+ PCPS_STATUS_STR *pstr = &tmp_strs.s[0];
+
+ memset( &tmp_strs, 0, sizeof( tmp_strs ) );
+
+ if ( !status_is_read )
+ pstr->cp = str_not_avail;
+ else
+ {
+ if ( status & PCPS_INVT )
+ {
+ pstr->cp = _lstr( clstr_time_inval );
+ pstr->is_err = 1;
+ }
+ else
+ if ( status & PCPS_IFTM )
+ {
+ pstr->cp = _lstr( clstr_set_manually );
+ pstr->is_err = 1;
+ }
+ else
+ {
+ pcps_setup_status_str( pstr, ( status & PCPS_SYNCD ) == 0,
+ is_gps ? &lstr_gps_syncd : &lstr_dcf_has_syncd );
+
+ pstr++;
+
+ pcps_setup_status_str( pstr, ( status & PCPS_FREER ) != 0,
+ is_gps ? &lstr_gps_pos : &lstr_dcf_not_free_running );
+ }
+
+ pstr++;
+
+ if ( status & PCPS_DL_ANN )
+ pstr->cp = _lstr( clstr_ann_dst );
+ else
+ if ( status & PCPS_LS_ANN )
+ pstr->cp = _lstr( clstr_ann_ls );
+ }
+
+ *pstrs = tmp_strs;
+
+} // pcps_status_strs
+
+
+
+/*HDR*/
+char *pcps_port_str( char *s, const PCPS_DEV *pdev )
+{
+ ushort port = _pcps_port_base( pdev, 0 );
+
+ ushort n = sprintf( s, "%3Xh", port );
+
+ port = _pcps_port_base( pdev, 1 );
+
+ if ( port )
+ sprintf( &s[n], ", %3Xh", port );
+
+ return s;
+
+} // pcps_port_str
+
+
+
+/*HDR*/
+const char *pcps_tzcode_str( PCPS_TZCODE tzcode )
+{
+ if ( language < N_LNG && tzcode < N_PCPS_TZCODE )
+ return tzcode_name[tzcode][language];
+
+ return inv_str();
+
+} // pcps_tzcode_str
+
+
+
+/*HDR*/
+char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p,
+ const RECEIVER_INFO *p_ri, int short_strs )
+{
+ const PORT_SETTINGS *p_ps = &p->pii[i].port_info.port_settings;
+ const STR_TYPE_INFO *p_sti = &p->stii[p_ps->str_type].str_type_info;
+
+ sprintf( s, "%lu,%s", (ulong) p_ps->parm.baud_rate, p_ps->parm.framing );
+
+ if ( short_strs )
+ sprintf( _eos( s ), ",%s", short_mode_name[p_ps->mode] );
+ else
+ {
+ if ( p_ri->n_str_type > 1 )
+ sprintf( _eos( s ), ", %s", p_sti->long_name );
+
+ sprintf( _eos( s ), ", %s", _lstr( mode_name[p_ps->mode] ) );
+ }
+
+ return( s );
+
+} // pcps_serial_str
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h
new file mode 100755
index 0000000..adf4b5e
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h
@@ -0,0 +1,1038 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpslstr.h 1.27.1.5 2011/02/16 09:34:23 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpslstr.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpslstr.h $
+ * Revision 1.27.1.5 2011/02/16 09:34:23 martin
+ * Added menu titles for PTP and PTP Unicast configuration.
+ * Revision 1.27.1.4 2011/02/09 14:43:42Z martin
+ * Revision 1.27.1.3 2011/01/28 09:34:38 martin
+ * Fixed build under FreeBSD.
+ * Revision 1.27.1.2 2010/11/22 15:23:06 martin
+ * Added strings for programmable output synthesizer mode.
+ * Revision 1.27.1.1 2010/07/15 13:02:16 martin
+ * Also use ANSI umlauts under QNX.
+ * Updated function prototypes.
+ * Revision 1.27 2010/06/28 08:28:17Z stefan
+ * Added greek character mu.
+ * Corrected a spelling mistake.
+ * Defined umlauts as hex codes.
+ * Added _pcps_sprint_vernum macro which is either _dec or _hex,
+ * depending on the target platform.
+ * Revision 1.26 2010/06/25 13:58:25 daniel
+ * Added IgnoreTFOM related language strings
+ * Revision 1.25 2010/01/28 09:02:27 martin
+ * Added menu option name for LAN interface.
+ * Added German POUT mode names for DCF77_M59.
+ * Revision 1.24 2009/03/19 08:07:45Z daniel
+ * Updated function prototypes.
+ * Revision 1.23 2008/11/14 12:12:45Z martin
+ * Updated function prototypes.
+ * Revision 1.22 2008/01/17 09:12:41Z daniel
+ * Use mbg_tgt.h, specially to care about wchar_t.
+ * Added strings for WEZ/WESZ, BST, GMT.
+ * Updated function prototypes.
+ * Revision 1.21 2007/03/30 13:24:42Z martin
+ * Added initializer for status string if time has been set manually.
+ * Revision 1.20 2007/03/29 12:59:23Z martin
+ * Moved some definitions here.
+ * Added and modified some definitions related to TZCODE.
+ * Revision 1.19 2006/10/23 15:18:15Z martin
+ * Added some configuration warning msg texts.
+ * Added definitions for uppercase umlauts.
+ * Separated English and German initializers for some strings.
+ * Revision 1.18 2006/09/26 14:57:22Z martin
+ * Added DEFAULT_OPT_NAME_POUT.
+ * Revision 1.17 2000/07/02 07:02:16Z martin
+ * Separate English and German initializers for "invalid time".
+ * Revision 1.16 2006/05/23 20:13:24Z martin
+ * Added initializers for German POUT mode strings.
+ * Revision 1.15 2005/12/20 10:30:56Z martin
+ * Made some strings start with uppercase letters.
+ * Revision 1.14 2005/08/12 12:35:34Z martin
+ * Fixed missing comma in a macro.
+ * Revision 1.13 2005/03/03 08:49:38Z martin
+ * Modified DEFAULT_OPT_NAME_SERIAL.
+ * Modified DEFAULT_OPT_NAME_IRIG_...
+ * Added default strings for synthesizer.
+ * Revision 1.12 2004/11/23 09:36:12Z martin
+ * Fixed a typo.
+ * Revision 1.11 2004/11/09 15:08:08Z martin
+ * Defined some separate strings for English and German.
+ * Modified some string contents.
+ * Revision 1.10 2004/10/26 15:03:57 martin
+ * Distinguish between IRIG RX and TX strings.
+ * Revision 1.9 2004/08/18 14:59:04Z martin
+ * Defined some flag bits to control the format of the output string
+ * generated by pcps_tz_name().
+ * Updated function prototypes.
+ * Revision 1.8 2004/04/07 12:49:06Z martin
+ * Added initializers for IRIG output cfg strings.
+ * Revision 1.7 2003/04/15 10:47:29Z martin
+ * Added initializers for IRIG menu strings.
+ * Updated function prototypes.
+ * Revision 1.6 2002/12/18 13:57:53 martin
+ * Some definitions and variables made global.
+ * Added some new macros _pcps_sprint_vernum...()
+ * and _pcps_sprint_dev_id().
+ * Revision 1.5 2002/02/19 10:01:36Z MARTIN
+ * New initializers for string mode names.
+ * New global variables mode_name and short_mode_name.
+ * Updated function prototypes.
+ * Revision 1.4 2001/09/17 13:26:16 MARTIN
+ * Added definitions for PCPS_STATUS_STRS.
+ * Added initializers for strings.
+ * Added some comments.
+ * Updated function prototypes.
+ * Revision 1.3 2001/08/14 11:35:40 MARTIN
+ * Added initializers for commonly used mulit-language
+ * text strings.
+ * Revision 1.2 2001/02/28 15:48:34 MARTIN
+ * Updated function prototypes.
+ * Modified syntax to initialize variables.
+ * Revision 1.1 2000/07/21 12:15:12 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCPSLSTR_H
+#define _PCPSLSTR_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+#include <parmpcps.h>
+#include <ctrydttm.h>
+#include <cnv_wday.h>
+
+#if MBG_TGT_HAS_WCHAR_T
+ #include <wchar.h>
+#endif
+
+#ifdef _PCPSLSTR
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+// upper case 'A' umlaut
+#define ANSI_UC_A_UML '\xC4' // single char
+#define ANSI_US_A_UML "\xC4" // string
+
+// upper case 'O' umlaut
+#define ANSI_UC_O_UML '\xD6' // single char
+#define ANSI_US_O_UML "\xD6" // string
+
+// upper case 'U' umlaut
+#define ANSI_UC_U_UML '\xDC' // single char
+#define ANSI_US_U_UML "\xDC" // string
+
+// lower case 'a' umlaut
+#define ANSI_LC_A_UML '\xE4' // single char
+#define ANSI_LS_A_UML "\xE4" // string
+
+// lower case 'o' umlaut
+#define ANSI_LC_O_UML '\xF6' // single char
+#define ANSI_LS_O_UML "\xF6" // string
+
+// lower case 'u' umlaut
+#define ANSI_LC_U_UML '\xFC' // single char
+#define ANSI_LS_U_UML "\xFC" // string
+
+// 'sz' umlaut
+#define ANSI_LC_SZ_UML '\xDF' // single char
+#define ANSI_LS_SZ_UML "\xDF" // string
+
+// degree character
+#define ANSI_C_DEGREE '\xB0' // single char
+#define ANSI_S_DEGREE "\xB0" // string
+
+// greek mu character
+#define ANSI_C_MU '\xB5' //single char
+#define ANSI_S_MU "\xB5" //string
+
+#if defined( MBG_TGT_WIN32 ) \
+ || defined( MBG_TGT_UNIX ) \
+ || defined( MBG_TGT_QNX )
+ #define DEFAULT_PCPS_WDAY_DATE_DIST 1
+ #define DEFAULT_PCPS_DATE_TIME_DIST 2
+ #define DEFAULT_PCPS_TIME_TZ_DIST 1
+
+ #define UCAE ANSI_US_A_UML
+ #define UCOE ANSI_US_O_UML
+ #define UCUE ANSI_US_U_UML
+
+ #define LCAE ANSI_LS_A_UML
+ #define LCOE ANSI_LS_O_UML
+ #define LCUE ANSI_LS_U_UML
+
+ #define LCSZ ANSI_LS_SZ_UML
+ #define DEG ANSI_S_DEGREE
+ #define MU ANSI_S_MU
+#else
+ #define DEFAULT_PCPS_WDAY_DATE_DIST 1
+ #define DEFAULT_PCPS_DATE_TIME_DIST 2
+ #define DEFAULT_PCPS_TIME_TZ_DIST 1
+
+ #define UCAE "\x8E"
+ #define UCOE "\x99"
+ #define UCUE "\x9A"
+
+ #define LCAE "\x84"
+ #define LCOE "\x94"
+ #define LCUE "\x81"
+
+ #define LCSZ "\xE1"
+ #define DEG "\xF8"
+ #define MU "\xE6"
+#endif
+
+
+// The flags defined below can be passed to pcps_tz_name()
+// in order to control the generation of time zone names
+
+enum
+{
+ PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS, // always print "UTC+offs"
+ PCPS_TZ_NAME_BIT_APP_DST, // append DST status
+ N_PCPS_TZ_NAME_FLAG
+};
+
+// bit masks corresponding to the flags above
+#define PCPS_TZ_NAME_FORCE_UTC_OFFS ( 1UL << PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS )
+#define PCPS_TZ_NAME_APP_DST ( 1UL << PCPS_TZ_NAME_BIT_APP_DST )
+
+
+// The definitions below are used with pcps_get_status_strs().
+
+#define N_PCPS_STATUS_STR 3
+
+typedef struct
+{
+ const char *cp;
+ int is_err;
+} PCPS_STATUS_STR;
+
+typedef struct
+{
+ PCPS_STATUS_STR s[N_PCPS_STATUS_STR];
+} PCPS_STATUS_STRS;
+
+
+// initializers for commonly use multi-language strings
+// (type: CLSTR )
+
+
+// time adjustment window
+
+#define DEFAULT_STR_TIME_ADJ_STATUS \
+{ \
+ "Time Adjustment Status", \
+ "Status der Zeitkontrolle" \
+}
+
+#define DEFAULT_STR_SYS_TIME \
+{ \
+ "System Time:", \
+ "Systemzeit:" \
+}
+
+#define DEFAULT_STR_REF_TIME \
+{ \
+ "Reference Time:", \
+ "Referenzzeit:" \
+}
+
+#define DEFAULT_STR_DELTA_TIME \
+{ \
+ "Difference:", \
+ "Zeitdifferenz:" \
+}
+
+#define DEFAULT_STR_LAST_CORR \
+{ \
+ "Last Correction:", \
+ "Letzte Korrektur:" \
+}
+
+#define DEFAULT_STR_WAIT_SYNC \
+{ \
+ "Waiting for Sync After Reset ...", \
+ "Warte auf Sync. nach Reset ..." \
+}
+
+
+// ref time window
+
+#define DEFAULT_STR_REF_TIME_INFO \
+{ \
+ "Reference Time Info", \
+ "Referenzzeit" \
+}
+
+#define DEFAULT_STR_REF_SRC_LABEL \
+{ \
+ "Time Source:", \
+ "Funkuhr ID:" \
+}
+
+#define DEFAULT_STR_REF_SYNC_LABEL \
+{ \
+ "Last Sync.:", \
+ "Letzte Sync.:" \
+}
+
+
+// Clock status messages:
+
+// Time is not valid (i.e. after batt. empty).
+#define DEFAULT_STR_TIME_INVAL_EN \
+ "Ref. Time is Invalid"
+
+#define DEFAULT_STR_TIME_INVAL_DE \
+ "Referenzzeit nicht g" LCUE "ltig"
+
+#define DEFAULT_STR_TIME_INVAL \
+{ \
+ DEFAULT_STR_TIME_INVAL_EN, \
+ DEFAULT_STR_TIME_INVAL_DE \
+}
+
+// on-board time has been set manually
+#define DEFAULT_STR_SET_MANUALLY \
+{ \
+ "Time has been set manually", \
+ "Zeit wurde manuell gesetzt" \
+}
+
+// DCF77 receiver has synch'd at least once
+// after reset.
+#define DEFAULT_STR_DCF_HAS_SYNCD \
+{ \
+ "Synchronized after last RESET", \
+ "Sync. nach RESET ist erfolgt" \
+}
+
+// DCF77 receiver has not synch'd after reset.
+#define DEFAULT_STR_DCF_HAS_NOT_SYNCD \
+{ \
+ "Not synchronized after last RESET", \
+ "Sync. nach RESET noch nicht erfolgt" \
+}
+
+// DCF77 receiver currently runs on XTAL.
+#define DEFAULT_STR_DCF_FREE_RUNNING \
+{ \
+ "Clock running on Xtal oscillator", \
+ "Funkuhr l" LCAE "uft frei auf Quarzbasis" \
+}
+
+// DCF77 receiver is currently synchronized.
+#define DEFAULT_STR_DCF_NOT_FREE_RUNNING \
+{ \
+ "Clock is synchronized", \
+ "Senderf" LCUE "hrung" \
+}
+
+// GPS receiver is currently synchronized.
+#define DEFAULT_STR_GPS_SYNCD \
+{ \
+ "Time is synchronized", \
+ "Zeitsynchronisation ist erfolgt" \
+}
+
+// GPS receiver is currently synchronized.
+#define DEFAULT_STR_GPS_NOT_SYNCD \
+{ \
+ "Time not synchronized", \
+ "Zeit ist nicht synchron" \
+}
+
+// GPS receiver has verified its position.
+#define DEFAULT_STR_GPS_POS_OK \
+{ \
+ "Receiver position has been verified", \
+ "Positionbestimmung durchgef" LCUE "hrt" \
+}
+
+// GPS receiver has not verified its position.
+#define DEFAULT_STR_GPS_POS_NOT_OK \
+{ \
+ "Receiver pos. not verified", \
+ "Position nicht gepr" LCUE "ft" \
+}
+
+// Announcement of DST change.
+#define DEFAULT_STR_ANN_DST \
+{ \
+ "Change in Daylight Saving Announced", \
+ "Zeitumschaltung angek" LCUE "ndigt" \
+}
+
+// Announcement of leap second.
+#define DEFAULT_STR_ANN_LS \
+{ \
+ "Leap Second Announced", \
+ "Schaltsekunde angek" LCUE "ndigt" \
+}
+
+
+// menu option: setup (title)
+
+#define DEFAULT_OPT_NAME_SETUP_EN \
+ "Setup"
+
+#define DEFAULT_OPT_NAME_SETUP_DE \
+ "Einstellungen"
+
+#define DEFAULT_OPT_NAME_SETUP \
+{ \
+ DEFAULT_OPT_NAME_SETUP_EN, \
+ DEFAULT_OPT_NAME_SETUP_DE \
+}
+
+
+// menu option: setup date/time
+
+#define DEFAULT_OPT_NAME_SET_TIME_EN \
+ "Radio Clock's Date/Time"
+
+#define DEFAULT_OPT_NAME_SET_TIME_DE \
+ "Datum/Zeit der Funkuhr"
+
+#define DEFAULT_OPT_NAME_SET_TIME \
+{ \
+ DEFAULT_OPT_NAME_SET_TIME_EN, \
+ DEFAULT_OPT_NAME_SET_TIME_DE \
+}
+
+#define DEFAULT_STR_NEW_DATE \
+{ \
+ "New date", \
+ "Neues Datum" \
+}
+
+#define DEFAULT_STR_NEW_TIME \
+{ \
+ "New time", \
+ "Neue Zeit" \
+}
+
+
+// menu option: setup time zone
+
+#define TZ_NAME_UTC "UTC"
+
+#define TZ_NAME_MEZ "MEZ"
+#define TZ_NAME_MESZ "MESZ"
+#define TZ_NAME_CET "CET"
+#define TZ_NAME_CEST "CEST"
+
+#define TZ_NAME_OEZ "OEZ"
+#define TZ_NAME_OESZ "OESZ"
+#define TZ_NAME_EET "EET"
+#define TZ_NAME_EEST "EEST"
+
+#define TZ_NAME_WEZ "WEZ"
+#define TZ_NAME_WESZ "WESZ"
+#define TZ_NAME_GMT "GMT"
+#define TZ_NAME_BST "BST"
+
+#define DEFAULT_OPT_NAME_TZ \
+{ \
+ "Radio Clock's Time Zone", \
+ "Zeitzone der Funkuhr" \
+}
+
+
+// menu option: setup time zone
+
+#define DEFAULT_TZCODE_NAME_CET_CEST \
+{ \
+ TZ_NAME_CET "/" TZ_NAME_CEST, \
+ TZ_NAME_MEZ "/" TZ_NAME_MESZ \
+}
+
+#define DEFAULT_TZCODE_HINT_CET_CEST \
+{ \
+ "Central European Time or Summer Time, as broadcasted by DCF77", \
+ "Mitteleurop" LCAE "ische Zeit oder Sommerzeit, wie von DCF77 gesendet" \
+}
+
+#define DEFAULT_TZCODE_NAME_GMT_BST \
+{ \
+ TZ_NAME_GMT "/" TZ_NAME_BST, \
+ TZ_NAME_WEZ "/" TZ_NAME_WESZ \
+}
+
+#define DEFAULT_TZCODE_HINT_GMT_BST \
+{ \
+ "Greenwich Mean Time or British Summer Time, as broadcasted by MSF", \
+ "Westeurop" LCAE "ische Zeit oder britische Sommerzeit, wie von MSF gesendet" \
+}
+
+
+
+#define DEFAULT_TZCODE_NAME_CET \
+{ \
+ "always " TZ_NAME_CET, \
+ "immer " TZ_NAME_MEZ \
+}
+
+#define DEFAULT_TZCODE_HINT_CET \
+{ \
+ "always CET (UTC+1h), daylight saving suppressed", \
+ "immer MEZ (UTC+1h), Sommerzeit wird unterdr" LCUE "ckt" \
+}
+
+
+#define DEFAULT_TZCODE_NAME_UTC \
+{ \
+ TZ_NAME_UTC, \
+ TZ_NAME_UTC \
+}
+
+#define DEFAULT_TZCODE_HINT_UTC \
+{ \
+ "always UTC", \
+ "immer UTC" \
+}
+
+
+#define DEFAULT_TZCODE_NAME_EET_EEST \
+{ \
+ TZ_NAME_EET "/" TZ_NAME_EEST, \
+ TZ_NAME_OEZ "/" TZ_NAME_OESZ \
+}
+
+#define DEFAULT_TZCODE_HINT_EET_EEST \
+{ \
+ "East European Time, CET/CEST + 1h", \
+ "Osteurop" LCAE "ische Zeit, MEZ/MESZ + 1h" \
+}
+
+
+#define DEFAULT_TZCODE_NAMES \
+{ \
+ DEFAULT_TZCODE_NAME_CET_CEST, \
+ DEFAULT_TZCODE_NAME_CET, \
+ DEFAULT_TZCODE_NAME_UTC, \
+ DEFAULT_TZCODE_NAME_EET_EEST \
+}
+
+#define DEFAULT_TZCODE_HINTS \
+{ \
+ DEFAULT_TZCODE_HINT_CET_CEST, \
+ DEFAULT_TZCODE_HINT_CET, \
+ DEFAULT_TZCODE_HINT_UTC, \
+ DEFAULT_TZCODE_HINT_EET_EEST \
+}
+
+
+// menu option: setup serial parameters
+
+#define DEFAULT_OPT_NAME_SERIAL \
+{ \
+ "On-Board Serial Ports", \
+ "Serielle Schnittstellen der Karte" \
+}
+
+
+// menu option: setup enable flags
+
+#define DEFAULT_OPT_NAME_EF \
+{ \
+ "Enable Outputs", \
+ "Freischaltung der Ausg" LCAE "nge" \
+}
+
+
+// menu option: setup length of antenna cable
+
+#define DEFAULT_OPT_NAME_CAB_LEN \
+{ \
+ "Antenna Cable", \
+ "Antennenkabel" \
+}
+
+
+// menu option: setup IRIG config
+
+#define DEFAULT_OPT_NAME_IRIG_TX_EN "IRIG Output"
+#define DEFAULT_OPT_NAME_IRIG_TX_DE "IRIG-Ausgang"
+
+#define DEFAULT_OPT_NAME_IRIG_TX \
+{ \
+ DEFAULT_OPT_NAME_IRIG_TX_EN, \
+ DEFAULT_OPT_NAME_IRIG_TX_DE \
+}
+
+
+#define DEFAULT_OPT_NAME_IRIG_RX_EN "IRIG Input"
+#define DEFAULT_OPT_NAME_IRIG_RX_DE "IRIG-Eingang"
+
+#define DEFAULT_OPT_NAME_IRIG_RX \
+{ \
+ DEFAULT_OPT_NAME_IRIG_RX_EN, \
+ DEFAULT_OPT_NAME_IRIG_RX_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_FMT_EN "IRIG Code Format"
+#define DEFAULT_STR_IRIG_FMT_DE "IRIG Code-Format"
+
+#define DEFAULT_STR_IRIG_FMT \
+{ \
+ DEFAULT_STR_IRIG_FMT_EN, \
+ DEFAULT_STR_IRIG_FMT_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_OFFS_EN "IRIG Time Offset from UTC"
+#define DEFAULT_STR_IRIG_OFFS_DE "IRIG-Zeitoffset zu UTC"
+
+#define DEFAULT_STR_IRIG_OFFS \
+{ \
+ DEFAULT_STR_IRIG_OFFS_EN, \
+ DEFAULT_STR_IRIG_OFFS_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_TIMESTR_UTC_EN "Send serial UTC"
+#define DEFAULT_STR_IRIG_TIMESTR_UTC_DE "Seriell UTC ausgeben"
+
+#define DEFAULT_STR_IRIG_TIMESTR_UTC \
+{ \
+ DEFAULT_STR_IRIG_TIMESTR_UTC_EN, \
+ DEFAULT_STR_IRIG_TIMESTR_UTC_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN "Transmit local time instead of UTC"
+#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM_DE "Ortszeit statt UTC aussenden"
+
+#define DEFAULT_STR_IRIG_OUTPUT_LOC_TM \
+{ \
+ DEFAULT_STR_IRIG_OUTPUT_LOC_TM_EN, \
+ DEFAULT_STR_IRIG_OUTPUT_LOC_TM_DE \
+}
+
+#define DEFAULT_IGNORE_RX_TFOM_EN "Ignore TFOM"
+#define DEFAULT_IGNORE_RX_TFOM_DE "Ignoriere TFOM"
+
+#define DEFAULT_IGNORE_RX_TFOM \
+{ \
+ DEFAULT_IGNORE_RX_TFOM_EN, \
+ DEFAULT_IGNORE_RX_TFOM_DE \
+}
+
+#define DEFAULT_STR_TFOM_ALWAYS_SYNC_EN "Output TFOM always as 'sync'"
+#define DEFAULT_STR_TFOM_ALWAYS_SYNC_DE "TFOM immer als 'sync' ausgeben"
+
+#define DEFAULT_STR_TFOM_ALWAYS_SYNC \
+{ \
+ DEFAULT_STR_TFOM_ALWAYS_SYNC_EN, \
+ DEFAULT_STR_TFOM_ALWAYS_SYNC_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_NOT_CFGD_EN \
+ "The IRIG receiver has not yet been configured!\n" \
+ "\n" \
+ "Please make sure the correct " DEFAULT_STR_IRIG_FMT_EN " has been\n" \
+ "selected, and enter the correct " DEFAULT_STR_IRIG_OFFS_EN "\n" \
+ "according to the settings of the IRIG generator."
+
+#define DEFAULT_STR_IRIG_NOT_CFGD_DE \
+ "Der IRIG-Empf" LCAE "nger wurde noch nicht konfiguriert!\n" \
+ "\n" \
+ "Das ausgew" LCAE "hlte " DEFAULT_STR_IRIG_FMT_DE " sowie der\n" \
+ DEFAULT_STR_IRIG_OFFS_DE " m" LCUE "ssen den Einstellungen\n" \
+ "des verwendeten IRIG-Generators entsprechen."
+
+#define DEFAULT_STR_IRIG_NOT_CFGD \
+{ \
+ DEFAULT_STR_IRIG_NOT_CFGD_EN, \
+ DEFAULT_STR_IRIG_NOT_CFGD_DE \
+}
+
+
+#define DEFAULT_STR_IRIG_INVT_EN \
+ "Please note that the IRIG receiver status may read\n" \
+ "\"" DEFAULT_STR_TIME_INVAL_EN "\" if the receiver's on-board date\n" \
+ "does not correspond to the date (day-of-year number)\n" \
+ "transmitted by the IRIG source."
+
+#define DEFAULT_STR_IRIG_INVT_DE \
+ "Wenn im Status des IRIG-Empf" LCAE "ngers \"" DEFAULT_STR_TIME_INVAL_DE "\"\n" \
+ "angezeigt wird, kann der Grund daf" LCUE "r sein, dass das Datum\n" \
+ "auf der Einsteckkarte nicht mit dem vom IRIG-Generator\n" \
+ "gesendeten Datum (bzw. dem Jahrestag) " LCUE "bereinstimmt." \
+
+#define DEFAULT_STR_IRIG_INVT \
+{ \
+ DEFAULT_STR_IRIG_INVT_EN, \
+ DEFAULT_STR_IRIG_INVT_DE \
+}
+
+
+// menu option: programmable outputs
+
+#define DEFAULT_OPT_NAME_POUT \
+{ \
+ "Programmable Pulse Outputs", \
+ "Programmierbare Schaltausg" LCAE "nge" \
+}
+
+
+// menu option: frequency synthesizer
+
+#define DEFAULT_OPT_NAME_SYNTH \
+{ \
+ "Frequency Synthesizer", \
+ "Frequenz-Synthesizer" \
+}
+
+#define DEFAULT_STR_SYNTH_FREQ \
+{ \
+ "Frequency", \
+ "Frequenz" \
+}
+
+#define DEFAULT_STR_SYNTH_PHASE \
+{ \
+ "Phase", \
+ NULL \
+}
+
+
+// menu option: LAN interface
+
+#define DEFAULT_OPT_NAME_LAN_INTF_EN "LAN Interface"
+#define DEFAULT_OPT_NAME_LAN_INTF_DE "Netzwerkschnittstelle"
+
+#define DEFAULT_OPT_NAME_LAN_INTF \
+{ \
+ DEFAULT_OPT_NAME_LAN_INTF_EN, \
+ DEFAULT_OPT_NAME_LAN_INTF_DE \
+}
+
+
+
+// menu option: PTP configuration
+
+#define DEFAULT_OPT_NAME_PTP_CFG_EN "PTP Configuration"
+#define DEFAULT_OPT_NAME_PTP_CFG_DE "PTP-Konfiguration"
+
+#define DEFAULT_OPT_NAME_PTP_CFG \
+{ \
+ DEFAULT_OPT_NAME_PTP_CFG_EN, \
+ DEFAULT_OPT_NAME_PTP_CFG_DE \
+}
+
+
+
+// menu option: PTP Unicast configuration
+
+#define DEFAULT_OPT_NAME_PTP_UC_CFG_EN "PTP Unicast Configuration"
+#define DEFAULT_OPT_NAME_PTP_UC_CFG_DE "PTP-Unicast-Konfiguration"
+
+#define DEFAULT_OPT_NAME_PTP_UC_CFG \
+{ \
+ DEFAULT_OPT_NAME_PTP_UC_CFG_EN, \
+ DEFAULT_OPT_NAME_PTP_UC_CFG_DE \
+}
+
+
+
+/*
+ * Default initializers for German mode string names.
+ * English strings are defined in in gpsdefs.h.
+ */
+#define GER_MODE_NAME_STR_ON_REQ "nur auf Anfrage '?'"
+#define GER_MODE_NAME_STR_PER_SEC "sek" LCUE "ndlich"
+#define GER_MODE_NAME_STR_PER_MIN "min" LCUE "tlich"
+#define GER_MODE_NAME_STR_AUTO "automatisch"
+#define GER_MODE_NAME_STR_ON_REQ_SEC "sek" LCUE "ndlich nach Anfrage"
+
+#define DEFAULT_MODE_NAMES \
+{ \
+ { ENG_MODE_NAME_STR_ON_REQ, GER_MODE_NAME_STR_ON_REQ }, \
+ { ENG_MODE_NAME_STR_PER_SEC, GER_MODE_NAME_STR_PER_SEC }, \
+ { ENG_MODE_NAME_STR_PER_MIN, GER_MODE_NAME_STR_PER_MIN }, \
+ { ENG_MODE_NAME_STR_AUTO, GER_MODE_NAME_STR_AUTO }, \
+ { ENG_MODE_NAME_STR_ON_REQ_SEC, GER_MODE_NAME_STR_ON_REQ_SEC } \
+}
+
+
+/*
+ * Default initializers for German pulse output mode string names.
+ * English strings are defined in in gpsdefs.h.
+ */
+#define GER_POUT_NAME_IDLE "Nicht verwendet"
+#define GER_POUT_NAME_TIMER "Zeitschaltung"
+#define GER_POUT_NAME_SINGLE_SHOT "Einzelimpuls"
+#define GER_POUT_NAME_CYCLIC_PULSE "Zyklischer Impuls"
+#define GER_POUT_NAME_PER_SEC "Sek" LCUE "ndlicher Impuls"
+#define GER_POUT_NAME_PER_MIN "Min" LCUE "tlicher Impuls"
+#define GER_POUT_NAME_PER_HOUR "St" LCUE "ndlicher Impuls"
+#define GER_POUT_NAME_DCF77 "DCF77-Zeitmarken"
+#define GER_POUT_NAME_POS_OK "Position OK"
+#define GER_POUT_NAME_TIME_SYNC "Zeit synchron"
+#define GER_POUT_NAME_ALL_SYNC "alles synchron"
+#define GER_POUT_NAME_TIMECODE "DCLS-Zeitcode"
+#define GER_POUT_NAME_TIMESTR "COM-Zeittelegramm"
+#define GER_POUT_NAME_10MHZ "Festfrequenz 10 MHz"
+#define GER_POUT_NAME_DCF77_M59 "DCF77-Zeitmarken mit 59. Impuls"
+#define GER_POUT_NAME_SYNTH "Frequenz-Synthesizer"
+
+#define DEFAULT_GER_POUT_NAMES \
+{ \
+ GER_POUT_NAME_IDLE, \
+ GER_POUT_NAME_TIMER, \
+ GER_POUT_NAME_SINGLE_SHOT, \
+ GER_POUT_NAME_CYCLIC_PULSE, \
+ GER_POUT_NAME_PER_SEC, \
+ GER_POUT_NAME_PER_MIN, \
+ GER_POUT_NAME_PER_HOUR, \
+ GER_POUT_NAME_DCF77, \
+ GER_POUT_NAME_POS_OK, \
+ GER_POUT_NAME_TIME_SYNC, \
+ GER_POUT_NAME_ALL_SYNC, \
+ GER_POUT_NAME_TIMECODE, \
+ GER_POUT_NAME_TIMESTR, \
+ GER_POUT_NAME_10MHZ, \
+ GER_POUT_NAME_DCF77_M59, \
+ GER_POUT_NAME_SYNTH \
+}
+
+/*
+ * Default initializers for German pulse output mode hints.
+ * English strings are defined in in gpsdefs.h.
+ */
+#define GER_POUT_HINT_IDLE "Konstanter Ausgangspegel"
+#define GER_POUT_HINT_TIMER "Schalten zu den angegebenen Zeiten"
+#define GER_POUT_HINT_SINGLE_SHOT "Einzelner Impuls mit angegebener L" LCAE "nge"
+#define GER_POUT_HINT_CYCLIC_PULSE "Impulse wiederholt nach angegebenem Intervall"
+#define GER_POUT_HINT_PER_SEC "Impuls zu Beginn jeder Sekunde"
+#define GER_POUT_HINT_PER_MIN "Impuls zu Beginn jeder Minute"
+#define GER_POUT_HINT_PER_HOUR "Impuls zu Beginn jeder Stunde"
+#define GER_POUT_HINT_DCF77 "DCF77-kompatible Zeitmarken"
+#define GER_POUT_HINT_POS_OK "Schalten, wenn Empf" LCAE "ngerposition " LCUE "berpr" LCUE "ft"
+#define GER_POUT_HINT_TIME_SYNC "Schalten, wenn Zeit synchron"
+#define GER_POUT_HINT_ALL_SYNC "Schalten, wenn Zeit synchron und Position " LCUE "berpr" LCUE "ft"
+#define GER_POUT_HINT_TIMECODE "Unmodulierter Zeitcode des IRIG-Ausgangs"
+#define GER_POUT_HINT_TIMESTR "Zeittelegramm der seriellen Schnittstelle der Karte duplizieren"
+#define GER_POUT_HINT_10MHZ "Feste Ausgangsfrequenz 10 MHz"
+#define GER_POUT_HINT_DCF77_M59 "Zeitmarken wie DCF77, aber mit 500 ms Impuls in 59. Sekunde"
+#define GER_POUT_HINT_SYNTH "Durch programmierbaren Synthesizer erzeugte Frequenz"
+
+#define DEFAULT_GER_POUT_HINTS \
+{ \
+ GER_POUT_HINT_IDLE, \
+ GER_POUT_HINT_TIMER, \
+ GER_POUT_HINT_SINGLE_SHOT, \
+ GER_POUT_HINT_CYCLIC_PULSE, \
+ GER_POUT_HINT_PER_SEC, \
+ GER_POUT_HINT_PER_MIN, \
+ GER_POUT_HINT_PER_HOUR, \
+ GER_POUT_HINT_DCF77, \
+ GER_POUT_HINT_POS_OK, \
+ GER_POUT_HINT_TIME_SYNC, \
+ GER_POUT_HINT_ALL_SYNC, \
+ GER_POUT_HINT_TIMECODE, \
+ GER_POUT_HINT_TIMESTR, \
+ GER_POUT_HINT_10MHZ, \
+ GER_POUT_HINT_DCF77_M59, \
+ GER_POUT_HINT_SYNTH \
+}
+
+
+
+// some macros which generate proper function calls
+
+#define _pcps_sprint_vernum_dec( _s, _v ) \
+ sprintf( (_s), "v%u.%02u", \
+ ( (unsigned) (_v) ) / 100, \
+ ( (unsigned) (_v) ) % 100 )
+
+#define _pcps_sprint_vernum_hex( _s, _v ) \
+ sprintf( (_s), "v%X.%02X", \
+ ( (unsigned) (_v) ) >> 8, \
+ ( (unsigned) (_v) ) & 0xFF )
+
+#if defined( MBG_TGT_WIN32 )
+ #define _pcps_sprint_vernum _pcps_sprint_vernum_dec
+#else
+ #define _pcps_sprint_vernum _pcps_sprint_vernum_hex
+#endif
+
+
+#define _pcps_sprint_dev_id( _s, _n ) \
+ sprintf( (_s), "%04Xh", _n )
+
+
+#define _pcps_sprint_wday( _s, _t, _l ) \
+ sprint_ctry_wday( (_s), _wday_mon17_to_sun06( (_t)->wday ), (_l) )
+
+#define _pcps_sprint_date( _s, _t, _yl ) \
+ sprint_ctry_dt( (_s), (_t)->mday, (_t)->month, \
+ pcps_exp_year( (_t)->year, (_yl) ) )
+
+#define _pcps_sprint_time( _s, _t ) \
+ sprint_ctry_tm( (_s), (_t)->hour, (_t)->min, (_t)->sec )
+
+#define _pcps_sprint_time_long( _s, _t ) \
+ sprint_ctry_tm_long( (_s), (_t)->hour, (_t)->min, (_t)->sec, (_t)->sec100, 2 )
+
+
+#define _cput_pcps_date( _t, _yl ) \
+{ \
+ char s[80]; \
+ _pcps_sprint_date( s, (_t), (_yl) ); \
+ cputs( s ); \
+}
+
+#define _cput_pcps_time( _t ) \
+{ \
+ char s[80]; \
+ _pcps_sprint_time( s, (_t) ); \
+ cputs( s ); \
+}
+
+#define _cput_pcps_time_long( _t ) \
+{ \
+ char s[80]; \
+ _pcps_sprint_time_long( s, (_t) ); \
+ cputs( s ); \
+}
+
+#define _cput_pcps_date_and_time( _t, _yl, _tz ) \
+{ \
+ char s[80]; \
+ cputs( pcps_date_time_str( s, (_t), (_yl), (_tz) ) ); \
+}
+
+
+_ext const char *str_not_avail
+#ifdef _DO_INIT
+ = "N/A"
+#endif
+;
+
+
+_ext CLSTR lstr_cet
+#ifdef _DO_INIT
+ = { TZ_NAME_CET, TZ_NAME_MEZ }
+#endif
+;
+
+
+_ext CLSTR lstr_cest
+#ifdef _DO_INIT
+ = { TZ_NAME_CEST, TZ_NAME_MESZ }
+#endif
+;
+
+_ext CLSTR lstr_gmt
+#ifdef _DO_INIT
+ = { TZ_NAME_GMT, TZ_NAME_WEZ }
+#endif
+;
+
+
+_ext CLSTR lstr_bst
+#ifdef _DO_INIT
+ = { TZ_NAME_BST, TZ_NAME_WESZ }
+#endif
+;
+
+_ext CLSTR tzcode_name[N_PCPS_TZCODE]
+#ifdef _DO_INIT
+ = DEFAULT_TZCODE_NAMES
+#endif
+;
+
+
+_ext int pcps_wday_date_dist
+#ifdef _DO_INIT
+ = DEFAULT_PCPS_WDAY_DATE_DIST
+#endif
+;
+
+
+_ext int pcps_date_time_dist
+#ifdef _DO_INIT
+ = DEFAULT_PCPS_DATE_TIME_DIST
+#endif
+;
+
+
+_ext int pcps_time_tz_dist
+#ifdef _DO_INIT
+ = DEFAULT_PCPS_TIME_TZ_DIST
+#endif
+;
+
+
+_ext const char *mode_name[N_STR_MODE][N_LNG]
+#ifdef _DO_INIT
+ = DEFAULT_MODE_NAMES
+#endif
+;
+
+
+_ext const char *short_mode_name[N_STR_MODE]
+#ifdef _DO_INIT
+ = DEFAULT_SHORT_MODE_NAMES
+#endif
+;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ const char *inv_str( void ) ;
+ int sprint_utc_offs( char *s, const char *info, long utc_offs ) ;
+ const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) ;
+ const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf ) ;
+ const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf ) ;
+ const char *pcps_tz_name_from_status( ushort status ) ;
+ char *pcps_date_time_str( char *s, const PCPS_TIME *t, ushort year_limit, const char *tz_str ) ;
+ wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t, ushort year_limit, const wchar_t *tz_str ) ;
+ void pcps_status_strs( ushort status, int status_is_read, int is_gps, PCPS_STATUS_STRS *pstrs ) ;
+ char *pcps_port_str( char *s, const PCPS_DEV *pdev ) ;
+ const char *pcps_tzcode_str( PCPS_TZCODE tzcode ) ;
+ char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p, const RECEIVER_INFO *p_ri, int short_strs ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _PCPSLSTR_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c
new file mode 100755
index 0000000..212dfb3
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c
@@ -0,0 +1,53 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsmktm.c 1.4 2006/12/14 15:27:49 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Function to convert PCPS_TIME to Unix time (seconds since 1970)
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsmktm.c $
+ * Revision 1.4 2006/12/14 15:27:49 martin
+ * Include time.h.
+ * Revision 1.3 2006/08/22 09:10:03 martin
+ * Renamed function totalsec() to mbg_mktime() and moved it
+ * to a separate file mbgmktm.c.
+ * Revision 1.2 2001/08/14 11:58:08 MARTIN
+ * Included sys/time.h for time_t definition.
+ * Revision 1.1 2001/02/02 15:30:09 MARTIN
+ *
+ **************************************************************************/
+
+#define _PCPSMKTM
+ #include <pcpsmktm.h>
+#undef _PCPSMKTM
+
+#include <mbgmktm.h>
+
+#include <time.h>
+
+
+/*HDR*/
+long pcps_mktime( PCPS_TIME *tp )
+{
+ time_t secs;
+ int year = tp->year;
+
+ if ( year < 70 )
+ year += 100;
+
+ secs = mbg_mktime( year, tp->month - 1, tp->mday - 1,
+ tp->hour, tp->min, tp->sec );
+
+ if ( secs != -1 )
+ secs -= tp->offs_utc * 3600;
+
+ return( secs );
+
+} // pcps_mktime
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h
new file mode 100755
index 0000000..efcc2df
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h
@@ -0,0 +1,62 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsmktm.h 1.1 2001/02/02 15:31:07 MARTIN REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpsmktm.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsmktm.h $
+ * Revision 1.1 2001/02/02 15:31:07 MARTIN
+ *
+ **************************************************************************/
+
+#ifndef _PCPSMKTM_H
+#define _PCPSMKTM_H
+
+
+/* Other headers to be included */
+
+#include <pcpsdefs.h>
+
+
+#ifdef _PCPSMKTM
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+//_ext PCPS_TIME tx;
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ long pcps_mktime( PCPS_TIME *tp ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PCPSMKTM_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c
new file mode 100755
index 0000000..e35ea25
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c
@@ -0,0 +1,160 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsutil.c 1.13 2009/03/09 13:39:45 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Utility functions used with programs for Meinberg radio clocks.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsutil.c $
+ * Revision 1.13 2009/03/09 13:39:45 martin
+ * Made pcps_exp_year() an inline function.
+ * Revision 1.12 2008/12/10 19:59:48 martin
+ * Made frac_sec_from_bin() an inline function.
+ * Revision 1.11 2008/11/25 10:00:25 martin
+ * Use new definitions of fraction conversion type and scale
+ * from pcpsdefs.h.
+ * Revision 1.10 2006/06/29 10:38:24Z martin
+ * New function pcps_time_is_valid().
+ * Modified pcps_str_to_port(), doesn't add a 0 entry to the list anymore.
+ * Fixed a compiler warning related to type conversion.
+ * Revision 1.9 2005/01/14 10:14:31Z martin
+ * Changed type of ISA port addr to int.
+ * Revision 1.8 2004/11/09 14:29:27Z martin
+ * Rewrote functions using C99 fixed-size definitions.
+ * Revision 1.7 2003/04/17 10:08:59Z martin
+ * Added some type casts to fix compiler warnings.
+ * Revision 1.6 2001/11/28 14:39:16Z MARTIN
+ * In frac_sec_from_bin(), define the divisor as floating point
+ * constant to avoid a domain errors on 16 bit systems.
+ * Revision 1.5 2001/09/17 07:28:01 MARTIN
+ * New function frac_sec_from_bin() to convert
+ * PCPS_HR_TIME fractions.
+ * Revision 1.4 2001/03/01 14:01:09 MARTIN
+ * Modified parameters for pcps_setup_isa_ports().
+ * Revision 1.3 2000/08/31 14:05:30 MARTIN
+ * Replaced pcps_str_to_port() by pcps_setup_isa_ports().
+ * Revision 1.2 2000/07/21 13:42:54 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#define _PCPSUTIL
+ #include <pcpsutil.h>
+#undef _PCPSUTIL
+
+#include <stdlib.h>
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_time_is_valid()
+ *
+ * Purpose: Pack a structure with serial port parameters
+ *
+ * Input/Output: p address of a structure holding both the
+ * packed and unpacked information
+ *
+ * Ret value: --
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+int pcps_time_is_valid( const PCPS_TIME *p )
+{
+ return ( p->sec100 <= 99 )
+ && ( p->sec <= 60 ) /* allow for leap second */
+ && ( p->min <= 59 )
+ && ( p->hour <= 23 )
+ && ( p->mday >= 1 ) && ( p->mday <= 31 )
+ && ( p->wday >= 1 ) && ( p->wday <= 7 )
+ && ( p->month >= 1 ) && ( p->month <= 12 )
+ && ( p->year <= 99 );
+
+} /* pcps_time_is_valid */
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_str_to_port()
+ *
+ * Purpose: Try to convert a string to a valid port
+ * address.
+ *
+ * Input: s the string
+ *
+ * Output: --
+ *
+ * Ret value: a valid port number or 0
+ *+-------------------------------------------------------------*/
+
+/*HDR*/
+void pcps_setup_isa_ports( char *s,
+ int *port_vals,
+ int n_vals )
+{
+ ushort i;
+
+
+ for ( i = 0; i < n_vals; i++ )
+ {
+ if ( *s == 0 )
+ break;
+
+ *port_vals++ = (uint16_t) strtoul( s, &s, 16 );
+
+ if ( *s == ',' )
+ s++;
+ }
+
+} // pcps_setup_isa_ports
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_unpack_serial()
+ *
+ * Purpose: Unpack a structure with serial port parameters
+ *
+ * Input/Output: p address of a structure holding both the
+ * packed and unpacked information
+ *
+ * Ret value: --
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+void pcps_unpack_serial( PCPS_SER_PACK *p )
+{
+ uint8_t pack = p->pack;
+
+ p->baud = (uint8_t) ( pack & BITMASK( PCPS_BD_BITS ) );
+ p->frame = (uint8_t) ( ( pack >> PCPS_FR_SHIFT ) & BITMASK( PCPS_FR_BITS ) );
+ p->mode = (uint8_t) ( ( pack >> PCPS_MOD_SHIFT ) & BITMASK( PCPS_MOD_BITS ) );
+
+} // pcps_unpack_serial
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_pack_serial()
+ *
+ * Purpose: Pack a structure with serial port parameters
+ *
+ * Input/Output: p address of a structure holding both the
+ * packed and unpacked information
+ *
+ * Ret value: --
+ *-------------------------------------------------------------*/
+
+/*HDR*/
+void pcps_pack_serial( PCPS_SER_PACK *p )
+{
+ p->pack = (uint8_t) ( ( p->baud & BITMASK( PCPS_BD_BITS ) )
+ | ( ( p->frame & BITMASK( PCPS_FR_BITS ) ) << PCPS_FR_SHIFT )
+ | ( ( p->mode & BITMASK( PCPS_MOD_BITS ) ) << PCPS_MOD_SHIFT ) );
+
+} /* pcps_pack_serial */
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h
new file mode 100755
index 0000000..e5cab81
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h
@@ -0,0 +1,183 @@
+
+/**************************************************************************
+ *
+ * $Id: pcpsutil.h 1.14 2009/03/09 13:39:45 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for pcpsutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: pcpsutil.h $
+ * Revision 1.14 2009/03/09 13:39:45 martin
+ * Made pcps_exp_year() an inline function.
+ * Revision 1.13 2008/12/10 19:59:48 martin
+ * Made frac_sec_from_bin() an inline function.
+ * Revision 1.12 2008/11/25 09:59:01 martin
+ * Moved definitions of PCPS_HRT_FRAC_SCALE and
+ * PCPS_HRT_FRAC_SCALE_FMT to pcpsdefs.h.
+ * Revision 1.11 2006/06/29 10:15:02Z martin
+ * Updated function prototypes.
+ * Revision 1.10 2005/01/14 10:16:12Z martin
+ * Updated function prototypes.
+ * Revision 1.9 2004/11/09 14:30:50Z martin
+ * Redefined interface data types using C99 fixed-size definitions.
+ * Updated function prototypes.
+ * Revision 1.8 2004/04/14 09:22:09Z martin
+ * Pack structures 1 byte aligned.
+ * Revision 1.7 2001/11/28 14:41:25Z MARTIN
+ * Changed PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT
+ * to print 7 rather than 6 digits.
+ * Revision 1.6 2001/09/14 11:59:33 MARTIN
+ * Support for PCPS_HR_TIME fraction conversion.
+ * Updated function prototypes.
+ * Revision 1.5 2001/08/14 12:06:44 MARTIN
+ * Defined constants used to draw a signal bar
+ * depending on a DCF77 clock's signal value.
+ * Revision 1.4 2001/03/01 14:03:18 MARTIN
+ * Updated function prototypes.
+ * Revision 1.3 2000/08/31 14:06:05 MARTIN
+ * Updated function prototypes.
+ * Revision 1.2 2000/07/21 13:43:40 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _PCPSUTIL_H
+#define _PCPSUTIL_H
+
+
+/* Other headers to be included */
+
+#include <pcpsdefs.h>
+#include <use_pack.h>
+
+
+#ifdef _PCPSUTIL
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+#if defined( _USE_PACK ) // set byte alignment
+ #pragma pack( 1 )
+#endif
+
+
+// The following constants are used to draw a signal bar
+// depending on a DCF77 clock's signal value:
+#define PCPS_SIG_BIAS 55
+#define PCPS_SIG_ERR 1
+#define PCPS_SIG_MIN 20
+#define PCPS_SIG_MAX 68
+
+
+// the structure below is used with a DCF77 clock's serial interface
+typedef struct
+{
+ PCPS_SERIAL pack; // this byte is passed to the board as parameter
+
+ uint8_t baud; // the other bytes can hold the unpacked values
+ uint8_t frame;
+ uint8_t mode;
+
+} PCPS_SER_PACK;
+
+
+
+/*--------------------------------------------------------------
+ * Name: pcps_exp_year()
+ *
+ * Purpose: Convert a 2-digit year number to a 4-digit
+ * year number. The resulting year number is in
+ * the range [year_lim ... ( year_lim + 99 )].
+ *
+ * Input: year the 2-digit year number
+ * year_lim the smallest 4-digit year number
+ * to be returned
+ *
+ * Output: --
+ *
+ * Ret value: the calculated 4-digit year num
+ *+-------------------------------------------------------------*/
+
+static __mbg_inline
+uint16_t pcps_exp_year( uint8_t year, uint16_t year_lim )
+{
+ uint16_t lyear = (uint16_t) ( (uint16_t) year + year_lim
+ - ( year_lim % 100 ) );
+
+ if ( lyear < year_lim )
+ lyear += 100;
+
+ return lyear;
+
+} // pcps_exp_year
+
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+ int pcps_time_is_valid( const PCPS_TIME *p ) ;
+ void pcps_setup_isa_ports( char *s, int *port_vals, int n_vals ) ;
+ void pcps_unpack_serial( PCPS_SER_PACK *p ) ;
+ void pcps_pack_serial( PCPS_SER_PACK *p ) ;
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*--------------------------------------------------------------
+ * Name: frac_sec_from_bin()
+ *
+ * Purpose: Convert a fraction of a second from binary
+ * format (as returned in a PCPS_HR_TIME structure
+ * to a decimal fraction, using a specified scale
+ * factor. See also the definitions of
+ * PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT
+ * in the header file.
+ *
+ * Input: b the binary fraction
+ * scale the scale factor
+ *
+ * Output: --
+ *
+ * Ret value: the calculated number
+ *+-------------------------------------------------------------*/
+
+static __mbg_inline
+uint32_t frac_sec_from_bin( uint32_t b, uint32_t scale )
+{
+ return (uint32_t) ( (PCPS_HRT_FRAC_CONVERSION_TYPE) b * scale
+ / PCPS_HRT_BIN_FRAC_SCALE );
+
+} // frac_sec_from_bin
+
+
+
+#if defined( _USE_PACK ) // set default alignment
+ #pragma pack()
+#endif
+
+/* End of header body */
+
+#undef _ext
+
+
+#endif /* _PCPSUTIL_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h
new file mode 100755
index 0000000..ba1ce53
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h
@@ -0,0 +1,76 @@
+
+/**************************************************************************
+ *
+ * $Id: plxdefs.h 1.2 2010/01/28 15:46:31 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions to be used with PLX PCIexpress interface chips.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: plxdefs.h $
+ * Revision 1.2 2010/01/28 15:46:31 martin
+ * Added PLX8311_REG_CTRL.
+ * Revision 1.1 2007/06/08 07:46:56Z martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _PLXDEFS_H
+#define _PLXDEFS_H
+
+
+/* Other headers to be included */
+
+
+#ifdef _PLXDEFS
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+// The following PLX8311 operation registers can
+// be accessed via port I/O or memory mapped:
+#define PLX8311_REG_INTCSR 0x68
+
+// The following bits must be set in the INTCSR register
+// to let the local microcontroller be able to generate
+// interrupts on the PCI bus via the chip's LINTi# line:
+#define PLX8311_INT_ENB ( (1UL << 11) | (1UL << 8) )
+
+// The bit below signals if an LINTi# interrupt is active:
+#define PLX8311_INT_FLAG (1UL << 15)
+
+#define PLX8311_REG_CNTRL 0x6C
+
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PLXDEFS_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/qsdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/qsdefs.h
new file mode 100755
index 0000000..352924b
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/qsdefs.h
@@ -0,0 +1,46 @@
+
+/**************************************************************************
+ *
+ * $Id: qsdefs.h 1.1 2002/02/19 13:46:20 MARTIN REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used with the Meinberg Quality Management System.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: qsdefs.h $
+ * Revision 1.1 2002/02/19 13:46:20 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _QSDEFS_H
+#define _QSDEFS_H
+
+
+/* Other headers to be included */
+
+/* Start of header body */
+
+// The fixed length of the group code string:
+#define MBG_GRP_CODE_LEN 4
+
+// The mem size required to store a group code string
+// including terminating 0:
+#define MBG_GRP_CODE_SIZE ( MBG_GRP_CODE_LEN + 1 )
+
+// A data type used to store a group code string:
+typedef char MBG_GRP_CODE[MBG_GRP_CODE_SIZE];
+
+
+// The length of the serial number:
+#define MBG_SERNUM_LEN 8
+
+// The length of the group code + serial number:
+#define MBG_GRP_SERNUM_LEN ( MBG_GRP_CODE_LEN + MBG_SERNUM_LEN )
+
+
+/* End of header body */
+
+#endif /* _QSDEFS_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h b/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h
new file mode 100755
index 0000000..744e443
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h
@@ -0,0 +1,89 @@
+
+/**************************************************************************
+ *
+ * $Id: rsrc.h 1.4.1.1 2006/09/19 14:52:02 martin TEST $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used to access resource manager functions under
+ * different operating systems.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: rsrc.h $
+ * Revision 1.4.1.1 2006/09/19 14:52:02 martin
+ * Preliminary support for *BSD.
+ * Revision 1.4 2001/02/28 15:45:11 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.3 2001/02/05 10:22:24 MARTIN
+ * Linux support.
+ * Revision 1.2 2000/09/20 08:15:34 MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _RSRC_H
+#define _RSRC_H
+
+
+/* Other headers to be included */
+
+#include <mbg_tgt.h>
+
+#if defined( MBG_TGT_OS2 )
+ #include <rsrc_os2.h> // resource manager functions for OS/2
+#elif defined( MBG_TGT_WIN32 )
+ #include <rsrc_nt.h> // resource manager functions for Win NT
+#elif defined( MBG_TGT_LINUX )
+ #include <rsrc_lx.h> // resource manager functions for Linux
+#elif defined( MBG_TGT_BSD )
+ #include <rsrc_bsd.h> // resource manager functions for *BSD
+#endif
+
+
+
+#ifdef _RSRC
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+enum
+{
+ RSRC_BUS_ISA,
+ RSRC_BUS_EISA,
+ RSRC_BUS_MCA,
+ RSRC_BUS_PCI
+};
+
+
+/* End of header body */
+
+#undef _ext
+
+
+/* function prototypes: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+/* (no header definitions found) */
+
+/* ----- function prototypes end ----- */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _RSRC_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c
new file mode 100755
index 0000000..50a4ad8
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c
@@ -0,0 +1,401 @@
+
+/**************************************************************************
+ *
+ * $Id: toolutil.c 1.3.2.1 2010/11/05 12:56:02 martin TEST $
+ *
+ * Description:
+ * Common functions which can be used with Meinberg command line
+ * utility programs.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: toolutil.c $
+ * Revision 1.3.2.1 2010/11/05 12:56:02 martin
+ * Revision 1.3 2009/06/19 12:12:14 martin
+ * Added function mbg_print_hr_timestamp().
+ * Revision 1.2 2009/02/18 09:15:55 martin
+ * Support TAI and GPS time scales in mbg_snprint_hr_time().
+ * Revision 1.1 2008/12/17 10:45:13 martin
+ * Initial revision.
+ * Revision 1.1 2008/12/15 08:35:07 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#define _TOOLUTIL
+ #include <toolutil.h>
+#undef _TOOLUTIL
+
+// include Meinberg headers
+#include <pcpsutil.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*HDR*/
+void mbg_print_program_info( const char *pname, const char *pversion, const char *pcopyright )
+{
+ printf( "\n%s %s %s\n\n", pname, pversion, pcopyright );
+
+} // mbg_print_program_info
+
+
+
+/*HDR*/
+void mbg_print_usage_intro( const char *pname, const char *info )
+{
+ printf( "Usage: %s [[opt] [opt] ...] [[dev] [dev] ...]\n\n", pname );
+
+ if ( info )
+ printf( "%s\n\n", info );
+
+
+} // mbg_print_usage_intro
+
+
+
+/*HDR*/
+void mbg_print_help_options( void )
+{
+ puts( "where opt is one of the options:" );
+ mbg_print_opt_info( "-? or -h", "print this usage information" );
+
+} // mbg_print_help_options
+
+
+
+/*HDR*/
+void mbg_print_opt_info( const char *opt_name, const char *opt_info )
+{
+ if ( opt_name == NULL )
+ opt_name = "";
+
+ if ( opt_info == NULL )
+ opt_info = "";
+
+ printf( " %8s %s\n", opt_name, opt_info );
+
+} // mbg_print_opt_info
+
+
+
+/*HDR*/
+void mbg_print_device_options( void )
+{
+ puts( "\nwhere dev is the name of a device, e.g.:\n"
+ " /dev/mbgclock0"
+ );
+
+} // mbg_print_device_options
+
+
+
+/*HDR*/
+void mbg_print_default_usage( const char *pname, const char *prog_info )
+{
+ mbg_print_usage_intro( pname, prog_info );
+ mbg_print_help_options();
+ mbg_print_device_options();
+ puts( "" );
+
+} // mbg_print_default_usage
+
+
+
+// test if ioctl error and print msg if true
+
+/*HDR*/
+int mbg_ioctl_err( int rc, const char *descr )
+{
+ if ( rc < 0 )
+ {
+ fprintf( stderr, "** IOCTL error %i: ", rc );
+ perror( descr );
+ return -1;
+ }
+
+ return 0;
+
+} // mbg_ioctl_err
+
+
+
+/*HDR*/
+int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev )
+{
+ unsigned long long port;
+ int irq_num;
+ int ret_val = 0;
+ int rc;
+
+ if ( dev_name )
+ printf( "%s:\n", dev_name );
+
+ // get information about the device
+ rc = mbg_get_device_info( dh, p_dev );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_device_info" ) )
+ goto fail;
+
+
+ printf( "%s", _pcps_type_name( p_dev ) );
+
+ if ( strlen( _pcps_sernum( p_dev ) ) &&
+ strcmp( _pcps_sernum( p_dev ), "N/A" ) )
+ printf( " %s", _pcps_sernum( p_dev ) );
+
+ printf( " (FW %X.%02X",
+ _pcps_fw_rev_num_major( _pcps_fw_rev_num( p_dev ) ),
+ _pcps_fw_rev_num_minor( _pcps_fw_rev_num( p_dev ) )
+ );
+
+ if ( _pcps_has_asic_version( p_dev ) )
+ {
+ PCI_ASIC_VERSION av;
+ int rc = mbg_get_asic_version( dh, &av );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ av = _convert_asic_version_number( av );
+
+ printf( ", ASIC %X.%02X",
+ _pcps_asic_version_major( av ),
+ _pcps_asic_version_minor( av )
+ );
+ }
+ }
+
+ printf( ")" );
+
+ port = _pcps_port_base( p_dev, 0 );
+
+ if ( port )
+ printf( " at port 0x%03LX", port );
+
+ port = _pcps_port_base( p_dev, 1 );
+
+ if ( port )
+ printf( "/0x%03LX", port );
+
+ irq_num = _pcps_irq_num( p_dev );
+
+ if ( irq_num != -1 )
+ printf( ", irq %i", irq_num );
+
+ goto done;
+
+fail:
+ ret_val = -1;
+
+done:
+ puts( "" );
+ return ret_val;
+
+} // mbg_get_show_dev_info
+
+
+
+/*HDR*/
+int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name,
+ int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) )
+{
+ PCPS_DEV dev;
+ int ret_val = 0;
+
+ if ( dh == MBG_INVALID_DEV_HANDLE )
+ {
+ if ( dev_name )
+ fprintf( stderr, "%s: ", dev_name );
+
+ perror( "Unable to open device" );
+ return -1;
+ }
+
+ if ( mbg_get_show_dev_info( dh, dev_name, &dev ) < 0 )
+ goto fail;
+
+ if ( fnc )
+ ret_val = fnc( dh, &dev );
+
+ goto done;
+
+fail:
+ ret_val = -1;
+
+done:
+ mbg_close_device( &dh );
+ puts( "" );
+
+ return ret_val;
+
+} // mbg_check_device
+
+
+
+/*HDR*/
+int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) )
+{
+ MBG_DEV_HANDLE dh;
+ int ret_val = 0;
+ int num_devices = argc - optind;
+
+ if ( num_devices == 0 ) // no device name given on the command line
+ {
+ // No devices specified on the command line, so
+ // try to find devices.
+ int devices = mbg_find_devices();
+
+ if ( devices == 0 )
+ {
+ printf( "No device found.\n" );
+ return 1;
+ }
+
+ // Handle only first device found.
+ dh = mbg_open_device( 0 );
+ ret_val = mbg_check_device( dh, NULL, fnc );
+ }
+ else
+ {
+ int i;
+ // One or more device names have been specified
+ // on the command line, so handle each device.
+ for ( i = optind; i < argc; i++ )
+ {
+ // Print device name only if output for several devices
+ // shall be displayed.
+ const char *fn = ( num_devices > 1 ) ? argv[i] : NULL;
+
+ dh = open( argv[i], 0 );
+ ret_val = mbg_check_device( dh, fn, fnc );
+
+ if ( ret_val )
+ break;
+ }
+ }
+
+ return ret_val;
+
+} // mbg_check_devices
+
+
+
+/*HDR*/
+int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p )
+{
+ int n = 0;
+
+ // We'll use the standard C library functions to convert the seconds
+ // to broken-down calendar date and time.
+ time_t t = p->sec;
+
+ // Our time stamp may be UTC, or have been converted to local time.
+ // Anyway, since we don't want to account for the system's time zone
+ // settings, we always use the gmtime() function for conversion:
+ struct tm *tmp = gmtime( &t );
+
+ #if defined( DEBUG )
+ n += snprintf( s + n, len_s - n, "raw: %08lX.%08lX, ",
+ (ulong) p->sec,
+ (ulong) p->frac );
+ #endif
+
+ n += snprintf( s + n, len_s - n, "%04i-%02i-%02i %02i:%02i:%02i." PCPS_HRT_FRAC_SCALE_FMT,
+ tmp->tm_year + 1900,
+ tmp->tm_mon + 1,
+ tmp->tm_mday,
+ tmp->tm_hour,
+ tmp->tm_min,
+ tmp->tm_sec,
+ (ulong) frac_sec_from_bin( p->frac, PCPS_HRT_FRAC_SCALE )
+ );
+
+ return n;
+
+} // mbg_snprint_hr_tstamp
+
+
+
+/*HDR*/
+int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p )
+{
+ char ws[80];
+ PCPS_TIME_STAMP ts = p->tstamp;
+ int n;
+ const char *time_scale_name;
+ const char *cp;
+
+ // If the local time offset is not 0 then add this to the time stamp
+ // and set up a string telling the offset.
+ if ( p->utc_offs )
+ {
+ ldiv_t ldt;
+
+ ts.sec += p->utc_offs;
+
+ // The local time offset is in seconds and may be negative, so we
+ // convert to absolute hours and minutes first.
+ ldt = ldiv( labs( p->utc_offs ) / 60, 60 );
+
+ snprintf( ws, sizeof( ws ), "%c%lu:%02luh",
+ ( p->utc_offs < 0 ) ? '-' : '+',
+ ldt.quot,
+ ldt.rem
+ );
+ cp = ws;
+ }
+ else
+ cp = ""; // no local time offset
+
+
+ // Convert the local time stamp to calendar date and time.
+ n = mbg_snprint_hr_tstamp( s, len_s, &ts );
+
+ // By default the time stamp represents UTC plus an optional local time offset.
+ time_scale_name = "UTC";
+
+ // However, some cards may be configured to output TAI or GPS time.
+ if ( p->status & PCPS_SCALE_TAI )
+ time_scale_name = "TAI"; // time stamp represents TAI
+ else
+ if ( p->status & PCPS_SCALE_GPS )
+ time_scale_name = "GPS"; // time stamp represents GPS system time
+
+ n += snprintf( s + n, len_s - n, " %s%s", time_scale_name, cp );
+
+ return n;
+
+} // mbg_snprint_hr_time
+
+
+
+/*HDR*/
+void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int raw )
+{
+ char ws[80];
+
+ mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ts );
+ printf( "Fast HR time %s", ws );
+
+ if ( p_prv_ts )
+ {
+ // print the difference between the current and the previous time stamp
+ uint64_t ts = pcps_time_stamp_to_uint64( p_ts );
+ uint64_t prv_ts = pcps_time_stamp_to_uint64( p_prv_ts );
+ // we divide by PCPS_HRT_BIN_FRAC_SCALE to get the correct fractions
+ // and we multiply by 1E6 to get the result in microseconds
+ double delta_t = (double) ( ts - prv_ts ) * 1E6 / PCPS_HRT_BIN_FRAC_SCALE;
+ printf( " (%+.1f us)", delta_t );
+ }
+
+ if ( !raw )
+ printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 );
+
+ puts( "" );
+
+} // mbg_print_hr_timestamp
+
+
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h
new file mode 100755
index 0000000..7c69e84
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h
@@ -0,0 +1,83 @@
+
+/**************************************************************************
+ *
+ * $Id: toolutil.h 1.2 2009/06/19 12:11:35 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions and prototypes for toolutil.c.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: toolutil.h $
+ * Revision 1.2 2009/06/19 12:11:35 martin
+ * Updated function prototypes.
+ * Revision 1.1 2008/12/17 10:45:14 martin
+ * Initial revision.
+ * Revision 1.1 2008/12/15 08:35:08 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+#ifndef _TOOLUTIL_H
+#define _TOOLUTIL_H
+
+
+/* Other headers to be included */
+
+#include <mbgdevio.h>
+
+
+
+#ifdef _TOOLUTIL
+ #define _ext
+ #define _DO_INIT
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+_ext int must_print_usage;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ----- function prototypes begin ----- */
+
+/* This section was generated automatically */
+/* by MAKEHDR, do not remove the comments. */
+
+void mbg_print_program_info( const char *pname, const char *pversion, const char *pcopyright );
+void mbg_print_usage_intro( const char *pname, const char *info );
+void mbg_print_help_options( void );
+void mbg_print_opt_info( const char *opt_name, const char *opt_info );
+void mbg_print_device_options( void );
+void mbg_print_default_usage( const char *pname, const char *prog_info );
+int mbg_ioctl_err( int rc, const char *descr ) ;
+int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev );
+int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) );
+int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) );
+int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p );
+int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p );
+void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int raw );
+
+/* ----- function prototypes end ----- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* End of header body */
+
+#undef _ext
+#undef _DO_INIT
+
+#endif /* _TOOLUTIL_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h
new file mode 100755
index 0000000..d853118
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h
@@ -0,0 +1,110 @@
+
+/**************************************************************************
+ *
+ * $Id: usbdefs.h 1.10 2010/11/11 09:16:33 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions used with USB devices.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: usbdefs.h $
+ * Revision 1.10 2010/11/11 09:16:33 martin
+ * Added device ID for DCF600USB.
+ * Revision 1.9 2009/03/13 09:02:24 martin
+ * Removed definitions for timeout intervals.
+ * Revision 1.8 2009/02/18 11:08:44 daniel
+ * Added new class code and device ID for SCU_USB
+ * Revision 1.7 2008/11/28 07:45:30Z daniel
+ * Added new class code and device ID for WWVB51USB
+ * Revision 1.6 2008/01/09 10:39:18Z daniel
+ * Added new class code and device ID for MSF51USB
+ * Revision 1.5 2007/10/29 08:23:26Z daniel
+ * Added new class code and device ID for TCR51USB
+ * Revision 1.4 2007/09/25 09:59:50Z daniel
+ * Added indices for endpoint definitions.
+ * Added timeout definitions.
+ * Revision 1.3 2006/12/20 16:11:36Z daniel
+ * Added new device class and device_id for nCipher CMC-device.
+ * Revision 1.2 2006/12/07 09:10:57Z daniel
+ * Added new class code and device ID for USB5131.
+ * Revision 1.1 2006/04/21 08:14:56Z martin
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _USBDEFS_H
+#define _USBDEFS_H
+
+
+/* Other headers to be included */
+
+
+/* Start of header body */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Meinberg's USB vendor ID number (assigned by USB-IF Administration) */
+#define USB_VENDOR_MEINBERG 0x1938
+
+
+/*
+ * USB device class codes (assigned by Meinberg)
+ */
+enum
+{
+ MBG_USB_CLASS_NONE, // (unknown or not defined)
+ MBG_USB_CLASS_CPC, // Control Panel Controller
+ MBG_USB_CLASS_TSU, // Time Stamp Unit
+ MBG_USB_CLASS_DCF, // DCF77 Radio Clock
+ MBG_USB_CLASS_CMC, // nCipher Crypto Module Carrier
+ MBG_USB_CLASS_TCR, // IRIG Time Code Receiver
+ MBG_USB_CLASS_MSF, // MSF Radio Clock
+ MBG_USB_CLASS_WWVB, // WWVB Radio Clock
+ MBG_USB_CLASS_SCU, // Meinberg Signal Changeover Unit
+ N_MBG_USB_CLASS // number of known device class codes
+};
+
+
+/*
+ * USB device ID numbers (assigned by Meinberg)
+ * High byte: USB device class as specified above
+ * Low byte: enumeration of device of a class
+ */
+#define USB_DEV_CPC_01 ( ( MBG_USB_CLASS_CPC << 8 ) | 0x01 )
+
+#define USB_DEV_TSU_01 ( ( MBG_USB_CLASS_TSU << 8 ) | 0x01 )
+
+#define USB_DEV_USB5131 ( ( MBG_USB_CLASS_DCF << 8 ) | 0x01 )
+#define USB_DEV_DCF600USB ( ( MBG_USB_CLASS_DCF << 8 ) | 0x02 )
+
+#define USB_DEV_CMC ( ( MBG_USB_CLASS_CMC << 8 ) | 0x01 )
+
+#define USB_DEV_TCR51USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x01 )
+
+#define USB_DEV_MSF51USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x01 )
+
+#define USB_DEV_WWVB51USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x01 )
+
+#define USB_DEV_SCU_USB ( ( MBG_USB_CLASS_SCU << 8 ) | 0x01 )
+
+enum
+{
+ MBGUSB_EP_IDX_HOST_IN, // transfers from device to host
+ MBGUSB_EP_IDX_HOST_OUT, // transfers from host to device
+ MBGUSB_EP_IDX_HOST_IN_CYCLIC, // cyclic auto-transfer to host
+ MBGUSB_MAX_ENDPOINTS // max number of supported endpoints
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* End of header body */
+
+#endif /* _USBDEFS_H */
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h b/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h
new file mode 100755
index 0000000..aaacd42
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h
@@ -0,0 +1,39 @@
+
+/**************************************************************************
+ *
+ * $Id: use_pack.h 1.3 2011/01/26 10:01:41 martin REL_M $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Check the current compiler type to decide if pragma pack() is
+ * required to pack cross-platform data structures.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: use_pack.h $
+ * Revision 1.3 2011/01/26 10:01:41 martin
+ * Provided a way to suppress packing of structures on a project base.
+ * Revision 1.2 2002/02/25 08:50:33 Andre
+ * query __ARM added, __SH2 removed
+ * Revision 1.1 2001/03/30 08:54:33Z MARTIN
+ * Initial revision
+ *
+ **************************************************************************/
+
+#ifndef _USE_PACK_H
+#define _USE_PACK_H
+
+#if ( !defined( _C166 ) && \
+ !defined( _CC51 ) && \
+ !defined( __ARM ) )
+
+ // _NO_USE_PACK can be defined for specific projects
+ // to avoid packing of structures.
+ #if ( !defined( _NO_USE_PACK ) )
+ #define _USE_PACK
+ #endif
+
+#endif
+
+#endif /* _USE_PACK_H */
+
diff --git a/src/external/bsd/meinberg/dist/mbglib/common/words.h b/src/external/bsd/meinberg/dist/mbglib/common/words.h
new file mode 100755
index 0000000..6106207
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbglib/common/words.h
@@ -0,0 +1,340 @@
+
+/**************************************************************************
+ *
+ * $Id: words.h 1.25.1.2 2011/03/22 09:41:32 martin TRASH $
+ *
+ * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
+ *
+ * Description:
+ * Definitions of commonly used data types.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: words.h $
+ * Revision 1.25.1.2 2011/03/22 09:41:32 martin
+ * Added FBYTE_OF() and FWORD_OF() macros.
+ * Revision 1.25.1.1 2011/01/25 08:25:49Z martin
+ * Avoid build errors under FreeBSD.
+ * Revision 1.25 2010/11/17 10:23:09 martin
+ * Define _BIT_REDEFINED if bit type is redefined.
+ * Revision 1.24 2010/11/17 08:44:56Z martin
+ * If supported, use type "bool" to implement "bit".
+ * Revision 1.23 2010/05/27 08:54:30Z martin
+ * Support fixed size data types with Keil RealView compiler for ARM.
+ * Keil RealView ARM targets are always considered as firmware.
+ * Revision 1.22 2009/10/21 07:53:55 martin
+ * Undid changes introduced in 1.21 since they were not consistent
+ * across glibc and/or Linux kernel header versions.
+ * Revision 1.21 2009/10/01 14:00:17 martin
+ * Conditionally define ulong and friends also for Linux/glibc.
+ * Revision 1.20 2009/07/02 15:38:12 martin
+ * Added new macro _wswap32().
+ * Revision 1.19 2009/04/14 14:45:45Z martin
+ * Added BYTE_OF_P() and WORD_OF_P() macros.
+ * Revision 1.18 2009/03/27 14:05:18 martin
+ * Cleanup for CVI.
+ * Revision 1.17 2009/03/13 09:06:03Z martin
+ * Declared bit type for non-firmware environments.
+ * Revision 1.16 2008/12/05 12:05:41Z martin
+ * Define dummy int64_t/uint64_t types for targets
+ * which don't support 64 bit data types.
+ * Revision 1.15 2008/07/14 14:44:00Z martin
+ * Use fixed size C99 types which come with GCC and newer Borland compilers.
+ * Revision 1.14 2008/01/30 10:27:50Z martin
+ * Moved some macro definitions here.
+ * Revision 1.13 2007/03/08 15:00:30Z martin
+ * Fixed incompatibility of macro _IS_MBG_FIRMWARE.
+ * Added a workaround for _IS_MBG_FIRMWARE under CVI.
+ * Support for BSD.
+ * Revision 1.12 2006/12/15 10:45:46 martin
+ * Added macro _IS_MBG_FIRMWARE.
+ * Cleanup for Linux, QNX, and Watcom C.
+ * Include mbg_tgt.h for non-firmware targets.
+ * Revision 1.11 2004/11/10 10:45:34 martin
+ * Added C99 fixed-type handling for QNX.
+ * Revision 1.10 2004/11/09 13:12:56 martin
+ * Redefined C99 integer types with fixed sizes as standard types
+ * if required, depending on the environment.
+ * Revision 1.9 2003/02/07 11:36:54 MARTIN
+ * New macros _hilo_16() and _hilo_32() for endian conversion.
+ * Revision 1.8 2002/05/28 10:09:54 MARTIN
+ * Added new macros _var_bswap16() and _var_bswap32().
+ * Revision 1.7 2001/03/14 11:30:48 MARTIN
+ * Removed definitions for UINT8, UINT16, UINT32.
+ * Redefined preprocessor control for Win32.
+ * Revision 1.6 2001/02/28 15:43:20 MARTIN
+ * Modified preprocessor syntax.
+ * Revision 1.5 2001/02/05 10:20:53 MARTIN
+ * Include different Linux types for user space and kernel space programs.
+ * Source code cleanup.
+ * Revision 1.4 2000/09/15 08:34:11 MARTIN
+ * Exclude some definitions if compiling under Win NT.
+ * Revision 1.3 2000/08/22 15:04:28 MARTIN
+ * Added new file header.
+ * Added macros to revert endianess of 16 and 32 bit values.
+ *
+ **************************************************************************/
+
+#ifndef _WORDS_H
+#define _WORDS_H
+
+
+/* Other headers to be included */
+
+
+#if !defined( _IS_MBG_FIRMWARE )
+
+#if defined( _C166 ) || \
+ defined( _CC51 ) || \
+ defined( __ARM ) || \
+ defined( __ARMCC_VERSION )
+ #define _IS_MBG_FIRMWARE 1
+#else
+ #define _IS_MBG_FIRMWARE 0
+#endif
+
+
+#endif
+
+#if !_IS_MBG_FIRMWARE
+ #include <mbg_tgt.h>
+#endif
+
+
+#ifdef _WORDS
+ #define _ext
+#else
+ #define _ext extern
+#endif
+
+
+/* Start of header body */
+
+
+// The compilers below support native bit types.
+
+#if defined( _C166 ) || defined( _CC51 )
+ #define _BIT_DEFINED 1
+#endif
+
+
+
+// Check whether the target system supports C99 fixed-size types.
+
+#if defined( MBG_TGT_LINUX ) // any Linux target
+
+ #if defined( __KERNEL__ )
+ #include <linux/types.h>
+ #else
+ #include <stdint.h>
+ #include <sys/types.h>
+ #endif
+
+ #define _C99_BIT_TYPES_DEFINED 1
+
+#elif defined( MBG_TGT_BSD )
+
+ #include <sys/types.h>
+
+ #define _C99_BIT_TYPES_DEFINED 1
+
+ //##++ a workaround for now to avoid inclusion of stdbool.h later
+ #define bit int
+ #define _BIT_DEFINED
+
+#elif defined( MBG_TGT_QNX ) // QNX 4.x or QNX 6.x
+
+ #if defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) with gcc
+ #include <stdint.h>
+ #else // QNX 4.x with Watcom C 10.6
+ #include <sys/types.h> // 64 bit types not supported
+ #endif
+
+ #define _C99_BIT_TYPES_DEFINED 1
+
+#endif
+
+
+
+// If it's not yet clear whether fixed-size types are supported,
+// check the build environment which may be multi-platform.
+
+#if !defined( _C99_BIT_TYPES_DEFINED )
+
+ #if defined( __WATCOMC__ )
+ #if __WATCOMC__ > 1230 // Open Watcom C 1.3 and above
+ #include <stdint.h>
+ #define _C99_BIT_TYPES_DEFINED 1
+ #elif defined( __WATCOM_INT64__ ) // Watcom C 11, non-QNX
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+ #define _C99_BIT_TYPES_DEFINED 1
+ #endif
+ #endif
+
+ #if defined( __BORLANDC__ )
+ #if ( __BORLANDC__ >= 0x570 ) // at least Borland Developer Studio 2006
+ #define _C99_BIT_TYPES_DEFINED 1
+ #endif
+ #endif
+
+ #if defined( __GNUC__ )
+ #include <stdint.h>
+ #define _C99_BIT_TYPES_DEFINED 1
+ #endif
+
+ #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM
+ #include <stdint.h>
+ #define _C99_BIT_TYPES_DEFINED 1
+ #endif
+
+#endif
+
+
+// If neither the target system nor the build environment define C99 fixed-size
+// types define those types based on standard types with the proper sizes
+// commonly used in 16/32 bit environments.
+
+#if defined( _C99_BIT_TYPES_DEFINED )
+
+ #define MBG_TGT_HAS_64BIT_TYPES 1
+
+#else
+
+ typedef char int8_t;
+ typedef unsigned char uint8_t;
+
+ typedef short int16_t;
+ typedef unsigned short uint16_t;
+
+ typedef long int32_t;
+ typedef unsigned long uint32_t;
+
+
+ #if defined( MBG_TGT_WIN32 )
+
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+ #define MBG_TGT_HAS_64BIT_TYPES 1
+
+ #else
+ // The types below are required to avoid build errors
+ // if these types are formally used in function prototypes.
+ // We explicitely use abnormal data types to hopefully
+ // cause compiler errors in case these types are
+ // unexpectedly used to generate real code for a target
+ // platform which does not support 64 bit types.
+ typedef void *int64_t;
+ typedef void *uint64_t;
+ #endif
+
+#endif
+
+
+
+#if !defined( MBG_TGT_HAS_64BIT_TYPES )
+
+ #define MBG_TGT_HAS_64BIT_TYPES 0
+
+#endif
+
+
+
+// Some commonly used types
+
+typedef unsigned char uchar;
+
+#if !defined( MBG_TGT_LINUX ) && !(defined ( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL ) )
+ typedef unsigned short ushort;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+#endif
+
+typedef double udouble;
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long longword;
+typedef unsigned long dword;
+
+#if !defined( _BIT_DEFINED )
+
+ #if _C99_BIT_TYPES_DEFINED
+ #include <stdbool.h>
+
+ typedef bool bit;
+ #else
+ typedef int bit;
+ #endif
+
+ #define _BIT_REDEFINED 1
+
+#endif
+
+
+#define HI_BYTE( _x ) ( (_x) >> 8 )
+#define LO_BYTE( _x ) ( (_x) & 0xFF )
+
+#define HI_WORD( _x ) ( (_x) >> 16 )
+#define LO_WORD( _x ) ( (_x) & 0xFFFF )
+
+// the macros below assume little endianess
+// these macros expect the name of a variable
+#define BYTE_OF( _v, _n ) *( ( (uint8_t *) &(_v) ) + (_n) )
+#define WORD_OF( _v, _n ) *( ( (uint16_t *) &(_v) ) + (_n) )
+
+#define FBYTE_OF( _v, _n ) *( ( (uint8_t far *) &(_v) ) + (_n) )
+#define FWORD_OF( _v, _n ) *( ( (uint16_t far *) &(_v) ) + (_n) )
+
+// same as above, but taking pointers
+#define BYTE_OF_P( _p, _n ) *( ( (uint8_t *) (_p) ) + (_n) )
+#define WORD_OF_P( _p, _n ) *( ( (uint16_t *) (_p) ) + (_n) )
+
+
+// a macro to swap the byte order of a 16 bit value
+#define _bswap16( _x ) \
+( \
+ ( ( ( (uint16_t) (_x) ) & 0x00FF ) << 8 ) | \
+ ( ( ( (uint16_t) (_x) ) & 0xFF00 ) >> 8 ) \
+)
+
+// a macro to swap the byte order of a 32 bit value
+#define _bswap32( _x ) \
+( \
+ ( ( ( (uint32_t) (_x) ) & 0x000000FFUL ) << 24 ) | \
+ ( ( ( (uint32_t) (_x) ) & 0x0000FF00UL ) << 8 ) | \
+ ( ( ( (uint32_t) (_x) ) & 0x00FF0000UL ) >> 8 ) | \
+ ( ( ( (uint32_t) (_x) ) & 0xFF000000UL ) >> 24 ) \
+)
+
+// a macro to swap the word order of a 32 bit value
+#define _wswap32( _x ) \
+( \
+ ( ( ( (uint32_t) (_x) ) & 0x0000FFFFUL ) << 16 ) | \
+ ( ( ( (uint32_t) (_x) ) >> 16 ) & 0x0000FFFFUL ) \
+)
+
+#define _var_bswap16( _v ) (_v) = _bswap16( _v )
+#define _var_bswap32( _v ) (_v) = _bswap32( _v )
+
+
+// The C51 compiler is big-endian, that means the most
+// significant byte of a 16 or 32 bit value is stored in
+// the lowest memory location. Most other systems are
+// little-endian, so we must use macros to adjust the
+// byte order if the C51 is used.
+
+#if defined( _CC51 )
+ #define _hilo_16( _x ) _bswap16( _x )
+ #define _hilo_32( _x ) _bswap32( _x )
+#else
+ #define _hilo_16( _x ) (_x)
+ #define _hilo_32( _x ) (_x)
+#endif
+
+/* End of header body */
+
+#undef _ext
+
+#endif /* _WORDS_H */
diff --git a/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile b/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile
new file mode 100755
index 0000000..07ec4e4
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile
@@ -0,0 +1,43 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.8.1.2 2010/08/30 09:05:23 martin TEST $
+#
+# Description:
+# Makefile for mbgsetsystime.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.8.1.2 2010/08/30 09:05:23 martin
+# Revision 1.8.1.1 2010/08/30 08:21:54 martin
+# Revision 1.8 2009/07/24 10:31:17 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.7 2008/12/22 11:56:59 martin
+# Changed enumeration of source files.
+# Define MBGDEVIO_SIMPLE to avoid inclusion of unnecessary modules.
+# Revision 1.6 2007/03/02 11:45:10 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.5 2006/08/22 09:06:07 martin
+# Added new library module mbgmktm.c.
+# Revision 1.4 2003/07/08 15:33:47 martin
+# Added gpsutils.c to the module list.
+# Revision 1.3 2003/04/25 10:21:06 martin
+# Updated source module list.
+# Revision 1.2 2002/11/21 14:56:31 martin
+# New targets install and uninstall.
+# Revision 1.1 2001/09/17 15:08:46 martin
+#
+#########################################################################
+
+TARGET = mbgsetsystime
+INST_DIR = /usr/local/sbin
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+OBJS += mbgmktm.o
+OBJS += pcpsmktm.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c b/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c
new file mode 100755
index 0000000..6015f12
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c
@@ -0,0 +1,173 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgsetsystime.c 1.8 2009/09/29 15:02:15 martin REL_M $
+ *
+ * Description:
+ * Main file for mbgsetsystime program which reads the current date
+ * and time from a Meinberg device and sets the system time accordingly.
+ * The program returns 0 if successfull, otherwise a value greater
+ * than 0.
+ *
+ * Be careful if using this program while (x)ntpd is running because
+ * (x)ntpd does not like time steps and may react unexpectedly.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgsetsystime.c $
+ * Revision 1.8 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.7 2009/07/24 09:50:09 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.6 2009/06/19 12:38:52 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.5 2009/03/19 17:04:26 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Revision 1.4 2008/12/22 12:43:31 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.3 2007/07/24 09:33:01 martin
+ * Updated copyright to include 2007.
+ * Revision 1.2 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.1 2001/09/17 15:08:46 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsmktm.h>
+#include <toolutil.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+
+static const char *pname = "mbgsetsystime";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2001-2009";
+
+
+
+
+static /*HDR*/
+void set_system_time( PCPS_TIME *tp )
+{
+ struct timeval tv_set;
+
+
+ tv_set.tv_sec = pcps_mktime( tp );
+ tv_set.tv_usec = (ulong) tp->sec100 * 10000;
+ settimeofday( &tv_set, NULL );
+
+ printf( "Date/time set to %02u.%02u.%02u %02u:%02u:%02u.%02u (UTC %+02ih)\n",
+ tp->mday, tp->month, tp->year,
+ tp->hour, tp->min, tp->sec, tp->sec100,
+ tp->offs_utc
+ );
+
+} // set_system_time
+
+
+
+static /*HDR*/
+int do_mbgsetsystime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ static int system_time_has_been_set;
+
+ PCPS_TIME t;
+ int ret_val = 0;
+ int rc;
+
+ if ( system_time_has_been_set )
+ goto done;
+
+ rc = mbg_get_time( dh, &t );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time" ) )
+ {
+ ret_val = -2;
+ goto done;
+ }
+
+ if ( t.status & PCPS_INVT )
+ {
+ // This may happen if the radio clock's battery
+ // was low or disconnected.
+ printf( "Radio clock has no valid date/time.\n" );
+ ret_val = -1;
+ goto done;
+ }
+
+ set_system_time( &t );
+ system_time_has_been_set = 1;
+
+ puts( "" );
+
+done:
+ mbg_close_device( &dh );
+
+ return 0;
+
+} // do_mbgsetsystime
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This program can be used to set the system time to the card's time.\n"
+ "This should be done only at boot time, before the NTP daemon is started."
+ );
+ mbg_print_help_options();
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int c;
+ int rc;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgsetsystime );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile b/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile
new file mode 100755
index 0000000..c10b915
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile
@@ -0,0 +1,39 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.7.1.2 2010/08/30 09:05:23 martin TEST $
+#
+# Description:
+# Makefile for mbgshowsignal.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.7.1.2 2010/08/30 09:05:23 martin
+# Revision 1.7.1.1 2010/08/30 08:22:00 martin
+# Revision 1.7 2009/07/24 10:31:17 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.6 2008/12/22 11:56:59 martin
+# Changed enumeration of source files.
+# Define MBGDEVIO_SIMPLE to avoid inclusion of unnecessary modules.
+# Revision 1.5 2007/03/02 11:45:10 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.4 2003/07/08 15:33:46 martin
+# Added gpsutils.c to the module list.
+# Revision 1.3 2003/04/25 10:21:06 martin
+# Updated source module list.
+# Revision 1.2 2002/11/21 14:56:31 martin
+# New targets install and uninstall.
+# Revision 1.1 2001/09/17 15:08:09 martin
+#
+#########################################################################
+
+TARGET = mbgshowsignal
+INST_DIR = /usr/local/bin
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c b/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c
new file mode 100755
index 0000000..308fec8
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c
@@ -0,0 +1,182 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgshowsignal.c 1.8 2009/09/29 15:02:15 martin REL_M $
+ *
+ * Description:
+ * Main file for mbgshowsignal program which demonstrates how to
+ * access a Meinberg device via IOCTL calls and show the modulation
+ * signal (second marks) of a longwave receiver, e.g. for DCF77.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgshowsignal.c $
+ * Revision 1.8 2009/09/29 15:02:15 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.7 2009/07/24 09:50:09 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.6 2009/06/19 12:38:52 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.5 2009/03/19 17:04:26 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Revision 1.4 2008/12/22 12:44:43 martin
+ * Changed ealier program name mbgdcfmod to mbgshowsignal.
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.3 2007/07/24 09:32:11 martin
+ * Updated copyright to include 2007.
+ * Revision 1.2 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.1 2001/09/17 15:08:09 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static const char *pname = "mbgshowsignal";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2001-2009";
+
+
+
+static /*HDR*/
+int show_modulation( MBG_DEV_HANDLE dh )
+{
+ static time_t prv_sys_t;
+ time_t sys_t;
+ uchar status_port; // current value of the clock's status port
+ PCPS_TIME t;
+ int signal;
+ int rc = mbg_get_status_port( dh, &status_port ); // read status port
+
+ if ( mbg_ioctl_err( rc, "mbg_get_status_port" ) )
+ return -1;
+
+ // show signal only once per second
+ sys_t = time( NULL );
+
+ if ( sys_t == prv_sys_t )
+ return 0;
+
+ prv_sys_t = sys_t;
+
+ rc = mbg_get_time( dh, &t );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time" ) )
+ return -1;
+
+
+ // The current value of the modulation (second mark) is returned
+ // in a single bit of the status port, so ignore the other bits.
+ printf( "\rMod: %c", ( status_port & PCPS_ST_MOD ) ? '*' : '_' );
+
+ signal = t.signal - PCPS_SIG_BIAS;
+
+ if ( signal < 0 )
+ signal = 0;
+ else
+ if ( signal > PCPS_SIG_MAX )
+ signal = PCPS_SIG_MAX;
+
+ printf( " Signal: %u%% ", signal * 100 / PCPS_SIG_MAX );
+
+ return 0;
+
+} // show_modulation
+
+
+
+static /*HDR*/
+int do_mbgshowsignal( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int has_mod = 0;
+ int rc = mbg_dev_has_mod( dh, &has_mod );
+
+ if ( mbg_ioctl_err( rc, "mbg_dev_has_mod" ) )
+ goto fail;
+
+ if ( !has_mod )
+ {
+ printf( "This device does not support monitoring signal modulation.\n" );
+ goto done;
+ }
+
+ printf( "\nMonitoring signal modulation:\n" );
+
+ for (;;)
+ if ( show_modulation( dh ) < 0 )
+ goto fail;
+
+done:
+ return 0;
+
+fail:
+ return -1;
+
+} // do_mbgshowsignal
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This program displays the modulation signal of cards which receive\n"
+ "a slowly modulated input signal, e.g. the longwave signal from DCF77.\n"
+ );
+ mbg_print_help_options();
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int c;
+ int rc;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgshowsignal );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbgstatus/Makefile b/src/external/bsd/meinberg/dist/mbgstatus/Makefile
new file mode 100755
index 0000000..3501003
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgstatus/Makefile
@@ -0,0 +1,50 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.7.1.4 2010/08/30 09:05:24 martin TEST $
+#
+# Description:
+# Makefile for mbgstatus.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.7.1.4 2010/08/30 09:05:24 martin
+# Revision 1.7.1.3 2010/08/30 08:20:32 martin
+# Revision 1.7.1.2 2010/08/24 08:35:11 martin
+# This basically builds kernel modules and user space apps correctly.
+# However, there's still an absolute path specification which needs
+# to be resolved.
+# Revision 1.7.1.1 2010/08/24 08:02:05 martin
+# Revision 1.7 2009/07/24 10:31:17 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.6 2008/12/22 11:54:32 martin
+# Changed enumeration of source files.
+# Revision 1.5 2007/03/02 11:45:10 martin
+# Parameter "DEBUG=1" lets the target be built with debug enabled.
+# Revision 1.4 2006/08/22 09:06:07 martin
+# Added new library module mbgmktm.c.
+# Revision 1.3 2003/04/25 10:21:06 martin
+# Updated source module list.
+# Revision 1.2 2002/11/21 14:56:31 martin
+# New targets install and uninstall.
+# Revision 1.1 2001/09/17 15:08:59 martin
+#
+#########################################################################
+
+TARGET = mbgstatus
+INST_DIR = /usr/local/bin
+
+OBJS := $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+OBJS += pcpsutil.o
+OBJS += mbgmktm.o
+OBJS += pcpslstr.o
+OBJS += parmpcps.o
+OBJS += parmgps.o
+OBJS += ctrydttm.o
+OBJS += ctry.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c b/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c
new file mode 100755
index 0000000..2409c5c
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c
@@ -0,0 +1,817 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgstatus.c 1.13.1.8 2011/03/03 10:01:23 daniel TRASH $
+ *
+ * Description:
+ * Main file for mbgstatus program which demonstrates how to
+ * access a Meinberg device via IOCTL calls and prints device
+ * information.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgstatus.c $
+ * Revision 1.13.1.8 2011/03/03 10:01:23 daniel
+ * Indicate Unicast role in PTP port state
+ * Revision 1.13.1.7 2011/02/07 12:10:58 martin
+ * Use mbg_get_ptp_status() API call.
+ * Revision 1.13.1.6 2010/11/25 14:54:51 martin
+ * Revision 1.13.1.5 2010/11/05 12:54:22 martin
+ * Introduce "verbose" flag and associated command line parameter -v.
+ * Revision 1.13.1.4 2010/10/15 11:28:56 martin
+ * Display UTC offs from IRIG signal.
+ * Revision 1.13.1.3 2010/08/30 08:22:24 martin
+ * Revision 1.13.1.2 2010/08/11 15:06:49 martin
+ * Preliminarily display raw IRIG data, if supported by the device.
+ * Revision 1.13.1.1 2010/02/17 14:11:43 martin
+ * Cosmetics ...
+ * Revision 1.13 2009/09/29 15:02:16 martin
+ * Updated version number to 3.4.0.
+ * Revision 1.12 2009/07/24 14:02:59 martin
+ * Display LAN and PTP status of PTP cards.
+ * Updated version number to 3.3.0.
+ * Revision 1.11 2009/06/19 14:20:36 martin
+ * Display raw IRIG time with TCR cards which support this.
+ * Revision 1.10 2009/06/16 08:21:08 martin
+ * Intermediate version 3.1.0a.
+ * Display IRIG debug status, if supported by the card.
+ * Revision 1.9 2009/03/20 11:35:41 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Display signal source after signal level.
+ * Display GPS UTC parameter info, if supported by the card.
+ * Display IRIG control bits, if supported by the card.
+ * Revision 1.8 2008/12/22 12:48:18 martin
+ * Updated description, copyright, revision number and string.
+ * Use unified functions from toolutil module.
+ * Warn if a PCI Express device with unsafe IRQ support is detected.
+ * Account for signed irq_num.
+ * Accept device name(s) on the command line.
+ * Don't use printf() without format, which migth produce warnings
+ * with newer gcc versions.
+ * Revision 1.7 2007/07/24 09:33:52 martin
+ * Fixed display of port and IRQ resources.
+ * Updated copyright to include 2007.
+ * Revision 1.6 2006/03/10 12:38:22 martin
+ * Fixed printing of sign in print_position().
+ * Revision 1.5 2004/11/08 15:41:56 martin
+ * Modified formatted printing of date/time string.
+ * Using type casts to avoid compiler warnings.
+ * Revision 1.4 2003/07/30 08:16:39 martin
+ * Also displays oscillator DAC values for GPS.
+ * Revision 1.3 2003/07/08 15:38:57 martin
+ * Call mbg_find_devices().
+ * Account for swap_doubles() now being called inside
+ * the mbgdevio API functions.
+ * Show IRQ number assigned to a device.
+ * Revision 1.2 2003/04/25 10:28:05 martin
+ * Use new functions from mbgdevio library.
+ * New program version v2.1.
+ * Revision 1.1 2001/09/17 15:08:59 martin
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <mbgtime.h>
+#include <pcpslstr.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static const char *pname = "mbgstatus";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2001-2009";
+
+static unsigned int verbose;
+
+static const char *ref_name[N_PCPS_REF]= PCPS_REF_NAMES_ENG;
+static const char *icode_rx_names[N_ICODE_RX] = DEFAULT_ICODE_RX_NAMES;
+static const char *osc_name[N_GPS_OSC] = DEFAULT_GPS_OSC_NAMES;
+
+static int year_limit = 1990;
+
+static int max_ref_offs_h = MBG_REF_OFFS_MAX / MINS_PER_HOUR;
+
+LANGUAGE language;
+CTRY ctry;
+
+
+
+static /*HDR*/
+void print_pcps_time( const char *s, const PCPS_TIME *tp, const char *tail )
+{
+ const char *fmt = "%s";
+ char ws[256];
+
+ if ( s )
+ printf( fmt, s );
+
+ printf( fmt, pcps_date_time_str( ws, tp, year_limit, pcps_tz_name( tp, PCPS_TZ_NAME_FORCE_UTC_OFFS, 0 ) ) );
+
+ if ( verbose > 1 )
+ printf( ", st: 0x%02lX", (ulong) tp->status );
+
+ if ( tail )
+ printf( fmt, tail );
+
+} // print_pcps_time
+
+
+
+static /*HDR*/
+void print_dms( const char *s, const DMS *p, const char *tail )
+{
+ const char *fmt = "%s";
+
+ printf( "%s %c %3i deg %02i min %05.2f sec",
+ s,
+ p->prefix,
+ p->deg,
+ p->min,
+ p->sec
+ );
+
+ if ( tail )
+ printf( fmt, tail );
+
+} // print_dms
+
+
+
+static /*HDR*/
+void print_position( const char *s, const POS *p, const char *tail )
+{
+ const char *fmt = "%s";
+ double r2d = 180 / PI;
+
+
+ if ( s )
+ printf( fmt, s );
+
+ if ( verbose > 0 )
+ {
+ printf( " x: %.0fm y: %.0fm z: %.0fm",
+ p->xyz[XP], p->xyz[YP], p->xyz[ZP] );
+
+ if ( tail )
+ printf( fmt, tail );
+ }
+
+ // LLA latitude and longitude are in radians, convert to degrees
+ printf( " lat: %+.4f lon: %+.4f alt: %.0fm",
+ p->lla[LAT] * r2d, p->lla[LON] * r2d, p->lla[ALT] );
+
+ if ( tail )
+ printf( fmt, tail );
+
+ print_dms( " latitude: ", &p->latitude, tail );
+ print_dms( " longitude:", &p->longitude, tail );
+
+} // print_position
+
+
+
+/*HDR*/
+int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *addr )
+{
+ int n;
+
+ n = snprintf( s, max_len, "%i.%i.%i.%i",
+ BYTE_OF( *addr, 3 ),
+ BYTE_OF( *addr, 2 ),
+ BYTE_OF( *addr, 1 ),
+ BYTE_OF( *addr, 0 )
+ );
+
+ return n;
+
+} // snprint_ip4_addr
+
+
+
+static /*HDR*/
+void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char *tail )
+{
+ const char *status_fmt = "Status info: %s%s\n";
+ const char *status_err = "*** ";
+ const char *status_ok = "";
+ PCPS_TIME t;
+ PCPS_STATUS_STRS strs;
+ int signal;
+ int ref_type;
+ int i;
+ int rc = mbg_get_time( dh, &t );
+ if ( mbg_ioctl_err( rc, "mbg_get_time" ) )
+ return;
+
+
+ print_pcps_time( "Date/time: ", &t, tail );
+
+ if ( ( verbose > 0 ) && _pcps_has_hr_time( pdev ) )
+ {
+ PCPS_HR_TIME ht;
+ char ws[80];
+
+ rc = mbg_get_hr_time( dh, &ht );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) )
+ return;
+
+ mbg_snprint_hr_time( ws, sizeof( ws ), &ht );
+ printf( "Local HR time: %s", ws );
+
+ if ( verbose > 1 )
+ printf( ", st: 0x%04lX", (ulong) ht.status );
+
+ printf( "%s", tail );
+ }
+
+ signal = t.signal - PCPS_SIG_BIAS;
+
+ if ( signal < 0 )
+ signal = 0;
+ else
+ if ( signal > PCPS_SIG_MAX )
+ signal = PCPS_SIG_MAX;
+
+ ref_type = _pcps_ref_type( pdev );
+
+ if ( ref_type >= N_PCPS_REF )
+ ref_type = PCPS_REF_NONE;
+
+ printf( "Signal: %u%% (%s", signal * 100 / PCPS_SIG_MAX, ref_name[ref_type] );
+
+ if ( _pcps_is_irig_rx( pdev ) )
+ {
+ IRIG_INFO irig_rx_info;
+ MBG_REF_OFFS ref_offs;
+
+ rc = mbg_get_irig_rx_info( dh, &irig_rx_info );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ int idx = irig_rx_info.settings.icode;
+
+ if ( idx < N_ICODE_RX )
+ {
+ printf( " %s", icode_rx_names[idx] );
+
+ if ( !( MSK_ICODE_RX_HAS_TZI & ( 1UL << idx ) ) )
+ {
+ if ( _pcps_has_ref_offs( pdev ) )
+ {
+ rc = mbg_get_ref_offs( dh, &ref_offs );
+
+ if ( rc == MBG_SUCCESS )
+ {
+ int ref_offs_h = ref_offs / MINS_PER_HOUR;
+
+ if ( abs( ref_offs_h ) > max_ref_offs_h )
+ printf( ", ** UTC offs not configured **" );
+ else
+ printf( ", UTC%+ih", ref_offs_h );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ puts( ")" );
+
+ if ( _pcps_has_irig_time( pdev ) )
+ {
+ PCPS_IRIG_TIME it;
+
+ rc = mbg_get_irig_time( dh, &it );
+
+ if ( !mbg_ioctl_err( rc, "mbg_get_irig_time" ) )
+ printf( "Raw IRIG time: yday %u, %02u:%02u:%02u\n",
+ it.yday, it.hour, it.min, it.sec );
+ }
+
+ if ( _pcps_is_irig_rx( pdev ) )
+ {
+ printf( status_fmt,
+ ( signal < PCPS_SIG_ERR ) ? status_err : status_ok,
+ ( signal < PCPS_SIG_ERR ) ? "NO INPUT SIGNAL"
+ : "Input signal available" );
+ }
+ else
+ {
+ printf( status_fmt,
+ ( signal < PCPS_SIG_ERR ) ? status_err : status_ok,
+ ( signal < PCPS_SIG_ERR ) ? "ANTENNA IS NOT CONNECTED"
+ : "Antenna is connected" );
+ }
+
+ // Evaluate the status code and setup status messages.
+ pcps_status_strs( t.status, _pcps_time_is_read( &t ),
+ _pcps_is_gps( pdev ), &strs );
+
+ // Print the status messages.
+ for ( i = 0; i < N_PCPS_STATUS_STR; i++ )
+ {
+ PCPS_STATUS_STR *pstr = &strs.s[i];
+ if ( pstr->cp )
+ printf( status_fmt,
+ pstr->is_err ? status_err : status_ok,
+ pstr->cp );
+ }
+
+} // show_time_and_status
+
+
+
+static /*HDR*/
+void show_sync_time( MBG_DEV_HANDLE dh, const char *tail )
+{
+ PCPS_TIME t;
+ int rc = mbg_get_sync_time( dh, &t );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_sync_time" ) )
+ return;
+
+ print_pcps_time( "Last sync: ", &t, tail );
+
+} // show_sync_time
+
+
+
+static /*HDR*/
+void show_ext_stat_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *tail )
+{
+ const char *fmt = "%s";
+ RECEIVER_INFO ri;
+ STAT_INFO si = { 0 };
+ char ws[80];
+ char *mode_name;
+
+ int rc = mbg_setup_receiver_info( dh, p_dev, &ri );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_stat_info" ) )
+ return;
+
+
+ if ( _pcps_is_gps( p_dev ) )
+ {
+ rc = mbg_get_gps_stat_info( dh, &si );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_stat_info" ) )
+ return;
+
+ switch ( si.mode )
+ {
+ case AUTO_166: mode_name = "Normal Operation"; break;
+ case WARM_166: mode_name = "Warm Boot"; break;
+ case COLD_166: mode_name = "Cold Boot"; break;
+
+ default: // This should never happen!
+ sprintf( ws, "Unknown mode of operation: %02Xh", si.mode );
+ mode_name = ws;
+
+ } // switch
+
+ printf( "%s, %i sats in view, %i sats used\n", mode_name, si.svs_in_view, si.good_svs );
+ }
+
+ printf( "Osc type: %s", osc_name[( ri.osc_type < N_GPS_OSC ) ? ri.osc_type : GPS_OSC_UNKNOWN] );
+
+ if ( _pcps_is_gps( p_dev ) )
+ {
+ printf( ", DAC cal: %+i, fine: %+i",
+ (int) ( si.dac_cal - OSC_DAC_BIAS ),
+ (int) ( si.dac_val - OSC_DAC_BIAS ) );
+ }
+
+ puts( "" );
+
+ if ( tail )
+ printf( fmt, tail );
+
+} // show_ext_stat_info
+
+
+
+static /*HDR*/
+void show_gps_pos( MBG_DEV_HANDLE dh, const char *tail )
+{
+ POS pos;
+ int rc = mbg_get_gps_pos( dh, &pos );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_gps_pos" ) )
+ return;
+
+ print_position( "Receiver Position:\n", &pos, tail );
+
+} // show_gps_pos
+
+
+
+static /*HDR*/
+void show_utc_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ UTC utc;
+
+ int rc = mbg_get_utc_parm( dh, &utc );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_utc_parm" ) )
+ return;
+
+ if ( !utc.valid )
+ {
+ puts( "** UTC parameters not valid" );
+ return;
+ }
+
+ if ( verbose > 1 )
+ {
+ //##++++ utc.delta_tls = utc.delta_tlsf - 1;
+
+ printf( "CSUM: %04X, valid: %04X\n", utc.csum, utc.valid );
+ printf( "t0t: %u|%u.%07u, A0: %g A1: %g\n",
+ utc.t0t.wn, utc.t0t.sec, utc.t0t.tick,
+ utc.A0, utc.A1 );
+ printf( "WNlsf: %u, DN: %u, offs: %i/%i\n",
+ utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf );
+ }
+
+ if ( utc.delta_tls != utc.delta_tlsf )
+ {
+ // a leap second is currently being announced
+ time_t t_ls = (time_t) utc.WNlsf * SECS_PER_WEEK
+ + (time_t) utc.DNt * SECS_PER_DAY
+ + GPS_SEC_BIAS - 1;
+
+ struct tm *tm = gmtime( &t_ls );
+
+ printf( "UTC offset transition from %is to %is due to leap second\n"
+ "%s at UTC midnight at the end of %04i-%02i-%02i.\n",
+ utc.delta_tls, utc.delta_tlsf,
+ ( utc.delta_tls < utc.delta_tlsf ) ? "insertion" : "deletion",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday
+ );
+ }
+ else
+ printf( "UTC offset parameter: %is, no leap second announced.\n", utc.delta_tls );
+
+} // show_utc_info
+
+
+
+static /*HDR*/
+void show_irig_ctrl_bits( MBG_DEV_HANDLE dh )
+{
+ MBG_IRIG_CTRL_BITS irig_ctrl_bits;
+
+ int rc = mbg_get_irig_ctrl_bits( dh, &irig_ctrl_bits );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_irig_ctrl_bits" ) )
+ return;
+
+ printf( "IRIG control bits: %08lX (hex, LSB first)", (ulong) irig_ctrl_bits );
+ printf( ", TFOM: 0x%X", _pcps_tfom_from_irig_ctrl_bits( &irig_ctrl_bits ) );
+ printf( "\n" );
+
+} // show_irig_ctrl_bits
+
+
+
+static /*HDR*/
+char *str_raw_irig_utc_offs_hours( char *s, int max_len, const MBG_RAW_IRIG_DATA *p )
+{
+ int n;
+ long offs = ( p->data_bytes[8] & 0x08 )
+ | ( ( p->data_bytes[8] >> 2 ) & 0x04 )
+ | ( ( p->data_bytes[8] >> 4 ) & 0x02 )
+ | ( ( p->data_bytes[8] >> 6 ) & 0x01 );
+
+ n = snprintf( s, max_len, "%c%li", ( p->data_bytes[8] & 0x80 ) ? '-' : '+', offs );
+
+ if ( p->data_bytes[8] & 0x02 )
+ n += snprintf( &s[n], max_len - n, "%s", ".5" );
+
+ return s;
+
+} // str_raw_irig_utc_offs_hours
+
+
+
+static /*HDR*/
+void show_raw_irig_data( MBG_DEV_HANDLE dh )
+{
+ MBG_RAW_IRIG_DATA raw_irig_data;
+ char ws[80];
+ int i;
+
+ int rc = mbg_get_raw_irig_data( dh, &raw_irig_data );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_raw_irig_data" ) )
+ return;
+
+ printf( "Raw IRIG data:" );
+
+ for ( i = 0; i < sizeof( raw_irig_data ); i++ )
+ printf( " %02X", raw_irig_data.data_bytes[i] );
+
+ printf( " (hex)" );
+ printf( ", TFOM: 0x%X", _pcps_tfom_from_raw_irig_data( &raw_irig_data ) );
+ printf( ", UTC offs: %sh", str_raw_irig_utc_offs_hours( ws, sizeof( ws ), &raw_irig_data ) );
+ printf( "\n" );
+
+} // show_raw_irig_data
+
+
+
+static /*HDR*/
+void show_irig_debug_status( MBG_DEV_HANDLE dh )
+{
+ static const char *status_str[N_MBG_DEBUG_BIT] = MBG_DEBUG_STATUS_STRS;
+
+ MBG_DEBUG_STATUS st;
+ int i;
+ int rc = _mbg_generic_read_var( dh, PCPS_GET_DEBUG_STATUS, st );
+
+ if ( mbg_ioctl_err( rc, "show_irig_debug_status" ) )
+ return;
+
+ printf( "Debug status (hex): %08lX\n", (ulong) st );
+
+ for ( i = 0; i < N_MBG_DEBUG_BIT; i++ )
+ if ( st & ( 1UL << i ) )
+ printf( " %s\n", status_str[i] );
+
+} // show_irig_debug_status
+
+
+
+static /*HDR*/
+void show_lan_intf_state( MBG_DEV_HANDLE dh )
+{
+ IP4_SETTINGS ip4_settings;
+ LAN_IF_INFO lan_if_info;
+ char ws[100];
+
+ int rc = mbg_get_ip4_state( dh, &ip4_settings );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ip4_state" ) )
+ return;
+
+ rc = mbg_get_lan_if_info( dh, &lan_if_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_lan_if_info" ) )
+ return;
+
+
+ printf( "On-board LAN interface settings:\n" );
+
+ snprintf( ws, sizeof( ws ), "%02X-%02X-%02X-%02X-%02X-%02X",
+ lan_if_info.mac_addr[0],
+ lan_if_info.mac_addr[1],
+ lan_if_info.mac_addr[2],
+ lan_if_info.mac_addr[3],
+ lan_if_info.mac_addr[4],
+ lan_if_info.mac_addr[5]
+ );
+ printf( " MAC Address: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr );
+ printf( " IP Address: %s%s\n", ws, ( ip4_settings.flags & IP4_MSK_DHCP ) ?
+ " (DHCP)" : "" );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.netmask );
+ printf( " Net Mask: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.broad_addr );
+ printf( " Broadcast Addr: %s\n", ws );
+
+ snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.gateway );
+ printf( " Gateway: %s\n", ws );
+
+ printf( " Link detected: %s\n", ( ip4_settings.flags & IP4_MSK_LINK ) ? "YES" : "NO" );
+
+} // show_lan_intf_state
+
+
+
+static /*HDR*/
+void show_ptp_state( MBG_DEV_HANDLE dh )
+{
+ static const char *ptp_stat_str[N_PTP_PORT_STATE] = PTP_PORT_STATE_STRS;
+ char ws[100];
+ const char *cp;
+ int ptp_state_available;
+ PTP_STATE ptp_state;
+ PTP_CFG_INFO ptp_info;
+
+ int rc = mbg_get_ptp_state( dh, &ptp_state );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_state" ) )
+ return;
+
+ rc = mbg_get_ptp_cfg_info( dh, &ptp_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_ptp_info" ) )
+ return;
+
+ printf( "PTP port status:\n" );
+
+ ptp_state_available = ( ptp_state.port_state == PTP_PORT_STATE_SLAVE );
+
+ printf( " Port mode: %s%s\n", ( ptp_state_available && ptp_info.settings.ptp_role == PTP_ROLE_UNICAST_SLAVE ) ? "Unicast" : "",
+ ( ptp_state.port_state < N_PTP_PORT_STATE ) ? ptp_stat_str[ptp_state.port_state] : "(undefined)" );
+
+ cp = ptp_state_available ? ws : str_not_avail;
+
+ snprintf( ws, sizeof( ws ), "%02X-%02X-%02X-%02X-%02X-%02X",
+ ptp_state.gm_identity.b[0],
+ ptp_state.gm_identity.b[1],
+ ptp_state.gm_identity.b[2],
+ ptp_state.gm_identity.b[5],
+ ptp_state.gm_identity.b[6],
+ ptp_state.gm_identity.b[7]
+ );
+ printf( " Grandmaster MAC: %s\n", cp );
+
+
+ snprintf( ws, sizeof( ws ), "%c%li.%09li s",
+ _nano_time_negative( &ptp_state.path_delay ) ? '-' : '+',
+ labs( (long) ptp_state.path_delay.secs ),
+ labs( (long) ptp_state.path_delay.nano_secs )
+ );
+ printf( " PTP path delay: %s\n", cp );
+
+
+ snprintf( ws, sizeof( ws ), "%c%li.%09li s",
+ _nano_time_negative( &ptp_state.offset ) ? '-' : '+',
+ labs( (long) ptp_state.offset.secs ),
+ labs( (long) ptp_state.offset.nano_secs )
+ );
+ printf( " PTP time offset: %s\n", cp );
+
+} // show_ptp_state
+
+
+
+static /*HDR*/
+int check_irq_unsafe( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ PCPS_IRQ_STAT_INFO irq_stat_info;
+ int ret_val = 0;
+ int rc = mbg_get_irq_stat_info( dh, &irq_stat_info );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_irq_stat_info" ) )
+ return -1;
+
+ if ( irq_stat_info & PCPS_IRQ_STAT_UNSAFE )
+ {
+ static const char *warn_line = "************************************************************************************";
+
+ puts( "" );
+ puts( warn_line );
+
+ printf(
+ "** WARNING!\n"
+ "**\n"
+ "** Device %s with S/N %s has a firmware version and ASIC version\n"
+ "** which do not allow safe operation with hardware interrupts (IRQs) enabled.\n"
+ "**\n"
+ "** Please see http://www.meinberg.de/english/info/pex-upgrades.htm\n"
+ "** for information how the card can easily be upgraded, or contact\n"
+ "** Meinberg support (Email: support@meinberg.de) or your local\n"
+ "** representative.\n"
+ ,
+ _pcps_type_name( p_dev ), _pcps_sernum( p_dev )
+ );
+
+ if ( irq_stat_info & PCPS_IRQ_STAT_ENABLED )
+ {
+ printf(
+ "**\n"
+ "** Interrupts are currently enabled for this card (NTP daemon running?)\n"
+ "** so other access is inhibited to prevent the system from hanging.\n"
+ );
+
+ ret_val = -1;
+ }
+
+ puts( warn_line );
+ puts( "" );
+ }
+
+ return ret_val;
+
+} // check_irq_unsafe
+
+
+
+static /*HDR*/
+int do_mbgstatus( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ int ret_val = 0;
+
+ if ( check_irq_unsafe( dh, p_dev ) < 0 )
+ goto done;
+
+ if ( _pcps_has_gps_data( p_dev ) )
+ show_ext_stat_info( dh, p_dev, NULL );
+
+ show_time_and_status( dh, p_dev, "\n" );
+ show_sync_time( dh, "\n" );
+
+ if ( _pcps_is_gps( p_dev ) )
+ show_gps_pos( dh, "\n" );
+
+ if ( _pcps_has_utc_parm( p_dev ) )
+ show_utc_info( dh, p_dev );
+
+ if ( _pcps_has_irig_ctrl_bits( p_dev ) )
+ show_irig_ctrl_bits( dh );
+
+ if ( _pcps_has_raw_irig_data( p_dev ) )
+ show_raw_irig_data( dh );
+
+ if ( _pcps_is_irig_rx( p_dev ) )
+ show_irig_debug_status( dh );
+
+ if ( _pcps_has_lan_intf( p_dev ) )
+ show_lan_intf_state( dh );
+
+ if ( _pcps_has_ptp( p_dev ) )
+ show_ptp_state( dh );
+
+done:
+ return ret_val;
+
+} // do_mbgstatus
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This program prints status information for a device.\n"
+ "The displayed information depends on the type of the card."
+ );
+ mbg_print_help_options();
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int c;
+ int rc;
+
+ ctry_setup( 0 );
+ language = LNG_ENGLISH;
+ ctry.dt_fmt = DT_FMT_YYYYMMDD;
+ ctry.dt_sep = '-';
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "vh?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'v':
+ verbose++;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+
+ if ( verbose )
+ pcps_date_time_dist = 1;
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgstatus );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbgsvcd/Makefile b/src/external/bsd/meinberg/dist/mbgsvcd/Makefile
new file mode 100755
index 0000000..d8a8fe8
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgsvcd/Makefile
@@ -0,0 +1,31 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.1.1.2.1.1 2010/09/20 12:07:10 stefan TEST $
+#
+# Description:
+# Makefile for mbgsvcd.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.1.1.2.1.1 2010/09/20 12:07:10 stefan
+# Updated for use with latest base Makefile.
+# Revision 1.1.1.2 2010/08/30 09:05:24 martin
+# Revision 1.1.1.1 2010/08/30 08:22:06 martin
+# Revision 1.1 2010/02/03 16:07:18 daniel
+# Revision 1.1 2009/09/29 08:34:23 martin
+#
+#########################################################################
+
+TARGET = mbgsvcd
+INST_TO_BIN = 1
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+OBJS += mbgmktm.o
+OBJS += pcpsmktm.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c b/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c
new file mode 100755
index 0000000..1a4921e
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c
@@ -0,0 +1,472 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgsvcd.c 1.3.1.3 2011/03/25 11:05:24 martin TRASH $
+ *
+ * Description:
+ * Main file for mbgsvcd which compares the system time to a PCI card's
+ * time and transfers this data pair to the SHM driver of the ntpd.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgsvcd.c $
+ * Revision 1.3.1.3 2011/03/25 11:05:24 martin
+ * Optionally support timespec for sys time.
+ * Cleanup.
+ * Revision 1.3.1.2 2011/03/23 16:30:40 martin
+ * Use /var/run as directory for the lockfile.
+ * Revision 1.3.1.1 2010/04/26 14:37:41 martin
+ * Print PC cycles counter frequency at program start.
+ * Revision 1.3 2010/03/03 14:59:36 martin
+ * Support -p parameter to pretend sync.
+ * Revision 1.2 2010/02/03 16:15:09 daniel
+ * Revision 1.1 2010/02/03 16:07:18 daniel
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+#include <pcpsmktm.h>
+
+// include system headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <syslog.h>
+
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#define NTPD_BASE 0x4e545030 /* "NTP0" */
+#define SHM_UNIT 0 /* SHM driver unit number (0..3) */
+#define MAX_SHM_REFCLOCKS 4
+
+#define RUNNING_DIR "/var/run"
+#define LOCK_FILE "mbgsvcd.pid"
+
+#define EXEC_TIME_SAMPLES 20
+
+static const char *pname = "mbgsvcd";
+static const char *pversion = "v1.2";
+static const char *pcopyright = "(c) Meinberg 2010-2011";
+
+static int sleep_intv = 1;
+static int pretend_sync;
+
+
+struct shmTime {
+ int mode; /* 0 - if valid set
+ * use values,
+ * clear valid
+ * 1 - if valid set
+ * if count before and after read of
+ * values is equal,
+ * use values
+ * clear valid
+ */
+ int count;
+ time_t clockTimeStampSec; /* external clock */
+ int clockTimeStampUSec; /* external clock */
+ time_t receiveTimeStampSec; /* internal clock, when external value was received */
+ int receiveTimeStampUSec; /* internal clock, when external value was received */
+ int leap;
+ int precision;
+ int nsamples;
+ int valid;
+ int dummy[10];
+};
+
+struct shmTime *shmTime[MAX_SHM_REFCLOCKS];
+
+
+static
+struct shmTime *getShmTime(int unit)
+{
+ int shmid = shmget( (key_t) ( NTPD_BASE + unit ),
+ sizeof( struct shmTime ), IPC_CREAT | 0644 );
+
+ if ( shmid == -1 )
+ {
+ syslog(LOG_ERR, "shmget failed\n");
+ return NULL;
+ }
+ else
+ {
+ struct shmTime *p = ( struct shmTime * ) shmat( shmid, 0, 0);
+
+ if ( (int) (long) p == -1 )
+ {
+ syslog(LOG_ERR, "shmat failed\n" );
+ return NULL;
+ }
+
+ syslog(LOG_INFO, "shmat(%d,0,0) succeeded\n", shmid);
+ return p;
+ }
+}
+
+
+
+static /*HDR*/
+void ntpshm_init( void )
+{
+ int i = 0;
+
+ syslog(LOG_INFO, "Initializing shared memory for ntpd");
+
+ for ( i = 0; i< MAX_SHM_REFCLOCKS; i++ )
+ shmTime[i] = getShmTime( i );
+
+} // ntpshm_init
+
+
+
+static /*HDR*/
+int ntpshm_alloc( void )
+{
+ int i;
+
+ for ( i = 0; i< MAX_SHM_REFCLOCKS; i++)
+ {
+ struct shmTime *p = shmTime[i];
+
+ if ( p )
+ {
+ memset( p, 0, sizeof( *p ) );
+
+ p->mode = 1;
+ p->precision = -5; /* initially 0.5 sec */
+ p->nsamples = 3; /* stages of median filter */
+
+ printf( "Shared memory %d initialized\n", i );
+ }
+ }
+
+ return 0;
+
+} // ntpshm_alloc
+
+
+
+static /*HDR*/
+int do_mbgsvctasks( void )
+{
+ MBG_PC_CYCLES_FREQUENCY cyc_freq;
+ MBG_TIME_INFO_HRT hrti;
+ PCPS_TIME_STAMP *p_ref_ts;
+ MBG_PC_CYCLES *p_ref_cyc;
+ MBG_SYS_TIME_CYCLES *p_sys_tic;
+ char ws[256];
+ double d_ref;
+ double d_sys;
+ int rc = 0;
+ int n_devices = 0;
+ MBG_DEV_HANDLE dhs[4];
+ PCPS_DEV devs[4];
+ int i,excnt;
+ double exec_limit = 30.0;
+ double exec_times[EXEC_TIME_SAMPLES];
+
+ n_devices = mbg_find_devices();
+
+ i = excnt = 0;
+
+ if ( n_devices == 0 )
+ {
+ printf("No devices found!\n");
+ goto done;
+ }
+
+ // Search for devices up to the maximum of supported NTP SHM refclocks
+ if ( n_devices > MAX_SHM_REFCLOCKS )
+ n_devices = MAX_SHM_REFCLOCKS;
+
+ syslog(LOG_INFO, "Found %d devices for NTPD", n_devices);
+
+ for ( i = 0; i < n_devices; i++ )
+ {
+ dhs[i] = mbg_open_device(i);
+ mbg_get_device_info( dhs[i], &devs[i] );
+ }
+
+ rc = mbg_get_default_cycles_frequency_from_dev( dhs[0], &cyc_freq );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_default_cycles_frequency_from_dev" ) )
+ goto done;
+
+ printf( "PC cycles counter clock frequency: %Lu Hz\n",
+ (unsigned long long) cyc_freq );
+
+ // Initialize NTP shared memory area
+ ntpshm_init();
+ ntpshm_alloc();
+
+ for (;;)
+ {
+ for ( i = 0; i < n_devices; i++ )
+ {
+ double ltcy_us;
+ double exec_us;
+ double ltcy_sec;
+ double exec_sec;
+ double d_ref_comp;
+ MBG_PC_CYCLES ltcy_cyc;
+ MBG_PC_CYCLES exec_cyc;
+ const char *cp;
+
+ if ( !_pcps_has_hr_time( &devs[i] ) )
+ {
+ printf( "This device does not support HR time stamps.\n" );
+ continue;
+ }
+
+
+ rc = mbg_get_time_info_hrt( dhs[i], &hrti );
+
+ if ( mbg_ioctl_err( rc, "mbg_get_time_info_..." ) )
+ continue;
+
+
+ p_ref_ts = &hrti.ref_hr_time_cycles.t.tstamp;
+ p_ref_cyc = &hrti.ref_hr_time_cycles.cycles;
+ p_sys_tic = &hrti.sys_time_cycles;
+
+ d_ref = (double) p_ref_ts->sec + ( (double) p_ref_ts->frac ) / (double) PCPS_HRT_BIN_FRAC_SCALE;
+
+ d_sys = (double) p_sys_tic->sys_time.tv_sec;
+ #if USE_TIMESPEC // use struct timespec
+ d_sys += (double) p_sys_tic->sys_time.tv_nsec / 1e9;
+ #else // use struct timeval
+ d_sys += (double) p_sys_tic->sys_time.tv_usec / 1e6;
+ #endif
+
+ ltcy_cyc = mbg_delta_pc_cycles( p_ref_cyc, &p_sys_tic->cyc_after );
+ exec_cyc = mbg_delta_pc_cycles( &p_sys_tic->cyc_after, &p_sys_tic->cyc_before );
+
+ ltcy_sec = ( (double) ltcy_cyc ) / (double) cyc_freq;
+ exec_sec = ( (double) exec_cyc ) / (double) cyc_freq;
+
+ // compensate latencies between time stamps ->
+ // normalize ref time to system time stamp
+ d_ref_comp = d_ref - ltcy_sec;
+
+ ltcy_us = ltcy_sec * 1e6;
+ exec_us = exec_sec * 1e6;
+
+ exec_times[excnt++] = exec_us;
+
+ if ( excnt == EXEC_TIME_SAMPLES )
+ {
+ exec_limit = 0;
+
+ for ( excnt = 0; excnt < EXEC_TIME_SAMPLES; excnt++ )
+ exec_limit += exec_times[excnt];
+
+ exec_limit /= ( (double) EXEC_TIME_SAMPLES );
+ exec_limit *= 1.7;
+ excnt = 0;
+ }
+
+
+ cp = "";
+
+ // check if refclock is sync and if exec time of the system time call was fast enough
+ if ( pretend_sync || ( ( ( hrti.ref_hr_time_cycles.t.status & PCPS_FREER ) == 0 )
+ && ( ( hrti.ref_hr_time_cycles.t.status & PCPS_SYNCD ) != 0 )
+ && ( exec_us < exec_limit ) ) )
+ {
+ struct shmTime *p = shmTime[i];
+
+ cp = " *";
+
+ // fill SHM structure
+ p->count++;
+ p->clockTimeStampSec = (time_t) d_ref_comp;
+ p->clockTimeStampUSec = (int) ( ( d_ref_comp - p->clockTimeStampSec ) * 1e6 ); // get µs from d_ref
+ p->receiveTimeStampSec = (time_t) p_sys_tic->sys_time.tv_sec;
+ #if USE_TIMESPEC // use struct timespec
+ p->receiveTimeStampUSec = (int) ( p_sys_tic->sys_time.tv_nsec / 1000 );
+ #else // use struct timeval
+ p->receiveTimeStampUSec = (int) p_sys_tic->sys_time.tv_usec;
+ #endif
+
+ // patch precision value according to the ref time accuracy
+ if ( _pcps_is_lwr( &devs[i] ) )
+ p->precision = -8;
+ else if (_pcps_is_irig_rx( &devs[i] ) )
+ {
+ if ( _pcps_is_usb( &devs[i] ) )
+ p->precision = -10;
+ else
+ p->precision = -18;
+ }
+ else
+ p->precision = -20;
+
+ p->count++;
+ p->valid = 1;
+ }
+
+ mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ref_ts );
+
+ printf( "%-9s: %s: %.7f-%.7f: %+.7f %+.7f, "
+ "ltcy: %.2f us, exec: %.2f us, limit: %.2f us%s\n",
+ _pcps_type_name( &devs[i] ), ws, d_ref, d_sys,
+ d_ref - d_sys, d_ref_comp - d_sys,
+ ltcy_us, exec_us, exec_limit, cp );
+
+ usleep( 10 );
+ }
+
+ printf("\n");
+
+ if ( sleep_intv )
+ sleep( sleep_intv );
+ }
+
+done:
+ for ( i = 0; i < n_devices; i++ )
+ mbg_close_device( &dhs[i] );
+
+ return rc;
+
+} // do_mbgsvctasks
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This deamon reads a time stamp from every refclock together.\n"
+ "with an associated system time stamp and transfers it to the SHM\n"
+ "refclock driver of NTP.\n"
+ "This works only with cards which support high resolution time stamps."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-f", "run program in foreground" );
+ mbg_print_opt_info( "-s num", "sleep num seconds between calls" );
+ mbg_print_opt_info( "-p", "pretend device is always synchronized" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+static /*HDR*/
+void startup_daemon( void )
+{
+ int i,lfp;
+ char str[1024];
+
+ if (getppid()==1)
+ return; /* already a daemon */
+
+ printf ("Daemon mode, backgrounding ... \n");
+ i=fork();
+
+ if (i<0)
+ exit(1); /* fork error */
+
+ if (i>0)
+ exit(0); /* parent exits */
+
+ /* child (daemon) continues */
+ setsid(); /* obtain a new process group */
+ for (i=getdtablesize(); i>=0; --i)
+ close(i); /* close all descriptors */
+
+ i=open("/dev/null",O_RDWR); dup(i); dup(i); /* handle standart I/O */
+
+ umask(027); /* set newly created file permissions */
+ chdir(RUNNING_DIR); /* change running directory */
+
+ lfp = open(LOCK_FILE,O_RDWR|O_CREAT,0640);
+
+ if (lfp<0)
+ exit(1); /* can not open */
+
+ if (lockf(lfp,F_TLOCK,0)<0)
+ {
+ syslog(LOG_ERR, "Lock file already exists, another instance of this daemon seems to be running");
+ closelog();
+ exit(0); /* can not lock */
+ }
+
+ /* first instance continues */
+ sprintf(str,"%d\n",getpid());
+ write(lfp,str,strlen(str)); /* record pid to lockfile */
+
+ signal(SIGCHLD,SIG_IGN); /* ignore child */
+ signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
+ signal(SIGTTOU,SIG_IGN);
+ signal(SIGTTIN,SIG_IGN);
+
+} // startup_daemon
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+ int foreground = 0;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ #if ( USE_TIMESPEC )
+ printf( "(using nanosecond resolution)\n\n" );
+ #endif
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "fps:h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'f':
+ foreground = 1;
+ break;
+
+ case 'p':
+ pretend_sync = 1;
+ break;
+
+ case 's':
+ sleep_intv = atoi( optarg );
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ if ( foreground == 0 )
+ startup_daemon();
+
+ syslog( LOG_INFO, "Starting Meinberg Service Daemon %s %s %s", pname, pversion, pcopyright );
+
+ rc = do_mbgsvctasks();
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile b/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile
new file mode 100755
index 0000000..75d6673
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile
@@ -0,0 +1,33 @@
+
+#########################################################################
+#
+# $Id: Makefile 1.2.1.2.1.1 2010/09/20 12:07:14 stefan TEST $
+#
+# Description:
+# Makefile for mbgxhrtime.
+#
+# -----------------------------------------------------------------------
+# $Log: Makefile $
+# Revision 1.2.1.2.1.1 2010/09/20 12:07:14 stefan
+# Updated for use with latest base Makefile.
+# Revision 1.2.1.2 2010/08/30 09:05:24 martin
+# Revision 1.2.1.1 2010/08/30 08:22:11 martin
+# Revision 1.2 2009/07/24 10:31:17 martin
+# Moved declarations to a common file which is now included.
+# Revision 1.1 2008/12/22 11:05:24 martin
+# Initial revision.
+#
+#########################################################################
+
+TARGET = mbgxhrtime
+INST_TO_BIN = 1
+
+USE_THREAD_API = 1
+
+OBJS = $(TARGET).o
+OBJS += mbgdevio.o
+OBJS += toolutil.o
+OBJS += gpsutils.o
+
+BASEDIR := ..
+include $(BASEDIR)/Makefile
diff --git a/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c b/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c
new file mode 100755
index 0000000..bceb331
--- /dev/null
+++ b/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c
@@ -0,0 +1,334 @@
+
+/**************************************************************************
+ *
+ * $Id: mbgxhrtime.c 1.5 2009/09/29 14:25:07 martin REL_M $
+ *
+ * Description:
+ * Main file for mbgxhrtime program which demonstrates how to retrieve
+ * fast and accurate timestamps.
+ *
+ * This program starts a polling thread which reads a high resolution
+ * time stamp and associated CPU cycles counter value once per second
+ * and saves that data pair.
+ *
+ * Current time stamps are then computed by taking the current CPU
+ * cycles value and extrapolating the time from the last data pair.
+ *
+ * This is very much faster than accessing the PCI card for every
+ * single time stamp.
+ *
+ * Notes:
+ *
+ * 1.) This approach works / makes sense only with cards which support
+ * high resolution time stamps (HR time). If a card doesn't support
+ * that then this program prints a warning.
+ *
+ * 2.) Under Linux extrapolation is done using the time stamp counter
+ * (TSC) registers provided by Pentium CPUs and newer/compatible
+ * types as the cycles counter. On SMP / multicore CPUs those
+ * counters may not be synchronized, so this works only correctly
+ * if all cycles counter values are taken from the same CPU.
+ * To achieve this the process CPU affinity is by default set to
+ * the first CPU at program start, which means all threads of this
+ * process are executed only on that CPU.
+ *
+ * 3.) Under Linux there's no easy way to find the accurate clock
+ * frequency of the cycles counter, so the polling thread computes
+ * the frequency from the time differences of 2 subsequent polls
+ * of the PCI card. If the time extrapolation function is called
+ * before the cycles clock frequency has been determined the
+ * returned time stamp is always 0.
+ *
+ * -----------------------------------------------------------------------
+ * $Log: mbgxhrtime.c $
+ * Revision 1.5 2009/09/29 14:25:07 martin
+ * Display measured and default PC cycles frequency.
+ * Updated version number to 3.4.0.
+ * Revision 1.4 2009/07/24 09:50:09 martin
+ * Updated version number to 3.3.0.
+ * Revision 1.3 2009/06/19 12:38:52 martin
+ * Updated version number to 3.2.0.
+ * Revision 1.2 2009/03/19 17:04:26 martin
+ * Updated version number to 3.1.0.
+ * Updated copyright year to include 2009.
+ * Revision 1.1 2008/12/22 11:05:24 martin
+ * Initial revision.
+ *
+ **************************************************************************/
+
+// include Meinberg headers
+#include <mbgdevio.h>
+#include <pcpsutil.h>
+#include <toolutil.h> // common utility functions
+
+// include system headers
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sched.h>
+
+
+#if !defined( MBGDEVIO_USE_THREAD_API )
+ #error Symbol MBGDEVIO_USE_THREAD_API needs to be defined, see the Makefile.
+#endif
+
+#if !defined ( USE_PROCESS_AFFINITY )
+ #define USE_PROCESS_AFFINITY 1
+#endif
+
+
+static const char *pname = "mbgxhrtime";
+static const char *pversion = "v3.4.0";
+static const char *pcopyright = "(c) Meinberg 2008-2009";
+
+static int loops;
+
+
+
+#if USE_PROCESS_AFFINITY
+
+static /*HDR*/
+void print_cpu_set( const char *info, MBG_CPU_SET *p_cpu_set )
+{
+ int min_cpu = MBG_CPU_SET_SIZE + 1;
+ int max_cpu = 0;
+ int i;
+
+ for ( i = 0; i < MBG_CPU_SET_SIZE; i++ )
+ {
+ if ( !_mbg_cpu_isset( i, p_cpu_set ) )
+ continue;
+
+ if ( i < min_cpu )
+ min_cpu = i;
+
+ if ( i > max_cpu )
+ max_cpu = i;
+ }
+
+ printf( "%s: CPU%i", info, min_cpu );
+
+ if ( max_cpu == min_cpu )
+ printf( " only" );
+ else
+ printf( "...CPU%i", max_cpu );
+
+ printf( "\n" );
+
+} // print_cpu_set
+
+
+
+/*HDR*/
+void check_set_process_affinity_mask( MBG_PROCESS_ID pid, int cpu_num )
+{
+ MBG_CPU_SET cpu_set;
+
+ int rc = mbg_get_process_affinity( pid, &cpu_set );
+
+ if ( rc < 0 )
+ {
+ perror( "Failed to get process affinity mask" );
+ exit( 1 );
+ }
+
+ print_cpu_set( "Initial process affinity mask", &cpu_set );
+
+ _mbg_cpu_clear( &cpu_set );
+ _mbg_cpu_set( cpu_num, &cpu_set );
+
+ rc = mbg_set_process_affinity( pid, &cpu_set );
+
+ if ( rc < 0 )
+ {
+ perror( "Failed to set process affinity mask" );
+ exit( 1 );
+ }
+
+ printf( "Process affinity mask set for CPU%i only\n", cpu_num );
+
+} // check_set_process_affinity_mask
+
+#endif
+
+
+
+static /*HDR*/
+int do_mbgxhrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev )
+{
+ MBG_PC_CYCLES_FREQUENCY freq_hz = 0;
+ MBG_PC_CYCLES_FREQUENCY default_freq_hz = 0;
+ int this_loops = loops;
+ MBG_POLL_THREAD_INFO poll_thread_info = { { { { 0 } } } };
+ int rc;
+
+ if ( !_pcps_has_hr_time( p_dev ) )
+ {
+ printf( "High resolution time not supported by this device.\n" );
+ return 0;
+ }
+
+ mbg_get_default_cycles_frequency_from_dev( dh, &default_freq_hz );
+
+ rc = mbg_xhrt_poll_thread_create( &poll_thread_info, dh, 0, 0 );
+
+ if ( rc != MBG_SUCCESS )
+ return -1;
+
+
+ for (;;)
+ {
+ static int has_printed_msg = 0;
+
+ PCPS_HR_TIME hrt;
+ char ws[80];
+ MBG_PC_CYCLES cyc_1;
+ MBG_PC_CYCLES cyc_2;
+ double latency;
+
+ rc = mbg_get_xhrt_cycles_frequency( &poll_thread_info.xhrt_info, &freq_hz );
+
+ if ( rc != MBG_SUCCESS )
+ goto fail;
+
+ if ( freq_hz == 0 )
+ {
+ if ( !has_printed_msg )
+ {
+ printf( "Waiting until PC cycles frequency has been computed ... " );
+ has_printed_msg = 1;
+ }
+
+ usleep( 50000 );
+ continue;
+ }
+
+ if ( has_printed_msg )
+ {
+ puts( "" );
+
+ printf( "PC cycles freq: %.6f MHz", ( (double) freq_hz ) / 1E6 );
+
+ if ( default_freq_hz )
+ printf( ", default: %.6f MHz", ( (double) default_freq_hz ) / 1E6 );
+
+ printf( "\n" );
+
+ has_printed_msg = 0;
+ }
+
+ // get an extrapolated time stamp bracketed by
+ // mbg_get_pc_cycles() calls to compute the latency
+ mbg_get_pc_cycles( &cyc_1 );
+ rc = mbg_get_xhrt_time_as_pcps_hr_time( &poll_thread_info.xhrt_info, &hrt );
+ mbg_get_pc_cycles( &cyc_2 );
+
+ if ( rc != MBG_SUCCESS )
+ goto fail;
+
+ // compute the latency
+ latency = ( (double) cyc_2 - (double) cyc_1 ) / (double) freq_hz * 1E6;
+
+ // convert to human readable date and time
+ mbg_snprint_hr_time( ws, sizeof( ws ), &hrt );
+ printf( "t: %s (%.3f us)\n", ws, latency );
+
+ if ( this_loops > 0 )
+ this_loops--;
+
+ if ( this_loops == 0 )
+ break;
+
+ // if this_loops is < 0 then loop forever
+ }
+
+ goto done;
+
+fail:
+ fprintf( stderr, "** Aborting: xhrt function returned %i\n", rc );
+
+done:
+ mbg_xhrt_poll_thread_stop( &poll_thread_info );
+
+ mbg_close_device( &dh );
+
+ return rc;
+
+} // do_mbgxhrtime
+
+
+
+static /*HDR*/
+void usage( void )
+{
+ mbg_print_usage_intro( pname,
+ "This example program reads fast extrapolated high resolution time stamps.\n"
+ "\n"
+ "The program starts an extra polling thread which reads a high resolution\n"
+ "time stamp plus associated PC cycles counter at regular intervals.\n"
+ "The returned time stamps are extrapolated using the current PC cycles\n"
+ "count value plus the last time stamp/cycles pair read by the polling thread.\n"
+ "\n"
+ "This is very much faster than accessing the card every time a time stamp\n"
+ "needs to be retrieved.\n"
+ "This works only for devices which support high resolution time (HR time)."
+ );
+ mbg_print_help_options();
+ mbg_print_opt_info( "-c", "run continuously" );
+ mbg_print_opt_info( "-n num", "run num loops" );
+ mbg_print_device_options();
+ puts( "" );
+
+} // usage
+
+
+
+int main( int argc, char *argv[] )
+{
+ int rc;
+ int c;
+
+ mbg_print_program_info( pname, pversion, pcopyright );
+
+ // check command line parameters
+ while ( ( c = getopt( argc, argv, "cn:h?" ) ) != -1 )
+ {
+ switch ( c )
+ {
+ case 'c':
+ loops = -1;
+ break;
+
+ case 'n':
+ loops = atoi( optarg );
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ must_print_usage = 1;
+ }
+ }
+
+ if ( must_print_usage )
+ {
+ usage();
+ return 1;
+ }
+
+ #if USE_PROCESS_AFFINITY
+ check_set_process_affinity_mask( _mbg_get_current_process(), 0 );
+ puts( "" );
+ #endif
+
+ // The function below checks which devices have been specified
+ // on the command, and for each device
+ // - tries to open the device
+ // - shows basic device info
+ // - calls the function passed as last parameter
+ rc = mbg_check_devices( argc, argv, optind, do_mbgxhrtime );
+
+ return abs( rc );
+}
diff --git a/src/external/bsd/meinberg/mbgclock/Makefile b/src/external/bsd/meinberg/mbgclock/Makefile
new file mode 100644
index 0000000..85ad982
--- /dev/null
+++ b/src/external/bsd/meinberg/mbgclock/Makefile
@@ -0,0 +1 @@
+.include "Makefile.kmod" \ No newline at end of file
diff --git a/src/external/bsd/meinberg/mbgclock/Makefile.kmod b/src/external/bsd/meinberg/mbgclock/Makefile.kmod
new file mode 100644
index 0000000..1912e2d
--- /dev/null
+++ b/src/external/bsd/meinberg/mbgclock/Makefile.kmod
@@ -0,0 +1,15 @@
+# $NetBSD: Makefile,v 1.1 2009/02/05 17:32:10 haad Exp $
+
+.include "../Makefile.inc"
+
+.PATH: ${MBG_LIB_COMMON} ${MBG_LIB_BSD}
+
+.include "../../../../sys/modules/Makefile.inc"
+
+KMOD= mbgclock
+SRCS= mbgclock.c
+SRCS+= pcpsdrvr.c
+SRCS+= identdec.c
+SRCS+= rsrc_bsd.c
+
+.include <bsd.kmodule.mk>
diff --git a/src/external/bsd/meinberg/mbgclock/files.mbgclock b/src/external/bsd/meinberg/mbgclock/files.mbgclock
new file mode 100644
index 0000000..9a1676a
--- /dev/null
+++ b/src/external/bsd/meinberg/mbgclock/files.mbgclock
@@ -0,0 +1,13 @@
+# $NetBSD: files.drm,v 1.6 2011/02/18 14:26:09 jmcneill Exp $
+
+device mbgclock
+attach mbgclock at pci
+file external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c mbgclock
+file external/bsd/meinberg/dist/mbglib/common/identdec.c mbgclock
+file external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c mbgclock
+file external/bsd/meinberg/mbgclock/mbgclock.c mbgclock
+
+makeoptions mbgclock CPPFLAGS+="-I$S/external/bsd/meinberg/dist/mbglib/common"
+makeoptions mbgclock CPPFLAGS+="-I$S/external/bsd/meinberg/dist/mbglib/bsd"
+
+
diff --git a/src/external/bsd/meinberg/mbgclock/mbgclock.c b/src/external/bsd/meinberg/mbgclock/mbgclock.c
new file mode 100644
index 0000000..2899933
--- /dev/null
+++ b/src/external/bsd/meinberg/mbgclock/mbgclock.c
@@ -0,0 +1,558 @@
+/*
+ * $Header$
+ *
+ * NetBSD Meinberg mbgclock driver, Frank Kardel
+ *
+ * $Created: Sat Mar 26 15:03:37 2011 $
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/lwp.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pcivar.h>
+#include <sys/errno.h>
+
+#include <pcpsdrvr.h>
+#include <mbgddmsg.h>
+
+#define REV_NUM 0x100
+#define REV_NUM_STR "1.00"
+#define MBG_COPYRIGHT "(c) Meinberg 2011"
+#define MBG_DRVR_NAME "mbgclock"
+
+const char pcps_driver_name[] = MBG_DRVR_NAME;
+
+static MBG_DBG_DATA mbg_dbg_data;
+static MBG_DBG_PORT mbg_dbg_port = 0x378 + 0; //##++
+static PCPS_IO_ADDR_MAPPED mbg_dbg_port_mapped; //##++
+static PCPS_DRVR_INFO drvr_info = { REV_NUM, 0, MBG_DRVR_NAME " radio clock driver" };
+
+#include <macioctl.h>
+
+static dev_type_open(mbgclockopen);
+static dev_type_close(mbgclockclose);
+static dev_type_read(mbgclockread);
+static dev_type_write(mbgclockwrite);
+static dev_type_ioctl(mbgclockioctl);
+static int mbgclock_match(device_t, cfdata_t, void *);
+static void mbgclock_attach(device_t, device_t, void *);
+static int mbgclock_detach(device_t, int);
+
+struct mbgclock_softc
+{
+ device_t dev; /* device backling */
+ struct pci_attach_args pa; /* attach argument */
+ PCPS_DDEV *pddev; /* driver handle */
+};
+
+#define MBG_UNITBITS 6 /* up to 64 devices */
+#define MBG_UNITMASK ((1<<MBG_UNITBITS)-1)
+#define MBG_UNIT(x) (minor(x) & MBG_UNITMASK)
+#define MBG_UNITTYPE(x) (minor(x) >> MBG_UNITBITS)
+
+const struct cdevsw mbgclock_cdevsw = {
+ .d_open = mbgclockopen,
+ .d_close = mbgclockclose,
+ .d_read = mbgclockread,
+ .d_write = mbgclockwrite,
+ .d_ioctl = mbgclockioctl,
+ .d_stop = nostop,
+ .d_tty = notty,
+ .d_poll = nopoll,
+ .d_mmap = nommap,
+ .d_kqfilter = nokqfilter,
+ D_OTHER|D_MPSAFE
+};
+
+CFATTACH_DECL3_NEW(mbgclock,
+ sizeof(struct mbgclock_softc),
+ mbgclock_match,
+ mbgclock_attach,
+ mbgclock_detach,
+ NULL,
+ NULL,
+ NULL,
+ DVF_DETACH_SHUTDOWN);
+
+extern struct cfdriver mbgclock_cd;
+
+#ifdef DEBUG
+int debug = 0;
+static int mbgclockdebug = ~0;
+#define DB_FOLLOW 0x00000001
+#define DPRINTF(_X_, _Y_) do { \
+ if (mbgclockdebug & (_X_)) { \
+ printf _Y_; \
+ } \
+ } \
+ while (/*CONST_COND*/0)
+#else
+#define DPRINTF(_X_, _Y_) /* empty */
+#endif
+
+/*----- module -----*/
+#ifdef _MODULE
+
+#include <sys/module.h>
+
+MODULE(MODULE_CLASS_DRIVER, mbgclock, NULL);
+CFDRIVER_DECL(mbgclock, DV_DULL, NULL);
+
+static int mbgclock_loc[] = { -1, -1 };
+
+static struct cfparent pciparent = {
+ "pci", "pci", DVUNIT_ANY
+};
+
+static struct cfdata mbgclock_cfdata[] = {
+ {
+ .cf_name = "mbgclock",
+ .cf_atname = "mbgclock",
+ .cf_unit = 0,
+ .cf_fstate = FSTATE_STAR,
+ .cf_loc = mbgclock_loc,
+ .cf_flags = 0,
+ .cf_pspec = &pciparent,
+ },
+ { NULL }
+};
+
+static int
+mbgclock_modcmd(modcmd_t cmd, void *arg)
+{
+ int bmajor = -1, cmajor = -1, error = 0;
+
+ switch (cmd) {
+ case MODULE_CMD_INIT:
+ DPRINTF(DB_FOLLOW, ("%s: MOD_CMD_INIT\n", mbgclock_cd.cd_name));
+
+ error = config_cfdriver_attach(&mbgclock_cd);
+ if (error)
+ break;
+
+ error = config_cfattach_attach(mbgclock_cd.cd_name, &mbgclock_ca);
+ if (error) {
+ config_cfdriver_detach(&mbgclock_cd);
+ aprint_error("%s: unable to register cfattach\n",
+ mbgclock_cd.cd_name);
+ break;
+ }
+
+ /* s = splaudio(); */
+ error = config_cfdata_attach(mbgclock_cfdata, 1);
+ /* splx(s); */
+
+ if (error == 0)
+ {
+ error = devsw_attach("mbgclock", NULL, &bmajor,
+ &mbgclock_cdevsw, &cmajor);
+ }
+
+ if (error) {
+ config_cfattach_detach(mbgclock_cd.cd_name, &mbgclock_ca);
+ config_cfdriver_detach(&mbgclock_cd);
+ break;
+ } else {
+ DPRINTF(DB_FOLLOW, ("%s: registered character major = %d\n",
+ mbgclock_cd.cd_name, cmajor));
+ }
+
+ break;
+
+ case MODULE_CMD_FINI:
+ DPRINTF(DB_FOLLOW, ("%s: MOD_CMD_FINI\n", mbgclock_cd.cd_name));
+ error = config_cfattach_detach(mbgclock_cd.cd_name, &mbgclock_ca);
+ if (error)
+ break;
+ config_cfdriver_detach(&mbgclock_cd);
+ devsw_detach(NULL, &mbgclock_cdevsw);
+ break;
+
+ case MODULE_CMD_STAT:
+ return ENOTTY;
+
+ default:
+ return ENOTTY;
+ }
+
+ DPRINTF(DB_FOLLOW, ("modcmd rc = %d\n", error));
+
+ return error;
+}
+#endif
+
+/*----- autoconf -----*/
+
+/* PCI Support Functions */
+
+static void
+mbg_deallocate_resource( device_t device, BSD_RSRC_INFO *p_ri)
+{
+ if ( p_ri->valid )
+ {
+ bus_space_unmap( p_ri->bst, p_ri->bsh, p_ri->size);
+ p_ri->valid = 0;
+ }
+}
+
+/*
+ * deallocate resources
+ */
+static void
+mbg_dealloc_rsrcs( device_t device )
+{
+ struct mbgclock_softc *psc = device_private( device );
+ PCPS_DDEV *pddev = psc->pddev;
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+ int i;
+
+/* mbg_deallocate_resource( device, &prsrci->irq.bsd, SYS_RES_IRQ ); */
+
+ for ( i = 0; i < N_PCPS_MEM_RSRC; i++ )
+ mbg_deallocate_resource( device, &prsrci->mem[i].bsd);
+
+ for ( i = 0; i < N_PCPS_PORT_RSRC; i++ )
+ mbg_deallocate_resource( device, &prsrci->port[i].bsd);
+
+}
+
+static void
+mbg_alloc_rsrc( device_t device, int reg, BSD_RSRC_INFO *p_ri, int type )
+{
+ struct mbgclock_softc *psc = device_private(device);
+
+ p_ri->reg = reg;
+ p_ri->type = type;
+
+ if (!pci_mapreg_map(&psc->pa, reg, type, BUS_SPACE_MAP_LINEAR,
+ &p_ri->bst, &p_ri->bsh, &p_ri->base, &p_ri->size))
+ {
+ p_ri->valid = 1;
+ } else {
+ p_ri->valid = 0;
+ }
+ /* bus_space_vaddr() */
+}
+
+static void
+mbg_alloc_rsrcs( device_t device )
+{
+ struct mbgclock_softc *psc = device_private( device );
+ PCPS_DDEV *pddev = psc->pddev;
+ PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info;
+ BSD_RSRC_INFO ri;
+ int bar;
+
+ for ( bar = 0; bar < 6; bar ++ )
+ {
+ int type;
+ int reg = PCI_BAR( bar );
+
+ _mbgddmsg_4( MBG_DBG_INIT_DEV,
+ "%s: alloc I/O range %i: PCI device 0x%04X:0x%04X supported",
+ pcps_driver_name, bar, PCI_VENDOR(psc->pa.pa_id),
+ PCI_PRODUCT(psc->pa.pa_id) );
+
+ switch ((type = pci_mapreg_type(psc->pa.pa_pc, psc->pa.pa_tag, reg)))
+ {
+ case PCI_MAPREG_TYPE_IO:
+ if ( prsrci->num_rsrc_io < N_PCPS_PORT_RSRC )
+ {
+ mbg_alloc_rsrc( device, reg, &ri, type );
+
+ if ( ri.valid )
+ {
+ prsrci->port[prsrci->num_rsrc_io].bsd = ri;
+ pcps_add_rsrc_io( pddev,
+ (MBG_MEM_ADDR)bus_space_vaddr(ri.bst,
+ ri.bsh),
+ (ulong)ri.size );
+ continue;
+ }
+ }
+ break;
+
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+#if __LP64__
+ /* XXX */
+ aprint_error_dev(self,
+ "WARNING: ignoring 64-bit BAR @ 0x%02x\n", reg);
+ continue;
+#else
+ /*FALLTHROUGH*/
+#endif
+ case PCI_MAPREG_TYPE_MEM:
+ /* case PCI_MAPREG_TYPE_ROM: currently same as above */
+ if ( prsrci->num_rsrc_mem < N_PCPS_MEM_RSRC )
+ {
+ mbg_alloc_rsrc( device, reg, &ri, type );
+
+ if ( ri.valid )
+ {
+ prsrci->mem[prsrci->num_rsrc_mem].bsd = ri;
+ pcps_add_rsrc_mem( pddev,
+ (MBG_MEM_ADDR)bus_space_vaddr( ri.bst, ri.bsh),
+ ri.size );
+ continue;
+ }
+ }
+ break;
+
+ default:
+ printf("XXX unsupported type from pci_mapreg_type: %d\n", type);
+ break;
+ }
+ }
+
+ /* single IRQ resource */
+#if 0 /* currently not used / required */
+ mbg_alloc_rsrc( device, 0, &ri, SYS_RES_IRQ, RF_SHAREABLE | RF_ACTIVE );
+
+ if ( ri.res )
+ {
+ prsrci->port[prsrci->num_rsrc_irq].bsd = ri;
+ pcps_add_rsrc_irq( pddev, rman_get_start( ri.res ) );
+ }
+#endif
+
+}
+
+static int
+mbgclock_match(struct device *parent, struct cfdata *match, void *aux)
+{
+ struct pci_attach_args *pa;
+ int16_t vend_id;
+ int16_t dev_id;
+
+ DPRINTF(DB_FOLLOW, ("mbgclock_match(0x%p, 0x%p, 0x%p)\n", parent, match, aux));
+
+ pa = aux;
+ vend_id = PCI_VENDOR(pa->pa_id);
+ dev_id = PCI_PRODUCT(pa->pa_id);
+
+ if (vend_id == PCI_VENDOR_MEINBERG)
+ {
+ PCPS_DEV_TYPE *pdt;
+
+ pdt = pcps_get_dev_type( PCPS_BUS_PCI, dev_id );
+
+ if (pdt != NULL)
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV,
+ "%s: probe: PCI device 0x%04X:0x%04X supported",
+ pcps_driver_name, vend_id, dev_id );
+
+ return 1;
+ }
+ }
+
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: probe: PCI device 0x%04X:0x%04X not supported",
+ pcps_driver_name, vend_id, dev_id );
+ return 0;
+}
+
+
+static void
+mbgclock_attach(struct device *parent, struct device *self, void *aux)
+{
+ int rc = 0;
+ char devinfo[256];
+ struct mbgclock_softc *psc = device_private(self);
+ struct pci_attach_args *pa = aux;
+ uint16_t dev_id = PCI_PRODUCT(pa->pa_id);
+
+ DPRINTF(DB_FOLLOW, ("mbgclock_attach(0x%p, 0x%p, 0x%p)\n", parent, self, aux));
+
+ psc->dev = self;
+ psc->pa = *pa;
+
+ pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
+ aprint_naive("\n");
+ aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
+ PCI_REVISION(pa->pa_class));
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: attach for device 0x%04X",
+ pcps_driver_name, dev_id );
+
+ psc->pddev = pcps_alloc_ddev();
+
+ if ( psc->pddev == NULL )
+ {
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_alloc_ddev() failed",
+ pcps_driver_name, dev_id );
+ goto fail;
+ }
+
+ rc = pcps_init_ddev( psc->pddev, PCPS_BUS_PCI, dev_id );
+
+ if ( rc != PCPS_SUCCESS )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_init_ddev() failed, rc: %i",
+ pcps_driver_name, dev_id, rc );
+ goto fail;
+ }
+
+ mbg_alloc_rsrcs( self );
+
+ rc = pcps_start_device( psc->pddev, 0, 0 );
+
+ if ( rc != PCPS_SUCCESS )
+ {
+ _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_start_device() failed, rc: %i",
+ pcps_driver_name, dev_id, rc );
+ goto fail;
+ }
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: device 0x%04X attached successfully",
+ pcps_driver_name, dev_id );
+
+ if (!pmf_device_register(self, NULL, NULL))
+ aprint_error_dev(self, "couldn't establish power handler\n");
+
+ return;
+
+fail:
+ mbg_dealloc_rsrcs( self );
+
+ if ( psc->pddev )
+ pcps_free_ddev( psc->pddev );
+
+ _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: failed to attach device 0x%04X",
+ pcps_driver_name, dev_id );
+ return;
+}
+
+static int
+mbgclock_detach(struct device *self, int flags)
+{
+ /* int error; */
+ /* struct vnd_softc *sc = device_private(self); */
+ DPRINTF(DB_FOLLOW, ("mbgclock_detach(0x%p, 0x%x)\n", self, flags));
+
+ pmf_device_deregister(self);
+
+ return 0;
+}
+
+#if 0
+static int
+mbgclock_activate(struct device *self, enum devact act)
+{
+ /* struct mbgclock_softc *sc; */
+ /* int error = 0; */
+ DPRINTF(DB_FOLLOW, ("mbgclock_activate(0x%"PRIx64", %d)\n", dev, (int)act));
+
+ return 0;
+}
+#endif
+
+/*------- driver -------*/
+
+static
+int mbgclockopen(dev_t dev, int flags, int mode, struct lwp *l)
+{
+ DPRINTF(DB_FOLLOW, ("mbgclockopen(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l));
+
+ return 0;
+}
+
+static
+int mbgclockclose(dev_t dev, int flags, int mode, struct lwp *l)
+{
+ DPRINTF(DB_FOLLOW,("mbgclockclose(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l));
+
+ return 0;
+}
+
+static
+int mbgclockread(dev_t dev, struct uio *uio, int flags)
+{
+ DPRINTF(DB_FOLLOW,("mbgclockread(0x%"PRIx64", %p)\n", dev, uio));
+
+ return 0;
+}
+
+static
+int mbgclockwrite(dev_t dev, struct uio *uio, int flags)
+{
+ DPRINTF(DB_FOLLOW, ("mbgclockwrite(0x%"PRIx64", %p)\n", dev, uio));
+
+ return 0;
+}
+
+#include <sys/ioctl.h>
+
+static
+int mbgclockioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
+{
+ struct mbgclock_softc *psc = device_lookup_private(&mbgclock_cd, MBG_UNIT(dev));
+ PCPS_DDEV *pddev = psc->pddev;
+ int rc;
+
+ DPRINTF(DB_FOLLOW, ("mbgclockioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p)\n",
+ dev, cmd, data, flag, l->l_proc));
+
+ rc = ioctl_switch( pddev, cmd, (void *) data, (void *) data );
+
+ /* On success we return quickly.*/
+
+ if ( rc == MBG_SUCCESS )
+ {
+ _mbgddmsg_6( MBG_DBG_INFO, "%s: %d,%d IOCTL 0x%02lX: success, dev %p_%s",
+ pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = 0;
+ goto out;
+ }
+
+
+ /* An error has occurred. */
+ /* Generate an appropriate debug/error message */
+ /* and return an error status. */
+
+ switch ( rc )
+ {
+ case MBG_ERR_INV_DEV_REQUEST:
+ _mbgddmsg_7( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%04lX: invalid cmd %04lX, dev %s_%s",
+ pcps_driver_name, major(dev), minor(dev), cmd, IOCBASECMD( cmd ),
+ _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EINVAL;
+ break;
+
+
+ case MBG_ERR_NOT_SUPP_BY_DEV:
+ _mbgddmsg_6( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%02lX: not supported by dev %s_%s",
+ pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EIO;
+ break;
+
+
+ case MBG_ERR_NO_MEM:
+ _mbgddmsg_6( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%02lX: unable to allocate buffer for dev %s_%s",
+ pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EFAULT;
+ break;
+
+
+ case MBG_ERR_IRQ_UNSAFE:
+ _mbgddmsg_6( MBG_DBG_DETAIL, "%s: %d,%d ioctl 0x%02lX: busy since unsafe IRQ enabled, dev %s_%s",
+ pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = -EBUSY;
+ break;
+
+
+ default: /* any access error code returned by the low level routine */
+ /* or copying from or to user space */
+ _mbgddmsg_7( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%02lX: error %i accessing dev %s_%s",
+ pcps_driver_name, major(dev), minor(dev), cmd, rc, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
+ rc = EFAULT;
+
+ }
+
+
+out:
+ return rc;
+}
+
diff --git a/src/sys/dev/pci/files.pci.diff b/src/sys/dev/pci/files.pci.diff
new file mode 100644
index 0000000..3871edb
--- /dev/null
+++ b/src/sys/dev/pci/files.pci.diff
@@ -0,0 +1,16 @@
+Index: files.pci
+===================================================================
+RCS file: /cvsroot/src/sys/dev/pci/files.pci,v
+retrieving revision 1.339
+diff -u -r1.339 files.pci
+--- files.pci 23 Feb 2011 00:35:29 -0000 1.339
++++ files.pci 27 Mar 2011 16:13:06 -0000
+@@ -1042,3 +1042,8 @@
+ device vte: ether, ifnet, arp, mii, mii_phy
+ attach vte at pci
+ file dev/pci/if_vte.c vte
++
++#
++# Meinberg radio clocks
++#
++include "external/bsd/meinberg/mbgclock/files.mbgclock"
diff --git a/src/sys/dev/pci/pcidevs.diff b/src/sys/dev/pci/pcidevs.diff
new file mode 100644
index 0000000..d5ecaff
--- /dev/null
+++ b/src/sys/dev/pci/pcidevs.diff
@@ -0,0 +1,47 @@
+Index: pcidevs
+===================================================================
+RCS file: /cvsroot/src/sys/dev/pci/pcidevs,v
+retrieving revision 1.1066
+diff -u -r1.1066 pcidevs
+--- pcidevs 25 Feb 2011 01:36:18 -0000 1.1066
++++ pcidevs 27 Mar 2011 16:12:26 -0000
+@@ -546,6 +546,7 @@
+ vendor SIIG 0x131f Siig
+ vendor DOMEX 0x134a Domex
+ vendor QUATECH 0x135c Quatech
++vendor MEINBERG 0x1360 Meinberg Funkuhren
+ vendor LMC 0x1376 LAN Media
+ vendor NETGEAR 0x1385 Netgear
+ vendor MOXA 0x1393 Moxa Technologies
+@@ -3047,6 +3048,31 @@
+ /* KTI products - XXX better descriptions */
+ product KTI NE2KETHER 0x3000 Ethernet
+
++/* Meinberg Funkuhren Products */
++product MEINBERG PCI32 0x0101 DCF77 PCI32
++product MEINBERG PCI509 0x0102 DCF77 PCI509
++product MEINBERG PCI510 0x0103 DCF77 PCI510
++product MEINBERG PCI511 0x0104 DCF77 PCI511
++product MEINBERG PEX511 0x0105 DCF77 PEX511
++
++product MEINBERG GPS167PCI 0x0201 GPS GPS167PCI
++product MEINBERG GPS168PCI 0x0202 GPS GPS168PCI
++product MEINBERG GPS169PCI 0x0203 GPS GPS169PCI
++product MEINBERG GPS170PCI 0x0204 GPS GPS170PCI
++product MEINBERG GPS170PEX 0x0205 GPS GPS170PEX
++product MEINBERG GPS180PEX 0x0206 GPS GPS180PEX
++
++product MEINBERG TCR510PCI 0x0301 IRIG TCR510PCI
++product MEINBERG TCR167PCI 0x0302 IRIG TCR167PCI
++product MEINBERG TCR511PCI 0x0303 IRIG TCR511PCI
++product MEINBERG TCR511PEX 0x0304 IRIG TCR511PEX
++product MEINBERG TCR170PEX 0x0305 IRIG TCR170PEX
++product MEINBERG TCR180PEX 0x0306 IRIG TCR180PEX
++
++product MEINBERG PTP280PEX 0x0501 PTP PTP280PEX
++
++product MEINBERG FRC511PEX 0x0601 FRC FRC511PEX
++
+ /* LAN Media */
+ product LMC HSSI 0x0003 HSSI Interface
+ product LMC DS3 0x0004 DS3 Interface
diff --git a/src/sys/external/bsd/meinberg b/src/sys/external/bsd/meinberg
new file mode 120000
index 0000000..39b5e46
--- /dev/null
+++ b/src/sys/external/bsd/meinberg
@@ -0,0 +1 @@
+../../../external/bsd/meinberg \ No newline at end of file