Initial checkout (vulcano)
Signed-off-by: Alec Ari <neotheuser@ymail.com>
This commit is contained in:
parent
97d3809ffb
commit
dc658435df
1275 changed files with 394449 additions and 0 deletions
74
.gitignore
vendored
Normal file
74
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# CVS junk
|
||||
CVS
|
||||
|
||||
# Build Files
|
||||
*.o
|
||||
*.cmd
|
||||
*.mod.c
|
||||
*.ko
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
*.swp
|
||||
*~
|
||||
base/sched/malloc.c
|
||||
Module.symvers
|
||||
modules.order
|
||||
base/include/asm
|
||||
base/scripts/rtai-config
|
||||
base/scripts/rtai-load
|
||||
rtai_config.h
|
||||
|
||||
# Auto-generated files
|
||||
rtai_config.h.in
|
||||
configure
|
||||
aclocal.m4
|
||||
ltversion.m4
|
||||
bin/
|
||||
doc/guide/*.html
|
||||
addons/drivers/16550A/FORCE
|
||||
|
||||
# Generated Makefiles
|
||||
GNUmakefile.in
|
||||
GNUmakefile
|
||||
Makefile
|
||||
|
||||
# Config Temp Files
|
||||
.cfok
|
||||
.cfchanged
|
||||
.rtai_config*
|
||||
addons/rtdm/FORCE
|
||||
autom4te.cache/
|
||||
config.log
|
||||
config.status
|
||||
libtool
|
||||
stamp-h1
|
||||
|
||||
# Make Temp Files
|
||||
.deps
|
||||
.tmp_versions
|
||||
.libs
|
||||
|
||||
# Executables
|
||||
base/arch/*/calibration/calibrate
|
||||
base/arch/*/calibration/calibration_helper
|
||||
base/arch/*/calibration/setsmi
|
||||
testsuite/*/*/display
|
||||
testsuite/*/*/latency
|
||||
testsuite/*/*/preempt
|
||||
testsuite/*/*/switches
|
||||
|
||||
# KConfig Generated files
|
||||
base/config/kconfig/.config*
|
||||
base/config/kconfig/.ncurses
|
||||
base/config/kconfig/lex.zconf.c
|
||||
base/config/kconfig/libkconfig.so
|
||||
base/config/kconfig/lxdialog/lxdialog
|
||||
base/config/kconfig/mconf
|
||||
base/config/kconfig/zconf.tab.c
|
||||
|
||||
# Documentation Files
|
||||
doc/doxygen/api
|
||||
doc/docbook/catalog
|
||||
doc/docbook/custom-stylesheets/xsl/html/chunk.xsl
|
||||
doc/doxygen/Doxyfile
|
||||
131
GNUmakefile.am
Normal file
131
GNUmakefile.am
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
ACLOCAL_AMFLAGS=-I base/config/autoconf
|
||||
|
||||
OPTDIRS =
|
||||
|
||||
if CONFIG_RTAI_TESTSUITE
|
||||
OPTDIRS += testsuite
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_ADDONS
|
||||
OPTDIRS += addons
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_LAB
|
||||
OPTDIRS += rtai-lab
|
||||
endif
|
||||
|
||||
OPTDIRS += rtai-py
|
||||
|
||||
SUBDIRS = base @RTAI_MAYBE_DOCDIR@ $(OPTDIRS)
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
@RTAI_MAYBE_DOCDIR@ \
|
||||
base \
|
||||
testsuite \
|
||||
addons \
|
||||
rtai-lab \
|
||||
rtai-py
|
||||
|
||||
EXTRA_DIST = \
|
||||
makefile \
|
||||
README.INSTALL \
|
||||
README.ISOLCPUS \
|
||||
README.LINUX_SERVER \
|
||||
README.LXRT_EXTS_IN_USE \
|
||||
README.SMI \
|
||||
@RTAI_MAYBE_SIMDIR@
|
||||
|
||||
DISTCLEANFILES = .rtai_config .rtai_config.old .cfok .cfchanged Module.symvers
|
||||
|
||||
moduledir = @RTAI_MODULE_DIR@
|
||||
|
||||
all-recursive install-recursive: base/GNUmakefile clean-if-reconfigured
|
||||
|
||||
base/GNUmakefile: @RTAI_LINUX_DIR@/.config
|
||||
@echo "*****************************************" ; \
|
||||
echo "* The Linux configuration has changed *" ; \
|
||||
echo "* forcing 'make reconfig' ... *" ; \
|
||||
echo "*****************************************" ; \
|
||||
$(MAKE) reconfig
|
||||
|
||||
clean-if-reconfigured:
|
||||
@if test -r .cfchanged ; then \
|
||||
rm -f .cfchanged ; \
|
||||
echo "****************************************" ; \
|
||||
echo "* Your RTAI configuration has changed *" ; \
|
||||
echo "* forcing 'make clean' ... *" ; \
|
||||
echo "****************************************" ; \
|
||||
$(MAKE) clean ; \
|
||||
fi
|
||||
|
||||
reconfig xconfig gconfig mconfig menuconfig config oldconfig:
|
||||
@$(MAKE) -f $(srcdir)/makefile $@ \
|
||||
srctree=$(srcdir) ARCH=@RTAI_HOST_STRING@ CROSS_COMPILE=@CROSS_COMPILE@
|
||||
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
clean-local:
|
||||
rm -fr modules .cfchanged
|
||||
|
||||
distclean-local:
|
||||
$(MAKE) -C $(srcdir)/base/config/kconfig \
|
||||
-f Makefile.kconfig distclean srctree=$(srcdir)
|
||||
find . -name autom4te.cache | xargs rm -fr
|
||||
else
|
||||
clean-local:
|
||||
rm -f .cfchanged
|
||||
|
||||
distclean-local:
|
||||
test -d $(top_builddir)/base/config && \
|
||||
$(MAKE) -C $(top_builddir)/base/config/kconfig \
|
||||
-f @abs_srcdir@/base/config/kconfig/Makefile.kconfig distclean srctree=@abs_srcdir@
|
||||
endif
|
||||
|
||||
install-data-local: .rtai_config
|
||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
|
||||
$(INSTALL_DATA) .rtai_config $(DESTDIR)$(pkgdatadir)/config-rtai-$(VERSION)
|
||||
if test -f Module.symvers ; then \
|
||||
$(INSTALL_DATA) Module.symvers $(DESTDIR)$(moduledir)/Module.symvers ; \
|
||||
fi
|
||||
|
||||
install-exec-local: devices
|
||||
|
||||
dist-hook:
|
||||
$(MAKE) -C $(distdir)/base/config/kconfig \
|
||||
-f Makefile.kconfig distclean srctree=$(distdir)
|
||||
rm -fr `find $(distdir) -name CVS`
|
||||
test -e $(srcdir)/doc || rm -fr $(distdir)/doc
|
||||
|
||||
dev devices:
|
||||
@if test -r $(DESTDIR)/etc/udev/udev.rules ; then \
|
||||
for f in \
|
||||
$(srcdir)/base/ipc/shm/rtai_shm.udev \
|
||||
$(srcdir)/base/ipc/fifos/rtai_fifos.udev \
|
||||
; do \
|
||||
b=`basename $$f` ; \
|
||||
grep -q RTAI:`basename $$b .udev` $(DESTDIR)/etc/udev/udev.rules || \
|
||||
$$sudo sh -c "( echo ; cat $$f ) >> $(DESTDIR)/etc/udev/udev.rules" ; \
|
||||
done ; \
|
||||
elif test -d $(DESTDIR)/etc/udev/rules.d ; then \
|
||||
for f in \
|
||||
$(srcdir)/base/ipc/shm/rtai_shm.udev \
|
||||
$(srcdir)/base/ipc/fifos/rtai_fifos.udev \
|
||||
; do \
|
||||
b=`basename $$f` ; \
|
||||
grep -q RTAI:`basename $$b .udev` $(DESTDIR)/etc/udev/rules.d/99-rtai.rules || \
|
||||
$$sudo sh -c "( echo ; cat $$f ) >> $(DESTDIR)/etc/udev/rules.d/99-rtai.rules" ; \
|
||||
done ; \
|
||||
fi ; \
|
||||
if test x$(DESTDIR) = x; then \
|
||||
if test \! "x`type -t sudo`" = x; then sudo=sudo; else sudo=; fi; \
|
||||
if test \! -c $(DESTDIR)/dev/rtai_shm; then \
|
||||
$$sudo mknod -m 666 $(DESTDIR)/dev/rtai_shm c 10 254; \
|
||||
fi; \
|
||||
for n in `seq 0 9`; do \
|
||||
f="$(DESTDIR)/dev/rtf$$n"; \
|
||||
if test \! -c $$f; then \
|
||||
$$sudo mknod -m 666 $$f c 150 $$n; \
|
||||
fi; \
|
||||
done ; \
|
||||
fi
|
||||
|
||||
.PHONY: reconfig xconfig gconfig mconfig menuconfig config oldconfig clean-if-reconfigured dev devices
|
||||
343
README.INSTALL
Normal file
343
README.INSTALL
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
Installing RTAI-3.x
|
||||
===================
|
||||
|
||||
0. RTAI 3.6
|
||||
================================
|
||||
|
||||
RTAI uses only the leanest and fastest RTAI+Linux combination now, i.e. it
|
||||
dispatches real time interrupts immediately. Moreover within such a scheme
|
||||
i386 has the possibility of completely avoiding the dispatching of critical
|
||||
internal timers and interprocessor scheduling interrupts by vectoring them
|
||||
directly to their handlers. Such an option strongly enhances performances
|
||||
on low end machines and comes by default. You can disable it while configuring
|
||||
RTAI though. See the related configuration helper.
|
||||
What above requires you to patch Linux just with patches found wihin this
|
||||
distribution.
|
||||
Notice also that this release is for use with:
|
||||
- i386,
|
||||
- x86_64,
|
||||
- PPC.
|
||||
|
||||
On recent distributions, managing udev/sysfs, devices created by following
|
||||
this installation procedure will disappear at each machine halting. Then they
|
||||
will be available nomore at the next reboot. RTAI should manage udev/sysfs
|
||||
support but in case something weird will impede it you can solve your problem
|
||||
quickly by restoring RTAI devices before running your application. For that
|
||||
the following short script containing:
|
||||
------------------------------ cut here -------------------------------------
|
||||
if test \! -c /dev/rtai_shm; then
|
||||
mknod -m 666 /dev/rtai_shm c 10 254
|
||||
fi
|
||||
for n in `seq 0 9`; do
|
||||
f=/dev/rtf$n
|
||||
if test \! -c $f; then
|
||||
mknod -m 666 $f c 150 $n
|
||||
fi
|
||||
done
|
||||
------------------------------ cut here -------------------------------------
|
||||
should suffice.
|
||||
|
||||
1. How to build
|
||||
===============
|
||||
|
||||
1.1 Standard procedure
|
||||
----------------------
|
||||
|
||||
The RTAI build system is a merge of Linux's Kconfig with
|
||||
autoconf/automake/libtool. Therefore, you can either build RTAI:
|
||||
|
||||
1.1.1 Interactive configuration
|
||||
-------------------------------
|
||||
|
||||
1) Into the source tree like with 24.1.x (your_source_dir ==
|
||||
your_build_dir). Just run either:
|
||||
|
||||
$ make xconfig # (Qt-based)
|
||||
$ make gconfig # (GTK-based)
|
||||
$ make menuconfig (dialog-based as in 24.1.x)
|
||||
|
||||
Save your configuration, wait for the shell prompt to come back after
|
||||
the configuration script has fully finished, then run "make".
|
||||
|
||||
2) Outside the source tree. From your fresh build directory,
|
||||
either run:
|
||||
|
||||
$ make -f $source_tree/makefile srctree=$source_tree xconfig
|
||||
$ make -f $source_tree/makefile srctree=$source_tree gconfig
|
||||
$ make -f $source_tree/makefile srctree=$source_tree menuconfig
|
||||
|
||||
If you are using a version of make >= 3.80, then you can even get rid
|
||||
of the "srctree=$source_tree" setting. The makefile will infere its
|
||||
value properly.
|
||||
|
||||
1.1.2 Non-interactive configuration
|
||||
-----------------------------------
|
||||
|
||||
Since RTAI 3.x has autoconf inside, people needing automatic
|
||||
non-interactive configuration can directly use the provided GNU
|
||||
configure script for this purpose. The available configuration
|
||||
switches can be listed by running ./configure --help. The
|
||||
RTAI-specific switches are:
|
||||
|
||||
--enable-trace Enable trace support
|
||||
--enable-math Enable math support
|
||||
--enable-bits Enable bits IPC support
|
||||
--enable-fifos Enable fifo IPC support
|
||||
--enable-netrpc Enable netrpc support
|
||||
--enable-netrpc-rtnet Enable use of RTNet
|
||||
--enable-sem Enable semaphore support
|
||||
--enable-msg Enable messaging support
|
||||
--enable-mbx Enable mailbox support
|
||||
--enable-tbx Enable typed mailbox support
|
||||
--enable-mq Enable POSIX-like message queue support
|
||||
--enable-shm Enable shared memory support
|
||||
--enable-malloc Enable real-time malloc support
|
||||
--enable-tasklets Enable tasklets support
|
||||
--enable-usi Enable user-space interrupt support
|
||||
--enable-watchdog Enable watchdog support
|
||||
--enable-leds Enable leds-based debugging support
|
||||
--enable-sched-lxrt Enable scheduler support without RTAI own ktasks
|
||||
--enable-ktasks-sched-lxrt Enable scheduler support with RTAI own ktasks
|
||||
--enable-sched-lock-isr Enable scheduler lock in ISRs
|
||||
--enable-sched-8254-latency= Set 8254 tuning latency
|
||||
--enable-sched-apic-latency= Set APIC tuning latency
|
||||
--enable-sched-lxrt-numslots= Set number of LXRT slots
|
||||
--enable-cplusplus Build in-kernel C++ support
|
||||
--enable-comedi-lxrt Enable comedi/LXRT support
|
||||
--enable-serial Build real-time serial driver
|
||||
--enable-testsuite Build RTAI testsuite
|
||||
--enable-rtailab Build RTAI-Lab
|
||||
--enable-fpu Enable FPU support
|
||||
--enable-math-c99 Enable math C99 support
|
||||
--enable-malloc-vmalloc Enable vmalloc support in malloc
|
||||
--enable-malloc-heap-size Set size of real-time malloc heap
|
||||
--enable-cpus Enable CPUs
|
||||
--enable-dox-doc Build Doxygen documentation
|
||||
--enable-dbx Build Docbook XML documentation.
|
||||
--enable-dbx-network Try to access Docbook DTD and XSL stylesheets through
|
||||
network.
|
||||
--enable-latex-doc Build LaTeX documentation
|
||||
--enable-verbose-latex Uses LaTeX non-stop mode
|
||||
--enable-compat Enable compatibility mode
|
||||
--enable-module-debug Enable debug information in kernel modules
|
||||
--enable-user-debug Enable debug information in user-space programs
|
||||
|
||||
Some configuration targets in base/ can either produce a module,
|
||||
or be statically linked to the RTAI schedulers. Either pass "m" for
|
||||
the modular build to their respective --enable-xxx switch, or "y" for
|
||||
selecting the built-in mode.
|
||||
|
||||
1.1.3 Recycling a configuration file
|
||||
------------------------------------
|
||||
|
||||
You can also recycle an existing .rtai_config file from a previous
|
||||
build by running:
|
||||
|
||||
$ cp -rp $old_builddir/.rtai_config \
|
||||
$new_builddir/.rtai_config
|
||||
$ cd $new_builddir
|
||||
$ make -f $source_tree/makefile srctree=$source_tree oldconfig
|
||||
|
||||
1.1.4 Selecting alternate compilers
|
||||
-----------------------------------
|
||||
|
||||
Compiler selection must be done at _configuration_ time. One only
|
||||
needs to pass the right values for the standard environment variables
|
||||
CC and CXX, respectively for compiling C and C++ source files. In any
|
||||
case, using a GCC toolchain is mandatory. When unspecified, these
|
||||
variables's values respectively default to "gcc" and "g++".
|
||||
|
||||
WARNING: this selection is not aimed at toggling the cross-compilation
|
||||
mode on. In order to do so, please refer to 1.2.
|
||||
|
||||
Examples:
|
||||
|
||||
# Start configuring using the Qt-based GUI with alternate compilers
|
||||
$ make xconfig CC=/my/favourite/c/compiler CXX=/my/favourite/c++/compiler
|
||||
|
||||
# Reconfiguring a previous build tree, changing the compilers on-the-fly.
|
||||
$ make reconfig CC=/my/favourite/c/compiler CXX=/my/favourite/c++/compiler
|
||||
|
||||
# Rebuild all [and optionally install]
|
||||
$ make [all [install]]
|
||||
|
||||
CAVEAT: Since the autoconf-based engine needs to analyze the
|
||||
compilers's features and crams the CC and CXX values into the
|
||||
Makefiles it produces, passing CC and CXX variables at build time
|
||||
simply does _not_ work for the purpose of selecting alternate compiler
|
||||
toolchains. Again, you need to let the configuration engine know about
|
||||
these new settings as explained above.
|
||||
|
||||
1.2 Cross-compilation support
|
||||
-----------------------------
|
||||
|
||||
Simply add ARCH and CROSS_COMPILE variables as usual to the standard
|
||||
command lines, e.g.
|
||||
|
||||
$ make -f $source_tree/makefile ARCH=arm CROSS_COMPILE=arm-linux-
|
||||
|
||||
Names of available architectures can be found under base/arch/*.
|
||||
|
||||
1.3 Installing the software
|
||||
---------------------------
|
||||
|
||||
When the standard (or cross-) compilation has finished:
|
||||
|
||||
$ cd $builddir
|
||||
$ make install
|
||||
|
||||
Everything needed to use the RTAI distribution will be copied there
|
||||
out of the build tree. From now on, you should be able to refer to the
|
||||
installation directory as the root of a complete standalone binary
|
||||
RTAI distribution.
|
||||
|
||||
One may also choose to install the RTAI programs under a temporary
|
||||
staging tree by passing the standard DESTDIR variable to "make" while
|
||||
installing. e.g.
|
||||
|
||||
$ make install DESTDIR=/mnt/target
|
||||
|
||||
will create a standard RTAI hierarchy under /mnt/target, keeping the
|
||||
original prefix information unmodified. If the installation directory
|
||||
selected at configuration time was "/usr/realtime", then the command
|
||||
above will put the RTAI binary distribution under
|
||||
/mnt/target/usr/realtime.
|
||||
|
||||
WARNING: running "make install" is required to run several standard
|
||||
RTAI programs correctly. RTAI 3.x enforces the actual split between
|
||||
the source distribution tree, the build tree where RTAI is going to be
|
||||
compiled, and the final installation directory where RTAI programs can
|
||||
be run eventually. In any case, you should only rely on the
|
||||
installation directory contents to run RTAI programs.
|
||||
|
||||
NOTE: Do not pay attention to the "*** Warning" messages appearing on
|
||||
module compilation output. They are harmless and will be fixed later.
|
||||
|
||||
1.4 Compiling parts of the tree
|
||||
-------------------------------
|
||||
|
||||
RTAI developers may want to recompile parts of the tree from times to
|
||||
times. This automake-based build system allows it: just go to the
|
||||
proper directory level, then issue "make", as usual. This process will
|
||||
recurse as needed.
|
||||
|
||||
The "makefile" (small caps) found in the root source directory is used
|
||||
to bootstrap the build system when it is about to be configured for
|
||||
the first time. After the first configuration has been successful, one
|
||||
just need to run "make xconfig|gconfig|menuconfig|..." as usual.
|
||||
|
||||
1.5 Changing the configuration
|
||||
------------------------------
|
||||
|
||||
Each time you want to change your configuration, just run "make
|
||||
xconfig|gconfig|menuconfig" in your build dir, then "make" (or "make
|
||||
all").
|
||||
|
||||
If you only want to rerun the "configure" script using the current
|
||||
RTAI configuration, just run "make reconfig", there is no need to
|
||||
restart any GUI for that.
|
||||
|
||||
When invoked for the first time in an empty build directory, the
|
||||
default "make" goal is "menuconfig" in a regular terminal, or
|
||||
"xconfig" in an emacs-term.
|
||||
|
||||
1.6 Modifying the autotool template files
|
||||
-----------------------------------------
|
||||
|
||||
If you have to change some template files used by any of the autotools
|
||||
(i.e. Makefile.am, configure.in, acinclude.m4), then you will need the
|
||||
following pack to rebuild the derived files:
|
||||
|
||||
o autoconf 2.59
|
||||
o automake 1.9.2
|
||||
o aclocal 1.9.2
|
||||
o libtool 1.5.8
|
||||
|
||||
1.7 Using the integrated calibration tool
|
||||
-----------------------------------------
|
||||
|
||||
RTAI 3.x comes with a brand new calibration tool which should help you
|
||||
determining if your hardware platform is up to the hard real-time
|
||||
duties. You can find this tool under $installdir/calibration. Here is
|
||||
the output of this tool's help message for x86-based platforms:
|
||||
|
||||
$ ./calibration --help
|
||||
|
||||
OPTIONS:
|
||||
-h, --help
|
||||
print usage
|
||||
-r, --r8254
|
||||
calibrate 8254 oneshot programming type
|
||||
-k, --kernel
|
||||
oneshot latency calibrated for scheduling kernel space tasks
|
||||
-u, --user
|
||||
oneshot latency calibrated for scheduling user space tasks
|
||||
-p <period (us)>, --period <period (us)>
|
||||
the period of the underlying hard real time task/intr, default 100 (us)
|
||||
-t <duration (s)>, --time <duration (s)>
|
||||
set the duration of the requested calibration, default 5 (s)
|
||||
-c, --cpufreq
|
||||
calibrate cpu frequency
|
||||
-a, --apic
|
||||
calibrate apic frequency
|
||||
-b, --both
|
||||
calibrate both apic and cpu frequency
|
||||
-i, --interrupt
|
||||
check worst case interrupt locking/contention on your PC
|
||||
-s<y/n>, --scope<y/n>
|
||||
toggle parport bit to monitor scheduling on a scope, default y(es)
|
||||
|
||||
2. Bootstrapping with vulcano in 7 steps
|
||||
========================================
|
||||
|
||||
>1. patch and build a vanilla Linux kernel tree with the RTAI support as
|
||||
usual. Patches for x86 are available from
|
||||
vulcano/base/arch/i386/patches/. Apply only one of them
|
||||
that matches the Linux kernel version, like this:
|
||||
$ cd $linux-src-dir
|
||||
$ patch -p1 < base/arch/$arch/patches/patchfile
|
||||
|
||||
>2. $ mkdir $builddir && cd $builddir
|
||||
|
||||
>3. $ make -f ../vulcano/makefile srctree=../vulcano
|
||||
|
||||
>4. a GUI should pop up, allowing you to configure RTAI:
|
||||
o default settings should be ok for most platforms
|
||||
o in the "General" section, set your site values for the RTAI
|
||||
installation directory (defaults to /usr/realtime) and
|
||||
Linux kernel tree (defaults to /usr/src/linux).
|
||||
o save and exit.
|
||||
|
||||
--
|
||||
|
||||
At this point, you should see the typical output of a GNU configure
|
||||
script. Your RTAI settings are being used to setup the
|
||||
autoconf/automake-based build system.
|
||||
|
||||
--
|
||||
|
||||
>5. $ make install
|
||||
|
||||
RTAI will be compiled then installed under the directory you specified
|
||||
at configuration time (ensure that your shell can write to the
|
||||
destination directory).
|
||||
|
||||
Remember to add $installdir/bin to your shell PATH variable, where
|
||||
$installdir is your site value for the RTAI installation directory.
|
||||
|
||||
--
|
||||
|
||||
>6. $ cd $installdir/testsuite/kern/latency
|
||||
|
||||
>7. $ ./run
|
||||
|
||||
If "sudo" is installed on your box, the application loader script
|
||||
(rtai-load) will attempt to use it for running privileged commands
|
||||
(e.g. insmod, rmmod et al.) If sudo is not available, just "su"
|
||||
manually before running the run script. You should then see the
|
||||
typical output of the latency calibration program running in kernel
|
||||
space. Hit ^C to stop it.
|
||||
|
||||
--
|
||||
<rpm@xenomai.org>
|
||||
12/5/2004
|
||||
265
README.ISOLCPUS
Normal file
265
README.ISOLCPUS
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
*** EXPLOITING CPUs ISOLATION ***
|
||||
|
||||
Written by:
|
||||
Bernhard Pfund <bernhard@chapter7.ch>
|
||||
and
|
||||
Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
|
||||
RTAI can take advantage of the possibility Linux affords to isolate CPUs
|
||||
from any of its scheduling activity on multi processor (MP) machines.
|
||||
|
||||
Contents:
|
||||
=========
|
||||
1. Isolcpus
|
||||
2. IsolCpuMask in RTAI
|
||||
3. Cpusets & CPU hotplug
|
||||
4. Example init script
|
||||
|
||||
|
||||
1. Isolcpus
|
||||
-----------
|
||||
|
||||
There should be no better explanation of what it is than the following
|
||||
excerpts from Linux 'Documentation/kernel-parameters.txt':
|
||||
|
||||
isolcpus= [KNL,SMP] Isolate CPUs from the general scheduler.
|
||||
Format:
|
||||
<cpu number>,...,<cpu number>
|
||||
or
|
||||
<cpu number>-<cpu number>
|
||||
(must be a positive range in ascending order) or a mixture
|
||||
<cpu number>,...,<cpu number>-<cpu number>
|
||||
This option can be used to specify one or more CPUs
|
||||
to isolate from the general SMP balancing and scheduling
|
||||
algorithms. The only way to move a process onto or off
|
||||
an "isolated" CPU is via the CPU affinity syscalls.
|
||||
<cpu number> begins at 0 and the maximum value is
|
||||
"number of CPUs in system - 1".
|
||||
|
||||
This option is the preferred way to isolate CPUs. The
|
||||
alternative -- manually setting the CPU mask of all
|
||||
tasks in the system -- can cause problems and
|
||||
suboptimal load balancer performance.
|
||||
|
||||
Add the following to the above, from the very same source:
|
||||
acpi_irq_nobalance [HW,ACPI]
|
||||
ACPI will not move active IRQs (default)
|
||||
default in PIC mode
|
||||
|
||||
Irq balancing can be disabled directly at kernel configuration and has little
|
||||
effect on what will follow. Nonetheless you should prefer to be sure that Linux
|
||||
does not manipulate hardware related stuff on its own. So if you forgot to
|
||||
disable irq balancing when you made your kernel there is no need to remake it,
|
||||
just set it at boot time.
|
||||
|
||||
From what above it should be easy to infer that by using "isolcpus" you can
|
||||
be sure that Linux will have none of its tasks running on the isolated cpus.
|
||||
That is not entirely true since a few kernel threads and kworkers will have
|
||||
a copy of each of them repeated and assigned to all of the available CPUs.
|
||||
It is assumed that they will have very little to do if no interrupt arrives
|
||||
on the isolated CPUs. Thus if RTAI is able to care avoiding any hard interrupt
|
||||
on the isolated CPUs they will be fairly well isolated from Linux.
|
||||
|
||||
Nevertheless, to further help isolation, RTAI removes any kernel thread and
|
||||
kworker at the insmoding of its HAL. Even if such an action does not impede
|
||||
their further dynamic creations there is some evidence that it is useful
|
||||
anyhow. It would also be possible to block such dynamic creations, an action
|
||||
that is postponed till more experience is gathered with the use of what above.
|
||||
To easily check if any following dynamic insertion of something within the
|
||||
isolated cpus has happened the following might be of help:
|
||||
cat /proc/*/task/*/status |grep "allowed:" |grep <mask>,
|
||||
where mask is the mask of what you want either to see not or see.
|
||||
|
||||
With what above only Linux rescheduling interrupts should appear on the
|
||||
isolated CPUs. They are not difficult to block too, but it does not seem
|
||||
that much more has to be gained by doing so. Therefore, as for what above,
|
||||
it is momentarily set aside as a possible future TODO action.
|
||||
|
||||
Finally, combining all of the above with the possibility of forcing RTAI
|
||||
enabled Linux process/thread/kthreads to stay on the isolated CPUs the
|
||||
latter will find themselves processing just RTAI real time stuff, with
|
||||
a significant reduction of latencies/jitters. In the case of many RTAI
|
||||
tasks running on the isolated CPUs all issues producing latency/jitter
|
||||
will still have an effect, but it will be reduced to the least possible,
|
||||
without any added bus/pipe/cache interference from Linux.
|
||||
|
||||
It should be noticed however that there will remain a single interrupt still
|
||||
managed by Linux, i.e. the one to the local APIC timer. Such an interrupt
|
||||
will not come from the hardware but from a software inter processor interrupt
|
||||
(IPI) generated by RTAI to keep Linux happy. It is likely that such an IPI
|
||||
could be sent only to non isolated CPUs but no testing of such a solution
|
||||
has been done up to now. The possible change requires just the substitution
|
||||
of a single line of code but I'm afraid it could damage Linux somehow.
|
||||
|
||||
|
||||
2. IsolCpuMask in RTAI
|
||||
----------------------
|
||||
|
||||
Then what you have to do on the RTAI side is to load the core RTAI HAL module
|
||||
using something like: "insmod rtai_hal.ko IsolCpusMask=<xxx>", where <xxx>
|
||||
is the mask of isolated CPUs. Please notice that Linux uses a list if isolated
|
||||
CPUs while RTAI requires the corresponding mask (I'm lazy and let you do it).
|
||||
|
||||
Suppose you have a quadcore system with cores #0 - #3 and want everything but
|
||||
core #0 to be used by RTAI. In that case, just like in the cpuset example below,
|
||||
your IsolCpusMask would be 0xE (1110).
|
||||
|
||||
What will happen next is that RTAI will divert all of Linux interrupts away
|
||||
from the isolated CPUs, keeping those requested for RTAI (rt_request_irq)
|
||||
on the isolated CPUs, without you having to care for it. In such a way there
|
||||
will be no Linux activity on the isolated CPUs whatsoever and they will remain
|
||||
within complete RTAI ownership.
|
||||
|
||||
Finally it is up to you to exploit such a feature by assigning all of your
|
||||
tasks to the isolated CPUs, according to your needs, by using:
|
||||
"rt_task_init_cpuid", "rt_thread_init_cpuid", "rt_task_init_schmod".
|
||||
|
||||
Notice that you have also the possibility of further specialising your CPUs
|
||||
isolation scheme by diverting any real time interrupt you use to a single
|
||||
specific CPU, or CPU cluster within the isolated CPUs, by using the RTAI
|
||||
function: rt_assign_irq_to_cpu.
|
||||
|
||||
Naturally you can set RTAI "IsolCpusMask" even without setting the Linux
|
||||
"isolcpus" list, still with some beneficial effects though, for sure, they
|
||||
will not be as good as with the complete isolation setting described
|
||||
previously.
|
||||
|
||||
|
||||
3. Cpusets & CPU hotplug
|
||||
------------------------
|
||||
|
||||
If you want to make sure nothing unwanted is _ever_ scheduled on a specific
|
||||
CPU or core the hotplug system is your friend. (Logically) offlined CPUs are
|
||||
removed from the Linux scheduler and thus no longer get tasks assigned. Online
|
||||
again and assigned to a cpuset, RTAI tasks can be scheduled on these CPUs. See
|
||||
'Documentation/cpusets.txt' and 'Documentation/cgroup.txt'.
|
||||
|
||||
Consequently you should inform RTAI about the allowed CPUs (1-3 in the example)
|
||||
and initialise your tasks accordingly (see section 2).
|
||||
|
||||
The example below shows a quadcore CPU partitioned into three sections.
|
||||
|
||||
+-Quadcore CPU---------------------+
|
||||
| |
|
||||
| +-Production-+ |
|
||||
| +--------+ | +--------+ | |
|
||||
| | | | | | | |
|
||||
| | Core 0 | | | Core 2 | | |
|
||||
| | | | | | | |
|
||||
| +--------+ | +--------+ | |
|
||||
| | | |
|
||||
| | | |
|
||||
| +-RTnet------+ | | |
|
||||
| | +--------+ | | +--------+ | |
|
||||
| | | | | | | | | |
|
||||
| | | Core 1 | | | | Core 3 | | |
|
||||
| | | | | | | | | |
|
||||
| | +--------+ | | +--------+ | |
|
||||
| +------------+ +------------+ |
|
||||
+----------------------------------+
|
||||
|
||||
- The root set where only core #0 remains. The kernel and all non real-time
|
||||
tasks run on that single core.
|
||||
|
||||
- The 'RTnet' cpuset on core #1 where all RTDM related tasks are scheduled on.
|
||||
|
||||
- The 'Production' cpuset where the real-time controller tasks are executed.
|
||||
This cpuset has load-balancing enabled, hence tasks assigned to that set are
|
||||
scheduled on either core #3 or #4 and can be moved within the scheduler domain
|
||||
if necessary.
|
||||
|
||||
Memory isolation is not used in this example and no overlapping sets exist, it's
|
||||
even actively prevented by using the cpu_exclusive attribute.
|
||||
|
||||
By appropriately exploiting both isolation methods illustrated above it is mostly
|
||||
possible to reduce latencies to single microsec digit figures, especially if the
|
||||
hard timer periodic mode is adopted.
|
||||
|
||||
|
||||
4. Example init script
|
||||
----------------------
|
||||
|
||||
############# START OF SCRIPT #############
|
||||
|
||||
# Environment
|
||||
MKDIR=/bin/mkdir
|
||||
MOUNT=/bin/mount
|
||||
ECHO=/bin/echo
|
||||
CPUSET=/dev/cpuset
|
||||
DEVICES=/sys/devices/system/cpu
|
||||
SLEEP=/bin/sleep
|
||||
NAME=cpuset
|
||||
|
||||
reset_cpus()
|
||||
{
|
||||
# Shutdown CPU cores 1 - 3
|
||||
$ECHO 0 > $DEVICES/cpu1/online
|
||||
$ECHO 0 > $DEVICES/cpu2/online
|
||||
$ECHO 0 > $DEVICES/cpu3/online
|
||||
|
||||
# Noop
|
||||
$SLEEP 1
|
||||
|
||||
# Enable CPU cores 1 - 3
|
||||
$ECHO 1 > $DEVICES/cpu1/online
|
||||
$ECHO 1 > $DEVICES/cpu2/online
|
||||
$ECHO 1 > $DEVICES/cpu3/online
|
||||
}
|
||||
|
||||
mount_cpuset()
|
||||
{
|
||||
$MKDIR $CPUSET
|
||||
|
||||
# Configure the root set
|
||||
if [ -e $CPUSET ]; then
|
||||
$MOUNT -t cgroup -ocpuset cpuset $CPUSET
|
||||
# Disable load balancing in the root set
|
||||
$ECHO 0 > $CPUSET/cpuset.sched_load_balance
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
create_rtnet_set()
|
||||
{
|
||||
# Configure the RTnet cpuset
|
||||
if [ -e $CPUSET ]; then
|
||||
$MKDIR $CPUSET/rtnet
|
||||
$ECHO 1 > $CPUSET/rtnet/cpuset.cpus
|
||||
$ECHO 1 > $CPUSET/rtnet/cpuset.cpu_exclusive
|
||||
|
||||
# Disable load balancing in the rtnet set
|
||||
$ECHO 0 > $CPUSET/rtnet/cpuset.sched_load_balance
|
||||
fi
|
||||
}
|
||||
|
||||
create_production_set()
|
||||
{
|
||||
# Configure the production cpuset
|
||||
if [ -e $CPUSET ]; then
|
||||
$MKDIR $CPUSET/production
|
||||
$ECHO 2,3 > $CPUSET/production/cpuset.cpus
|
||||
$ECHO 1 > $CPUSET/production/cpuset.cpu_exclusive
|
||||
|
||||
# Enable load balancing in the production set
|
||||
$ECHO 1 > $CPUSET/production/cpuset.sched_load_balance
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
reset_cpus
|
||||
mount_cpuset
|
||||
create_rtnet_set
|
||||
create_production_set
|
||||
;;
|
||||
stop)
|
||||
reset_cpus
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/$NAME {start|stop}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
############# END OF SCRIPT #############
|
||||
186
README.LINUX_SERVER
Normal file
186
README.LINUX_SERVER
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
*** SERVING LINUX SYSCALLS IN RTAI HARD REAL TIME MODE ***
|
||||
|
||||
The default RTAI way of dealing with Linux syscalls done while in hard real
|
||||
time consists in moving a task wanting to use Linux back to soft mode,
|
||||
recovering it to hard real time again, as soon as possible, afterward. See the
|
||||
related RTAI configuration helper for an explanation of the different available
|
||||
modes to implement the "as soon as possible" above on various architectures.
|
||||
|
||||
This README documents possible alternative ways to access Linux services from
|
||||
hard real time RTAI applications in user space. Such a support is based on the
|
||||
creation of a general purpose server thread that takes over Linux requests.
|
||||
|
||||
It must be noticed that if Linux is to be used synchronously at the very moment
|
||||
Linux is called the task becomes timed by Linux, wherever a Linux server is
|
||||
used or not. So hard real time constraints cannot be satisfied anyhow. The use
|
||||
of a Linux server has an advantage though. In fact it takes just two context
|
||||
switches, in place of the four used by hard-soft-hard transitions. Moreover it
|
||||
ensures that RTAI returns to hard real time immediately after the Linux syscall
|
||||
has finished while, if the architecture does not support the immediate Linux
|
||||
syscall mode reliably for all Linux syscalls, there will be the need to wait
|
||||
for a call to an RTAI function to go back in RTAI hard real time fully. That
|
||||
will add even far more latencies when a hard RTAI task does some processing
|
||||
for a significant amount of time after the Linux syscall, without using any
|
||||
RTAI service. So, provided it is allowed loosing real time, installing a
|
||||
synchronous server might be the best way to interact with Linux anyhow.
|
||||
|
||||
There are however instances in which Linux can be used asynchronously. In
|
||||
such cases RTAI hard real time tasks might use Linux without loosing hard
|
||||
real time determinism. Such a capability can be implemented in many ways,
|
||||
the one chosen by RTAI is based on a buffering of async Linux syscalls mated
|
||||
either to an optional callback function or to inquiry mechanisms to help
|
||||
implementing any user own async call policy. Beware of not reusing read/write
|
||||
data buffers made available to async calls though.
|
||||
If you do not want, or cannot, either inquire for or check async terminations,
|
||||
to avoid running the risk of reusing an yet unserved buffer, use RTAI dynamic
|
||||
memory or SCB to allocate them in real time, freeing them afterward, possibly
|
||||
with the help of a support callback function.
|
||||
Async support is a bit tricky but, provided one cares of what said above, it
|
||||
should work always when Linux syscalls arguments are fully contained in the
|
||||
passed registers structure. That is not the case for a few Linux syscalls that
|
||||
are multiplexed within a single framework, whereas libc can end in building a
|
||||
hidden object on the stack, so that it is not assured it will be available at
|
||||
the time the server uses it. On some archs a notable example of that is the
|
||||
socketcall, but RTAI should already care of it appropriately. There remain
|
||||
nonetheless the chance of other instances to be cared as well. So beware that
|
||||
some async calls might not work with a few Linux services yet, in which case
|
||||
you should let us know about it for a possible fix.
|
||||
Just to mention another typical care to be taken we notice that printf might
|
||||
work as it is but it will often crash. So the safe way to printf is as follows:
|
||||
- sprintf(buffer, format, args, ....);
|
||||
- write(STDOUT_FILENO, buffer, strlen(buffer));
|
||||
|
||||
Provided the socketcall has been intercepted well you should be able to do many
|
||||
IO operations asynchronously, e.g.: dumping data directly to disk, Linux ipcs
|
||||
and POSIX mq, fifos, pipes, serial and networked communications etc. etc.
|
||||
In many applications one often requires RTAI specific IO drivers just to avoid
|
||||
loosing real time for communications with non real time support/interface
|
||||
processes and tasks. The async server should be of much help in such cases by
|
||||
letting you use standard Linux, with the ensuing advantage of not needing any
|
||||
special hard real time driver.
|
||||
|
||||
Clearly what above does not impede you to set up your own async server to
|
||||
which your hard real time task can be connected by using RTAI non blocking
|
||||
communication functions, i.e. those ending with "_if". So the choice of the
|
||||
most viable solution is left to you.
|
||||
|
||||
How it works
|
||||
------------
|
||||
|
||||
By using the functions described below a server thread is created that will
|
||||
block waiting for parent task requests to Linux. Whenever the RTAI scheduler
|
||||
intercepts a Linux syscall in hard real time mode it passes it to the server
|
||||
thread and:
|
||||
- remains waiting for its execution if in sync mode;
|
||||
- returns immediately if in async mode.
|
||||
The server carries out the syscall and:
|
||||
- resumes the hard real time parent, returning what returned by Linux, if in
|
||||
sync mode:
|
||||
- calls a callback function, if one has been made available, in async mode,
|
||||
returning an identifier.
|
||||
|
||||
As said in sync mode real time is lost, but there will be two task switches per
|
||||
Linux service request only, while there will be four if no sync server is used.
|
||||
In async mode there is no need for any task switch, as the server will execute
|
||||
in soft mode when there will be no RTAI real time activity any more.
|
||||
The need of passing syscall data to the server is responsible for most of the
|
||||
penalty incurred by using a Linux server.
|
||||
Let's stress once more that this is a far better alternative way to what the
|
||||
RTAI scheduler will have to do anyhow, i.e. make you soft and recover hard mode
|
||||
at the next RTAI proper service call, which will require four task switches,
|
||||
keeping you in Linux hands from the Linux syscall till an RTAI function is
|
||||
called again.
|
||||
With a server instead you will stay soft just either till Linux has finished
|
||||
servicing your request, when in sync mode, or kept working in real time, when
|
||||
in async mode.
|
||||
|
||||
API Functions prototypes
|
||||
------------------------
|
||||
|
||||
The available functions are:
|
||||
|
||||
- void *rt_create_linux_syscall_server(RT_TASK *task, int mode, void
|
||||
(*callback_fun)(long, long), int nr_bufd_async_calls);
|
||||
create a Linux syscall server for task, a NULL task means the current one; a
|
||||
non NULL return is the handle allowing you to link to the server for any
|
||||
further management request, see functions below, NULL indicates a failure in
|
||||
setting the server up; a NULL callback_fun is allowed. It will operate
|
||||
according to mode setting, either SYNC_LINUX_SYSCALL or ASYNC_LINUX_SYSCALL.
|
||||
Beware of using an appropriate nr_bufd_async_calls. If async requests overrun
|
||||
the latest will be discarded till some space is available again.
|
||||
If a server exists already it is terminated and a new one replaces it.
|
||||
|
||||
- void rt_destroy_linux_syscall(RT_TASK *task);
|
||||
destroy the linux_syscall_server of task, if NULL use the current task.
|
||||
|
||||
- void *rt_sync_async_linux_syscall_server_create(RT_TASK *task, int mode,
|
||||
void (*callback_fun)(long, long), int nr_bufd_async_calls);
|
||||
legacy interface, the same as:
|
||||
rt_create_linux_syscall_server(task, mode, callback_fun, nr_bufd_async_calls).
|
||||
|
||||
- void *rt_linux_syscall_server_create(RT_TASK *task);
|
||||
legacy call, the same as:
|
||||
rt_create_linux_syscall_server(task, SYNC_LINUX_SYSCALL, NULL, 1).
|
||||
|
||||
Notice that in sync mode Linux functions will return their usual values while
|
||||
that is not possible in async mode and what returned is an identifier, id, of
|
||||
that specific async call, a negative id meaning the call was not satisfied
|
||||
because of a buffer overrun. When <= 0 ids can be used for monitoring async
|
||||
calls execution, as explained below.
|
||||
|
||||
- int rt_set_linux_syscall_mode(int mode, void (*callback_fun)(long, long);
|
||||
to both switch between sync and async mode and change the call back function.
|
||||
It returns EINVAL if there is no server or the mode setting is not correct.
|
||||
|
||||
Notice that this is a legacy call, you'd better use:
|
||||
|
||||
- int rt_linux_syscall_mode(struct linux_syscalls_list *syscalls, int mode);
|
||||
to switch between sync and async mode; syscalls is the handle returned by
|
||||
rt_sync_async_linux_syscall_server_create; mode can be: SYNC_LINUX_SYSCALL,
|
||||
ASYNC_LINUX_SYSCALL, LINUX_SYSCALL_GET_MODE.
|
||||
The function returns the previous mode and LINUX_SYSCALL_GET_MODE can be used
|
||||
to just inquire for it, in which case mode is discarded. EINVAL is returned if
|
||||
syscalls is not a valid pointer.
|
||||
|
||||
- void *rt_linux_syscall_cbfun(struct linux_syscalls_list *syscalls, void (*cbfun)(long, long));
|
||||
to change the callback function; syscalls is the handle returned by
|
||||
rt_sync_async_linux_syscall_server_create; cbfun can be either a NULL, no
|
||||
callback will be used, a pointer to a true callback function,
|
||||
LINUX_SYSCALL_GET_CALLBACK.
|
||||
The function returns the pointer to the previous callback function and
|
||||
LINUX_SYSCALL_GET_CALLBACK can be used to just inquire for it. EINVAL is
|
||||
returned if syscall is not a valid pointer
|
||||
|
||||
The callback function afford a notification control mechanism for async calls.
|
||||
An alternative way to monitor async calls execution is given by the following
|
||||
functions:
|
||||
|
||||
- int rt_linux_syscall_status(struct linux_syscalls_list *syscalls, int id, int *retval);
|
||||
syscalls is the handle returned from rt_sync_async_linux_syscall_server_create;
|
||||
id is the value returned by the call to Linux, retval is a pointer to an int
|
||||
that will receive the value returned by Linux after executing the related
|
||||
service.
|
||||
It returns:
|
||||
- EINVAL if syscalls is not a valid pointer or id < 0
|
||||
- ENOENT if no id is found, meaning the function has been overwritten;
|
||||
- ECANCELED when the function has call has been explicitly canceled by the
|
||||
user;
|
||||
- EINPROGRESS when the function is pending waiting for execution;
|
||||
- 0 when the function has been executed, in such a case retval, if not NULL,
|
||||
will receive the value returned by Linux.
|
||||
|
||||
- int rt_linux_syscall_cancel(struct linux_syscalls_list *syscalls, int id);
|
||||
Syscalls is the handle returned from rt_sync_async_linux_syscall_server_create;
|
||||
id is the value returned by the call to Linux.
|
||||
It returns:
|
||||
- EINVAL if syscalls is not a valid pointer or id < 0
|
||||
- ENOENT if no id is found, meaning the function has been overwritten;
|
||||
- -id when the function has been executed already;
|
||||
- 0 if the function has been successfully canceled.
|
||||
|
||||
Examples
|
||||
-------
|
||||
|
||||
They are in RTAI "showroom" CVS: linux_server and printer_server.
|
||||
|
||||
Paolo.
|
||||
57
README.LXRT_EXTS_IN_USE
Normal file
57
README.LXRT_EXTS_IN_USE
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
User space RTAI syscalls have 16 extensions slots. They allow any user to
|
||||
extend RTAI with her/his own user space callable APIs without touching
|
||||
RTAI itself. For the most efficient inline usage of any extension user slots
|
||||
must be assigned statically. RTAI itself uses a few extension slots for some
|
||||
of its native addons, as listed below.
|
||||
|
||||
Those already used by modules found in this distributions are:
|
||||
0 - RTAI itself (hardwired),
|
||||
1 - tasklets (hardwired),
|
||||
2 - watchdog (hardwired),
|
||||
9 - comedi,
|
||||
10 - fifos,
|
||||
14 - serial,
|
||||
15 - rtdm.
|
||||
|
||||
So you can reuse the above slots only if you are not using the related modules
|
||||
found in this distribution. In any case check the value returned by:
|
||||
set_rt_fun_ext_index.
|
||||
|
||||
N.B. "(hardwired)" above means they are assumed as basic RTAI proper extensions.
|
||||
Nonetheless extension 1 and 2 do check if they can install into their hardwired
|
||||
slots, exiting their installation in error if they cannot.
|
||||
So you can make the related slot yours if neither tasklets nor watchdog are
|
||||
being used by your applications; __NEVER__ USE 0 though.
|
||||
In any case you'd better choose the other many free slots available to avoid
|
||||
any trouble.
|
||||
|
||||
If in doubt about slots engaged already use something like the following piece
|
||||
of code in your extension module to discover them:
|
||||
|
||||
#define MAX_LXRT_EXT 16
|
||||
do {
|
||||
int i;
|
||||
struct rt_fun_entry fun;
|
||||
for (i = 0; i < MAX_LXRT_EXT; i++) {
|
||||
if (set_rt_fun_ext_index(&fun, i) < 0) {
|
||||
rt_printk("< LXRT SLOT %d ENGAGED >\n", i);
|
||||
} else {
|
||||
reset_rt_fun_ext_index(&fun, i);
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
It has been already said above but, if you are still asking yourself why there
|
||||
is a forced staticalization of LXRT extension slots assignment, while it
|
||||
would be trivial to have functions to get/free slots dynamically, think about
|
||||
efficiency first, especially if direct (eager in the related RTAI config
|
||||
caption) inlining is used.
|
||||
|
||||
WARNING
|
||||
|
||||
If you intend to use Linux i386 with REGPARM configured notice that all your
|
||||
functions callable from user space must be prefixed with "RTAI_SYSCALL_MODE".
|
||||
In such a way they will be usable both with and without REGPARM. If you do
|
||||
not do so then avoid configuring REGPARM for Linux, which is not possible from
|
||||
2.6.20 onward, where REGPARM is the only way to operate and so it is an option
|
||||
no more.
|
||||
1
README.SMI
Normal file
1
README.SMI
Normal file
|
|
@ -0,0 +1 @@
|
|||
See base/arch/i386/calibration/README.SMI
|
||||
14
README.maintainer
Normal file
14
README.maintainer
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
- change version in:
|
||||
- configure.in
|
||||
- base/arch/*/defconfig (no more)
|
||||
- base/arch/*/Kconfig (no more)
|
||||
|
||||
- cvs tag -F RTAI_X_Y
|
||||
|
||||
NOTE: base/arch/m68k contains files whose path is too long for the default
|
||||
command generated by automake/autoconf for the tar command, which uses
|
||||
the (obsolete) -o option for compatibility with legacy versions.
|
||||
s/chof/chf/
|
||||
|
||||
This option, right now, needs to be manually removed from the generated
|
||||
GNUMakefile in the root of the build tree.
|
||||
18
addons/GNUmakefile.am
Normal file
18
addons/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
OPTDIRS =
|
||||
|
||||
if CONFIG_RTAI_CPLUSPLUS
|
||||
OPTDIRS += cpp
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_RTDM
|
||||
OPTDIRS += rtdm
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_COMEDI_LXRT
|
||||
OPTDIRS += comedi
|
||||
endif
|
||||
|
||||
OPTDIRS += drivers
|
||||
|
||||
SUBDIRS = $(OPTDIRS)
|
||||
59
addons/comedi/GNUmakefile.am
Normal file
59
addons/comedi/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
moduledir = @RTAI_MODULE_DIR@
|
||||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
CROSS_COMPILE = @CROSS_COMPILE@
|
||||
|
||||
libmodule_a_SOURCES = kcomedi-module.c
|
||||
|
||||
include_HEADERS = rtai_comedi.h
|
||||
|
||||
if CONFIG_KBUILD
|
||||
rtai_comedi.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_comedi.ko: $(libmodule_a_SOURCES)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ rtai_extradef="-I@COMEDI_DIR@/include" \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
clean-local:
|
||||
@RTAI_KBUILD_CLEAN@
|
||||
else
|
||||
noinst_LIBRARIES = libmodule.a
|
||||
|
||||
libmodule_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
libmodule_a_CFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include \
|
||||
-I@COMEDI_DIR@/include
|
||||
|
||||
rtai_comedi.o: libmodule.a
|
||||
$(CROSS_COMPILE)$(LD) --whole-archive $< -r -o $@
|
||||
endif
|
||||
|
||||
all-local: rtai_comedi$(modext)
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
$(mkinstalldirs) $(top_srcdir)/modules
|
||||
$(INSTALL_DATA) $^ $(top_srcdir)/modules
|
||||
endif
|
||||
|
||||
install-exec-local: rtai_comedi$(modext)
|
||||
$(mkinstalldirs) $(DESTDIR)$(moduledir)
|
||||
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
|
||||
|
||||
lib_LIBRARIES = libkcomedilxrt.a
|
||||
|
||||
libkcomedilxrt_a_CFLAGS = \
|
||||
@RTAI_REAL_USER_CFLAGS@ \
|
||||
-DCONFIG_RTAI_LXRT_INLINE=0 \
|
||||
-D_GNU_SOURCE -D_REENTRANT \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include \
|
||||
-I@COMEDI_DIR@/include
|
||||
|
||||
libkcomedilxrt_a_SOURCES = kcomedi.c
|
||||
|
||||
libkcomedilxrt_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
EXTRA_DIST = Makefile.kbuild patchlinuxcomedi
|
||||
10
addons/comedi/Makefile.kbuild
Normal file
10
addons/comedi/Makefile.kbuild
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
|
||||
-I$(rtai_srcdir) \
|
||||
-I$(src)/../../base/include \
|
||||
-I$(src)/../.. \
|
||||
$(rtai_extradef) \
|
||||
-D__IN_RTAI__
|
||||
|
||||
obj-m += rtai_comedi.o
|
||||
|
||||
rtai_comedi-objs := $(rtai_objs)
|
||||
243
addons/comedi/README
Normal file
243
addons/comedi/README
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
<*> RTAI_KCOMEDI IN USER SPACE <*>
|
||||
|
||||
This release of RTAI is intended to be mated to the latest COMEDI git
|
||||
repository, as found at: www.comedi.org. Warm thanks are due to Frank Mori Hess
|
||||
<fmhess@users.sourceforge.net> and Ian Abbott <abbotti@mev.co.uk>, for their
|
||||
help and suggestions about stabilizing on such a choice, taking the chance
|
||||
of these thanks to recall also the one who initiated it all: David Schleef.
|
||||
|
||||
This porting of KCOMEDI to user space is done using the standard extension
|
||||
feature of LXRT and makes KCOMEDI symmetrically usable in kernel and user
|
||||
space within RTAI, in soft/hard real time. To use KCOMEDI in user space you
|
||||
have just to know how to use it in kernel space. So whatever space you are
|
||||
going to work in it will be mostly the same.
|
||||
|
||||
There are nonetheless a few points forbidding the above statements to be
|
||||
unconditionally true. The related clashes are resolved with functions
|
||||
prefixed with "rt_".
|
||||
|
||||
One is related to a couple of name returning functions:
|
||||
"comedi_get_driver_name" and "comedi_get_board_name".
|
||||
|
||||
In kernel space the requested name is simply got by returning a pointer to
|
||||
a directly addressable global namestring, which wont work in user space.
|
||||
So there is the need of copying the namestring available in kernel space to
|
||||
user space, therefore the calling convention must be changed. Then the
|
||||
following two aliases, usable both in kernel and user space, have been made
|
||||
available:
|
||||
void *rt_comedi_get_driver_name(unsigned int dev, char *name);
|
||||
void *rt_comedi_get_board_name(unsigned int dev, char *name);
|
||||
On success both of them return the address "name", at which the actual name
|
||||
is copied, NULL otherwise.
|
||||
|
||||
The solution of the above problem is simple and, almost, compulsory.
|
||||
In fact the only real problem to be solved for a symmetric approach to
|
||||
KCOMEDI in kernel and user space has been the use of a callback function
|
||||
in user space for which a fairly general usage scheme has been devised.
|
||||
|
||||
The callback method made available is based on using a built in callback
|
||||
function that triggers an rt_task_resume and allows returning back to the
|
||||
user the important unsigned long mask, made available by the standard KCOMEDI
|
||||
callback service as its first argument.
|
||||
|
||||
The related support comes from using the following function, not needed but
|
||||
available in kernel space also (in case you'll like it):
|
||||
int rt_comedi_register_callback(void *dev, unsigned int subdev, unsigned int
|
||||
mask, int (*callback)(unsigned int, void *), void *task);
|
||||
- the first 3 arguments are the same as in "comedi_register_callback", while
|
||||
"callback" is discarded and "task" is the pointer to an RTAI task that
|
||||
waits for asynchronous events to happen. NULL can be used in place of
|
||||
"task", if it is the current one, in which case RTAI can care of setting
|
||||
it appropriately.
|
||||
|
||||
For compatibility reasons the standard COMEDI:
|
||||
int comedi_register_callback(unsigned int minor, unsigned int subdev,
|
||||
unsigned int mask, int (*cb)(unsigned int, void *), void *arg);
|
||||
is also available in user space in the form of a macro that redirects it to
|
||||
"rt_comedi_register_callback", setting "cb" to NULL while "arg" should be
|
||||
assigned either the pointer to the task to be used or NULL.
|
||||
As said there is clearly no need for anything similar in kernel space, as the
|
||||
original COMEDI function is available directly, but the user space approach,
|
||||
with its canned solution, might prove viable and easier to use in kernel space
|
||||
also.
|
||||
|
||||
After the COMEDI callback has been initialized a user can synchronize its
|
||||
application with COMEDI asynchronous events by using any of the following
|
||||
functions, usable in kernel space also naturally:
|
||||
|
||||
long rt_comedi_wait(unsigned int *cbmask);
|
||||
- this function waits for the callback unconditionally; cbmask is a compulsory
|
||||
non NULL pointer to a variable that will receive the callback mask of the
|
||||
events that triggered it.
|
||||
|
||||
long rt_comedi_wait_if(unsigned int *cbmask);
|
||||
- this function is equivalent to "rt_comedi_wait" but returns immediately
|
||||
if no COMEDI event has been signaled yet. Useful for polling COMEDI events,
|
||||
through the returned mask, without blocking.
|
||||
|
||||
long rt_comedi_wait_until(RTIME until, unsigned int *cbmask);
|
||||
- this function is equivalent to "rt_comedi_wait" but features an absolute
|
||||
timeout, given by "until".
|
||||
|
||||
unsigned long rt_comedi_wait_timed(RTIME delay, unsigned int *cbmask);
|
||||
- this function is equivalent to "rt_comedi_wait" but features a relative
|
||||
timeout, given by "delay".
|
||||
|
||||
- The returned value can be:
|
||||
- 0 if waiting for a callback succeeded,
|
||||
- a negative number, in which case its absolute value indicates wait overruns;
|
||||
- an RTAI error if >= RTE_BASE.
|
||||
|
||||
It is likely that the illustrated callback scheme and synchronization is
|
||||
better exploited by using a thread acting as an asynchronous COMEDI events
|
||||
manager in hard real time. However it is by no means the only way as the
|
||||
above wait functions can be used anywhere and rt_comedi_wait_if makes it
|
||||
possible an easy implementation of a polling scheme.
|
||||
In fact async wait read functions embed comedi_waits for an easier and more
|
||||
compact use of async command readings, see below.
|
||||
Notice that rt_comedi_wait_if is provided to comply with the standard RTAI
|
||||
synchronizing functions scheme: unconditional, if, until, timed.
|
||||
An alternative way is provided through the standard KCOMEDI async data polling,
|
||||
i.e.: comedi_poll.
|
||||
|
||||
Once woken up from wait one can call:
|
||||
long rt_comedi_command_data_read (void *dev, unsigned int subdev, long nchans,
|
||||
lsampl_t *data);
|
||||
to get "nchans" channels in "data". Notice that data are read only if "nchans"
|
||||
elements are available, nothing being done otherwise. Such a condition can
|
||||
be checked through the returned value, which will be the number of available
|
||||
read channels data. So a return value less than "nchans" will mean nothing has
|
||||
been read. The return value can be RTE_OBJINV also, in the case of dev/subdev
|
||||
being wrong.
|
||||
It is believed that imposing that either "nchans" data or nothing is available
|
||||
is the most appropriate real time mechanism, as it is better to let the user
|
||||
decide what to do in place of waiting on a rescheduling by default. In fact,
|
||||
after an appropriate wait function is called, missing data might be a error
|
||||
to care of. If it is not so then, by exploiting the available wait functions,
|
||||
the user has plenty of opportunities to implement her/his own best policy.
|
||||
If one notices a bias toward sampling data for digital control systems, versus
|
||||
pure data acquisition, (s)he is right, absolutely. See below for something
|
||||
reinforcing such a bias. Despite such an attitude nothing is lost in the case
|
||||
of pure data acquisition.
|
||||
|
||||
A typical code sample could be:
|
||||
|
||||
long mask, avbs;
|
||||
.
|
||||
comedi_register_callback(dev, subdev, COMEDI_CB_EOS, NULL, task);
|
||||
.
|
||||
if (rt_comedi_wait_timed(nano2count(TIMEOUT), &mask) != 0) {
|
||||
printf("waiting for async data failed\n");
|
||||
}
|
||||
.
|
||||
if (mask & COMEDI_CB_EOS) {
|
||||
if ((avbs = rt_comedi_command_data_read(dev, subdev, NCHAN, data)) != NCHAN) {
|
||||
printf("only %ld channels data available in place of %d, nothing read\n", avbs, NCHAN);
|
||||
}
|
||||
.
|
||||
}
|
||||
.
|
||||
|
||||
Calling an rt_comedi_wait followed by rt_comedi_command_data_read is OK and
|
||||
let the user do whatever check (s)he needs. Nonetheless, when working in user
|
||||
space, it has the disadvantage of taking two trips to kernel space. Since what
|
||||
is mostly required is a successful rt_comedi_wait with a mask containing the
|
||||
appropriate user expected callback mask the two calls can be unified. Such a
|
||||
scheme is mostly useful in a digital controller, whereas a single call paces
|
||||
its action in such a way that at each sampling time one is ready to apply
|
||||
her/his control law on the available channels samples immediately.
|
||||
|
||||
To that end RTAI makes available the following:
|
||||
long rt_comedi_command_data_wread(void *dev, unsigned int subdev, long nchans, lsampl_t *data, long *mask);
|
||||
long rt_comedi_command_data_wread_if(void *dev, unsigned int subdev, long nchans, lsampl_t *data, long *mask);
|
||||
long rt_comedi_command_data_wread_until (void *dev, unsigned int subdev, long nchans, lsampl_t *data, RTIME until, long *mask);
|
||||
long rt_comedi_command_data_wread_timed(void *dev, unsigned int subdev, long nchans, lsampl_t *data, RTIME delay, long *mask);
|
||||
whose arguments are the union of the previous calls, with "mask" containing
|
||||
the event flags that must be found set in the callback mask returned by COMEDI
|
||||
callbacks.
|
||||
|
||||
The previous code snippet would become:
|
||||
|
||||
long mask, avbs;
|
||||
.
|
||||
comedi_register_callback(dev, subdev, COMEDI_CB_EOS, NULL, task);
|
||||
.
|
||||
mask = COMEDI_CB_EOS;
|
||||
if ((avbs = rt_comedi_command_data_wread_timed(dev, subdev, NCHAN, data, nano2count(TIMEOUT), &mask)) != NCHAN) {
|
||||
printf("only %ld channels data available in place of %d, or an error occured, nothing read\n", avbs, NCHAN);
|
||||
}
|
||||
.
|
||||
|
||||
There are examples in RTAI "showroom" CVS, "user/comedi" that should help
|
||||
in depicting the use of the above explained extensions.
|
||||
|
||||
The async write mate of async data reading is the following:
|
||||
long rt_comedi_command_data_write(void *dev, unsigned int subdev, long nchans, lsampl_t *data);
|
||||
arguments and return values being the same of rt_comedi_command_data_read.
|
||||
|
||||
Another useful service is:
|
||||
int rt_comedi_trigger(void *dev, unsigned int subdev);
|
||||
It is based on an easy set up of a wrapper, using the appropriate
|
||||
comedi_do_insn for the actual triggering action.
|
||||
|
||||
Finally the function:
|
||||
int rt_comedi_do_insnlist(void *dev, comedi_insnlist *ilist);
|
||||
has been added, symmetrically in kernel/user space as usual.
|
||||
It is an exact image of its parent:
|
||||
int comedi_do_insnlist(void *dev, comedi_insnlist *list);
|
||||
which is not available in KCOMEDI. That's why we prefixed it with an "rt_".
|
||||
The simple reason of it being missed in kernel space is because it will add
|
||||
just the overhead of one call more to obtain something that a user can have
|
||||
directly by executing repeated "comedi_do_insn" in her/his own way. From user
|
||||
space instead the overhead of calling "comedi_do_insn" many times could
|
||||
be much more significant, so it might help in having the possibility of
|
||||
executing a whole set of instructions in a single shot to kernel space only.
|
||||
|
||||
The following macros can be used to avoid remembering the instruction fields:
|
||||
#define BUILD_AREAD_INSN(insn, subdev, data, nd, chan, arange, aref)
|
||||
to set up an instruction for analog input;
|
||||
#define BUILD_AWRITE_INSN(insn, subdev, data, nd, chan, arange, aref)
|
||||
to set up an instruction for analog output;
|
||||
#define BUILD_DIO_INSN(insn, subdev, data, nd)
|
||||
to set up an instruction for digital input/output.
|
||||
|
||||
A final warning: all KCOMEDI functions are executed without the comedi_lock
|
||||
being activated. That's because it adds some, albeit negligible on nowadays
|
||||
machines, overhead and because in control systems it is rare to have possible
|
||||
conflicting acquisitions shared among more tasks. If a locked execution is
|
||||
needed nonetheless, then the user can explicitly configure RTAI to do that,
|
||||
in which case it will be applied to all services. Being "comedi_lock" and
|
||||
"comedi_unlock" available to the user anyhow, (s)he is free to apply them
|
||||
explicitly whenever (s)he has decided to not configure them by default.
|
||||
|
||||
"The Comedi Players"
|
||||
|
||||
|
||||
<*> USING RTAI_KCOMEDI FOR DISTRIBUTED DATA ACQUISITION <*>
|
||||
|
||||
Distributed data acquisition is obtained by simply using the standard NETRPC
|
||||
specification, i.e.:
|
||||
|
||||
- use just the name of any already available function substituting either
|
||||
"rt_..." with "RT_..." or, as for the direct use of COMEDI APIs names.
|
||||
prefixing "RT_" in front of them
|
||||
- add two initial arguments more, i.e. the "node" of and the "port" on the
|
||||
remote machine that will execute "RT_..." functions.
|
||||
|
||||
For example:
|
||||
rt_comedi_do_insnlist(dev, ilist);
|
||||
becomes:
|
||||
RT_comedi_do_insnlist(dev, ilist);
|
||||
while:
|
||||
comedi_do_insn(dev, insn);
|
||||
becomes:
|
||||
RT_comedi_do_insn(dev, insn);
|
||||
as well.
|
||||
|
||||
Naturally the remote node, where the data acquisition hardware is installed,
|
||||
must have insmoded: all of the modules needed for COMEDI, rtai_netrpc and
|
||||
rtai_comedi.
|
||||
There are examples in RTAI "showroom" CVS, "user/comedi" that should help
|
||||
in depicting the use of the above explained extensions.
|
||||
|
||||
Paolo Mantegazza
|
||||
741
addons/comedi/kcomedi-module.c
Normal file
741
addons/comedi/kcomedi-module.c
Normal file
|
|
@ -0,0 +1,741 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Thomas Leibner (leibner@t-online.de) (first complete writeup)
|
||||
* 2002 David Schleef (ds@schleef.org) (COMEDI master)
|
||||
* 2002 Lorenzo Dozio (dozio@aero.polimi.it) (made it all work)
|
||||
* 2006 Roberto Bucher <roberto.bucher@supsi.ch> (upgrade)
|
||||
* 2002-2010 Paolo Mantegazza (mantegazza@aero.polimi.it) (hints/support)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the module to support using COMEDI in hard real time within RTAI.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <rtai_schedcore.h>
|
||||
#include <rtai_sched.h>
|
||||
#include <rtai_lxrt.h>
|
||||
#include <rtai_shm.h>
|
||||
#include <rtai_msg.h>
|
||||
#include <rtai_comedi.h>
|
||||
|
||||
#define MODULE_NAME "rtai_comedi.o"
|
||||
MODULE_DESCRIPTION("RTAI LXRT binding for COMEDI kcomedilib");
|
||||
MODULE_AUTHOR("The Comedi Players");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef CONFIG_RTAI_USE_COMEDI_LOCK
|
||||
|
||||
#define RTAI_COMEDI_LOCK(dev, subdev) \
|
||||
do { comedi_lock(dev, subdev); } while (0)
|
||||
#define RTAI_COMEDI_UNLOCK(dev, subdev) \
|
||||
do { comedi_unlock(dev, subdev); } while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define RTAI_COMEDI_LOCK(dev, subdev) do { } while (0)
|
||||
#define RTAI_COMEDI_UNLOCK(dev, subdev) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define KSPACE(adr) ((unsigned long)adr > PAGE_OFFSET)
|
||||
|
||||
static int rtai_comedi_callback(unsigned int, RT_TASK *) __attribute__ ((__unused__));
|
||||
static int rtai_comedi_callback(unsigned int val, RT_TASK *task)
|
||||
{
|
||||
if (task->magic == RT_TASK_MAGIC) {
|
||||
task->resumsg = val;
|
||||
rt_task_resume(task);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE void *_comedi_open(const char *filename)
|
||||
{
|
||||
return comedi_open(filename);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_close(void *dev)
|
||||
{
|
||||
return comedi_close(dev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_lock(void *dev, unsigned int subdev)
|
||||
{
|
||||
return comedi_lock(dev, subdev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_unlock(void *dev, unsigned int subdev)
|
||||
{
|
||||
return comedi_unlock(dev, subdev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_cancel(void *dev, unsigned int subdev)
|
||||
{
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
return comedi_cancel(dev, subdev);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_comedi_register_callback(void *dev, unsigned int subdev, unsigned int mask, int (*callback)(unsigned int, void *), void *task)
|
||||
{
|
||||
int retval;
|
||||
if (task == NULL) {
|
||||
task = rt_whoami();
|
||||
}
|
||||
((RT_TASK *)task)->resumsg = 0;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_register_callback(dev, subdev, mask, (void *)rtai_comedi_callback, task);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_command(void *dev, comedi_cmd *cmd)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, cmd->subdev);
|
||||
retval = comedi_command(dev, (void *)cmd);
|
||||
RTAI_COMEDI_UNLOCK(dev, cmd->subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_command_test(void *dev, comedi_cmd *cmd)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, cmd->subdev);
|
||||
retval = comedi_command_test(dev, (void *)cmd);
|
||||
RTAI_COMEDI_UNLOCK(dev, cmd->subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int RT_comedi_command(void *dev, struct cmds_ofstlens *ofstlens, long test)
|
||||
{
|
||||
int retval;
|
||||
comedi_cmd cmd[2]; // 2 instances, a safe room for 64 getting into 32
|
||||
memcpy(cmd, (void *)ofstlens + ofstlens->cmd_ofst, ofstlens->cmd_len);
|
||||
cmd[0].chanlist = (void *)ofstlens + ofstlens->chanlist_ofst;
|
||||
cmd[0].chanlist_len = ofstlens->chanlist_len;
|
||||
cmd[0].data = (void *)ofstlens + ofstlens->data_ofst;
|
||||
cmd[0].data_len = ofstlens->data_len;
|
||||
retval = test ? _comedi_command_test(dev, cmd) : _comedi_command(dev, cmd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long rt_comedi_command_data_read(void *dev, unsigned int subdev, long nchans, lsampl_t *data)
|
||||
{
|
||||
void *aibuf;
|
||||
int i, ofsti, ofstf, size;
|
||||
#if 1
|
||||
if (comedi_map(dev, subdev, &aibuf)) {
|
||||
return RTE_OBJINV;
|
||||
}
|
||||
if ((i = comedi_get_buffer_contents(dev, subdev)) < nchans) {
|
||||
return i;
|
||||
}
|
||||
size = comedi_get_buffer_size(dev, subdev);
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
ofstf = ofsti = comedi_get_buffer_offset(dev, subdev);
|
||||
for (i = 0; i < nchans; i++) {
|
||||
data[i] = *(sampl_t *)(aibuf + ofstf % size);
|
||||
ofstf += sizeof(sampl_t);
|
||||
}
|
||||
comedi_mark_buffer_read(dev, subdev, ofstf - ofsti);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
#else
|
||||
comedi_device *cdev = (comedi_device *)dev;
|
||||
comedi_async *async;
|
||||
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
if (subdev >= cdev->n_subdevices) {
|
||||
return RTE_OBJINV;
|
||||
}
|
||||
if ((async = (cdev->subdevices + cdev->n_subdevices)->async) == NULL) {
|
||||
return RTE_OBJINV;
|
||||
}
|
||||
aibuf = (sampl_t *)async->prealloc_buf;
|
||||
if ((i = comedi_buf_read_n_available(async)) < nchans) {
|
||||
return i;
|
||||
}
|
||||
ofstf = ofsti = async->buf_read_ptr;
|
||||
size = async->prealloc_bufsz;
|
||||
for (i = 0; i < nchans; i++) {
|
||||
data[i] = *(sampl_t *)(aibuf + ofstf % size);
|
||||
ofstf += sizeof(sampl_t);
|
||||
}
|
||||
comedi_buf_read_alloc(async, ofstf - ofsti);
|
||||
comedi_buf_read_free(async, ofstf - ofsti);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
#endif
|
||||
return nchans;
|
||||
}
|
||||
|
||||
#define WAIT 0
|
||||
#define WAITIF 1
|
||||
#define WAITUNTIL 2
|
||||
|
||||
static inline int __rt_comedi_command_data_wread(void *dev, unsigned int subdev, long nchans, lsampl_t *data, RTIME until, unsigned int *cbmaskarg, int waitmode)
|
||||
{
|
||||
unsigned int cbmask, mask;
|
||||
long retval, kspace;
|
||||
if ((kspace = KSPACE(cbmaskarg))) {
|
||||
mask = cbmaskarg[0];
|
||||
} else {
|
||||
rt_get_user(mask, cbmaskarg);
|
||||
}
|
||||
switch (waitmode) {
|
||||
case WAIT:
|
||||
retval = rt_comedi_wait(&cbmask);
|
||||
break;
|
||||
case WAITIF:
|
||||
retval = rt_comedi_wait_if(&cbmask);
|
||||
break;
|
||||
case WAITUNTIL:
|
||||
retval = _rt_comedi_wait_until(&cbmask, until);
|
||||
break;
|
||||
default: // useless, just to avoid compiler warnings
|
||||
return RTE_PERM;
|
||||
}
|
||||
if (!retval && (mask & cbmask)) {
|
||||
if (kspace) {
|
||||
cbmaskarg[0] = cbmask;
|
||||
} else {
|
||||
rt_put_user(cbmask, cbmaskarg);
|
||||
}
|
||||
return rt_comedi_command_data_read(dev, subdev, nchans, data);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long rt_comedi_command_data_wread(void *dev, unsigned int subdev, long nchans, lsampl_t *data, unsigned int *cbmask)
|
||||
{
|
||||
return __rt_comedi_command_data_wread(dev, subdev, nchans, data, (RTIME)0, cbmask, WAIT);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long rt_comedi_command_data_wread_if(void *dev, unsigned int subdev, long nchans, lsampl_t *data, unsigned int *cbmask)
|
||||
{
|
||||
return __rt_comedi_command_data_wread(dev, subdev, nchans, data, (RTIME)0, cbmask, WAITIF);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long _rt_comedi_command_data_wread_until(void *dev, unsigned int subdev, long nchans, lsampl_t *data, unsigned int *cbmask, RTIME until)
|
||||
{
|
||||
return __rt_comedi_command_data_wread(dev, subdev, nchans, data, until, cbmask, WAITUNTIL);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long _rt_comedi_command_data_wread_timed(void *dev, unsigned int subdev, long nchans, lsampl_t *data, unsigned int *cbmask, RTIME delay)
|
||||
{
|
||||
return _rt_comedi_command_data_wread_until(dev, subdev, nchans, data, cbmask, rt_get_time() + delay);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long RT_comedi_command_data_wread(void *dev, unsigned int subdev, long nchans, lsampl_t *data, unsigned int *cbmask, unsigned int datalen, RTIME time)
|
||||
{
|
||||
switch (nchans & 0x3) {
|
||||
case 0:
|
||||
return __rt_comedi_command_data_wread(dev, subdev, nchans >> 2, data, (RTIME)0, cbmask, WAIT);
|
||||
case 1:
|
||||
return __rt_comedi_command_data_wread(dev, subdev, nchans >> 2, data, (RTIME)0, cbmask, WAITIF);
|
||||
case 2:
|
||||
return __rt_comedi_command_data_wread(dev, subdev, nchans >> 2, data, time, cbmask, WAITUNTIL);
|
||||
case 3:
|
||||
return _rt_comedi_command_data_wread_until(dev, subdev, nchans >> 2, data, cbmask, rt_get_time() + time);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_data_write(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref, lsampl_t data)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_data_write(dev, subdev, chan, range, aref, data);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_data_read(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref, lsampl_t *data)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_data_read(dev, subdev, chan, range, aref, data);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_data_read_delayed(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref, lsampl_t *data, unsigned int nanosec)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_data_read_delayed(dev, subdev, chan, range, aref, data, nanosec);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_data_read_hint(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_data_read_hint(dev, subdev, chan, range, aref);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan, unsigned int io)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_dio_config(dev, subdev, chan, io);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan, unsigned int *val)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_dio_read(dev, subdev, chan, val);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan, unsigned int val)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_dio_write(dev, subdev, chan, val);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int write_mask, unsigned int *bits)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_dio_bitfield(dev, subdev, write_mask, bits);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_n_subdevices(void *dev)
|
||||
{
|
||||
return comedi_get_n_subdevices(dev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_version_code(void *dev)
|
||||
{
|
||||
return comedi_get_version_code(dev);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE char *rt_comedi_get_driver_name(void *dev, char *name)
|
||||
{
|
||||
const char *kname;
|
||||
if ((kname = comedi_get_driver_name((void *)dev)) != 0) {
|
||||
strncpy(name, kname, COMEDI_NAMELEN);
|
||||
return name;
|
||||
};
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE char *rt_comedi_get_board_name(void *dev, char *name)
|
||||
{
|
||||
const char *kname;
|
||||
if ((kname = comedi_get_board_name((void *)dev)) != 0) {
|
||||
strncpy(name, kname, COMEDI_NAMELEN);
|
||||
return name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_subdevice_type(void *dev, unsigned int subdev)
|
||||
{
|
||||
return comedi_get_subdevice_type(dev, subdev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_find_subdevice_by_type(void *dev, int type, unsigned int start_subdevice)
|
||||
{
|
||||
return comedi_find_subdevice_by_type(dev, type, start_subdevice);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_n_channels(void *dev, unsigned int subdev)
|
||||
{
|
||||
return comedi_get_n_channels(dev, subdev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE lsampl_t _comedi_get_maxdata(void *dev, unsigned int subdev, unsigned int chan)
|
||||
{
|
||||
return comedi_get_maxdata(dev, subdev, chan);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_n_ranges(void *dev, unsigned int subdev, unsigned int chan)
|
||||
{
|
||||
return comedi_get_n_ranges(dev, subdev, chan);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_do_insn(void *dev, comedi_insn *insn)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, insn->subdev);
|
||||
retval = comedi_do_insn(dev, insn);
|
||||
RTAI_COMEDI_UNLOCK(dev, insn->subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_comedi_do_insnlist(void *dev, comedi_insnlist *ilist)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ilist->n_insns; i ++) {
|
||||
if ((ilist->insns[i].n = comedi_do_insn(dev, &ilist->insns[i])) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE int RT_comedi_do_insnlist(void *dev, long n_insns, struct insns_ofstlens *ofstlens)
|
||||
{
|
||||
#define RT_INSN(offset) (*((unsigned int *)(insns + ofstlens->offset)))
|
||||
#define RT_INSN_ADR(offset) ((void *)ofstlens + ofstlens->offset)
|
||||
int i;
|
||||
void *insns = RT_INSN_ADR(insns_ofst);
|
||||
unsigned int *data_ofsts = RT_INSN_ADR(data_ofsts);
|
||||
lsampl_t *data = RT_INSN_ADR(data_ofst);
|
||||
comedi_insn insn[2]; // 2 instances, a safe room for 64 getting into 32
|
||||
for (i = 0; i < n_insns; i ++) {
|
||||
memcpy(insn, insns, ofstlens->insn_len);
|
||||
insn[0].data = data + data_ofsts[i];
|
||||
insn[0].subdev = RT_INSN(subdev_ofst);
|
||||
insn[0].chanspec = RT_INSN(chanspec_ofst);
|
||||
if ((RT_INSN(n_ofst) = comedi_do_insn(dev, insn)) < 0) {
|
||||
break;
|
||||
}
|
||||
insns += ofstlens->insn_len;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline int _rt_comedi_trigger(void *dev, unsigned int subdev)
|
||||
{
|
||||
comedi_insn insn;
|
||||
lsampl_t data = 0;
|
||||
insn.insn = INSN_INTTRIG;
|
||||
insn.subdev = subdev;
|
||||
insn.n = 1;
|
||||
insn.data = &data;
|
||||
return _comedi_do_insn(dev, &insn);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_comedi_trigger(void *dev, unsigned int subdev)
|
||||
{
|
||||
return _rt_comedi_trigger(dev, subdev);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_poll(void *dev, unsigned int subdev)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_poll(dev, subdev);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* DEPRECATED FUNCTION
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_rangetype(unsigned int minor, unsigned int subdevice, unsigned int chan)
|
||||
{
|
||||
return comedi_get_rangetype(minor, subdevice, chan);
|
||||
}
|
||||
*/
|
||||
|
||||
static RTAI_SYSCALL_MODE unsigned int _comedi_get_subdevice_flags(void *dev, unsigned int subdev)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_get_subdevice_flags(dev, subdev);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_krange(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, comedi_krange *krange)
|
||||
{
|
||||
return comedi_get_krange(dev, subdev, chan, range, krange);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_get_buf_head_pos(void * dev, unsigned int subdev)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_get_buf_head_pos(dev, subdev);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_set_user_int_count(void *dev, unsigned int subdev, unsigned int buf_user_count)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_set_user_int_count(dev, subdev, buf_user_count);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_map(void *dev, unsigned int subdev, void *ptr)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_map(dev, subdev, ptr);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int _comedi_unmap(void *dev, unsigned int subdev)
|
||||
{
|
||||
int retval;
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
retval = comedi_unmap(dev, subdev);
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline int __rt_comedi_wait(RTIME until, unsigned int *cbmask, int waitmode)
|
||||
{
|
||||
if (cbmask) {
|
||||
long retval;
|
||||
RT_TASK *task = _rt_whoami();
|
||||
switch (waitmode) {
|
||||
case WAIT:
|
||||
retval = rt_task_suspend(task);
|
||||
break;
|
||||
case WAITIF:
|
||||
retval = rt_task_suspend_if(task);
|
||||
break;
|
||||
case WAITUNTIL:
|
||||
retval = rt_task_suspend_until(task, until);
|
||||
break;
|
||||
default: // useless, just to avoid compiler warnings
|
||||
return RTE_PERM;
|
||||
}
|
||||
if (KSPACE(cbmask)) {
|
||||
cbmask[0] = (unsigned int)task->resumsg;
|
||||
} else {
|
||||
rt_put_user((unsigned int)task->resumsg, cbmask);
|
||||
}
|
||||
task->resumsg = 0;
|
||||
return retval;
|
||||
}
|
||||
return RTE_PERM;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long rt_comedi_wait(unsigned int *cbmask)
|
||||
{
|
||||
return __rt_comedi_wait((RTIME)0, cbmask, WAIT);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long rt_comedi_wait_if(unsigned int *cbmask)
|
||||
{
|
||||
return __rt_comedi_wait((RTIME)0, cbmask, WAITIF);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long _rt_comedi_wait_until(unsigned int *cbmask, RTIME until)
|
||||
{
|
||||
return __rt_comedi_wait(until, cbmask, WAITUNTIL);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long _rt_comedi_wait_timed(unsigned int *cbmask, RTIME delay)
|
||||
{
|
||||
return _rt_comedi_wait_until(cbmask, rt_get_time() + delay);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE long rt_comedi_command_data_write(void *dev, unsigned int subdev, long nchans, lsampl_t *data)
|
||||
{
|
||||
void *aobuf;
|
||||
int i, ofsti, ofstf, size, avbs;
|
||||
if (comedi_map(dev, subdev, &aobuf)) {
|
||||
return RTE_OBJINV;
|
||||
}
|
||||
size = comedi_get_buffer_size(dev, subdev);
|
||||
avbs = comedi_get_buffer_contents(dev, subdev);
|
||||
if ((size - avbs) < nchans) {
|
||||
return (size - avbs);
|
||||
}
|
||||
RTAI_COMEDI_LOCK(dev, subdev);
|
||||
ofstf = ofsti = (comedi_get_buffer_offset(dev, subdev) + avbs) % size;
|
||||
for (i = 0; i < nchans; i++) {
|
||||
*(sampl_t *)(aobuf + ofstf % size) = data[i];
|
||||
ofstf += sizeof(sampl_t);
|
||||
}
|
||||
comedi_mark_buffer_written(dev, subdev, ofstf - ofsti);
|
||||
#if 0
|
||||
if (!avbs) {
|
||||
int retval;
|
||||
if ((retval = _rt_comedi_trigger(dev, subdev)) < 0) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
RTAI_COMEDI_UNLOCK(dev, subdev);
|
||||
return nchans;
|
||||
}
|
||||
|
||||
static struct rt_fun_entry rtai_comedi_fun[] = {
|
||||
[_KCOMEDI_OPEN] = { 0, _comedi_open }
|
||||
,[_KCOMEDI_CLOSE] = { 0, _comedi_close }
|
||||
,[_KCOMEDI_LOCK] = { 0, _comedi_lock }
|
||||
,[_KCOMEDI_UNLOCK] = { 0, _comedi_unlock }
|
||||
,[_KCOMEDI_CANCEL] = { 0, _comedi_cancel }
|
||||
,[_KCOMEDI_REGISTER_CALLBACK] = { 0, rt_comedi_register_callback }
|
||||
,[_KCOMEDI_COMMAND] = { 0, _comedi_command }
|
||||
,[_KCOMEDI_COMMAND_TEST] = { 0, _comedi_command_test }
|
||||
,[_KCOMEDI_TRIGGER ] = { 0, rt_comedi_trigger }
|
||||
,[_KCOMEDI_DATA_WRITE] = { 0, _comedi_data_write}
|
||||
,[_KCOMEDI_DATA_READ] = { 0, _comedi_data_read }
|
||||
,[_KCOMEDI_DATA_READ_DELAYED] = { 0, _comedi_data_read_delayed }
|
||||
,[_KCOMEDI_DATA_READ_HINT] = { 0, _comedi_data_read_hint }
|
||||
,[_KCOMEDI_DIO_CONFIG] = { 0, _comedi_dio_config }
|
||||
,[_KCOMEDI_DIO_READ] = { 0, _comedi_dio_read }
|
||||
,[_KCOMEDI_DIO_WRITE] = { 0, _comedi_dio_write }
|
||||
,[_KCOMEDI_DIO_BITFIELD] = { 0, _comedi_dio_bitfield }
|
||||
,[_KCOMEDI_GET_N_SUBDEVICES] = { 0, _comedi_get_n_subdevices }
|
||||
,[_KCOMEDI_GET_VERSION_CODE] = { 0, _comedi_get_version_code }
|
||||
,[_KCOMEDI_GET_DRIVER_NAME] = { 0, rt_comedi_get_driver_name }
|
||||
,[_KCOMEDI_GET_BOARD_NAME] = { 0, rt_comedi_get_board_name }
|
||||
,[_KCOMEDI_GET_SUBDEVICE_TYPE] = { 0, _comedi_get_subdevice_type }
|
||||
,[_KCOMEDI_FIND_SUBDEVICE_TYPE] = { 0, _comedi_find_subdevice_by_type }
|
||||
,[_KCOMEDI_GET_N_CHANNELS] = { 0, _comedi_get_n_channels }
|
||||
,[_KCOMEDI_GET_MAXDATA] = { 0, _comedi_get_maxdata }
|
||||
,[_KCOMEDI_GET_N_RANGES] = { 0, _comedi_get_n_ranges }
|
||||
,[_KCOMEDI_DO_INSN] = { 0, _comedi_do_insn }
|
||||
,[_KCOMEDI_DO_INSN_LIST] = { 0, rt_comedi_do_insnlist }
|
||||
,[_KCOMEDI_POLL] = { 0, _comedi_poll }
|
||||
/*
|
||||
,[_KCOMEDI_GET_RANGETYPE] = { 0, _comedi_get_rangetype }
|
||||
*/
|
||||
,[_KCOMEDI_GET_SUBDEVICE_FLAGS] = { 0, _comedi_get_subdevice_flags }
|
||||
,[_KCOMEDI_GET_KRANGE] = { 0, _comedi_get_krange }
|
||||
,[_KCOMEDI_GET_BUF_HEAD_POS] = { 0, _comedi_get_buf_head_pos }
|
||||
,[_KCOMEDI_SET_USER_INT_COUNT] = { 0, _comedi_set_user_int_count }
|
||||
,[_KCOMEDI_MAP] = { 0, _comedi_map }
|
||||
,[_KCOMEDI_UNMAP] = { 0, _comedi_unmap }
|
||||
,[_KCOMEDI_WAIT] = { 1, rt_comedi_wait }
|
||||
,[_KCOMEDI_WAIT_IF] = { 0, rt_comedi_wait_if }
|
||||
,[_KCOMEDI_WAIT_UNTIL] = { 1, _rt_comedi_wait_until }
|
||||
,[_KCOMEDI_WAIT_TIMED] = { 1, _rt_comedi_wait_timed }
|
||||
,[_KCOMEDI_COMD_DATA_READ] = { 0, rt_comedi_command_data_read }
|
||||
,[_KCOMEDI_COMD_DATA_WREAD] = { 1, rt_comedi_command_data_wread }
|
||||
,[_KCOMEDI_COMD_DATA_WREAD_IF] = { 0, rt_comedi_command_data_wread_if }
|
||||
,[_KCOMEDI_COMD_DATA_WREAD_UNTIL] = { 1, _rt_comedi_command_data_wread_until }
|
||||
,[_KCOMEDI_COMD_DATA_WREAD_TIMED] = { 1, _rt_comedi_command_data_wread_timed }
|
||||
,[_KCOMEDI_COMD_DATA_WRITE] = { 0, rt_comedi_command_data_write }
|
||||
,[_RT_KCOMEDI_COMMAND] = { 0, RT_comedi_command }
|
||||
,[_RT_KCOMEDI_DO_INSN_LIST] = { 0, RT_comedi_do_insnlist }
|
||||
,[_RT_KCOMEDI_COMD_DATA_WREAD] = { 0, RT_comedi_command_data_wread }
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RTAI_USE_LINUX_COMEDI
|
||||
|
||||
extern void *rt_comedi_request_irq;
|
||||
extern void *rt_comedi_release_irq;
|
||||
extern void *rt_comedi_busy_sleep;
|
||||
|
||||
#define RTAI_NR_IRQS IPIPE_NR_XIRQS
|
||||
static int (*comedi_irq_handler_p[RTAI_NR_IRQS])(unsigned int, void *);
|
||||
|
||||
static int comedi_irq_handler(unsigned int irq, void *dev_id)
|
||||
{
|
||||
comedi_irq_handler_p[irq](irq, dev_id);
|
||||
rt_enable_irq(irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int comedi_request_irq(unsigned int irq, int (*handler)(unsigned int irq, void *dev_id), unsigned long flags, const char *name, void *dev)
|
||||
{
|
||||
int retval;
|
||||
if (comedi_irq_handler_p[irq]) {
|
||||
return -EBUSY;
|
||||
}
|
||||
if ((retval = rt_request_irq(irq, comedi_irq_handler, dev, 0))) {
|
||||
return retval;
|
||||
}
|
||||
comedi_irq_handler_p[irq] = handler;
|
||||
rt_startup_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void comedi_release_irq(unsigned int irq, void *dev)
|
||||
{
|
||||
rt_shutdown_irq(irq);
|
||||
rt_release_irq(irq);
|
||||
}
|
||||
|
||||
static int us2tsc;
|
||||
void comedi_busy_sleep(int us)
|
||||
{
|
||||
RTIME break_time;
|
||||
break_time = rtai_rdtsc() + us*us2tsc;
|
||||
while (rtai_rdtsc() < break_time);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RTAI_USE_LINUX_COMEDI) */
|
||||
|
||||
int __rtai_comedi_init(void)
|
||||
{
|
||||
if( set_rt_fun_ext_index(rtai_comedi_fun, FUN_COMEDI_LXRT_INDX) ) {
|
||||
printk("Recompile your module with a different index\n");
|
||||
return -EACCES;
|
||||
}
|
||||
#ifdef CONFIG_RTAI_USE_LINUX_COMEDI
|
||||
us2tsc = tuned.cpu_freq/1000000;
|
||||
rt_comedi_request_irq = comedi_request_irq;
|
||||
rt_comedi_release_irq = comedi_release_irq;
|
||||
rt_comedi_busy_sleep = comedi_busy_sleep;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __rtai_comedi_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_RTAI_USE_LINUX_COMEDI
|
||||
int irq;
|
||||
for (irq = 0; irq < RTAI_NR_IRQS; irq++) {
|
||||
if (comedi_irq_handler_p[irq]) {
|
||||
comedi_release_irq(irq, NULL);
|
||||
}
|
||||
}
|
||||
rt_comedi_request_irq = rt_request_irq;
|
||||
rt_comedi_release_irq = rt_release_irq;
|
||||
rt_comedi_busy_sleep = __udelay;
|
||||
#endif
|
||||
reset_rt_fun_ext_index(rtai_comedi_fun, FUN_COMEDI_LXRT_INDX);
|
||||
}
|
||||
|
||||
module_init(__rtai_comedi_init);
|
||||
module_exit(__rtai_comedi_exit);
|
||||
|
||||
EXPORT_SYMBOL(rt_comedi_wait);
|
||||
EXPORT_SYMBOL(rt_comedi_wait_if);
|
||||
EXPORT_SYMBOL(_rt_comedi_wait_until);
|
||||
EXPORT_SYMBOL(_rt_comedi_wait_timed);
|
||||
EXPORT_SYMBOL(rt_comedi_get_driver_name);
|
||||
EXPORT_SYMBOL(rt_comedi_get_board_name);
|
||||
EXPORT_SYMBOL(rt_comedi_register_callback);
|
||||
EXPORT_SYMBOL(rt_comedi_command_data_read);
|
||||
EXPORT_SYMBOL(rt_comedi_command_data_wread);
|
||||
EXPORT_SYMBOL(rt_comedi_command_data_wread_if);
|
||||
EXPORT_SYMBOL(_rt_comedi_command_data_wread_until);
|
||||
EXPORT_SYMBOL(_rt_comedi_command_data_wread_timed);
|
||||
EXPORT_SYMBOL(rt_comedi_do_insnlist);
|
||||
EXPORT_SYMBOL(rt_comedi_trigger);
|
||||
EXPORT_SYMBOL(rt_comedi_command_data_write);
|
||||
28
addons/comedi/kcomedi.c
Normal file
28
addons/comedi/kcomedi.c
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Thomas Leibner (leibner@t-online.de) (first complete writeup)
|
||||
* 2002 David Schleef (ds@schleef.org) (COMEDI master)
|
||||
* 2002 Lorenzo Dozio (dozio@aero.polimi.it) (made it all work)
|
||||
* 2002 Paolo Mantegazza (mantegazza@aero.polimi.it) (hints/support)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is the non-inline KComedilib-LXRT userspace lib.
|
||||
* It will be compiled into a libkcomedilxrt.a library with which
|
||||
* your application can link if it included the rtai_comedi.h file.
|
||||
*/
|
||||
|
||||
#include <rtai_comedi.h>
|
||||
117
addons/comedi/patchlinuxcomedi
Normal file
117
addons/comedi/patchlinuxcomedi
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
#
|
||||
# Copyright (C) 2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
||||
# USA; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
# WHAT TO DO:
|
||||
# See "WHAT TO DO" in README in this directory.
|
||||
# END OF WHAT TO DO.
|
||||
#
|
||||
# >>> Save original comedi dir
|
||||
#
|
||||
if test -d ../comedi.orig; then
|
||||
echo "*** comedi.orig exists, no copy made ***"
|
||||
else
|
||||
cp -r ../comedi ../comedi.orig
|
||||
fi
|
||||
#
|
||||
# >>> Set generic calls in comedi.
|
||||
#
|
||||
for i in `find . -name "*.c"`; do cat $i | sed s/request_irq/comedi_request_irq/g | sed s/free_irq/comedi_free_irq/g | sed s/udelay/comedi_udelay/g | sed s/spin_lock_irqsave/comedi_spin_lock_irqsave/g | sed s/spin_unlock_irqrestore/comedi_spin_unlock_irqrestore/g > newcopy; mv newcopy $i; done
|
||||
#
|
||||
# >>> Create comedi_system.h by cleaning this script part, care of not inserting
|
||||
# >>> blank lines but the one that separates this script from comedi_system.h
|
||||
# >>> body.
|
||||
#
|
||||
cat $0 | sed '1,/^$/ d' > comedi_system.h
|
||||
#
|
||||
# >>> Add an include for comedi_system.h in comedidev.h, to be seen everywhere.
|
||||
#
|
||||
cat comedidev.h | sed '/comedi.h/ i\#include "comedi_system.h"' > newcopy
|
||||
mv newcopy comedidev.h
|
||||
#
|
||||
# >>> Append and export pointers for dynamically linking rtai_comedi extensions.
|
||||
#
|
||||
echo "" >>comedi_ksyms.c
|
||||
echo "int (*rt_comedi_request_irq)(unsigned int, irq_handler_t, unsigned long, const char *, void *) = request_irq;" >>comedi_ksyms.c
|
||||
echo "void (*rt_comedi_release_irq)(unsigned int, void *) = free_irq;" >>comedi_ksyms.c
|
||||
echo "void (*rt_comedi_busy_sleep)(unsigned long) = __udelay;" >>comedi_ksyms.c
|
||||
echo "" >>comedi_ksyms.c
|
||||
echo "EXPORT_SYMBOL(rt_comedi_request_irq);" >>comedi_ksyms.c
|
||||
echo "EXPORT_SYMBOL(rt_comedi_release_irq);" >>comedi_ksyms.c
|
||||
echo "EXPORT_SYMBOL(rt_comedi_busy_sleep);" >>comedi_ksyms.c
|
||||
#
|
||||
# >>> Simulate a comedi.org distribution, to cheat RTAI configure for a while.
|
||||
#
|
||||
mkdir include
|
||||
mkdir include/linux
|
||||
cp comedi.h include/linux
|
||||
cp comedilib.h include/linux
|
||||
exit
|
||||
|
||||
#ifndef _COMEDI_SYSTEM_H_
|
||||
#define _COMEDI_SYSTEM_H_
|
||||
|
||||
#ifdef CONFIG_IPIPE
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
extern int (*rt_comedi_request_irq)(unsigned int, irq_handler_t, unsigned long, const char *, void *);
|
||||
extern void (*rt_comedi_release_irq)(unsigned int, void *);
|
||||
extern void (*rt_comedi_busy_sleep)(unsigned long);
|
||||
|
||||
#define comedi_request_irq(irq, handler, flags, name, dev) \
|
||||
({ rt_comedi_request_irq(irq, (void *)handler, flags, name, dev); })
|
||||
|
||||
#define comedi_free_irq(irq, dev) \
|
||||
rt_comedi_release_irq(irq, dev)
|
||||
|
||||
#define comedi_udelay(usec) \
|
||||
rt_comedi_busy_sleep(usec)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
|
||||
#define COMEDI_SPIN_LOCKP(lock_ptr) lock_ptr
|
||||
#else
|
||||
#define COMEDI_SPIN_LOCKP(lock_ptr) ((raw_spinlock_t *)lock_ptr)
|
||||
#endif
|
||||
#define comedi_spin_lock_irqsave(lock_ptr, flags) \
|
||||
({ local_irq_save_hw(flags); _raw_spin_lock(COMEDI_SPIN_LOCKP(lock_ptr)); flags; })
|
||||
|
||||
#define comedi_spin_unlock_irqrestore(lock_ptr, flags) \
|
||||
do { _raw_spin_unlock(COMEDI_SPIN_LOCKP(lock_ptr)); local_irq_restore_hw(flags); } while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define comedi_request_irq(irq, handler, flags, device, dev_id) \
|
||||
request_irq(irq, handler, flags, device, dev_id)
|
||||
|
||||
#define comedi_free_irq(irq, dev_id) \
|
||||
free_irq(irq, dev_id)
|
||||
|
||||
#define comedi_udelay(usec) \
|
||||
udelay(usec)
|
||||
|
||||
#define comedi_spin_lock_irqsave(lock_ptr, flags) \
|
||||
({ spin_lock_irqsave(lock_ptr, flags); flags; })
|
||||
|
||||
#define comedi_spin_unlock_irqrestore(lock_ptr, flags) \
|
||||
spin_unlock_irqrestore(lock_ptr, flags)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _COMEDI_SYSTEM_H_ */
|
||||
1036
addons/comedi/rtai_comedi.h
Normal file
1036
addons/comedi/rtai_comedi.h
Normal file
File diff suppressed because it is too large
Load diff
227
addons/cpp/GNUmakefile.am
Normal file
227
addons/cpp/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
moduledir = @RTAI_MODULE_DIR@
|
||||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
CROSS_COMPILE = @CROSS_COMPILE@
|
||||
|
||||
include_HEADERS = rtai_cpp.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
bits.h \
|
||||
cond.h \
|
||||
count.h \
|
||||
iostream.h \
|
||||
linux_wrapper.h \
|
||||
mbx.h \
|
||||
module.h \
|
||||
mutex.h \
|
||||
new.h \
|
||||
rtai_wrapper.h \
|
||||
rtai_pqueue_wrapper.h \
|
||||
rtai_pthread_int_wrapper.h \
|
||||
rtai_pthread_wrapper.h \
|
||||
tld_key.h \
|
||||
rtf.h \
|
||||
sem.h \
|
||||
task.h \
|
||||
tbx.h \
|
||||
time.h \
|
||||
trace.h \
|
||||
watchdog.h
|
||||
|
||||
libcpp_a_SOURCES = \
|
||||
builtin.c \
|
||||
cs.cc \
|
||||
cond.cc \
|
||||
count.cc \
|
||||
init.c \
|
||||
iostream.cc \
|
||||
mbx.cc \
|
||||
module.cc \
|
||||
mutex.cc \
|
||||
sem.cc \
|
||||
task.cc \
|
||||
time.cc \
|
||||
tld_key.c \
|
||||
rtai_wrapper.c
|
||||
|
||||
if CONFIG_RTAI_TRACE
|
||||
libcpp_a_SOURCES += trace.cc
|
||||
endif
|
||||
|
||||
libcpp_bits_a_SOURCES = \
|
||||
bits.cc \
|
||||
bits_init.c \
|
||||
linux_wrapper.c
|
||||
|
||||
libcpp_rtf_a_SOURCES = \
|
||||
rtf.cc \
|
||||
rtf_init.c \
|
||||
linux_wrapper.c
|
||||
|
||||
libcpp_tbx_a_SOURCES = \
|
||||
tbx.cc \
|
||||
tbx_init.c \
|
||||
linux_wrapper.c
|
||||
|
||||
libcpp_wd_a_SOURCES = \
|
||||
watchdog_init.c \
|
||||
watchdog.cc \
|
||||
linux_wrapper.c
|
||||
|
||||
crt_files = \
|
||||
crtbegin.c \
|
||||
crtend.c \
|
||||
crtmbegin.c \
|
||||
crtmend.c \
|
||||
crtsbegin.c \
|
||||
crtsend.c
|
||||
|
||||
crtobjs = $(crt_files:%.c=%.o)
|
||||
|
||||
if CONFIG_KBUILD
|
||||
modules = rtai_cpp.ko rtai_cpp_rtf.ko rtai_cpp_tbx.ko rtai_cpp_wd.ko
|
||||
|
||||
rtai_cpp.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_cpp.ko: $(libcpp_a_SOURCES) $(noinst_HEADERS)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
rtai_cpp_bits.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_cpp_bits.ko: $(libcpp_bits_a_SOURCES) $(noinst_HEADERS)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
rtai_cpp_rtf.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_cpp_rtf.ko: $(libcpp_rtf_a_SOURCES) $(noinst_HEADERS)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
rtai_cpp_tbx.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_cpp_tbx.ko: $(libcpp_tbx_a_SOURCES) $(noinst_HEADERS)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
rtai_cpp_wd.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_cpp_wd.ko: $(libcpp_wd_a_SOURCES) $(noinst_HEADERS)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
clean-local:
|
||||
@RTAI_KBUILD_CLEAN@
|
||||
else
|
||||
noinst_LIBRARIES = \
|
||||
libcpp.a \
|
||||
libcpp_bits.a \
|
||||
libcpp_rtf.a \
|
||||
libcpp_tbx.a \
|
||||
libcpp_wd.a
|
||||
|
||||
modules = $(foreach lib,$(noinst_LIBRARIES),$(patsubst lib%.a,rtai_%.o,$(lib)))
|
||||
|
||||
libcpp_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
libcpp_a_CFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_a_CXXFLAGS = \
|
||||
@RTAI_KMOD_CXXFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_bits_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
libcpp_bits_a_CFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_bits_a_CXXFLAGS = \
|
||||
@RTAI_KMOD_CXXFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_rtf_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
libcpp_rtf_a_CFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_rtf_a_CXXFLAGS = \
|
||||
@RTAI_KMOD_CXXFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_tbx_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
libcpp_tbx_a_CFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_tbx_a_CXXFLAGS = \
|
||||
@RTAI_KMOD_CXXFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_wd_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
libcpp_wd_a_CFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
libcpp_wd_a_CXXFLAGS = \
|
||||
@RTAI_KMOD_CXXFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
CRTFLAGS = \
|
||||
-I../.. \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../base/include
|
||||
|
||||
crtsbegin.o : $(srcdir)/crt.c
|
||||
$(CC) $(CRTFLAGS) -DCRT_BEGIN -DNO_MOD_INIT -c $< -o $@
|
||||
|
||||
crtsend.o : $(srcdir)/crt.c
|
||||
$(CC) $(CRTFLAGS) -DCRT_END -DNO_MOD_INIT -c $< -o $@
|
||||
|
||||
crtbegin.o : $(srcdir)/crt.c
|
||||
$(CC) $(CRTFLAGS) -DCRT_BEGIN -c $< -o $@
|
||||
|
||||
crtend.o : $(srcdir)/crt.c
|
||||
$(CC) $(CRTFLAGS) -DCRT_END -c $< -o $@
|
||||
|
||||
crtmbegin.o : $(srcdir)/crt.c
|
||||
$(CC) $(CRTFLAGS) -DCRT_BEGIN -DUSE_MAIN -c $< -o $@
|
||||
|
||||
crtmend.o : $(srcdir)/crt.c
|
||||
$(CC) $(CRTFLAGS) -DCRT_END -DUSE_MAIN -c $< -o $@
|
||||
|
||||
rtai_%.o: lib%.a
|
||||
$(CROSS_COMPILE)$(LD) --whole-archive $< -r -o $@
|
||||
endif
|
||||
|
||||
all-local: $(modules) $(crtobjs)
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
$(mkinstalldirs) $(top_srcdir)/modules
|
||||
$(INSTALL_DATA) $^ $(top_srcdir)/modules
|
||||
endif
|
||||
|
||||
install-exec-local: $(modules) $(crtobjs)
|
||||
$(mkinstalldirs) $(DESTDIR)$(moduledir)
|
||||
$(INSTALL_DATA) $(modules) $(DESTDIR)$(moduledir)
|
||||
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||
$(INSTALL_DATA) $(crtobjs) $(DESTDIR)$(libdir)
|
||||
|
||||
EXTRA_DIST = crt.c
|
||||
92
addons/cpp/bits.cc
Normal file
92
addons/cpp/bits.cc
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: bits.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "bits.h"
|
||||
#include "rtai.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Bits::Bits(){
|
||||
rt_printk("Bits::Bits( ) %p\n",this);
|
||||
m_Bits = 0;
|
||||
}
|
||||
|
||||
Bits::Bits( unsigned long mask )
|
||||
{
|
||||
rt_printk("Bits::Bits( unsigned long mask=%lu) %p\n",mask,this);
|
||||
m_Bits = 0;
|
||||
init( mask );
|
||||
}
|
||||
|
||||
Bits::~Bits()
|
||||
{
|
||||
if( m_Bits != 0 )
|
||||
rt_bits_delete( m_Bits );
|
||||
}
|
||||
|
||||
void Bits::init(unsigned long mask)
|
||||
{
|
||||
rt_bits_init(m_Bits, mask );
|
||||
}
|
||||
|
||||
unsigned long Bits::get_bits(){
|
||||
return rt_get_bits( m_Bits );
|
||||
}
|
||||
|
||||
int Bits::reset( unsigned long mask )
|
||||
{
|
||||
return rt_bits_reset( m_Bits, mask );
|
||||
}
|
||||
|
||||
unsigned long Bits::signal( Function setfun, unsigned long masks )
|
||||
{
|
||||
return rt_bits_signal( m_Bits, setfun, masks );
|
||||
}
|
||||
|
||||
int Bits::wait(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks,
|
||||
unsigned long *resulting_mask )
|
||||
{
|
||||
return rt_bits_wait( m_Bits, testfun, testmasks, exitfun, exitmasks, resulting_mask );
|
||||
}
|
||||
|
||||
int Bits::wait_if(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks,
|
||||
unsigned long *resulting_mask )
|
||||
{
|
||||
return rt_bits_wait_if( m_Bits, testfun, testmasks, exitfun, exitmasks, resulting_mask );
|
||||
}
|
||||
|
||||
int Bits::wait_until(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks, const Count& time,
|
||||
unsigned long *resulting_mask )
|
||||
{
|
||||
return rt_bits_wait_until( m_Bits, testfun, testmasks, exitfun, exitmasks, time, resulting_mask );
|
||||
}
|
||||
|
||||
int Bits::wait_timed(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks, const Count& delay,
|
||||
unsigned long *resulting_mask )
|
||||
{
|
||||
return rt_bits_wait_timed( m_Bits, testfun, testmasks, exitfun, exitmasks, delay , resulting_mask );
|
||||
}
|
||||
|
||||
};
|
||||
154
addons/cpp/bits.h
Normal file
154
addons/cpp/bits.h
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: bits.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BITS_H__
|
||||
#define __BITS_H__
|
||||
|
||||
#include "count.h"
|
||||
#include "rtai_bits.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Bits a wrapper class around the RTAI BITS
|
||||
*/
|
||||
class Bits
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Function types used by Bits
|
||||
*/
|
||||
enum Function {
|
||||
all_set = ALL_SET, ///< all set
|
||||
any_set = ANY_SET, ///< any set
|
||||
all_clr = ALL_CLR, ///< all clear
|
||||
any_clr = ANY_CLR, ///< any clear
|
||||
|
||||
all_set_and_any_set = ALL_SET_AND_ANY_SET, ///< all set and any clear
|
||||
all_set_and_all_clr = ALL_SET_AND_ALL_CLR, ///< all set and all clear
|
||||
all_set_and_any_clr = ALL_SET_AND_ANY_CLR, ///< all set and any clear
|
||||
any_set_and_all_clr = ANY_SET_AND_ALL_CLR, ///< any set and all clear
|
||||
any_set_and_any_clr = ANY_SET_AND_ANY_CLR, ///< any set and any clear
|
||||
all_clr_and_any_clr = ALL_CLR_AND_ANY_CLR, ///< all clear and any clear
|
||||
|
||||
all_set_or_any_set = ALL_SET_OR_ANY_SET, ///< all set or any clear
|
||||
all_set_or_all_clr = ALL_SET_OR_ALL_CLR, ///< all set or all clear
|
||||
all_set_or_any_clr = ALL_SET_OR_ANY_CLR, ///< all set or any clear
|
||||
any_set_or_all_clr = ANY_SET_OR_ALL_CLR, ///< all set or all clear
|
||||
any_set_or_any_clr = ANY_SET_OR_ANY_CLR, ///< any set or any clear
|
||||
all_clr_or_any_clr = ALL_CLR_OR_ANY_CLR, ///< all clear or any clear
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* Default Constructor.
|
||||
* when using the default constructor one has to call
|
||||
* the init methode by hand before the object can be used.
|
||||
*/
|
||||
Bits();
|
||||
/**
|
||||
*Contructor
|
||||
*@param mask The masked
|
||||
* This constructor will automaticly call init
|
||||
*/
|
||||
Bits( unsigned long mask );
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Bits();
|
||||
|
||||
/**
|
||||
* init will initialize the under laying BITS
|
||||
* @param mask The mask
|
||||
*/
|
||||
void init(unsigned long mask);
|
||||
/**
|
||||
* Get the current status of the bits
|
||||
* @return The 32 bits
|
||||
*/
|
||||
unsigned long get_bits();
|
||||
/**
|
||||
* Reset the bits
|
||||
* @param mask the mask
|
||||
* @return ?
|
||||
*/
|
||||
int reset( unsigned long mask );
|
||||
/**
|
||||
* Signal the bits
|
||||
* @param setfun The set function
|
||||
* @param masks the mask
|
||||
* @return ?
|
||||
*/
|
||||
unsigned long signal( Function setfun, unsigned long masks );
|
||||
/**
|
||||
* Wait for a change
|
||||
* @param testfun ?
|
||||
* @param testmasks ?
|
||||
* @param exitfun ?
|
||||
* @param exitmask ?
|
||||
* @return ?
|
||||
*/
|
||||
int wait(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks,
|
||||
unsigned long *resulting_mask );
|
||||
/**
|
||||
* Wait for a change
|
||||
* @param testfun ?
|
||||
* @param testmasks ?
|
||||
* @param exitfun ?
|
||||
* @param exitmasks
|
||||
* @return ?
|
||||
*/
|
||||
int wait_if(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks,
|
||||
unsigned long *resulting_mask );
|
||||
/**
|
||||
* Wait for a change
|
||||
* @param testfun ?
|
||||
* @param testmasks ?
|
||||
* @param exitfun ?
|
||||
* @param exitmasks
|
||||
* @return ?
|
||||
*/
|
||||
int wait_until(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks, const Count& time,
|
||||
unsigned long *resulting_mask );
|
||||
/**
|
||||
* Wait for a change
|
||||
* @param testfun ?
|
||||
* @param testmasks ?
|
||||
* @param exitfun ?
|
||||
* @param exitmasks
|
||||
* @return ?
|
||||
*/
|
||||
int wait_timed(Function testfun, unsigned long testmasks,
|
||||
Function exitfun, unsigned long exitmasks, const Count& delay,
|
||||
unsigned long *resulting_mask);
|
||||
protected:
|
||||
BITS* m_Bits;
|
||||
private:
|
||||
Bits(const Bits&);
|
||||
Bits& operator=(const Bits&);
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
77
addons/cpp/bits_init.c
Normal file
77
addons/cpp/bits_init.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: bits_init.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <rtai_sched.h>
|
||||
#include <rtai_bits.h>
|
||||
#include <rtai_malloc.h>
|
||||
|
||||
// RTAI-- MODULE INIT and CLEANUP functions
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("the RTAI-Team (contact person Erwin Rol)");
|
||||
MODULE_DESCRIPTION("RTAI C++ BITS support");
|
||||
|
||||
BITS* __rt_bits_init(unsigned long mask){
|
||||
BITS * bits;
|
||||
|
||||
bits = rt_malloc(sizeof(BITS));
|
||||
|
||||
if(bits == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
memset(bits,0,sizeof(BITS));
|
||||
|
||||
rt_bits_init(bits,mask);
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
int __rt_bits_delete(BITS *bits){
|
||||
int result;
|
||||
|
||||
if(bits == 0)
|
||||
return -1;
|
||||
|
||||
result = rt_bits_delete(bits);
|
||||
|
||||
rt_free(bits);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int __init rtai_cpp_bits_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtai_cpp_bits_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(rtai_cpp_bits_init)
|
||||
module_exit(rtai_cpp_bits_cleanup)
|
||||
|
||||
162
addons/cpp/builtin.c
Normal file
162
addons/cpp/builtin.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: builtin.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <rtai_sched.h>
|
||||
#include <rtai_malloc.h>
|
||||
|
||||
#if __GNUC__ < 3
|
||||
|
||||
void
|
||||
__builtin_delete(void* vp){
|
||||
rt_printk("__builtin_delete %p\n",vp);
|
||||
if(vp != 0)
|
||||
rt_free(vp);
|
||||
}
|
||||
|
||||
void*
|
||||
__builtin_new(int size){
|
||||
void* vp = rt_malloc(size);
|
||||
rt_printk("__builtin_new %p %d\n",vp,size);
|
||||
return vp;
|
||||
}
|
||||
|
||||
void
|
||||
__builtin_vec_delete(void* vp){
|
||||
rt_printk("__builtin_vec_delete %p\n",vp);
|
||||
if(vp != 0)
|
||||
rt_free(vp);
|
||||
}
|
||||
|
||||
void*
|
||||
__builtin_vec_new(int size){
|
||||
void* vp = rt_malloc(size);
|
||||
rt_printk("__builtin_vec_new %p %d\n",vp,size);
|
||||
return vp;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern void __default_terminate (void) __attribute__ ((__noreturn__));
|
||||
|
||||
void
|
||||
__default_terminate(void)
|
||||
{
|
||||
while(1)
|
||||
rt_task_suspend(rt_whoami());
|
||||
}
|
||||
|
||||
void (*__terminate_func)(void) = __default_terminate;
|
||||
|
||||
void
|
||||
__terminate(void)
|
||||
{
|
||||
(*__terminate_func)();
|
||||
}
|
||||
|
||||
void
|
||||
__pure_virtual(void)
|
||||
{
|
||||
rt_printk("pure virtual method called\n");
|
||||
__terminate ();
|
||||
}
|
||||
/* Declare a pointer to void function type. */
|
||||
|
||||
typedef void (*func_ptr) (void);
|
||||
|
||||
static func_ptr* atexit_function_tab;
|
||||
static int atexit_function_tab_size;
|
||||
static int atexit_function_tab_len;
|
||||
|
||||
int atexit( func_ptr function )
|
||||
{
|
||||
rt_printk("atexit %p\n",function);
|
||||
// we check if the pointer is NULL, this
|
||||
// can happen when a second C++ modules is loaded
|
||||
// and than unloaded. At unload time the second module
|
||||
// will call the atexit handlers and delete
|
||||
// the function table
|
||||
if( atexit_function_tab == 0 ){
|
||||
rt_printk("atexit_function_tab == NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( atexit_function_tab_len >= atexit_function_tab_size)
|
||||
return -1;
|
||||
|
||||
if( function == 0 )
|
||||
return -1;
|
||||
|
||||
atexit_function_tab[ atexit_function_tab_len++ ] = function;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __do_atexit( void )
|
||||
{
|
||||
func_ptr *p = atexit_function_tab;
|
||||
|
||||
rt_printk("__do_atexit START\n");
|
||||
|
||||
// we check if the pointer is NULL, this
|
||||
// can happen when a second C++ modules is loaded
|
||||
// and than unloaded. At unload time the second module
|
||||
// will call the atexit handlers and delete
|
||||
// the function table
|
||||
if( atexit_function_tab == 0 ){
|
||||
rt_printk("atexit_function_tab == NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while(*p)
|
||||
{
|
||||
rt_printk("calling atexit function %p\n",p );
|
||||
(*(p))();
|
||||
p++;
|
||||
if( atexit_function_tab_len-- )
|
||||
break;
|
||||
}
|
||||
|
||||
vfree( atexit_function_tab );
|
||||
|
||||
atexit_function_tab_size = 0;
|
||||
atexit_function_tab_len = 0;
|
||||
atexit_function_tab = 0;
|
||||
|
||||
rt_printk("__do_atexit END\n");
|
||||
}
|
||||
void __init_atexit( int max_size )
|
||||
{
|
||||
// we check if the pointer is NULL, this
|
||||
// can happen when a second C++ modules is loaded
|
||||
// and than unloaded. At unload time the second module
|
||||
// will call the atexit handlers and delete
|
||||
// the function table
|
||||
if( atexit_function_tab != 0 ){
|
||||
rt_printk("__init_atexit atexit_function_tab != NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
atexit_function_tab_size = max_size;
|
||||
atexit_function_tab_len = 0;
|
||||
atexit_function_tab = vmalloc( sizeof(func_ptr) * atexit_function_tab_size);
|
||||
memset( atexit_function_tab , 0 , sizeof(func_ptr) * atexit_function_tab_size );
|
||||
}
|
||||
51
addons/cpp/cond.cc
Normal file
51
addons/cpp/cond.cc
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: cond.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "cond.h"
|
||||
#include "mutex.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Condition::Condition()
|
||||
: Semaphore(0, BIN_SEM)
|
||||
{
|
||||
}
|
||||
|
||||
Condition::~Condition(){
|
||||
}
|
||||
|
||||
int Condition::wait( Mutex& mtx )
|
||||
{
|
||||
return rt_cond_wait( m_Sem, mtx.m_Sem );
|
||||
}
|
||||
|
||||
int Condition::wait_until( Mutex& mtx,const Count& time)
|
||||
{
|
||||
return rt_cond_wait_until( m_Sem, mtx.m_Sem, time );
|
||||
}
|
||||
|
||||
int Condition::wait_timed( Mutex& mtx, const Count& delay)
|
||||
{
|
||||
return rt_cond_wait_timed( m_Sem, mtx.m_Sem, delay );
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
52
addons/cpp/cond.h
Normal file
52
addons/cpp/cond.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: cond.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "rtai.h"
|
||||
#include "count.h"
|
||||
#include "sem.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#ifndef __COND_H__
|
||||
#define __COND_H__
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Condition Variable
|
||||
*/
|
||||
class Condition
|
||||
: public Semaphore
|
||||
{
|
||||
public:
|
||||
Condition();
|
||||
~Condition();
|
||||
int wait( Mutex& mtx );
|
||||
int wait_until( Mutex& mtx, const Count& time);
|
||||
int wait_timed( Mutex& mtx, const Count& delay);
|
||||
private:
|
||||
Condition(const Condition&);
|
||||
Condition& operator=(const Condition&);
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
140
addons/cpp/count.cc
Normal file
140
addons/cpp/count.cc
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: count.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "count.h"
|
||||
#include "rtai_sched.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Count::Count(){
|
||||
m_Count = 0;
|
||||
}
|
||||
|
||||
Count::Count(const Count& count)
|
||||
: m_Count(count.m_Count)
|
||||
{
|
||||
}
|
||||
|
||||
Count::Count(long long count)
|
||||
: m_Count(count)
|
||||
{
|
||||
}
|
||||
|
||||
Count& Count::operator=(const Count& count)
|
||||
{
|
||||
m_Count = count.m_Count;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Count& Count::operator=(long long count)
|
||||
{
|
||||
m_Count = count;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Count Count::now(){
|
||||
return Count( rt_get_time() );
|
||||
}
|
||||
|
||||
Count Count::end(){
|
||||
return Count(0x7FFFFFFFFFFFFFFFLL);
|
||||
}
|
||||
|
||||
long long Count::to_time() const {
|
||||
return count2nano( m_Count );
|
||||
}
|
||||
|
||||
Count Count::from_time(long long time) {
|
||||
Count tmp( nano2count(time) );
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool Count::operator==(const Count& count) const
|
||||
{
|
||||
return m_Count == count.m_Count;
|
||||
}
|
||||
|
||||
bool Count::operator==(long long count) const
|
||||
{
|
||||
return m_Count == count;
|
||||
}
|
||||
|
||||
bool Count::operator<(const Count& count)const{
|
||||
return m_Count < count.m_Count;
|
||||
}
|
||||
|
||||
bool Count::operator>(const Count& count)const {
|
||||
return m_Count > count.m_Count;
|
||||
}
|
||||
|
||||
bool Count::operator<=(const Count& count)const{
|
||||
return m_Count <= count.m_Count;
|
||||
}
|
||||
|
||||
bool Count::operator>=(const Count& count)const {
|
||||
return m_Count >= count.m_Count;
|
||||
}
|
||||
|
||||
Count& Count::operator+=(const Count& count){
|
||||
m_Count += count.m_Count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Count& Count::operator+=(long long count) {
|
||||
m_Count += count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Count& Count::operator-=(const Count& count) {
|
||||
m_Count -= count.m_Count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Count& Count::operator-=(long long count){
|
||||
m_Count -= count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Count Count::operator+(const Count& count) const {
|
||||
Count tmp(m_Count + count.m_Count);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Count Count::operator+(long long count) const {
|
||||
Count tmp(m_Count + count);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Count Count::operator-(const Count& count) const {
|
||||
Count tmp(m_Count - count.m_Count);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Count Count::operator-(long long count) const {
|
||||
Count tmp(m_Count - count);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
114
addons/cpp/count.h
Normal file
114
addons/cpp/count.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: count.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __COUNT_H__
|
||||
#define __COUNT_H__
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Tick Count helper class
|
||||
*
|
||||
* Ticks are sometimes needed by the system calls.
|
||||
* For human readable time keeping, use the Time class.
|
||||
*/
|
||||
class Count {
|
||||
public:
|
||||
/**
|
||||
* The count ticks
|
||||
*/
|
||||
typedef long long ticks;
|
||||
|
||||
/**
|
||||
* The time in nanoseconds
|
||||
*/
|
||||
typedef long long nsecs;
|
||||
|
||||
/**
|
||||
* Instantiates a Count object with count zero
|
||||
*/
|
||||
Count();
|
||||
|
||||
/**
|
||||
* Make a deep copy of a Count instance
|
||||
*/
|
||||
Count(const Count& count);
|
||||
|
||||
/**
|
||||
* Instantiates a Count object with counts on <count>
|
||||
*
|
||||
* @oaram count The system counts to be used
|
||||
*/
|
||||
explicit Count(ticks count);
|
||||
|
||||
Count& operator=(const Count& count);
|
||||
Count& operator=(ticks count);
|
||||
|
||||
static Count now();
|
||||
static Count end();
|
||||
|
||||
inline operator ticks() const { return m_Count; }
|
||||
|
||||
/**
|
||||
* Returns the time in nanoseconds that this Count
|
||||
* instance represents.
|
||||
*/
|
||||
nsecs to_time() const;
|
||||
|
||||
/**
|
||||
* Factory Method. Creates a Count instance
|
||||
* denoting <time> in nanoseconds
|
||||
*
|
||||
* @param time The time in nanoseconds
|
||||
*/
|
||||
static Count from_time(nsecs time);
|
||||
|
||||
bool operator==(const Count& count) const;
|
||||
bool operator==(ticks count) const;
|
||||
|
||||
inline bool operator!=(const Count& count) const { return !this->operator==(count); }
|
||||
inline bool operator!=(ticks count) const { return !this->operator==(count); }
|
||||
|
||||
bool operator<(const Count& count)const;
|
||||
bool operator>(const Count& count)const;
|
||||
|
||||
bool operator<=(const Count& count)const;
|
||||
bool operator>=(const Count& count)const;
|
||||
|
||||
Count& operator+=(const Count& count);
|
||||
Count& operator+=(ticks count);
|
||||
|
||||
Count& operator-=(const Count& count);
|
||||
Count& operator-=(ticks count);
|
||||
|
||||
Count operator+(const Count& count) const;
|
||||
Count operator+(ticks count) const;
|
||||
|
||||
Count operator-(const Count& count) const;
|
||||
Count operator-(ticks count) const;
|
||||
protected:
|
||||
ticks m_Count; // internal count ticks
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
237
addons/cpp/crt.c
Normal file
237
addons/cpp/crt.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: crt.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Specialized bits of code needed to support construction and
|
||||
* destruction of file-scope objects in C++ code.
|
||||
*
|
||||
* This code was partly taken from the GCC sources.
|
||||
*
|
||||
* Copyright:
|
||||
*
|
||||
* Copyright (C) 1991, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
|
||||
* Contributed by Ron Guilmette (rfg@monkeys.com).
|
||||
* Copyright (C) 2002 Erwin Rol (erwin@muffin.org).
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* As a special exception, if you link this library with files
|
||||
* compiled with GCC to produce an executable, this does not cause
|
||||
* the resulting executable to be covered by the GNU General Public License.
|
||||
* This exception does not however invalidate any other reasons why
|
||||
* the executable file might be covered by the GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
static int errno;
|
||||
#define __KERNEL_SYSCALLS__
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <rtai_malloc.h>
|
||||
|
||||
extern int rt_printk(const char *format, ...);
|
||||
extern void __do_atexit( void );
|
||||
extern int __init_atexit( int max_size );
|
||||
|
||||
#if (__GNUC__ <= 2)
|
||||
|
||||
#ifndef CTORS_SECTION_ASM_OP
|
||||
#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\""
|
||||
#endif
|
||||
#ifndef DTORS_SECTION_ASM_OP
|
||||
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
|
||||
#endif
|
||||
|
||||
#else /* ! (__GNUC__ > 3) */
|
||||
|
||||
extern void __do_global_ctors_aux(void);
|
||||
#define __do_global_ctors __do_global_ctors_aux
|
||||
extern void __do_global_dtors_aux(void);
|
||||
#define __do_global_dtors __do_global_dtors_aux
|
||||
|
||||
#endif /* __GNUC__ > 3 */
|
||||
|
||||
/* Declare a pointer to void function type. */
|
||||
#if (__GNUC__ <= 2)
|
||||
typedef void (*func_ptr) (void);
|
||||
#endif /* ! (__GNUC__ > 3) */
|
||||
|
||||
#ifdef CRT_BEGIN
|
||||
|
||||
#if (__GNUC__ <= 2)
|
||||
extern int atexit( func_ptr function );
|
||||
|
||||
static func_ptr __DTOR_LIST__[];
|
||||
static void
|
||||
__do_global_dtors(void)
|
||||
{
|
||||
static func_ptr *p = __DTOR_LIST__ + 1;
|
||||
static int completed = 0;
|
||||
|
||||
rt_printk("GLOBAL DTORS START\n");
|
||||
|
||||
while (*p)
|
||||
{
|
||||
p++;
|
||||
(*(p-1)) ();
|
||||
}
|
||||
|
||||
rt_printk("GLOBAL DTORS END\n");
|
||||
|
||||
completed = 1;
|
||||
}
|
||||
|
||||
extern func_ptr __CTOR_LIST__[];
|
||||
static void
|
||||
__do_global_ctors(void)
|
||||
{
|
||||
unsigned long nptrs = (unsigned long) __CTOR_LIST__[0];
|
||||
unsigned i;
|
||||
|
||||
rt_printk("GLOBAL CTORS START\n");
|
||||
|
||||
if (nptrs == (unsigned long)-1)
|
||||
for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++);
|
||||
|
||||
for (i = nptrs; i >= 1; i--)
|
||||
__CTOR_LIST__[i] ();
|
||||
|
||||
rt_printk("GLOBAL CTORS END\n");
|
||||
}
|
||||
|
||||
#endif /* ! (__GNUC__ > 3) */
|
||||
|
||||
#ifdef USE_MAIN
|
||||
|
||||
extern int main(int argc, char* argv[]);
|
||||
|
||||
static int main_thread(void *unused){
|
||||
sigset_t tmpsig;
|
||||
int res = -1;
|
||||
|
||||
/* Block all signals except SIGKILL and SIGSTOP */
|
||||
spin_lock_irq(¤t->sigmask_lock);
|
||||
tmpsig = current->blocked;
|
||||
siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) );
|
||||
recalc_sigpending(current);
|
||||
spin_unlock_irq(¤t->sigmask_lock);
|
||||
|
||||
__do_global_ctors();
|
||||
|
||||
res = main(0,0);
|
||||
|
||||
__do_global_dtors();
|
||||
__do_atexit();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // USE_MAIN
|
||||
|
||||
|
||||
|
||||
// RTAI-- MODULE INIT and CLEANUP functions
|
||||
|
||||
#ifdef NO_MOD_INIT
|
||||
|
||||
void init_cpp( void )
|
||||
{
|
||||
__init_atexit( 128 );
|
||||
__do_global_ctors();
|
||||
}
|
||||
|
||||
void cleanup_cpp( void )
|
||||
{
|
||||
__do_global_dtors();
|
||||
__do_atexit();
|
||||
}
|
||||
|
||||
#else /* NO_MOD_INIT */
|
||||
|
||||
#include <linux/kthread.h>
|
||||
|
||||
int __init startup_init(void)
|
||||
{
|
||||
__init_atexit( 128 );
|
||||
|
||||
#ifdef USE_MAIN
|
||||
kthread_run(main_thread, NULL, "RTAI_KCPP_SUPRT");
|
||||
#else
|
||||
__do_global_ctors();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startup_cleanup(void)
|
||||
{
|
||||
#ifdef USE_MAIN
|
||||
int waitpid_result = 1;
|
||||
|
||||
while( waitpid_result > 0 )
|
||||
waitpid_result = waitpid(-1,NULL,__WCLONE|WNOHANG);
|
||||
#else
|
||||
__do_global_dtors();
|
||||
__do_atexit();
|
||||
#endif
|
||||
}
|
||||
|
||||
module_init(startup_init)
|
||||
module_exit(startup_cleanup)
|
||||
|
||||
#endif /* NO_MOD_INIT */
|
||||
|
||||
#if (__GNUC__ <= 2)
|
||||
|
||||
/* Force cc1 to switch to .data section. */
|
||||
static func_ptr force_to_data[0] __attribute__ ((__unused__)) = { };
|
||||
|
||||
asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
|
||||
static func_ptr __CTOR_LIST__[1] __attribute__ ((__unused__))
|
||||
= { (func_ptr) (-1) };
|
||||
|
||||
asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
|
||||
static func_ptr __DTOR_LIST__[1] __attribute__ ((__unused__))
|
||||
= { (func_ptr) (-1) };
|
||||
|
||||
#endif /* ! (__GNUC__ > 3) */
|
||||
|
||||
#else // CRT_BEGIN
|
||||
|
||||
#if (__GNUC__ <= 2)
|
||||
|
||||
/* Force cc1 to switch to .data section. */
|
||||
static func_ptr force_to_data[0] __attribute__ ((__unused__)) = { };
|
||||
|
||||
asm (CTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
|
||||
static func_ptr __CTOR_END__[1] __attribute__ ((__unused__))
|
||||
= { (func_ptr) 0 };
|
||||
|
||||
asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
|
||||
static func_ptr __DTOR_END__[1] __attribute__ ((__unused__))
|
||||
= { (func_ptr) 0 };
|
||||
|
||||
#endif /* ! (__GNUC__ > 3) */
|
||||
|
||||
#endif // CRT_BEGIN
|
||||
49
addons/cpp/cs.cc
Normal file
49
addons/cpp/cs.cc
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include "rtai_wrapper.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "rtai.h"
|
||||
#include "rtai_malloc.h"
|
||||
|
||||
}
|
||||
|
||||
#if __GNUC__ < 3
|
||||
/* use __builtin_delete() */
|
||||
#else
|
||||
|
||||
void operator delete(void* vp)
|
||||
{
|
||||
rt_printk("my __builtin_delete %p\n",vp);
|
||||
|
||||
if(vp != 0)
|
||||
rt_free(vp);
|
||||
}
|
||||
|
||||
/* for gcc-3.3 */
|
||||
|
||||
void operator delete[](void* vp){
|
||||
if(vp != 0)
|
||||
rt_free(vp);
|
||||
}
|
||||
|
||||
void *operator new(size_t size){
|
||||
void* vp = rt_malloc(size);
|
||||
return vp;
|
||||
}
|
||||
|
||||
void *operator new[](size_t size){
|
||||
void* vp = rt_malloc(size);
|
||||
return vp;
|
||||
}
|
||||
|
||||
/* __cxa_pure_virtual(void) support */
|
||||
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
rt_printk("attempt to use a virtual function before object has been constructed\n");
|
||||
for ( ; ; );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
65
addons/cpp/init.c
Normal file
65
addons/cpp/init.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: init.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <rtai_malloc.h>
|
||||
#include "tld_key.h"
|
||||
|
||||
extern void init_iostream( void );
|
||||
|
||||
// RTAI-- MODULE INIT and CLEANUP functions
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("the RTAI-Team (contact person Erwin Rol)");
|
||||
MODULE_DESCRIPTION("RTAI C++ support");
|
||||
|
||||
int __init rtai_cpp_init(void){
|
||||
|
||||
cpp_key = __rt_tld_create_key();
|
||||
|
||||
if(cpp_key == -1){
|
||||
rt_printk("Could not get free TLD key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rt_printk("Got %d TLD key\n",cpp_key);
|
||||
|
||||
init_iostream();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtai_cpp_cleanup(void)
|
||||
{
|
||||
if(cpp_key != -1)
|
||||
__rt_tld_free_key(cpp_key);
|
||||
}
|
||||
|
||||
module_init(rtai_cpp_init)
|
||||
module_exit(rtai_cpp_cleanup)
|
||||
|
||||
227
addons/cpp/iostream.cc
Normal file
227
addons/cpp/iostream.cc
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: iostream.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "rtai.h"
|
||||
#include "iostream.h"
|
||||
#include <new.h>
|
||||
|
||||
namespace std {
|
||||
|
||||
ostream cerr;
|
||||
ostream cout;
|
||||
|
||||
ostream& endl( ostream& s )
|
||||
{
|
||||
return s.put( '\n' );
|
||||
}
|
||||
|
||||
ostream& output_on( ostream& s )
|
||||
{
|
||||
return s.set_output_on( true );
|
||||
}
|
||||
|
||||
ostream& output_off( ostream& s )
|
||||
{
|
||||
return s.set_output_on( false );
|
||||
}
|
||||
|
||||
ostream::ostream()
|
||||
: m_OutputOn( true )
|
||||
{
|
||||
rt_printk("ostream::ostream() %p\n",(void*)this);
|
||||
}
|
||||
|
||||
ostream::~ostream()
|
||||
{
|
||||
rt_printk("ostream::~ostream() %p\n",(void*)this);
|
||||
}
|
||||
|
||||
ostream& ostream::set_output_on( bool f )
|
||||
{
|
||||
m_OutputOn = f;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::put(char c)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk( "%c" , c );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::write(const char *s)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%s",s);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::write(const char *s, int n)
|
||||
{
|
||||
if ( m_OutputOn )
|
||||
{
|
||||
for (int i = 0; i < n; i++) {
|
||||
put(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( const char* s )
|
||||
{
|
||||
return write(s);;
|
||||
}
|
||||
|
||||
|
||||
ostream& ostream::operator<<( const void* p )
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%p",p);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( unsigned char c)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%c",c);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( unsigned short n)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%d",n);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( unsigned int n)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%d",n);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( unsigned long n )
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%lu",n);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( unsigned long long n)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("<unsigned long long not implemented>");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( signed char c)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%c",c);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ostream& ostream::operator<<( signed short n)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%d",n);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( signed int n)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%d",n);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( signed long n )
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("%ld",n);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( signed long long n)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("<long long not implemented>");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( float f )
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("<float not implemented>");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( double f )
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("<double not implemented>");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<( long double f)
|
||||
{
|
||||
if( m_OutputOn )
|
||||
rt_printk("<long double not implemented>");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
}; // namespace std
|
||||
|
||||
// doing a placement new with the address of the two global
|
||||
// objects. This is a dirty hack to have just these two
|
||||
// constructors called, because at the moment the rtai_cpp
|
||||
// modules only support one module doing global constructors/destructors
|
||||
// and atexit handling
|
||||
extern "C" {
|
||||
void init_iostream()
|
||||
{
|
||||
new( (void*)&std::cerr ) std::ostream;
|
||||
new( (void*)&std::cout ) std::ostream;
|
||||
}
|
||||
|
||||
} // end extern "C"
|
||||
|
||||
94
addons/cpp/iostream.h
Normal file
94
addons/cpp/iostream.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: iostream.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __IOSTREAM_H__
|
||||
#define __IOSTREAM_H__
|
||||
|
||||
namespace std {
|
||||
|
||||
class ostream;
|
||||
typedef ostream& (*__omanip)(ostream&);
|
||||
|
||||
/**
|
||||
* printk Helper Class
|
||||
*/
|
||||
class ostream {
|
||||
public:
|
||||
ostream();
|
||||
virtual ~ostream();
|
||||
|
||||
ostream& set_output_on( bool f );
|
||||
|
||||
ostream& put(char c);
|
||||
ostream& put(unsigned char c) { return put((char)c); }
|
||||
ostream& put(signed char c) { return put((char)c); }
|
||||
|
||||
ostream& write(const char *s);
|
||||
ostream& write(const unsigned char *s) {
|
||||
return write((const char*)s);
|
||||
}
|
||||
ostream& write(const signed char *s) {
|
||||
return write((const char*)s);
|
||||
}
|
||||
|
||||
ostream& write(const char *s, int n);
|
||||
ostream& write(const unsigned char *s, int n) {
|
||||
return write((const char*)s,n);
|
||||
}
|
||||
ostream& write(const signed char *s, int n) {
|
||||
return write((const char*)s,n);
|
||||
}
|
||||
|
||||
ostream& operator<<( const char* s );
|
||||
ostream& operator<<( const void* p );
|
||||
|
||||
ostream& operator<<( unsigned char n);
|
||||
ostream& operator<<( unsigned short n);
|
||||
ostream& operator<<( unsigned int n);
|
||||
ostream& operator<<( unsigned long n );
|
||||
ostream& operator<<( unsigned long long n);
|
||||
|
||||
ostream& operator<<( signed char n);
|
||||
ostream& operator<<( signed short n);
|
||||
ostream& operator<<( signed int n );
|
||||
ostream& operator<<( signed long n );
|
||||
ostream& operator<<( signed long long n);
|
||||
|
||||
ostream& operator<<( float f );
|
||||
ostream& operator<<( double f );
|
||||
ostream& operator<<( long double f);
|
||||
|
||||
ostream& operator<<(__omanip func) { return (*func)(*this); }
|
||||
protected:
|
||||
bool m_OutputOn;
|
||||
};
|
||||
|
||||
extern ostream& endl( ostream& s );
|
||||
extern ostream& output_off( ostream& s);
|
||||
extern ostream& output_on( ostream& s);
|
||||
|
||||
extern ostream cerr;
|
||||
extern ostream cout;
|
||||
|
||||
}; // namespace std
|
||||
|
||||
#endif
|
||||
32
addons/cpp/linux_wrapper.c
Normal file
32
addons/cpp/linux_wrapper.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: linux_wrapper.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include "linux_wrapper.h"
|
||||
|
||||
int __smp_num_cpus(){
|
||||
return smp_num_cpus;
|
||||
}
|
||||
38
addons/cpp/linux_wrapper.h
Normal file
38
addons/cpp/linux_wrapper.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: linux_wrapper.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_WRAPPER_H__
|
||||
#define __LINUX_WRAPPER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int __smp_num_cpus(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
164
addons/cpp/mbx.cc
Normal file
164
addons/cpp/mbx.cc
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: mbx.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "mbx.h"
|
||||
#include "rtai_registry.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Mailbox::Mailbox(){
|
||||
rt_printk("Mailbox::Mailbox() %p\n",this);
|
||||
m_Mailbox = 0;
|
||||
m_Owner = true;
|
||||
m_Named = false;
|
||||
}
|
||||
|
||||
Mailbox::Mailbox(int size){
|
||||
rt_printk("Mailbox::Mailbox(int size=%d) %p\n",size,this);
|
||||
m_Mailbox = 0;
|
||||
m_Owner = true;
|
||||
m_Named = false;
|
||||
init(size);
|
||||
}
|
||||
|
||||
Mailbox::Mailbox(const char* name){
|
||||
rt_printk("Mailbox::Mailbox(const char* name=%s) %p\n",name,this);
|
||||
m_Mailbox = 0;
|
||||
m_Owner = false;
|
||||
m_Named = true;
|
||||
init(name);
|
||||
}
|
||||
|
||||
Mailbox::Mailbox(const char* name, int size){
|
||||
rt_printk("Mailbox::Mailbox(const char* name=%s, int size=%d)%p\n",name ,size,this);
|
||||
m_Mailbox = 0;
|
||||
m_Owner = true;
|
||||
m_Named = true;
|
||||
init(name,size);
|
||||
}
|
||||
|
||||
Mailbox::~Mailbox(){
|
||||
rt_printk("Mailbox::~Mailbox() %p\n",this);
|
||||
|
||||
if(m_Mailbox != 0){
|
||||
if( m_Owner ){
|
||||
if( m_Named){
|
||||
rt_named_mbx_delete(m_Mailbox);
|
||||
} else {
|
||||
rt_mbx_delete(m_Mailbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mailbox::init(int size){
|
||||
rt_printk("Mailbox::init(int size=%d) %p\n",size,this);
|
||||
if(m_Mailbox == 0){
|
||||
m_Named = false;
|
||||
m_Owner = true;
|
||||
rt_mbx_init(m_Mailbox, size);
|
||||
if( m_Mailbox == 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Mailbox::init(const char* name, int size){
|
||||
rt_printk("Mailbox::init(int size=%d) %p\n",size,this);
|
||||
if(m_Mailbox == 0){
|
||||
m_Owner = true;
|
||||
m_Named = true;
|
||||
m_Mailbox = rt_named_mbx_init(name, size);
|
||||
if( m_Mailbox == 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Mailbox::init(const char* name)
|
||||
{
|
||||
rt_printk("Mailbox::init() %p\n",this);
|
||||
if(m_Mailbox == 0){
|
||||
m_Owner = false;
|
||||
m_Named = true;
|
||||
|
||||
unsigned long num = nam2num(name);
|
||||
if( rt_get_type( num ) == IS_MBX ){
|
||||
m_Mailbox = static_cast<MBX*>(rt_get_adr( num ));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int Mailbox::send(const void* msg, int msg_size){
|
||||
return rt_mbx_send(m_Mailbox,const_cast<void*>(msg),msg_size);
|
||||
}
|
||||
|
||||
int Mailbox::send_wp(const void* msg, int msg_size){
|
||||
return rt_mbx_send_wp(m_Mailbox,const_cast<void*>(msg),msg_size);
|
||||
}
|
||||
|
||||
int Mailbox::send_if(const void* msg, int msg_size){
|
||||
return rt_mbx_send_if(m_Mailbox,const_cast<void*>(msg),msg_size);
|
||||
}
|
||||
|
||||
int Mailbox::send_until(const void* msg, int msg_size, const Count& time){
|
||||
return rt_mbx_send_until(m_Mailbox,const_cast<void*>(msg),msg_size,time);
|
||||
}
|
||||
|
||||
int Mailbox::send_timed(const void* msg, int msg_size, const Count& delay){
|
||||
return rt_mbx_send_timed(m_Mailbox,const_cast<void*>(msg),msg_size,delay);
|
||||
}
|
||||
|
||||
int Mailbox::receive(void* msg, int msg_size){
|
||||
return rt_mbx_receive(m_Mailbox,msg,msg_size);
|
||||
}
|
||||
|
||||
int Mailbox::receive_wp(void* msg, int msg_size){
|
||||
return rt_mbx_receive_wp(m_Mailbox,msg,msg_size);
|
||||
}
|
||||
|
||||
int Mailbox::receive_if(void* msg, int msg_size){
|
||||
return rt_mbx_receive_if(m_Mailbox,msg,msg_size);
|
||||
}
|
||||
|
||||
int Mailbox::receive_until(void* msg, int msg_size, const Count& time){
|
||||
return rt_mbx_receive_until(m_Mailbox,msg,msg_size,time);
|
||||
}
|
||||
|
||||
int Mailbox::receive_timed(void* msg, int msg_size, const Count& delay){
|
||||
return rt_mbx_receive_timed(m_Mailbox,msg,msg_size,delay);
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
117
addons/cpp/mbx.h
Normal file
117
addons/cpp/mbx.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: mbx.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __MBX_H__
|
||||
#define __MBX_H__
|
||||
|
||||
#include "rtai.h"
|
||||
#include "rtai_sched.h"
|
||||
#include "rtai_mbx.h"
|
||||
#include "count.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* MBX wrapper class
|
||||
*/
|
||||
class Mailbox {
|
||||
public:
|
||||
Mailbox();
|
||||
Mailbox(int size);
|
||||
Mailbox(const char* name);
|
||||
Mailbox(const char* name, int size);
|
||||
|
||||
virtual ~Mailbox();
|
||||
|
||||
bool init(int size);
|
||||
bool init(const char* name);
|
||||
bool init(const char* name, int size);
|
||||
|
||||
int send(const void* msg, int msg_size);
|
||||
int send_wp(const void* msg, int msg_size);
|
||||
int send_if(const void* msg, int msg_size);
|
||||
int send_until(const void* msg, int msg_size, const Count& time);
|
||||
int send_timed(const void* msg, int msg_size, const Count& delay);
|
||||
int receive(void* msg, int msg_size);
|
||||
int receive_wp(void* msg, int msg_size);
|
||||
int receive_if(void* msg, int msg_size);
|
||||
int receive_until(void* msg, int msg_size, const Count& time);
|
||||
int receive_timed(void* msg, int msg_size, const Count& delay);
|
||||
protected:
|
||||
MBX* m_Mailbox;
|
||||
bool m_Named;
|
||||
bool m_Owner;
|
||||
private:
|
||||
Mailbox(const Mailbox&);
|
||||
Mailbox& operator=(const Mailbox&);
|
||||
};
|
||||
|
||||
/**
|
||||
* templated Mailbox class
|
||||
*/
|
||||
template <class Type>
|
||||
class MailboxT
|
||||
: public Mailbox
|
||||
{
|
||||
public:
|
||||
MailboxT(){}
|
||||
MailboxT(int size):Mailbox(size){}
|
||||
MailboxT(const char* name ):Mailbox(name){}
|
||||
MailboxT(const char* name, int size):Mailbox(name,size){}
|
||||
|
||||
int send(const Type* msg){
|
||||
return Mailbox::send(msg,sizeof(Type));
|
||||
}
|
||||
int send_wp(const Type* msg){
|
||||
return Mailbox::send_wp(msg,sizeof(Type));
|
||||
}
|
||||
int send_if(const Type* msg){
|
||||
return Mailbox::send_if(msg,sizeof(Type));
|
||||
}
|
||||
int send_until(const Type* msg, const Count& time){
|
||||
return Mailbox::send_until(msg,sizeof(Type),time);
|
||||
}
|
||||
int send_timed(const Type* msg, const Count& delay){
|
||||
return Mailbox::send_timed(msg,sizeof(Type),delay);
|
||||
}
|
||||
int receive(Type* msg){
|
||||
return Mailbox::receive(msg,sizeof(Type));
|
||||
}
|
||||
int receive_wp(Type* msg){
|
||||
return Mailbox::receive_wp(msg,sizeof(Type));
|
||||
}
|
||||
int receive_if(Type* msg){
|
||||
return Mailbox::receive_if(msg,sizeof(Type));
|
||||
}
|
||||
int receive_until(Type* msg, const Count& time){
|
||||
return Mailbox::receive_until(msg,sizeof(Type),time);
|
||||
}
|
||||
int receive_timed(Type* msg, const Count& delay){
|
||||
return Mailbox::receive_timed(msg,sizeof(Type),delay);
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
25
addons/cpp/module.cc
Normal file
25
addons/cpp/module.cc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: module.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
38
addons/cpp/module.h
Normal file
38
addons/cpp/module.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: module.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __MODULE_H__
|
||||
#define __MODULE_H__
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
class Module {
|
||||
public:
|
||||
Module(){}
|
||||
virtual ~Module(){}
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
48
addons/cpp/mutex.cc
Normal file
48
addons/cpp/mutex.cc
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: mutex.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "mutex.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Mutex::Mutex()
|
||||
: Semaphore(1, RES_SEM)
|
||||
{
|
||||
}
|
||||
|
||||
Mutex::~Mutex(){
|
||||
}
|
||||
|
||||
ScopedMutex::ScopedMutex( Mutex& m )
|
||||
: m_Mutex( m )
|
||||
{
|
||||
m_Mutex.wait();
|
||||
}
|
||||
|
||||
ScopedMutex::~ScopedMutex()
|
||||
{
|
||||
m_Mutex.signal();
|
||||
}
|
||||
|
||||
};
|
||||
66
addons/cpp/mutex.h
Normal file
66
addons/cpp/mutex.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: mutex.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "rtai.h"
|
||||
#include "time.h"
|
||||
#include "sem.h"
|
||||
|
||||
#ifndef __MUTEX_H__
|
||||
#define __MUTEX_H__
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* mutal exclusion lock class
|
||||
*/
|
||||
class Mutex
|
||||
: public Semaphore
|
||||
{
|
||||
friend class Condition;
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
private:
|
||||
Mutex(const Mutex&);
|
||||
Mutex& operator=(const Mutex&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Scoped mutal exclusion lock class
|
||||
*/
|
||||
class ScopedMutex {
|
||||
public:
|
||||
ScopedMutex( Mutex& m );
|
||||
~ScopedMutex();
|
||||
protected:
|
||||
Mutex& m_Mutex;
|
||||
private:
|
||||
ScopedMutex( const ScopedMutex& );
|
||||
ScopedMutex operator=( const ScopedMutex& );
|
||||
};
|
||||
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
64
addons/cpp/new.h
Normal file
64
addons/cpp/new.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// The -*- C++ -*- dynamic memory management header.
|
||||
// Copyright (C) 1994, 1996, 1997, 1998, 2000, 2001 Free Software Foundation
|
||||
//
|
||||
// This file is part of GNU CC.
|
||||
//
|
||||
// GNU CC is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// GNU CC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GNU CC; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free software
|
||||
// library without restriction. Specifically, if other files instantiate
|
||||
// templates or use macros or inline functions from this file, or you compile
|
||||
// this file and link it with other files to produce an executable, this
|
||||
// file does not by itself cause the resulting executable to be covered by
|
||||
// the GNU General Public License. This exception does not however
|
||||
// invalidate any other reasons why the executable file might be covered by
|
||||
// the GNU General Public License.
|
||||
|
||||
/** @file new
|
||||
* This header defines several functions to manage dynamic memory and
|
||||
* handling memory allocation errors; see
|
||||
* http://gcc.gnu.org/onlinedocs/libstdc++/18_support/howto.html#4 for more.
|
||||
*/
|
||||
|
||||
#ifndef __NEW_H__
|
||||
#define __NEW_H__
|
||||
|
||||
extern "C++" {
|
||||
|
||||
//@{
|
||||
/** These are replaceable signatures:
|
||||
* - normal single new and delete (no arguments, throw @c bad_alloc on error)
|
||||
* - normal array new and delete (same)
|
||||
* - @c nothrow single new and delete (take a @c nothrow argument, return
|
||||
* @c NULL on error)
|
||||
* - @c nothrow array new and delete (same)
|
||||
*
|
||||
* Placement new and delete signatures (take a memory address argument,
|
||||
* does nothing) may not be replaced by a user's program.
|
||||
*/
|
||||
void *operator new(unsigned int);
|
||||
void *operator new[](unsigned int);
|
||||
void operator delete(void *);
|
||||
void operator delete[](void *);
|
||||
|
||||
// Default placement versions of operator new.
|
||||
inline void *operator new(unsigned int, void *place) { return place; }
|
||||
inline void *operator new[](unsigned int, void *place) { return place; }
|
||||
//@}
|
||||
|
||||
} // extern "C++"
|
||||
|
||||
#endif
|
||||
53
addons/cpp/rtai_cpp.h
Normal file
53
addons/cpp/rtai_cpp.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: rtai_cpp.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __RTAI_CPP_H__
|
||||
#define __RTAI_CPP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
// for C++ only
|
||||
|
||||
#include <rtai_sched.h>
|
||||
|
||||
extern RT_TASK* __rt_task_init(void (*rt_thread)(int), int data,
|
||||
int stack_size, int priority, int uses_fpu,
|
||||
void(*signal)(void));
|
||||
|
||||
extern int __rt_task_delete(RT_TASK *task);
|
||||
|
||||
#endif
|
||||
|
||||
/* for both C and C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void init_cpp( void );
|
||||
extern void cleanup_cpp( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
272
addons/cpp/rtai_pqueue_wrapper.h
Normal file
272
addons/cpp/rtai_pqueue_wrapper.h
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
#ifndef _RTAI_PQUEUE_WRAPPER_H
|
||||
#define _RTAI_PQUEUE_WRAPPER_H
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (©) 1999 Zentropic Computing, All rights reserved
|
||||
//
|
||||
// Authors: Trevor Woolven (trevw@zentropix.com)
|
||||
// Original date: Thu 15 Jul 1999
|
||||
// Id: @(#)$Id: rtai_pqueue_wrapper.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
//
|
||||
// pqueues interface for Real Time Linux.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "linux_wrapper.h"
|
||||
#include "rtai.h"
|
||||
#include "rtai_pthread_wrapper.h"
|
||||
#include "zdefs.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#define TASK_FPU_DISABLE 0
|
||||
#define TASK_FPU_ENABLE 1
|
||||
|
||||
//Posix definitions
|
||||
#define MQ_OPEN_MAX 8 //Maximum number of message queues per process
|
||||
#define MQ_PRIO_MAX 32 //Maximum number of message priorities
|
||||
#define MQ_BLOCK 0 //Flag to set queue into blocking mode
|
||||
#define MQ_NONBLOCK 1 //Flag to set queue into non-blocking mode
|
||||
#define MQ_NAME_MAX 80 //Maximum length of a queue name string
|
||||
|
||||
#define MQ_MIN_MSG_PRIORITY 0 //Lowest priority message
|
||||
#define MQ_MAX_MSG_PRIORITY MQ_PRIO_MAX //Highest priority message
|
||||
|
||||
//Definitions to support higher-level applications
|
||||
typedef enum {FIFO_BASED, PRIORITY_BASED} QUEUEING_POLICY;
|
||||
typedef enum {POSIX, VxWORKS} QUEUE_TYPE;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//Posix Queue Attributes
|
||||
struct mq_attr {
|
||||
long mq_maxmsg; //Maximum number of messages in queue
|
||||
long mq_msgsize; //Maximum size of a message (in bytes)
|
||||
long mq_flags; //Blocking/Non-blocking behaviour specifier
|
||||
// not used in mq_open only relevant for
|
||||
// mq_getattrs and mq_setattrs
|
||||
long mq_curmsgs; //Number of messages currently in queue
|
||||
};
|
||||
typedef struct mq_attr MQ_ATTR;
|
||||
|
||||
typedef union sigval {
|
||||
int sival_int;
|
||||
void *sival_ptr;
|
||||
} sigval_t;
|
||||
|
||||
/*
|
||||
* sigevent definitions
|
||||
*
|
||||
* It seems likely that SIGEV_THREAD will have to be handled from
|
||||
* userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
|
||||
* thread manager then catches and does the appropriate nonsense.
|
||||
* However, everything is written out here so as to not get lost.
|
||||
*/
|
||||
#define SIGEV_SIGNAL 0 /* notify via signal */
|
||||
#define SIGEV_NONE 1 /* other notification: meaningless */
|
||||
#define SIGEV_THREAD 2 /* deliver via thread creation */
|
||||
|
||||
#define SIGEV_MAX_SIZE 64
|
||||
#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
|
||||
|
||||
typedef struct sigevent {
|
||||
sigval_t sigev_value;
|
||||
int sigev_signo;
|
||||
int sigev_notify;
|
||||
union {
|
||||
int _pad[SIGEV_PAD_SIZE];
|
||||
|
||||
struct {
|
||||
void (*_function)(sigval_t);
|
||||
void *_attribute; /* really pthread_attr_t */
|
||||
} _sigev_thread;
|
||||
} _sigev_un;
|
||||
} sigevent_t;
|
||||
|
||||
//Notification data
|
||||
struct notify {
|
||||
RT_TASK *task;
|
||||
struct sigevent data;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//Generic Message format
|
||||
//TODO: Consider moving this definition into rtai_utils.h
|
||||
struct msg_hdr {
|
||||
BOOL in_use;
|
||||
size_t size; //Actual message size
|
||||
uint priority; //Usage priority (message/task)
|
||||
void *next; //Pointer to next message on queue
|
||||
};
|
||||
typedef struct msg_hdr MSG_HDR;
|
||||
|
||||
//Generic queue header
|
||||
struct queue_control {
|
||||
void *base; //Pointer to the base of the queue in memory
|
||||
void *head; //Pointer to the element at the front of the queue
|
||||
void *tail; //Pointer to the element at the back of the queue
|
||||
MQ_ATTR attrs; //Queue attributes
|
||||
};
|
||||
typedef struct queue_control Q_CTRL;
|
||||
|
||||
//Data messages
|
||||
struct msg {
|
||||
MSG_HDR hdr;
|
||||
char data; //Anchor point for message data
|
||||
};
|
||||
typedef struct msg MSG;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//Posix Queue Descriptors
|
||||
struct _pqueue_descr_struct {
|
||||
RT_TASK *owner; //Task that created the queue
|
||||
int open_count; //Count of the number of tasks that have
|
||||
// 'opened' the queue for access
|
||||
char q_name[MQ_NAME_MAX]; //Name supplied for queue
|
||||
uint q_id; //Queue Id (index into static list of queues)
|
||||
BOOL marked_for_deletion; //Queue can be deleted once all tasks have
|
||||
// closed it
|
||||
Q_CTRL data; //Data queue (real messages)
|
||||
mode_t permissions; //Permissions granted by creator (ugo, rwx)
|
||||
struct notify notify; //Notification data (empty -> !empty)
|
||||
pthread_cond_t emp_cond; //For blocking on empty queue
|
||||
pthread_cond_t full_cond; //For blocking on full queue
|
||||
pthread_mutex_t mutex; //For synchronisation of queue
|
||||
};
|
||||
typedef struct _pqueue_descr_struct MSG_QUEUE;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//Task-related Posix Queue data
|
||||
//A task can open up to MQ_OPEN_MAX pqueues, each with 'potentially'
|
||||
//different permissions (read, write, blocking/non-blocking etc)
|
||||
//
|
||||
struct _pqueue_access_data {
|
||||
int q_id;
|
||||
int oflags; //Queue access permissions & blocking spec
|
||||
};
|
||||
|
||||
struct _pqueue_access_struct {
|
||||
RT_TASK *this_task;
|
||||
int n_open_pqueues;
|
||||
struct _pqueue_access_data q_access[MQ_OPEN_MAX];
|
||||
};
|
||||
typedef struct _pqueue_access_struct *QUEUE_CTRL;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
typedef unsigned long mqd_t;
|
||||
#define INVALID_PQUEUE 0
|
||||
|
||||
typedef enum {FOR_READ, FOR_WRITE} Q_ACCESS;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ACCESS FUNCTIONS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
QUEUEING_POLICY get_task_queueing_policy(void);
|
||||
QUEUEING_POLICY set_task_queuing_policy(QUEUEING_POLICY policy);
|
||||
|
||||
QUEUE_TYPE get_queue_type(void);
|
||||
QUEUE_TYPE set_queue_type(QUEUE_TYPE type);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// POSIX MESSAGE QUEUES API
|
||||
//
|
||||
// Note that error returns represent the appropriate macro found in errno.h
|
||||
// eg: -EINVAL, -EBADF etc
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//--------------------------------< mq_open >----------------------------------
|
||||
// Create and/or open a message queue
|
||||
//
|
||||
// Return codes: >= 0 valid Posix Queue Id
|
||||
// < 0 error
|
||||
//
|
||||
extern mqd_t mq_open(char *mq_name, int oflags, mode_t permissions,
|
||||
struct mq_attr *mq_attr);
|
||||
|
||||
//------------------------------< mq_receive >---------------------------------
|
||||
// Receive a message from a message queue
|
||||
//
|
||||
// Return codes: >= 0 number of bytes received
|
||||
// < 0 error
|
||||
//
|
||||
extern size_t mq_receive(mqd_t mq, char *msg_buffer,
|
||||
size_t buflen, unsigned int *msgprio);
|
||||
|
||||
//--------------------------------< mq_send >----------------------------------
|
||||
// Send a message to a queue
|
||||
//
|
||||
// Return codes: >= 0 number of bytes sent
|
||||
// < 0 error
|
||||
extern int mq_send(mqd_t mq, const char *msg, size_t msglen,
|
||||
unsigned int msgprio);
|
||||
|
||||
//--------------------------------< mq_close >---------------------------------
|
||||
// Close a message queue (note that the queue remains in existance!)
|
||||
//
|
||||
// Return codes: = 0 pQueue closed OK
|
||||
// < 0 error
|
||||
//
|
||||
extern int mq_close(mqd_t mq);
|
||||
|
||||
//-------------------------------< mq_getattr >--------------------------------
|
||||
// Get the attributes of a message queue
|
||||
//
|
||||
// Return codes: = 0 attributes copied successfully
|
||||
// < 0 error
|
||||
//
|
||||
extern int mq_getattr(mqd_t mq, struct mq_attr *attrbuf);
|
||||
|
||||
//-------------------------------< mq_setattr >--------------------------------
|
||||
// Set a subset of a message queue's attributes
|
||||
//
|
||||
// Return codes: = 0 attributes set successfully
|
||||
// < 0 error
|
||||
//
|
||||
extern int mq_setattr(mqd_t mq, const struct mq_attr *new_attrs,
|
||||
struct mq_attr *old_attrs);
|
||||
|
||||
//-------------------------------< mq_notify >---------------------------------
|
||||
// Register a request to be notified whenever a message arrives on an empty
|
||||
// queue
|
||||
// Note that setting the 'notification' parameter to NULL cancels the task's
|
||||
// earlier notification request
|
||||
//
|
||||
// Return codes: = 0 notification set/cleared successfully
|
||||
// < 0 error
|
||||
//
|
||||
extern int mq_notify(mqd_t mq, const struct sigevent *notification);
|
||||
|
||||
//-------------------------------< mq_unlink >---------------------------------
|
||||
// Destroy a message queue
|
||||
//
|
||||
// Returns: = 0 queue was successfully unlinked
|
||||
// < 0 error
|
||||
// > 0 'n' tasks still have the queue 'open'
|
||||
//
|
||||
extern int mq_unlink(char *mq_name);
|
||||
|
||||
// ---------------------------------< eof >------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _RTAI_PQUEUE_WRAPPER_H_
|
||||
78
addons/cpp/rtai_pthread_int_wrapper.h
Normal file
78
addons/cpp/rtai_pthread_int_wrapper.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef _RTAI_PTHREAD_INT_WRAPPER_H_
|
||||
#define _RTAI_PTHREAD_INT_WRAPPER_H_
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (©) 1999 Zentropic Computing, All rights reserved
|
||||
//
|
||||
// Authors: Steve Papacharalambous (stevep@zentropix.com)
|
||||
// Original date: Thu 15 Jul 1999
|
||||
//
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
//
|
||||
// pthreads interface for Real Time Linux.
|
||||
//
|
||||
// Modified for wrapping the pthreads to rtai_cpp by Peter Soetens
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define POSIX_THREADS_MAX 64
|
||||
#define PTHREAD_KEYS_MAX 1024
|
||||
|
||||
// Thread specific data is kept in a special data structure, a two-level
|
||||
// array. The top-level array contains pointers to dynamically allocated
|
||||
// arrays of a certain number of data pointers. So a sparse array can be
|
||||
// implemented. Each dynamic second-level array has
|
||||
// PTHREAD_KEY_2NDLEVEL_SIZE
|
||||
// entries,and this value shouldn't be too large.
|
||||
#define PTHREAD_KEY_2NDLEVEL_SIZE 32
|
||||
|
||||
// Need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
|
||||
// keys in each subarray.
|
||||
#define PTHREAD_KEY_1STLEVEL_SIZE \
|
||||
((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
|
||||
/ PTHREAD_KEY_2NDLEVEL_SIZE)
|
||||
|
||||
|
||||
#define TASK_FPU_DISABLE 0
|
||||
#define TASK_FPU_ENABLE 1
|
||||
|
||||
#define NSECS_PER_SEC 1000000000
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Arguments passed to thread creation routine.
|
||||
|
||||
struct pthread_start_args;
|
||||
|
||||
#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, 0, 0, { 0 } }
|
||||
|
||||
|
||||
struct _pthread_descr_struct;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _RTAI_PTHREAD_INT_WRAPPER_H_
|
||||
304
addons/cpp/rtai_pthread_wrapper.h
Normal file
304
addons/cpp/rtai_pthread_wrapper.h
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
#ifndef _RTAI_PTHREAD_WRAPPER_H_
|
||||
#define _RTAI_PTHREAD_WRAPPER_H_
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (©) 1999 Zentropic Computing, All rights reserved
|
||||
//
|
||||
// Authors: Steve Papacharalambous (stevep@zentropix.com)
|
||||
// Original date: Thu 15 Jul 1999
|
||||
//
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
//
|
||||
// pthreads interface for Real Time Linux.
|
||||
//
|
||||
// Modified for wrapping the pthreads to rtai_cpp by Peter Soetens
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "linux_wrapper.h"
|
||||
#include "rtai.h"
|
||||
#include "rtai_pthread_int_wrapper.h"
|
||||
#include "rtai_types.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef struct rt_task_struct RT_TASK;
|
||||
#define SEM_ERR (0xffff) // MUST be the same as rtai_sched.c
|
||||
#define RT_SEM_MAGIC 0xaabcdeff // MUST be the same as rtai_sched.c
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define PTHREAD_MUTEX_INITIALIZER {0, PTHREAD_MUTEX_FAST_NP, {{0, 0, 0}, RT_SEM_MAGIC, BIN_SEM, 1, 0, FIFO_Q}}
|
||||
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {0, PTHREAD_MUTEX_RECURSIVE_NP, {{0, 0, 0}, RT_SEM_MAGIC, BIN_SEM, 1, 0, FIFO_Q}}
|
||||
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP {0, PTHREAD_MUTEX_ERRORCHECK_NP, {{0, 0, 0}, RT_SEM_MAGIC, BIN_SEM, 1, 0, FIFO_Q}}
|
||||
|
||||
#define PTHREAD_COND_INITIALIZER {{{0, 0, 0}, RT_SEM_MAGIC, BIN_SEM, 1, 0, FIFO_Q}}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
enum { PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE };
|
||||
enum { PTHREAD_CANCEL_DEFERRED, PTHREAD_CANCEL_ASYNCHRONOUS };
|
||||
enum { PTHREAD_INHERIT_SCHED, PTHREAD_EXPLICIT_SCHED };
|
||||
enum { PTHREAD_CREATE_JOINABLE, PTHREAD_CREATE_DETACHED };
|
||||
enum { PTHREAD_SCOPE_SYSTEM, PTHREAD_SCOPE_PROCESS };
|
||||
|
||||
enum {
|
||||
PTHREAD_MUTEX_FAST_NP,
|
||||
PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ERRORCHECK_NP
|
||||
};
|
||||
|
||||
|
||||
enum { CLOCK_REALTIME };
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef unsigned long pthread_t;
|
||||
|
||||
typedef struct _pthread_descr_struct *pthread_descr;
|
||||
|
||||
typedef int rt_jmp_buf[6];
|
||||
|
||||
|
||||
/* START by Peter Soetens */
|
||||
|
||||
struct sched_param {
|
||||
int sched_priority;
|
||||
};
|
||||
#define SCHED_OTHER 0
|
||||
#define SCHED_FIFO 1
|
||||
#define SCHED_RR 2
|
||||
struct rt_queue {
|
||||
struct rt_queue *prev;
|
||||
struct rt_queue *next;
|
||||
struct rt_task_struct *task;
|
||||
};
|
||||
|
||||
typedef struct rt_queue QUEUE;
|
||||
|
||||
struct rt_semaphore {
|
||||
struct rt_queue queue; //must be first in struct
|
||||
int magic;
|
||||
int type;
|
||||
int count;
|
||||
struct rt_task_struct *owndby;
|
||||
int qtype;
|
||||
};
|
||||
|
||||
typedef struct rt_semaphore SEM;
|
||||
|
||||
/* END by Peter Soetens */
|
||||
|
||||
typedef struct {
|
||||
int detachstate;
|
||||
int schedpolicy;
|
||||
struct sched_param schedparam;
|
||||
int inheritsched;
|
||||
int scope;
|
||||
} pthread_attr_t;
|
||||
|
||||
typedef struct {
|
||||
int mutexkind;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
typedef struct {
|
||||
int dummy;
|
||||
} pthread_condattr_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
RT_TASK *m_owner;
|
||||
int m_kind;
|
||||
struct rt_semaphore m_semaphore;
|
||||
} pthread_mutex_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
SEM c_waiting;
|
||||
} pthread_cond_t;
|
||||
|
||||
|
||||
// Cleanup buffer.
|
||||
|
||||
struct _pthread_cleanup_buffer {
|
||||
void (*routine)(void *); // Function to call.
|
||||
void *arg; // Its argument.
|
||||
int canceltype; // Saved cancellation type.
|
||||
struct _pthread_cleanup_buffer *prev; // Chaining of cleanup functions.
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Create a RT task with attributes ATTR, or default attributes if ATTR is NULL
|
||||
// and call start function START_ROUTINE passing arguments ARG.
|
||||
extern int pthread_create(pthread_t *thread, pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg);
|
||||
|
||||
|
||||
// Terminate the calling thread,
|
||||
extern void pthread_exit(void *retval);
|
||||
|
||||
// Get the identifier of the current thread.
|
||||
extern pthread_t pthread_self(void);
|
||||
|
||||
// Initialise thread attribute object, and fill it in with default values.
|
||||
extern int pthread_attr_init(pthread_attr_t *attr);
|
||||
|
||||
// Destroy a thread attribute object.
|
||||
extern int pthread_attr_destroy(pthread_attr_t *attr);
|
||||
|
||||
// Set the detach state for the thread.
|
||||
extern int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
|
||||
|
||||
// Get the detach state for the thread.
|
||||
extern int pthread_attr_getdetachstate(const pthread_attr_t *attr,
|
||||
int *detachstate);
|
||||
|
||||
// Set the thread scheduling parameters.
|
||||
extern int pthread_attr_setschedparam(pthread_attr_t *attr,
|
||||
const struct sched_param *param);
|
||||
|
||||
// Get the thread scheduling parameters.
|
||||
extern int pthread_attr_getschedparam(const pthread_attr_t *attr,
|
||||
struct sched_param *param);
|
||||
|
||||
// Set thread scheduling policy.
|
||||
extern int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
|
||||
|
||||
// Get thread scheduling policy.
|
||||
extern int pthread_attr_getschedpolicy(const pthread_attr_t *attr,
|
||||
int *policy);
|
||||
|
||||
// Set thread scheduling inheritance.
|
||||
extern int pthread_attr_setinheritsched(pthread_attr_t *attr,
|
||||
int inherit);
|
||||
|
||||
// Get thread scheduling inheritance.
|
||||
extern int pthread_attr_getinheritsched(const pthread_attr_t *attr,
|
||||
int *inherit);
|
||||
|
||||
// Set thread scheduling scope.
|
||||
extern int pthread_attr_setscope(pthread_attr_t *attr, int scope);
|
||||
|
||||
|
||||
// Get thread scheduling scope.
|
||||
extern int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
|
||||
|
||||
|
||||
// Yield the processor.
|
||||
extern int sched_yield(void);
|
||||
|
||||
// Get the current clock count. (Only CLOCK_REALTIME is currently supported)
|
||||
extern void clock_gettime( int clockid, struct timespec *current_time);
|
||||
|
||||
// Delay the execution of the calling task for the time specified in req.
|
||||
extern int nanosleep(const struct timespec *req, struct timespec *rem);
|
||||
|
||||
// Initialise mutex object.
|
||||
extern int pthread_mutex_init(pthread_mutex_t *mutex,
|
||||
const pthread_mutexattr_t *mutex_attr);
|
||||
|
||||
|
||||
// Destroy mutex object.
|
||||
extern int pthread_mutex_destroy(pthread_mutex_t *mutex);
|
||||
|
||||
|
||||
// Initialise mutex object attributes.
|
||||
extern int pthread_mutexattr_init(pthread_mutexattr_t *attr);
|
||||
|
||||
|
||||
// Destroy mutex object attributes.
|
||||
extern int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
|
||||
|
||||
|
||||
// Set mutex kind attribute.
|
||||
extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
|
||||
|
||||
|
||||
// Retrieve the current value of the mutex kind attribute.
|
||||
extern int pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr,
|
||||
int *kind);
|
||||
|
||||
// Set thread scheduling parameters.
|
||||
extern int pthread_setschedparam(pthread_t thread, int policy,
|
||||
const struct sched_param *param);
|
||||
|
||||
// Get thread scheduling parameters.
|
||||
extern int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);
|
||||
|
||||
// Non blocking mutex lock.
|
||||
extern int pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||
|
||||
|
||||
|
||||
// Blocking mutex lock.
|
||||
extern int pthread_mutex_lock(pthread_mutex_t *mutex);
|
||||
|
||||
|
||||
// Mutex unlock.
|
||||
extern int pthread_mutex_unlock(pthread_mutex_t *mutex);
|
||||
|
||||
|
||||
// Initialise conditional variable.
|
||||
extern int pthread_cond_init(pthread_cond_t *cond,
|
||||
const pthread_condattr_t *cond_attr);
|
||||
|
||||
|
||||
// Destroy conditional variable.
|
||||
extern int pthread_cond_destroy(pthread_cond_t *cond);
|
||||
|
||||
|
||||
// Initialise condition attribute object.
|
||||
extern int pthread_condattr_init(pthread_condattr_t *attr);
|
||||
|
||||
|
||||
// Destroy condition attribute object.
|
||||
extern int pthread_condattr_destroy(pthread_condattr_t *attr);
|
||||
|
||||
|
||||
// Wait for condition variable to be signaled.
|
||||
extern int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
||||
|
||||
|
||||
// Wait for condition variable to be signaled or timeout expires.
|
||||
extern int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime);
|
||||
|
||||
|
||||
// Restart one of the threads waiting on the conditional variable cond.
|
||||
extern int pthread_cond_signal(pthread_cond_t *cond);
|
||||
|
||||
|
||||
// Restart all of the threads waiting on the conditional variable cond.
|
||||
extern int pthread_cond_broadcast(pthread_cond_t *cond);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _RTAI_PTHREAD_WRAPPER_H_
|
||||
95
addons/cpp/rtai_wrapper.c
Normal file
95
addons/cpp/rtai_wrapper.c
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: rtai_wrapper.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
#include "rtai_wrapper.h"
|
||||
|
||||
#include <rtai.h>
|
||||
#include <rtai_malloc.h>
|
||||
#include "tld_key.h"
|
||||
|
||||
void __rt_get_global_lock(void){
|
||||
rt_get_global_lock();
|
||||
}
|
||||
|
||||
void __rt_release_global_lock(void){
|
||||
rt_release_global_lock();
|
||||
}
|
||||
|
||||
int __hard_cpu_id( void ){
|
||||
return hard_cpu_id();
|
||||
}
|
||||
|
||||
/* task functions */
|
||||
|
||||
RT_TASK * __rt_task_init(void (*rt_thread)(int), int data,
|
||||
int stack_size, int priority, int uses_fpu,
|
||||
void(*signal)(void))
|
||||
{
|
||||
RT_TASK * task;
|
||||
|
||||
task = rt_malloc( sizeof(RT_TASK) );
|
||||
|
||||
if(task == 0)
|
||||
return 0;
|
||||
|
||||
memset(task,0,sizeof(RT_TASK));
|
||||
|
||||
rt_task_init(task,rt_thread,data,stack_size,priority,uses_fpu,signal);
|
||||
|
||||
__rt_tld_set_data(task,cpp_key,(void*)data);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
int __rt_task_delete(RT_TASK *task)
|
||||
{
|
||||
int result;
|
||||
rt_printk("__rt_task_delete(%p)\n",task);
|
||||
|
||||
if(task == 0)
|
||||
return -1;
|
||||
|
||||
rt_task_suspend(task);
|
||||
|
||||
result = rt_task_delete(task);
|
||||
|
||||
rt_free(task);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTAI_TRACE
|
||||
|
||||
void __trace_destroy_event( int id ){
|
||||
trace_destroy_event( id );
|
||||
}
|
||||
|
||||
int __trace_create_event( const char* name, void* p){
|
||||
return trace_create_event( (char *)name, NULL, CUSTOM_EVENT_FORMAT_TYPE_NONE, (char *)p);
|
||||
}
|
||||
|
||||
int __trace_raw_event( int id, int size, void* p){
|
||||
return trace_raw_event( id, size, p);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RTAI_TRACE */
|
||||
49
addons/cpp/rtai_wrapper.h
Normal file
49
addons/cpp/rtai_wrapper.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: rtai_wrapper.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __RTAI_WRAPPER_H__
|
||||
#define __RTAI_WRAPPER_H__
|
||||
|
||||
/**
|
||||
* The aim of this file is to contain all RTAI functions that can by no
|
||||
* means be included with the C++ compiler.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtai_types.h>
|
||||
|
||||
void __rt_get_global_lock(void);
|
||||
|
||||
void __rt_release_global_lock(void);
|
||||
|
||||
int __hard_cpu_id(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __RTAI_WRAPPER_H__ */
|
||||
77
addons/cpp/rtf.cc
Normal file
77
addons/cpp/rtf.cc
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: rtf.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "rtf.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
RTAI::fifo* RTAI::fifo::m_this_table[MAX_FIFOS];
|
||||
|
||||
fifo::fifo(){
|
||||
}
|
||||
|
||||
fifo::fifo(int id, int size){
|
||||
create(id,size);
|
||||
}
|
||||
|
||||
int fifo::create(int id, int size){
|
||||
int res = rtf_create(id,size);
|
||||
m_fifo = id;
|
||||
m_this_table[id] = this;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
fifo::~fifo(){
|
||||
if(m_fifo != -1){
|
||||
m_this_table[m_fifo] = 0;
|
||||
rtf_destroy(m_fifo);
|
||||
}
|
||||
}
|
||||
|
||||
int fifo::reset(){
|
||||
return rtf_reset(m_fifo);
|
||||
}
|
||||
|
||||
int fifo::resize(int size){
|
||||
return rtf_resize(m_fifo,size);
|
||||
}
|
||||
|
||||
int fifo::put(const void* buffer, int count){
|
||||
return rtf_put(m_fifo,const_cast<void*>(buffer),count);
|
||||
}
|
||||
|
||||
int fifo::get(void* buffer, int count){
|
||||
return rtf_get(m_fifo,buffer,count);
|
||||
}
|
||||
|
||||
int fifo::activate_handler(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fifo::deactivate_handler(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
78
addons/cpp/rtf.h
Normal file
78
addons/cpp/rtf.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: rtf.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __RTF_H__
|
||||
#define __RTF_H__
|
||||
|
||||
#include "rtai.h"
|
||||
#include "rtai_fifos.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* RTF wrapper class
|
||||
*/
|
||||
class fifo {
|
||||
public:
|
||||
fifo();
|
||||
fifo(int id, int size);
|
||||
virtual ~fifo();
|
||||
|
||||
int create(int id, int size);
|
||||
|
||||
int reset();
|
||||
int resize(int size);
|
||||
int put(const void* buffer, int count);
|
||||
int get(void* buffer, int count);
|
||||
|
||||
int activate_handler();
|
||||
int deactivate_handler();
|
||||
|
||||
virtual void handler(){};
|
||||
protected:
|
||||
int m_fifo;
|
||||
static fifo* m_this_table[MAX_FIFOS];
|
||||
};
|
||||
|
||||
template <class Type>
|
||||
class fifoT
|
||||
: public fifo
|
||||
{
|
||||
public:
|
||||
fifoT(){}
|
||||
fifoT(int id,int size) : fifo(id,size){}
|
||||
|
||||
int put(const Type* type) {
|
||||
return fifo::put((const void*)type,sizeof(Type));
|
||||
}
|
||||
|
||||
int get(Type* type) {
|
||||
return fifo::get((void*)type,sizeof(Type));
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
51
addons/cpp/rtf_init.c
Normal file
51
addons/cpp/rtf_init.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: rtf_init.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <rtai_malloc.h>
|
||||
#include "rtai.h"
|
||||
|
||||
// RTAI-- MODULE INIT and CLEANUP functions
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("the RTAI-Team (contact person Erwin Rol)");
|
||||
MODULE_DESCRIPTION("RTAI C++ RTF support");
|
||||
|
||||
int __init rtai_cpp_rtf_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtai_cpp_rtf_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(rtai_cpp_rtf_init)
|
||||
module_exit(rtai_cpp_rtf_cleanup)
|
||||
|
||||
112
addons/cpp/sem.cc
Normal file
112
addons/cpp/sem.cc
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: sem.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "sem.h"
|
||||
#include "rtai_registry.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Semaphore::Semaphore(int value, int type){
|
||||
m_Owner = true;
|
||||
m_Named = false;
|
||||
rt_typed_sem_init(m_Sem, value,type);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(const char* name, int value, int type){
|
||||
m_Owner = true;
|
||||
m_Named = true;
|
||||
m_Sem = rt_typed_named_sem_init(name,value,type);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(const char* name){
|
||||
m_Named = true;
|
||||
m_Owner = false;
|
||||
m_Sem = 0;
|
||||
unsigned long num = nam2num(name);
|
||||
if( rt_get_type( num ) == IS_SEM ){
|
||||
m_Sem = static_cast<SEM*>( rt_get_adr( num ) );
|
||||
}
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore(){
|
||||
if(m_Sem != 0){
|
||||
if( m_Owner ){
|
||||
if( m_Named )
|
||||
rt_named_sem_delete(m_Sem);
|
||||
else
|
||||
rt_sem_delete(m_Sem);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Semaphore::signal(){
|
||||
return rt_sem_signal(m_Sem);
|
||||
}
|
||||
|
||||
int Semaphore::broadcast(){
|
||||
return rt_sem_broadcast(m_Sem);
|
||||
}
|
||||
|
||||
int Semaphore::wait(){
|
||||
return rt_sem_wait(m_Sem);
|
||||
}
|
||||
|
||||
int Semaphore::wait_if(){
|
||||
return rt_sem_wait_if(m_Sem);
|
||||
}
|
||||
|
||||
int Semaphore::wait_until(const Time& time){
|
||||
return rt_sem_wait_until(m_Sem,time.to_count());
|
||||
}
|
||||
|
||||
int Semaphore::wait_timed(const Time& delay){
|
||||
return rt_sem_wait_timed(m_Sem,delay.to_count());
|
||||
}
|
||||
|
||||
BinarySemaphore::BinarySemaphore()
|
||||
: Semaphore(0,BIN_SEM)
|
||||
{
|
||||
}
|
||||
|
||||
BinarySemaphore::~BinarySemaphore(){
|
||||
}
|
||||
|
||||
CountingSemaphore::CountingSemaphore()
|
||||
: Semaphore(0,CNT_SEM)
|
||||
{
|
||||
}
|
||||
|
||||
CountingSemaphore::~CountingSemaphore(){
|
||||
}
|
||||
|
||||
ResourceSemaphore::ResourceSemaphore()
|
||||
: Semaphore(0,RES_SEM)
|
||||
{
|
||||
}
|
||||
|
||||
ResourceSemaphore::~ResourceSemaphore(){
|
||||
}
|
||||
|
||||
};
|
||||
106
addons/cpp/sem.h
Normal file
106
addons/cpp/sem.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: sem.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "rtai_sched.h"
|
||||
#include "rtai_sem.h"
|
||||
#include "time.h"
|
||||
|
||||
#ifndef __SEM_H__
|
||||
#define __SEM_H__
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Abstract Semaphore base class.
|
||||
*/
|
||||
class Semaphore {
|
||||
protected:
|
||||
Semaphore(int value,int type);
|
||||
Semaphore(const char* name, int value, int type);
|
||||
Semaphore(const char* name );
|
||||
public:
|
||||
virtual ~Semaphore();
|
||||
int signal();
|
||||
int broadcast();
|
||||
int wait();
|
||||
int wait_if();
|
||||
int wait_until(const Time& time);
|
||||
int wait_timed(const Time& delay);
|
||||
protected:
|
||||
SEM* m_Sem;
|
||||
bool m_Owner;
|
||||
bool m_Named;
|
||||
private:
|
||||
Semaphore(const Semaphore&);
|
||||
Semaphore& operator=(const Semaphore&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Binary Semaphore class
|
||||
*/
|
||||
class BinarySemaphore
|
||||
: public Semaphore
|
||||
{
|
||||
public:
|
||||
BinarySemaphore();
|
||||
virtual ~BinarySemaphore();
|
||||
protected:
|
||||
private:
|
||||
BinarySemaphore(const BinarySemaphore&);
|
||||
BinarySemaphore& operator=(const BinarySemaphore&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Counting Semaphore class
|
||||
*/
|
||||
class CountingSemaphore
|
||||
: public Semaphore
|
||||
{
|
||||
public:
|
||||
CountingSemaphore();
|
||||
virtual ~CountingSemaphore();
|
||||
protected:
|
||||
private:
|
||||
CountingSemaphore(const CountingSemaphore&);
|
||||
CountingSemaphore& operator=(const CountingSemaphore&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Resource Semaphore class
|
||||
*/
|
||||
class ResourceSemaphore
|
||||
: public Semaphore
|
||||
{
|
||||
public:
|
||||
ResourceSemaphore();
|
||||
~ResourceSemaphore();
|
||||
protected:
|
||||
private:
|
||||
ResourceSemaphore(const ResourceSemaphore&);
|
||||
ResourceSemaphore& operator=(const ResourceSemaphore&);
|
||||
};
|
||||
|
||||
}; // namesapce RTAI
|
||||
|
||||
#endif
|
||||
336
addons/cpp/task.cc
Normal file
336
addons/cpp/task.cc
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: task.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "task.h"
|
||||
#include "iostream.h"
|
||||
#include "tld_key.h"
|
||||
#include <asm/rtai.h>
|
||||
#include <rtai_registry.h>
|
||||
#include <rtai_wrapper.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// OK, this is _ugly_, int casting to this* is even
|
||||
// worse than casting a void* to a this* (like with pthreads)
|
||||
void entry_point(int this_pointer){
|
||||
RTAI::Task* This = (RTAI::Task*)this_pointer;
|
||||
This->run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void signal_handler(){
|
||||
#if 0
|
||||
RTAI::Task* This = RTAI::Task::self();
|
||||
This->signal_handler();
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
void get_global_lock(void){
|
||||
__rt_get_global_lock();
|
||||
}
|
||||
|
||||
void release_global_lock(void){
|
||||
__rt_release_global_lock();
|
||||
}
|
||||
|
||||
int hard_cpu_id(void){
|
||||
return hard_cpu_id();
|
||||
}
|
||||
|
||||
int assign_irq_to_cpu(int irq, unsigned long cpus_mask){
|
||||
return rt_assign_irq_to_cpu(irq,cpus_mask);
|
||||
}
|
||||
|
||||
int reset_irq_to_sym_mode(int irq){
|
||||
return rt_reset_irq_to_sym_mode(irq);
|
||||
}
|
||||
|
||||
void set_oneshot_mode(void){
|
||||
rt_set_oneshot_mode();
|
||||
}
|
||||
|
||||
void set_periodic_mode(void){
|
||||
rt_set_periodic_mode();
|
||||
}
|
||||
|
||||
Count start_timer(void){
|
||||
return Count( start_rt_timer(0) );
|
||||
}
|
||||
|
||||
Count start_timer(const Count& period){
|
||||
return Count( start_rt_timer( period ) );
|
||||
}
|
||||
|
||||
void stop_timer(void){
|
||||
stop_rt_timer();
|
||||
}
|
||||
|
||||
void linux_use_fpu(bool use_fpu_flag){
|
||||
rt_linux_use_fpu(use_fpu_flag);
|
||||
}
|
||||
|
||||
void preempt_always(bool yes_no){
|
||||
rt_preempt_always(yes_no);
|
||||
}
|
||||
|
||||
void preempt_always_cpuid(bool yes_no, unsigned int cpu_id){
|
||||
rt_preempt_always_cpuid(yes_no,cpu_id);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// class RTAI::Task
|
||||
//
|
||||
|
||||
Task::Task(){
|
||||
std::cerr << "Task::Task() " << (void*)this << std::endl;
|
||||
m_TaskOwner = false;
|
||||
m_Named = false;
|
||||
m_Task = 0;
|
||||
for(int n=0; n < CONFIG_RTAI_CPUS;n++)
|
||||
m_CpuUse[n] = 0;
|
||||
}
|
||||
|
||||
Task::~Task(){
|
||||
std::cerr << "Task::~Task() " << (void*)this << std::endl;
|
||||
|
||||
if(m_Task != 0)
|
||||
{
|
||||
if( m_TaskOwner ){
|
||||
if( m_Named){
|
||||
rt_named_task_delete(m_Task);
|
||||
} else {
|
||||
rt_task_delete(m_Task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Task::Task(int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid)
|
||||
{
|
||||
std::cerr << "Task::Task(...) " << (void*)this << std::endl;
|
||||
|
||||
m_TaskOwner = true;
|
||||
m_Named = false;
|
||||
m_Task = 0;
|
||||
for(int n=0; n < CONFIG_RTAI_CPUS;n++)
|
||||
m_CpuUse[n] = 0;
|
||||
|
||||
init(stack_size,priority,uses_fpu,use_signal,cpuid);
|
||||
}
|
||||
|
||||
Task::Task(const char* name,
|
||||
int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid)
|
||||
{
|
||||
std::cerr << "Task::Task(...) " << (void*)this << std::endl;
|
||||
|
||||
m_Named = true;
|
||||
m_TaskOwner = true;
|
||||
m_Task = 0;
|
||||
for(int n=0; n < CONFIG_RTAI_CPUS;n++)
|
||||
m_CpuUse[n] = 0;
|
||||
|
||||
init(name,stack_size,priority,uses_fpu,use_signal,cpuid);
|
||||
}
|
||||
|
||||
Task::Task(const char* name )
|
||||
{
|
||||
std::cerr << "Task::Task(...) " << (void*)this << std::endl;
|
||||
|
||||
m_Named = true;
|
||||
m_TaskOwner = false;
|
||||
m_Task = 0;
|
||||
for(int n=0; n < CONFIG_RTAI_CPUS;n++)
|
||||
m_CpuUse[n] = 0;
|
||||
|
||||
init( name );
|
||||
}
|
||||
|
||||
bool Task::init(int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid)
|
||||
{
|
||||
rt_printk("Task::init(...) %p\n",this);
|
||||
|
||||
if(m_Task != 0)
|
||||
return false;
|
||||
|
||||
m_Named = false;
|
||||
m_TaskOwner = true;
|
||||
|
||||
if(stack_size == 0)
|
||||
stack_size = 1024*4;
|
||||
|
||||
if(use_signal)
|
||||
rt_task_init(m_Task, ::entry_point,(int)this,
|
||||
stack_size,priority,uses_fpu,::signal_handler);
|
||||
else
|
||||
rt_task_init(m_Task, ::entry_point,(int)this,
|
||||
stack_size,priority,uses_fpu,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Task::init(const char* name,
|
||||
int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid)
|
||||
{
|
||||
rt_printk("Task::init(...) %p\n",this);
|
||||
|
||||
if(m_Task != 0)
|
||||
return false;
|
||||
|
||||
m_Named = true;
|
||||
m_TaskOwner = true;
|
||||
|
||||
if(stack_size == 0)
|
||||
stack_size = 1024*4;
|
||||
|
||||
if(use_signal)
|
||||
m_Task = rt_named_task_init(name, ::entry_point,(int)this,
|
||||
stack_size,priority,uses_fpu,::signal_handler);
|
||||
else
|
||||
m_Task = rt_named_task_init(name, ::entry_point,(int)this,
|
||||
stack_size,priority,uses_fpu,0);
|
||||
|
||||
if( m_Task == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Task::init(const char* name)
|
||||
{
|
||||
rt_printk("Task::init(...) %p\n",this);
|
||||
|
||||
if(m_Task != 0)
|
||||
return false;
|
||||
|
||||
m_Named = true;
|
||||
m_TaskOwner = false;
|
||||
|
||||
unsigned long num = nam2num(name);
|
||||
if( rt_get_type( num ) == IS_TASK ){
|
||||
m_Task = static_cast<RT_TASK*>( rt_get_adr( num ) );
|
||||
}
|
||||
|
||||
if( m_Task == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Task* Task::self(){
|
||||
struct rt_task_struct* task = rt_whoami();
|
||||
if(task == 0)
|
||||
return 0;
|
||||
|
||||
return (Task*)__rt_tld_get_data(task,cpp_key);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Task::suspend(){
|
||||
rt_task_suspend(m_Task);
|
||||
}
|
||||
|
||||
void Task::resume(){
|
||||
rt_task_resume(m_Task);
|
||||
}
|
||||
|
||||
void Task::yield(){
|
||||
rt_task_yield();
|
||||
}
|
||||
|
||||
int Task::make_periodic(const Count& start_time, const Count& period){
|
||||
return rt_task_make_periodic(m_Task,start_time, period );
|
||||
}
|
||||
|
||||
int Task::make_periodic_relative(const Time& start_delay, const Time& period){
|
||||
return rt_task_make_periodic_relative_ns(m_Task,start_delay, period);
|
||||
}
|
||||
|
||||
void Task::set_runnable_on_cpus(unsigned int cpu_mask){
|
||||
rt_set_runnable_on_cpus(m_Task,cpu_mask);
|
||||
}
|
||||
|
||||
void Task::set_runnable_on_cpuid(unsigned int cpuid){
|
||||
rt_set_runnable_on_cpuid(m_Task,cpuid);
|
||||
}
|
||||
|
||||
void Task::wait_period(){
|
||||
rt_task_wait_period();
|
||||
}
|
||||
|
||||
void Task::busy_sleep(const Time& time){
|
||||
rt_busy_sleep((long long)time);
|
||||
}
|
||||
|
||||
void Task::sleep(const Count& delay){
|
||||
rt_sleep( delay );
|
||||
}
|
||||
|
||||
void Task::sleep_until(const Count& count){
|
||||
rt_sleep_until( count );
|
||||
}
|
||||
|
||||
int Task::use_fpu(bool use_fpu_flag){
|
||||
return rt_task_use_fpu(m_Task,use_fpu_flag);
|
||||
}
|
||||
|
||||
bool Task::is_valid(){
|
||||
return (m_Task != 0);
|
||||
}
|
||||
|
||||
void Task::inc_cpu_use(){
|
||||
m_CpuUse[ RTAI::hard_cpu_id() ]++;
|
||||
}
|
||||
|
||||
void Task::dump_cpu_use()
|
||||
{
|
||||
int cpuid;
|
||||
|
||||
// Output some statistics about CPU usage
|
||||
std::cerr << "\n\nCPU USE SUMMARY\n";
|
||||
for (cpuid = 0; cpuid < CONFIG_RTAI_CPUS; cpuid++) {
|
||||
std::cerr << "# " << cpuid << " -> " << m_CpuUse[ cpuid ] << std::endl;
|
||||
}
|
||||
std::cerr << "END OF CPU USE SUMMARY\n\n";
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
137
addons/cpp/task.h
Normal file
137
addons/cpp/task.h
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: task.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TASK_H__
|
||||
#define __TASK_H__
|
||||
|
||||
#include "rtai_config.h"
|
||||
#include "rtai.h"
|
||||
#include "rtai_sched.h"
|
||||
#include "time.h"
|
||||
#include "count.h"
|
||||
|
||||
|
||||
extern "C" void entry_point(int this_pointer);
|
||||
|
||||
extern "C" void signal_handler(void);
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
extern void get_global_lock(void);
|
||||
extern void release_global_lock(void);
|
||||
extern int hard_cpu_id(void);
|
||||
extern int assign_irq_to_cpu(int irq, unsigned long cpus_mask);
|
||||
extern int reset_irq_to_sym_mode(int irq);
|
||||
|
||||
extern void set_oneshot_mode(void);
|
||||
extern void set_periodic_mode(void);
|
||||
extern Count start_timer(void);
|
||||
extern Count start_timer(const Count& period);
|
||||
extern void stop_timer(void);
|
||||
|
||||
|
||||
extern void linux_use_fpu(bool use_fpu_flag);
|
||||
extern void preempt_always(bool yes_no);
|
||||
extern void preempt_always_cpuid(bool yes_no, unsigned int cpu_id);
|
||||
|
||||
|
||||
/**
|
||||
* Task wrapper class
|
||||
*/
|
||||
class Task {
|
||||
friend void entry_point(int this_pointer);
|
||||
public:
|
||||
Task();
|
||||
Task(int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid);
|
||||
|
||||
Task(const char* name,
|
||||
int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid);
|
||||
|
||||
Task(const char* name );
|
||||
|
||||
virtual ~Task();
|
||||
|
||||
virtual bool init(int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid);
|
||||
|
||||
virtual bool init(const char* name,
|
||||
int stack_size,
|
||||
int priority,
|
||||
bool uses_fpu,
|
||||
bool use_signal,
|
||||
unsigned int cpuid);
|
||||
|
||||
|
||||
virtual bool init(const char* name);
|
||||
#if 0
|
||||
static Task* self();
|
||||
#endif
|
||||
static void yield();
|
||||
void suspend();
|
||||
void resume();
|
||||
|
||||
virtual int make_periodic(const Count& start_time, const Count& period);
|
||||
virtual int make_periodic_relative(const Time& start_delay, const Time& period);
|
||||
static void wait_period();
|
||||
static void busy_sleep(const Time& time);
|
||||
static void sleep(const Count& delay);
|
||||
static void sleep_until(const Count& count);
|
||||
int use_fpu(bool use_fpu_flag);
|
||||
|
||||
void set_runnable_on_cpus(unsigned int cpu_mask);
|
||||
void set_runnable_on_cpuid(unsigned int cpuid);
|
||||
|
||||
virtual void signal_handler(){}
|
||||
virtual int run() = 0;
|
||||
|
||||
bool is_valid();
|
||||
|
||||
void inc_cpu_use();
|
||||
void dump_cpu_use();
|
||||
protected:
|
||||
int m_CpuUse[ CONFIG_RTAI_CPUS ];
|
||||
|
||||
bool m_Named;
|
||||
// true if this task object is the owner of the m_Task RT_TASK*
|
||||
bool m_TaskOwner;
|
||||
RT_TASK* m_Task;
|
||||
}; // class Task
|
||||
|
||||
// global functions inside RTAI:: namespace
|
||||
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
177
addons/cpp/tbx.cc
Normal file
177
addons/cpp/tbx.cc
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: tbx.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "tbx.h"
|
||||
#include "iostream.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
TypedMailbox::TypedMailbox()
|
||||
{
|
||||
rt_printk("TypedMailbox::TypedMailbox() %p\n",this);
|
||||
m_TypedMailbox = 0;
|
||||
m_Owner = true;
|
||||
m_Named = false;
|
||||
}
|
||||
|
||||
TypedMailbox::TypedMailbox(int size, int flags)
|
||||
{
|
||||
rt_printk("TypedMailbox::TypedMailbox( int size=%d, int flags=%d) %p\n",size,flags,this);
|
||||
m_TypedMailbox = 0;
|
||||
m_Owner = true;
|
||||
m_Named = false;
|
||||
|
||||
init( size , flags );
|
||||
}
|
||||
|
||||
TypedMailbox::TypedMailbox(const char* name)
|
||||
{
|
||||
m_TypedMailbox = 0;
|
||||
m_Named = true;
|
||||
m_Owner = false;
|
||||
|
||||
init( name );
|
||||
}
|
||||
|
||||
TypedMailbox::TypedMailbox(const char* name, int size, int flags)
|
||||
{
|
||||
m_TypedMailbox = 0;
|
||||
m_Named = true;
|
||||
m_Owner = true;
|
||||
init(name,size,flags);
|
||||
}
|
||||
|
||||
TypedMailbox::~TypedMailbox()
|
||||
{
|
||||
rt_printk("TypedMailbox::~TypedMailbox() %p\n",this);
|
||||
|
||||
if(m_TypedMailbox != 0){
|
||||
if( m_Owner ){
|
||||
if( m_Named ) {
|
||||
// nothing yet
|
||||
} else {
|
||||
rt_tbx_delete(m_TypedMailbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypedMailbox::init(int size, int flags )
|
||||
{
|
||||
rt_printk("TypedMailbox::init(int size=%d, int flags=%d) %p\n",size,flags,this);
|
||||
if(m_TypedMailbox == 0)
|
||||
rt_tbx_init(m_TypedMailbox, size,flags);
|
||||
}
|
||||
|
||||
void TypedMailbox::init(const char* name )
|
||||
{
|
||||
std::cerr << "TypedMailbox::init(name) NOT IMPLEMENTED" << std::endl;
|
||||
}
|
||||
|
||||
void TypedMailbox::init(const char* name, int size, int flags )
|
||||
{
|
||||
std::cerr << "TypedMailbox::init(name,size,flags) NOT IMPLEMENTED" << std::endl;
|
||||
}
|
||||
|
||||
int TypedMailbox::send( void *msg, int msg_size )
|
||||
{
|
||||
return rt_tbx_send( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::send_if( void *msg, int msg_size )
|
||||
{
|
||||
return rt_tbx_send_if( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::send_until( void *msg, int msg_size, const Count& time)
|
||||
{
|
||||
return rt_tbx_send_until( m_TypedMailbox, msg, msg_size, time );
|
||||
}
|
||||
|
||||
int TypedMailbox::send_timed( void *msg, int msg_size, const Count& delay)
|
||||
{
|
||||
return rt_tbx_send_timed( m_TypedMailbox, msg, msg_size, delay );
|
||||
}
|
||||
|
||||
int TypedMailbox::receive( void *msg, int msg_size)
|
||||
{
|
||||
return rt_tbx_receive( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::receive_if( void *msg, int msg_size)
|
||||
{
|
||||
return rt_tbx_receive_if( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::receive_until( void *msg, int msg_size, const Count& time)
|
||||
{
|
||||
return rt_tbx_receive_until( m_TypedMailbox, msg, msg_size, time );
|
||||
}
|
||||
|
||||
int TypedMailbox::receive_timed( void *msg, int msg_size, const Count& delay)
|
||||
{
|
||||
return rt_tbx_receive_timed( m_TypedMailbox, msg, msg_size, delay );
|
||||
}
|
||||
|
||||
int TypedMailbox::broadcast( void *msg, int msg_size)
|
||||
{
|
||||
return rt_tbx_broadcast( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::broadcast_if( void *msg, int msg_size)
|
||||
{
|
||||
return rt_tbx_broadcast_if( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::broadcast_until( void *msg, int msg_size, const Count& time)
|
||||
{
|
||||
return rt_tbx_broadcast_until( m_TypedMailbox, msg, msg_size, time);
|
||||
}
|
||||
|
||||
int TypedMailbox::broadcast_timed( void *msg, int msg_size, const Count& delay)
|
||||
{
|
||||
return rt_tbx_broadcast_timed( m_TypedMailbox, msg, msg_size, delay );
|
||||
}
|
||||
|
||||
int TypedMailbox::urgent( void *msg, int msg_size)
|
||||
{
|
||||
return rt_tbx_urgent( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::urgent_if( void *msg, int msg_size)
|
||||
{
|
||||
return rt_tbx_urgent_if( m_TypedMailbox, msg, msg_size );
|
||||
}
|
||||
|
||||
int TypedMailbox::urgent_until( void *msg, int msg_size, const Count& time)
|
||||
{
|
||||
return rt_tbx_urgent_until( m_TypedMailbox, msg, msg_size, time );
|
||||
}
|
||||
|
||||
int TypedMailbox::urgent_timed( void *msg, int msg_size, const Count& delay)
|
||||
{
|
||||
return rt_tbx_urgent_timed( m_TypedMailbox, msg, msg_size, delay );
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
159
addons/cpp/tbx.h
Normal file
159
addons/cpp/tbx.h
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: tbx.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TBX_H__
|
||||
#define __TBX_H__
|
||||
|
||||
#include "rtai.h"
|
||||
#include "rtai_tbx.h"
|
||||
#include "count.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Typed Mailbox wrapper class
|
||||
*/
|
||||
class TypedMailbox {
|
||||
public:
|
||||
TypedMailbox();
|
||||
TypedMailbox(int size, int flags);
|
||||
TypedMailbox(const char* name);
|
||||
TypedMailbox(const char* name, int size, int flags);
|
||||
|
||||
virtual ~TypedMailbox();
|
||||
|
||||
void init(int size, int flags );
|
||||
void init(const char* name );
|
||||
void init(const char* name, int size, int flags );
|
||||
|
||||
int send( void *msg, int msg_size );
|
||||
int send_if( void *msg, int msg_size );
|
||||
int send_until( void *msg, int msg_size, const Count& time);
|
||||
int send_timed( void *msg, int msg_size, const Count& delay);
|
||||
|
||||
int receive( void *msg, int msg_size);
|
||||
int receive_if( void *msg, int msg_size);
|
||||
int receive_until( void *msg, int msg_size, const Count& time);
|
||||
int receive_timed( void *msg, int msg_size, const Count& delay);
|
||||
|
||||
int broadcast( void *msg, int msg_size);
|
||||
int broadcast_if( void *msg, int msg_size);
|
||||
int broadcast_until( void *msg, int msg_size, const Count& time);
|
||||
int broadcast_timed( void *msg, int msg_size, const Count& delay);
|
||||
|
||||
int urgent( void *msg, int msg_size);
|
||||
int urgent_if( void *msg, int msg_size);
|
||||
int urgent_until( void *msg, int msg_size, const Count& time);
|
||||
int urgent_timed( void *msg, int msg_size, const Count& delay);
|
||||
protected:
|
||||
TBX* m_TypedMailbox;
|
||||
bool m_Owner;
|
||||
bool m_Named;
|
||||
private:
|
||||
TypedMailbox(const TypedMailbox&);
|
||||
TypedMailbox& operator=(const TypedMailbox&);
|
||||
};
|
||||
|
||||
/**
|
||||
* templated Typed Mailbox wrapper class
|
||||
*/
|
||||
template <class Type>
|
||||
class TypedMailboxT
|
||||
: public TypedMailbox
|
||||
{
|
||||
public:
|
||||
TypedMailboxT(){}
|
||||
TypedMailboxT(int size, int flags):TypedMailbox(size,flags){}
|
||||
TypedMailboxT(const char* name ):TypedMailbox(name){}
|
||||
TypedMailboxT(const char* name, int size, int flags ):TypedMailbox(name,size,flags){}
|
||||
|
||||
int send( Type *msg ){
|
||||
return TypedMailbox::send( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int send_if( Type *msg ){
|
||||
return TypedMailbox::send_if( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int send_until( Type *msg, const Count& time){
|
||||
return TypedMailbox::send_until( (void*)msg, sizeof( Type ), time );
|
||||
}
|
||||
|
||||
int send_timed( Type *msg, const Count& delay){
|
||||
return TypedMailbox::send_timed( (void*)msg, sizeof( Type ), delay );
|
||||
}
|
||||
|
||||
|
||||
int receive( Type *msg ){
|
||||
return TypedMailbox::receive( (void*)msg, sizeof( Type ));
|
||||
}
|
||||
|
||||
int receive_if( Type *msg ){
|
||||
return TypedMailbox::receive_if( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int receive_until( Type *msg, const Count& time){
|
||||
return TypedMailbox::receive_until( (void*)msg, sizeof( Type ), time );
|
||||
}
|
||||
|
||||
int receive_timed( Type *msg, const Count& delay){
|
||||
return TypedMailbox::receive_timed((void*)msg, sizeof( Type ), delay );
|
||||
}
|
||||
|
||||
int broadcast( Type *msg ){
|
||||
return TypedMailbox::broadcast( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int broadcast_if( Type *msg ){
|
||||
return TypedMailbox::broadcast_if( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int broadcast_until( Type *msg, const Count& time){
|
||||
return TypedMailbox::broadcast_until( (void*)msg, sizeof( Type ), time );
|
||||
}
|
||||
|
||||
int broadcast_timed( Type *msg, const Count& delay){
|
||||
return TypedMailbox::broadcast_timed( (void*)msg, sizeof( Type ), delay );
|
||||
}
|
||||
|
||||
int urgent( Type *msg ){
|
||||
return TypedMailbox::urgent( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int urgent_if( Type *msg ){
|
||||
return TypedMailbox::urgent_if( (void*)msg, sizeof( Type ) );
|
||||
}
|
||||
|
||||
int urgent_until( Type *msg, const Count& time){
|
||||
return TypedMailbox::urgent_until( (void*)msg, sizeof( Type ), time );
|
||||
}
|
||||
|
||||
int urgent_timed( Type *msg, const Count& delay){
|
||||
return TypedMailbox::urgent_timed( (void*)msg, sizeof( Type ), delay );
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
83
addons/cpp/tbx_init.c
Normal file
83
addons/cpp/tbx_init.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: tbx_init.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <rtai_tbx.h>
|
||||
#include <rtai_malloc.h>
|
||||
|
||||
TBX* __rt_tbx_init(int size, int flags)
|
||||
{
|
||||
TBX * tbx;
|
||||
|
||||
tbx = rt_malloc(sizeof(TBX));
|
||||
|
||||
if(tbx == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
memset(tbx,0,sizeof(TBX));
|
||||
|
||||
rt_tbx_init(tbx,size,flags);
|
||||
|
||||
return tbx;
|
||||
}
|
||||
|
||||
|
||||
int __rt_tbx_delete(TBX *tbx)
|
||||
{
|
||||
int result;
|
||||
|
||||
if(tbx == 0)
|
||||
return -1;
|
||||
|
||||
result = rt_tbx_delete(tbx);
|
||||
|
||||
rt_free(tbx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// RTAI-- MODULE INIT and CLEANUP functions
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("the RTAI-Team (contact person Erwin Rol)");
|
||||
MODULE_DESCRIPTION("RTAI C++ TBX support");
|
||||
|
||||
int __init rtai_cpp_tbx_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtai_cpp_tbx_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(rtai_cpp_tbx_init)
|
||||
module_exit(rtai_cpp_tbx_cleanup)
|
||||
|
||||
142
addons/cpp/time.cc
Normal file
142
addons/cpp/time.cc
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: time.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "time.h"
|
||||
#include "rtai_sched.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
Time::Time(){
|
||||
m_Time = 0;
|
||||
}
|
||||
|
||||
Time::Time(const Time& time)
|
||||
: m_Time(time.m_Time)
|
||||
{
|
||||
}
|
||||
|
||||
Time::Time(long long time)
|
||||
: m_Time(time)
|
||||
{
|
||||
}
|
||||
|
||||
Time& Time::operator=(const Time& time)
|
||||
{
|
||||
m_Time = time.m_Time;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Time& Time::operator=(long long time)
|
||||
{
|
||||
m_Time = time;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Time Time::now(){
|
||||
return Time( count2nano( rt_get_time() ) );
|
||||
}
|
||||
|
||||
Time Time::end(){
|
||||
return Time(0x7FFFFFFFFFFFFFFFLL);
|
||||
}
|
||||
|
||||
long long Time::to_count() const {
|
||||
return nano2count(m_Time);
|
||||
}
|
||||
|
||||
Time Time::from_count(long long count) {
|
||||
Time tmp( count2nano(count) );
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool Time::operator==(const Time& time) const
|
||||
{
|
||||
return m_Time == time.m_Time;
|
||||
}
|
||||
|
||||
bool Time::operator==(long long time) const
|
||||
{
|
||||
return m_Time == time;
|
||||
}
|
||||
|
||||
bool Time::operator<(const Time& time)const{
|
||||
return m_Time < time.m_Time;
|
||||
}
|
||||
|
||||
bool Time::operator>(const Time& time)const {
|
||||
return m_Time > time.m_Time;
|
||||
}
|
||||
|
||||
bool Time::operator<=(const Time& time)const{
|
||||
return m_Time <= time.m_Time;
|
||||
}
|
||||
|
||||
bool Time::operator>=(const Time& time)const {
|
||||
return m_Time >= time.m_Time;
|
||||
}
|
||||
|
||||
Time& Time::operator+=(const Time& time){
|
||||
m_Time += time.m_Time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Time& Time::operator+=(long long time) {
|
||||
m_Time += time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Time& Time::operator-=(const Time& time) {
|
||||
m_Time -= time.m_Time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Time& Time::operator-=(long long time){
|
||||
m_Time -= time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Time Time::operator+(const Time& time) const {
|
||||
Time tmp(m_Time + time.m_Time);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Time Time::operator+(long long time) const {
|
||||
Time tmp(m_Time + time);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Time Time::operator-(const Time& time) const {
|
||||
Time tmp(m_Time - time.m_Time);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Time Time::operator-(long long time) const {
|
||||
Time tmp(m_Time - time);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
124
addons/cpp/time.h
Normal file
124
addons/cpp/time.h
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: time.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "rtai.h"
|
||||
|
||||
#ifndef __TIME_H__
|
||||
#define __TIME_H__
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* time wrapper class
|
||||
*
|
||||
* Time keeps time in nanoseconds.
|
||||
*/
|
||||
class Time {
|
||||
public:
|
||||
/**
|
||||
* The count ticks
|
||||
*/
|
||||
typedef long long ticks;
|
||||
|
||||
/**
|
||||
* The time in nanoseconds
|
||||
*/
|
||||
typedef long long nsecs;
|
||||
|
||||
/**
|
||||
* Initialise a time instance denoting zero nanoseconds
|
||||
*/
|
||||
Time();
|
||||
|
||||
/**
|
||||
* Make a deep copy of a Time instance
|
||||
*/
|
||||
Time(const Time& time);
|
||||
/**
|
||||
* Initialise a time instance with <time>
|
||||
*
|
||||
* @param time The time in nanoseconds
|
||||
*/
|
||||
explicit Time(nsecs time);
|
||||
|
||||
Time& operator=(const Time& time);
|
||||
Time& operator=(nsecs time);
|
||||
|
||||
/**
|
||||
* Returns the current system time in nanoseconds
|
||||
*/
|
||||
static Time now();
|
||||
|
||||
/**
|
||||
* Returns the largest system time (==infinity)
|
||||
*/
|
||||
static Time end();
|
||||
|
||||
inline operator nsecs() const { return m_Time; }
|
||||
|
||||
/**
|
||||
* Converts this Time to internal system count units
|
||||
*/
|
||||
ticks to_count() const;
|
||||
|
||||
/**
|
||||
* Factory Method. Creates a time instance from
|
||||
* with a time converted from system count units
|
||||
* to nanoseconds
|
||||
*
|
||||
* @param The system time in count units
|
||||
*/
|
||||
static Time from_count(ticks count);
|
||||
|
||||
bool operator==(const Time& time) const;
|
||||
bool operator==(nsecs time) const;
|
||||
|
||||
inline bool operator!=(const Time& time) const { return !this->operator==(time); }
|
||||
inline bool operator!=(nsecs time) const { return !this->operator==(time); }
|
||||
|
||||
bool operator<(const Time& time)const;
|
||||
bool operator>(const Time& time)const;
|
||||
|
||||
bool operator<=(const Time& time)const;
|
||||
bool operator>=(const Time& time)const;
|
||||
|
||||
Time& operator+=(const Time& time);
|
||||
Time& operator+=(nsecs time);
|
||||
|
||||
Time& operator-=(const Time& time);
|
||||
Time& operator-=(nsecs time);
|
||||
|
||||
Time operator+(const Time& time) const;
|
||||
Time operator+(nsecs time) const;
|
||||
|
||||
Time operator-(const Time& time) const;
|
||||
Time operator-(nsecs time) const;
|
||||
protected:
|
||||
nsecs m_Time; // nanosecs
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
|
||||
81
addons/cpp/tld_key.c
Normal file
81
addons/cpp/tld_key.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: tld_key.c,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "tld_key.h"
|
||||
#include "rtai.h"
|
||||
|
||||
#if 0
|
||||
void __rt_get_global_lock(void){
|
||||
rt_get_global_lock();
|
||||
}
|
||||
|
||||
void __rt_release_global_lock(void){
|
||||
rt_release_global_lock();
|
||||
}
|
||||
|
||||
int __hard_cpu_id( void ){
|
||||
return hard_cpu_id();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int cpp_key;
|
||||
|
||||
// get a new key and mark it in tld_used_mask
|
||||
int __rt_tld_create_key(void){
|
||||
#if 1
|
||||
return 0;
|
||||
#else
|
||||
return rt_tld_create_key();
|
||||
#endif
|
||||
}
|
||||
|
||||
// free the bit in tld_used_mask
|
||||
int __rt_tld_free_key(int key){
|
||||
#if 1
|
||||
return 0;
|
||||
#else
|
||||
return rt_tld_free_key(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
// set the data in the currents RT_TASKS tld_data array
|
||||
int __rt_tld_set_data(RT_TASK *task,int key,void* data){
|
||||
#if 1
|
||||
task->system_data_ptr = (void*)data;
|
||||
return 0;
|
||||
#else
|
||||
return rt_tld_set_data(task,key,data);
|
||||
#endif
|
||||
}
|
||||
|
||||
// get the data from the current task
|
||||
void* __rt_tld_get_data(RT_TASK *task,int key){
|
||||
#if 1
|
||||
return (void*)task->system_data_ptr;
|
||||
#else
|
||||
return rt_tld_get_data(task,key);
|
||||
#endif
|
||||
}
|
||||
|
||||
55
addons/cpp/tld_key.h
Normal file
55
addons/cpp/tld_key.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: tld_key.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TLD_KEY_H__
|
||||
#define __TLD_KEY_H__
|
||||
|
||||
#include "rtai_sched.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int cpp_key;
|
||||
|
||||
#if 0
|
||||
void rt_get_global_lock(void);
|
||||
|
||||
void rt_release_global_lock(void);
|
||||
#endif
|
||||
|
||||
int __rt_tld_create_key(void);
|
||||
|
||||
int __rt_tld_free_key(int key);
|
||||
|
||||
int __rt_tld_set_data(RT_TASK *task,int key,void* data);
|
||||
|
||||
void * __rt_tld_get_data(RT_TASK *task,int key);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
61
addons/cpp/trace.cc
Normal file
61
addons/cpp/trace.cc
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: trace.cc,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
TraceEvent::TraceEvent()
|
||||
{
|
||||
m_ID = -1;
|
||||
}
|
||||
|
||||
TraceEvent::TraceEvent( const char* name, void* p1, void* p2)
|
||||
{
|
||||
init( name, p1, p2 );
|
||||
}
|
||||
|
||||
TraceEvent::~TraceEvent()
|
||||
{
|
||||
#ifdef CONFIG_RTAI_TRACE
|
||||
if( m_ID != -1 )
|
||||
__trace_destroy_event(m_ID);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TraceEvent::init( const char* name, void* p1, void* p2)
|
||||
{
|
||||
#ifdef CONFIG_RTAI_TRACE
|
||||
m_ID = __trace_create_event(name, p1, p2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TraceEvent::trigger( int size, void* data )
|
||||
{
|
||||
#ifdef CONFIG_RTAI_TRACE
|
||||
__trace_raw_event(m_ID, size, data );
|
||||
#endif
|
||||
}
|
||||
|
||||
}; // namespace RTAI
|
||||
73
addons/cpp/trace.h
Normal file
73
addons/cpp/trace.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: trace.h,v 1.4 2013/10/22 14:54:14 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TRACE_H__
|
||||
#define __TRACE_H__
|
||||
|
||||
#include <rtai_config.h>
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Trace toolkit wrapper class
|
||||
*/
|
||||
class TraceEvent
|
||||
{
|
||||
public:
|
||||
TraceEvent();
|
||||
TraceEvent( const char* name, void*, void* );
|
||||
~TraceEvent();
|
||||
|
||||
void init( const char* name, void*, void* );
|
||||
void trigger( int size, void* data );
|
||||
protected:
|
||||
int m_ID;
|
||||
};
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#ifndef CONFIG_RTAI_TRACE
|
||||
#warning included trace.h but no support in kernel for tracing
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void __trace_destroy_event(int id);
|
||||
|
||||
int __trace_create_event(const char *name,
|
||||
void *p1,
|
||||
void *p2);
|
||||
|
||||
int __trace_raw_event(int id,
|
||||
int size,
|
||||
void *p);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // CONFIG_RTAI_TRACE
|
||||
|
||||
#endif // __TRACE_H__
|
||||
|
||||
68
addons/cpp/watchdog.cc
Normal file
68
addons/cpp/watchdog.cc
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: watchdog.cc,v 1.4 2013/10/22 14:54:15 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "watchdog.h"
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
namespace Watchdog {
|
||||
|
||||
int set_grace(int new_value)
|
||||
{
|
||||
return rt_wdset_grace( new_value );
|
||||
}
|
||||
|
||||
int set_gracediv(int new_value)
|
||||
{
|
||||
return rt_wdset_gracediv( new_value );
|
||||
}
|
||||
|
||||
wd_policy set_policy(wd_policy new_value)
|
||||
{
|
||||
return rt_wdset_policy( new_value );
|
||||
}
|
||||
|
||||
int set_slip(int new_value)
|
||||
{
|
||||
return rt_wdset_slip( new_value );
|
||||
}
|
||||
|
||||
int set_stretch(int new_value)
|
||||
{
|
||||
return rt_wdset_stretch( new_value );
|
||||
}
|
||||
|
||||
int set_limit(int new_value)
|
||||
{
|
||||
return rt_wdset_limit( new_value );
|
||||
}
|
||||
|
||||
int set_safety(int new_value)
|
||||
{
|
||||
return rt_wdset_safety( new_value );
|
||||
}
|
||||
|
||||
}; // namespace Watchdog
|
||||
|
||||
}; // namespace RTAI
|
||||
57
addons/cpp/watchdog.h
Normal file
57
addons/cpp/watchdog.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: watchdog.h,v 1.4 2013/10/22 14:54:15 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __WATCHDOG_H__
|
||||
#define __WATCHDOG_H__
|
||||
|
||||
#include "rtai.h"
|
||||
#include "rtai_sched.h"
|
||||
#include "time.h"
|
||||
|
||||
extern "C" {
|
||||
#include "rtai_wd.h"
|
||||
}
|
||||
|
||||
|
||||
namespace RTAI {
|
||||
|
||||
/**
|
||||
* Watchdog namesapce
|
||||
*/
|
||||
namespace Watchdog
|
||||
{
|
||||
|
||||
int set_grace(int new_value);
|
||||
int set_gracediv(int new_value);
|
||||
wd_policy set_policy(wd_policy new_value);
|
||||
int set_slip(int new_value);
|
||||
int set_stretch(int new_value);
|
||||
int set_limit(int new_value);
|
||||
int set_safety(int new_value);
|
||||
|
||||
}; // namespace Watchdog
|
||||
|
||||
}; // namespace RTAI
|
||||
|
||||
#endif
|
||||
51
addons/cpp/watchdog_init.c
Normal file
51
addons/cpp/watchdog_init.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Project: rtai_cpp - RTAI C++ Framework
|
||||
*
|
||||
* File: $Id: watchdog_init.c,v 1.4 2013/10/22 14:54:15 ando Exp $
|
||||
*
|
||||
* Copyright: (C) 2001,2002 Erwin Rol <erwin@muffin.org>
|
||||
*
|
||||
* Licence:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <rtai_malloc.h>
|
||||
#include <rtai.h>
|
||||
|
||||
// RTAI-- MODULE INIT and CLEANUP functions
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("the RTAI-Team (contact person Erwin Rol)");
|
||||
MODULE_DESCRIPTION("RTAI C++ Watchdog support");
|
||||
|
||||
int __init rtai_cpp_watchdog_init(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtai_cpp_watchdog_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(rtai_cpp_watchdog_init)
|
||||
module_exit(rtai_cpp_watchdog_cleanup)
|
||||
|
||||
1206
addons/drivers/16550A/16550A.c
Normal file
1206
addons/drivers/16550A/16550A.c
Normal file
File diff suppressed because it is too large
Load diff
213
addons/drivers/16550A/16550A_io.h
Normal file
213
addons/drivers/16550A/16550A_io.h
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Jan Kiszka <jan.kiszka@web.de>.
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Manages the I/O access method of the driver. */
|
||||
|
||||
|
||||
typedef enum { MODE_PIO, MODE_MMIO } io_mode_t;
|
||||
|
||||
#if defined(CONFIG_RTAI_16550A_PIO) || \
|
||||
defined(CONFIG_RTAI_16550A_ANY)
|
||||
static unsigned long io[MAX_DEVICES];
|
||||
compat_module_param_array(io, ulong, MAX_DEVICES, 0400);
|
||||
MODULE_PARM_DESC(io, "I/O port addresses of the serial devices");
|
||||
#endif /* CONFIG_RTAI_16550A_PIO || CONFIG_RTAI_16550A_ANY */
|
||||
|
||||
#if defined(CONFIG_RTAI_16550A_MMIO) || \
|
||||
defined(CONFIG_RTAI_16550A_ANY)
|
||||
static unsigned long mem[MAX_DEVICES];
|
||||
static void *mapped_io[MAX_DEVICES];
|
||||
compat_module_param_array(mem, ulong, MAX_DEVICES, 0400);
|
||||
MODULE_PARM_DESC(mem, "I/O memory addresses of the serial devices");
|
||||
#endif /* CONFIG_RTAI_16550A_MMIO || CONFIG_RTAI_16550A_ANY */
|
||||
|
||||
#ifdef CONFIG_RTAI_16550A_PIO
|
||||
|
||||
#define RT_16550_IO_INLINE inline
|
||||
|
||||
extern void *mapped_io[]; /* dummy */
|
||||
|
||||
static inline unsigned long rt_16550_addr_param(int dev_id)
|
||||
{
|
||||
return io[dev_id];
|
||||
}
|
||||
|
||||
static inline int rt_16550_addr_param_valid(int dev_id)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline unsigned long rt_16550_base_addr(int dev_id)
|
||||
{
|
||||
return io[dev_id];
|
||||
}
|
||||
|
||||
static inline io_mode_t rt_16550_io_mode(int dev_id)
|
||||
{
|
||||
return MODE_PIO;
|
||||
}
|
||||
|
||||
static inline io_mode_t
|
||||
rt_16550_io_mode_from_ctx(struct rt_16550_context *ctx)
|
||||
{
|
||||
return MODE_PIO;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rt_16550_init_io_ctx(int dev_id, struct rt_16550_context *ctx)
|
||||
{
|
||||
ctx->base_addr = io[dev_id];
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_RTAI_16550A_MMIO)
|
||||
|
||||
#define RT_16550_IO_INLINE inline
|
||||
|
||||
extern unsigned long io[]; /* dummy */
|
||||
|
||||
static inline unsigned long rt_16550_addr_param(int dev_id)
|
||||
{
|
||||
return mem[dev_id];
|
||||
}
|
||||
|
||||
static inline int rt_16550_addr_param_valid(int dev_id)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline unsigned long rt_16550_base_addr(int dev_id)
|
||||
{
|
||||
return (unsigned long)mapped_io[dev_id];
|
||||
}
|
||||
|
||||
static inline io_mode_t rt_16550_io_mode(int dev_id)
|
||||
{
|
||||
return MODE_MMIO;
|
||||
}
|
||||
|
||||
static inline io_mode_t
|
||||
rt_16550_io_mode_from_ctx(struct rt_16550_context *ctx)
|
||||
{
|
||||
return MODE_MMIO;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rt_16550_init_io_ctx(int dev_id, struct rt_16550_context *ctx)
|
||||
{
|
||||
ctx->base_addr = (unsigned long)mapped_io[dev_id];
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_RTAI_16550A_ANY)
|
||||
|
||||
#define RT_16550_IO_INLINE /* uninline */
|
||||
|
||||
static inline unsigned long rt_16550_addr_param(int dev_id)
|
||||
{
|
||||
return (io[dev_id]) ? io[dev_id] : mem[dev_id];
|
||||
}
|
||||
|
||||
static inline int rt_16550_addr_param_valid(int dev_id)
|
||||
{
|
||||
return !(io[dev_id] && mem[dev_id]);
|
||||
}
|
||||
|
||||
static inline unsigned long rt_16550_base_addr(int dev_id)
|
||||
{
|
||||
return (io[dev_id]) ? io[dev_id] : (unsigned long)mapped_io[dev_id];
|
||||
}
|
||||
|
||||
static inline io_mode_t rt_16550_io_mode(int dev_id)
|
||||
{
|
||||
return (io[dev_id]) ? MODE_PIO : MODE_MMIO;
|
||||
}
|
||||
|
||||
static inline io_mode_t
|
||||
rt_16550_io_mode_from_ctx(struct rt_16550_context *ctx)
|
||||
{
|
||||
return ctx->io_mode;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rt_16550_init_io_ctx(int dev_id, struct rt_16550_context *ctx)
|
||||
{
|
||||
if (io[dev_id]) {
|
||||
ctx->base_addr = io[dev_id];
|
||||
ctx->io_mode = MODE_PIO;
|
||||
} else {
|
||||
ctx->base_addr = (unsigned long)mapped_io[dev_id];
|
||||
ctx->io_mode = MODE_MMIO;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
# error Unsupported I/O access method
|
||||
#endif
|
||||
|
||||
static RT_16550_IO_INLINE u8
|
||||
rt_16550_reg_in(io_mode_t io_mode, unsigned long base, int off)
|
||||
{
|
||||
switch (io_mode) {
|
||||
case MODE_PIO:
|
||||
return inb(base + off);
|
||||
default: /* MODE_MMIO */
|
||||
return readb((void *)base + off);
|
||||
}
|
||||
}
|
||||
|
||||
static RT_16550_IO_INLINE void
|
||||
rt_16550_reg_out(io_mode_t io_mode, unsigned long base, int off, u8 val)
|
||||
{
|
||||
switch (io_mode) {
|
||||
case MODE_PIO:
|
||||
outb(val, base + off);
|
||||
break;
|
||||
case MODE_MMIO:
|
||||
writeb(val, (void *)base + off);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rt_16550_init_io(int dev_id, char* name)
|
||||
{
|
||||
switch (rt_16550_io_mode(dev_id)) {
|
||||
case MODE_PIO:
|
||||
if (!request_region(rt_16550_addr_param(dev_id), 8, name))
|
||||
return -EBUSY;
|
||||
break;
|
||||
case MODE_MMIO:
|
||||
mapped_io[dev_id] = ioremap(rt_16550_addr_param(dev_id), 8);
|
||||
if (!mapped_io[dev_id])
|
||||
return -EBUSY;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rt_16550_release_io(int dev_id)
|
||||
{
|
||||
switch (rt_16550_io_mode(dev_id)) {
|
||||
case MODE_PIO:
|
||||
release_region(io[dev_id], 8);
|
||||
break;
|
||||
case MODE_MMIO:
|
||||
iounmap(mapped_io[dev_id]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
288
addons/drivers/16550A/16550A_pci.h
Normal file
288
addons/drivers/16550A/16550A_pci.h
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2007 Jan Kiszka <jan.kiszka@web.de>.
|
||||
* Copyright (C) 2011 Stefan Kisdaroczi <kisda@hispeed.ch>.
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* Rtai is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Rtai is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Rtai; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_RTAI_DRIVERS_16550A_PCI)
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
struct rt_16550_pci_board {
|
||||
char *name;
|
||||
resource_size_t resource_base_addr;
|
||||
unsigned int nports;
|
||||
unsigned int port_ofs;
|
||||
unsigned long irqtype;
|
||||
unsigned int baud_base;
|
||||
int tx_fifo;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_RTAI_DRIVERS_16550A_PCI_MOXA)
|
||||
|
||||
#define PCI_DEVICE_ID_CP112UL 0x1120
|
||||
#define PCI_DEVICE_ID_CP114UL 0x1143
|
||||
#define PCI_DEVICE_ID_CP138U 0x1380
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_c104 = {
|
||||
.name = "Moxa C104H/PCI",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 4,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_c168 = {
|
||||
.name = "Moxa C168H/PCI",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 8,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp114 = {
|
||||
.name = "Moxa CP-114",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 4,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp132 = {
|
||||
.name = "Moxa CP-132",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 2,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp102u = {
|
||||
.name = "Moxa CP-102U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 2,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp102ul = {
|
||||
.name = "Moxa CP-102UL",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 2,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp104u = {
|
||||
.name = "Moxa CP-104U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 4,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp112ul = {
|
||||
.name = "Moxa CP-112UL",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 2,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp114ul = {
|
||||
.name = "Moxa CP-114UL",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 4,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp118u = {
|
||||
.name = "Moxa CP-118U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 8,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp132u = {
|
||||
.name = "Moxa CP-132U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 2,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp134u = {
|
||||
.name = "Moxa CP-134U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 4,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp138u = {
|
||||
.name = "Moxa CP-138U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 8,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
|
||||
static const struct rt_16550_pci_board rt_16550_moxa_cp168u = {
|
||||
.name = "Moxa CP-168U",
|
||||
.resource_base_addr = 2,
|
||||
.nports = 8,
|
||||
.port_ofs = 8,
|
||||
.baud_base = 921600,
|
||||
.tx_fifo = 16,
|
||||
.irqtype = RTDM_IRQTYPE_SHARED,
|
||||
};
|
||||
#endif
|
||||
|
||||
DEFINE_PCI_DEVICE_TABLE( rt_16550_pci_table ) = {
|
||||
#if defined(CONFIG_RTAI_DRIVERS_16550A_PCI_MOXA)
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_c104},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_c168},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp114},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp132},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp102u},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp102ul},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp104u},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp112ul},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp114ul},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp118u},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp132u},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp134u},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp138u},
|
||||
{PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U),
|
||||
.driver_data = (unsigned long)&rt_16550_moxa_cp168u},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
static int rt_16550_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct rt_16550_pci_board *board;
|
||||
int err;
|
||||
int i;
|
||||
int port = 0;
|
||||
int base_addr;
|
||||
int max_devices = 0;
|
||||
|
||||
if (!ent->driver_data)
|
||||
return -ENODEV;
|
||||
|
||||
board = (struct rt_16550_pci_board *)ent->driver_data;
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i++)
|
||||
if (!rt_16550_addr_param(i))
|
||||
max_devices++;
|
||||
|
||||
if (board->nports > max_devices)
|
||||
return -ENODEV;
|
||||
|
||||
if ((err = pci_enable_device(pdev)))
|
||||
return err;
|
||||
|
||||
base_addr = pci_resource_start(pdev, board->resource_base_addr);
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i++) {
|
||||
if ((port < board->nports) && (!rt_16550_addr_param(i))) {
|
||||
io[i] = base_addr + port * board->port_ofs;
|
||||
irq[i] = pdev->irq;
|
||||
irqtype[i] = board->irqtype;
|
||||
baud_base[i] = board->baud_base;
|
||||
tx_fifo[i] = board->tx_fifo;
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rt_16550_pci_remove(struct pci_dev *pdev) {
|
||||
pci_disable_device( pdev );
|
||||
};
|
||||
|
||||
static struct pci_driver rt_16550_pci_driver = {
|
||||
.name = RT_16550_DRIVER_NAME,
|
||||
.id_table = rt_16550_pci_table,
|
||||
.probe = rt_16550_pci_probe,
|
||||
.remove = rt_16550_pci_remove
|
||||
};
|
||||
|
||||
static int pci_registered;
|
||||
|
||||
static inline void rt_16550_pci_init(void)
|
||||
{
|
||||
if (pci_register_driver(&rt_16550_pci_driver) == 0)
|
||||
pci_registered = 1;
|
||||
}
|
||||
|
||||
static inline void rt_16550_pci_cleanup(void)
|
||||
{
|
||||
if (pci_registered)
|
||||
pci_unregister_driver(&rt_16550_pci_driver);
|
||||
}
|
||||
|
||||
#else /* Linux < 2.6.0 || !CONFIG_PCI || !(..._16550A_PCI */
|
||||
|
||||
#define rt_16550_pci_init() do { } while (0)
|
||||
#define rt_16550_pci_cleanup() do { } while (0)
|
||||
|
||||
#endif /* Linux < 2.6.0 || !CONFIG_PCI || !(..._16550A_PCI */
|
||||
389
addons/drivers/16550A/16550A_pnp.h
Normal file
389
addons/drivers/16550A/16550A_pnp.h
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2007 Jan Kiszka <jan.kiszka@web.de>.
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && defined(CONFIG_PNP) && \
|
||||
(defined(CONFIG_RTAI_16550A_PIO) || \
|
||||
defined(CONFIG_RTAI_16550A_ANY))
|
||||
|
||||
#include <linux/pnp.h>
|
||||
|
||||
#define UNKNOWN_DEV 0x3000
|
||||
|
||||
/* Bluntly cloned from drivers/serial/8250_pnp.c */
|
||||
static const struct pnp_device_id rt_16550_pnp_tbl[] = {
|
||||
/* Archtek America Corp. */
|
||||
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
||||
{ "AAC000F", 0 },
|
||||
/* Anchor Datacomm BV */
|
||||
/* SXPro 144 External Data Fax Modem Plug & Play */
|
||||
{ "ADC0001", 0 },
|
||||
/* SXPro 288 External Data Fax Modem Plug & Play */
|
||||
{ "ADC0002", 0 },
|
||||
/* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
|
||||
{ "AEI0250", 0 },
|
||||
/* Actiontec ISA PNP 56K X2 Fax Modem */
|
||||
{ "AEI1240", 0 },
|
||||
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
||||
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
|
||||
/* AZT3005 PnP SOUND DEVICE */
|
||||
{ "AZT4001", 0 },
|
||||
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||
{ "BDP3336", 0 },
|
||||
/* Boca Research */
|
||||
/* Boca Complete Ofc Communicator 14.4 Data-FAX */
|
||||
{ "BRI0A49", 0 },
|
||||
/* Boca Research 33,600 ACF Modem */
|
||||
{ "BRI1400", 0 },
|
||||
/* Boca 33.6 Kbps Internal FD34FSVD */
|
||||
{ "BRI3400", 0 },
|
||||
/* Boca 33.6 Kbps Internal FD34FSVD */
|
||||
{ "BRI0A49", 0 },
|
||||
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||
{ "BDP3336", 0 },
|
||||
/* Computer Peripherals Inc */
|
||||
/* EuroViVa CommCenter-33.6 SP PnP */
|
||||
{ "CPI4050", 0 },
|
||||
/* Creative Labs */
|
||||
/* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
|
||||
{ "CTL3001", 0 },
|
||||
/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
|
||||
{ "CTL3011", 0 },
|
||||
/* Creative */
|
||||
/* Creative Modem Blaster Flash56 DI5601-1 */
|
||||
{ "DMB1032", 0 },
|
||||
/* Creative Modem Blaster V.90 DI5660 */
|
||||
{ "DMB2001", 0 },
|
||||
/* E-Tech */
|
||||
/* E-Tech CyberBULLET PC56RVP */
|
||||
{ "ETT0002", 0 },
|
||||
/* FUJITSU */
|
||||
/* Fujitsu 33600 PnP-I2 R Plug & Play */
|
||||
{ "FUJ0202", 0 },
|
||||
/* Fujitsu FMV-FX431 Plug & Play */
|
||||
{ "FUJ0205", 0 },
|
||||
/* Fujitsu 33600 PnP-I4 R Plug & Play */
|
||||
{ "FUJ0206", 0 },
|
||||
/* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
|
||||
{ "FUJ0209", 0 },
|
||||
/* Archtek America Corp. */
|
||||
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
||||
{ "GVC000F", 0 },
|
||||
/* Hayes */
|
||||
/* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
|
||||
{ "HAY0001", 0 },
|
||||
/* Hayes Optima 336 V.34 + FAX + Voice PnP */
|
||||
{ "HAY000C", 0 },
|
||||
/* Hayes Optima 336B V.34 + FAX + Voice PnP */
|
||||
{ "HAY000D", 0 },
|
||||
/* Hayes Accura 56K Ext Fax Modem PnP */
|
||||
{ "HAY5670", 0 },
|
||||
/* Hayes Accura 56K Ext Fax Modem PnP */
|
||||
{ "HAY5674", 0 },
|
||||
/* Hayes Accura 56K Fax Modem PnP */
|
||||
{ "HAY5675", 0 },
|
||||
/* Hayes 288, V.34 + FAX */
|
||||
{ "HAYF000", 0 },
|
||||
/* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
|
||||
{ "HAYF001", 0 },
|
||||
/* IBM */
|
||||
/* IBM Thinkpad 701 Internal Modem Voice */
|
||||
{ "IBM0033", 0 },
|
||||
/* Intertex */
|
||||
/* Intertex 28k8 33k6 Voice EXT PnP */
|
||||
{ "IXDC801", 0 },
|
||||
/* Intertex 33k6 56k Voice EXT PnP */
|
||||
{ "IXDC901", 0 },
|
||||
/* Intertex 28k8 33k6 Voice SP EXT PnP */
|
||||
{ "IXDD801", 0 },
|
||||
/* Intertex 33k6 56k Voice SP EXT PnP */
|
||||
{ "IXDD901", 0 },
|
||||
/* Intertex 28k8 33k6 Voice SP INT PnP */
|
||||
{ "IXDF401", 0 },
|
||||
/* Intertex 28k8 33k6 Voice SP EXT PnP */
|
||||
{ "IXDF801", 0 },
|
||||
/* Intertex 33k6 56k Voice SP EXT PnP */
|
||||
{ "IXDF901", 0 },
|
||||
/* Kortex International */
|
||||
/* KORTEX 28800 Externe PnP */
|
||||
{ "KOR4522", 0 },
|
||||
/* KXPro 33.6 Vocal ASVD PnP */
|
||||
{ "KORF661", 0 },
|
||||
/* Lasat */
|
||||
/* LASAT Internet 33600 PnP */
|
||||
{ "LAS4040", 0 },
|
||||
/* Lasat Safire 560 PnP */
|
||||
{ "LAS4540", 0 },
|
||||
/* Lasat Safire 336 PnP */
|
||||
{ "LAS5440", 0 },
|
||||
/* Microcom, Inc. */
|
||||
/* Microcom TravelPorte FAST V.34 Plug & Play */
|
||||
{ "MNP0281", 0 },
|
||||
/* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
|
||||
{ "MNP0336", 0 },
|
||||
/* Microcom DeskPorte FAST EP 28.8 Plug & Play */
|
||||
{ "MNP0339", 0 },
|
||||
/* Microcom DeskPorte 28.8P Plug & Play */
|
||||
{ "MNP0342", 0 },
|
||||
/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
|
||||
{ "MNP0500", 0 },
|
||||
/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
|
||||
{ "MNP0501", 0 },
|
||||
/* Microcom DeskPorte 28.8S Internal Plug & Play */
|
||||
{ "MNP0502", 0 },
|
||||
/* Motorola */
|
||||
/* Motorola BitSURFR Plug & Play */
|
||||
{ "MOT1105", 0 },
|
||||
/* Motorola TA210 Plug & Play */
|
||||
{ "MOT1111", 0 },
|
||||
/* Motorola HMTA 200 (ISDN) Plug & Play */
|
||||
{ "MOT1114", 0 },
|
||||
/* Motorola BitSURFR Plug & Play */
|
||||
{ "MOT1115", 0 },
|
||||
/* Motorola Lifestyle 28.8 Internal */
|
||||
{ "MOT1190", 0 },
|
||||
/* Motorola V.3400 Plug & Play */
|
||||
{ "MOT1501", 0 },
|
||||
/* Motorola Lifestyle 28.8 V.34 Plug & Play */
|
||||
{ "MOT1502", 0 },
|
||||
/* Motorola Power 28.8 V.34 Plug & Play */
|
||||
{ "MOT1505", 0 },
|
||||
/* Motorola ModemSURFR External 28.8 Plug & Play */
|
||||
{ "MOT1509", 0 },
|
||||
/* Motorola Premier 33.6 Desktop Plug & Play */
|
||||
{ "MOT150A", 0 },
|
||||
/* Motorola VoiceSURFR 56K External PnP */
|
||||
{ "MOT150F", 0 },
|
||||
/* Motorola ModemSURFR 56K External PnP */
|
||||
{ "MOT1510", 0 },
|
||||
/* Motorola ModemSURFR 56K Internal PnP */
|
||||
{ "MOT1550", 0 },
|
||||
/* Motorola ModemSURFR Internal 28.8 Plug & Play */
|
||||
{ "MOT1560", 0 },
|
||||
/* Motorola Premier 33.6 Internal Plug & Play */
|
||||
{ "MOT1580", 0 },
|
||||
/* Motorola OnlineSURFR 28.8 Internal Plug & Play */
|
||||
{ "MOT15B0", 0 },
|
||||
/* Motorola VoiceSURFR 56K Internal PnP */
|
||||
{ "MOT15F0", 0 },
|
||||
/* Com 1 */
|
||||
/* Deskline K56 Phone System PnP */
|
||||
{ "MVX00A1", 0 },
|
||||
/* PC Rider K56 Phone System PnP */
|
||||
{ "MVX00F2", 0 },
|
||||
/* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
|
||||
{ "nEC8241", 0 },
|
||||
/* Pace 56 Voice Internal Plug & Play Modem */
|
||||
{ "PMC2430", 0 },
|
||||
/* Generic */
|
||||
/* Generic standard PC COM port */
|
||||
{ "PNP0500", 0 },
|
||||
/* Generic 16550A-compatible COM port */
|
||||
{ "PNP0501", 0 },
|
||||
/* Compaq 14400 Modem */
|
||||
{ "PNPC000", 0 },
|
||||
/* Compaq 2400/9600 Modem */
|
||||
{ "PNPC001", 0 },
|
||||
/* Dial-Up Networking Serial Cable between 2 PCs */
|
||||
{ "PNPC031", 0 },
|
||||
/* Dial-Up Networking Parallel Cable between 2 PCs */
|
||||
{ "PNPC032", 0 },
|
||||
/* Standard 9600 bps Modem */
|
||||
{ "PNPC100", 0 },
|
||||
/* Standard 14400 bps Modem */
|
||||
{ "PNPC101", 0 },
|
||||
/* Standard 28800 bps Modem*/
|
||||
{ "PNPC102", 0 },
|
||||
/* Standard Modem*/
|
||||
{ "PNPC103", 0 },
|
||||
/* Standard 9600 bps Modem*/
|
||||
{ "PNPC104", 0 },
|
||||
/* Standard 14400 bps Modem*/
|
||||
{ "PNPC105", 0 },
|
||||
/* Standard 28800 bps Modem*/
|
||||
{ "PNPC106", 0 },
|
||||
/* Standard Modem */
|
||||
{ "PNPC107", 0 },
|
||||
/* Standard 9600 bps Modem */
|
||||
{ "PNPC108", 0 },
|
||||
/* Standard 14400 bps Modem */
|
||||
{ "PNPC109", 0 },
|
||||
/* Standard 28800 bps Modem */
|
||||
{ "PNPC10A", 0 },
|
||||
/* Standard Modem */
|
||||
{ "PNPC10B", 0 },
|
||||
/* Standard 9600 bps Modem */
|
||||
{ "PNPC10C", 0 },
|
||||
/* Standard 14400 bps Modem */
|
||||
{ "PNPC10D", 0 },
|
||||
/* Standard 28800 bps Modem */
|
||||
{ "PNPC10E", 0 },
|
||||
/* Standard Modem */
|
||||
{ "PNPC10F", 0 },
|
||||
/* Standard PCMCIA Card Modem */
|
||||
{ "PNP2000", 0 },
|
||||
/* Rockwell */
|
||||
/* Modular Technology */
|
||||
/* Rockwell 33.6 DPF Internal PnP */
|
||||
/* Modular Technology 33.6 Internal PnP */
|
||||
{ "ROK0030", 0 },
|
||||
/* Kortex International */
|
||||
/* KORTEX 14400 Externe PnP */
|
||||
{ "ROK0100", 0 },
|
||||
/* Rockwell 28.8 */
|
||||
{ "ROK4120", 0 },
|
||||
/* Viking Components, Inc */
|
||||
/* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
|
||||
{ "ROK4920", 0 },
|
||||
/* Rockwell */
|
||||
/* British Telecom */
|
||||
/* Modular Technology */
|
||||
/* Rockwell 33.6 DPF External PnP */
|
||||
/* BT Prologue 33.6 External PnP */
|
||||
/* Modular Technology 33.6 External PnP */
|
||||
{ "RSS00A0", 0 },
|
||||
/* Viking 56K FAX INT */
|
||||
{ "RSS0262", 0 },
|
||||
/* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
|
||||
{ "RSS0250", 0 },
|
||||
/* SupraExpress 28.8 Data/Fax PnP modem */
|
||||
{ "SUP1310", 0 },
|
||||
/* SupraExpress 33.6 Data/Fax PnP modem */
|
||||
{ "SUP1421", 0 },
|
||||
/* SupraExpress 33.6 Data/Fax PnP modem */
|
||||
{ "SUP1590", 0 },
|
||||
/* SupraExpress 336i Sp ASVD */
|
||||
{ "SUP1620", 0 },
|
||||
/* SupraExpress 33.6 Data/Fax PnP modem */
|
||||
{ "SUP1760", 0 },
|
||||
/* SupraExpress 56i Sp Intl */
|
||||
{ "SUP2171", 0 },
|
||||
/* Phoebe Micro */
|
||||
/* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
|
||||
{ "TEX0011", 0 },
|
||||
/* Archtek America Corp. */
|
||||
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
||||
{ "UAC000F", 0 },
|
||||
/* 3Com Corp. */
|
||||
/* Gateway Telepath IIvi 33.6 */
|
||||
{ "USR0000", 0 },
|
||||
/* U.S. Robotics Sporster 33.6K Fax INT PnP */
|
||||
{ "USR0002", 0 },
|
||||
/* Sportster Vi 14.4 PnP FAX Voicemail */
|
||||
{ "USR0004", 0 },
|
||||
/* U.S. Robotics 33.6K Voice INT PnP */
|
||||
{ "USR0006", 0 },
|
||||
/* U.S. Robotics 33.6K Voice EXT PnP */
|
||||
{ "USR0007", 0 },
|
||||
/* U.S. Robotics Courier V.Everything INT PnP */
|
||||
{ "USR0009", 0 },
|
||||
/* U.S. Robotics 33.6K Voice INT PnP */
|
||||
{ "USR2002", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP */
|
||||
{ "USR2070", 0 },
|
||||
/* U.S. Robotics 56K Voice EXT PnP */
|
||||
{ "USR2080", 0 },
|
||||
/* U.S. Robotics 56K FAX INT */
|
||||
{ "USR3031", 0 },
|
||||
/* U.S. Robotics 56K FAX INT */
|
||||
{ "USR3050", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP */
|
||||
{ "USR3070", 0 },
|
||||
/* U.S. Robotics 56K Voice EXT PnP */
|
||||
{ "USR3080", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP */
|
||||
{ "USR3090", 0 },
|
||||
/* U.S. Robotics 56K Message */
|
||||
{ "USR9100", 0 },
|
||||
/* U.S. Robotics 56K FAX EXT PnP*/
|
||||
{ "USR9160", 0 },
|
||||
/* U.S. Robotics 56K FAX INT PnP*/
|
||||
{ "USR9170", 0 },
|
||||
/* U.S. Robotics 56K Voice EXT PnP*/
|
||||
{ "USR9180", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP*/
|
||||
{ "USR9190", 0 },
|
||||
/* Wacom tablets */
|
||||
{ "WACF004", 0 },
|
||||
{ "WACF005", 0 },
|
||||
{ "WACF006", 0 },
|
||||
/* Compaq touchscreen */
|
||||
{ "FPI2002", 0 },
|
||||
/* Fujitsu Stylistic touchscreens */
|
||||
{ "FUJ02B2", 0 },
|
||||
{ "FUJ02B3", 0 },
|
||||
/* Fujitsu Stylistic LT touchscreens */
|
||||
{ "FUJ02B4", 0 },
|
||||
/* Passive Fujitsu Stylistic touchscreens */
|
||||
{ "FUJ02B6", 0 },
|
||||
{ "FUJ02B7", 0 },
|
||||
{ "FUJ02B8", 0 },
|
||||
{ "FUJ02B9", 0 },
|
||||
{ "FUJ02BC", 0 },
|
||||
/* Rockwell's (PORALiNK) 33600 INT PNP */
|
||||
{ "WCI0003", 0 },
|
||||
/* Unkown PnP modems */
|
||||
{ "PNPCXXX", UNKNOWN_DEV },
|
||||
/* More unkown PnP modems */
|
||||
{ "PNPDXXX", UNKNOWN_DEV },
|
||||
{ "", 0 }
|
||||
};
|
||||
|
||||
static int rt_16550_pnp_probe(struct pnp_dev *dev,
|
||||
const struct pnp_device_id *dev_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i++)
|
||||
if (pnp_port_valid(dev, 0) &&
|
||||
pnp_port_start(dev, 0) == io[i]) {
|
||||
if (!irq[i])
|
||||
irq[i] = pnp_irq(dev, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct pnp_driver rt_16550_pnp_driver = {
|
||||
.name = RT_16550_DRIVER_NAME,
|
||||
.id_table = rt_16550_pnp_tbl,
|
||||
.probe = rt_16550_pnp_probe,
|
||||
};
|
||||
|
||||
static int pnp_registered;
|
||||
|
||||
static inline void rt_16550_pnp_init(void)
|
||||
{
|
||||
if (pnp_register_driver(&rt_16550_pnp_driver) == 0)
|
||||
pnp_registered = 1;
|
||||
}
|
||||
|
||||
static inline void rt_16550_pnp_cleanup(void)
|
||||
{
|
||||
if (pnp_registered)
|
||||
pnp_unregister_driver(&rt_16550_pnp_driver);
|
||||
}
|
||||
|
||||
#else /* Linux < 2.6.0 || !CONFIG_PNP || !(..._16550A_IO || ..._16550A_ANY) */
|
||||
|
||||
#define rt_16550_pnp_init() do { } while (0)
|
||||
#define rt_16550_pnp_cleanup() do { } while (0)
|
||||
|
||||
#endif /* Linux < 2.6.0 || !CONFIG_PNP || !(..._16550A_IO || ..._16550A_ANY) */
|
||||
57
addons/drivers/16550A/GNUmakefile.am
Normal file
57
addons/drivers/16550A/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
moduledir = @RTAI_MODULE_DIR@
|
||||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
CROSS_COMPILE = @CROSS_COMPILE@
|
||||
|
||||
lib16550A_a_SOURCES = 16550A.c
|
||||
|
||||
distfiles = $(lib16550A_a_SOURCES)
|
||||
|
||||
if CONFIG_KBUILD
|
||||
rtai_16550A$(modext): @RTAI_KBUILD_ENV@
|
||||
rtai_16550A$(modext): $(lib16550A_a_SOURCES) FORCE
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ rtai_extradef="@RTAI_KMOD_CFLAGS@" \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
clean-local:
|
||||
@RTAI_KBUILD_CLEAN@
|
||||
rm -f FORCE
|
||||
|
||||
distclean-local:
|
||||
@RTAI_KBUILD_DISTCLEAN@
|
||||
else
|
||||
noinst_LIBRARIES = lib16550A.a
|
||||
|
||||
lib16550A_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
INCLUDES = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I$(top_srcdir)/addons \
|
||||
-I$(top_srcdir)/addons/drivers/16550A/ \
|
||||
-I../../../base/include \
|
||||
-I../..
|
||||
|
||||
rtai_16550A.o: lib16550A.a
|
||||
$(CROSS_COMPILE)$(LD) --whole-archive $< -r -o $@
|
||||
endif
|
||||
|
||||
all-local: rtai_16550A$(modext)
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
$(mkinstalldirs) $(top_srcdir)/modules
|
||||
$(INSTALL_DATA) $^ $(top_srcdir)/modules
|
||||
endif
|
||||
|
||||
install-exec-local: rtai_16550A$(modext)
|
||||
$(mkinstalldirs) $(DESTDIR)$(moduledir)
|
||||
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
|
||||
|
||||
uninstall-local:
|
||||
$(RM) $(DESTDIR)$(moduledir)/rtai_16550A$(modext)
|
||||
|
||||
.PHONY: FORCE
|
||||
|
||||
EXTRA_DIST = $(distfiles) Makefile.kbuild \
|
||||
16550A_io.h 16550A_pci.h 16550A_pnp.h
|
||||
10
addons/drivers/16550A/Makefile.kbuild
Normal file
10
addons/drivers/16550A/Makefile.kbuild
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
|
||||
-I$(rtai_srctree)/addons/drivers/16550A \
|
||||
-I$(rtai_srcdir)/../.. \
|
||||
-I$(src)/../../../base/include \
|
||||
-I$(src)/../../.. \
|
||||
$(rtai_extradef)
|
||||
|
||||
obj-m += $(rtai_target).o
|
||||
|
||||
$(rtai_target)-objs := $(rtai_objs)
|
||||
11
addons/drivers/GNUmakefile.am
Normal file
11
addons/drivers/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
OPTDIRS =
|
||||
|
||||
if CONFIG_RTAI_DRIVERS_SERIAL
|
||||
OPTDIRS += serial
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_DRIVERS_16550A
|
||||
OPTDIRS += 16550A
|
||||
endif
|
||||
|
||||
SUBDIRS = $(OPTDIRS)
|
||||
46
addons/drivers/serial/GNUmakefile.am
Normal file
46
addons/drivers/serial/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
moduledir = @RTAI_MODULE_DIR@
|
||||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
CROSS_COMPILE = @CROSS_COMPILE@
|
||||
|
||||
libserial_a_SOURCES = \
|
||||
serial.c \
|
||||
serialP.h
|
||||
|
||||
include_HEADERS = rtai_serial.h
|
||||
|
||||
if CONFIG_KBUILD
|
||||
rtai_serial.ko: @RTAI_KBUILD_ENV@
|
||||
rtai_serial.ko: $(libserial_a_SOURCES)
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
clean-local:
|
||||
@RTAI_KBUILD_CLEAN@
|
||||
else
|
||||
noinst_LIBRARIES = libserial.a
|
||||
|
||||
libserial_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
INCLUDES = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I../../../base/include
|
||||
|
||||
rtai_serial.o: libserial.a
|
||||
$(CROSS_COMPILE)$(LD) --whole-archive $< -r -o $@
|
||||
endif
|
||||
|
||||
all-local: rtai_serial$(modext)
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
$(mkinstalldirs) $(top_srcdir)/modules
|
||||
$(INSTALL_DATA) $^ $(top_srcdir)/modules
|
||||
endif
|
||||
|
||||
install-exec-local: rtai_serial$(modext)
|
||||
$(mkinstalldirs) $(DESTDIR)$(moduledir)
|
||||
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
|
||||
|
||||
EXTRA_DIST = Makefile.kbuild
|
||||
9
addons/drivers/serial/Makefile.kbuild
Normal file
9
addons/drivers/serial/Makefile.kbuild
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
|
||||
-I$(rtai_srcdir) \
|
||||
-I$(src)/../../../base/include \
|
||||
-I$(src)/../../.. \
|
||||
-D__IN_RTAI__
|
||||
|
||||
obj-m += rtai_serial.o
|
||||
|
||||
rtai_serial-objs := $(rtai_objs)
|
||||
433
addons/drivers/serial/README
Normal file
433
addons/drivers/serial/README
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
This is a complete rewriting of rt_com. Changes:
|
||||
|
||||
- possibility of parametrizing the base_adr and irq of the serial ports used,
|
||||
along with rx/tx buffer sizes, at insmod,
|
||||
- new read/write buffer management, with the possibility of previewing what's
|
||||
in the receiver before reading,
|
||||
- enhanced interrupt service management,
|
||||
- interrupt callback function with user thresholded callbacks,
|
||||
- special interrupt callback function for serial port hardware errors,
|
||||
- the above callbacks are available in user space also,
|
||||
- info functions to check rx/tx data availability,
|
||||
|
||||
Compatibility with rt_com is provided through inlines and defines.
|
||||
rt_com_hwsetup is not supported, use the appropriate parametrization at insmod.
|
||||
|
||||
Any comment is welcomed.
|
||||
|
||||
The work of all the original rt_com writers: Jens Michaelsen, Jochen Kupper,
|
||||
Hua Mao, Roberto Finazzi, provided the base for an easy rewriting and is warmly
|
||||
acknowledged.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
N.B.: in the followings "spct" stands for "serial port control table".
|
||||
|
||||
********************************************************************************
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spclear_rx(unsigned int tty)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Clear serial port rx and reset the related buffer and UART rx FIFO.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spclear_tx(unsigned int tty)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Clear serial port tx and reset the related buffer.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spset_mode(unsigned int tty, int mode)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Set serial port flow control.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
mode working mode, i.e. handshaking and the likes, see
|
||||
available modes and related macros in rtai_spdrv :
|
||||
RT_SP_NO_HAND_SHAKE no hw flow control
|
||||
RT_SP_DSR_ON_TX transmitter enabled if DSR active
|
||||
RT_SP_HW_FLOW RTS-CTS flow control
|
||||
Note that RT_SP_DSR_ON_TX and RT_SP_HW_FLOW can be
|
||||
ORed toghether.
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spset_fifotrig(unsigned int tty, int fifotrig)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Set serial port UART receiver fifo trigger level.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
fifotrig this value must be choosen between one of these
|
||||
valued defined in rt_spdrv.h :
|
||||
RT_SP_FIFO_DISABLE
|
||||
RT_SP_FIFO_SIZE_1
|
||||
RT_SP_FIFO_SIZE_4
|
||||
RT_SP_FIFO_SIZE_8
|
||||
RT_SP_FIFO_SIZE_14
|
||||
RT_SP_FIFO_SIZE_DEFAULT
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spset_mcr(unsigned int tty, int mask, int setbits)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Set MODEM Control Register (MCR). Can be used to set the status
|
||||
of DTR and RTS lines.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
mask Output mask:
|
||||
RT_COM_DTR, RT_COM_RTS or any ORed combination.
|
||||
|
||||
setbits 0 -> reset bits in mask
|
||||
!= 0 -> set bits in mask
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
-EINVAL wrong mask value
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spget_msr(unsigned int tty, int mask)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Get serial port MODEM Status Register (MSR) (CTS, DSR, RI, DCD).
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
mask Input mask:
|
||||
RT_SP_CTS, RT_SP_DSR, RT_SP_RI, RT_SP_DCD
|
||||
or any ORed combination.
|
||||
|
||||
return:
|
||||
>= 0 input signal status, i.e. the bitwise-OR of
|
||||
the signal argument and MSR register.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spget_err(unsigned int tty)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Return the last error detected on a serial port.
|
||||
|
||||
param:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
return:
|
||||
>=0 tipically one or more codes ORed :
|
||||
RT_SP_BUFFER_FULL rx buffer full
|
||||
RT_SP_BUFFER_OVF rx buffer overflow (chars missed)
|
||||
RT_SP_OVERRUN_ERR rx overrun (chars missed)
|
||||
RT_SP_PARITY_ERR parity error
|
||||
RT_SP_FRAMING_ERR framing error
|
||||
RT_SP_BREAK break condition
|
||||
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spwrite(unsigned int tty, char *msg, int msg_size)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Write to a serial port.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
msg pointer to buffer of char to send.
|
||||
|
||||
msg_size abs(msg_size) is the number of bytes to write.
|
||||
If > 0, write bytes that are possible to send.
|
||||
If < 0, write bytes only if possible to write them all
|
||||
together.
|
||||
|
||||
return:
|
||||
>= 0 number of bytes not written.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spread(unsigned int tty, char *msg, int msg_size)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Read from a serial port.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
msg Address of data buffer. Needs to be of size > cnt !
|
||||
|
||||
msg_size abs(msg_size) is the number of bytes to read.
|
||||
If > 0, read all the bytes up to msg_size
|
||||
If < 0, read bytes only if it is possible to read them all
|
||||
together.
|
||||
|
||||
return:
|
||||
>= 0 number of bytes not read.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spevdrp(unsigned int tty, char *msg, int msg_size)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Eavesdrop data we got from a line just for a preview, i.e. keeping the read
|
||||
buffer unchanged.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
msg Address of data buffer. Needs to be of size > cnt !
|
||||
|
||||
msg_size abs(msg_size) is the number of bytes to read.
|
||||
If > 0, read all the bytes up to msg_size
|
||||
If < 0, read bytes only if it is possible to read them all
|
||||
together.
|
||||
|
||||
return:
|
||||
>= 0 number of bytes not eavesdropped.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spget_rxavbs(unsigned int tty)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Get the number of bytes available in rx buffer.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
return:
|
||||
>= 0 number of readable bytes.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spget_txfrbs(unsigned int tty)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Get the number of free bytes in rx buffer.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
return:
|
||||
>= 0 number of writable bytes.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spset_thrs(int tty, int rxthrs, int txthrs)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Set rx and tx thresholds for callback function.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
rxthrs call callback fun when rx has available a number of bytes
|
||||
>= rxthrs.
|
||||
|
||||
txthrs call callback fun when tx has a free a number of bytes
|
||||
>= txthrs.
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spset_callback_fun(int tty, void (*callback_fun)(int, int),
|
||||
int rxthrs, int txthrs)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Define the callback function to be called when the chars in the receive
|
||||
buffer or the free chars in the transmit buffer have reached the
|
||||
specified thresholds
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
callback_fun user assigned callback function, it will be called when
|
||||
the received/trasmitted bytes give/live the related
|
||||
buffers with a number of bytes >= the corresponding
|
||||
threshold values, passing the bytes available/free in
|
||||
the buffers.
|
||||
|
||||
return:
|
||||
>= 0 address of any already existing calbackfun, cast to int,
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
-EINVAL if wrong parameter value
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spset_err_callback_fun(int tty, void (*err_callback_fun)(int))
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Define the callback function to be called when the interrupt service routine
|
||||
detect an error
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
err_callback_fun user assigned callback function, it will be called
|
||||
when an error (the same reported by rt_spget_err) is
|
||||
detected by the interrupt service routine.
|
||||
|
||||
return:
|
||||
>= 0 address of any already existing calbackfun, cast to int,
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
-EINVAL if wrong parameter value
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spopen(unsigned int tty, unsigned int baud, unsigned int numbits,
|
||||
unsigned int stopbits, unsigned int parity, int mode,
|
||||
int fifotrig)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Setup and open a serial port.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
baud Data transmission rate to use [Byte/s]: 50 .. 115200.
|
||||
|
||||
numbits number of bits per char
|
||||
5,6,7,8
|
||||
|
||||
stopbits Number of stopbits to use.
|
||||
1 gives you one stopbit,
|
||||
2 actually gives really two stopbits for character lengths
|
||||
of 6,7,8 bit, but 1.5 stopbits for a character length of
|
||||
5 bits.
|
||||
|
||||
parity Parity for transmission protocol.
|
||||
Is possible to choose between macros defined in rt_spdrv.h :
|
||||
RT_SP_PARITY_NONE
|
||||
RT_SP_PARITY_EVEN
|
||||
RT_SP_PARITY_ODD
|
||||
RT_SP_PARITY_HIGH
|
||||
RT_SP_PARITY_LOW
|
||||
|
||||
mode working mode, i.e. handshaking and the likes, see
|
||||
available modes and related macros in rtai_spdrv :
|
||||
RT_SP_NO_HAND_SHAKE no hw flow control
|
||||
RT_SP_DSR_ON_TX transmitter enabled if DSR active
|
||||
RT_SP_HW_FLOW RTS-CTS flow control
|
||||
Note that RT_SP_DSR_ON_TX and RT_SP_HW_FLOW can be
|
||||
ORed toghether.
|
||||
|
||||
fifotrig this value must be choosen between one of these
|
||||
valued defined in rt_spdrv.h :
|
||||
RT_SP_FIFO_DISABLE
|
||||
RT_SP_FIFO_SIZE_1
|
||||
RT_SP_FIFO_SIZE_4
|
||||
RT_SP_FIFO_SIZE_8
|
||||
RT_SP_FIFO_SIZE_14
|
||||
RT_SP_FIFO_SIZE_DEFAULT
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
-EINVAL if wrong parameter value
|
||||
-EADDRINUSE if trying to open an openend port
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spclose(unsigned int tty)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Close a serial port.
|
||||
|
||||
params:
|
||||
tty Number corresponding to internal port numbering scheme,
|
||||
i.e. the index of the spct slot to use.
|
||||
|
||||
return:
|
||||
0 if all right.
|
||||
-ENODEV no entry in spct slots for that device.
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spwrite_timed(unsigned int tty, char *msg, int msg_size, RTIME delay)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Send one or more bytes with timeout
|
||||
|
||||
Arguments:
|
||||
tty serial port number.
|
||||
|
||||
msg pointer to the chars to send.
|
||||
|
||||
msg_size number of bytes to send.
|
||||
|
||||
delay timeout in internal count unit,
|
||||
use DELAY_FOREVER for a blocking send.
|
||||
|
||||
Return Value:
|
||||
-ENODEV, if wrong tty number;
|
||||
msg_size, if < 0 or another writer is already using tty;
|
||||
one of the semaphores error messages;
|
||||
0, message sent succesfully.
|
||||
|
||||
|
||||
+------------------------------------------------------------------------------+
|
||||
int rt_spread_timed(unsigned int tty, char *msg, int msg_size, RTIME delay)
|
||||
+------------------------------------------------------------------------------+
|
||||
|
||||
Receive one or more bytes with timeout
|
||||
|
||||
Arguments:
|
||||
tty serial port number.
|
||||
|
||||
msg pointer to the chars to receive.
|
||||
|
||||
msg_size the number of bytes to receive.
|
||||
|
||||
delay timeout in internal count unit,
|
||||
use DELAY_FOREVER for a blocking receive.
|
||||
|
||||
Return Value:
|
||||
-ENODEV, if wrong tty number;
|
||||
msg_size, if < 0 or another reader is already using tty;
|
||||
one of the semaphores error messages;
|
||||
0, message received succesfully.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
Paolo Mantegazza & Giuseppe Renoldi.
|
||||
418
addons/drivers/serial/rtai_serial.h
Normal file
418
addons/drivers/serial/rtai_serial.h
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* Copyright (C) 2002,2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
* Giuseppe Renoldi <giuseppe@renoldi.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _RTAI_SERIAL_H
|
||||
#define _RTAI_SERIAL_H
|
||||
|
||||
#define TTY0 0
|
||||
#define TTY1 1
|
||||
#define COM1 TTY0
|
||||
#define COM2 TTY1
|
||||
|
||||
#define RT_SP_NO_HAND_SHAKE 0x00
|
||||
#define RT_SP_DSR_ON_TX 0x01
|
||||
#define RT_SP_HW_FLOW 0x02
|
||||
|
||||
#define RT_SP_PARITY_EVEN 0x18
|
||||
#define RT_SP_PARITY_NONE 0x00
|
||||
#define RT_SP_PARITY_ODD 0x08
|
||||
#define RT_SP_PARITY_HIGH 0x28
|
||||
#define RT_SP_PARITY_LOW 0x38
|
||||
|
||||
#define RT_SP_FIFO_DISABLE 0x00
|
||||
#define RT_SP_FIFO_SIZE_1 0x00
|
||||
#define RT_SP_FIFO_SIZE_4 0x40
|
||||
#define RT_SP_FIFO_SIZE_8 0x80
|
||||
#define RT_SP_FIFO_SIZE_14 0xC0
|
||||
|
||||
#define RT_SP_FIFO_SIZE_DEFAULT RT_SP_FIFO_SIZE_8
|
||||
|
||||
#define RT_SP_DTR 0x01
|
||||
#define RT_SP_RTS 0x02
|
||||
|
||||
#define RT_SP_CTS 0x10
|
||||
#define RT_SP_DSR 0x20
|
||||
#define RT_SP_RI 0x40
|
||||
#define RT_SP_DCD 0x80
|
||||
|
||||
#define RT_SP_BUFFER_FULL 0x01
|
||||
#define RT_SP_OVERRUN_ERR 0x02
|
||||
#define RT_SP_PARITY_ERR 0x04
|
||||
#define RT_SP_FRAMING_ERR 0x08
|
||||
#define RT_SP_BREAK 0x10
|
||||
#define RT_SP_BUFFER_OVF 0x20
|
||||
|
||||
#define DELAY_FOREVER 0x3FFFFFFFFFFFFFFFLL
|
||||
|
||||
#define FUN_EXT_RTAI_SP 14
|
||||
|
||||
#define _SPOPEN 0
|
||||
#define _SPCLOSE 1
|
||||
#define _SPREAD 2
|
||||
#define _SPEVDRP 3
|
||||
#define _SPWRITE 4
|
||||
#define _SPCLEAR_RX 5
|
||||
#define _SPCLEAR_TX 6
|
||||
#define _SPGET_MSR 7
|
||||
#define _SPSET_MCR 8
|
||||
#define _SPGET_ERR 9
|
||||
#define _SPSET_MODE 10
|
||||
#define _SPSET_FIFOTRIG 11
|
||||
#define _SPGET_RXAVBS 12
|
||||
#define _SPGET_TXFRBS 13
|
||||
#define _SPSET_THRS 14
|
||||
#define _SPSET_CALLBACK 15
|
||||
#define _SPSET_ERR_CALLBACK 16
|
||||
#define _SPWAIT_USR_CALLBACK 17
|
||||
#define _SPREAD_TIMED 18
|
||||
#define _SPWRITE_TIMED 19
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <rtai.h>
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spopen(unsigned int tty, unsigned int baud, unsigned int numbits, unsigned int stopbits, unsigned int parity, int mode, int fifotrig);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spclose(unsigned int tty);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spread(unsigned int tty, char *msg, int msg_size);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spevdrp(unsigned int tty, char *msg, int msg_size);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spwrite(unsigned int tty, char *msg, int msg_size);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spget_rxavbs(unsigned int tty);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spget_txfrbs(unsigned int tty);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spclear_rx(unsigned int tty);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spclear_tx(unsigned int tty);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spset_mcr(unsigned int tty, int mask, int setbits);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spget_msr(unsigned int tty, int mask);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spset_mode(unsigned int tty, int mode);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spset_fifotrig(unsigned int tty, int fifotrig);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spget_err(unsigned int tty);
|
||||
|
||||
long rt_spset_callback_fun(unsigned int tty, void (*callback_fun)(int, int), int rxthrs, int txthrs);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spset_thrs(unsigned int tty, int rxthrs, int txthrs);
|
||||
|
||||
long rt_spset_err_callback_fun(unsigned int tty, void (*err_callback_fun)(int));
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spset_callback_fun_usr(unsigned int tty, unsigned long callback_fun, int rxthrs, int txthrs, int code, void *task);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spset_err_callback_fun_usr(unsigned int tty, unsigned long err_callback_fun, int dummy1, int dummy2, int code, void *task);
|
||||
|
||||
RTAI_SYSCALL_MODE void rt_spwait_usr_callback(unsigned int tty, unsigned long *retvals);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spread_timed(unsigned int tty, char *msg, int msg_size, RTIME delay);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_spwrite_timed(unsigned int tty, char *msg, int msg_size, RTIME delay);
|
||||
|
||||
/*
|
||||
* rt_com compatibility functions.
|
||||
*/
|
||||
|
||||
static inline int rt_com_setup(unsigned int tty,
|
||||
int baud, int mode,
|
||||
unsigned int parity,
|
||||
unsigned int stopbits,
|
||||
unsigned int numbits,
|
||||
int fifotrig)
|
||||
{
|
||||
return baud <= 0 ? rt_spclose(tty) : rt_spopen(tty, baud, numbits, stopbits, parity, mode, fifotrig);
|
||||
}
|
||||
|
||||
static inline int rt_com_read(unsigned int tty,
|
||||
char *msg,
|
||||
int msg_size)
|
||||
{
|
||||
int notrd;
|
||||
if ((notrd = rt_spread(tty, msg, msg_size)) >= 0) {
|
||||
return msg_size - notrd;
|
||||
}
|
||||
return notrd;
|
||||
}
|
||||
|
||||
static inline int rt_com_write(unsigned int tty,
|
||||
char *msg,
|
||||
int msg_size)
|
||||
{
|
||||
int notwr;
|
||||
if ((notwr = rt_spwrite(tty, msg, msg_size)) >= 0) {
|
||||
return msg_size - notwr;
|
||||
}
|
||||
return notwr;
|
||||
}
|
||||
|
||||
#define rt_com_clear_input(indx) rt_spclear_rx(indx)
|
||||
#define rt_com_clear_output(indx) rt_spclear_tx(indx)
|
||||
|
||||
#define rt_com_write_modem(indx, mask, op) rt_spset_mcr(indx, mask, op)
|
||||
#define rt_com_read_modem(indx, mask) rt_spget_msr(indx, mask)
|
||||
|
||||
#define rt_com_set_mode(indx, mode) rt_spset_mode(indx, mode)
|
||||
#define rt_com_set_fifotrig(indx, fifotrig) rt_spset_fifotrig(indx, fifotrig)
|
||||
|
||||
#define rt_com_error(indx) rt_spget_err(indx)
|
||||
|
||||
#else /* !__KERNEL__ */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <rtai_lxrt.h>
|
||||
|
||||
RTAI_PROTO(int, rt_spopen, (unsigned int tty, unsigned int baud, unsigned int numbits, unsigned int stopbits, unsigned int parity, int mode, int fifotrig))
|
||||
{
|
||||
struct { unsigned long tty, baud, numbits, stopbits, parity; long mode, fifotrig; } arg = { tty, baud, numbits, stopbits, parity, mode, fifotrig };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPOPEN, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spclose, (unsigned int tty))
|
||||
{
|
||||
struct { unsigned long tty; } arg = { tty };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPCLOSE, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spread, (unsigned int tty, char *msg, int msg_size))
|
||||
{
|
||||
int notrd, size;
|
||||
char lmsg[size = abs(msg_size)];
|
||||
struct { unsigned long tty; char *msg; long msg_size; } arg = { tty, lmsg, msg_size };
|
||||
notrd = rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPREAD, &arg).i[LOW];
|
||||
if (notrd >= 0 && notrd != size) {
|
||||
memcpy(msg, lmsg, size - notrd);
|
||||
}
|
||||
return notrd;
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spevdrp, (unsigned int tty, char *msg, int msg_size))
|
||||
{
|
||||
int notrd, size;
|
||||
char lmsg[size = abs(msg_size)];
|
||||
struct { unsigned long tty; char *msg; long msg_size; } arg = { tty, lmsg, msg_size };
|
||||
notrd = rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPEVDRP, &arg).i[LOW];
|
||||
if ( notrd >= 0 && notrd != size ) {
|
||||
memcpy(msg, lmsg, size - notrd);
|
||||
}
|
||||
return notrd;
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spwrite, (unsigned int tty, char *msg, int msg_size))
|
||||
{
|
||||
int size;
|
||||
char lmsg[size = abs(msg_size)];
|
||||
struct { unsigned long tty; char *msg; long msg_size; } arg = { tty, lmsg, msg_size };
|
||||
memcpy(lmsg, msg, size);
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPWRITE, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spread_timed, (unsigned int tty, char *msg, int msg_size, RTIME delay))
|
||||
{
|
||||
struct { unsigned long tty; char *msg; long msg_size; RTIME delay; } arg = { tty, msg, msg_size, delay };
|
||||
return msg_size > 0 ? rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPREAD_TIMED, &arg).i[LOW] : msg_size;
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spwrite_timed, (unsigned int tty, char *msg, int msg_size, RTIME delay))
|
||||
{
|
||||
struct { unsigned long tty; char *msg; long msg_size; RTIME delay; } arg = { tty, msg, msg_size, delay };
|
||||
return msg_size > 0 ? rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPWRITE_TIMED, &arg).i[LOW] : msg_size;
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spclear_rx, (unsigned int tty))
|
||||
{
|
||||
struct { unsigned long tty; } arg = { tty };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPCLEAR_RX, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spclear_tx, (unsigned int tty))
|
||||
{
|
||||
struct { unsigned long tty; } arg = { tty };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPCLEAR_TX, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spget_msr, (unsigned int tty, int mask))
|
||||
{
|
||||
struct { unsigned long tty; long mask; } arg = { tty, mask };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPGET_MSR, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spset_mcr, (unsigned int tty, int mask, int setbits))
|
||||
{
|
||||
struct { unsigned long tty; long mask, setbits; } arg = { tty, mask, setbits };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPSET_MCR, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spget_err, (unsigned int tty))
|
||||
{
|
||||
struct { unsigned long tty; } arg = { tty };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPGET_ERR, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spset_mode, (unsigned int tty, int mode))
|
||||
{
|
||||
struct { unsigned long tty; long mode; } arg = { tty, mode };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPSET_MODE, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spset_fifotrig, (unsigned int tty, int fifotrig))
|
||||
{
|
||||
struct { unsigned long tty; long fifotrig; } arg = { tty, fifotrig };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPSET_FIFOTRIG, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spget_rxavbs, (unsigned int tty))
|
||||
{
|
||||
struct { unsigned long tty; } arg = { tty };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPGET_RXAVBS, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spget_txfrbs, (unsigned int tty))
|
||||
{
|
||||
struct { unsigned long tty; } arg = { tty };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPGET_TXFRBS, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spset_thrs, (unsigned int tty, int rxthrs, int txthrs))
|
||||
{
|
||||
struct { unsigned long tty; long rxthrs, txthrs; } arg = { tty, rxthrs, txthrs };
|
||||
return rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPSET_THRS, &arg).i[LOW];
|
||||
}
|
||||
|
||||
RTAI_PROTO(void, rt_spwait_usr_callback, (unsigned int tty, unsigned long *retvals))
|
||||
{
|
||||
struct { unsigned long tty; unsigned long *retvals; long size; } arg = { tty, retvals, 6*sizeof(unsigned long) };
|
||||
rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPWAIT_USR_CALLBACK, &arg);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef __CALLBACK_THREAD__
|
||||
#define __CALLBACK_THREAD__
|
||||
static void *callback_thread(void *farg)
|
||||
{
|
||||
unsigned long retvals[6];
|
||||
struct farg_t { long tty; void *callback_fun; long rxthrs, txthrs, code; RT_TASK *task; } *arg;
|
||||
|
||||
arg = (struct farg_t *)farg;
|
||||
if (!(arg->task = rt_task_init_schmod((unsigned long)arg, 0, 0, 0, SCHED_FIFO, 0xF))) {
|
||||
printf("CANNOT INIT USER SPACE CALLBACK SUPPORT\n");
|
||||
return (void *)1;
|
||||
}
|
||||
retvals[0] = arg->code;
|
||||
arg->code = 0;
|
||||
if (rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, retvals[0], arg).i[LOW] < 0) {
|
||||
printf("CANNOT SET USER SPACE CALLBACK SUPPORT\n");
|
||||
rt_task_delete(arg->task);
|
||||
free(arg);
|
||||
return (void *)1;
|
||||
}
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
|
||||
rt_make_hard_real_time();
|
||||
while(1) {
|
||||
rt_spwait_usr_callback(arg->tty, retvals);
|
||||
if (!retvals[5]) break;
|
||||
if (retvals[0]) {
|
||||
((void(*)(unsigned long, unsigned long))retvals[0])(retvals[2], retvals[3]);
|
||||
}
|
||||
if (retvals[1]) {
|
||||
((void(*)(unsigned long))retvals[1])(retvals[4]);
|
||||
}
|
||||
}
|
||||
rt_make_soft_real_time();
|
||||
|
||||
rt_task_delete(arg->task);
|
||||
free(arg);
|
||||
return (void *)0;
|
||||
}
|
||||
#endif
|
||||
|
||||
RTAI_PROTO(int, rt_spset_callback_fun, (unsigned int tty, void (*callback_fun)(int, int), int rxthrs, int txthrs))
|
||||
{
|
||||
int ret;
|
||||
pthread_t thread;
|
||||
struct { long tty; void (*callback_fun)(int, int); long rxthrs, txthrs, code; void *task; } arg = { tty, callback_fun, rxthrs, txthrs, _SPSET_CALLBACK, 0 };
|
||||
if ((ret = rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPSET_CALLBACK, &arg).i[LOW]) == EINVAL) {
|
||||
void *argp;
|
||||
argp = (void *)malloc(sizeof(arg));
|
||||
memcpy(argp, &arg, sizeof(arg));
|
||||
return pthread_create(&thread, NULL, callback_thread, argp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RTAI_PROTO(int, rt_spset_err_callback_fun, (unsigned int tty, void (*err_callback_fun)(int)))
|
||||
{
|
||||
int ret;
|
||||
pthread_t thread;
|
||||
struct { long tty; void (*err_callback_fun)(int); long dummy1, dummy2, code; void *task; } arg = { tty, err_callback_fun, 0, 0, _SPSET_ERR_CALLBACK, 0 };
|
||||
if ((ret = rtai_lxrt(FUN_EXT_RTAI_SP, SIZARG, _SPSET_ERR_CALLBACK, &arg).i[LOW]) == EINVAL) {
|
||||
void *argp;
|
||||
argp = (void *)malloc(sizeof(arg));
|
||||
memcpy(argp, &arg, sizeof(arg));
|
||||
return pthread_create(&thread, NULL, callback_thread, argp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int rt_com_setup(unsigned int tty, int baud, int mode, unsigned int parity, unsigned int stopbits, unsigned int numbits, int fifotrig)
|
||||
{
|
||||
return baud <= 0 ? rt_spclose(tty) : rt_spopen(tty, baud, numbits, stopbits, parity, mode, fifotrig);
|
||||
}
|
||||
|
||||
static inline int rt_com_read(unsigned int tty, char *msg, int msg_size)
|
||||
{
|
||||
int notrd;
|
||||
if ((notrd = rt_spread(tty, msg, msg_size)) >= 0) {
|
||||
return abs(msg_size) - notrd;
|
||||
}
|
||||
return notrd;
|
||||
}
|
||||
|
||||
static inline int rt_com_write(unsigned int tty, char *msg, int msg_size)
|
||||
{
|
||||
int notwr;
|
||||
if ((notwr = rt_spwrite(tty, msg, msg_size)) >= 0) {
|
||||
return abs(msg_size) - notwr;
|
||||
}
|
||||
return notwr;
|
||||
}
|
||||
|
||||
#define rt_com_clear_input(indx) rt_spclear_rx(indx)
|
||||
#define rt_com_clear_output(indx) rt_spclear_tx(indx)
|
||||
|
||||
#define rt_com_write_modem(indx, mask, op) rt_spset_mcr(indx, mask, op)
|
||||
#define rt_com_read_modem(indx, mask) rt_spget_msr(indx, mask)
|
||||
|
||||
#define rt_com_set_mode(indx, mode) rt_spset_mode(indx, mode)
|
||||
#define rt_com_set_fifotrig(indx, fifotrig) rt_spset_fifotrig(indx, fifotrig)
|
||||
|
||||
#define rt_com_error(indx) rt_spget_err(indx)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* !_RTAI_SERIAL_H */
|
||||
1334
addons/drivers/serial/serial.c
Normal file
1334
addons/drivers/serial/serial.c
Normal file
File diff suppressed because it is too large
Load diff
118
addons/drivers/serial/serialP.h
Normal file
118
addons/drivers/serial/serialP.h
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
COPYRIGHT (C) 2002-2008 Paolo Mantegazza (mantegazza@aero.polimi.it)
|
||||
Giuseppe Renoldi (giuseppe@renoldi.org)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef RTAI_SPDRV_HW_H
|
||||
#define RTAI_SPDRV_HW_H
|
||||
|
||||
#define RTAI_SPDRV_NAME "RTAI_SPDRV"
|
||||
|
||||
#define CONFIG_SIZE 40 // likely abundant, twice the max # of serial ports
|
||||
#define SPBUFSIZ 512 // bufsize will be (1 << SPBUFMSB)
|
||||
#define RT_SP_CONFIG_INIT { 0x3f8, 4, 0x2f8, 3, }
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static DEFINE_SPINLOCK(splock);
|
||||
#define chip_atomic_bgn(flags) do { rtai_hw_save_flags_and_cli(flags); rt_spin_lock(&splock); } while (0)
|
||||
#define chip_atomic_end(flags) do { rt_spin_unlock(&splock); rtai_hw_restore_flags(flags); } while (0)
|
||||
#define buf_atomic_bgn(flags, mbx) do { flags = rt_spin_lock_irqsave(&(mbx)->lock); } while (0)
|
||||
#define buf_atomic_end(flags, mbx) do { rt_spin_unlock_irqrestore(flags, &(mbx)->lock); } while (0)
|
||||
#else
|
||||
#define chip_atomic_bgn(flags) do { rtai_hw_save_flags_and_cli(flags); } while (0)
|
||||
#define chip_atomic_end(flags) do { rtai_hw_restore_flags(flags); } while (0)
|
||||
#define buf_atomic_bgn(flags, mbx) do { rtai_save_flags_and_cli(flags); } while (0)
|
||||
#define buf_atomic_end(flags, mbx) do { rtai_restore_flags(flags); } while (0)
|
||||
#endif
|
||||
|
||||
#define ENABLE_SP(irq) rt_enable_irq(irq)
|
||||
|
||||
#define RT_SP_BASE_BAUD 115200
|
||||
|
||||
#define RT_SP_RXB 0x00
|
||||
#define RT_SP_TXB 0x00
|
||||
#define RT_SP_IER 0x01
|
||||
#define RT_SP_IIR 0x02
|
||||
#define RT_SP_FCR 0x02
|
||||
#define RT_SP_LCR 0x03
|
||||
#define RT_SP_MCR 0x04
|
||||
#define RT_SP_LSR 0x05
|
||||
#define RT_SP_MSR 0x06
|
||||
#define RT_SP_DLL 0x00
|
||||
#define RT_SP_DLM 0x01
|
||||
|
||||
#define MCR_DTR 0x01
|
||||
#define MCR_RTS 0x02
|
||||
#define MCR_OUT1 0x04
|
||||
#define MCR_OUT2 0x08
|
||||
#define MCR_LOOP 0x10
|
||||
#define MCR_AFE 0x20
|
||||
|
||||
#define IER_ERBI 0x01 // Enable Received Data Available Interrupt
|
||||
#define IER_ETBEI 0x02 // Enable Transmitter Holding Register Empty Interrupt
|
||||
#define IER_ELSI 0x04 // Enable Receiver Line Status Interrupt
|
||||
#define IER_EDSSI 0x08 // Enable MODEM Status Interrupt
|
||||
|
||||
#define MSR_DELTA_CTS 0x01
|
||||
#define MSR_DELTA_DSR 0x02
|
||||
#define MSR_TERI 0x04
|
||||
#define MSR_DELTA_DCD 0x08
|
||||
#define MSR_CTS 0x10
|
||||
#define MSR_DSR 0x20
|
||||
#define MSR_RI 0x40
|
||||
#define MSR_DCD 0x80
|
||||
|
||||
#define LSR_DATA_READY 0x01
|
||||
#define LSR_OVERRUN_ERR 0x02
|
||||
#define LSR_PARITY_ERR 0x04
|
||||
#define LSR_FRAMING_ERR 0x08
|
||||
#define LSR_BREAK 0x10
|
||||
#define LSR_THRE 0x20
|
||||
#define LSR_TEMT 0x40
|
||||
|
||||
#define FCR_FIFO_ENABLE 0x01
|
||||
#define FCR_INPUT_FIFO_RESET 0x02
|
||||
#define FCR_OUTPUT_FIFO_RESET 0x04
|
||||
|
||||
struct rt_spmbx {
|
||||
int frbs, avbs, fbyte, lbyte;
|
||||
char *bufadr;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct rt_spct_t {
|
||||
int opened;
|
||||
int base_adr, irq;
|
||||
int mode, fifotrig;
|
||||
int ier, mcr;
|
||||
int error;
|
||||
unsigned long just_onew, just_oner;
|
||||
int tx_fifo_depth;
|
||||
struct rt_spmbx ibuf, obuf;
|
||||
void (*callback_fun)(int, int);
|
||||
volatile int rxthrs, txthrs;
|
||||
void (*err_callback_fun)(int);
|
||||
RT_TASK *callback_task;
|
||||
unsigned long callback_fun_usr;
|
||||
unsigned long err_callback_fun_usr;
|
||||
volatile unsigned long call_usr;
|
||||
SEM txsem, rxsem;
|
||||
struct rt_spct_t *next;
|
||||
};
|
||||
|
||||
#endif /* RTAI_SPDRV_HW_H */
|
||||
79
addons/rtdm/GNUmakefile.am
Normal file
79
addons/rtdm/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
moduledir = @RTAI_MODULE_DIR@
|
||||
includedir = $(prefix)/include/rtdm
|
||||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
CROSS_COMPILE = @CROSS_COMPILE@
|
||||
|
||||
librtdm_a_SOURCES = \
|
||||
core.c \
|
||||
device.c \
|
||||
drvlib.c \
|
||||
module.c \
|
||||
proc.c \
|
||||
rtai_taskq.c \
|
||||
select.c
|
||||
|
||||
include_HEADERS = \
|
||||
rtdm.h \
|
||||
rtdm_driver.h \
|
||||
rtserial.h \
|
||||
xn.h \
|
||||
rtai_taskq.h \
|
||||
select.h
|
||||
|
||||
if CONFIG_KBUILD
|
||||
rtai_rtdm$(modext): @RTAI_KBUILD_ENV@
|
||||
rtai_rtdm$(modext): $(librtdm_a_SOURCES) FORCE
|
||||
@RTAI_KBUILD_TOP@ \
|
||||
@RTAI_KBUILD_CMD@ rtai_extradef="@RTAI_KMOD_CFLAGS@" \
|
||||
@RTAI_KBUILD_BOTTOM@
|
||||
|
||||
clean-local:
|
||||
@RTAI_KBUILD_CLEAN@
|
||||
rm -f FORCE
|
||||
|
||||
distclean-local:
|
||||
@RTAI_KBUILD_DISTCLEAN@
|
||||
else
|
||||
noinst_LIBRARIES = librtdm.a
|
||||
|
||||
|
||||
librtdm_a_AR = $(CROSS_COMPILE)ar cru
|
||||
|
||||
INCLUDES = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I$(top_srcdir)/addons \
|
||||
-I../../base/include \
|
||||
-I../.. \
|
||||
-I..
|
||||
|
||||
rtai_rtdm.o: librtdm.a
|
||||
$(CROSS_COMPILE)$(LD) --whole-archive $< -r -o $@
|
||||
endif
|
||||
|
||||
all-local: rtai_rtdm$(modext)
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
$(mkinstalldirs) $(top_srcdir)/modules
|
||||
$(INSTALL_DATA) $^ $(top_srcdir)/modules
|
||||
endif
|
||||
|
||||
install-exec-local: rtai_rtdm$(modext)
|
||||
$(mkinstalldirs) $(DESTDIR)$(moduledir) $(DESTDIR)$(includedir)
|
||||
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
|
||||
|
||||
uninstall-local:
|
||||
$(RM) $(DESTDIR)$(moduledir)/rtai_rtdm$(modext)
|
||||
|
||||
.PHONY: FORCE
|
||||
|
||||
EXTRA_DIST = $(libmodule_SRC) Makefile.kbuild \
|
||||
internal.h
|
||||
|
||||
# Always build if CONFIG_RTAI_RTDM is enabled
|
||||
if CONFIG_RTAI_RTDM
|
||||
OPTDIRS = lib
|
||||
endif
|
||||
|
||||
SUBDIRS = $(OPTDIRS)
|
||||
12
addons/rtdm/Makefile.kbuild
Normal file
12
addons/rtdm/Makefile.kbuild
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
|
||||
-I$(rtai_srctree)/addons/rtdm \
|
||||
-I$(rtai_srcdir)/.. \
|
||||
-I$(src)/../../base/include \
|
||||
-I$(src) \
|
||||
-I$(src)/../.. \
|
||||
$(rtai_extradef)
|
||||
|
||||
obj-m += $(rtai_target).o
|
||||
|
||||
$(rtai_target)-objs := $(rtai_objs)
|
||||
|
||||
1527
addons/rtdm/core.c
Normal file
1527
addons/rtdm/core.c
Normal file
File diff suppressed because it is too large
Load diff
522
addons/rtdm/device.c
Normal file
522
addons/rtdm/device.c
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
/**
|
||||
* @file
|
||||
* Real-Time Driver Model for RTAI, device management
|
||||
*
|
||||
* @note Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>
|
||||
* @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @addtogroup driverapi
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "rtdm/internal.h"
|
||||
|
||||
#define SET_DEFAULT_OP(device, operation) \
|
||||
(device).operation##_rt = (void *)rtdm_no_support; \
|
||||
(device).operation##_nrt = (void *)rtdm_no_support
|
||||
|
||||
#define SET_DEFAULT_OP_IF_NULL(device, operation) \
|
||||
if (!(device).operation##_rt) \
|
||||
(device).operation##_rt = (void *)rtdm_no_support; \
|
||||
if (!(device).operation##_nrt) \
|
||||
(device).operation##_nrt = (void *)rtdm_no_support
|
||||
|
||||
#define ANY_HANDLER(device, operation) \
|
||||
((device).operation##_rt || (device).operation##_nrt)
|
||||
|
||||
unsigned int devname_hashtab_size = DEF_DEVNAME_HASHTAB_SIZE;
|
||||
unsigned int protocol_hashtab_size = DEF_PROTO_HASHTAB_SIZE;
|
||||
module_param(devname_hashtab_size, uint, 0400);
|
||||
module_param(protocol_hashtab_size, uint, 0400);
|
||||
MODULE_PARM_DESC(devname_hashtab_size,
|
||||
"Size of hash table for named devices (must be power of 2)");
|
||||
MODULE_PARM_DESC(protocol_hashtab_size,
|
||||
"Size of hash table for protocol devices "
|
||||
"(must be power of 2)");
|
||||
|
||||
struct list_head *rtdm_named_devices; /* hash table */
|
||||
struct list_head *rtdm_protocol_devices; /* hash table */
|
||||
static int name_hashkey_mask;
|
||||
static int proto_hashkey_mask;
|
||||
|
||||
int rtdm_apc;
|
||||
EXPORT_SYMBOL(rtdm_apc);
|
||||
|
||||
struct semaphore nrt_dev_lock;
|
||||
DEFINE_XNLOCK(rt_dev_lock);
|
||||
|
||||
#ifndef MODULE
|
||||
int rtdm_initialised = 0;
|
||||
#endif /* !MODULE */
|
||||
|
||||
int rtdm_no_support(void)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int rtdm_select_bind_no_support(struct rtdm_dev_context *context,
|
||||
struct xnselector *selector,
|
||||
unsigned type,
|
||||
unsigned index)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
static inline int get_name_hash(const char *str, int limit, int hashkey_mask)
|
||||
{
|
||||
int hash = 0;
|
||||
|
||||
while (*str != 0) {
|
||||
hash += *str++;
|
||||
if (--limit == 0)
|
||||
break;
|
||||
}
|
||||
return hash & hashkey_mask;
|
||||
}
|
||||
|
||||
static inline int get_proto_hash(int protocol_family, int socket_type)
|
||||
{
|
||||
return protocol_family & proto_hashkey_mask;
|
||||
}
|
||||
|
||||
static inline void rtdm_reference_device(struct rtdm_device *device)
|
||||
{
|
||||
atomic_inc(&device->reserved.refcount);
|
||||
}
|
||||
|
||||
struct rtdm_device *get_named_device(const char *name)
|
||||
{
|
||||
struct list_head *entry;
|
||||
struct rtdm_device *device;
|
||||
int hashkey;
|
||||
spl_t s;
|
||||
|
||||
hashkey = get_name_hash(name, RTDM_MAX_DEVNAME_LEN, name_hashkey_mask);
|
||||
|
||||
xnlock_get_irqsave(&rt_dev_lock, s);
|
||||
|
||||
list_for_each(entry, &rtdm_named_devices[hashkey]) {
|
||||
device = list_entry(entry, struct rtdm_device, reserved.entry);
|
||||
|
||||
if (strcmp(name, device->device_name) == 0) {
|
||||
rtdm_reference_device(device);
|
||||
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct rtdm_device *get_protocol_device(int protocol_family, int socket_type)
|
||||
{
|
||||
struct list_head *entry;
|
||||
struct rtdm_device *device;
|
||||
int hashkey;
|
||||
spl_t s;
|
||||
|
||||
hashkey = get_proto_hash(protocol_family, socket_type);
|
||||
|
||||
xnlock_get_irqsave(&rt_dev_lock, s);
|
||||
|
||||
list_for_each(entry, &rtdm_protocol_devices[hashkey]) {
|
||||
device = list_entry(entry, struct rtdm_device, reserved.entry);
|
||||
|
||||
if ((device->protocol_family == protocol_family) &&
|
||||
(device->socket_type == socket_type)) {
|
||||
rtdm_reference_device(device);
|
||||
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @ingroup driverapi
|
||||
* @defgroup devregister Device Registration Services
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Register a RTDM device
|
||||
*
|
||||
* @param[in] device Pointer to structure describing the new device.
|
||||
*
|
||||
* @return 0 is returned upon success. Otherwise:
|
||||
*
|
||||
* - -EINVAL is returned if the device structure contains invalid entries.
|
||||
* Check kernel log in this case.
|
||||
*
|
||||
* - -ENOMEM is returned if the context for an exclusive device cannot be
|
||||
* allocated.
|
||||
*
|
||||
* - -EEXIST is returned if the specified device name of protocol ID is
|
||||
* already in use.
|
||||
*
|
||||
* - -EAGAIN is returned if some /proc entry cannot be created.
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
int rtdm_dev_register(struct rtdm_device *device)
|
||||
{
|
||||
int hashkey;
|
||||
spl_t s;
|
||||
struct list_head *entry;
|
||||
struct rtdm_device *existing_dev;
|
||||
int ret;
|
||||
|
||||
/* Catch unsuccessful initialisation */
|
||||
if (!rtdm_initialised)
|
||||
return -ENOSYS;
|
||||
|
||||
/* Sanity check: structure version */
|
||||
RTAI_ASSERT(RTDM, device->struct_version == RTDM_DEVICE_STRUCT_VER,
|
||||
xnlogerr("RTDM: invalid rtdm_device version (%d, "
|
||||
"required %d)\n", device->struct_version,
|
||||
RTDM_DEVICE_STRUCT_VER);
|
||||
return -EINVAL;);
|
||||
|
||||
/* Sanity check: proc_name specified? */
|
||||
RTAI_ASSERT(RTDM, device->proc_name,
|
||||
xnlogerr("RTDM: no /proc entry name specified\n");
|
||||
return -EINVAL;);
|
||||
|
||||
switch (device->device_flags & RTDM_DEVICE_TYPE_MASK) {
|
||||
case RTDM_NAMED_DEVICE:
|
||||
/* Sanity check: any open handler? */
|
||||
RTAI_ASSERT(RTDM, ANY_HANDLER(*device, open),
|
||||
xnlogerr("RTDM: missing open handler\n");
|
||||
return -EINVAL;);
|
||||
if (device->open_rt &&
|
||||
device->socket_rt != (void *)rtdm_no_support)
|
||||
xnlogerr("RTDM: RT open handler is deprecated, "
|
||||
"driver requires update.\n");
|
||||
SET_DEFAULT_OP_IF_NULL(*device, open);
|
||||
SET_DEFAULT_OP(*device, socket);
|
||||
break;
|
||||
|
||||
case RTDM_PROTOCOL_DEVICE:
|
||||
/* Sanity check: any socket handler? */
|
||||
RTAI_ASSERT(RTDM, ANY_HANDLER(*device, socket),
|
||||
xnlogerr("RTDM: missing socket handler\n");
|
||||
return -EINVAL;);
|
||||
if (device->socket_rt &&
|
||||
device->socket_rt != (void *)rtdm_no_support)
|
||||
xnlogerr("RTDM: RT socket creation handler is "
|
||||
"deprecated, driver requires update.\n");
|
||||
SET_DEFAULT_OP_IF_NULL(*device, socket);
|
||||
SET_DEFAULT_OP(*device, open);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Sanity check: non-RT close handler?
|
||||
* (Always required for forced cleanup) */
|
||||
if (!device->ops.close_nrt) {
|
||||
xnlogerr("RTDM: missing non-RT close handler\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (device->ops.close_rt &&
|
||||
device->ops.close_rt != (void *)rtdm_no_support)
|
||||
xnlogerr("RTDM: RT close handler is deprecated, driver "
|
||||
"requires update.\n");
|
||||
else
|
||||
device->ops.close_rt = (void *)rtdm_no_support;
|
||||
|
||||
SET_DEFAULT_OP_IF_NULL(device->ops, ioctl);
|
||||
SET_DEFAULT_OP_IF_NULL(device->ops, read);
|
||||
SET_DEFAULT_OP_IF_NULL(device->ops, write);
|
||||
SET_DEFAULT_OP_IF_NULL(device->ops, recvmsg);
|
||||
SET_DEFAULT_OP_IF_NULL(device->ops, sendmsg);
|
||||
if (!device->ops.select_bind)
|
||||
device->ops.select_bind = rtdm_select_bind_no_support;
|
||||
|
||||
atomic_set(&device->reserved.refcount, 0);
|
||||
device->reserved.exclusive_context = NULL;
|
||||
|
||||
if (device->device_flags & RTDM_EXCLUSIVE) {
|
||||
device->reserved.exclusive_context =
|
||||
kmalloc(sizeof(struct rtdm_dev_context) +
|
||||
device->context_size, GFP_KERNEL);
|
||||
if (!device->reserved.exclusive_context) {
|
||||
xnlogerr("RTDM: no memory for exclusive context "
|
||||
"(context size: %ld)\n",
|
||||
(long)device->context_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* mark exclusive context as unused */
|
||||
device->reserved.exclusive_context->device = NULL;
|
||||
}
|
||||
|
||||
down(&nrt_dev_lock);
|
||||
|
||||
if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE) {
|
||||
trace_mark(xn_rtdm, nameddev_register, "device %p name %s "
|
||||
"flags %d class %d sub_class %d profile_version %d "
|
||||
"driver_version %d", device, device->device_name,
|
||||
device->device_flags, device->device_class,
|
||||
device->device_sub_class, device->profile_version,
|
||||
device->driver_version);
|
||||
|
||||
hashkey =
|
||||
get_name_hash(device->device_name, RTDM_MAX_DEVNAME_LEN,
|
||||
name_hashkey_mask);
|
||||
|
||||
list_for_each(entry, &rtdm_named_devices[hashkey]) {
|
||||
existing_dev =
|
||||
list_entry(entry, struct rtdm_device,
|
||||
reserved.entry);
|
||||
if (strcmp(device->device_name,
|
||||
existing_dev->device_name) == 0) {
|
||||
ret = -EEXIST;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = rtdm_proc_register_device(device);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
xnlock_get_irqsave(&rt_dev_lock, s);
|
||||
list_add_tail(&device->reserved.entry,
|
||||
&rtdm_named_devices[hashkey]);
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
up(&nrt_dev_lock);
|
||||
} else {
|
||||
trace_mark(xn_rtdm, protocol_register, "device %p "
|
||||
"protocol_family %d socket_type %d flags %d "
|
||||
"class %d sub_class %d profile_version %d "
|
||||
"driver_version %d", device,
|
||||
device->protocol_family, device->socket_type,
|
||||
device->device_flags, device->device_class,
|
||||
device->device_sub_class, device->profile_version,
|
||||
device->driver_version);
|
||||
|
||||
hashkey = get_proto_hash(device->protocol_family,
|
||||
device->socket_type);
|
||||
|
||||
list_for_each(entry, &rtdm_protocol_devices[hashkey]) {
|
||||
existing_dev =
|
||||
list_entry(entry, struct rtdm_device,
|
||||
reserved.entry);
|
||||
if ((device->protocol_family ==
|
||||
existing_dev->protocol_family)
|
||||
&& (device->socket_type ==
|
||||
existing_dev->socket_type)) {
|
||||
xnlogerr("RTDM: protocol %u:%u already "
|
||||
"exists\n", device->protocol_family,
|
||||
device->socket_type);
|
||||
ret = -EEXIST;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = rtdm_proc_register_device(device);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
xnlock_get_irqsave(&rt_dev_lock, s);
|
||||
list_add_tail(&device->reserved.entry,
|
||||
&rtdm_protocol_devices[hashkey]);
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
up(&nrt_dev_lock);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
up(&nrt_dev_lock);
|
||||
if (device->reserved.exclusive_context)
|
||||
kfree(device->reserved.exclusive_context);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(rtdm_dev_register);
|
||||
|
||||
/**
|
||||
* @brief Unregisters a RTDM device
|
||||
*
|
||||
* @param[in] device Pointer to structure describing the device to be
|
||||
* unregistered.
|
||||
* @param[in] poll_delay Polling delay in milliseconds to check repeatedly for
|
||||
* open instances of @a device, or 0 for non-blocking mode.
|
||||
*
|
||||
* @return 0 is returned upon success. Otherwise:
|
||||
*
|
||||
* - -ENODEV is returned if the device was not registered.
|
||||
*
|
||||
* - -EAGAIN is returned if the device is busy with open instances and 0 has
|
||||
* been passed for @a poll_delay.
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay)
|
||||
{
|
||||
spl_t s;
|
||||
struct rtdm_device *reg_dev;
|
||||
unsigned long warned = 0;
|
||||
|
||||
if (!rtdm_initialised)
|
||||
return -ENOSYS;
|
||||
|
||||
if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE)
|
||||
reg_dev = get_named_device(device->device_name);
|
||||
else
|
||||
reg_dev = get_protocol_device(device->protocol_family,
|
||||
device->socket_type);
|
||||
if (!reg_dev)
|
||||
return -ENODEV;
|
||||
|
||||
trace_mark(xn_rtdm, dev_unregister, "device %p poll_delay %u",
|
||||
device, poll_delay);
|
||||
|
||||
down(&nrt_dev_lock);
|
||||
xnlock_get_irqsave(&rt_dev_lock, s);
|
||||
|
||||
while (atomic_read(®_dev->reserved.refcount) > 1) {
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
up(&nrt_dev_lock);
|
||||
|
||||
if (!poll_delay) {
|
||||
rtdm_dereference_device(reg_dev);
|
||||
trace_mark(xn_rtdm, dev_busy, "device %p", device);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!__test_and_set_bit(0, &warned))
|
||||
xnlogwarn("RTDM: device %s still in use - waiting for "
|
||||
"release...\n", reg_dev->device_name);
|
||||
msleep(poll_delay);
|
||||
trace_mark(xn_rtdm, dev_poll, "device %p", device);
|
||||
|
||||
down(&nrt_dev_lock);
|
||||
xnlock_get_irqsave(&rt_dev_lock, s);
|
||||
}
|
||||
|
||||
list_del(®_dev->reserved.entry);
|
||||
|
||||
xnlock_put_irqrestore(&rt_dev_lock, s);
|
||||
|
||||
rtdm_proc_unregister_device(device);
|
||||
|
||||
up(&nrt_dev_lock);
|
||||
|
||||
if (reg_dev->reserved.exclusive_context)
|
||||
kfree(device->reserved.exclusive_context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(rtdm_dev_unregister);
|
||||
/** @} */
|
||||
|
||||
int __init rtdm_dev_init(void)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
sema_init(&nrt_dev_lock, 1);
|
||||
|
||||
rtdm_apc = rthal_apc_alloc("deferred RTDM close", rtdm_apc_handler,
|
||||
NULL);
|
||||
if (rtdm_apc < 0)
|
||||
return rtdm_apc;
|
||||
|
||||
name_hashkey_mask = devname_hashtab_size - 1;
|
||||
proto_hashkey_mask = protocol_hashtab_size - 1;
|
||||
if (((devname_hashtab_size & name_hashkey_mask) != 0) ||
|
||||
((protocol_hashtab_size & proto_hashkey_mask) != 0)) {
|
||||
err = -EINVAL;
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
rtdm_named_devices = (struct list_head *)
|
||||
kmalloc(devname_hashtab_size * sizeof(struct list_head),
|
||||
GFP_KERNEL);
|
||||
if (!rtdm_named_devices) {
|
||||
err = -ENOMEM;
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
for (i = 0; i < devname_hashtab_size; i++)
|
||||
INIT_LIST_HEAD(&rtdm_named_devices[i]);
|
||||
|
||||
rtdm_protocol_devices = (struct list_head *)
|
||||
kmalloc(protocol_hashtab_size * sizeof(struct list_head),
|
||||
GFP_KERNEL);
|
||||
if (!rtdm_protocol_devices) {
|
||||
err = -ENOMEM;
|
||||
goto err_out2;
|
||||
}
|
||||
|
||||
for (i = 0; i < protocol_hashtab_size; i++)
|
||||
INIT_LIST_HEAD(&rtdm_protocol_devices[i]);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out2:
|
||||
kfree(rtdm_named_devices);
|
||||
|
||||
err_out1:
|
||||
rthal_apc_free(rtdm_apc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void rtdm_dev_cleanup(void)
|
||||
{
|
||||
/*
|
||||
* Note: no need to flush the cleanup_queue as no device is allowed
|
||||
* to deregister as long as there are references.
|
||||
*/
|
||||
rthal_apc_free(rtdm_apc);
|
||||
kfree(rtdm_named_devices);
|
||||
kfree(rtdm_protocol_devices);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
67
addons/rtdm/device.h
Normal file
67
addons/rtdm/device.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>.
|
||||
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _RTDM_DEVICE_H
|
||||
#define _RTDM_DEVICE_H
|
||||
|
||||
#include <rtdm/rtdm_driver.h>
|
||||
#include <linux/sem.h>
|
||||
|
||||
|
||||
#define DEF_DEVNAME_HASHTAB_SIZE 256 /* entries in name hash table */
|
||||
#define DEF_PROTO_HASHTAB_SIZE 256 /* entries in protocol hash table */
|
||||
|
||||
|
||||
extern struct semaphore nrt_dev_lock;
|
||||
extern xnlock_t rt_dev_lock;
|
||||
|
||||
extern unsigned int devname_hashtab_size;
|
||||
extern unsigned int protocol_hashtab_size;
|
||||
|
||||
extern struct list_head *rtdm_named_devices;
|
||||
extern struct list_head *rtdm_protocol_devices;
|
||||
|
||||
#ifdef MODULE
|
||||
#define rtdm_initialised 1
|
||||
#else /* !MODULE */
|
||||
extern int rtdm_initialised;
|
||||
#endif /* MODULE */
|
||||
|
||||
|
||||
int rtdm_no_support(void);
|
||||
|
||||
struct rtdm_device *get_named_device(const char *name);
|
||||
struct rtdm_device *get_protocol_device(int protocol_family, int socket_type);
|
||||
|
||||
static inline void rtdm_dereference_device(struct rtdm_device *device)
|
||||
{
|
||||
atomic_dec(&device->reserved.refcount);
|
||||
}
|
||||
|
||||
int __init rtdm_dev_init(void);
|
||||
|
||||
static inline void rtdm_dev_cleanup(void)
|
||||
{
|
||||
kfree(rtdm_named_devices);
|
||||
kfree(rtdm_protocol_devices);
|
||||
}
|
||||
|
||||
#endif /* _RTDM_DEVICE_H */
|
||||
2372
addons/rtdm/drvlib.c
Normal file
2372
addons/rtdm/drvlib.c
Normal file
File diff suppressed because it is too large
Load diff
106
addons/rtdm/internal.h
Normal file
106
addons/rtdm/internal.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de>.
|
||||
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _RTDM_INTERNAL_H
|
||||
#define _RTDM_INTERNAL_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sem.h>
|
||||
|
||||
|
||||
|
||||
#include <rtdm/rtdm_driver.h>
|
||||
|
||||
#define RTDM_FD_MAX CONFIG_RTAI_RTDM_FD_MAX
|
||||
|
||||
#define DEF_DEVNAME_HASHTAB_SIZE 256 /* entries in name hash table */
|
||||
#define DEF_PROTO_HASHTAB_SIZE 256 /* entries in protocol hash table */
|
||||
|
||||
struct rtdm_fildes {
|
||||
struct rtdm_dev_context *context;
|
||||
};
|
||||
|
||||
struct rtdm_process {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
char name[32];
|
||||
pid_t pid;
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
|
||||
};
|
||||
|
||||
DECLARE_EXTERN_XNLOCK(rt_fildes_lock);
|
||||
DECLARE_EXTERN_XNLOCK(rt_dev_lock);
|
||||
|
||||
extern int __rtdm_muxid;
|
||||
extern struct rtdm_fildes fildes_table[];
|
||||
extern int open_fildes;
|
||||
extern struct semaphore nrt_dev_lock;
|
||||
extern unsigned int devname_hashtab_size;
|
||||
extern unsigned int protocol_hashtab_size;
|
||||
extern struct list_head *rtdm_named_devices;
|
||||
extern struct list_head *rtdm_protocol_devices;
|
||||
|
||||
#ifdef MODULE
|
||||
#define rtdm_initialised 1
|
||||
#else /* !MODULE */
|
||||
extern int rtdm_initialised;
|
||||
#endif /* MODULE */
|
||||
|
||||
void cleanup_owned_contexts(void *user_info);
|
||||
int rtdm_no_support(void);
|
||||
struct rtdm_device *get_named_device(const char *name);
|
||||
struct rtdm_device *get_protocol_device(int protocol_family, int socket_type);
|
||||
|
||||
static inline void rtdm_dereference_device(struct rtdm_device *device)
|
||||
{
|
||||
atomic_dec(&device->reserved.refcount);
|
||||
}
|
||||
|
||||
int __init rtdm_dev_init(void);
|
||||
void rtdm_dev_cleanup(void);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
int __init rtdm_proc_init(void);
|
||||
void rtdm_proc_cleanup(void);
|
||||
int rtdm_proc_register_device(struct rtdm_device *device);
|
||||
void rtdm_proc_unregister_device(struct rtdm_device *device);
|
||||
#else
|
||||
static inline int rtdm_proc_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void rtdm_proc_cleanup(void)
|
||||
{
|
||||
}
|
||||
static int rtdm_proc_register_device(struct rtdm_device *device)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static void rtdm_proc_unregister_device(struct rtdm_device *device)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void rtdm_apc_handler(void *cookie);
|
||||
|
||||
#endif /* _RTDM_INTERNAL_H */
|
||||
19
addons/rtdm/lib/GNUmakefile.am
Normal file
19
addons/rtdm/lib/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
lib_LTLIBRARIES = librtdm.la
|
||||
|
||||
librtdm_la_LDFLAGS = -module -version-info 0:0:0
|
||||
|
||||
librtdm_la_SOURCES = \
|
||||
services.c
|
||||
|
||||
INCLUDES = \
|
||||
@RTAI_REAL_USER_CFLAGS@ \
|
||||
-fno-inline \
|
||||
-I../../../base/include \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I$(top_srcdir)/addons \
|
||||
-I$(srcdir)/../..
|
||||
|
||||
if CONFIG_RTAI_DRIVERS_16550A
|
||||
INCLUDES += -I$(top_srcdir)/addons/drivers/16550A
|
||||
endif
|
||||
|
||||
23
addons/rtdm/lib/services.c
Normal file
23
addons/rtdm/lib/services.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) Pierre Cloutier <pcloutier@PoseidonControls.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the version 2 of the GNU Lesser
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
//#define CONFIG_RTAI_LXRT_INLINE 0
|
||||
#include <rtdm/rtdm.h>
|
||||
#ifdef CONFIG_RTAI_DRIVERS_16550A
|
||||
#include <rtdm/rtserial.h>
|
||||
#endif /* CONFIG_RTAI_DRIVERS_16550A */
|
||||
977
addons/rtdm/module.c
Normal file
977
addons/rtdm/module.c
Normal file
|
|
@ -0,0 +1,977 @@
|
|||
/**
|
||||
* @file
|
||||
* Real-Time Driver Model for RTAI
|
||||
*
|
||||
* @note Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>
|
||||
* @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
|
||||
* @note Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
* only for the adaption to RTAI.
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @defgroup rtdm Real-Time Driver Model
|
||||
*
|
||||
* The Real-Time Driver Model (RTDM) provides a unified interface to
|
||||
* both users and developers of real-time device
|
||||
* drivers. Specifically, it addresses the constraints of mixed
|
||||
* RT/non-RT systems like RTAI. RTDM conforms to POSIX
|
||||
* semantics (IEEE Std 1003.1) where available and applicable.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @ingroup rtdm
|
||||
* @defgroup profiles Device Profiles
|
||||
*
|
||||
* Device profiles define which operation handlers a driver of a certain class
|
||||
* has to implement, which name or protocol it has to register, which IOCTLs
|
||||
* it has to provide, and further details. Sub-classes can be defined in order
|
||||
* to extend a device profile with more hardware-specific functions.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <rtdm/rtdm.h>
|
||||
#include <rtdm/internal.h>
|
||||
#include <rtdm/rtdm_driver.h>
|
||||
|
||||
MODULE_DESCRIPTION("Real-Time Driver Model");
|
||||
MODULE_AUTHOR("jan.kiszka@web.de");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_fdcount(void)
|
||||
{
|
||||
return RTDM_FD_MAX;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_open(const char *path, long oflag)
|
||||
{
|
||||
struct task_struct *curr = current;
|
||||
char krnl_path[RTDM_MAX_DEVNAME_LEN + 1];
|
||||
|
||||
if (unlikely(!__xn_access_ok(curr, VERIFY_READ, path, sizeof(krnl_path)))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
__xn_copy_from_user(curr, krnl_path, path, sizeof(krnl_path) - 1);
|
||||
krnl_path[sizeof(krnl_path) - 1] = '\0';
|
||||
return __rt_dev_open(curr, (const char *)krnl_path, oflag);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_socket(long protocol_family, long socket_type, long protocol)
|
||||
{
|
||||
return __rt_dev_socket(current, protocol_family, socket_type, protocol);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_close(long fd, long forced)
|
||||
{
|
||||
return __rt_dev_close(current, fd);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_ioctl(long fd, long request, void *arg)
|
||||
{
|
||||
return __rt_dev_ioctl(current, fd, request, arg);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_read(long fd, void *buf, long nbytes)
|
||||
{
|
||||
return __rt_dev_read(current, fd, buf, nbytes);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_write(long fd, void *buf, long nbytes)
|
||||
{
|
||||
return __rt_dev_write(current, fd, buf, nbytes);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_recvmsg(long fd, struct msghdr *msg, long flags)
|
||||
{
|
||||
struct msghdr krnl_msg;
|
||||
struct task_struct *curr = current;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!__xn_access_ok(curr, VERIFY_WRITE, msg, sizeof(krnl_msg)))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
__xn_copy_from_user(curr, &krnl_msg, msg, sizeof(krnl_msg));
|
||||
if ((ret = __rt_dev_recvmsg(curr, fd, &krnl_msg, flags)) >= 0) {
|
||||
__xn_copy_to_user(curr, msg, &krnl_msg, sizeof(krnl_msg));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_sendmsg(long fd, const struct msghdr *msg, long flags)
|
||||
{
|
||||
struct msghdr krnl_msg;
|
||||
struct task_struct *curr = current;
|
||||
|
||||
if (unlikely(!__xn_access_ok(curr, VERIFY_READ, msg, sizeof(krnl_msg)))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
__xn_copy_from_user(curr, &krnl_msg, msg, sizeof(krnl_msg));
|
||||
return __rt_dev_sendmsg(curr, fd, &krnl_msg, flags);
|
||||
}
|
||||
|
||||
static RTAI_SYSCALL_MODE int sys_rtdm_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
|
||||
{
|
||||
return rt_dev_select(nfds, rfds, wfds, efds, timeout);
|
||||
}
|
||||
|
||||
static struct rt_fun_entry rtdm[] = {
|
||||
[__rtdm_fdcount] = { 0, sys_rtdm_fdcount },
|
||||
[__rtdm_open] = { 0, sys_rtdm_open },
|
||||
[__rtdm_socket] = { 0, sys_rtdm_socket },
|
||||
[__rtdm_close] = { 0, sys_rtdm_close },
|
||||
[__rtdm_ioctl] = { 0, sys_rtdm_ioctl },
|
||||
[__rtdm_read] = { 0, sys_rtdm_read },
|
||||
[__rtdm_write] = { 0, sys_rtdm_write },
|
||||
[__rtdm_recvmsg] = { 0, sys_rtdm_recvmsg },
|
||||
[__rtdm_sendmsg] = { 0, sys_rtdm_sendmsg },
|
||||
[__rtdm_select] = { 0, sys_rtdm_select },
|
||||
};
|
||||
|
||||
/* This is needed because RTDM interrupt handlers:
|
||||
* - do no want immediate in handler rescheduling, RTAI can be configured
|
||||
* to act in the same, way but might not have been enabled to do so;
|
||||
* - may not reenable the PIC directly, assuming it will be done here;
|
||||
* - may not propagate, assuming it will be done here as well.
|
||||
* - might use shared interrupts its own way;
|
||||
* REMARK: RTDM irqs management is as generic as its pet system dictates
|
||||
* and there is no choice but doing the same as closely as possible;
|
||||
* so this is an as verbatim as possible copy of what is needed from
|
||||
* the RTDM pet system.
|
||||
* REMINDER: the RTAI dispatcher cares mask/ack-ing anyhow, but RTDM will
|
||||
* (must) provide the most suitable one for the shared case. */
|
||||
|
||||
#ifndef CONFIG_RTAI_SCHED_ISR_LOCK
|
||||
extern struct { volatile int locked, rqsted; } rt_scheduling[];
|
||||
extern void rtai_isr_sched_handle(int);
|
||||
|
||||
#define RTAI_SCHED_ISR_LOCK() \
|
||||
do { \
|
||||
int cpuid = rtai_cpuid(); \
|
||||
if (!rt_scheduling[cpuid].locked++) { \
|
||||
rt_scheduling[cpuid].rqsted = 0; \
|
||||
}
|
||||
#define RTAI_SCHED_ISR_UNLOCK() \
|
||||
rtai_cli(); \
|
||||
if (rt_scheduling[cpuid].locked && !(--rt_scheduling[cpuid].locked)) { \
|
||||
if (rt_scheduling[cpuid].rqsted > 0) { \
|
||||
rtai_isr_sched_handle(cpuid); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else /* !CONFIG_RTAI_SCHED_ISR_LOCK */
|
||||
#define RTAI_SCHED_ISR_LOCK() \
|
||||
do { } while (0)
|
||||
#define RTAI_SCHED_ISR_UNLOCK() \
|
||||
do { rtai_cli(); } while (0)
|
||||
#endif /* CONFIG_RTAI_SCHED_ISR_LOCK */
|
||||
|
||||
#define XNINTR_MAX_UNHANDLED 1000
|
||||
|
||||
DEFINE_PRIVATE_XNLOCK(intrlock);
|
||||
|
||||
static void xnintr_irq_handler(unsigned irq, void *cookie);
|
||||
|
||||
#ifdef CONFIG_RTAI_RTDM_SHIRQ
|
||||
|
||||
typedef struct xnintr_irq {
|
||||
|
||||
DECLARE_XNLOCK(lock);
|
||||
|
||||
xnintr_t *handlers;
|
||||
int unhandled;
|
||||
|
||||
} ____cacheline_aligned_in_smp xnintr_irq_t;
|
||||
|
||||
static xnintr_irq_t xnirqs[RTHAL_NR_IRQS];
|
||||
|
||||
static inline xnintr_t *xnintr_shirq_first(unsigned irq)
|
||||
{
|
||||
return xnirqs[irq].handlers;
|
||||
}
|
||||
|
||||
static inline xnintr_t *xnintr_shirq_next(xnintr_t *prev)
|
||||
{
|
||||
return prev->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level interrupt handler dispatching the user-defined ISRs for
|
||||
* shared interrupts -- Called with interrupts off.
|
||||
*/
|
||||
static void xnintr_shirq_handler(unsigned irq, void *cookie)
|
||||
{
|
||||
|
||||
xnintr_irq_t *shirq = &xnirqs[irq];
|
||||
|
||||
|
||||
xnintr_t *intr;
|
||||
int s = 0, ret;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RTAI_SCHED_ISR_LOCK();
|
||||
|
||||
|
||||
xnlock_get(&shirq->lock);
|
||||
intr = shirq->handlers;
|
||||
|
||||
while (intr) {
|
||||
|
||||
|
||||
|
||||
|
||||
ret = intr->isr(intr);
|
||||
s |= ret;
|
||||
|
||||
if (ret & XN_ISR_HANDLED) {
|
||||
xnstat_counter_inc(
|
||||
&intr->stat[xnsched_cpu(sched)].hits);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
intr = intr->next;
|
||||
}
|
||||
|
||||
xnlock_put(&shirq->lock);
|
||||
|
||||
if (unlikely(s == XN_ISR_NONE)) {
|
||||
if (++shirq->unhandled == XNINTR_MAX_UNHANDLED) {
|
||||
xnlogerr("%s: IRQ%d not handled. Disabling IRQ "
|
||||
"line.\n", __FUNCTION__, irq);
|
||||
s |= XN_ISR_NOENABLE;
|
||||
}
|
||||
} else
|
||||
shirq->unhandled = 0;
|
||||
|
||||
if (s & XN_ISR_PROPAGATE)
|
||||
xnarch_chain_irq(irq);
|
||||
else if (!(s & XN_ISR_NOENABLE))
|
||||
xnarch_end_irq(irq);
|
||||
|
||||
RTAI_SCHED_ISR_UNLOCK();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level interrupt handler dispatching the user-defined ISRs for
|
||||
* shared edge-triggered interrupts -- Called with interrupts off.
|
||||
*/
|
||||
static void xnintr_edge_shirq_handler(unsigned irq, void *cookie)
|
||||
{
|
||||
const int MAX_EDGEIRQ_COUNTER = 128;
|
||||
|
||||
xnintr_irq_t *shirq = &xnirqs[irq];
|
||||
int s = 0, counter = 0, ret, code;
|
||||
struct xnintr *intr, *end = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RTAI_SCHED_ISR_LOCK();
|
||||
|
||||
|
||||
xnlock_get(&shirq->lock);
|
||||
intr = shirq->handlers;
|
||||
|
||||
while (intr != end) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ret = intr->isr(intr);
|
||||
code = ret & ~XN_ISR_BITMASK;
|
||||
s |= ret;
|
||||
|
||||
if (code == XN_ISR_HANDLED) {
|
||||
end = NULL;
|
||||
xnstat_counter_inc(
|
||||
&intr->stat[xnsched_cpu(sched)].hits);
|
||||
|
||||
|
||||
|
||||
|
||||
} else if (end == NULL)
|
||||
end = intr;
|
||||
|
||||
if (counter++ > MAX_EDGEIRQ_COUNTER)
|
||||
break;
|
||||
|
||||
if (!(intr = intr->next))
|
||||
intr = shirq->handlers;
|
||||
}
|
||||
|
||||
xnlock_put(&shirq->lock);
|
||||
|
||||
if (counter > MAX_EDGEIRQ_COUNTER)
|
||||
xnlogerr
|
||||
("xnintr_edge_shirq_handler() : failed to get the IRQ%d line free.\n",
|
||||
irq);
|
||||
|
||||
if (unlikely(s == XN_ISR_NONE)) {
|
||||
if (++shirq->unhandled == XNINTR_MAX_UNHANDLED) {
|
||||
xnlogerr("%s: IRQ%d not handled. Disabling IRQ "
|
||||
"line.\n", __FUNCTION__, irq);
|
||||
s |= XN_ISR_NOENABLE;
|
||||
}
|
||||
} else
|
||||
shirq->unhandled = 0;
|
||||
|
||||
if (s & XN_ISR_PROPAGATE)
|
||||
xnarch_chain_irq(irq);
|
||||
else if (!(s & XN_ISR_NOENABLE))
|
||||
xnarch_end_irq(irq);
|
||||
|
||||
|
||||
|
||||
|
||||
RTAI_SCHED_ISR_UNLOCK();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static inline int xnintr_irq_attach(xnintr_t *intr)
|
||||
{
|
||||
xnintr_irq_t *shirq = &xnirqs[intr->irq];
|
||||
xnintr_t *prev, **p = &shirq->handlers;
|
||||
int err;
|
||||
|
||||
if ((prev = *p) != NULL) {
|
||||
/* Check on whether the shared mode is allowed. */
|
||||
if (!(prev->flags & intr->flags & XN_ISR_SHARED) ||
|
||||
(prev->iack != intr->iack)
|
||||
|| ((prev->flags & XN_ISR_EDGE) !=
|
||||
(intr->flags & XN_ISR_EDGE)))
|
||||
return -EBUSY;
|
||||
|
||||
/* Get a position at the end of the list to insert the new element. */
|
||||
while (prev) {
|
||||
p = &prev->next;
|
||||
prev = *p;
|
||||
}
|
||||
} else {
|
||||
/* Initialize the corresponding interrupt channel */
|
||||
void (*handler) (unsigned, void *) = &xnintr_irq_handler;
|
||||
|
||||
if (intr->flags & XN_ISR_SHARED) {
|
||||
if (intr->flags & XN_ISR_EDGE)
|
||||
handler = &xnintr_edge_shirq_handler;
|
||||
else
|
||||
handler = &xnintr_shirq_handler;
|
||||
|
||||
}
|
||||
shirq->unhandled = 0;
|
||||
|
||||
err = xnarch_hook_irq(intr->irq, handler,
|
||||
intr->iack, intr);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
intr->next = NULL;
|
||||
|
||||
/* Add the given interrupt object. No need to synchronise with the IRQ
|
||||
handler, we are only extending the chain. */
|
||||
*p = intr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int xnintr_irq_detach(xnintr_t *intr)
|
||||
{
|
||||
xnintr_irq_t *shirq = &xnirqs[intr->irq];
|
||||
xnintr_t *e, **p = &shirq->handlers;
|
||||
int err = 0;
|
||||
|
||||
while ((e = *p) != NULL) {
|
||||
if (e == intr) {
|
||||
/* Remove the given interrupt object from the list. */
|
||||
xnlock_get(&shirq->lock);
|
||||
*p = e->next;
|
||||
xnlock_put(&shirq->lock);
|
||||
|
||||
|
||||
|
||||
/* Release the IRQ line if this was the last user */
|
||||
if (shirq->handlers == NULL)
|
||||
err = xnarch_release_irq(intr->irq);
|
||||
|
||||
return err;
|
||||
}
|
||||
p = &e->next;
|
||||
}
|
||||
|
||||
xnlogerr("attempted to detach a non previously attached interrupt "
|
||||
"object.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_RTAI_RTDM_SHIRQ */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
typedef struct xnintr_irq {
|
||||
|
||||
DECLARE_XNLOCK(lock);
|
||||
|
||||
} ____cacheline_aligned_in_smp xnintr_irq_t;
|
||||
|
||||
static xnintr_irq_t xnirqs[RTHAL_NR_IRQS];
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
static inline xnintr_t *xnintr_shirq_first(unsigned irq)
|
||||
{
|
||||
return xnarch_get_irq_cookie(irq);
|
||||
}
|
||||
|
||||
static inline xnintr_t *xnintr_shirq_next(xnintr_t *prev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int xnintr_irq_attach(xnintr_t *intr)
|
||||
{
|
||||
return xnarch_hook_irq(intr->irq, &xnintr_irq_handler,
|
||||
intr->iack, intr);
|
||||
}
|
||||
|
||||
static inline int xnintr_irq_detach(xnintr_t *intr)
|
||||
{
|
||||
int irq = intr->irq, ret;
|
||||
|
||||
xnlock_get(&xnirqs[irq].lock);
|
||||
ret = xnarch_release_irq(irq);
|
||||
xnlock_put(&xnirqs[irq].lock);
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_RTAI_RTDM_SHIRQ */
|
||||
|
||||
/*
|
||||
* Low-level interrupt handler dispatching non-shared ISRs -- Called with
|
||||
* interrupts off.
|
||||
*/
|
||||
static void xnintr_irq_handler(unsigned irq, void *cookie)
|
||||
{
|
||||
|
||||
|
||||
struct xnintr *intr;
|
||||
|
||||
int s;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RTAI_SCHED_ISR_LOCK();
|
||||
|
||||
|
||||
xnlock_get(&xnirqs[irq].lock);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* In SMP case, we have to reload the cookie under the per-IRQ
|
||||
* lock to avoid racing with xnintr_detach. However, we
|
||||
* assume that no CPU migration will occur while running the
|
||||
* interrupt service routine, so the scheduler pointer will
|
||||
* remain valid throughout this function.
|
||||
*/
|
||||
intr = xnarch_get_irq_cookie(irq);
|
||||
if (unlikely(!intr)) {
|
||||
s = 0;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
#else
|
||||
/* cookie always valid, attach/detach happens with IRQs disabled */
|
||||
intr = cookie;
|
||||
#endif
|
||||
s = intr->isr(intr);
|
||||
if (unlikely(s == XN_ISR_NONE)) {
|
||||
if (++intr->unhandled == XNINTR_MAX_UNHANDLED) {
|
||||
xnlogerr("%s: IRQ%d not handled. Disabling IRQ "
|
||||
"line.\n", __FUNCTION__, irq);
|
||||
s |= XN_ISR_NOENABLE;
|
||||
}
|
||||
} else {
|
||||
xnstat_counter_inc(&intr->stat[xnsched_cpu(sched)].hits);
|
||||
|
||||
|
||||
|
||||
intr->unhandled = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
unlock_and_exit:
|
||||
#endif
|
||||
xnlock_put(&xnirqs[irq].lock);
|
||||
|
||||
if (s & XN_ISR_PROPAGATE)
|
||||
xnarch_chain_irq(irq);
|
||||
else if (!(s & XN_ISR_NOENABLE))
|
||||
xnarch_end_irq(irq);
|
||||
|
||||
|
||||
|
||||
RTAI_SCHED_ISR_UNLOCK();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int xnintr_mount(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < RTHAL_NR_IRQS; ++i)
|
||||
xnlock_init(&xnirqs[i].lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnintr_init(xnintr_t *intr,
|
||||
const char *name,
|
||||
unsigned irq, xnisr_t isr, xniack_t iack, xnflags_t flags)
|
||||
{
|
||||
if (irq >= RTHAL_NR_IRQS)
|
||||
return -EINVAL;
|
||||
|
||||
intr->irq = irq;
|
||||
intr->isr = isr;
|
||||
intr->iack = iack;
|
||||
intr->cookie = NULL;
|
||||
intr->name = name ? : "<unknown>";
|
||||
intr->flags = flags;
|
||||
intr->unhandled = 0;
|
||||
memset(&intr->stat, 0, sizeof(intr->stat));
|
||||
#ifdef CONFIG_RTAI_RTDM_SHIRQ
|
||||
intr->next = NULL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_init);
|
||||
|
||||
int xnintr_destroy(xnintr_t *intr)
|
||||
{
|
||||
return xnintr_detach(intr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_destroy);
|
||||
|
||||
int xnintr_attach(xnintr_t *intr, void *cookie)
|
||||
{
|
||||
int ret;
|
||||
spl_t s;
|
||||
|
||||
|
||||
|
||||
|
||||
intr->cookie = cookie;
|
||||
memset(&intr->stat, 0, sizeof(intr->stat));
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
xnarch_set_irq_affinity(intr->irq, nkaffinity);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
xnlock_get_irqsave(&intrlock, s);
|
||||
|
||||
if (__testbits(intr->flags, XN_ISR_ATTACHED)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = xnintr_irq_attach(intr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
__setbits(intr->flags, XN_ISR_ATTACHED);
|
||||
|
||||
out:
|
||||
xnlock_put_irqrestore(&intrlock, s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_attach);
|
||||
|
||||
int xnintr_detach(xnintr_t *intr)
|
||||
{
|
||||
int ret;
|
||||
spl_t s;
|
||||
|
||||
|
||||
|
||||
xnlock_get_irqsave(&intrlock, s);
|
||||
|
||||
if (!__testbits(intr->flags, XN_ISR_ATTACHED)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
__clrbits(intr->flags, XN_ISR_ATTACHED);
|
||||
|
||||
ret = xnintr_irq_detach(intr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
||||
out:
|
||||
xnlock_put_irqrestore(&intrlock, s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_detach);
|
||||
|
||||
int xnintr_enable(xnintr_t *intr)
|
||||
{
|
||||
|
||||
rt_enable_irq(intr->irq);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_enable);
|
||||
|
||||
int xnintr_disable(xnintr_t *intr)
|
||||
{
|
||||
|
||||
rt_disable_irq(intr->irq);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_disable);
|
||||
|
||||
typedef cpumask_t xnarch_cpumask_t;
|
||||
void xnintr_affinity(xnintr_t *intr, xnarch_cpumask_t cpumask)
|
||||
{
|
||||
trace_mark(xn_nucleus, irq_affinity, "irq %u %lu",
|
||||
intr->irq, *(unsigned long *)&cpumask);
|
||||
|
||||
xnarch_set_irq_affinity(intr->irq, cpumask);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnintr_affinity);
|
||||
|
||||
extern struct epoch_struct boot_epoch;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define NUM_CPUS RTAI_NR_CPUS
|
||||
#define TIMED_TIMER_CPUID (timed_timer->cpuid)
|
||||
#define TIMER_CPUID (timer->cpuid)
|
||||
#define LIST_CPUID (cpuid)
|
||||
#else
|
||||
#define NUM_CPUS 1
|
||||
#define TIMED_TIMER_CPUID (0)
|
||||
#define TIMER_CPUID (0)
|
||||
#define LIST_CPUID (0)
|
||||
#endif
|
||||
|
||||
static struct rtdm_timer_struct timers_list[NUM_CPUS] =
|
||||
{ { &timers_list[0], &timers_list[0], RT_SCHED_LOWEST_PRIORITY, 0, RT_TIME_END, 0LL, NULL, 0UL,
|
||||
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
|
||||
{ NULL }
|
||||
#endif
|
||||
}, };
|
||||
|
||||
//static spinlock_t timers_lock[NUM_CPUS] = { SPIN_LOCK_UNLOCKED, };
|
||||
static spinlock_t timers_lock[NUM_CPUS] = { __SPIN_LOCK_UNLOCKED(timers_lock[0]), };
|
||||
|
||||
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
|
||||
|
||||
/* BINARY TREE */
|
||||
static inline void enq_timer(struct rtdm_timer_struct *timed_timer)
|
||||
{
|
||||
struct rtdm_timer_struct *timerh, *tmrnxt, *timer;
|
||||
rb_node_t **rbtn, *rbtpn = NULL;
|
||||
timer = timerh = &timers_list[TIMED_TIMER_CPUID];
|
||||
rbtn = &timerh->rbr.rb_node;
|
||||
|
||||
while (*rbtn) {
|
||||
rbtpn = *rbtn;
|
||||
tmrnxt = rb_entry(rbtpn, struct rtdm_timer_struct, rbn);
|
||||
if (timer->firing_time > tmrnxt->firing_time) {
|
||||
rbtn = &(rbtpn)->rb_right;
|
||||
} else {
|
||||
rbtn = &(rbtpn)->rb_left;
|
||||
timer = tmrnxt;
|
||||
}
|
||||
}
|
||||
rb_link_node(&timed_timer->rbn, rbtpn, rbtn);
|
||||
rb_insert_color(&timed_timer->rbn, &timerh->rbr);
|
||||
timer->prev = (timed_timer->prev = timer->prev)->next = timed_timer;
|
||||
timed_timer->next = timer;
|
||||
}
|
||||
|
||||
#define rb_erase_timer(timer) \
|
||||
rb_erase(&(timer)->rbn, &timers_list[NUM_CPUS > 1 ? (timer)->cpuid : 0].rbr)
|
||||
|
||||
#else /* !CONFIG_RTAI_LONG_TIMED_LIST */
|
||||
|
||||
/* LINEAR */
|
||||
static inline void enq_timer(struct rtdm_timer_struct *timed_timer)
|
||||
{
|
||||
struct rtdm_timer_struct *timer;
|
||||
timer = &timers_list[TIMED_TIMER_CPUID];
|
||||
while (timed_timer->firing_time > (timer = timer->next)->firing_time);
|
||||
timer->prev = (timed_timer->prev = timer->prev)->next = timed_timer;
|
||||
timed_timer->next = timer;
|
||||
}
|
||||
|
||||
#define rb_erase_timer(timer)
|
||||
|
||||
#endif /* CONFIG_RTAI_LONG_TIMED_LIST */
|
||||
|
||||
static inline void rem_timer(struct rtdm_timer_struct *timer)
|
||||
{
|
||||
(timer->next)->prev = timer->prev;
|
||||
(timer->prev)->next = timer->next;
|
||||
timer->next = timer->prev = timer;
|
||||
rb_erase_timer(timer);
|
||||
}
|
||||
|
||||
static RT_TASK timers_manager[NUM_CPUS];
|
||||
|
||||
static inline void asgn_min_prio(int cpuid)
|
||||
{
|
||||
RT_TASK *timer_manager;
|
||||
struct rtdm_timer_struct *timer, *timerl;
|
||||
spinlock_t *lock;
|
||||
unsigned long flags;
|
||||
int priority;
|
||||
|
||||
priority = (timer = (timerl = &timers_list[LIST_CPUID])->next)->priority;
|
||||
flags = rt_spin_lock_irqsave(lock = &timers_lock[LIST_CPUID]);
|
||||
while ((timer = timer->next) != timerl) {
|
||||
if (timer->priority < priority) {
|
||||
priority = timer->priority;
|
||||
}
|
||||
rt_spin_unlock_irqrestore(flags, lock);
|
||||
flags = rt_spin_lock_irqsave(lock);
|
||||
}
|
||||
rt_spin_unlock_irqrestore(flags, lock);
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
if ((timer_manager = &timers_manager[LIST_CPUID])->priority > priority) {
|
||||
timer_manager->priority = priority;
|
||||
if (timer_manager->state == RT_SCHED_READY) {
|
||||
rem_ready_task(timer_manager);
|
||||
enq_ready_task(timer_manager);
|
||||
}
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_timer_insert(struct rtdm_timer_struct *timer, int priority, RTIME firing_time, RTIME period, void (*handler)(unsigned long), unsigned long data)
|
||||
{
|
||||
spinlock_t *lock;
|
||||
unsigned long flags, cpuid;
|
||||
RT_TASK *timer_manager;
|
||||
|
||||
if (!handler) {
|
||||
return -EINVAL;
|
||||
}
|
||||
timer->handler = handler;
|
||||
timer->data = data;
|
||||
timer->priority = priority;
|
||||
timer->firing_time = firing_time;
|
||||
timer->period = period;
|
||||
REALTIME2COUNT(firing_time)
|
||||
|
||||
timer->cpuid = cpuid = NUM_CPUS > 1 ? rtai_cpuid() : 0;
|
||||
// timer insertion in timers_list
|
||||
flags = rt_spin_lock_irqsave(lock = &timers_lock[LIST_CPUID]);
|
||||
enq_timer(timer);
|
||||
rt_spin_unlock_irqrestore(flags, lock);
|
||||
// timers_manager priority inheritance
|
||||
if (timer->priority < (timer_manager = &timers_manager[LIST_CPUID])->priority) {
|
||||
timer_manager->priority = timer->priority;
|
||||
}
|
||||
// timers_task deadline inheritance
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
if (timers_list[LIST_CPUID].next == timer && (timer_manager->state & RT_SCHED_DELAYED) && firing_time < timer_manager->resume_time) {
|
||||
timer_manager->resume_time = firing_time;
|
||||
rem_timed_task(timer_manager);
|
||||
enq_timed_task(timer_manager);
|
||||
rt_schedule();
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTAI_SYSCALL_MODE void rt_timer_remove(struct rtdm_timer_struct *timer)
|
||||
{
|
||||
if (timer->next != timer && timer->prev != timer) {
|
||||
spinlock_t *lock;
|
||||
unsigned long flags;
|
||||
flags = rt_spin_lock_irqsave(lock = &timers_lock[TIMER_CPUID]);
|
||||
rem_timer(timer);
|
||||
rt_spin_unlock_irqrestore(flags, lock);
|
||||
asgn_min_prio(TIMER_CPUID);
|
||||
}
|
||||
}
|
||||
|
||||
static int TimersManagerPrio = 0;
|
||||
RTAI_MODULE_PARM(TimersManagerPrio, int);
|
||||
|
||||
static void rt_timers_manager(long cpuid)
|
||||
{
|
||||
RTIME now;
|
||||
RT_TASK *timer_manager;
|
||||
struct rtdm_timer_struct *tmr, *timer, *timerl;
|
||||
spinlock_t *lock;
|
||||
unsigned long flags, timer_tol;
|
||||
int priority;
|
||||
|
||||
timer_manager = &timers_manager[LIST_CPUID];
|
||||
timerl = &timers_list[LIST_CPUID];
|
||||
lock = &timers_lock[LIST_CPUID];
|
||||
timer_tol = tuned.timers_tol[LIST_CPUID];
|
||||
|
||||
while (1) {
|
||||
rt_sleep_until((timerl->next)->firing_time);
|
||||
now = rt_get_time() + timer_tol;
|
||||
while (1) {
|
||||
tmr = timer = timerl;
|
||||
priority = RT_SCHED_LOWEST_PRIORITY;
|
||||
flags = rt_spin_lock_irqsave(lock);
|
||||
while ((tmr = tmr->next)->firing_time <= now) {
|
||||
if (tmr->priority < priority) {
|
||||
priority = (timer = tmr)->priority;
|
||||
}
|
||||
}
|
||||
rt_spin_unlock_irqrestore(flags, lock);
|
||||
if (timer == timerl) {
|
||||
if (timer_manager->priority > TimersManagerPrio) {
|
||||
timer_manager->priority = TimersManagerPrio;
|
||||
}
|
||||
break;
|
||||
}
|
||||
timer_manager->priority = priority;
|
||||
flags = rt_spin_lock_irqsave(lock);
|
||||
rem_timer(timer);
|
||||
if (timer->period) {
|
||||
timer->firing_time += timer->period;
|
||||
enq_timer(timer);
|
||||
}
|
||||
rt_spin_unlock_irqrestore(flags, lock);
|
||||
timer->handler(timer->data);
|
||||
}
|
||||
asgn_min_prio(LIST_CPUID);
|
||||
}
|
||||
}
|
||||
|
||||
static int TimersManagerStacksize = 8192;
|
||||
RTAI_MODULE_PARM(TimersManagerStacksize, int);
|
||||
|
||||
static int rtai_timers_init(void)
|
||||
{
|
||||
int cpuid;
|
||||
|
||||
for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
|
||||
timers_lock[cpuid] = timers_lock[0];
|
||||
timers_list[cpuid] = timers_list[0];
|
||||
timers_list[cpuid].cpuid = cpuid;
|
||||
timers_list[cpuid].next = timers_list[cpuid].prev = &timers_list[cpuid];
|
||||
}
|
||||
for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
|
||||
rt_task_init_cpuid(&timers_manager[cpuid], rt_timers_manager, cpuid, TimersManagerStacksize, TimersManagerPrio, 0, NULL, cpuid);
|
||||
rt_task_resume(&timers_manager[cpuid]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtai_timers_cleanup(void)
|
||||
{
|
||||
int cpuid;
|
||||
for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
|
||||
rt_task_delete(&timers_manager[cpuid]);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(rt_timer_insert);
|
||||
EXPORT_SYMBOL(rt_timer_remove);
|
||||
|
||||
int __init rtdm_skin_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
rtai_timers_init();
|
||||
if(set_rt_fun_ext_index(rtdm, RTDM_INDX)) {
|
||||
printk("LXRT extension %d already in use. Recompile RTDM with a different extension index\n", RTDM_INDX);
|
||||
return -EACCES;
|
||||
}
|
||||
if ((err = rtdm_dev_init())) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
xnintr_mount();
|
||||
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
if (xnselect_mount()) {
|
||||
goto cleanup_core;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if ((err = rtdm_proc_init())) {
|
||||
goto cleanup_core;
|
||||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
printk("RTDM started.\n");
|
||||
return 0;
|
||||
|
||||
cleanup_core:
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
xnselect_umount();
|
||||
#endif
|
||||
rtdm_dev_cleanup();
|
||||
#ifdef CONFIG_PROC_FS
|
||||
rtdm_proc_cleanup();
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
fail:
|
||||
return err;
|
||||
}
|
||||
|
||||
void __exit rtdm_skin_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
xnselect_umount();
|
||||
#endif
|
||||
rtai_timers_cleanup();
|
||||
rtdm_dev_cleanup();
|
||||
reset_rt_fun_ext_index(rtdm, RTDM_INDX);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
rtdm_proc_cleanup();
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
printk("RTDM stopped.\n");
|
||||
}
|
||||
|
||||
module_init(rtdm_skin_init);
|
||||
module_exit(rtdm_skin_exit);
|
||||
317
addons/rtdm/proc.c
Normal file
317
addons/rtdm/proc.c
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>.
|
||||
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "rtdm/internal.h"
|
||||
|
||||
/* Derived from Erwin Rol's rtai_proc_fs.h.
|
||||
Assumes that output fits into the provided buffer. */
|
||||
|
||||
#define RTDM_PROC_PRINT_VARS(MAX_BLOCK_LEN) \
|
||||
const int max_block_len = MAX_BLOCK_LEN; \
|
||||
off_t __limit = count - MAX_BLOCK_LEN; \
|
||||
int __len = 0; \
|
||||
\
|
||||
*eof = 1; \
|
||||
if (count < MAX_BLOCK_LEN) \
|
||||
return 0
|
||||
|
||||
#define RTDM_PROC_PRINT(fmt, args...) \
|
||||
({ \
|
||||
__len += snprintf(buf + __len, max_block_len, fmt, ##args); \
|
||||
(__len <= __limit); \
|
||||
})
|
||||
|
||||
#define RTDM_PROC_PRINT_DONE \
|
||||
return __len
|
||||
|
||||
struct proc_dir_entry *rtdm_proc_root; /* /proc/rtai/rtdm */
|
||||
|
||||
static int proc_read_named_devs(char *buf, char **start, off_t offset,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int i;
|
||||
struct list_head *entry;
|
||||
struct rtdm_device *device;
|
||||
RTDM_PROC_PRINT_VARS(80);
|
||||
|
||||
if (down_interruptible(&nrt_dev_lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!RTDM_PROC_PRINT("Hash\tName\t\t\t\tDriver\t\t/proc\n"))
|
||||
goto done;
|
||||
|
||||
for (i = 0; i < devname_hashtab_size; i++)
|
||||
list_for_each(entry, &rtdm_named_devices[i]) {
|
||||
device = list_entry(entry, struct rtdm_device,
|
||||
reserved.entry);
|
||||
|
||||
if (!RTDM_PROC_PRINT("%02X\t%-31s\t%-15s\t%s\n",
|
||||
i, device->device_name,
|
||||
device->driver_name,
|
||||
device->proc_name))
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
up(&nrt_dev_lock);
|
||||
|
||||
RTDM_PROC_PRINT_DONE;
|
||||
}
|
||||
|
||||
static int proc_read_proto_devs(char *buf, char **start, off_t offset,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int i;
|
||||
struct list_head *entry;
|
||||
struct rtdm_device *device;
|
||||
char txt[32];
|
||||
RTDM_PROC_PRINT_VARS(80);
|
||||
|
||||
if (down_interruptible(&nrt_dev_lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!RTDM_PROC_PRINT("Hash\tProtocolFamily:SocketType\tDriver\t\t"
|
||||
"/proc\n"))
|
||||
goto done;
|
||||
|
||||
for (i = 0; i < protocol_hashtab_size; i++)
|
||||
list_for_each(entry, &rtdm_protocol_devices[i]) {
|
||||
device = list_entry(entry, struct rtdm_device,
|
||||
reserved.entry);
|
||||
|
||||
snprintf(txt, sizeof(txt), "%u:%u",
|
||||
device->protocol_family, device->socket_type);
|
||||
if (!RTDM_PROC_PRINT("%02X\t%-31s\t%-15s\t%s\n", i,
|
||||
txt, device->driver_name,
|
||||
device->proc_name))
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
up(&nrt_dev_lock);
|
||||
|
||||
RTDM_PROC_PRINT_DONE;
|
||||
}
|
||||
|
||||
static int proc_read_open_fildes(char *buf, char **start, off_t offset,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int i;
|
||||
int close_lock_count;
|
||||
struct rtdm_device *device;
|
||||
struct rtdm_process owner;
|
||||
spl_t s;
|
||||
RTDM_PROC_PRINT_VARS(80);
|
||||
|
||||
if (!RTDM_PROC_PRINT("Index\tLocked\tDevice\t\tOwner [PID]\n"))
|
||||
goto done;
|
||||
|
||||
if (down_interruptible(&nrt_dev_lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
for (i = 0; i < RTDM_FD_MAX; i++) {
|
||||
struct rtdm_dev_context *context;
|
||||
|
||||
xnlock_get_irqsave(&rt_fildes_lock, s);
|
||||
|
||||
context = fildes_table[i].context;
|
||||
if (!context) {
|
||||
xnlock_put_irqrestore(&rt_fildes_lock, s);
|
||||
continue;
|
||||
}
|
||||
|
||||
close_lock_count = atomic_read(&context->close_lock_count);
|
||||
device = context->device;
|
||||
|
||||
if (context->reserved.owner)
|
||||
memcpy(&owner, context->reserved.owner, sizeof(owner));
|
||||
else {
|
||||
strcpy(owner.name, "<kernel>");
|
||||
owner.pid = -1;
|
||||
}
|
||||
|
||||
xnlock_put_irqrestore(&rt_fildes_lock, s);
|
||||
|
||||
if (!RTDM_PROC_PRINT("%d\t%d\t%-15s %s [%d]\n", i,
|
||||
close_lock_count,
|
||||
(device->device_flags&RTDM_NAMED_DEVICE) ?
|
||||
device->device_name : device->proc_name,
|
||||
owner.name, owner.pid))
|
||||
break;
|
||||
}
|
||||
|
||||
up(&nrt_dev_lock);
|
||||
|
||||
done:
|
||||
RTDM_PROC_PRINT_DONE;
|
||||
}
|
||||
|
||||
static int proc_kill_open_fildes(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
char krnl_buf[32];
|
||||
int fd;
|
||||
int res;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
if (count >= sizeof(krnl_buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(krnl_buf, buffer, count))
|
||||
return -EFAULT;
|
||||
krnl_buf[count] = '\0';
|
||||
|
||||
if (!sscanf(krnl_buf, "%d", &fd))
|
||||
return -EINVAL;
|
||||
|
||||
res = __rt_dev_close(current, fd);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int proc_read_fildes(char *buf, char **start, off_t offset,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
RTDM_PROC_PRINT_VARS(80);
|
||||
|
||||
RTDM_PROC_PRINT("total=%d:open=%d:free=%d\n", RTDM_FD_MAX,
|
||||
open_fildes, RTDM_FD_MAX - open_fildes);
|
||||
|
||||
RTDM_PROC_PRINT_DONE;
|
||||
}
|
||||
|
||||
static int proc_read_dev_info(char *buf, char **start, off_t offset,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
/* accessing the device during unregister (remove_proc_entry) might be
|
||||
racy, but no official workaround is known yet */
|
||||
struct rtdm_device *device = data;
|
||||
RTDM_PROC_PRINT_VARS(256);
|
||||
|
||||
if (!RTDM_PROC_PRINT("driver:\t\t%s\nversion:\t%d.%d.%d\n",
|
||||
device->driver_name,
|
||||
RTDM_DRIVER_MAJOR_VER(device->driver_version),
|
||||
RTDM_DRIVER_MINOR_VER(device->driver_version),
|
||||
RTDM_DRIVER_PATCH_VER(device->driver_version)))
|
||||
goto done;
|
||||
if (!RTDM_PROC_PRINT("peripheral:\t%s\nprovider:\t%s\n",
|
||||
device->peripheral_name, device->provider_name))
|
||||
goto done;
|
||||
if (!RTDM_PROC_PRINT("class:\t\t%d\nsub-class:\t%d\n",
|
||||
device->device_class, device->device_sub_class))
|
||||
goto done;
|
||||
if (!RTDM_PROC_PRINT("flags:\t\t%s%s%s\n",
|
||||
(device->device_flags & RTDM_EXCLUSIVE) ?
|
||||
"EXCLUSIVE " : "",
|
||||
(device->device_flags & RTDM_NAMED_DEVICE) ?
|
||||
"NAMED_DEVICE " : "",
|
||||
(device->device_flags & RTDM_PROTOCOL_DEVICE) ?
|
||||
"PROTOCOL_DEVICE " : ""))
|
||||
goto done;
|
||||
RTDM_PROC_PRINT("lock count:\t%d\n",
|
||||
atomic_read(&device->reserved.refcount));
|
||||
|
||||
done:
|
||||
RTDM_PROC_PRINT_DONE;
|
||||
}
|
||||
|
||||
int rtdm_proc_register_device(struct rtdm_device *device)
|
||||
{
|
||||
struct proc_dir_entry *dev_dir;
|
||||
struct proc_dir_entry *proc_entry;
|
||||
|
||||
dev_dir = create_proc_entry(device->proc_name, S_IFDIR, rtdm_proc_root);
|
||||
if (!dev_dir)
|
||||
goto err_out;
|
||||
|
||||
proc_entry = create_proc_entry("information", S_IFREG | S_IRUGO,
|
||||
dev_dir);
|
||||
if (!proc_entry) {
|
||||
remove_proc_entry(device->proc_name, rtdm_proc_root);
|
||||
goto err_out;
|
||||
}
|
||||
proc_entry->data = device;
|
||||
proc_entry->read_proc = proc_read_dev_info;
|
||||
|
||||
device->proc_entry = dev_dir;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
xnlogerr("RTDM: error while creating device proc entry\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
void rtdm_proc_unregister_device(struct rtdm_device *device)
|
||||
{
|
||||
remove_proc_entry("information", device->proc_entry);
|
||||
remove_proc_entry(device->proc_name, rtdm_proc_root);
|
||||
}
|
||||
|
||||
int __init rtdm_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *proc_entry;
|
||||
|
||||
/* Initialise /proc entries */
|
||||
rtdm_proc_root = create_proc_entry("rtai/rtdm", S_IFDIR, NULL);
|
||||
if (!rtdm_proc_root)
|
||||
return -EAGAIN;
|
||||
|
||||
proc_entry = create_proc_entry("named_devices", S_IFREG | S_IRUGO,
|
||||
rtdm_proc_root);
|
||||
if (!proc_entry)
|
||||
return -EAGAIN;
|
||||
proc_entry->read_proc = proc_read_named_devs;
|
||||
|
||||
proc_entry = create_proc_entry("protocol_devices", S_IFREG | S_IRUGO,
|
||||
rtdm_proc_root);
|
||||
if (!proc_entry)
|
||||
return -EAGAIN;
|
||||
proc_entry->read_proc = proc_read_proto_devs;
|
||||
|
||||
proc_entry =
|
||||
create_proc_entry("open_fildes", S_IFREG | S_IRUGO, rtdm_proc_root);
|
||||
if (!proc_entry)
|
||||
return -EAGAIN;
|
||||
proc_entry->read_proc = proc_read_open_fildes;
|
||||
proc_entry->write_proc = proc_kill_open_fildes;
|
||||
|
||||
proc_entry =
|
||||
create_proc_entry("fildes", S_IFREG | S_IRUGO, rtdm_proc_root);
|
||||
if (!proc_entry)
|
||||
return -EAGAIN;
|
||||
proc_entry->read_proc = proc_read_fildes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtdm_proc_cleanup(void)
|
||||
{
|
||||
remove_proc_entry("fildes", rtdm_proc_root);
|
||||
remove_proc_entry("open_fildes", rtdm_proc_root);
|
||||
remove_proc_entry("protocol_devices", rtdm_proc_root);
|
||||
remove_proc_entry("named_devices", rtdm_proc_root);
|
||||
remove_proc_entry("rtai/rtdm", NULL);
|
||||
}
|
||||
32
addons/rtdm/proc.h
Normal file
32
addons/rtdm/proc.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>.
|
||||
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _RTDM_PROC_H
|
||||
#define _RTDM_PROC_H
|
||||
|
||||
extern struct proc_dir_entry *rtdm_proc_root;
|
||||
|
||||
|
||||
int rtdm_proc_register_device(struct rtdm_device* device);
|
||||
|
||||
int __init rtdm_proc_init(void);
|
||||
|
||||
void rtdm_proc_cleanup(void);
|
||||
|
||||
#endif /* _RTDM_PROC_H */
|
||||
164
addons/rtdm/rtai_taskq.c
Normal file
164
addons/rtdm/rtai_taskq.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "rtai_taskq.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
volatile unsigned long tosched_mask;
|
||||
#endif
|
||||
|
||||
void rt_schedule_readied(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned long cpumask, rmask, lmask;
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
lmask = tosched_mask;
|
||||
tosched_mask = 0;
|
||||
rt_global_restore_flags(flags);
|
||||
rmask = lmask & ~(cpumask = (1 << rtai_cpuid()));
|
||||
if (rmask) {
|
||||
rtai_save_flags_and_cli(flags);
|
||||
send_sched_ipi(rmask);
|
||||
rtai_restore_flags(flags);
|
||||
}
|
||||
if (lmask | cpumask)
|
||||
#endif
|
||||
{
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
rt_schedule();
|
||||
rt_global_restore_flags(flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rt_schedule_readied);
|
||||
|
||||
void rt_taskq_init(TASKQ *taskq, unsigned long type)
|
||||
{
|
||||
taskq->qtype = (type & TASKQ_FIFO) ? 1 : 0;
|
||||
taskq->queue = (QUEUE) { &taskq->queue, &taskq->queue, NULL };
|
||||
}
|
||||
EXPORT_SYMBOL(rt_taskq_init);
|
||||
|
||||
RT_TASK *rt_taskq_ready_one(TASKQ *taskq)
|
||||
{
|
||||
unsigned long flags;
|
||||
RT_TASK *task = NULL;
|
||||
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
if ((task = (taskq->queue.next)->task)) {
|
||||
dequeue_blocked(task);
|
||||
rem_timed_task(task);
|
||||
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_TASKQ | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
|
||||
enq_ready_task(task);
|
||||
TOSCHED_TASK(task);
|
||||
}
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
return task;
|
||||
}
|
||||
EXPORT_SYMBOL(rt_taskq_ready_one);
|
||||
|
||||
int rt_taskq_ready_all(TASKQ *taskq, unsigned long why)
|
||||
{
|
||||
unsigned long flags, tosched;
|
||||
RT_TASK *task;
|
||||
QUEUE *q;
|
||||
|
||||
tosched = 0;
|
||||
q = &(taskq->queue);
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
while ((q = q->next) != &(taskq->queue)) {
|
||||
if ((task = q->task)) {
|
||||
dequeue_blocked(task = q->task);
|
||||
rem_timed_task(task);
|
||||
task->retval = why;
|
||||
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_TASKQ | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
|
||||
enq_ready_task(task);
|
||||
TOSCHED_TASK(task);
|
||||
tosched = 1;
|
||||
}
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
return tosched;
|
||||
}
|
||||
EXPORT_SYMBOL(rt_taskq_ready_all);
|
||||
|
||||
void rt_taskq_wait(TASKQ *taskq)
|
||||
{
|
||||
RT_TASK *rt_current;
|
||||
unsigned long flags;
|
||||
void *retp;
|
||||
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
rt_current = RT_CURRENT;
|
||||
rt_current->retval = 0;
|
||||
rt_current->state |= RT_SCHED_TASKQ;
|
||||
rem_ready_current(rt_current);
|
||||
enqueue_blocked(rt_current, &taskq->queue, taskq->qtype);
|
||||
rt_schedule();
|
||||
if (unlikely((retp = rt_current->blocked_on) != NULL)) {
|
||||
if (likely(retp != RTP_OBJREM)) {
|
||||
dequeue_blocked(rt_current);
|
||||
rt_current->retval = XNBREAK;
|
||||
} else {
|
||||
rt_current->prio_passed_to = NULL;
|
||||
rt_current->retval = XNRMID;
|
||||
}
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(rt_taskq_wait);
|
||||
|
||||
|
||||
void rt_taskq_wait_until(TASKQ *taskq, RTIME time)
|
||||
{
|
||||
DECLARE_RT_CURRENT;
|
||||
unsigned long flags;
|
||||
void *retp;
|
||||
|
||||
REALTIME2COUNT(time);
|
||||
|
||||
flags = rt_global_save_flags_and_cli();
|
||||
ASSIGN_RT_CURRENT;
|
||||
rt_current->retval = 0;
|
||||
rt_current->blocked_on = &taskq->queue;
|
||||
if ((rt_current->resume_time = time) > rt_time_h) {
|
||||
rt_current->state |= (RT_SCHED_TASKQ | RT_SCHED_DELAYED);
|
||||
rem_ready_current(rt_current);
|
||||
enqueue_blocked(rt_current, &taskq->queue, taskq->qtype);
|
||||
enq_timed_task(rt_current);
|
||||
rt_schedule();
|
||||
}
|
||||
if (unlikely((retp = rt_current->blocked_on) != NULL)) {
|
||||
if (likely(retp != RTP_OBJREM)) {
|
||||
dequeue_blocked(rt_current);
|
||||
rt_current->retval = retp > RTP_HIGERR ? XNTIMEO : XNBREAK;
|
||||
} else {
|
||||
rt_current->prio_passed_to = NULL;
|
||||
rt_current->retval = XNRMID;
|
||||
}
|
||||
}
|
||||
rt_global_restore_flags(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(rt_taskq_wait_until);
|
||||
76
addons/rtdm/rtai_taskq.h
Normal file
76
addons/rtdm/rtai_taskq.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _RTAI_TASKQ_H
|
||||
#define _RTAI_TASKQ_H
|
||||
|
||||
#include <rtai_schedcore.h>
|
||||
|
||||
extern struct epoch_struct boot_epoch;
|
||||
|
||||
typedef struct rt_task_queue {
|
||||
struct rt_queue queue; /* <= Must be first in struct. */
|
||||
int qtype;
|
||||
} TASKQ;
|
||||
|
||||
#define XNTIMEO 0x00000001 // RTE_TIMOUT
|
||||
#define XNRMID 0x00000002 // RTE_OBJREM
|
||||
#define XNBREAK 0x00000004 // RTE_UNBLKD
|
||||
|
||||
#define TASKQ_PRIO 0x0
|
||||
#define TASKQ_FIFO 0x1
|
||||
|
||||
#define RT_SCHED_TASKQ RT_SCHED_SEMAPHORE
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
extern volatile unsigned long tosched_mask;
|
||||
|
||||
#define TOSCHED_TASK(task) \
|
||||
do { tosched_mask |= (1 << (task)->runnable_on_cpus); } while (0)
|
||||
|
||||
#else /* !CONFIG_SMP */
|
||||
|
||||
#define TOSCHED_TASK(task)
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
void rt_schedule_readied(void);
|
||||
|
||||
void rt_taskq_init(TASKQ *taskq, unsigned long type);
|
||||
|
||||
RT_TASK *rt_taskq_ready_one(TASKQ *taskq);
|
||||
|
||||
int rt_taskq_ready_all(TASKQ *taskq, unsigned long why);
|
||||
|
||||
void rt_taskq_wait(TASKQ *taskq);
|
||||
|
||||
void rt_taskq_wait_until(TASKQ *taskq, RTIME time);
|
||||
|
||||
#define rt_taskq_delete(taskq) rt_taskq_ready_all(taskq, RTE_OBJREM)
|
||||
|
||||
#define rt_taskq_wait_timed(taskq, delay) \
|
||||
do { rt_taskq_wait_until(taskq, get_time() + delay); } while (0)
|
||||
|
||||
static inline int rt_task_test_taskq_retval(RT_TASK *task, unsigned long mask)
|
||||
{
|
||||
return ((task)->retval & mask);
|
||||
}
|
||||
|
||||
#endif /* !_RTAI_TASKQ_H */
|
||||
571
addons/rtdm/rtdm.h
Normal file
571
addons/rtdm/rtdm.h
Normal file
|
|
@ -0,0 +1,571 @@
|
|||
/**
|
||||
* @file
|
||||
* Real-Time Driver Model for RTAI, user API header
|
||||
*
|
||||
* @note Copyright (C) 2005, 2006 Jan Kiszka <jan.kiszka@web.de>
|
||||
* @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
|
||||
* @note Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* @ingroup userapi
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @defgroup rtdm Real-Time Driver Model
|
||||
*
|
||||
* The Real-Time Driver Model (RTDM) provides a unified interface to
|
||||
* both users and developers of real-time device
|
||||
* drivers. Specifically, it addresses the constraints of mixed
|
||||
* RT/non-RT systems like RTAI. RTDM conforms to POSIX
|
||||
* semantics (IEEE Std 1003.1) where available and applicable.
|
||||
*
|
||||
* @b API @b Revision: 8
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @ingroup rtdm
|
||||
* @defgroup userapi User API
|
||||
*
|
||||
* This is the upper interface of RTDM provided to application programs both
|
||||
* in kernel and user space. Note that certain functions may not be
|
||||
* implemented by every device. Refer to the @ref profiles "Device Profiles"
|
||||
* for precise information.
|
||||
*/
|
||||
|
||||
#ifndef _RTDM_H
|
||||
#define _RTDM_H
|
||||
|
||||
#define RTDM_INDX 15
|
||||
|
||||
#define __rtdm_fdcount 0
|
||||
#define __rtdm_open 1
|
||||
#define __rtdm_socket 2
|
||||
#define __rtdm_close 3
|
||||
#define __rtdm_ioctl 4
|
||||
#define __rtdm_read 5
|
||||
#define __rtdm_write 6
|
||||
#define __rtdm_recvmsg 7
|
||||
#define __rtdm_sendmsg 8
|
||||
#define __rtdm_select 9
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/socket.h>
|
||||
|
||||
typedef u32 socklen_t;
|
||||
typedef struct task_struct rtdm_user_info_t;
|
||||
|
||||
#else /* !__KERNEL__ */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#endif /* !__KERNEL__ */
|
||||
|
||||
/*!
|
||||
* @addtogroup rtdm
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @anchor api_versioning @name API Versioning
|
||||
* @{ */
|
||||
/** Common user and driver API version */
|
||||
#define RTDM_API_VER 8
|
||||
|
||||
/** Minimum API revision compatible with the current release */
|
||||
#define RTDM_API_MIN_COMPAT_VER 6
|
||||
/** @} API Versioning */
|
||||
|
||||
/** RTDM type for representing absolute dates. Its base type is a 64 bit
|
||||
* unsigned integer. The unit is 1 nanosecond. */
|
||||
typedef int64_t nanosecs_abs_t;
|
||||
|
||||
/** RTDM type for representing relative intervals. Its base type is a 64 bit
|
||||
* signed integer. The unit is 1 nanosecond. Relative intervals can also
|
||||
* encode the special timeouts "infinite" and "non-blocking", see
|
||||
* @ref RTDM_TIMEOUT_xxx. */
|
||||
typedef int64_t nanosecs_rel_t;
|
||||
|
||||
/*!
|
||||
* @anchor RTDM_TIMEOUT_xxx @name RTDM_TIMEOUT_xxx
|
||||
* Special timeout values
|
||||
* @{ */
|
||||
/** Block forever. */
|
||||
#define RTDM_TIMEOUT_INFINITE 0
|
||||
|
||||
/** Any negative timeout means non-blocking. */
|
||||
#define RTDM_TIMEOUT_NONE (-1)
|
||||
/** @} RTDM_TIMEOUT_xxx */
|
||||
/** @} rtdm */
|
||||
|
||||
/*!
|
||||
* @addtogroup profiles
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @anchor RTDM_CLASS_xxx @name RTDM_CLASS_xxx
|
||||
* Device classes
|
||||
* @{ */
|
||||
#define RTDM_CLASS_PARPORT 1
|
||||
#define RTDM_CLASS_SERIAL 2
|
||||
#define RTDM_CLASS_CAN 3
|
||||
#define RTDM_CLASS_NETWORK 4
|
||||
#define RTDM_CLASS_RTMAC 5
|
||||
#define RTDM_CLASS_TESTING 6
|
||||
#define RTDM_CLASS_RTIPC 7
|
||||
/*
|
||||
#define RTDM_CLASS_USB ?
|
||||
#define RTDM_CLASS_FIREWIRE ?
|
||||
#define RTDM_CLASS_INTERBUS ?
|
||||
#define RTDM_CLASS_PROFIBUS ?
|
||||
#define ...
|
||||
*/
|
||||
#define RTDM_CLASS_EXPERIMENTAL 224
|
||||
#define RTDM_CLASS_MAX 255
|
||||
/** @} RTDM_CLASS_xxx */
|
||||
|
||||
#define RTDM_SUBCLASS_GENERIC (-1)
|
||||
|
||||
#define RTIOC_TYPE_COMMON 0
|
||||
|
||||
/*!
|
||||
* @anchor device_naming @name Device Naming
|
||||
* Maximum length of device names (excluding the final null character)
|
||||
* @{
|
||||
*/
|
||||
#define RTDM_MAX_DEVNAME_LEN 31
|
||||
/** @} Device Naming */
|
||||
|
||||
/**
|
||||
* Device information
|
||||
*/
|
||||
typedef struct rtdm_device_info {
|
||||
/** Device flags, see @ref dev_flags "Device Flags" for details */
|
||||
int device_flags;
|
||||
|
||||
/** Device class ID, see @ref RTDM_CLASS_xxx */
|
||||
int device_class;
|
||||
|
||||
/** Device sub-class, either RTDM_SUBCLASS_GENERIC or a
|
||||
* RTDM_SUBCLASS_xxx definition of the related @ref profiles
|
||||
* "Device Profile" */
|
||||
int device_sub_class;
|
||||
|
||||
/** Supported device profile version */
|
||||
int profile_version;
|
||||
} rtdm_device_info_t;
|
||||
|
||||
/*!
|
||||
* @anchor RTDM_PURGE_xxx_BUFFER @name RTDM_PURGE_xxx_BUFFER
|
||||
* Flags selecting buffers to be purged
|
||||
* @{ */
|
||||
#define RTDM_PURGE_RX_BUFFER 0x0001
|
||||
#define RTDM_PURGE_TX_BUFFER 0x0002
|
||||
/** @} RTDM_PURGE_xxx_BUFFER*/
|
||||
|
||||
/*!
|
||||
* @anchor common_IOCTLs @name Common IOCTLs
|
||||
* The following IOCTLs are common to all device profiles.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieve information about a device or socket.
|
||||
* @param[out] arg Pointer to information buffer (struct rtdm_device_info)
|
||||
*/
|
||||
#define RTIOC_DEVICE_INFO \
|
||||
_IOR(RTIOC_TYPE_COMMON, 0x00, struct rtdm_device_info)
|
||||
|
||||
/**
|
||||
* Purge internal device or socket buffers.
|
||||
* @param[in] arg Purge mask, see @ref RTDM_PURGE_xxx_BUFFER
|
||||
*/
|
||||
#define RTIOC_PURGE _IOW(RTIOC_TYPE_COMMON, 0x10, int)
|
||||
/** @} Common IOCTLs */
|
||||
/** @} rtdm */
|
||||
|
||||
/* Internally used for mapping socket functions on IOCTLs */
|
||||
struct _rtdm_getsockopt_args {
|
||||
int level;
|
||||
int optname;
|
||||
void *optval;
|
||||
socklen_t *optlen;
|
||||
};
|
||||
|
||||
struct _rtdm_setsockopt_args {
|
||||
int level;
|
||||
int optname;
|
||||
const void *optval;
|
||||
socklen_t optlen;
|
||||
};
|
||||
|
||||
struct _rtdm_getsockaddr_args {
|
||||
struct sockaddr *addr;
|
||||
socklen_t *addrlen;
|
||||
};
|
||||
|
||||
struct _rtdm_setsockaddr_args {
|
||||
const struct sockaddr *addr;
|
||||
socklen_t addrlen;
|
||||
};
|
||||
|
||||
#define _RTIOC_GETSOCKOPT _IOW(RTIOC_TYPE_COMMON, 0x20, \
|
||||
struct _rtdm_getsockopt_args)
|
||||
#define _RTIOC_SETSOCKOPT _IOW(RTIOC_TYPE_COMMON, 0x21, \
|
||||
struct _rtdm_setsockopt_args)
|
||||
#define _RTIOC_BIND _IOW(RTIOC_TYPE_COMMON, 0x22, \
|
||||
struct _rtdm_setsockaddr_args)
|
||||
#define _RTIOC_CONNECT _IOW(RTIOC_TYPE_COMMON, 0x23, \
|
||||
struct _rtdm_setsockaddr_args)
|
||||
#define _RTIOC_LISTEN _IOW(RTIOC_TYPE_COMMON, 0x24, \
|
||||
int)
|
||||
#define _RTIOC_ACCEPT _IOW(RTIOC_TYPE_COMMON, 0x25, \
|
||||
struct _rtdm_getsockaddr_args)
|
||||
#define _RTIOC_GETSOCKNAME _IOW(RTIOC_TYPE_COMMON, 0x26, \
|
||||
struct _rtdm_getsockaddr_args)
|
||||
#define _RTIOC_GETPEERNAME _IOW(RTIOC_TYPE_COMMON, 0x27, \
|
||||
struct _rtdm_getsockaddr_args)
|
||||
#define _RTIOC_SHUTDOWN _IOW(RTIOC_TYPE_COMMON, 0x28, \
|
||||
int)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
int __rt_dev_open(rtdm_user_info_t *user_info, const char *path, int oflag);
|
||||
int __rt_dev_socket(rtdm_user_info_t *user_info, int protocol_family,
|
||||
int socket_type, int protocol);
|
||||
int __rt_dev_close(rtdm_user_info_t *user_info, int fd);
|
||||
int __rt_dev_ioctl(rtdm_user_info_t *user_info, int fd, int request, ...);
|
||||
ssize_t __rt_dev_read(rtdm_user_info_t *user_info, int fd, void *buf,
|
||||
size_t nbyte);
|
||||
ssize_t __rt_dev_write(rtdm_user_info_t *user_info, int fd, const void *buf,
|
||||
size_t nbyte);
|
||||
ssize_t __rt_dev_recvmsg(rtdm_user_info_t *user_info, int fd,
|
||||
struct msghdr *msg, int flags);
|
||||
ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info, int fd,
|
||||
const struct msghdr *msg, int flags);
|
||||
#include "select.h"
|
||||
int __rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout, struct xnselector *selector, int space);
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/* Define RTDM_NO_DEFAULT_USER_API to switch off the default rt_dev_xxx
|
||||
* interface when providing a customised user API */
|
||||
#ifndef RTDM_NO_DEFAULT_USER_API
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define rt_dev_open(path, oflag, ...) \
|
||||
__rt_dev_open(NULL, path, oflag)
|
||||
|
||||
#define rt_dev_socket(protocol_family, socket_type, protocol) \
|
||||
__rt_dev_socket(NULL, protocol_family, socket_type, protocol)
|
||||
|
||||
#define rt_dev_close(fd) \
|
||||
__rt_dev_close(NULL, fd)
|
||||
|
||||
#define rt_dev_ioctl(fd, request, ...) \
|
||||
__rt_dev_ioctl(NULL, fd, request, __VA_ARGS__)
|
||||
|
||||
#define rt_dev_read(fd, buf, nbyte) \
|
||||
__rt_dev_read(NULL, fd, buf, nbyte)
|
||||
|
||||
#define rt_dev_write(fd, buf, nbyte) \
|
||||
__rt_dev_write(NULL, fd, buf, nbyte)
|
||||
|
||||
#define rt_dev_recvmsg(fd, msg, flags) \
|
||||
__rt_dev_recvmsg(NULL, fd, msg, flags)
|
||||
|
||||
#define rt_dev_sendmsg(fd, msg, flags) \
|
||||
__rt_dev_sendmsg(NULL, fd, msg, flags)
|
||||
|
||||
static inline ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *from,
|
||||
socklen_t *fromlen)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
int ret;
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
|
||||
msg.msg_name = from;
|
||||
msg.msg_namelen = from ? *fromlen : 0;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
|
||||
ret = rt_dev_recvmsg(fd, &msg, flags);
|
||||
if (ret >= 0 && from)
|
||||
*fromlen = msg.msg_namelen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
|
||||
{
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
struct xnselector *selector;
|
||||
int ret;
|
||||
selector = rt_malloc(sizeof(struct xnselector));
|
||||
xnselector_init(selector);
|
||||
ret = __rt_dev_select(nfds, rfds, wfds, efds, timeout, selector, 1);
|
||||
xnselector_destroy(selector);
|
||||
return ret;
|
||||
#else
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !__KERNEL__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _RTAI_FUSION_LXRT_H
|
||||
#include <rtai_lxrt.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
//#define RTAI_LXRT(ext, lsize, srq, arg) rtai_lxrt(ext, lsize, srq, arg).i[LOW]
|
||||
|
||||
#ifndef RTDM_RTAI_LXRT
|
||||
static inline int RTDM_RTAI_LXRT(int ext, int lsize, int srq, void *arg)
|
||||
{
|
||||
int r;
|
||||
if ((r = rtai_lxrt(ext, lsize, srq, arg).i[LOW]) == -ENOSYS && rt_is_hard_real_time(NULL)) {
|
||||
rt_make_soft_real_time();
|
||||
r = rtai_lxrt(ext, lsize, srq, arg).i[LOW];
|
||||
rt_make_hard_real_time();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int rt_dev_fdcount(void)
|
||||
{
|
||||
struct { long dummy; } arg = { 0 };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_fdcount, &arg);
|
||||
}
|
||||
|
||||
static inline int rt_dev_open(const char *path, int oflag, ...)
|
||||
{
|
||||
struct { const char *path; long oflag; } arg = { path, oflag };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_open, &arg);
|
||||
}
|
||||
|
||||
static inline int rt_dev_socket(int protocol_family, int socket_type, int protocol)
|
||||
{
|
||||
struct { long protocol_family; long socket_type; long protocol; } arg = { protocol_family, socket_type, protocol };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_socket, &arg);
|
||||
}
|
||||
|
||||
static inline int rt_dev_close(int fd)
|
||||
{
|
||||
struct { long fd; } arg = { fd };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_close, &arg);
|
||||
}
|
||||
|
||||
static inline int rt_dev_ioctl(int fd, int request, ...)
|
||||
{
|
||||
struct { long fd; long request; void *arg; } arg = { fd, request, NULL };
|
||||
va_list ap;
|
||||
va_start(ap, request);
|
||||
arg.arg = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_ioctl, &arg);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_read(int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
struct { long fd; void *buf; long nbytes; } arg = { fd, buf, nbytes };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_read, &arg);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_write(int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
struct { long fd; const void *buf; long nbytes; } arg = { fd, buf, nbytes };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_write, &arg);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_recvmsg(int fd, struct msghdr *msg, int flags)
|
||||
{
|
||||
struct { long fd; struct msghdr *msg; long flags; } arg = { fd, msg, flags };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_recvmsg, &arg);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_sendmsg(int fd, const struct msghdr *msg, int flags)
|
||||
{
|
||||
struct { long fd; const struct msghdr *msg; long flags; } arg = { fd, msg, flags };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_sendmsg, &arg);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
int ret;
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
|
||||
msg.msg_name = from;
|
||||
msg.msg_namelen = from ? *fromlen : 0;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
|
||||
ret = rt_dev_recvmsg(fd, &msg, flags);
|
||||
if (ret >= 0 && from)
|
||||
*fromlen = msg.msg_namelen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
|
||||
{
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
struct { long nfds; fd_set *rfds; fd_set *wfds; fd_set *efds; nanosecs_rel_t timeout; } arg = { nfds, rfds, wfds, efds, timeout };
|
||||
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_select, &arg);
|
||||
#else
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !__KERNEL__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline ssize_t rt_dev_recv(int fd, void *buf, size_t len, int flags)
|
||||
{
|
||||
return rt_dev_recvfrom(fd, buf, len, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_sendto(int fd, const void *buf, size_t len,
|
||||
int flags, const struct sockaddr *to,
|
||||
socklen_t tolen)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
|
||||
iov.iov_base = (void *)buf;
|
||||
iov.iov_len = len;
|
||||
|
||||
msg.msg_name = (struct sockaddr *)to;
|
||||
msg.msg_namelen = tolen;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
|
||||
return rt_dev_sendmsg(fd, &msg, flags);
|
||||
}
|
||||
|
||||
static inline ssize_t rt_dev_send(int fd, const void *buf, size_t len,
|
||||
int flags)
|
||||
{
|
||||
return rt_dev_sendto(fd, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int rt_dev_getsockopt(int fd, int level, int optname,
|
||||
void *optval, socklen_t *optlen)
|
||||
{
|
||||
struct _rtdm_getsockopt_args args =
|
||||
{ level, optname, optval, optlen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_GETSOCKOPT, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_setsockopt(int fd, int level, int optname,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
struct _rtdm_setsockopt_args args =
|
||||
{ level, optname, (void *)optval, optlen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_SETSOCKOPT, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_bind(int fd, const struct sockaddr *my_addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct _rtdm_setsockaddr_args args = { my_addr, addrlen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_BIND, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_connect(int fd, const struct sockaddr *serv_addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct _rtdm_setsockaddr_args args = { serv_addr, addrlen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_CONNECT, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_listen(int fd, int backlog)
|
||||
{
|
||||
return rt_dev_ioctl(fd, _RTIOC_LISTEN, backlog);
|
||||
}
|
||||
|
||||
static inline int rt_dev_accept(int fd, struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
struct _rtdm_getsockaddr_args args = { addr, addrlen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_ACCEPT, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_getsockname(int fd, struct sockaddr *name,
|
||||
socklen_t *namelen)
|
||||
{
|
||||
struct _rtdm_getsockaddr_args args = { name, namelen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_GETSOCKNAME, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_getpeername(int fd, struct sockaddr *name,
|
||||
socklen_t *namelen)
|
||||
{
|
||||
struct _rtdm_getsockaddr_args args = { name, namelen };
|
||||
|
||||
return rt_dev_ioctl(fd, _RTIOC_GETPEERNAME, &args);
|
||||
}
|
||||
|
||||
static inline int rt_dev_shutdown(int fd, int how)
|
||||
{
|
||||
return rt_dev_ioctl(fd, _RTIOC_SHUTDOWN, how);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RTDM_NO_DEFAULT_USER_API */
|
||||
|
||||
#endif /* _RTDM_H */
|
||||
1373
addons/rtdm/rtdm_driver.h
Normal file
1373
addons/rtdm/rtdm_driver.h
Normal file
File diff suppressed because it is too large
Load diff
522
addons/rtdm/rtserial.h
Normal file
522
addons/rtdm/rtserial.h
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
/**
|
||||
* @file
|
||||
* Real-Time Driver Model for RTAI, serial device profile header
|
||||
*
|
||||
* @note Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de>
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* @ingroup rtserial
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @ingroup profiles
|
||||
* @defgroup rtserial Serial Devices
|
||||
*
|
||||
* This is the common interface a RTDM-compliant serial device has to provide.
|
||||
* Feel free to comment on this profile via the RTAI mailing list
|
||||
* (rtai@rtai.org) or directly to the author (jan.kiszka@web.de).
|
||||
*
|
||||
* @b Profile @b Revision: 3
|
||||
* @n
|
||||
* @n
|
||||
* @par Device Characteristics
|
||||
* @ref rtdm_device.device_flags "Device Flags": @c RTDM_NAMED_DEVICE, @c RTDM_EXCLUSIVE @n
|
||||
* @n
|
||||
* @ref rtdm_device.device_name "Device Name": @c "rtser<N>", N >= 0 @n
|
||||
* @n
|
||||
* @ref rtdm_device.device_class "Device Class": @c RTDM_CLASS_SERIAL @n
|
||||
* @n
|
||||
*
|
||||
* @par Supported Operations
|
||||
* @b Open @n
|
||||
* Environments: non-RT (RT optional, deprecated)@n
|
||||
* Specific return values: none @n
|
||||
* @n
|
||||
* @b Close @n
|
||||
* Environments: non-RT (RT optional, deprecated)@n
|
||||
* Specific return values: none @n
|
||||
* @n
|
||||
* @b IOCTL @n
|
||||
* Mandatory Environments: see @ref SERIOCTLs "below" @n
|
||||
* Specific return values: see @ref SERIOCTLs "below" @n
|
||||
* @n
|
||||
* @b Read @n
|
||||
* Environments: RT (non-RT optional)@n
|
||||
* Specific return values:
|
||||
* - -ETIMEDOUT
|
||||
* - -EINTR (interrupted explicitly or by signal)
|
||||
* - -EAGAIN (no data available in non-blocking mode)
|
||||
* - -EBADF (device has been closed while reading)
|
||||
* - -EIO (hardware error or broken bit stream)
|
||||
* .
|
||||
* @n
|
||||
* @b Write @n
|
||||
* Environments: RT (non-RT optional)@n
|
||||
* Specific return values:
|
||||
* - -ETIMEDOUT
|
||||
* - -EINTR (interrupted explicitly or by signal)
|
||||
* - -EAGAIN (no data written in non-blocking mode)
|
||||
* - -EBADF (device has been closed while writing)
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _RTSERIAL_H
|
||||
#define _RTSERIAL_H
|
||||
|
||||
#include <rtdm/rtdm.h>
|
||||
|
||||
#define RTSER_PROFILE_VER 3
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_DEF_BAUD @name RTSER_DEF_BAUD
|
||||
* Default baud rate
|
||||
* @{ */
|
||||
#define RTSER_DEF_BAUD 9600
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_xxx_PARITY @name RTSER_xxx_PARITY
|
||||
* Number of parity bits
|
||||
* @{ */
|
||||
#define RTSER_NO_PARITY 0x00
|
||||
#define RTSER_ODD_PARITY 0x01
|
||||
#define RTSER_EVEN_PARITY 0x03
|
||||
#define RTSER_DEF_PARITY RTSER_NO_PARITY
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_xxx_BITS @name RTSER_xxx_BITS
|
||||
* Number of data bits
|
||||
* @{ */
|
||||
#define RTSER_5_BITS 0x00
|
||||
#define RTSER_6_BITS 0x01
|
||||
#define RTSER_7_BITS 0x02
|
||||
#define RTSER_8_BITS 0x03
|
||||
#define RTSER_DEF_BITS RTSER_8_BITS
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_xxx_STOPB @name RTSER_xxx_STOPB
|
||||
* Number of stop bits
|
||||
* @{ */
|
||||
#define RTSER_1_STOPB 0x00
|
||||
/** valid only in combination with 5 data bits */
|
||||
#define RTSER_1_5_STOPB 0x01
|
||||
#define RTSER_2_STOPB 0x01
|
||||
#define RTSER_DEF_STOPB RTSER_1_STOPB
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_xxx_HAND @name RTSER_xxx_HAND
|
||||
* Handshake mechanisms
|
||||
* @{ */
|
||||
#define RTSER_NO_HAND 0x00
|
||||
#define RTSER_RTSCTS_HAND 0x01
|
||||
#define RTSER_DEF_HAND RTSER_NO_HAND
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_RS485_xxx @name RTSER_RS485_xxx
|
||||
* RS485 mode with automatic RTS handling
|
||||
* @{ */
|
||||
#define RTSER_RS485_DISABLE 0x00
|
||||
#define RTSER_RS485_ENABLE 0x01
|
||||
#define RTSER_DEF_RS485 RTSER_RS485_DISABLE
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_FIFO_xxx @name RTSER_FIFO_xxx
|
||||
* Reception FIFO interrupt threshold
|
||||
* @{ */
|
||||
#define RTSER_FIFO_DEPTH_1 0x00
|
||||
#define RTSER_FIFO_DEPTH_4 0x40
|
||||
#define RTSER_FIFO_DEPTH_8 0x80
|
||||
#define RTSER_FIFO_DEPTH_14 0xC0
|
||||
#define RTSER_DEF_FIFO_DEPTH RTSER_FIFO_DEPTH_1
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_TIMEOUT_xxx @name RTSER_TIMEOUT_xxx
|
||||
* Special timeout values, see also @ref RTDM_TIMEOUT_xxx
|
||||
* @{ */
|
||||
#define RTSER_TIMEOUT_INFINITE RTDM_TIMEOUT_INFINITE
|
||||
#define RTSER_TIMEOUT_NONE RTDM_TIMEOUT_NONE
|
||||
#define RTSER_DEF_TIMEOUT RTDM_TIMEOUT_INFINITE
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_xxx_TIMESTAMP_HISTORY @name RTSER_xxx_TIMESTAMP_HISTORY
|
||||
* Timestamp history control
|
||||
* @{ */
|
||||
#define RTSER_RX_TIMESTAMP_HISTORY 0x01
|
||||
#define RTSER_DEF_TIMESTAMP_HISTORY 0x00
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_EVENT_xxx @name RTSER_EVENT_xxx
|
||||
* Events bits
|
||||
* @{ */
|
||||
#define RTSER_EVENT_RXPEND 0x01
|
||||
#define RTSER_EVENT_ERRPEND 0x02
|
||||
#define RTSER_EVENT_MODEMHI 0x04
|
||||
#define RTSER_EVENT_MODEMLO 0x08
|
||||
#define RTSER_EVENT_TXEMPTY 0x10
|
||||
#define RTSER_DEF_EVENT_MASK 0x00
|
||||
/** @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_SET_xxx @name RTSER_SET_xxx
|
||||
* Configuration mask bits
|
||||
* @{ */
|
||||
#define RTSER_SET_BAUD 0x0001
|
||||
#define RTSER_SET_PARITY 0x0002
|
||||
#define RTSER_SET_DATA_BITS 0x0004
|
||||
#define RTSER_SET_STOP_BITS 0x0008
|
||||
#define RTSER_SET_HANDSHAKE 0x0010
|
||||
#define RTSER_SET_FIFO_DEPTH 0x0020
|
||||
#define RTSER_SET_TIMEOUT_RX 0x0100
|
||||
#define RTSER_SET_TIMEOUT_TX 0x0200
|
||||
#define RTSER_SET_TIMEOUT_EVENT 0x0400
|
||||
#define RTSER_SET_TIMESTAMP_HISTORY 0x0800
|
||||
#define RTSER_SET_EVENT_MASK 0x1000
|
||||
#define RTSER_SET_RS485 0x2000
|
||||
/** @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_LSR_xxx @name RTSER_LSR_xxx
|
||||
* Line status bits
|
||||
* @{ */
|
||||
#define RTSER_LSR_DATA 0x01
|
||||
#define RTSER_LSR_OVERRUN_ERR 0x02
|
||||
#define RTSER_LSR_PARITY_ERR 0x04
|
||||
#define RTSER_LSR_FRAMING_ERR 0x08
|
||||
#define RTSER_LSR_BREAK_IND 0x10
|
||||
#define RTSER_LSR_THR_EMTPY 0x20
|
||||
#define RTSER_LSR_TRANSM_EMPTY 0x40
|
||||
#define RTSER_LSR_FIFO_ERR 0x80
|
||||
#define RTSER_SOFT_OVERRUN_ERR 0x0100
|
||||
/** @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_MSR_xxx @name RTSER_MSR_xxx
|
||||
* Modem status bits
|
||||
* @{ */
|
||||
#define RTSER_MSR_DCTS 0x01
|
||||
#define RTSER_MSR_DDSR 0x02
|
||||
#define RTSER_MSR_TERI 0x04
|
||||
#define RTSER_MSR_DDCD 0x08
|
||||
#define RTSER_MSR_CTS 0x10
|
||||
#define RTSER_MSR_DSR 0x20
|
||||
#define RTSER_MSR_RI 0x40
|
||||
#define RTSER_MSR_DCD 0x80
|
||||
/** @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_MCR_xxx @name RTSER_MCR_xxx
|
||||
* Modem control bits
|
||||
* @{ */
|
||||
#define RTSER_MCR_DTR 0x01
|
||||
#define RTSER_MCR_RTS 0x02
|
||||
#define RTSER_MCR_OUT1 0x04
|
||||
#define RTSER_MCR_OUT2 0x08
|
||||
#define RTSER_MCR_LOOP 0x10
|
||||
/** @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @anchor RTSER_BREAK_xxx @name RTSER_BREAK_xxx
|
||||
* Break control
|
||||
* @{ */
|
||||
#define RTSER_BREAK_CLR 0x00
|
||||
#define RTSER_BREAK_SET 0x01
|
||||
|
||||
|
||||
/**
|
||||
* Serial device configuration
|
||||
*/
|
||||
typedef struct rtser_config {
|
||||
/** mask specifying valid fields, see @ref RTSER_SET_xxx */
|
||||
int config_mask;
|
||||
|
||||
/** baud rate, default @ref RTSER_DEF_BAUD */
|
||||
int baud_rate;
|
||||
|
||||
/** number of parity bits, see @ref RTSER_xxx_PARITY */
|
||||
int parity;
|
||||
|
||||
/** number of data bits, see @ref RTSER_xxx_BITS */
|
||||
int data_bits;
|
||||
|
||||
/** number of stop bits, see @ref RTSER_xxx_STOPB */
|
||||
int stop_bits;
|
||||
|
||||
/** handshake mechanisms, see @ref RTSER_xxx_HAND */
|
||||
int handshake;
|
||||
|
||||
/** reception FIFO interrupt threshold, see @ref RTSER_FIFO_xxx */
|
||||
int fifo_depth;
|
||||
|
||||
int reserved;
|
||||
|
||||
/** reception timeout, see @ref RTSER_TIMEOUT_xxx for special
|
||||
* values */
|
||||
nanosecs_rel_t rx_timeout;
|
||||
|
||||
/** transmission timeout, see @ref RTSER_TIMEOUT_xxx for special
|
||||
* values */
|
||||
nanosecs_rel_t tx_timeout;
|
||||
|
||||
/** event timeout, see @ref RTSER_TIMEOUT_xxx for special values */
|
||||
nanosecs_rel_t event_timeout;
|
||||
|
||||
/** enable timestamp history, see @ref RTSER_xxx_TIMESTAMP_HISTORY */
|
||||
int timestamp_history;
|
||||
|
||||
/** event mask to be used with @ref RTSER_RTIOC_WAIT_EVENT, see
|
||||
* @ref RTSER_EVENT_xxx */
|
||||
int event_mask;
|
||||
|
||||
/** enable RS485 mode, see @ref RTSER_RS485_xxx */
|
||||
int rs485;
|
||||
} rtser_config_t;
|
||||
|
||||
/**
|
||||
* Serial device status
|
||||
*/
|
||||
typedef struct rtser_status {
|
||||
/** line status register, see @ref RTSER_LSR_xxx */
|
||||
int line_status;
|
||||
|
||||
/** modem status register, see @ref RTSER_MSR_xxx */
|
||||
int modem_status;
|
||||
} rtser_status_t;
|
||||
|
||||
/**
|
||||
* Additional information about serial device events
|
||||
*/
|
||||
typedef struct rtser_event {
|
||||
/** signalled events, see @ref RTSER_EVENT_xxx */
|
||||
int events;
|
||||
|
||||
/** number of pending input characters */
|
||||
int rx_pending;
|
||||
|
||||
/** last interrupt timestamp */
|
||||
nanosecs_abs_t last_timestamp;
|
||||
|
||||
/** reception timestamp of oldest character in input queue */
|
||||
nanosecs_abs_t rxpend_timestamp;
|
||||
} rtser_event_t;
|
||||
|
||||
|
||||
#define RTIOC_TYPE_SERIAL RTDM_CLASS_SERIAL
|
||||
|
||||
|
||||
/*!
|
||||
* @name Sub-Classes of RTDM_CLASS_SERIAL
|
||||
* @{ */
|
||||
#define RTDM_SUBCLASS_16550A 0
|
||||
/** @} */
|
||||
|
||||
|
||||
/*!
|
||||
* @anchor SERIOCTLs @name IOCTLs
|
||||
* Serial device IOCTLs
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* Get serial device configuration
|
||||
*
|
||||
* @param[out] arg Pointer to configuration buffer (struct rtser_config)
|
||||
*
|
||||
* @return 0 on success, otherwise negative error code
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT, non-RT)
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
#define RTSER_RTIOC_GET_CONFIG \
|
||||
_IOR(RTIOC_TYPE_SERIAL, 0x00, struct rtser_config)
|
||||
|
||||
/**
|
||||
* Set serial device configuration
|
||||
*
|
||||
* @param[in] arg Pointer to configuration buffer (struct rtser_config)
|
||||
*
|
||||
* @return 0 on success, otherwise:
|
||||
*
|
||||
* - -EPERM is returned if the caller's context is invalid, see note below.
|
||||
*
|
||||
* - -ENOMEM is returned if a new history buffer for timestamps cannot be
|
||||
* allocated.
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT, non-RT)
|
||||
*
|
||||
* @note If rtser_config contains a valid timestamp_history and the
|
||||
* addressed device has been opened in non-real-time context, this IOCTL must
|
||||
* be issued in non-real-time context as well. Otherwise, this command will
|
||||
* fail.
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
#define RTSER_RTIOC_SET_CONFIG \
|
||||
_IOW(RTIOC_TYPE_SERIAL, 0x01, struct rtser_config)
|
||||
|
||||
/**
|
||||
* Get serial device status
|
||||
*
|
||||
* @param[out] arg Pointer to status buffer (struct rtser_status)
|
||||
*
|
||||
* @return 0 on success, otherwise negative error code
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT, non-RT)
|
||||
*
|
||||
* @note The error states @c RTSER_LSR_OVERRUN_ERR, @c RTSER_LSR_PARITY_ERR,
|
||||
* @c RTSER_LSR_FRAMING_ERR, and @c RTSER_SOFT_OVERRUN_ERR that may have
|
||||
* occured during previous read accesses to the device will be saved for being
|
||||
* reported via this IOCTL. Upon return from @c RTSER_RTIOC_GET_STATUS, the
|
||||
* saved state will be cleared.
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
#define RTSER_RTIOC_GET_STATUS \
|
||||
_IOR(RTIOC_TYPE_SERIAL, 0x02, struct rtser_status)
|
||||
|
||||
/**
|
||||
* Get serial device's modem contol register
|
||||
*
|
||||
* @param[out] arg Pointer to variable receiving the content (int, see
|
||||
* @ref RTSER_MCR_xxx)
|
||||
*
|
||||
* @return 0 on success, otherwise negative error code
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT, non-RT)
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
#define RTSER_RTIOC_GET_CONTROL \
|
||||
_IOR(RTIOC_TYPE_SERIAL, 0x03, int)
|
||||
|
||||
/**
|
||||
* Set serial device's modem contol register
|
||||
*
|
||||
* @param[in] arg New control register content (int, see @ref RTSER_MCR_xxx)
|
||||
*
|
||||
* @return 0 on success, otherwise negative error code
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT, non-RT)
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
#define RTSER_RTIOC_SET_CONTROL \
|
||||
_IOW(RTIOC_TYPE_SERIAL, 0x04, int)
|
||||
|
||||
/**
|
||||
* Wait on serial device events according to previously set mask
|
||||
*
|
||||
* @param[out] arg Pointer to event information buffer (struct rtser_event)
|
||||
*
|
||||
* @return 0 on success, otherwise:
|
||||
*
|
||||
* - -EBUSY is returned if another task is already waiting on events of this
|
||||
* device.
|
||||
*
|
||||
* - -EBADF is returned if the file descriptor is invalid or the device has
|
||||
* just been closed.
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT)
|
||||
*
|
||||
* Rescheduling: possible.
|
||||
*/
|
||||
#define RTSER_RTIOC_WAIT_EVENT \
|
||||
_IOR(RTIOC_TYPE_SERIAL, 0x05, struct rtser_event)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Set or clear break on UART output line
|
||||
*
|
||||
* @param[in] arg @c RTSER_BREAK_SET or @c RTSER_BREAK_CLR (int)
|
||||
*
|
||||
* @return 0 on success, otherwise negative error code
|
||||
*
|
||||
* Environments:
|
||||
*
|
||||
* This service can be called from:
|
||||
*
|
||||
* - Kernel module initialization/cleanup code
|
||||
* - Kernel-based task
|
||||
* - User-space task (RT, non-RT)
|
||||
*
|
||||
* @note A set break condition may also be cleared on UART line
|
||||
* reconfiguration.
|
||||
*
|
||||
* Rescheduling: never.
|
||||
*/
|
||||
#define RTSER_RTIOC_BREAK_CTL \
|
||||
_IOR(RTIOC_TYPE_SERIAL, 0x06, int)
|
||||
/** @} */
|
||||
|
||||
/*!
|
||||
* @anchor SERutils @name RT Serial example and utility programs
|
||||
* @{ */
|
||||
/** @example cross-link.c */
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _RTSERIAL_H */
|
||||
466
addons/rtdm/select.c
Normal file
466
addons/rtdm/select.c
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
/*!\file select.c
|
||||
* \brief file descriptors events multiplexing.
|
||||
* \author Gilles Chanteperdrix
|
||||
*
|
||||
* Copyright (C) 2008 Efixo <gilles.chanteperdrix@laposte.net>
|
||||
*
|
||||
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* RTAI is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* RTAI is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAI; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* \ingroup select
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup nucleus
|
||||
* \defgroup select File descriptors events multiplexing services.
|
||||
*
|
||||
* File descriptors events multiplexing services.
|
||||
*
|
||||
* This module implements the services needed for implementing the posix
|
||||
* "select" service, or any other events multiplexing services.
|
||||
*
|
||||
* Following the implementation of the posix select service, this module defines
|
||||
* three types of events:
|
||||
* - \a XNSELECT_READ meaning that a file descriptor is ready for reading;
|
||||
* - \a XNSELECT_WRITE meaning that a file descriptor is ready for writing;
|
||||
* - \a XNSELECT_EXCEPT meaning that a file descriptor received an exceptional
|
||||
* event.
|
||||
*
|
||||
* It works by defining two structures:
|
||||
* - a @a struct @a xnselect structure, which should be added to every file
|
||||
* descriptor for every event type (read, write, or except);
|
||||
* - a @a struct @a xnselector structure, the selection structure, passed by
|
||||
* the thread calling the xnselect service, where this service does all its
|
||||
* housekeeping.
|
||||
*@{*/
|
||||
|
||||
#include "select.h"
|
||||
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h> /* For hweight_long */
|
||||
|
||||
static xnqueue_t xnselectors;
|
||||
static int xnselect_apc;
|
||||
|
||||
#define link2binding(baddr, memb) \
|
||||
container_of(baddr, struct xnselect_binding, memb)
|
||||
|
||||
/**
|
||||
* Initialize a @a struct @a xnselect structure.
|
||||
*
|
||||
* This service must be called to initialize a @a struct @a xnselect structure
|
||||
* before it is bound to a selector by the means of xnselect_bind().
|
||||
*
|
||||
* @param select_block pointer to the xnselect structure to be initialized
|
||||
*/
|
||||
void xnselect_init(struct xnselect *select_block)
|
||||
{
|
||||
initq(&select_block->bindings);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnselect_init);
|
||||
|
||||
static inline int xnselect_wakeup(struct xnselector *selector)
|
||||
{
|
||||
return xnsynch_flush(&selector->synchbase, 0) == XNSYNCH_RESCHED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a file descriptor (represented by its @a xnselect structure) to a
|
||||
* selector block.
|
||||
*
|
||||
* @param select_block pointer to the @a struct @a xnselect to be bound;
|
||||
*
|
||||
* @param binding pointer to a newly allocated (using xnmalloc) @a struct
|
||||
* @a xnselect_binding;
|
||||
*
|
||||
* @param selector pointer to the selector structure;
|
||||
*
|
||||
* @param type type of events (@a XNSELECT_READ, @a XNSELECT_WRITE, or @a
|
||||
* XNSELECT_EXCEPT);
|
||||
*
|
||||
* @param index index of the file descriptor (represented by @a select_block) in the bit fields used by the @a selector structure;
|
||||
*
|
||||
* @param state current state of the file descriptor>.
|
||||
*
|
||||
* @a select_block must have been initialized with xnselect_init(),
|
||||
* the @a xnselector structure must have been initialized with
|
||||
* xnselector_init(), @a binding may be uninitialized.
|
||||
*
|
||||
* This service must be called with nklock locked, irqs off. For this reason,
|
||||
* the @a binding parameter must have been allocated by the caller outside the
|
||||
* locking section.
|
||||
*
|
||||
* @retval -EINVAL if @a type or @a index is invalid;
|
||||
* @retval 0 otherwise.
|
||||
*/
|
||||
int xnselect_bind(struct xnselect *select_block,
|
||||
struct xnselect_binding *binding,
|
||||
struct xnselector *selector,
|
||||
unsigned type,
|
||||
unsigned index,
|
||||
unsigned state)
|
||||
{
|
||||
if (type >= XNSELECT_MAX_TYPES || index > __FD_SETSIZE)
|
||||
return -EINVAL;
|
||||
|
||||
binding->selector = selector;
|
||||
binding->fd = select_block;
|
||||
binding->type = type;
|
||||
binding->bit_index = index;
|
||||
inith(&binding->link);
|
||||
inith(&binding->slink);
|
||||
|
||||
appendq(&selector->bindings, &binding->slink);
|
||||
appendq(&select_block->bindings, &binding->link);
|
||||
__FD_SET__(index, &selector->fds[type].expected);
|
||||
if (state) {
|
||||
__FD_SET__(index, &selector->fds[type].pending);
|
||||
if (xnselect_wakeup(selector))
|
||||
xnpod_schedule();
|
||||
} else
|
||||
__FD_CLR__(index, &selector->fds[type].pending);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnselect_bind);
|
||||
|
||||
/* Must be called with nklock locked irqs off */
|
||||
int __xnselect_signal(struct xnselect *select_block, unsigned state)
|
||||
{
|
||||
xnholder_t *holder;
|
||||
int resched;
|
||||
|
||||
for(resched = 0, holder = getheadq(&select_block->bindings);
|
||||
holder; holder = nextq(&select_block->bindings, holder)) {
|
||||
struct xnselect_binding *binding;
|
||||
struct xnselector *selector;
|
||||
|
||||
binding = link2binding(holder, link);
|
||||
|
||||
selector = binding->selector;
|
||||
if (state) {
|
||||
if (!__FD_ISSET__(binding->bit_index,
|
||||
&selector->fds[binding->type].pending)) {
|
||||
__FD_SET__(binding->bit_index,
|
||||
&selector->fds[binding->type].pending);
|
||||
if (xnselect_wakeup(selector))
|
||||
resched = 1;
|
||||
}
|
||||
} else
|
||||
__FD_CLR__(binding->bit_index,
|
||||
&selector->fds[binding->type].pending);
|
||||
}
|
||||
|
||||
return resched;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__xnselect_signal);
|
||||
|
||||
/**
|
||||
* Destroy the @a xnselect structure associated with a file descriptor.
|
||||
*
|
||||
* Any binding with a @a xnselector block is destroyed.
|
||||
*
|
||||
* @param select_block pointer to the @a xnselect structure associated with a file descriptor
|
||||
*/
|
||||
void xnselect_destroy(struct xnselect *select_block)
|
||||
{
|
||||
xnholder_t *holder;
|
||||
int resched = 0;
|
||||
spl_t s;
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
while ((holder = getq(&select_block->bindings))) {
|
||||
struct xnselect_binding *binding;
|
||||
struct xnselector *selector;
|
||||
|
||||
binding = link2binding(holder, link);
|
||||
selector = binding->selector;
|
||||
|
||||
__FD_CLR__(binding->bit_index,
|
||||
&selector->fds[binding->type].expected);
|
||||
if (!__FD_ISSET__(binding->bit_index,
|
||||
&selector->fds[binding->type].pending)) {
|
||||
__FD_SET__(binding->bit_index,
|
||||
&selector->fds[binding->type].pending);
|
||||
if (xnselect_wakeup(selector))
|
||||
resched = 1;
|
||||
}
|
||||
removeq(&selector->bindings, &binding->slink);
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
|
||||
xnfree(binding);
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
}
|
||||
if (resched)
|
||||
xnpod_schedule();
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnselect_destroy);
|
||||
|
||||
static unsigned
|
||||
fd_set_andnot(fd_set *result, fd_set *first, fd_set *second, unsigned n)
|
||||
{
|
||||
unsigned i, not_empty = 0;
|
||||
|
||||
for (i = 0; i < __FDELT__(n); i++)
|
||||
if((result->fds_bits[i] =
|
||||
first->fds_bits[i] & ~(second->fds_bits[i])))
|
||||
not_empty = 1;
|
||||
|
||||
if (i < __FDSET_LONGS__
|
||||
&& (result->fds_bits[i] =
|
||||
first->fds_bits[i] & ~(second->fds_bits[i]) & (__FDMASK__(n) - 1)))
|
||||
not_empty = 1;
|
||||
|
||||
return not_empty;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
fd_set_and(fd_set *result, fd_set *first, fd_set *second, unsigned n)
|
||||
{
|
||||
unsigned i, not_empty = 0;
|
||||
|
||||
for (i = 0; i < __FDELT__(n); i++)
|
||||
if((result->fds_bits[i] =
|
||||
first->fds_bits[i] & second->fds_bits[i]))
|
||||
not_empty = 1;
|
||||
|
||||
if (i < __FDSET_LONGS__
|
||||
&& (result->fds_bits[i] =
|
||||
first->fds_bits[i] & second->fds_bits[i] & (__FDMASK__(n) - 1)))
|
||||
not_empty = 1;
|
||||
|
||||
return not_empty;
|
||||
}
|
||||
|
||||
static void fd_set_zeropad(fd_set *set, unsigned n)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
i = __FDELT__(n);
|
||||
|
||||
if (i < __FDSET_LONGS__)
|
||||
set->fds_bits[i] &= (__FDMASK__(n) - 1);
|
||||
|
||||
for(i++; i < __FDSET_LONGS__; i++)
|
||||
set->fds_bits[i] = 0;
|
||||
}
|
||||
|
||||
static unsigned fd_set_popcount(fd_set *set, unsigned n)
|
||||
{
|
||||
unsigned count = 0, i;
|
||||
|
||||
for (i = 0; i < __FDELT__(n); i++)
|
||||
if (set->fds_bits[i])
|
||||
count += hweight_long(set->fds_bits[i]);
|
||||
|
||||
if (i < __FDSET_LONGS__ && (set->fds_bits[i] & (__FDMASK__(n) - 1)))
|
||||
count += hweight_long(set->fds_bits[i] & (__FDMASK__(n) - 1));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a selector structure.
|
||||
*
|
||||
* @param selector The selector structure to be initialized.
|
||||
*
|
||||
* @retval 0
|
||||
*/
|
||||
int xnselector_init(struct xnselector *selector)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
xnsynch_init(&selector->synchbase, XNSYNCH_FIFO, NULL);
|
||||
for (i = 0; i < XNSELECT_MAX_TYPES; i++) {
|
||||
__FD_ZERO__(&selector->fds[i].expected);
|
||||
__FD_ZERO__(&selector->fds[i].pending);
|
||||
}
|
||||
initq(&selector->bindings);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnselector_init);
|
||||
|
||||
/**
|
||||
* Check the state of a number of file descriptors, wait for a state change if
|
||||
* no descriptor is ready.
|
||||
*
|
||||
* @param selector structure to check for pending events
|
||||
* @param out_fds The set of descriptors with pending events if a strictly positive number is returned, or the set of descriptors not yet bound if -ECHRNG is returned;
|
||||
* @param in_fds the set of descriptors which events should be checked
|
||||
* @param nfds the highest-numbered descriptor in any of the @a in_fds sets, plus 1;
|
||||
* @param timeout the timeout, whose meaning depends on @a timeout_mode, note
|
||||
* that xnselect() pass @a timeout and @a timeout_mode unchanged to
|
||||
* xnsynch_sleep_on, so passing a relative value different from XN_INFINITE as a
|
||||
* timeout with @a timeout_mode set to XN_RELATIVE, will cause a longer sleep
|
||||
* than expected if the sleep is interrupted.
|
||||
* @param timeout_mode the mode of @a timeout.
|
||||
*
|
||||
* @retval -EINVAL if @a nfds is negative;
|
||||
* @retval -ECHRNG if some of the descriptors passed in @a in_fds have not yet
|
||||
* been registered with xnselect_bind(), @a out_fds contains the set of such
|
||||
* descriptors;
|
||||
* @retval -EINTR if @a xnselect was interrupted while waiting;
|
||||
* @retval 0 in case of timeout.
|
||||
* @retval the number of file descriptors having received an event.
|
||||
*/
|
||||
int xnselect(struct xnselector *selector,
|
||||
fd_set *out_fds[XNSELECT_MAX_TYPES],
|
||||
fd_set *in_fds[XNSELECT_MAX_TYPES],
|
||||
int nfds,
|
||||
xnticks_t timeout, xntmode_t timeout_mode)
|
||||
{
|
||||
unsigned i, not_empty = 0;
|
||||
xnthread_t *thread;
|
||||
spl_t s;
|
||||
|
||||
if ((unsigned) nfds > __FD_SETSIZE)
|
||||
return -EINVAL;
|
||||
|
||||
thread = xnpod_current_thread();
|
||||
|
||||
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
|
||||
if (out_fds[i])
|
||||
fd_set_zeropad(out_fds[i], nfds);
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
|
||||
if (out_fds[i]
|
||||
&& fd_set_andnot(out_fds[i], in_fds[i],
|
||||
&selector->fds[i].expected, nfds))
|
||||
not_empty = 1;
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
|
||||
if (not_empty)
|
||||
return -ECHRNG;
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
|
||||
if (out_fds[i]
|
||||
&& fd_set_and(out_fds[i], in_fds[i],
|
||||
&selector->fds[i].pending, nfds))
|
||||
not_empty = 1;
|
||||
|
||||
while (!not_empty) {
|
||||
xnsynch_sleep_on(&selector->synchbase, timeout, timeout_mode);
|
||||
|
||||
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
|
||||
if (out_fds[i]
|
||||
&& fd_set_and(out_fds[i], in_fds[i],
|
||||
&selector->fds[i].pending, nfds))
|
||||
not_empty = 1;
|
||||
|
||||
if (xnthread_test_info(thread, XNBREAK | XNTIMEO))
|
||||
break;
|
||||
}
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
|
||||
if (not_empty) {
|
||||
unsigned count;
|
||||
|
||||
for (count = 0, i = 0; i < XNSELECT_MAX_TYPES; i++)
|
||||
if (out_fds[i])
|
||||
count += fd_set_popcount(out_fds[i], nfds);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
if (xnthread_test_info(thread, XNBREAK))
|
||||
return -EINTR;
|
||||
|
||||
return 0; /* Timeout */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnselect);
|
||||
|
||||
/**
|
||||
* Destroy a selector block.
|
||||
*
|
||||
* All bindings with file descriptor are destroyed.
|
||||
*
|
||||
* @param selector the selector block to be destroyed
|
||||
*/
|
||||
void xnselector_destroy(struct xnselector *selector)
|
||||
{
|
||||
spl_t s;
|
||||
|
||||
inith(&selector->destroy_link);
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
appendq(&xnselectors, &selector->destroy_link);
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
rthal_apc_schedule(xnselect_apc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xnselector_destroy);
|
||||
|
||||
static void xnselector_destroy_loop(void *cookie)
|
||||
{
|
||||
struct xnselector *selector;
|
||||
xnholder_t *holder;
|
||||
int resched;
|
||||
spl_t s;
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
while ((holder = getq(&xnselectors))) {
|
||||
selector = container_of(holder, struct xnselector, destroy_link);
|
||||
while ((holder = getq(&selector->bindings))) {
|
||||
struct xnselect_binding *binding;
|
||||
struct xnselect *fd;
|
||||
|
||||
binding = link2binding(holder, slink);
|
||||
fd = binding->fd;
|
||||
removeq(&fd->bindings, &binding->link);
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
|
||||
xnfree(binding);
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
}
|
||||
resched =
|
||||
xnsynch_destroy(&selector->synchbase) == XNSYNCH_RESCHED;
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
|
||||
xnfree(selector);
|
||||
if (resched)
|
||||
xnpod_schedule();
|
||||
|
||||
xnlock_get_irqsave(&nklock, s);
|
||||
}
|
||||
xnlock_put_irqrestore(&nklock, s);
|
||||
}
|
||||
|
||||
int xnselect_mount(void)
|
||||
{
|
||||
initq(&xnselectors);
|
||||
xnselect_apc = rthal_apc_alloc("xnselectors_destroy",
|
||||
xnselector_destroy_loop, NULL);
|
||||
if (xnselect_apc < 0)
|
||||
return xnselect_apc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnselect_umount(void)
|
||||
{
|
||||
rthal_apc_free(xnselect_apc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
169
addons/rtdm/select.h
Normal file
169
addons/rtdm/select.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*!\file select.h
|
||||
* \brief file descriptors events multiplexing header.
|
||||
* \author Gilles Chanteperdrix
|
||||
*
|
||||
* Copyright (C) 2008 Efixo <gilles.chanteperdrix@laposte.net>
|
||||
*
|
||||
* Rtai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Rtai is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Rtai; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* \ingroup select
|
||||
*/
|
||||
|
||||
#ifndef XNSELECT_H
|
||||
#define XNSELECT_H
|
||||
|
||||
/*! \addtogroup select
|
||||
*@{*/
|
||||
|
||||
#include "xn.h"
|
||||
|
||||
#define XNSELECT_READ 0
|
||||
#define XNSELECT_WRITE 1
|
||||
#define XNSELECT_EXCEPT 2
|
||||
#define XNSELECT_MAX_TYPES 3
|
||||
|
||||
struct xnselector {
|
||||
xnsynch_t synchbase;
|
||||
struct fds {
|
||||
fd_set expected;
|
||||
fd_set pending;
|
||||
} fds [XNSELECT_MAX_TYPES];
|
||||
xnholder_t destroy_link;
|
||||
xnqueue_t bindings; /* only used by xnselector_destroy */
|
||||
};
|
||||
|
||||
#define __NFDBITS__ (8 * sizeof(unsigned long))
|
||||
#define __FDSET_LONGS__ (__FD_SETSIZE/__NFDBITS__)
|
||||
#define __FDELT__(d) ((d) / __NFDBITS__)
|
||||
#define __FDMASK__(d) (1UL << ((d) % __NFDBITS__))
|
||||
|
||||
static inline void __FD_SET__(unsigned long __fd, __kernel_fd_set *__fdsetp)
|
||||
{
|
||||
unsigned long __tmp = __fd / __NFDBITS__;
|
||||
unsigned long __rem = __fd % __NFDBITS__;
|
||||
__fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
|
||||
}
|
||||
|
||||
static inline void __FD_CLR__(unsigned long __fd, __kernel_fd_set *__fdsetp)
|
||||
{
|
||||
unsigned long __tmp = __fd / __NFDBITS__;
|
||||
unsigned long __rem = __fd % __NFDBITS__;
|
||||
__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
|
||||
}
|
||||
|
||||
static inline int __FD_ISSET__(unsigned long __fd, const __kernel_fd_set *__p)
|
||||
{
|
||||
unsigned long __tmp = __fd / __NFDBITS__;
|
||||
unsigned long __rem = __fd % __NFDBITS__;
|
||||
return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
|
||||
}
|
||||
|
||||
static inline void __FD_ZERO__(__kernel_fd_set *__p)
|
||||
{
|
||||
unsigned long *__tmp = __p->fds_bits;
|
||||
int __i;
|
||||
|
||||
__i = __FDSET_LONGS__;
|
||||
while (__i) {
|
||||
__i--;
|
||||
*__tmp = 0;
|
||||
__tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
|
||||
struct xnselect {
|
||||
xnqueue_t bindings;
|
||||
};
|
||||
|
||||
#define DECLARE_XNSELECT(name) struct xnselect name
|
||||
|
||||
struct xnselect_binding {
|
||||
struct xnselector *selector;
|
||||
struct xnselect *fd;
|
||||
unsigned type;
|
||||
unsigned bit_index;
|
||||
xnholder_t link; /* link in selected fds list. */
|
||||
xnholder_t slink; /* link in selector list */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void xnselect_init(struct xnselect *select_block);
|
||||
|
||||
int xnselect_bind(struct xnselect *select_block,
|
||||
struct xnselect_binding *binding,
|
||||
struct xnselector *selector,
|
||||
unsigned type,
|
||||
unsigned bit_index,
|
||||
unsigned state);
|
||||
|
||||
int __xnselect_signal(struct xnselect *select_block, unsigned state);
|
||||
|
||||
/**
|
||||
* Signal a file descriptor state change.
|
||||
*
|
||||
* @param select_block pointer to an @a xnselect structure representing the file
|
||||
* descriptor whose state changed;
|
||||
* @param state new value of the state.
|
||||
*
|
||||
* @retval 1 if rescheduling is needed;
|
||||
* @retval 0 otherwise.
|
||||
*/
|
||||
static inline int
|
||||
xnselect_signal(struct xnselect *select_block, unsigned state)
|
||||
{
|
||||
if (!emptyq_p(&select_block->bindings))
|
||||
return __xnselect_signal(select_block, state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xnselect_destroy(struct xnselect *select_block);
|
||||
|
||||
int xnselector_init(struct xnselector *selector);
|
||||
|
||||
int xnselect(struct xnselector *selector,
|
||||
fd_set *out_fds[XNSELECT_MAX_TYPES],
|
||||
fd_set *in_fds[XNSELECT_MAX_TYPES],
|
||||
int nfds,
|
||||
xnticks_t timeout, xntmode_t timeout_mode);
|
||||
|
||||
void xnselector_destroy(struct xnselector *selector);
|
||||
|
||||
int xnselect_mount(void);
|
||||
|
||||
int xnselect_umount(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#else /* !CONFIG_RTAI_RTDM_SELECT */
|
||||
struct xnselector;
|
||||
#define DECLARE_XNSELECT(name)
|
||||
#define xnselect_init(block)
|
||||
#define xnselect_bind(select_block,binding,selector,type,bit_index,state) \
|
||||
({ -EBADF; })
|
||||
#define xnselect_signal(block, state) ({ int __ret = 0; __ret; })
|
||||
#define xnselect_destroy(block)
|
||||
#endif /* !CONFIG_RTAI_RTDM_SELECT */
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* XNSELECT_H */
|
||||
651
addons/rtdm/xn.h
Normal file
651
addons/rtdm/xn.h
Normal file
|
|
@ -0,0 +1,651 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
// Wrappers and inlines to avoid too much an editing of RTDM code.
|
||||
// The core stuff is just RTAI in disguise.
|
||||
|
||||
#ifndef _RTAI_XNSTUFF_H
|
||||
#define _RTAI_XNSTUFF_H
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mman.h>
|
||||
|
||||
#include <rtai_schedcore.h>
|
||||
|
||||
#define CONFIG_RTAI_OPT_PERVASIVE
|
||||
|
||||
#ifndef CONFIG_RTAI_DEBUG_RTDM
|
||||
#define CONFIG_RTAI_DEBUG_RTDM 0
|
||||
#endif
|
||||
|
||||
#define RTAI_DEBUG(subsystem) (CONFIG_RTAI_DEBUG_##subsystem > 0)
|
||||
|
||||
#define RTAI_ASSERT(subsystem, cond, action) do { \
|
||||
if (unlikely(CONFIG_RTAI_DEBUG_##subsystem > 0 && !(cond))) { \
|
||||
xnlogerr("assertion failed at %s:%d (%s)\n", __FILE__, __LINE__, (#cond)); \
|
||||
action; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define RTAI_BUGON(subsystem, cond) do { /*\
|
||||
if (unlikely(CONFIG_RTAI_DEBUG_##subsystem > 0 && (cond))) \
|
||||
xnpod_fatal("bug at %s:%d (%s)", __FILE__, __LINE__, (#cond)); */ \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
With what above we let some assertion diagnostic. Here below we keep knowledge
|
||||
of specific assertions we care of.
|
||||
*/
|
||||
|
||||
#define xnpod_root_p() (!current->rtai_tskext(TSKEXT0) || !((RT_TASK *)(current->rtai_tskext(TSKEXT0)))->is_hard)
|
||||
#define xnshadow_thread(t) ((xnthread_t *)current->rtai_tskext(TSKEXT0))
|
||||
#define rthal_local_irq_test() (!rtai_save_flags_irqbit())
|
||||
#define rthal_local_irq_enable rtai_sti
|
||||
#define rthal_domain rtai_domain
|
||||
#define rthal_local_irq_disabled() \
|
||||
({ \
|
||||
unsigned long __flags, __ret; \
|
||||
local_irq_save_hw_smp(__flags); \
|
||||
__ret = ipipe_test_pipeline_from(&rthal_domain); \
|
||||
local_irq_restore_hw_smp(__flags); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
|
||||
#define _MODULE_PARM_STRING_charp "s"
|
||||
#define compat_module_param_array(name, type, count, perm) \
|
||||
static inline void *__check_existence_##name(void) { return &name; } \
|
||||
MODULE_PARM(name, "1-" __MODULE_STRING(count) _MODULE_PARM_STRING_##type)
|
||||
|
||||
typedef unsigned long phys_addr_t;
|
||||
|
||||
#else
|
||||
|
||||
#define compat_module_param_array(name, type, count, perm) \
|
||||
module_param_array(name, type, NULL, perm)
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
|
||||
#define trace_mark(ev, fmt, args...) do { } while (0)
|
||||
#else
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
|
||||
#include <linux/marker.h>
|
||||
#endif
|
||||
#define trace_mark(ev, fmt, args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
//recursive smp locks, as for RTAI global lock stuff but with an own name
|
||||
|
||||
#define nklock (*((xnlock_t *)rtai_cpu_lock))
|
||||
|
||||
#define XNARCH_LOCK_UNLOCKED (xnlock_t) { { 0, 0 } }
|
||||
|
||||
typedef unsigned long spl_t;
|
||||
typedef struct { volatile unsigned long lock[2]; } xnlock_t;
|
||||
|
||||
#ifndef list_first_entry
|
||||
#define list_first_entry(ptr, type, member) \
|
||||
list_entry((ptr)->next, type, member)
|
||||
#endif
|
||||
|
||||
#ifndef local_irq_save_hw_smp
|
||||
#ifdef CONFIG_SMP
|
||||
#define local_irq_save_hw_smp(flags) local_irq_save_hw(flags)
|
||||
#define local_irq_restore_hw_smp(flags) local_irq_restore_hw(flags)
|
||||
#else /* !CONFIG_SMP */
|
||||
#define local_irq_save_hw_smp(flags) do { (void)(flags); } while (0)
|
||||
#define local_irq_restore_hw_smp(flags) do { } while (0)
|
||||
#endif /* !CONFIG_SMP */
|
||||
#endif /* !local_irq_save_hw_smp */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#define DECLARE_XNLOCK(lock) xnlock_t lock
|
||||
#define DECLARE_EXTERN_XNLOCK(lock) extern xnlock_t lock
|
||||
#define DEFINE_XNLOCK(lock) xnlock_t lock = XNARCH_LOCK_UNLOCKED
|
||||
#define DEFINE_PRIVATE_XNLOCK(lock) static DEFINE_XNLOCK(lock)
|
||||
|
||||
static inline void xnlock_init(xnlock_t *lock)
|
||||
{
|
||||
*lock = XNARCH_LOCK_UNLOCKED;
|
||||
}
|
||||
|
||||
static inline void xnlock_get(xnlock_t *lock)
|
||||
{
|
||||
barrier();
|
||||
rtai_cli();
|
||||
if (!test_and_set_bit(hal_processor_id(), &lock->lock[0])) {
|
||||
rtai_spin_glock(&lock->lock[0]);
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
|
||||
static inline void xnlock_put(xnlock_t *lock)
|
||||
{
|
||||
barrier();
|
||||
rtai_cli();
|
||||
if (test_and_clear_bit(hal_processor_id(), &lock->lock[0])) {
|
||||
rtai_spin_gunlock(&lock->lock[0]);
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
|
||||
static inline spl_t __xnlock_get_irqsave(xnlock_t *lock)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
barrier();
|
||||
flags = rtai_save_flags_irqbit_and_cli();
|
||||
if (!test_and_set_bit(hal_processor_id(), &lock->lock[0])) {
|
||||
rtai_spin_glock(&lock->lock[0]);
|
||||
barrier();
|
||||
return flags | 1;
|
||||
}
|
||||
barrier();
|
||||
return flags;
|
||||
}
|
||||
|
||||
#define xnlock_get_irqsave(lock, flags) \
|
||||
do { flags = __xnlock_get_irqsave(lock); } while (0)
|
||||
|
||||
static inline void xnlock_put_irqrestore(xnlock_t *lock, spl_t flags)
|
||||
{
|
||||
barrier();
|
||||
if (test_and_clear_bit(0, &flags)) {
|
||||
xnlock_put(lock);
|
||||
} else {
|
||||
xnlock_get(lock);
|
||||
}
|
||||
if (flags) {
|
||||
rtai_sti();
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SMP */
|
||||
|
||||
#define DECLARE_XNLOCK(lock)
|
||||
#define DECLARE_EXTERN_XNLOCK(lock)
|
||||
#define DEFINE_XNLOCK(lock)
|
||||
#define DEFINE_PRIVATE_XNLOCK(lock)
|
||||
|
||||
#define xnlock_init(lock) do { } while(0)
|
||||
#define xnlock_get(lock) rtai_cli()
|
||||
#define xnlock_put(lock) rtai_sti()
|
||||
#define xnlock_get_irqsave(lock, flags) rtai_save_flags_and_cli(flags)
|
||||
#define xnlock_put_irqrestore(lock, flags) rtai_restore_flags(flags)
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
// memory allocation
|
||||
|
||||
#define xnmalloc rt_malloc
|
||||
#define xnfree rt_free
|
||||
#define xnarch_fault_range(vma)
|
||||
|
||||
// in kernel printing (taken from RTDM pet system)
|
||||
|
||||
#define XNARCH_PROMPT "RTDM: "
|
||||
|
||||
#define xnprintf(fmt, args...) printk(KERN_INFO XNARCH_PROMPT fmt, ##args)
|
||||
#define xnlogerr(fmt, args...) printk(KERN_ERR XNARCH_PROMPT fmt, ##args)
|
||||
#define xnlogwarn xnlogerr
|
||||
|
||||
// user space access (taken from Linux)
|
||||
|
||||
#define __xn_access_ok(task, type, addr, size) \
|
||||
(access_ok(type, addr, size))
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#define __xn_copy_from_user(task, dstP, srcP, n) \
|
||||
({ long err = __copy_from_user(dstP, srcP, n); err; })
|
||||
|
||||
#define __xn_copy_to_user(task, dstP, srcP, n) \
|
||||
({ long err = __copy_to_user(dstP, srcP, n); err; })
|
||||
#else
|
||||
#define __xn_copy_from_user(task, dstP, srcP, n) \
|
||||
({ long err = __copy_from_user_inatomic(dstP, srcP, n); err; })
|
||||
|
||||
#define __xn_copy_to_user(task, dstP, srcP, n) \
|
||||
({ long err = __copy_to_user_inatomic(dstP, srcP, n); err; })
|
||||
#endif
|
||||
|
||||
#if !defined CONFIG_M68K || defined CONFIG_MMU
|
||||
#define __xn_strncpy_from_user(task, dstP, srcP, n) \
|
||||
({ long err = rt_strncpy_from_user(dstP, srcP, n); err; })
|
||||
/* ({ long err = __strncpy_from_user(dstP, srcP, n); err; }) */
|
||||
#else
|
||||
#define __xn_strncpy_from_user(task, dstP, srcP, n) \
|
||||
({ long err = strncpy_from_user(dstP, srcP, n); err; })
|
||||
#endif /* CONFIG_M68K */
|
||||
|
||||
static inline int xnarch_remap_io_page_range(struct file *filp, struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return remap_page_range(from, to, size, prot);
|
||||
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
|
||||
return remap_pfn_range(vma, from, (to) >> PAGE_SHIFT, size, prot);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
|
||||
return remap_pfn_range(vma, from, (to) >> PAGE_SHIFT, size, prot);
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) */
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return remap_page_range(vma, from, to, size, prot);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
|
||||
}
|
||||
|
||||
#define wrap_remap_kmem_page_range(vma,from,to,size,prot) ({ \
|
||||
vma->vm_flags |= VM_RESERVED; \
|
||||
remap_page_range(from,to,size,prot); \
|
||||
})
|
||||
|
||||
static inline int xnarch_remap_kmem_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return remap_page_range(from, to, size, prot);
|
||||
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) && defined(CONFIG_MMU)
|
||||
return remap_pfn_range(vma, from, to >> PAGE_SHIFT, size, prot);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
|
||||
return remap_pfn_range(vma, from, to >> PAGE_SHIFT, size, prot);
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) */
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return remap_page_range(from, to, size, prot);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
|
||||
}
|
||||
|
||||
#include <rtai_shm.h>
|
||||
#define __va_to_kva(adr) UVIRT_TO_KVA(adr)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
static inline int xnarch_remap_vm_page(struct vm_area_struct *vma, unsigned long from, unsigned long to)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return remap_page_range(from, virt_to_phys((void *)__va_to_kva(to)), PAGE_SIZE, PAGE_SHARED);
|
||||
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
|
||||
|
||||
#ifndef VM_RESERVED
|
||||
#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) && defined(CONFIG_MMU)
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return vm_insert_page(vma, from, vmalloc_to_page((void *)to));
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
|
||||
return remap_pfn_range(vma, from, virt_to_phys((void *)__va_to_kva(to)) >> PAGE_SHIFT, PAGE_SHIFT, PAGE_SHARED);
|
||||
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) */
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
return remap_page_range(from, virt_to_phys((void *)__va_to_kva(to)), PAGE_SIZE, PAGE_SHARED);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt setup/management (adopted_&|_adapted from RTDM pet system)
|
||||
|
||||
#define RTHAL_NR_IRQS IPIPE_NR_XIRQS
|
||||
|
||||
#define XN_ISR_NONE 0x1
|
||||
#define XN_ISR_HANDLED 0x2
|
||||
|
||||
#define XN_ISR_PROPAGATE 0x100
|
||||
#define XN_ISR_NOENABLE 0x200
|
||||
#define XN_ISR_BITMASK ~0xff
|
||||
|
||||
#define XN_ISR_SHARED 0x1
|
||||
#define XN_ISR_EDGE 0x2
|
||||
|
||||
#define XN_ISR_ATTACHED 0x10000
|
||||
|
||||
#if !defined(CONFIG_PPC) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,32) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)))
|
||||
|
||||
#define rthal_virtualize_irq(dom, irq, isr, cookie, ackfn, mode) \
|
||||
ipipe_virtualize_irq(dom, irq, isr, ackfn, mode)
|
||||
|
||||
#else
|
||||
|
||||
#define rthal_virtualize_irq(dom, irq, isr, cookie, ackfn, mode) \
|
||||
ipipe_virtualize_irq(dom, irq, isr, cookie, ackfn, mode)
|
||||
|
||||
#endif
|
||||
|
||||
struct xnintr;
|
||||
|
||||
typedef int (*xnisr_t)(struct xnintr *intr);
|
||||
|
||||
typedef int (*xniack_t)(unsigned irq);
|
||||
|
||||
typedef unsigned long xnflags_t;
|
||||
|
||||
typedef atomic_t atomic_counter_t;
|
||||
|
||||
typedef RTIME xnticks_t;
|
||||
|
||||
typedef struct xnstat_exectime {
|
||||
xnticks_t start;
|
||||
xnticks_t total;
|
||||
} xnstat_exectime_t;
|
||||
|
||||
typedef struct xnstat_counter {
|
||||
int counter;
|
||||
} xnstat_counter_t;
|
||||
#define xnstat_counter_inc(c) ((c)->counter++)
|
||||
|
||||
typedef struct xnintr {
|
||||
#ifdef CONFIG_RTAI_RTDM_SHIRQ
|
||||
struct xnintr *next;
|
||||
#endif /* CONFIG_RTAI_RTDM_SHIRQ */
|
||||
unsigned unhandled;
|
||||
xnisr_t isr;
|
||||
void *cookie;
|
||||
xnflags_t flags;
|
||||
unsigned irq;
|
||||
xniack_t iack;
|
||||
const char *name;
|
||||
struct {
|
||||
xnstat_counter_t hits;
|
||||
xnstat_exectime_t account;
|
||||
xnstat_exectime_t sum;
|
||||
} stat[RTAI_NR_CPUS];
|
||||
|
||||
} xnintr_t;
|
||||
|
||||
#define xnsched_cpu(sched) rtai_cpuid()
|
||||
|
||||
int xnintr_shirq_attach(xnintr_t *intr, void *cookie);
|
||||
int xnintr_shirq_detach(xnintr_t *intr);
|
||||
int xnintr_init (xnintr_t *intr, const char *name, unsigned irq, xnisr_t isr, xniack_t iack, xnflags_t flags);
|
||||
int xnintr_destroy (xnintr_t *intr);
|
||||
int xnintr_attach (xnintr_t *intr, void *cookie);
|
||||
int xnintr_detach (xnintr_t *intr);
|
||||
int xnintr_enable (xnintr_t *intr);
|
||||
int xnintr_disable (xnintr_t *intr);
|
||||
|
||||
/* Atomic operations are already serializing on x86 */
|
||||
#define xnarch_before_atomic_dec() smp_mb__before_atomic_dec()
|
||||
#define xnarch_after_atomic_dec() smp_mb__after_atomic_dec()
|
||||
#define xnarch_before_atomic_inc() smp_mb__before_atomic_inc()
|
||||
#define xnarch_after_atomic_inc() smp_mb__after_atomic_inc()
|
||||
|
||||
#define xnarch_memory_barrier() smp_mb()
|
||||
#define xnarch_atomic_get(pcounter) atomic_read(pcounter)
|
||||
#define xnarch_atomic_inc(pcounter) atomic_inc(pcounter)
|
||||
#define xnarch_atomic_dec(pcounter) atomic_dec(pcounter)
|
||||
|
||||
#define testbits(flags, mask) ((flags) & (mask))
|
||||
#define __testbits(flags, mask) ((flags) & (mask))
|
||||
#define __setbits(flags, mask) do { (flags) |= (mask); } while(0)
|
||||
#define __clrbits(flags, mask) do { (flags) &= ~(mask); } while(0)
|
||||
|
||||
#define xnarch_chain_irq rt_pend_linux_irq
|
||||
#define xnarch_end_irq rt_enable_irq
|
||||
|
||||
#define xnarch_hook_irq(irq, handler, iack, intr) \
|
||||
rt_request_irq_wack(irq, (void *)handler, intr, 0, (void *)iack);
|
||||
#define xnarch_release_irq(irq) \
|
||||
rt_release_irq(irq);
|
||||
|
||||
extern struct rtai_realtime_irq_s rtai_realtime_irq[];
|
||||
//#define xnarch_get_irq_cookie(irq) (rtai_realtime_irq[irq].cookie)
|
||||
#define xnarch_get_irq_cookie(irq) (rtai_domain.irqs[irq].cookie)
|
||||
|
||||
extern unsigned long IsolCpusMask;
|
||||
#define xnarch_set_irq_affinity(irq, nkaffinity) \
|
||||
rt_assign_irq_to_cpu(irq, IsolCpusMask)
|
||||
|
||||
// support for RTDM timers
|
||||
|
||||
struct rtdm_timer_struct {
|
||||
struct rtdm_timer_struct *next, *prev;
|
||||
int priority, cpuid;
|
||||
RTIME firing_time, period;
|
||||
void (*handler)(unsigned long);
|
||||
unsigned long data;
|
||||
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
|
||||
rb_root_t rbr;
|
||||
rb_node_t rbn;
|
||||
#endif
|
||||
};
|
||||
|
||||
RTAI_SYSCALL_MODE void rt_timer_remove(struct rtdm_timer_struct *timer);
|
||||
|
||||
RTAI_SYSCALL_MODE int rt_timer_insert(struct rtdm_timer_struct *timer, int priority, RTIME firing_time, RTIME period, void (*handler)(unsigned long), unsigned long data);
|
||||
|
||||
typedef struct rtdm_timer_struct xntimer_t;
|
||||
|
||||
#define XN_INFINITE (0)
|
||||
|
||||
/* Timer modes */
|
||||
typedef enum xntmode {
|
||||
XN_RELATIVE,
|
||||
XN_ABSOLUTE,
|
||||
XN_REALTIME
|
||||
} xntmode_t;
|
||||
|
||||
#define xntbase_ns2ticks(rtdm_tbase, expiry) nano2count(expiry)
|
||||
|
||||
static inline void xntimer_init(xntimer_t *timer, void (*handler)(xntimer_t *))
|
||||
{
|
||||
memset(timer, 0, sizeof(struct rtdm_timer_struct));
|
||||
timer->handler = (void *)handler;
|
||||
timer->data = (unsigned long)timer;
|
||||
timer->next = timer->prev = timer;
|
||||
}
|
||||
|
||||
#define xntimer_set_name(timer, name)
|
||||
|
||||
static inline int xntimer_start(xntimer_t *timer, xnticks_t value, xnticks_t interval, int mode)
|
||||
{
|
||||
return rt_timer_insert(timer, 0, value, interval, timer->handler, (unsigned long)timer);
|
||||
}
|
||||
|
||||
static inline void xntimer_destroy(xntimer_t *timer)
|
||||
{
|
||||
rt_timer_remove(timer);
|
||||
}
|
||||
|
||||
static inline void xntimer_stop(xntimer_t *timer)
|
||||
{
|
||||
rt_timer_remove(timer);
|
||||
}
|
||||
|
||||
// support for use in RTDM usage testing found in RTAI SHOWROOM CVS
|
||||
|
||||
static inline unsigned long long xnarch_ulldiv(unsigned long long ull, unsigned
|
||||
long uld, unsigned long *r)
|
||||
{
|
||||
unsigned long rem = do_div(ull, uld);
|
||||
if (r) {
|
||||
*r = rem;
|
||||
}
|
||||
return ull;
|
||||
}
|
||||
|
||||
// support for RTDM select
|
||||
|
||||
typedef struct xnholder {
|
||||
struct xnholder *next;
|
||||
struct xnholder *prev;
|
||||
} xnholder_t;
|
||||
|
||||
typedef xnholder_t xnqueue_t;
|
||||
|
||||
#define DEFINE_XNQUEUE(q) xnqueue_t q = { { &(q), &(q) } }
|
||||
|
||||
#define inith(holder) \
|
||||
do { *(holder) = (xnholder_t) { holder, holder }; } while (0)
|
||||
|
||||
#define initq(queue) \
|
||||
do { inith(queue); } while (0)
|
||||
|
||||
#define appendq(queue, holder) \
|
||||
do { \
|
||||
(holder)->prev = (queue); \
|
||||
((holder)->next = (queue)->next)->prev = holder; \
|
||||
(queue)->next = holder; \
|
||||
} while (0)
|
||||
|
||||
#define removeq(queue, holder) \
|
||||
do { \
|
||||
(holder)->prev->next = (holder)->next; \
|
||||
(holder)->next->prev = (holder)->prev; \
|
||||
} while (0)
|
||||
|
||||
static inline xnholder_t *getheadq(xnqueue_t *queue)
|
||||
{
|
||||
xnholder_t *holder = queue->next;
|
||||
return holder == queue ? NULL : holder;
|
||||
}
|
||||
|
||||
static inline xnholder_t *getq(xnqueue_t *queue)
|
||||
{
|
||||
xnholder_t *holder;
|
||||
if ((holder = getheadq(queue))) {
|
||||
removeq(queue, holder);
|
||||
}
|
||||
return holder;
|
||||
}
|
||||
|
||||
static inline xnholder_t *nextq(xnqueue_t *queue, xnholder_t *holder)
|
||||
{
|
||||
xnholder_t *nextholder = holder->next;
|
||||
return nextholder == queue ? NULL : nextholder;
|
||||
}
|
||||
|
||||
static inline int emptyq_p(xnqueue_t *queue)
|
||||
{
|
||||
return queue->next == queue;
|
||||
}
|
||||
|
||||
#include "rtai_taskq.h"
|
||||
|
||||
#define xnpod_schedule rt_schedule_readied
|
||||
|
||||
#define xnthread_t RT_TASK
|
||||
#define xnpod_current_thread _rt_whoami
|
||||
#define xnthread_test_info rt_task_test_taskq_retval
|
||||
|
||||
#define xnsynch_t TASKQ
|
||||
#define xnsynch_init(s, f, p) rt_taskq_init(s, f)
|
||||
#define xnsynch_destroy rt_taskq_delete
|
||||
#define xnsynch_wakeup_one_sleeper rt_taskq_ready_one
|
||||
#define xnsynch_flush rt_taskq_ready_all
|
||||
static inline void xnsynch_sleep_on(void *synch, xnticks_t timeout, xntmode_t timeout_mode)
|
||||
{
|
||||
if (timeout == XN_INFINITE) {
|
||||
rt_taskq_wait(synch);
|
||||
} else {
|
||||
rt_taskq_wait_until(synch, timeout_mode == XN_RELATIVE ? rt_get_time() + timeout : timeout);
|
||||
}
|
||||
}
|
||||
|
||||
#define XNSYNCH_NOPIP 0
|
||||
#define XNSYNCH_PRIO TASKQ_PRIO
|
||||
#define XNSYNCH_FIFO TASKQ_FIFO
|
||||
#define XNSYNCH_RESCHED 1
|
||||
|
||||
#define rthal_apc_alloc(name, handler, cookie) \
|
||||
rt_request_srq(nam2num(name), (void *)(handler), NULL);
|
||||
|
||||
#define rthal_apc_free(apc) \
|
||||
rt_free_srq((apc))
|
||||
|
||||
#define __rthal_apc_schedule(apc) \
|
||||
hal_pend_uncond(apc, rtai_cpuid())
|
||||
|
||||
#define rthal_apc_schedule(apc) \
|
||||
rt_pend_linux_srq((apc))
|
||||
|
||||
#ifdef CONFIG_RTAI_RTDM_SELECT
|
||||
|
||||
#define SELECT_SIGNAL(select_block, state) \
|
||||
do { \
|
||||
spl_t flags; \
|
||||
xnlock_get_irqsave(&nklock, flags); \
|
||||
if (xnselect_signal(select_block, state) && state) { \
|
||||
xnpod_schedule(); \
|
||||
} \
|
||||
xnlock_put_irqrestore(&nklock, flags); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define SELECT_SIGNAL(select_block, state) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
|
||||
#define __WORK_INITIALIZER(n,f,d) { \
|
||||
.list = { &(n).list, &(n).list }, \
|
||||
.sync = 0, \
|
||||
.routine = (f), \
|
||||
.data = (d), \
|
||||
}
|
||||
|
||||
#define DECLARE_WORK(n,f,d) struct tq_struct n = __WORK_INITIALIZER(n, f, d)
|
||||
#define DECLARE_WORK_NODATA(n, f) DECLARE_WORK(n, f, NULL)
|
||||
#define DECLARE_WORK_FUNC(f) void f(void *cookie)
|
||||
#define DECLARE_DELAYED_WORK_NODATA(n, f) DECLARE_WORK(n, f, NULL)
|
||||
|
||||
#define schedule_delayed_work(work, delay) do { \
|
||||
if (delay) { \
|
||||
set_current_state(TASK_UNINTERRUPTIBLE); \
|
||||
schedule_timeout(delay); \
|
||||
} \
|
||||
schedule_task(work); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
|
||||
#define DECLARE_WORK_NODATA(f, n) DECLARE_WORK(f, n, NULL)
|
||||
#define DECLARE_WORK_FUNC(f) void f(void *cookie)
|
||||
#define DECLARE_DELAYED_WORK_NODATA(n, f) DECLARE_DELAYED_WORK(n, f, NULL)
|
||||
#else /* >= 2.6.20 */
|
||||
#define DECLARE_WORK_NODATA(f, n) DECLARE_WORK(f, n)
|
||||
#define DECLARE_WORK_FUNC(f) void f(struct work_struct *work)
|
||||
#define DECLARE_DELAYED_WORK_NODATA(n, f) DECLARE_DELAYED_WORK(n, f)
|
||||
#endif /* >= 2.6.20 */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_RTAI_XNSTUFF_H */
|
||||
37
base/GNUmakefile.am
Normal file
37
base/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
OPTDIRS = include
|
||||
|
||||
# `malloc', in $(OPTDIRS), must be after `sched' when compiling
|
||||
# with kernel 2.4 and builtin RTAI malloc support
|
||||
if CONFIG_RTAI_MALLOC
|
||||
OPTDIRS += malloc
|
||||
endif
|
||||
|
||||
OPTDIRS += sched ipc arch posix
|
||||
|
||||
if CONFIG_RTAI_TRACE
|
||||
OPTDIRS += trace
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_MATH
|
||||
OPTDIRS += math
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_TASKLETS
|
||||
OPTDIRS += tasklets
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_USI
|
||||
OPTDIRS += usi
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_WD
|
||||
OPTDIRS += wd
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_LEDS
|
||||
OPTDIRS += leds
|
||||
endif
|
||||
|
||||
SUBDIRS = $(OPTDIRS) scripts
|
||||
|
||||
EXTRA_DIST = config
|
||||
36
base/arch/GNUmakefile.am
Normal file
36
base/arch/GNUmakefile.am
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
if CONFIG_X86
|
||||
ARCHDIR = x86
|
||||
endif
|
||||
|
||||
#if CONFIG_I386
|
||||
#ARCHDIR = i386
|
||||
#endif
|
||||
|
||||
#if CONFIG_X86_64
|
||||
#ARCHDIR = x86_64
|
||||
#endif
|
||||
|
||||
if CONFIG_ARM
|
||||
ARCHDIR = arm
|
||||
endif
|
||||
|
||||
if CONFIG_PPC
|
||||
ARCHDIR = ppc
|
||||
endif
|
||||
|
||||
if CONFIG_M68KNOMMU
|
||||
ARCHDIR = m68k
|
||||
endif
|
||||
|
||||
if CONFIG_M68K
|
||||
ARCHDIR = m68k
|
||||
endif
|
||||
|
||||
SUBDIRS = $(ARCHDIR)
|
||||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
rtai_hal$(modext):
|
||||
@(cd $(ARCHDIR)/hal && make rtai_hal$(modext))
|
||||
|
||||
#EXTRA_DIST = x86/patches
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue